sloop 一个嵌入式裸机框架(二次宣发)
嫌 sloop 太繁复, sloopLite 来啦-CSDN博客
sloop开源项目仓库链接:
https://github.com/sloop-open/sloop
开源许可证 MIT
sloop 是一个嵌入式裸机框架,提供一套API,方便管理多种任务,比如超时任务/周期任务/并行任务/互斥任务等。
有 sys_wait 和 sys_wait_bare 这两个非阻塞等待API,支持挂起当前互斥任务,但不阻塞并行任务。
任务采用动态注册机制,有以下优势:
1. 可以在运行时方便地启用和停止任务,停止后没有副作用。
2. 可以替代部分静态调用,简化文件之间的调用耦合。
3. 可以替代部分依赖标志量进行同步的操作,有效降低标志的使用数量,增加代码的可读性。
01
目录结构说明:
/project
├── Bin/ # 可执行文件目录
├── Libraries/ # MCU 库文件
│ ├── CMSIS # CMSIS
│ └── STM32F2xx_StdPeriph_Driver # ST标准外设库
├── MDK-ARM/ # MDK 工程文件
├── user/ # 用户文件
│ ├── app === 应用层文件 ===
│ │ ├── config # 用户配置
│ │ │ ├── bl_config.h # sloop 配置文件
│ │ │ ├── com_config.h # 串口和can 配置文件
│ │ │ ├── gpio_config.c # GPIO 配置文件
│ │ │ ├── gpio_config.h # GPIO 对外API和别名
│ │ │ └── stm32f2xx_conf.h # ST 外设库配置(不要变更)
│ │ ├── module # 整机功能模块,比如伺服电机、编码器
│ │ ├── tasks # 任务存放文件夹
│ │ │ ├── task_baseInit.c # 原始任务
│ │ │ ├── task_demo.c # 演示任务
│ │ │ └── task_idle.c # 空闲任务
│ │ ├── common.h # 应用层公共包含
│ │ ├── main.c # 程序入口 main,在此弱定义任务
│ │ └── main.h # 在此声明任务
│ ├── sloop === sloop 源码(不要变更)===
│ │ ├── kernel # 内核
│ │ │ ├── sloop.c # sloop 内核源代码
│ │ │ ├── behavior_log.h # 行为日志宏
│ │ │ └── console.c # 控制台源代码
│ │ ├── mcu_interface # BL移植时,MCU 接口代码
│ │ │ ├── stm32f2xx_it.c # mcu 中断头文件(不要变更)
│ │ │ └── stm32f2xx_it.h # mcu 中断源文件(不要变更)建议在驱动中实现 RQHandler,不需要汇总到这里
│ │ ├── RTT # 日志支持模块,SEGGER RTT
│ │ ├── sloop.h # sloop 用户 API
│ │ └── bl_common.h # sloop 用户 宏 API,主要是日志
│ ├── service === 为应用层提供服务(不要变更)===
│ │ ├── app_service_pack # 面向应用层的服务包,与 MCU 无关,完全可移植
│ │ ├── mcu_service_pack # 基于MCU的服务包,对其他MCU平台不可移植
│ │ └── service_api.h # 服务包面向应用层,提供给用户的API
└── readme.md # 项目说明文档 和 更新日志
02
系统控制台,可以在RTT终端执行预设命令,比如输入reboot执行重启,输入m、M或menu出菜单。
RTT设置:
input->"end of line"->none
input->"echo input"->all enable
控制台内置命令汇总:
| 功能 | 命令 | 简写 | 数字调用 | 参数 |
| c1: 重启 | reboot | r/R | 0 | 无 |
| c2: 查询版本 | version | v/V | 1 | 无 |
| c3: 查询当前任务数据 | task | t/T | 2 | 命令示例:"task" 打印一次,"task on" 10Hz打印,"task off" 关闭10Hz打印 |
| c4: 查询 cpu 负载 | cpu | c/C | 3 | 命令示例:"cpu" 打印一次,"cpu on" 10Hz打印,"cpu off" 关闭10Hz打印 |
| c5: 串口发送 | uart | 无 | 无 | 命令示例:ASCLL 模式:"uart6 hello",HEX 模式:"uart6 -hex 68 65 6C 6C 6F" |
| c6: CAN发送 | can | 无 | 无 | 命令示例:ASCLL 模式:"can1 -id 1 hello",HEX 模式:"can1 -id 1 -hex 68 65 6C 6C 6F" |
| c7: GPIO输出和 gpio输入回显开关 | gpio | 无 | 无 | 命令示例:命令示例:"gpio pin_beep H", "gpio input on" or "gpio input off" |
命令 -h: 可查看命令使用举例,比如uart -h
03
使用注意:
1. 超时任务和周期任务 以回调函数名称作为ID,故同一时刻,同一个回调函数不支持开启多种超时或者周期任务。
开启多个,最新的会覆盖旧的。同一个回调即开启超时又开启周期,是允许的。
2. 重置超时任务,只需重新调用 sys_timeout_start。超时任务到达后,会自动释放任务,没有副作用。关闭后,可以重新设置超时时间。
3. 所有需要在主线程轮询的任务,必须通过 sys_task_start 注册调用(不允许在 main 函数 while(1) 下添加其他函数),这样才能保证 sys_wait 非阻塞等待功能正常。
4. sys_wait 和 sys_wait_bare 只能在互斥任务中调用,使用次数不限,不允许嵌套调用(嵌套日志会报错)。
不建议在互斥任务的驱动中和互斥任务的子函数中调用,容易出现嵌套。保证不嵌套的情况下可以使用。
5. sys_wait 和 sys_wait_bare 调用会阻塞当前任务,但不影响其他并行任务执行。相当于挂起当前任务。
可以用sys_wait_break中断等待,中断后返回1,建议应用层直接返回,不再执行等待后的业务。
可以用sys_wait_continue忽略等待,返回0,继续执行等待后的业务。
6. sys_wait推荐使用方法
等待前的业务,进入 wait 后开始阻塞
if(sys_wait(10))
return;
等待完成后的业务
7. 建议不要使用 sys_delay,特别是周期调用,会大大降低系统性能。sys_delay_us <100us ,可以安全调用。
8. 在互斥任务顶层,可以使用 sys_wait ,达到 sys_delay 的相同效果。
9. 互斥任务是主要的业务执行场景,并行任务是辅助服务。
10. 在所有任务操作中,调用stop后,任务被释放,没有副作用。
11. NVIC 分组已经配置为 16 级响应,不支持抢占,他处不应再调用 NVIC_PriorityGroupConfig。
12. 配置外设中断时,预优先级恒为0,子优先级默认设为宏 PRIO_DEFAULT,如遇到响应延迟,再调整。
| 中断优先级分配表 | |
| SysTick_IRQn | PRIO_HIGHEST 0 |
| 外设中断 | PRIO_DEFAULT 5 |
| 最低优先级 | PRIO_LOWEST 15 |
| main 主线程 | 16(相当于) |
13. 新增互斥任务需要在 main.h 声明,在 main.c 中弱定义,在用户创建的 task 文件中实现。
14. 在 bl_config.h 中可以开启看门狗,默认不启用。
15. 在 bl_config.h 中开启行为日志功能,默认启用。
开启行为日志后,会对系统 API 进行打印增强。即在调用系统 API 时会有相应日志输出。
这对分析系统工作流程会有帮助。
16. 互斥任务有三个阶段:
a1. 初始化阶段(_INIT 和 _FREE)
a2. 运行阶段 _RUN;之后
a3. 运行终止(_FREE; 和 _RUN;)
17._INIT _FREE和_RUN必须实现,为空没关系。因为任务跳转依赖它。
18. systick和tim7两个外设,内核已占用,应用层不要再使用。
19. sloop不适用运行时间长的任务,比如做连续FFT,时间超过1ms。
如果是这种任务建议用状态机拆分或者直接拆分成更小的任务。拆分后,小任务的执行周期应小于10us。
20. 推荐使用V5版本编译器,速度更快。编译优化等级,推荐使用 -O2。
sloop开源项目仓库链接:
https://github.com/sloop-open/sloop
开源许可证 MIT
更多推荐

所有评论(0)