内核移植

最近更新时间:2024-08-26 14:55:51

我的收藏
本文将为您介绍 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\\armccarch\\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 256
void task1(void *pdata);
osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
//task2,定义任务栈大小和优先级参数等
#define TASK2_STK_SIZE 256
void 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 initialize
osThreadCreate(osThread(task1), NULL);// Create task1
osThreadCreate(osThread(task2), NULL);// Create task2
osKernelStart();//Start TOS Tiny
添加代码位置如下图:



步骤5:编译下载测试 TencentOS tiny 移植结果

1. 单击按钮对工程进行编译下载到开发板。
2. 编译后系统显示如下参数则表示编译成功,即可完成 TencentOS tiny 的测试。

如下图所示,可以看到串口交替打印信息,并且板载 LED 闪烁,表示两个任务正在进行调度,切换运行。



步骤6:下一步操作

请前往 移植AT框架、SAL框架、模组驱动 进行框架、模组驱动移植操作。