# embedded_system **Repository Path**: xcet/embedded_system ## Basic Information - **Project Name**: embedded_system - **Description**: 嵌入式解耦分层框架,包含CBB模块,DEV模块,BSP模块,APP模块。便于移植,基于C语言的面向对象编程。专注于嵌入式系统开发的开源项目,涵盖硬件驱动、实时操作系统及应用层软件和设备,适用于物联网、工业控制等领域。 - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2025-12-25 - **Last Updated**: 2025-12-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目简介 本项目是一个面向嵌入式系统开发的开源框架,旨在提供一个高效、可移植且易于扩展的开发环境。项目采用分层解耦的设计理念,将系统划分为多个独立的模块,包括CBB(Common Building Blocks)、DEV(Device)、BSP(Board Support Package)和APP(Application)模块。这种架构不仅便于移植到不同的硬件平台,还支持基于C语言的面向对象编程风格,使得代码更加模块化、易于维护和复用。 项目专注于嵌入式系统开发的全生命周期,涵盖了硬件驱动开发、实时操作系统(RTOS)集成、以及应用层软件和设备的实现。通过提供一系列标准化的接口和抽象层,项目降低了开发难度,提高了开发效率,特别适用于物联网(IoT)、工业控制、智能家居等领域的应用开发。 # 项目特点 * **分层解耦架构**:采用分层设计,将系统划分为多个独立模块,便于移植和扩展。 * **面向对象编程**:基于C语言实现面向对象编程风格,代码更加模块化和易于维护。 * **丰富的模块支持**:提供CBB模块(如内存管理、事件处理、软定时器、队列、链表等)、DEV模块(设备抽象层,如LED、按钮等)、BSP模块(板级支持包,如外设初始化、系统时钟配置等)和APP模块(用户应用代码)。 * **集成第三方库**:支持多种第三方库,如FreeRTOS、LwIP、FatFS等,提供强大的中间件支持。 * **易于扩展**:用户可以在MyProject目录下创建自己的项目工程,快速搭建应用。 # 项目文件夹架构 1. **librarise**: 存放嵌入式mcu驱动库等 2. **middleware**: 存放第三方库,如freertos、lwip,fatfs等 3. **tools**: 放下载工具以及链接文件等 4. **MyProject**: 存放用户自己的项目工程 # 项目工程架构 1. **APP**: 存放用户自己的应用代码 2. **CBB**: 存放CBB独立模块代码,如内存管理,事件,软定时,队列,链表等 3. **BSP**: 存放核心板级支持代码,如外设初始化、系统时钟配置、外设驱动等 4. **DEV**: 存放设备抽象层,如LED,BUTTON等 # CBB模块层 ![alt text](IMG/image.png) ## Init自动初始化模块 该模块主要负责自动调用嵌入式的初始化函数,比如bsp初始化,dev初始化等,无需繁琐的手动调用一个一个初始化 ### Init自动初始化模块接口 ```C // 初始化函数定义 typedef void (*init_func_t)(void); // 注册初始化函数 -- 优先级从高到低 #define INIT_PORT_BSP(func) const init_func_t init_##func __attribute__((used, section(".init.1"))) = func #define INIT_PORT_DEVICE(func) const init_func_t init_##func __attribute__((used, section(".init.2"))) = func #define INIT_PORT_TASK(func) const init_func_t init_##func __attribute__((used, section(".init.3"))) = func #define INIT_PORT_OTHERS(func) const init_func_t init_##func __attribute__((used, section(".init.4"))) = func /** * @brief 系统初始化函数 */ void cbb_system_init(void); ``` ### 链接文件修改 若你是gcc交叉编译的ld链接文件,需要在ld文件里加入以下内容段 ``` .init : { KEEP(*(SORT_BY_NAME(.init.*))) } > FLASH ``` ### 自动初始化使用方法 ![alt text](IMG/image2.png) 用宏定义包含初始化函数即可,会自动编译进map文件进行调用 ![alt text](IMG/image3.png) ## MEM 内存管理模块 该内存管理模块仿照rtos的heap4实现,支持静态内存申请以及动态内存申请 ### 内存管理接口 1. 通过以下两个宏配置静态和动态内存的大小,即可初始化内存池,使用内存管理功能 ```C #define STATIC_MEM_SIZE 1 * 1024 // 静态内存大小(4字节对齐) #define DYNAMIC_MEM_SIZE 0 * 1024 // 动态内存大小(4字节对齐) ``` 2. 配置好内存池大小后,即可通过下面两个宏快速进行内存分配和释放 ```C #define S_MALLOC(size) cbb_s_malloc(size) // 静态内存申请 #define A_MALLOC(size) cbb_a_malloc(size) // 动态内存申请 #define A_FREE(size) cbb_a_free(size) // 动态内存释放 ``` ## BIT 位操作模块 该模块提供了一些位操作函数,如设置、清除等 ### BIT 位操作模块接口 ```C /** * @brief 获取指定位的值 * @param pvValue 存放位的变量的指针 @ref uint8_t @ref uint16_t @ref uint32_t * @param u8Type 位类型 @see Bit_Type_t * @param bit 位序号 * @return 位的值 */ uint8_t cbb_get_bit(void* pvValue, uint8_t u8Type, uint8_t bit); /** * @brief 清除指定位的值 * @param pvValue 存放位的变量的指针 @ref uint8_t @ref uint16_t @ref uint32_t * @param u8Type 位类型 @see Bit_Type_t * @param bit 位序号 * @return 1:成功 0:失败 */ uint8_t cbb_clear_bit(void* pvValue, uint8_t u8Type, uint8_t bit); /** * @brief 设置指定位的值 * @param pvValue 存放位的变量的指针 @ref uint8_t @ref uint16_t @ref uint32_t * @param u8Type 位类型 @see Bit_Type_t * @param bit 位序号 * @return 1:成功 0:失败 */ uint8_t cbb_set_bit(void* pvValue, uint8_t u8Type, uint8_t bit); ``` ## EVENT 事件处理模块 该模块提供了事件处理机制,支持用户注册事件,事件回调函数链接,事件发生监控,并通过事件类型触发相应的事件处理函数 ### EVENT 事件处理模块接口 ```C /** * @brief 事件注册函数 * @note 该函数用于注册事件,并返回事件句柄 * @param pu32Event 事件来源 * @param u16BitMap 事件位图 * @param u16Offset 事件偏移 * @return Event_t* 事件句柄 */ Event_t* cbb_event_register(void* pu32Event, Event_Type_t eType, uint32_t u32BitMap); /** * @brief 事件连接函数 * @note 该函数用于连接事件回调函数 * @param pstEvent 事件句柄 * @param pfnCallback 事件回调函数 * @param pvArgs 事件参数 * @return @see EVENT_RET_t * * @note 事件回调函数尽可能简短,避免占用过多资源,避免阻塞事件处理 */ EVENT_RET_t cbb_event_connect(Event_t* pstEvent, Event_CB_t pfnCallback, void* pvArgs); /** * @brief 事件处理函数 * @note 该函数用于处理事件 -- 适合多线程,线程内单独处理事件 * @param pstEvent 事件句柄 * @return void */ void cbb_event_monitor(Event_t* pstEvent); /** * @brief 事件处理函数 * @note 该函数由系统调用,用于处理事件 -- 适合单线程,系统调用处理事件 * @return void */ void cbb_event_run(void); ``` ## Delay模块 提供简单的延时,根据MCU时钟频率,不需要特别精准。主要是用for循环计时来进行阻塞延时。 ### Delay模块接口 ```C // 可替换为自己的延时函数 #define DELAY_US(x) delay_us(x) #define DELAY_MS(x) delay_ms(x) // 时钟频率修正 #define SYS_CLK_FREQ 240000000UL // 240MHz // 延时系数校准(基于CM4指令周期估算) #define DELAY_LOOP_COEFFICIENT 6 // 每个循环约6个时钟周期 /** * @brief 延时us * @param u32US 延时时间(us) */ void delay_us(uint32_t u32US); /** * @brief 延时ms * @param u32MS 延时时间(ms) */ void delay_ms(uint32_t u32MS); ``` ## 软定时器模块 需要有硬件定时器提供时基心跳,从而扩展软定时器,仿照FreeRTOS的软定时器 ### 软定时器模块接口 ```C /** * @brief 注册软定时器 * @param u16Interval 定时器周期 * @return 软定时器结构体指针 */ Soft_Tim_t* cbb_soft_tim_register(uint16_t u16Interval); /** * @brief 监视软定时器 * @param pstTim 软定时器结构体指针 * @return @see SOFT_TIM_RET_t */ SOFT_TIM_RET_t cbb_soft_tim_monitor(Soft_Tim_t* pstTim); /** * @brief 设置软定时器周期 * @param pstTim 软定时器结构体指针 * @param u16Interval 定时器周期 * @return @see SOFT_TIM_RET_t */ SOFT_TIM_RET_t cbb_soft_tim_set_interval(Soft_Tim_t* pstTim, uint16_t u16Interval); /** * @brief 使能软定时器 * @param pstTim 软定时器结构体指针 * @param u8Enable 使能标志,0 -- 禁止定时器,1 -- 使能定时器 * @return @see SOFT_TIM_RET_t */ SOFT_TIM_RET_t cbb_soft_tim_enable(Soft_Tim_t* pstTim, uint8_t u8Enable); /** * @brief 获取软定时器超时标志 * @param pstTim 软定时器结构体指针 * @return 超时标志,0 -- 未超时,1 -- 超时 */ uint8_t cbb_soft_tim_timeout(Soft_Tim_t* pstTim); /** * @brief 清除软定时器超时标志 * @param pstTim 软定时器结构体指针 * @return @see SOFT_TIM_RET_t */ SOFT_TIM_RET_t cbb_soft_tim_clear_timeout(Soft_Tim_t* pstTim); ``` ## Queue模块 提供队列功能,支持FIFO模式,仿照FreeRTOS的队列 ### Queue模块接口 ```C /** * @brief 创建队列 * @param u16ObjSize 队列中元素的大小 * @param u16MaxCnt 队列最大元素个数 * @return 队列对象指针 */ Queue_t* cbb_queue_register(uint16_t u16ObjSize, uint16_t u16MaxCnt); /** * @brief 向队列中添加元素 * @param pObj 待添加的元素指针 * @return @see QUEUE_RET_t */ QUEUE_RET_t cbb_queue_psuh(Queue_t* pstQueue, void* pvObj); /** * @brief 从队列中取出元素 * @param pObj 取出的元素指针 * @return @see QUEUE_RET_t */ QUEUE_RET_t cbb_queue_pull(Queue_t* pstQueue, void* pvObj); ``` ### Queue模块注意点 依赖内存管理来申请内存传递数据,仿照freertos的队列 ## Protocol校验模块 主要用于协议算啊,如modbus主从算法等 ## Verify校验模块 主要用于协议校验算法,如crc16,以及签名算法等 # DEV抽象层 为了统一设备接口,因此简历设备基类来扩展特征设备对象,如led,button等. ## DEV基类 设备基类由设备事件和设备上下文组成,设备上下文用于存储设备的特征信息,如led的亮灭状态等。事件存储设备事件是否发生,如按钮按下事件等。 ```C // 设备结构体 typedef struct Device{ void* pvFeature; // 设备上下文 uint32_t u32Event; // 事件位 }Device_t; ``` ## 设备上下文特征扩展 设备特征主要包含设备的硬件接口(HW)以及软件逻辑(SW) ```C /* 声明一个设备的 Feature 类型 */ #define DEVICE_FEATURE_DECLARE(name, hw_type, sw_type) \ typedef struct name { \ hw_type HW; \ sw_type SW; \ } name##_t // 设备上下文举例 /* DEVICE_FEATURE_DECLARE ( name, struct { // 硬件相关的接口以及变量 }, struct { // 软件相关的接口以及变量 } ) Expaned: typedef struct Device_Context{ struct HW { // 硬件相关的接口以及变量 }; struct SW { // 软件相关的接口以及变量 }; }Device_Context_t; */ ``` ### LED设备 ```C // LED结构体 DEVICE_FEATURE_DECLARE ( Led, struct { /** * @brief LED输出状态 * @param u8State 0/1 */ void (*pfnWrite)(uint8_t u8State); }, struct { uint8_t u8Active; // 有效状态 uint8_t u8State; // 当前状态 uint16_t u16Reserved; // 保留字段 } ); ``` ### 目前支持的设备 * **LED**:led灯,点亮,熄灭 * **BUTTON**:普通按钮,按下,释放 * **MULTI_BUTTON**: 多状态按钮,单机,多击,短按,长按 * **UART**: 串口 * **W25QXX**: W25QXX系列Flash芯片驱动 # OS -- FreeRTOS 使用了裁剪后的最小FreeRTOS,只保留了任务调度,资源占用如下 * **RAM**:720B * **FLASH**:2328B # BSP板级支持包 需要由用户自己按照设备抽象接口实现对应的驱动函数,比如串口,spi,i2c,gpio等 # APP应用层 APP层调用DEV层的设备来实现功能,如下按键按下反转led为例 ```C if(get_device_event(pstBtnMode,BUTTON_CLICKED)){ clear_device_event(pstBtnMode,BUTTON_CLICKED); led_toggle(pstLedBlue); } ``` 由于使用硬件抽象接口来调用底层驱动,因此可以实现移植MCU时只需要修改BSP驱动函数即可。同时面向对象编程使得代码的复用率也极大提升。