1.TobudOS
1.1.简介
TobudOS是开放原子开源基金会孵化的,面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率,助力物联网终端设备及业务快速接入云上服务和应用。
1.2.特点
(1).小体积
最小内核:RAM 0.6KB,ROM 1.8KB 典型 LoraWAN 及传感器应用:RAM 3.3KB,ROM 12KB
(2).低功耗
休眠最低功耗低至 2uA 支持外设功耗管理框架
(3).丰富的 IoT 组件
集成主流 IoT 协议栈 多种通信模组SAL层适配框架; 支持 OTA 升级 提供简单易用端云 API,加速用户业务接入腾讯云
(4).可靠的安全框架
多样化的安全分级方案 均衡安全需求&成本控制
(5).良好的可移植性
内核及IoT组件高度解耦,提供标准适配层 提供自动化移植工具,提升开发效率
(6).便捷的调试手段
提供云化的最后一屏调试功能 故障现场信息自动上传云平台,方便开发人员调试分析
2.准备工作
2.1. 软件准备
STM32CubeMX (代码将使用HAL库) 下载地址:
下载地址: https://www.st.com/zh/development-tools/stm32cubemx.html
KEIL 下载地址:
https://www.keil.com/demo/eval/arm.htm
开发板芯片为STM32H750XBH6,提前安装好安装Keil.STM32H7xx_DFP.3.1.1.pack系列器件支持包
支持包下载地址:
https://www.keil.arm.com/packs/stm32h7xx_dfp-keil/boards/
2.2.硬件准备
EVB_AIoT_STM32开发板,STM32H750XBH6主控芯片。
3.TobudOS移植
3.1.新建裸机工程
3.1.1.新建STM32Cubemx项目
1.新建项目
3.1.2.选择对应芯片型号
1.输入芯片型号搜索。
2.选择芯片。
3.1.3.关闭内存管理
3.1.4.时钟源选择外部晶振
3.1.5.设置串口UART5
开发板与外部连接的串口为UART5,其他开发板根据自己选择。
1.开启UART5
2.通信参数默认
1.搜索PB13引脚
2.将PB13引脚设置为UART5_TX
3.1.6.设置LED引脚
1.将PB1设置成输出
3.1.7.设置按键KEY引脚
设置PJ3引脚为输入,上拉。
3.1.8.设置中断
1.开启UART5中断
1.Hard fault,Pendable request,Time base三个中断不生成中断函数。前两个中断函数tobudOS会在RTOS里面对这三个中断函数进行接管,最后的Time base中断需要我们重写,下面会讲到。
3.1.9.配置时钟
3.1.10.工程和代码生成配置
1.选择工程配置。
2.选择工程。
3.填写工程名称和保存位置。
4.选择IDE为 MDK-ARM
1.选择工程配置。
2.选择代码生成。
3.选择只生成用到的库。
4.生成.C .H代码。
1.生成代码
3.2.KEIL设置
1.开启MicroLIB。到时候print函数需要重构。
1.下载器选择ST-LINK。
1.打开下载自动复位运行选项。
1.编译,下载。
3.3.准备tobudOS源码
atomgit的下载地址:
https://atomgit.com/OpenAtomFoundation/TobudOS
3.4.内核移植
3.4.1.在工程下新建tobudOS文件夹
把需要的内核文件都复制进该文件夹下。
3.4.2.添加内核代码到工程
1.新建三个gruops:tos/arch tos/kernel tos/cmsis
1.
tobudOS\arch\arm\arm-v7m\common\tos_cpu.c
tobudOS\arch\arm\arm-v7m\cortex-m7\armcc\port_c.c
tobudOS\arch\arm\arm-v7m\cortex-m7\armcc\port_s.S
添加进文件。
1.
tobudOS\kernel\core\内所有添加进文件
1.
tobudOS\osal\cmsis_os\cmsis_os.c
添加进文件。
3.4.3.添加tobudOS头文件目录
把需要的头文件目录包含进去。
3.4.4.新建 TobudOS 系统配置文件 tos_config.h
新建一个User文件夹
新建一个User Groups
包含User的头文件
新建一个tos_config.h 头文件
将下面的代码复制进tos_config.h
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stm32h7xx.h" // 目标芯片头文件,用户需要根据情况更改
#define TOS_CFG_OBJ_DYNAMIC_CREATE_EN 1u
#define TOS_CFG_TASK_PRIO_MAX 10u // 配置TobudOS默认支持的最大优先级数量
#define TOS_CFG_ROUND_ROBIN_EN 0u // 配置TobudOS的内核是否开启时间片轮转
#define TOS_CFG_OBJECT_VERIFY_EN 1u // 配置TobudOS是否校验指针合法
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 1u // TobudOS 动态任务创建功能宏
#define TOS_CFG_EVENT_EN 1u // TobudOS 事件模块功能宏
#define TOS_CFG_MMBLK_EN 1u //配置TobudOS是否开启内存块管理模块
#define TOS_CFG_MMHEAP_EN 1u //配置TobudOS是否开启动态内存模块
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u // TobudOS 默认动态内存池功能宏
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x100 // 配置TobudOS默认动态内存池大小
#define TOS_CFG_MUTEX_EN 1u // 配置TobudOS是否开启互斥锁模块
#define TOS_CFG_MESSAGE_QUEUE_EN 1u // 配置TobudOS是否开启消息队列模块
#define TOS_CFG_MAIL_QUEUE_EN 1u // 配置TobudOS是否开启消息邮箱模块
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u // 配置TobudOS是否开启优先级消息队列模块
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u // 配置TobudOS是否开启优先级消息邮箱模块
#define TOS_CFG_TIMER_EN 1u // 配置TobudOS是否开启软件定时器模块
#define TOS_CFG_PWR_MGR_EN 0u // 配置TobudOS是否开启外设电源管理模块
#define TOS_CFG_TICKLESS_EN 0u // 配置Tickless 低功耗模块开关
#define TOS_CFG_SEM_EN 1u // 配置TobudOS是否开启信号量模块
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u // 配置TobudOS是否开启任务栈深度检测
#define TOS_CFG_FAULT_BACKTRACE_EN 0u // 配置TobudOS是否开启异常栈回溯功能
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u // 配置TobudOS空闲任务栈大小
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // 配置TobudOS的tick频率
#define TOS_CFG_CPU_CLOCK (SystemCoreClock) // 配置TobudOS CPU频率
#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将TIMER配置成函数模式
#define TOS_CFG_OBJ_DYNAMIC_CREATE_EN 1u // 配置是否开启任务的动态分配处理和堆栈
#endif
把tos_config.h放入User Groups
4.创建任务,测试移植效果
4.1.包含tos_k.h和stdio.h头文件
4.2.重写SYSTICK中断函数 SysTick_Handler
void SysTick_Handler(void)
{
HAL_IncTick();
if (tos_knl_is_running())
{
tos_knl_irq_enter();
tos_tick_handler();
tos_knl_irq_leave();
}
}
4.3.重构fputc fgetc用于printf
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart5, (uint8_t *)&ch, 1, 0xFFFF);
return (ch);
}
int fgetc(FILE *f)
{
int ch;
while (__HAL_UART_GET_FLAG(&huart5, UART_FLAG_RXNE) == RESET)
;
__HAL_UART_CLEAR_OREFLAG(&huart5);
HAL_UART_Receive(&huart5, (uint8_t *)&ch, 1, 0xFFFF);
return (ch);
}
4.4.创建LED任务
创建一个LED任务,让LED间隔1000ms亮灭,并打印任务信息。
k_task_t led_thread; // LED任务句柄
#define LED_THREAD_STACK_SIZE 512
uint8_t led_thread_stack[LED_THREAD_STACK_SIZE]; //LED任务内存空间
void led_thread_entry(void *arg) // LED任务入口函数
{
while (1) // 任务内死循环
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); // LED开启
printf("led_thread running,LED ON\r\n"); // 打印信息
tos_task_delay(1000); // 阻塞延时
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); // LED关闭
printf("led_thread running,LED OFF\r\n"); // 打印信息
tos_task_delay(1000); // 阻塞延时
}
}
4.5.创建KEY按键任务
创建一个KEY任务,让按键单击时,打印单击信息.
k_task_t key_thread; // KEY任务句柄
#define KEY_THREAD_STACK_SIZE 512
uint8_t key_thread_stack[KEY_THREAD_STACK_SIZE]; //KEY任务内存空间
void key_thread_entry(void *arg) //KEY任务入口函数
{
uint8_t press = 0; // 记录KEY状态
while (1) // 任务内死循环
{
if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET) //KEY按下
{
if (press == 0)
{
press = 1; // 记录KEY状态
printf("key_thread runing,KEY被单击\r\n"); // 打印信息
}
}
else
press = 0;
tos_task_delay(20); //阻塞延时
}
}
4.6.内核初始化,任务创建和运行
在main中,硬件初始化之后,初始化内核,创建任务,运行任务。
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART5_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
//在硬件初始化后,开始初始化tobudOS
printf("Welcome to TobudOS(%s)\r\n", TOS_VERSION); //打印tobudOS版本信息
tos_knl_init(); //内核初始化
//创建LED任务
tos_task_create(&led_thread,
"led_thread",
led_thread_entry,
NULL,
3,
led_thread_stack,
LED_THREAD_STACK_SIZE,
0);
//创建KEY任务
tos_task_create(&key_thread,
"key_thread",
key_thread_entry,
NULL,
3,
key_thread_stack,
KEY_THREAD_STACK_SIZE,
0);
//启动任务
tos_knl_start();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
4.7.编译下载,测试结果
编译下载。串口助手输出信息。
并观察到开发板LED闪烁