# 项目说明

## 项目结构

```bash
.
├── app                 # 应用层代码。仅有一个入口 app_main.c/void work_app_main(void *arg)
│   ├── button          # 完整独立的按键检测模块代码（少量依赖底层抽象），上层使用接口文件： button.h
│   ├── config          # 配置文件
│   │   ├── app_config      # 应用层的配置，与具体硬件无关，只存放头文件，用以定义出厂默认配置，被上层 app_config.c 所包含，通过 idf.py menuconfig 配置
│   │   └── board_config    # 板载硬件的配置，仅与具体硬件相关，只存放头文件，用以适应不同的 PCB 布局，被上层 board_config.c 所包含，通过 idf.py menuconfig 配置
│   ├── drivers         # 拥有具体硬件的驱动代码，包括 MCU 外设
│   │   ├── data_port       # 数据端口，用于连接上层应用。由 sb_data_port.h 统一应用层的通讯接口，接口对象由具体硬件的驱动获得
│   │   └── ws2812_spi      # 使用 SPI 接口驱动 WS2812 灯珠的代码
│   ├── led_strip       # 灯带驱动，这里只提供一个 Kconfig 的示例
│   └── utils           # 工具函数，纯软件，与具体硬件无关
├── components          # 自定义组件。重点关注 system/include 目录，统一抽象实时内核和驱动接口
├── main                # 主函数。执行仅与具体平台相关的初始化，并调用 app_main.c/void work_app_main(void *arg) 开始运行应用
├── partitions.csv      # ESP32 的分区表。如无特殊需求不必修改
├── README.md           # 项目说明
├── release             # 发布文件。使用顶层目录的脚本自动生成，如 ./.release-sbdemo_s3.sh
├── sal                 # components 目录下抽象层的实现代码，实现实时内核和驱动接口的抽象
└── sdkconfig_defaults  # 默认配置文件，通过 idf.py menuconfig 配置
```

## 编译命令

```bash
$ get_idf  # 设置当前终端的编译环境变量，当打开一个新的终端时需要重新执行
$ ./.release-sbdemo_s3.sh # 仅需要切换项目时执行一次，需要新增项目时参考此文件添加一个配置
$ idf.py build size flash monitor # 编译、查看大小、烧录、打开串口
```

## 新增一个默认的配置
- 当新增一个项目时，为方便设置不同项目间的配置差异，可以参考 sdkconfig_defaults 目录下的文件，生成一个默认的配置文件。具体操作方法：
1. 使用 idf.py menuconfig 配置好一个项目。
2. 使用 idf.py save-defconfig 保存配置。这将输出一个 sdkconfig.defaults 文件。
3. 在 sdkconfig_defaults 目录下新增一个文件，文件名格式为： "sdkconfig.release_${FW_NAME}_${CHIP_NAME}${ADDITIONAL}.defaults" 。注意：文件名中的变量在第 6 步中定义。
4. 把 sdkconfig.defaults 文件的内容复制到 "sdkconfig.release_${FW_NAME}_${CHIP_NAME}${ADDITIONAL}.defaults" 文件中。
5. 以 .release-sbdemo_s3.sh 为例，复制一个新文件，命名规范为 .release-PRODUCT_ID_name.sh 。其中 PRODUCT_ID 在 app/config/version.h 中应与宏 PRODUCT_ID 所定义的值一致。注意 PRODUCT_ID 必须是6个字符。
6. 根据实际项目修改 .release-PRODUCT_ID_name.sh 文件中变量的值。
7. 使用 .release-PRODUCT_ID_name.sh 脚本生成固件。

## 其他功能概要

### 对设备调用的设计建议：
```text
应用 <---> 设备抽象接口 <---> 设备驱动 <---> 硬件抽象接口 <---> 硬件驱动
```

### 实时内核： #include "os/os.h"
- 请把所有与实时内核相关的代码通过此文件的接口调用。

### 命令行工具： #include "shell/sh.h"
- 请参考 app/drivers/ws2812_spi/ws2812_spi_shell.c

### 调试日志： #include "sys_log.h"
- 使用范例：
```C
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_DBG
#define SYS_LOG_DOMAIN "MAIN"
#include "sys_log.h"

int main(void)
{
    SYS_LOG_INF("Hello, World!");
    return 0;
}
```

### 内建隐藏的命令
- 如果烧录是一个空片，终嵯不会出现程序运行日志，要打印日志，使内置的隐藏命令 'syslogON' 可打开日志。
- 其他隐藏命令： 使用 which info 可打印隐藏命令的定义位置。
