基于裸机工程移植内核
在TencentOS Tiny官方项目仓下载内核代码,下载地址:
GITHUB:https://github.com/OpenAtomFoundation/TencentOS-tiny
Gitee:https://gitee.com/Tencent/TencentOS-tiny
在这分享一下我的微云链接:https://share.weiyun.com/iNSdPrD4
拷贝如下目录的内核代码到workspace工程目录下的source文件夹下,然后回到IDE按F5刷新即可(请不要拷贝多余的文件,微云链接下载的不需要修改)
其中arch
文件夹主要是储存CPU架构相关汇编程序支持,用于任务调度,kernel
文件夹存放内核源码,TOS_CONFIG
主要存放操作系统抽象层(可选)。
目录 | 文件 | 说明 |
---|---|---|
arch\arm\arm-v7m | common | TencentOS tiny 中断tick相关代码 |
arch\arm\arm-v7m | cortex-m7\gcc | TencentOS Tiny M核调度汇编 GCC |
kernel | core | TencentOS tiny内核源码 |
hal | TencentOS tiny驱动抽象层 | |
pm | TencentOS tiny低功耗源码 | |
TOS_CONFIG | TencentOS tiny配置头文件,用户自定义,从模板修改过来 |
接下来,我们在gpio_led_output.c
添加TencentOS Tiny内核初始化和相关任务代码
1.包含内核头文件 #include “tos_k.h”
2.添加Tick处理函数 SysTick_Handler ,代码如下:
这里是要让内核接管中断,但不是完全接管
void SysTick_Handler(void)
{
if (tos_knl_is_running())//检查当前内核是否在运行
{
tos_knl_irq_enter();//告诉内核要进入中断
tos_tick_handler();//调用系统中断
tos_knl_irq_leave();//告诉内核要退出中断
}
}
3. 新建两个测试任务
文档版
#define TASK1_STK_SIZE 1024
k_task_t task1;
uint8_t task1_stk[TASK1_STK_SIZE];
#define TASK2_STK_SIZE 1024
k_task_t task2;
uint8_t task2_stk[TASK2_STK_SIZE];
void task1_entry(void *arg)//任务入口函数
{
while (1) {
PRINTF("###I am task1\r\n");
tos_task_delay(2000);
}
}
void task2_entry(void *arg)
{
while (1) {
PRINTF("***I am task2\r\n");
tos_task_delay(1000);
}
}
直播版
#define APPLICATION_TASK_STK_SIZE 1024
k_task_t application_task;
uint8_t application_task_stk[APPLICATION_TASK_STK_SIZE];
void __attribute__((weak)) application_entry(void *arg)//任务入口函数
{
while (1) {
PRINTF("###I am task1\r\n");
tos_task_delay(2000);
}
}
4.在main函数后面增加操作系统初始化函数
文档版
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
/* Board pin, clock, debug console init */
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/* Print a note to terminal. */
PRINTF("\r\n GPIO Driver example\r\n");
PRINTF("\r\n Welcome to TencentOS Tiny!\r\n");
/* Init output LED GPIO. */
GPIO_PinInit(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, &led_config);
tos_knl_init(); // TencentOS Tiny kernel initialize
//tos_task_create(任务块指针,任务名,任务入口函数,入口函数的传入参数,任务优先级,任务栈大小,时间片参数)
//时间片参数只有在开启时间片是才有用,默认是关的
tos_task_create(&task1, "task1", task1_entry, NULL, 4, task1_stk, TASK1_STK_SIZE, 0); // Create task1
tos_task_create(&task2, "task2", task2_entry, NULL, 3, task2_stk, TASK2_STK_SIZE, 0);// Create task2
tos_knl_start();//启动调度器,注意:启动后永不返回,所以后面的代码都无效
}
直播版
int main(void)
{
k_err_t err;
tos_knl_init(); // TencentOS Tiny kernel initialize
//tos_task_create(任务块指针,任务名,任务入口函数,入口函数的传入参数,任务优先级,任务栈大小,时间片参数)
//时间片参数只有在开启时间片是才有用,默认是关的
err=tos_task_create(&application_task, "application_task", application_entry, NULL, 2, application_task_stk, APPLICATION_TASK_STK_SIZE,10); // Create task1
if(err!= K_ERR_NONE){
PRINTF("task create fail.\r\n");
}
tos_knl_start();//启动调度器,注意:启动后永不返回,所以后面的代码都无效
}
5. 在工程里面配置TencentOS Tiny 头文件编译目录
6.修改tos_config.h文件
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "board.h" // 目标芯片头文件,用户需要根据情况更改
// 配置TencentOS tiny默认支持的最大优先级数量
#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 0x2000
// 配置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
// 配置Tickless 低功耗模块开关
#define TOS_CFG_TICKLESS_EN 0u
// 配置TencentOS tiny是否开启信号量模块
#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的tick频率
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
// 配置TencentOS tiny CPU频率
#define TOS_CFG_CPU_CLOCK (SystemCoreClock)
// 配置是否将TIMER配置成函数模式
#define TOS_CFG_TIMER_AS_PROC 1u
#endif
7.编译下载测试
编译完成下载到开发板,通过串口助手我们可以看到两个任务交替运行,打印task信息,说明内核移植成功,如下图所示:
引用官方例程
下载源码包后有这样一个文件夹,里面都是官方给的一些例程,无论我们是学习还是开发对我们都会有很大的帮助,下面我举例示范一下如何引用
在这我选择简单的hello_world
例程作为示范。有其他问题大家评论区讨论。
首先把例程拷贝到工程目录下,回到MCUXpresso按F5刷新
打开例程我们看一下代码,例程中有一个函数的总入口,我们只需要在main函数中调用这个任务即可。
第一步:配置任务的参数
#define TASK_STK_SIZE 512//任务栈大小
k_task_t application_task;
uint8_t application_task_stk[TASK_STK_SIZE];
第二步:初始化、创建、启动
tos_knl_init();//系统内核初始化
err=tos_task_create(&application_task, "application_task", application_entry, NULL, 2, application_task_stk, TASK_STK_SIZE, 10); // Create task1
//tos_task_create(任务块指针,任务名,任务入口函数,入口函数的传入参数,任务优先级,任务栈大小,时间片参数)
if(err != K_ERR_NONE){
PRINTF("task create fail.\r\n");
}
// application_entry();
tos_knl_start();//启动内核
好了,下一步我们要开始准备上网了。