TencentOS tiny 移植到STM32F103教程

一、移植前的准备工作

1. STM32的裸机工程模板

这个可以自己创建(创建过程参考之前的STM32裸机工程也有工程网盘在上面)

2.下载TencentOS tiny 源码

TencentOS tiny的源码可从TencentOS tiny GitHub仓库地址https://github.com/Tencent/TencentOS-tiny下载,如果GitHub下载慢,也可以通过腾讯工蜂开源仓下载,地址:https://git.code.tencent.com/Tencent_Open_Source/TencentOS-tiny

3.TencentOS tiny源码核心文件夹分析

打开TencentOS tiny源码文件,可以看见里面有12个文件夹,下面先来了解主要文件夹及其子文件夹的作用,然后将TencentOS tiny源码的核心文件提取出来,添加到工程根目录下的文件夹中,因为工程只需要有用的源码文件,而不是全部的TencentOS tiny源码,所以可以避免工程过于庞大。

一级目录

二 / 三级目录

说明

arch

arm

TencentOS tiny适配的IP核架构(含M核中断、调度、tick相关代码),对我们的移植很重要

arch

risc-v

TencentOS tiny适配的risc-v架构

board

TencentOS_tiny_EVB_MX

TencentOS tiny 定制开发板demo,包含AT适配框架、MQTT协议、安全组件等

component

connectivity / loraWAN

loRaWAN协议栈实现源码及适配层

connectivity / Eclipse-Paho-MQTT

MQTT协议栈实现源码及适配层

connectivity / TencentCloud_SDK

腾讯云C-SDK实现源码及适配层

fs

文件系统实现源码

security

mbedtls 安全协议源码

utils

包含json相关源码

devices

TencentOS tiny适配的一些外设驱动(如串口wifi gprs 驱动等)

doc

TencentOS tiny相关技术文档及开发指南(建议多看这部分)

examples

TencentOS tiny提供的功能示例

kernel

core

TencentOS tiny内核源码(这部分是最重要的)

hal

TencentOS tiny驱动抽象层

pm

TencentOS tiny低功耗模块源码

net

at

TencentOS tiny为串口类通信模组提供的AT框架实现层

lwip

TencentOS tiny为串口类LoraWAN模块提供的移植框架

sal_module_wrapper

Lwip协议实现源码及适配层

tencent_firmware_module_wrapper

TencentOS tiny为串口类网络模块(wifi gprs)提供的socket移植框架

tencent_firmware_module_wrapper

TencentOS tiny提供的腾讯定制模组移植框架

osal

cmsis_os

TencentOS tiny提供的cmsis os 适配

platform

hal

TencentOS tiny适配的部分芯片的驱动实现源码

vendor_bsp

芯片厂家提供的原厂bsp固件库,如STM32的HAL库

test

存放TencentOS tiny提供的一些测试代码,含内核及上层模块示例及测试代码

tools

存放TencentOS tiny提供的工具,小程序,配置工具等

简单提一下我们的重点文件夹:

*arch: TencentOS tiny是软件,单片机是硬件,为了使TencentOS tiny运行在单片机上面,TencentOS tiny和单片机必须关联在一起,那么如何关联呢?还是要通过代码来关联,这部分关联的文件叫接口文件,通常由汇编语言和C语言联合编写。这些接口文件都是跟硬件密切相关的,不同的硬件接口文件是不一样的,但都大同小异。

*TencentOS tiny在arch\arm\arm-v6m目录中存放了cortex m0内核的单片机的接口文件,在arch\arm\arm-v7m目录中存放了cortex m3、m4和m7内核的单片机的接口文件,以及一些通用的接口文件,基于这些内核的mcu都可以使用里面的接口文件。

*kernelkernel是TencentOS tiny内核核心源码,它的重要性我也不用多说,毕竟整个内核就是由这里面的文件组成,而其他文件夹都是基于内核的组件。

