diff --git a/README.md b/README.md new file mode 100644 index 0000000..e4d5c9d --- /dev/null +++ b/README.md @@ -0,0 +1,338 @@ +# 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. \ No newline at end of file diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..220ec31 --- /dev/null +++ b/README_CN.md @@ -0,0 +1,340 @@ +# sweekar-esp32-gyroscope +[English](README.md) | [中文](README_CN.md) +## 项目简介 + +`sweekar-esp32-gyroscope` 是一个基于 **ESP-IDF** 的模块化嵌入式工程。 + +这个仓库是从原始 `sweekar-esp32` 工程中精简出来的版本,当前主要保留了 **gyroscope(陀螺仪)相关功能**,用于独立开发、裁剪验证和测试。 + +工程仍然保留了原项目的模块化结构,方便后续继续扩展板级驱动、HAL 模块、执行器模块和测试代码。 + +--- + +## 目录说明 + +### `main/02_physical/boards` +板级相关代码。 +这里放和具体板子强相关的内容,例如板卡定义、板级初始化、IO 扩展、板级配置。 + +### `main/04_hal` +硬件抽象层(HAL)。 +这里放和板子驱动有关的基础模块,例如: + +- `audio_codec` +- `base_board_hal` +- `stepper_driver` + +### `main/05_executors` +执行器 / 功能模块层。 +当前这个精简工程里,主要保留: + +- `gyroscope`:陀螺仪驱动代码 + +### `main/tests` +测试模块目录。 +这里用于编写测试用例,验证某个模块能否正常包含、编译、链接和运行。 + +--- + +## 怎么运行 + +先确保已经正确安装并导出 **ESP-IDF** 环境。 + +### 正常编译、烧录、查看日志 + +```bash +idf.py build flash monitor +``` + +### 当需要自动生成 `module.cmake` 时 + +如果你新增了测试目录,或者希望重新触发模块扫描与生成,使用: + +```bash +idf.py fullclean build flash monitor +``` + +说明: + +* 平时正常开发:`idf.py build flash monitor` +* 新增测试目录后想自动生成 `module.cmake`:`idf.py fullclean build flash monitor` + +--- + +## 运行结果示例 + +如果测试代码运行正常,可以看到类似输出: + +```text +I (600) main_task: Calling app_main() +load OK +9 +I (604) main_task: Returned from app_main() +``` + +这说明: + +* `load_gyroscope` 测试模块运行成功 +* `Gyroscope` 可以正常实例化 +* `add` 测试模块也正常运行,输出结果为 `9` + +--- + +## 怎么创建测试用例 + +创建测试用例的流程很简单: + +### 1. 先在 `main/tests/` 下新建一个文件夹 + +一个测试功能对应一个目录。 + +例如新建: + +```text +main/tests/add/ +``` + +或者: + +```text +main/tests/load_gyroscope/ +``` + +--- + +### 2. 在新建的文件夹里写代码 + +通常至少写两个文件: + +* `xxx.h` +* `xxx.cc` + +例如 `add` 测试模块: + +#### `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; +} +``` + +再例如 `load_gyroscope` 测试模块: + +#### `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"); +} +``` + +这个例子用于验证: + +* `gyroscope.h` 能否正常包含 +* `Gyroscope` 类能否正常实例化 +* 测试模块能否正确参与链接和运行 + +--- + +### 3. 在 `main/main.cc` 里调用测试用例 + +测试代码写好后,在 `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)); +} +``` + +然后编译运行: + +```bash +idf.py build flash monitor +``` + +如果你是**第一次新增测试目录**,想让工程自动生成对应的 `module.cmake`,使用: + +```bash +idf.py fullclean build flash monitor +``` + +--- + +## 测试模块的最小结构 + +推荐每个测试模块至少包含下面 3 个文件: + +```text +xxx/ +├── xxx.cc +├── xxx.h +└── module.cmake +``` + +含义如下: + +* `xxx.h`:声明接口 +* `xxx.cc`:实现测试逻辑 +* `module.cmake`:把这个模块注册进构建系统 + +--- + +## `module.cmake` 怎么来 + +当你在 `main/tests/` 下新增一个测试目录时,工程可以自动为它生成 `module.cmake`。 + +例如你先新建: + +```text +main/tests/load_gyroscope/ +├── load.cc +└── load.h +``` + +执行: + +```bash +idf.py fullclean build flash monitor +``` + +之后目录会变成: + +```text +main/tests/load_gyroscope/ +├── load.cc +├── load.h +└── module.cmake +``` + +所以流程就是: + +1. 先建测试目录 +2. 再写 `.h` 和 `.cc` +3. 执行 `idf.py fullclean build flash monitor` +4. 自动生成 `module.cmake` +5. 在 `main/main.cc` 中调用测试代码 + +--- + +## 自动添加代码文件到 CMake 的原理 + +这个工程不是手工在 `main/CMakeLists.txt` 里一条条写死所有 `.cc` 文件,而是通过扫描各模块目录下的 `module.cmake` 自动收集源码和头文件目录。 + +### 第一步:定义要扫描的目录 + +在 `main/CMakeLists.txt` 中定义: + +```cmake +set(SUBSYSTEM_DIRS + "04_hal" + "05_executors" + "05_service" + "06_behaviors" + "tests" +) +``` + +--- + +### 第二步:扫描每个子目录下的 `module.cmake` + +```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() +``` + +也就是说,主工程会自动去找各个模块自己的 `module.cmake`。 + +--- + +### 第三步:每个模块把自己的信息追加进去 + +每个模块自己的 `module.cmake` 会把内容追加到这些全局变量里: + +* `MODULE_SRCS` +* `MODULE_INCLUDE_DIRS` +* `MODULE_REQUIRES` +* `MODULE_PRIV_REQUIRES` + +例如测试模块会把: + +* `tests/add/add.cc` +* `tests/add` + +加进去。 + +--- + +### 第四步:统一交给 `idf_component_register(...)` + +最后统一注册: + +```cmake +idf_component_register( + SRCS + "main.cc" + ${MODULE_SRCS} + INCLUDE_DIRS + "." + ${MODULE_INCLUDE_DIRS} + REQUIRES + ${MODULE_REQUIRES} + PRIV_REQUIRES + ${MODULE_PRIV_REQUIRES} +) +``` + +所以本质上就是: + +**主工程自动扫描所有模块的 `module.cmake`,每个模块自己声明要参与编译的文件,最后统一汇总到 `idf_component_register(...)`。** + +--- + +## 总结 + +这个仓库的定位是: + +* `sweekar-esp32` 的精简版 +* 当前主要保留 `gyroscope` 相关代码 +* 支持在 `main/tests/` 下快速新增测试模块 + +新增测试用例时,按下面流程做即可: + +1. 在 `main/tests/` 下新建一个文件夹 +2. 在新文件夹里写 `.h` 和 `.cc` +3. 首次新增目录时执行 `idf.py fullclean build flash monitor` 自动生成 `module.cmake` +4. 在 `main/main.cc` 中调用测试代码 +5. 后续正常开发执行 `idf.py build flash monitor` + +这样就可以快速验证模块是否正常编译和运行。