Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/datasheets/STM32-STM32F401-line.jpg.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/datasheets/TC74.pdf
Binary file not shown.
Binary file not shown.
Binary file added docs/datasheets/ads1110_en.pdf
Binary file not shown.
50 changes: 50 additions & 0 deletions rebel/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# AGENTS Guidelines (Rebel)

This document defines high-level context and engineering principles for AI agents working on Rebel.

## Project Context

- `Cheetah` is a smart remotely-controlled car platform.
- `Rebel` is a Cheetah subproject containing car hardware and software.

## Architecture Boundaries

- `cars/`: board-specific BSP-like hardware/software layer.
- `apps/`: hardware-agnostic application logic.
- `lib/`: cross-layer contracts and communication interfaces.

Keep these boundaries strict:
- No board-specific logic in `apps/`.
- No app/business logic in `cars/`.
- Shared contracts must live in `lib/`.

## Habilis Hardware Source Of Truth

- MCU: `STM32F401CE`.
- Shared I2C bus: `I2C1` (`PB6=SCL`, `PB7=SDA`) with `4.7k` pull-ups on both lines.
- I2C1 devices:
- `PCA9685 @ 0x41`
- `ADS1110 @ 0x48`
- `24C04A @ 0x50`
- Proteus I2C debugger
- Virtual terminal: `USART1` (`PA9=TX`, `PA10=RX`).
- `L298` is connected to `LED0` and `LED1` outputs of `PCA9685`.

Treat this hardware profile as authoritative unless explicitly updated by the user.

## Engineering Principles

- Prefer root-cause fixes over symptom suppression.
- Avoid ad-hoc hacks that depend on fragile simulator/toolchain side effects.
- Keep changes minimal, auditable, and reversible.
- Preserve interface compatibility unless a breaking change is explicitly requested.
- Make build and runtime behavior deterministic across environments.
- Keep board-specific simulation details local to board files; keep shared templates generic.
- State assumptions and tradeoffs clearly in task summaries.

## Build And Compatibility Policy

- Favor explicit, stable build contracts over implicit compiler defaults.
- Pin language semantics intentionally (via explicit standard settings), while allowing toolchain upgrades.
- Do not rely on undefined behavior, toolchain quirks, or parser-specific artifacts.
- When simulator behavior diverges from hardware expectations, validate against hardware datasheets and protocol-level evidence first.
62 changes: 39 additions & 23 deletions rebel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@ cmake_minimum_required(VERSION 3.16)
set(APPS_ROOT "${CMAKE_SOURCE_DIR}/apps")
set(CARS_ROOT "${CMAKE_SOURCE_DIR}/cars")

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

# Define the build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
message("Build type: " ${CMAKE_BUILD_TYPE})