*config:board就是TencentOS tiny为一些常用开发板开发的demo文件夹,其内有各个工程的配置文件,选一个与移植芯片最相机的开发板,找到它的配置文件tos_config.h,比如我们可以选择:TencentOS-tiny\board\STM32F103_SIM800A\TOS-CONFIG

这个配置文件很重要,后续在移植工程时,我们需要对这个配置文件进行修改,这样子可以裁剪TencentOS tiny的功能,得到最适合的工程配置。

这个congfig就是FreeRTOS一样,可以根据自己需求配置

所以我们需要以上分析的这三个文件

二、开始移植

第一步:创建文件夹TencentOS-tiny,将所有下载代码都添加进来

第二步:先创建文件夹TOS-CONFIG,用于存放TencentOS tiny的配置头文件,头文件后面在放

第三步:创建文件夹,添加文件
第四步:添加源码

(1)tos/kemel添加,从该路径TencentOS-tiny\kernel\core将源码添加进来

(2)添加arch平台代码

*1)从该路径TencentOS-tiny\arch\arm\arm-v7m\common将tos_cpu.c添加进来

tos_cpu.c是TencentOS tiny 的CPU适配文件,包括堆栈初始化,中断适配等,如果您的芯片是ARM Cortex M核,该文件可以不做改动,M0、M3 、M4、M7是通用的,其他IP核需要重新适配;

*2)从该路径TencentOS-tiny\arch\arm\arm-v7m\cortex-m3\armcc将port_c.c、port_s.S添加进来

port_s.S 文件是TencentOS tiny的任务调度汇编代码,主要做弹栈压栈等处理的,

port_c.c适配systick等

我们这边STM32F103是M3内核所以路径选择的是cortex-m3

这两个文件 每个IP核和编译器都是不一样的,如果您的芯片是ARM Cortex M核,我们都已经适配好

*3)从该路径TencentOS-tiny\board\TencentOS_Tiny_EVB_STM32WL\TOS_CONFIG将tos_config.h复制起来,这里随便选了一个例程的tos_config.h复制,我们把它复制到先前创建的TOS-CONFIG文件夹里面,后面在做修改。

因为这个配置文件很重要,后续在移植工程时,我们需要对这个配置文件进行修改,这样子可以裁剪TencentOS tiny的功能,得到最适合的工程配置

*4)从该路径TencentOS-tiny\osal\cmsis_os将cmsis_os.c添加进来

cmsis os是TencentOS tiny为了兼容cmsis标准而适配的OS抽象层,可以简化大家将业务从其他RTOS迁移到TencentOS tiny的工作量。

第五步:添加TencentOS tiny头文件目录

第六步:修改config.h

修改前:

#ifndef _TOS_CONFIG_H_
#define  _TOS_CONFIG_H_

#include "stm32wlxx.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   0u// 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   0x8000// 配置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

修改后:

#ifndef _TOS_CONFIG_H_
#define  _TOS_CONFIG_H_

#include "stm32f10x.h"

#define TOS_CFG_TASK_PRIO_MAX     10u// 配置TencentOS tiny默认支持的最大优先级数量

#define TOS_CFG_ROUND_ROBIN_EN       1u// 配置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    0x200// 配置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

第七步:编译下

有重复定义的函数,注释PendSV_Handler()函数

