
开放原子训练营(第四季)TobudOS(1)—— TobudOS移植
使用一款STM32开发板演示TobudOS移植。
一、移植前准备
1、目标硬件
手上没有活动STM32H750XBH6这个型号的开发板,移植目标板主控为STM32F407VET6,Cortex-M4内核。
2、编译环境
使用Keil MDK编译器,需要有芯片器件支持包,例如我用到的芯片需要安装的支持包为Keil.STM32F4xx_DFP.2.17.1.pack官方下载地址为:Arm Keil | Keil STM32F4xx_DFP;下载后双击解压安装即可。
3、准备芯片对应的裸机工程
3.1 查看原理图
要使用一路串口输出调试LOG信息:PA9/PA10 - USART1
使用2个LED作为试验测试内容
3.2 使用STM32CubeMX新建工程
3.3 芯片型号选择
3.4 时钟配置
3.5 引脚配置
3.5.1 串口引脚
3.5.2 使能串口中断
3.5.3 LED引脚配置
3.6 时钟总线配置
3.7 工程配置
点击GENERATE CODE生成工程代码。
3.8 串口重定义
为了使用printf标准函数来进行调试信息输出,在uart.c中添加代码,添加stdio.h头文件。
#include "stdio.h"
#if 1
#pragma import(__use_no_semihosting)
//解决HAL库使用时,某些情况可能报错的bug
//因为禁止了半主机模式,需要重写一个半主机模式下的接口,如下
int _ttywrch(int ch)
{
ch=ch;
return ch;
}
//标准库需要的支持函数
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (unsigned) ch;
return (ch);
}
#endif
3.9 测试工程
main.c中添加调试测试信息
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
printf("system run\n");
编译工程,下载测试。
到此,裸机工程准备完毕。
二、内核移植
1、准备TobudOS源码
TobudOS源码现在由开放原子基金会托管,需要下载源码,下载地址为:TobudOS · AtomGit_开放原子开源基金会代码托管平台
2、工程文件目录
新建TobudOS_STM32F407文件夹,arch、kernel、osal文件夹直接从TobudOS源码中复制,新建board文件夹,将上面的裸机工程复制到目录下,在MDK-ARM目录下新建TOS_CONFIG文件夹,新建tos_config.h文件。
3、工程中添加arch源码
这一步要根据芯片的内核架构选择内核支持文件,例如STM32F407VET6内核为cortex-m4,架构为arm-v7m,则添加代码时添加对应arch/arm/arm-v7m文件夹下的芯片文件。
4、工程添加kernel源码
5、添加cmsis_os源码
6、工程添加路径
7、修改tos_config.h
注意这里包含的芯片头文件一定要根据芯片型号修改。
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stm32f4xx.h" // 目标芯片头文件,用户需要根据情况更改
#include <stdio.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配置成函数模式
#define TOS_CFG_OBJ_DYNAMIC_CREATE_EN 1u // 配置是否开启任务的动态分配处理和堆栈
#endif
至此,TobudOS源码添加完毕。
三、创建TobudOS任务,测试移植结果
1、修改stm32f4xx_it.c部分代码
添加tos_k.h头文件
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
#include "tos_k.h"
PendSV_Handler 函数前添加___weak 关键字
__weak void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
修改中断服务
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
if(tos_knl_is_running())
{
tos_knl_irq_enter();
tos_tick_handler();
tos_knl_irq_leave();
}
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
2、main.c中添加测试任务
添加tos_k.h头文件
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "tos_k.h"
添加任务
/* 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);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin|LED2_Pin, GPIO_PIN_SET);
}
}
void task2_entry(void *arg)
{
while (1) {
printf("***I am task2\r\n");
tos_task_delay(1000);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin|LED2_Pin, GPIO_PIN_RESET);
}
}
int fgetc(FILE *f)
{
int ch;
while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == RESET);
__HAL_UART_CLEAR_OREFLAG(&huart1);
HAL_UART_Receive(&huart5, (uint8_t *)&ch, 1, 0xFFFF);
return (ch);
}
任务初始化
MX_USART1_UART_Init();
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();
3、编译测试
编译工程,下载到开发板,串口输出log信息如下,移植成功。

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)