338 lines
7.3 KiB
Markdown
338 lines
7.3 KiB
Markdown
# 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 <cstdio>
|
|
#include <gyroscope.h>
|
|
|
|
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 <cstdio>
|
|
|
|
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. |