TobudOS ⽬前主要⽀持 ARM Cortex M 核芯⽚的移植,⽐如 STM32 基于 Cortex M 核全系列。本教程将使⽤基于STM32H750XBH6主控芯⽚定制的EVB_AIoT_STM32开发套件,该套件是由TobudOS开源社区联合意法半导体、南京厚德物联⽹设计的⼀款⾼性能IoT开发平台,开发套件如下图所⽰:
在这里插入图片描述

一 移植前的准备

1.硬件

基于STM32H750XBH6主控芯⽚定制的EVB_AIoT_STM32开发套件

2.编译环境

使用keil5.28编译工程
使用stm32 cubemx搭建工程

3 搭建工程

3.1启动stm32CubeMX

在这里插入图片描述

3.2 选择mcu型号

在这里插入图片描述
双击弹出配置工程界面,如下图
在这里插入图片描述
选择不开启mpu,进入工程配置界面
在这里插入图片描述

3.3 pin界面配置时钟源

在这里插入图片描述

3.4 pin界面配置串口

有4个串口,一并全部配置

3.4.1 配置USART4

引脚修改映射
在这里插入图片描述
修改波特率
在这里插入图片描述
3.4.2 配置USART5
引脚映射修改
在这里插入图片描述
修改波特率
在这里插入图片描述

3.4.3 配置USART2

引脚映射修改
在这里插入图片描述
修改波特率
在这里插入图片描述
3.4.4 配置USART6
引脚映射修改
在这里插入图片描述
修改波特率
在这里插入图片描述

3.4.5 打开所以串口的中断服务

在这里插入图片描述

3.5 pin设置界面配置GPIO

在这里插入图片描述

3.6 配置时钟总线

总线时钟源选择HSE,具体的配置参数请参考下图。如配置错误可能导致程序不⼯作:
在这里插入图片描述

3.7 工程生成参数配置

在这里插入图片描述
3.8 代码生成方式配置
在这里插入图片描述

3.9 生成工程

在这里插入图片描述
做完上述事情,即可生成keil 工程,可使用keil编译。

4.准备TobudOS源码

TobudOS 的源码已经开源在开放原⼦开源基⾦会的代码托管平台。
由于本教程只介绍 TobudOS 的内核移植,所以这⾥只需要⽤到 arch、board、kernel、osal 四个⽬录下的源码。
在这里插入图片描述

二 内核移植

如图所⽰,新建 TobudOS 主⽬录,并在主⽬录下添加四个⼦⽬录,其中 arch、kernel、osal 从代码仓直接拷贝过
在这里插入图片描述

来即可,⽽ board ⽬录下则放⼊我们前⾯⽣成的裸机⼯程代码,我的工程取名叫TAioT_stm32,裸机代码全部拷贝到下⾯即可,如下图所⽰:
在这里插入图片描述
接下来进⼊ TobudOS\board\MDK-ARM ⽬录,打开 keil ⼯程,我们开始添加TobudOS 的内核代码。
添加arch平台代码
在这里插入图片描述tos_cpu.c 是 TobudOS 的 CPU 适配⽂件,包括堆栈初始化,中断适配等,如果您的芯⽚是 ARM Cortex M 核,该
⽂件可以不做改动,M0、M3、M4、M7 是通⽤的,其他 IP 核需要重新适配;
port_s.S ⽂件是 TobudOS 的任务调度汇编代码,主要做弹栈压栈等处理的,port_c.c 适配 systick 等,这两个⽂件
每个 IP 核和编译器都是不⼀样的,如果您的芯⽚是 ARM Cortex M 核,我们都已经适配好,⽐如现在我们移植的
芯⽚是 STM32H750,是 ARM Cortex M7核,使⽤的编译器是 KEIL,所以我们选择 arch\arm\arm-v7m\cortexm7\armcc 下的适配代码,如果你的开发板是 STM32F429IG,M4 核,编译器是 GCC,则可以选择arch\arm\arm-v7m\cortex-m4\gcc ⽬录下的适配⽂件。
添加内核源码
内核源码 kerne ⽬录下包含 core 和 pm 两个⽬录,其中 core 下为基础内核,pm 是内核中的低功耗组件;基础移植
的时候可以不添加 pm ⽬录下的代码,如下图所⽰,添加全部基本内核源码:
在这里插入图片描述
添加cmsis os源码
在这里插入图片描述
添加 TobudOS 头⽂件⽬录

添加头⽂件⽬录前,我们在要移植的⼯程⽬录下新增⼀个 TOS_CONFIG ⽂件夹,⽤于存放 TobudOS 的配置头⽂
件,也就是接下来要新建的 tos_config.h ⽂件;
TobudOS 所有要添加的头⽂件⽬录如下:

在这里插入图片描述
新建 TobudOS 系统配置⽂件 tos_config.h
将下列代码复制到tos_config.h中

#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stm32h7xx.h" // ⽬标芯⽚头⽂件,⽤户需要根据情况更改
#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配置成函数模式

#endif

按照上⾯的模板配置好 TobudOS 的各项功能后,将 tos_config.h ⽂件放⼊要移植的 board ⼯程⽬录下即可.。
在这里插入图片描述
这样,TobudOS 的源码就全部添加完毕了。

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

修改 stm32h7xx_it.c 的中断函数,在 stm32h7xx_it.c ⽂件中包含 tos_k.h 头⽂件
在这里插入图片描述
在 stm32h7xx_it.c ⽂件中的 PendSV_Handler 函数前添加___weak 关键字,因为该函数在 TobudOS 的调度汇编中
已经重新实现;同时在 SysTick_Handler 函数中添加 TobudOS 的调度处理函数,如下图所⽰
在这里插入图片描述
编写TobudOS测试任务

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "tos_k.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "tos_k.h"

void SystemClock_Config(void);

/* USER CODE BEGIN 0 */
#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);
    }
}

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);
}

这段代码需要添加"stdio.h"和"tos_k.h"内核头文件、设置任务栈大小
void task1_entry(void *arg);为任务1的测试函数
void task2_entry(void *arg);为任务2的测试函数
分别打印task1和task2
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
用来重映射USART5到printf函数
继续在 main.c 的 main 函数中硬件外设初始化代码后添加 TobudOS 的初始化代码:

    printf("Welcome to TobudOS(%s)\r\n", TOS_VERSION);
	tos_knl_init(); // TobudOS kernel initialize
  tos_task_create(&task1, "task1", task1_entry, NULL, 3, 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();

在这里插入图片描述
编译下载,测试结果
通过keil下载程序,看见有task1和task2的打印,说明内核移植成功!
在这里插入图片描述
另:
我在移植过程中遇到几个问题:
1.板子上有一个拨码开关,选择PC或者MCU,当我们仅使用stlink进行下载调试,使用打印时,需要把拨码开关拨到mcu端,PC端可能是需要接CH340等usb转串口模块的时候使用的。
在这里插入图片描述

2.如果使用的是win11系统,stlink可能会识别不到驱动,需要去st官方去下载驱动。

四 总结

开放原子是一个发展非常快,非常大的平台,这次训练营也学到不少东西,希望开放原子多组织类似的训练营,希望开放原子越来越好。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