鉴于TencentOS tiny已经处理好PendSV与SysTick中断了,就不需要用户自己去处理,所以要在中断相关的源文件(stm32f10x_it.c文件)中注释(或者删除PendSV_Handler()函数。

另外我们也把SysTick_Handler屏蔽掉,因为我们在另外建的BSP_SysTick_放置了SysTick_Handler

添加___weak关键字添加上去,变成弱定义即可

在编译下,编译通过!

第八步:编写SysTick_Handler()函数

SysTick中断服务函数是一个非常重要的函数,TencentOS tiny所有跟时间相关的事情都在里面处理,SysTick就是TencentOS tiny的一个心跳时钟,驱动着TencentOS tiny的运行,就像人的心跳一样,假如没有心跳,我们就相当于“挂掉”,同样的,TencentOS tiny没有了心跳,那么它就会卡死在某个地方,不能进行任务调度,不能运行任何的东西,因此我们需要实现一个TencentOS tiny的心跳时钟。

在SysTick_Handler函数中添加TencentOS tiny的调度处理函数,然后在BSP_Systick.c文件中包含 tos_k.h 头文件

#include "BSP_SysTick.h"
#include "tos_k.h" 

//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void BSP_SysTickInit()
{
    u32 reload;//装载次数
    /*滴答定时频率配置72MHZ,而心跳中断需要1ms中断一次,那么装载计数值->X = 0.0001s/(1/72000000) = 72000次  */
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLK = SystemCoreClock = 72000000HZ
    reload=SystemCoreClock/1000000;                //reload = 72
    reload*=1000000/TOS_CFG_CPU_TICK_PER_SECOND;        //根据configTICK_RATE_HZ设定溢出时间 
                                                                                                    //reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右       
    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;       //开启SYSTICK中断
    SysTick->LOAD=reload;                         //滴答定时频率72MHZ,72000*(1/72000000) = 1ms
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;       //开启SYSTICK 
}

void SysTick_Handler(void)//1ms中断一次
{
     if (tos_knl_is_running())
  {
    tos_knl_irq_enter();
    tos_tick_handler();
    tos_knl_irq_leave();
  }
}

三、创建TencentOS tiny任务,测试移植结果

第一步:在mian.c 中添加TencentOS tiny 头文件,编写任务函数
#include "main.h"
#include "bsp_Stm32fx.h"
/* TencentOS头文件 */
#include "cmsis_os.h"

//task1
#define TASK1_STK_SIZE        256//任务栈大小
void task1(void *pdata);//任务函数
osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);//创建TASK1任务

//task2
#define TASK2_STK_SIZE        256//任务栈大小
void task2(void *pdata);//任务函数
osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);//创建TASK2任务



void BoardInit(void)
{
    //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//裸机工程配置
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//一旦一只哦操作系统需需要设置为中断分组4 
    BSP_SysTickInit();
    BSP_GpioInit();
    BSP_UartInit(115200);
}


int main(void)
{
    BoardInit();     BSP_SetLed0(0);     BSP_SetLed0(0);
    printf("Welcome to TencentOS tiny,CoreClock:%d\r\n",SystemCoreClock);  
    osKernelInitialize(); //TOS Tiny kernel initialize
  osThreadCreate(osThread(task1), NULL);// Create task1
  osThreadCreate(osThread(task2), NULL);// Create task2
  osKernelStart();//Start TOS Tiny
}


   void task1(void *pdata)
   {
       int count = 1;
       while(1)
       {
          printf("\r\nHello world!\r\n###This is task1 ,count is %d \r\n", count++);
               BSP_SetLed0(2);
           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++);
                    BSP_SetLed1(2);
           osDelay(1000);
       }
   }

// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);切记,这个中断分组一定要设置成组4,设置成组4,总共变成了0-15级抢占优先级,就没有响应优先级了。

原来裸机工程默认将STM32的优先级分组配置为2,即4个抢占优先级、4个亚优先级。而freeRTOS的中断配置没有处理亚优先级这种情况,即要求全部为抢占优先级。所以STM32移植freeRTOS时,应将中断优先级配置为4,即16个抢占优先级。

第二步:编译工程

下载进去,查看现象

串口数据正常输出,证明两个任务都有跑,

但是确发现板载的LED灯没有闪烁运行,这个很奇怪

第三步:查找LED驱动问题

经过查找,我发现只有把 USE Micro LIB勾选起来,LED灯才会闪烁,很奇怪。

从理论上分析,USE Micro LIB勾选起来只是牺牲运行速度从而达到减小代码所占的空间跟这个GPIO没关系才对啊,我找不到答案。目前带线就是这个问题

附录:

针对第三步的问题,如果有小伙伴知道请评论区告诉我下,感谢,此次移植到此结束啦!

工程文件:

链接:https://pan.baidu.com/s/1IscZGbKQpbXfAQ3YwfuGdw

提取码:9ohw

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值