# sweekar-esp32-gyroscope [English](README.md) | [中文](README_CN.md) ## Project Overview `sweekar-esp32-gyroscope` is a modular embedded project based on **ESP-IDF**. This repository is a trimmed-down version of the original `sweekar-esp32` project. It currently keeps only the **gyroscope-related functionality**, and is intended for independent development, feature isolation, verification, and testing. The project still preserves the modular structure of the original codebase, making it easy to continue extending board-level drivers, HAL modules, executor modules, and test code in the future. --- ## Directory Description ### `main/02_physical/boards` Board-level related code. This directory contains content strongly tied to specific hardware boards, such as board definitions, board initialization, IO expansion, and board configuration. ### `main/04_hal` Hardware Abstraction Layer (HAL). This directory contains basic modules related to board drivers, such as: - `audio_codec` - `base_board_hal` - `stepper_driver` ### `main/05_executors` Executor / functional module layer. In this trimmed-down project, the main retained module is: - `gyroscope`: gyroscope driver code ### `main/tests` Test module directory. This directory is used to write test cases to verify whether a module can be correctly included, compiled, linked, and executed. --- ## How to Run Make sure **ESP-IDF** has been installed correctly and the environment has been exported. ### Normal build, flash, and monitor ```bash idf.py build flash monitor ``` ### When you need to auto-generate `module.cmake` If you add a new test directory, or want to re-trigger module scanning and generation, use: ```bash idf.py fullclean build flash monitor ``` Notes: * For normal development: `idf.py build flash monitor` * After adding a new test directory and you want to auto-generate `module.cmake`: `idf.py fullclean build flash monitor` --- ## Example Output If the test code runs correctly, you should see output similar to: ```text I (600) main_task: Calling app_main() load OK 9 I (604) main_task: Returned from app_main() ``` This means: * The `load_gyroscope` test module ran successfully * `Gyroscope` was instantiated successfully * The `add` test module also ran successfully and printed `9` --- ## How to Create a Test Case The workflow for creating a test case is simple: ### 1. Create a new folder under `main/tests/` Each test feature should correspond to one directory. For example: ```text main/tests/add/ ``` or: ```text main/tests/load_gyroscope/ ``` --- ### 2. Write code inside the new folder Usually, you should create at least two files: * `xxx.h` * `xxx.cc` For example, the `add` test module: #### `main/tests/add/add.h` ```cpp int add(int a, int b); ``` #### `main/tests/add/add.cc` ```cpp #include "add.h" int add(int a, int b) { return a + b; } ``` Another example is the `load_gyroscope` test module: #### `main/tests/load_gyroscope/load.h` ```cpp void load(); ``` #### `main/tests/load_gyroscope/load.cc` ```cpp #include "load.h" #include #include void load() { Gyroscope g; printf("load OK\n"); } ``` This example is used to verify: * Whether `gyroscope.h` can be included correctly * Whether the `Gyroscope` class can be instantiated correctly * Whether the test module can participate in linking and execution correctly --- ### 3. Call the test case in `main/main.cc` After writing the test code, include the headers and call the test functions in `main/main.cc`. #### `main/main.cc` ```cpp #include "add.h" #include "load.h" #include extern "C" void app_main() { load(); printf("%d\n", add(5, 4)); } ``` Then build and run: ```bash idf.py build flash monitor ``` If this is the **first time you add a new test directory** and you want the project to auto-generate the corresponding `module.cmake`, use: ```bash idf.py fullclean build flash monitor ``` --- ## Minimal Structure of a Test Module It is recommended that each test module contains at least the following 3 files: ```text xxx/ ├── xxx.cc ├── xxx.h └── module.cmake ``` Meaning: * `xxx.h`: declares the interface * `xxx.cc`: implements the test logic * `module.cmake`: registers this module into the build system --- ## Where `module.cmake` Comes From When you add a new test directory under `main/tests/`, the project can automatically generate a corresponding `module.cmake` for it. For example, if you first create: ```text main/tests/load_gyroscope/ ├── load.cc └── load.h ``` Then run: ```bash idf.py fullclean build flash monitor ``` After that, the directory will become: ```text main/tests/load_gyroscope/ ├── load.cc ├── load.h └── module.cmake ``` So the workflow is: 1. Create a test directory 2. Write the `.h` and `.cc` files 3. Run `idf.py fullclean build flash monitor` 4. `module.cmake` is generated automatically 5. Call the test code in `main/main.cc` --- ## How Automatic CMake Registration Works This project does not manually hardcode every `.cc` file one by one in `main/CMakeLists.txt`. Instead, it automatically collects source files and include directories by scanning each module's `module.cmake`. ### Step 1: Define the directories to scan In `main/CMakeLists.txt`: ```cmake set(SUBSYSTEM_DIRS "04_hal" "05_executors" "05_service" "06_behaviors" "tests" ) ``` --- ### Step 2: Scan `module.cmake` under each subdirectory ```cmake foreach(dir ${SUBSYSTEM_DIRS}) file(GLOB MODULE_FILES "${CMAKE_CURRENT_LIST_DIR}/${dir}/*/module.cmake") foreach(mod_file ${MODULE_FILES}) include(${mod_file}) endforeach() endforeach() ``` That means the main project automatically looks for each module's own `module.cmake`. --- ### Step 3: Each module appends its own information Each module's `module.cmake` appends content to these global variables: * `MODULE_SRCS` * `MODULE_INCLUDE_DIRS` * `MODULE_REQUIRES` * `MODULE_PRIV_REQUIRES` For example, a test module may append: * `tests/add/add.cc` * `tests/add` --- ### Step 4: Everything is registered through `idf_component_register(...)` Finally, everything is registered together: ```cmake idf_component_register( SRCS "main.cc" ${MODULE_SRCS} INCLUDE_DIRS "." ${MODULE_INCLUDE_DIRS} REQUIRES ${MODULE_REQUIRES} PRIV_REQUIRES ${MODULE_PRIV_REQUIRES} ) ``` So in essence: **The main project automatically scans all modules' `module.cmake` files, each module declares the files it wants to participate in compilation, and finally everything is merged into `idf_component_register(...)`.** --- ## Summary The purpose of this repository is very clear: * It is a trimmed-down version of `sweekar-esp32` * It currently keeps mainly the `gyroscope`-related code * It supports quickly adding new test modules under `main/tests/` When adding a new test case, just follow this process: 1. Create a new folder under `main/tests/` 2. Write the `.h` and `.cc` files in that folder 3. When the directory is added for the first time, run `idf.py fullclean build flash monitor` to auto-generate `module.cmake` 4. Call the test code in `main/main.cc` 5. For later normal development, run `idf.py build flash monitor` This allows you to quickly verify whether a module can compile and run correctly.