# ========== App setup ==========
set(APP starter CACHE STRING "Application logic target")
Expand All @@ -32,10 +40,6 @@ set(CMAKE_TOOLCHAIN_FILE ${CAR_DIR}/toolchain.cmake)
message(STATUS "Building app: ${APP} for car: ${CAR}")
message(STATUS "Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

project(rebel C CXX ASM)

# ========== Directories ==========
Expand All @@ -51,11 +55,23 @@ set(SRC
)

# ========== Compiler and linker flags ==========
# Shared C flags (warnings, optimization)
add_compile_options(-Wall -Wextra -Os)
add_compile_options(-Wall -Wextra)

# Centralized optimization/debug policy.
add_compile_options(
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:Debug>>:-O0>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:-O0>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:Debug>>:-g3>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:-g3>

$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:Release>>:-Os>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Release>>:-Os>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:Release>>:-g0>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Release>>:-g0>
)

# ========== Build main executable ==========
add_executable(firmware.elf ${SRC})
add_executable(firmware ${SRC})

# Libraries
add_subdirectory(lib/toolkit)
Expand All @@ -65,36 +81,36 @@ add_subdirectory(lib/app)
add_subdirectory(${APP_DIR})

# Linker script
set_target_properties(firmware.elf PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
set_target_properties(firmware.elf PROPERTIES ADDITIONAL_CLEAN_FILES ${CMAKE_PROJECT_NAME}.map)
target_link_libraries(firmware.elf PRIVATE car_${CAR} toolkit app_${APP})
target_link_options(firmware.elf PRIVATE "-T${LINKER_SCRIPT}")
set_target_properties(firmware PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
set_target_properties(firmware PROPERTIES ADDITIONAL_CLEAN_FILES ${CMAKE_PROJECT_NAME}.map)
target_link_libraries(firmware PRIVATE car_${CAR} toolkit app_${APP})
target_link_options(firmware PRIVATE "-T${LINKER_SCRIPT}")

# ========== Print size ==========
add_custom_command(TARGET firmware POST_BUILD
COMMAND ${CMAKE_SIZE} firmware.elf
COMMENT "Firmware size"
)

# ========== Generate HEX ==========
add_custom_command(TARGET firmware.elf POST_BUILD
add_custom_command(TARGET firmware POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex firmware.elf firmware.hex
COMMENT "Generating firmware.hex from firmware.elf"
)

# ========== Clean target ==========
# Not needed: use `cmake --build . --target clean`

# ========== Generate emulation.resc ==========
configure_file(
${CARS_ROOT}/emulation.resc.tpl
${CMAKE_BINARY_DIR}/emulation.resc
)

# ========== Clean target ==========
# Not needed: use `cmake --build . --target clean`

# ========== Print size ==========
add_custom_command(TARGET firmware.elf POST_BUILD
COMMAND ${CMAKE_SIZE} firmware.elf
COMMENT "Firmware size"
)

# Add custom target to run Renode test
add_custom_target(run_emulation
COMMAND renode ${CMAKE_BINARY_DIR}/emulation.resc
DEPENDS firmware.elf
COMMAND renode --console ${CMAKE_BINARY_DIR}/emulation.resc
DEPENDS firmware
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running Renode simulation for ${CAR}"
)
53 changes: 3 additions & 50 deletions rebel/cars/habilis/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,52 +1,4 @@
set(STM32CUBE_DIR "${CMAKE_SOURCE_DIR}/vendor/stm32cubef4")
# Only download if directory doesn't exist
if (NOT EXISTS "${STM32CUBE_DIR}")
message(STATUS "Downloading STM32CubeF4...")
execute_process(
COMMAND git clone --depth 1 --branch v1.28.3 --recurse-submodules
https://github.com/STMicroelectronics/STM32CubeF4.git
"${STM32CUBE_DIR}"
RESULT_VARIABLE GIT_RESULT
)
if (NOT GIT_RESULT EQUAL "0")
message(FATAL_ERROR "Failed to clone STM32CubeF4")
endif ()
endif ()

set(STM32_HAL_DIR "${STM32CUBE_DIR}/Drivers/STM32F4xx_HAL_Driver/Src")
file(GLOB STM32_HAL_SOURCES "${STM32_HAL_DIR}/stm32f4xx_hal*.c")
list(FILTER STM32_HAL_SOURCES EXCLUDE REGEX "_template\\.c$")

set(CAR_HAL_DEFINES USE_HAL_DRIVER STM32F401xE)
set(CAR_HAL_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/include
${STM32CUBE_DIR}/Drivers/STM32F4xx_HAL_Driver/Inc
${STM32CUBE_DIR}/Drivers/CMSIS/Include
${STM32CUBE_DIR}/Drivers/CMSIS/Device/ST/STM32F4xx/Include
)
set(CAR_HAL_LOWLEVEL_SOURCES
${STM32CUBE_DIR}/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
src/isr.c
src/hal_msp.c
src/sysmem.c
src/syscalls.c
src/startup.s
)

add_library(car_hal OBJECT)
target_compile_definitions(car_hal PRIVATE ${CAR_HAL_DEFINES})
target_include_directories(car_hal PRIVATE ${CAR_HAL_INCLUDES})
target_sources(car_hal PRIVATE
${STM32_HAL_SOURCES}
${CAR_HAL_LOWLEVEL_SOURCES}
)
target_compile_options(car_hal PRIVATE
-O0
-mno-unaligned-access
# -fno-inline
-fno-tree-sra
-fno-ipa-sra
)
include(src/hal/CMakeLists.txt)

add_library(car_habilis INTERFACE)
target_compile_definitions(car_habilis INTERFACE ${CAR_HAL_DEFINES})
Expand All @@ -55,7 +7,8 @@ target_sources(car_habilis INTERFACE
$<TARGET_OBJECTS:car_hal>
src/car/car_factory.cpp
src/car/habilis.cpp
src/car/i2c.cpp
src/car/i2c_bus.cpp
src/car/i2c_device.cpp
src/toolkit/store.cpp
src/toolkit/usart_logger.cpp
)
Expand Down
2 changes: 1 addition & 1 deletion rebel/cars/habilis/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Rebel - Habilis Car
Board is based on STM32F103C6 (Blue Pill)
Board is based on STM32F401CE (Black Pill)
10 changes: 8 additions & 2 deletions rebel/cars/habilis/board.resc
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
machine LoadPlatformDescription @platforms/cpus/stm32f4.repl

machine LoadPlatformDescriptionFromString "motors: Mocks.DummyI2CSlave @ i2c1 0x40"
machine LoadPlatformDescriptionFromString "pca9685: Mocks.DummyI2CSlave @ i2c1 0x41"
machine LoadPlatformDescriptionFromString "ads1110: Mocks.DummyI2CSlave @ i2c1 0x48"
machine LoadPlatformDescriptionFromString "eeprom24c04a: Mocks.DummyI2CSlave @ i2c1 0x50"

include @cars/habilis/renode/peripherals.py

mach set "habilis"
sysbus LoadELF @build/habilis-starter/firmware.elf
python "setup_peripherals(monitor, 'pca9685', 'ads1110', 'eeprom24c04a')"

showAnalyzer usart1
showAnalyzer usart1
10 changes: 7 additions & 3 deletions rebel/cars/habilis/include/rebel/habilis/car/habilis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
#include <rebel/car/car.hpp>
#include <rebel/toolkit/store.hpp>

#include <rebel/habilis/car/i2c.hpp>
#include <rebel/habilis/car/i2c_device.hpp>
#include <rebel/habilis/toolkit/store.hpp>

namespace Rebel::Habilis::Car
{
class Habilis : public Rebel::Car::Car
{
public:
Habilis(Rebel::Habilis::Toolkit::Store& store, I2CBus& engine);
Habilis(Rebel::Habilis::Toolkit::Store& store, I2CBus& i2c);

void Run() override;

Expand All @@ -40,6 +40,10 @@ namespace Rebel::Habilis::Car

private:
Rebel::Habilis::Toolkit::Store& store;
I2CBus& engine;
I2CBus& i2c;

protected:
void boot() const;
void scanDevices() const;
};
}
32 changes: 0 additions & 32 deletions rebel/cars/habilis/include/rebel/habilis/car/i2c.hpp

This file was deleted.

43 changes: 43 additions & 0 deletions rebel/cars/habilis/include/rebel/habilis/car/i2c_bus.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Created by pouyan on 7/13/25.
//

#pragma once

#include <rebel/habilis/hal.h>
#include <rebel/habilis/car/i2c_device.hpp>

namespace Rebel::Habilis::Car
{
class I2CDevice;

class I2CBus
{
friend class I2CDevice;

public:
explicit I2CBus(I2C_TypeDef* instance);

I2CBus(const I2CBus&) = delete;
I2CBus& operator=(const I2CBus&) = delete;
I2CBus(I2CBus&&) = delete;
I2CBus& operator=(I2CBus&&) = delete;

I2CDevice device(uint16_t address);
uint32_t error();

private:
I2C_HandleTypeDef hi2c;

HAL_StatusTypeDef isDeviceReady(uint16_t address);
HAL_StatusTypeDef write(uint16_t address, const uint8_t* data, size_t length);
HAL_StatusTypeDef read(uint16_t address, uint8_t* data, size_t length);

protected:
void configure(I2C_TypeDef *instance);

void waitForReadiness();
void recover();
static uint16_t addressOnWire(uint16_t address);
};
};
26 changes: 26 additions & 0 deletions rebel/cars/habilis/include/rebel/habilis/car/i2c_device.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Created by pouyan on 3/6/26.
//

#pragma once

#include <rebel/habilis/car/i2c_bus.hpp>

namespace Rebel::Habilis::Car
{
class I2CBus;

class I2CDevice
{
public:
explicit I2CDevice(I2CBus* bus, uint16_t address);

[[nodiscard]] HAL_StatusTypeDef isReady() const;
HAL_StatusTypeDef send(const uint8_t* data, size_t length) const;
HAL_StatusTypeDef receive(uint8_t* data, size_t length) const;

private:
I2CBus* bus;
uint16_t address;
};
};
5 changes: 1 addition & 4 deletions rebel/cars/habilis/include/rebel/habilis/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// Created by pouyan on 10/11/25.
//

#ifndef HAL_H
#define HAL_H
#pragma once

#include <stm32f4xx_hal.h>

Expand All @@ -23,5 +22,3 @@ Peripherals* GetPeripherals();
#ifdef __cplusplus
}
#endif

#endif //HAL_H
Loading