本文将为您介绍 TencentOS tiny 接入腾讯物联网开发平台内核移植的相关操作。
步骤1:代码目录规划
1. 新建 TencentOS_tiny_Demo 主目录,并在主目录下添加四个子目录:arch、board、kernel、osal,其中 arch、kernel、osal 目录文件可直接从代码仓拷贝。
2. 在 board 目录下放入上个步骤中生成的 裸机工程代码,并将移植的开发板取名为 EVB_MX_Plus_Demo,将裸机代码全部拷贝到该目录下。
3. 进入
TencentOS_tiny_Demo\\board\\EVB_MX_Plus_Demo\\MDK-ARM
目录,打开 Keil 工程,开始进行下一步,添加 TencentOS tiny 内核代码。步骤2:添加 TencentOS tiny 内核代码
TencentOS tiny 的内核代码添加分为添加 arch 平台代码、内核源码、 cmsis os 源码及 tos_config.h 头文件等步骤。
2.1 添加 arch 平台代码
1. 在 Keil 工程中添加 tos/arch 分组目录。
2. 将
arch\\arm\\arm-v7m\\common
目录下 tos_cpu.c 文件添加至 tos/arch 目录下。
tos_cpu.c 是 TencentOS tiny 的 CPU 适配文件,包括堆栈初始化、中断适配等。如果您的芯片是 ARM Cortex M 核,例如:M0、M3 、M4、M7 通用核,则该文件无需改动。
如果您的芯片是其他 IP 核时,则需要重新适配。
3. 将
arch\\arm\\arm-v7m\\cortex-m4\\armcc
或 arch\\arm\\arm-v7m\\cortex-m4\\gcc
目录下的 port_s.S 和 port_c.c 文件添加至 tos/arch 目录下。
port_s.S 文件是 TencentOS tiny 的任务调度汇编代码,主要用于弹栈压栈等处理工作;port_c.c 文件适配 systick 。这两个文件每个 IP 核和编译器都不相同。如果您使用的芯片是 ARM Cortex M 核,则无需再进行配置,例如移植的芯片是 STM32L431RCT6,属于 ARM Cortex M4 核,使用的编译器是 Keil,直接选择
arch\\arm\\arm-v7m\\cortex-m4\\armcc
目录下的适配代码。如果您的开发板是 STM32F429IG M4 核,使用的编译器是 GCC,则选择
arch\\arm\\arm-v7m\\cortex-m4\\gcc
目录下的适配文件。4. 完成以上步骤,arch 代码则添加完成,如下图所示:
2.2 添加内核源码
内核源码 kernel 目录下包含 core 和 pm 两个目录,其中 core 目录下的代码为基础内核,pm 目录下的代码为低功耗组件。进行基础移植时无需添加 pm 目录下的代码,只需添加全部的基本内核源码,操作步骤如下:
1. 在 Keil 工程中添加 tos/kernel 分组。
2. 将
kernel\\core
目录下的内核源码文件添加至 tos/kernel 分组中。
2.3 添加 cmsis os 源码
1. 添加 tos/cmsis_os 分组。
cmsis os 是 TencentOS tiny 为兼容 cmsis 标准而适配的 OS 抽象层,可以简化用户将业务从其他 RTOS 迁移到 TencentOS tiny 的工作量。
2. 将
osal\\cmsis_os
目录下 cmsis_os.c 文件添加至 tos/cmsis_os 分组。
2.4 新建 TencentOS tiny 系统配置文件 tos_config.h
1. 在需要移植的工程目录下新增一个 TOS_CONFIG 目录,在该目录下新建一个
tos_config.h
文件,作为当前项目中 TencentOS tiny 的配置头文件,文件内容如下:#ifndef _TOS_CONFIG_H_#define _TOS_CONFIG_H_#include "stm32l4xx.h" // 目标芯片头文件,用户需要根据情况更改#define TOS_CFG_TASK_PRIO_MAX 10u // 配置TencentOS tiny默认支持的最大优先级数量#define TOS_CFG_ROUND_ROBIN_EN 0u // 配置TencentOS tiny的内核是否开启时间片轮转#define TOS_CFG_OBJECT_VERIFY_EN 1u // 配置TencentOS tiny是否校验指针合法#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 1u // TencentOS tiny 动态任务创建功能宏#define TOS_CFG_EVENT_EN 1u // TencentOS tiny 事件模块功能宏#define TOS_CFG_MMBLK_EN 1u //配置TencentOS tiny是否开启内存块管理模块#define TOS_CFG_MMHEAP_EN 1u //配置TencentOS tiny是否开启动态内存模块#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u // TencentOS tiny 默认动态内存池功能宏#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x100 // 配置TencentOS tiny默认动态内存池大小#define TOS_CFG_MUTEX_EN 1u // 配置TencentOS tiny是否开启互斥锁模块#define TOS_CFG_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否开启消息队列模块#define TOS_CFG_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否开启消息邮箱模块#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否开启优先级消息队列模块#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否开启优先级消息邮箱模块#define TOS_CFG_TIMER_EN 1u // 配置TencentOS tiny是否开启软件定时器模块#define TOS_CFG_PWR_MGR_EN 0u // 配置TencentOS tiny是否开启外设电源管理模块#define TOS_CFG_TICKLESS_EN 0u // 配置Tickless 低功耗模块开关#define TOS_CFG_SEM_EN 1u // 配置TencentOS tiny是否开启信号量模块#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u // 配置TencentOS tiny是否开启任务栈深度检测#define TOS_CFG_FAULT_BACKTRACE_EN 0u // 配置TencentOS tiny是否开启异常栈回溯功能#define TOS_CFG_IDLE_TASK_STK_SIZE 128u // 配置TencentOS tiny空闲任务栈大小#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // 配置TencentOS tiny的tick频率#define TOS_CFG_CPU_CLOCK (SystemCoreClock) // 配置TencentOS tiny CPU频率#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将TIMER配置成函数模式#endif
2. tos_config.h 头文件内容添加完成后,将头文件放入需要移植的 board 工程目录下即可,例如本教程放到
board\\EVB_MX_Plus_Demo\\TOS_CONFIG
目录下。再将 tos_config.h 文件加入到 Keil-MDK 工程中,方便修改。
2.5 添加 TencentOS tiny 头文件目录
TencentOS tiny 需要添加的所有头文件目录如下:
完成以上步骤,TencentOS tiny 的内核代码则全部添加完毕。
步骤3:修改冲突代码
修改 stm32l4xx_it.c 的中断函数,在 stm32l4xx_it.c 文件中添加 tos_k.h 头文件。
由于 PendSV_Handler 函数在 TencentOS tiny 的调度汇编中已经重新实现,所以需要在 stm32l4xx_it.c 文件中的 PendSV_Handler 函数前添加 ___weak
关键字;同时在 SysTick_Handler 函数中添加 TencentOS tiny 的调度处理函数,如下图:
步骤4:编写 TencentOS tiny 测试任务
1. 在 mian.c 中添加 TencentOS tiny 头文件,编写任务函数。
#include "cmsis_os.h" //包含 TencentOS tiny 相关头函数//task1,定义任务栈大小和优先级参数等#define TASK1_STK_SIZE 256void task1(void *pdata);osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);//task2,定义任务栈大小和优先级参数等#define TASK2_STK_SIZE 256void task2(void *pdata);osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);void task1(void *pdata)//任务入口函数,用于测试{int count = 1;while(1){printf("\\r\\nHello world!\\r\\n###This is task1 ,count is %d \\r\\n", count++);HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);osDelay(2000);}}void task2(void *pdata) //任务入口函数,用于测试{int count = 1;while(1){printf("\\r\\nHello TencentOS !\\r\\n***This is task2 ,count is %d \\r\\n", count++);osDelay(1000);}}int fputc(int ch, FILE *f)//将 printf 函数重定向到串口2{if (ch == '\\n'){HAL_UART_Transmit(&huart2, (void *)"\\r", 1,30000);}HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);return ch;}
添加代码位置如下图:
2. 继续在 main.c 的 main 函数中添加硬件外设初始化代码,添加 TencentOS tiny 的初始化代码:
osKernelInitialize(); //TOS Tiny kernel initializeosThreadCreate(osThread(task1), NULL);// Create task1osThreadCreate(osThread(task2), NULL);// Create task2osKernelStart();//Start TOS Tiny
添加代码位置如下图:
步骤5:编译下载测试 TencentOS tiny 移植结果
1. 单击按钮对工程进行编译下载到开发板。
2. 编译后系统显示如下参数则表示编译成功,即可完成 TencentOS tiny 的测试。
如下图所示,可以看到串口交替打印信息,并且板载 LED 闪烁,表示两个任务正在进行调度,切换运行。