目录
3.2 Pinout&Configuration >> 配置GPIO
3.3 Pinout&Configuration >> 配置时钟源
3.4 Pinout&Configuration >> 配置串口
一、移植前的准备工作
1. 硬件(STM32测试板)
MCU:STM32F407VET6(RAM: 196K ,FLASH: 512K,最高168MHz工作频率)
晶振:8MHz
2. 软件
编译器环境:Keil MDK-ARM Version 5.33
STM32cube 初始化代码生成器:STM32CubeMX Version 6.20
3. 裸机工程
使用 STM32cubeMX 生成裸机代码
3.1选择芯片STM32F407VET6
3.2 Pinout&Configuration >> 配置GPIO
板载三个指示灯,原理图如下图所示。
接着配置控制指示灯的引脚,配置为推挽输出,输出电平为高电平,保证初始化后指示灯是灭的。
在user Label(用户标签)中填写内容是用来表示该引脚的,代替实际引脚,提高代码的移植性。STM32cubeMX生成程序时会在 main.h 中添加宏定义,如下所示。
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
......
/* Private defines -----------------------------------------------------------*/
#define BLUETOOTH_EN_Pin GPIO_PIN_2
#define BLUETOOTH_EN_GPIO_Port GPIOE
#define BLUETOOTH_RST_Pin GPIO_PIN_3
#define BLUETOOTH_RST_GPIO_Port GPIOE
#define LED_Run_Pin GPIO_PIN_4
#define LED_Run_GPIO_Port GPIOE
#define LED_Status_Pin GPIO_PIN_5
#define LED_Status_GPIO_Port GPIOE
#define LED_Error_Pin GPIO_PIN_6
#define LED_Error_GPIO_Port GPIOE
3.3 Pinout&Configuration >> 配置时钟源
3.4 Pinout&Configuration >> 配置串口
3.5 时钟配置
芯片的最高时钟频率可达到168MHz
3.6 生成工程配置
3.7 生成代码配置
3.8 生成代码
3.9 裸机代码结构
二、移植TencentOS-tiny
1. TencentOS-tiny 架构
TencentOS tiny 由一个轻量级 RTOS 内核 + 多个物联网组件构成,其主体架构图(引用 腾讯物联网终端操作系统)如下图所示:
2. 获取TencentOS-tiny源码
可直接前往Github:https://github.com/Tencent/TencentOS-tiny 直接进行下载。
3. TencentOS-tiny源码文件
打开 TencentOS-tiny 源文件,如下图所示。其中一共有13个文件夹(以最新源码为主),各个文件夹的具体说明见【doc / 09.Code_Directories.md】。这里较以往的源码增加一个qmk文件,是TencentOS的一个 Makefile 编译框架。
说明文件是使用Markdown语言编写的文件,后缀.md,查看使用 Visual Studio Code 软件。
4.添加TencentOS-tiny源码
新建工程文件夹develop,在其目录下新建如下图所示子目录文件夹。
board:目录下放入我们前面生成的裸机代码,全部复制粘贴即可;在裸机工程中添加 TencentOS-tiny 配置文件,可以直接找源码 board 目录下的 Demo 中找到相近的工程,将其 TOS_CONFIG 文件夹复制带该裸机工程中,这个配置主要用于我们对TencentOS-tiny 的功能进行裁剪,得到我们需要的配置。
Doc: 放入自己的文档。
其他:可以先全部从TencentOS-tiny源码中复制过来,然后按最终需要进行裁剪。
4.1 添加分组目录
在裸机工程中添加分组目录,分别为tos/arch、tos/kernel、tos/cmsis_os、tos/config。
4.2 添加arch源码
根据所使用的芯片选择合适的文件,当前移植的芯片是 STM32F407VET6 ,属于ARM Cortex M4 内核,使用的编译器是Keil MDK-ARM。
tos_cpu.c:在arch\arm\arm-v7m\common目录中;arm-v7m 架构共用的支持,是 TencentOS tiny 的 CPU 适配文件,包括堆栈初始化、中断适配等。
port_c.c:在 arch\arm\arm-v7m\cortex-m4\armcc 目录中;Systick操作接口移植实现。
port_s.S:在 arch\arm\arm-v7m\cortex-m4\armcc 目录中;是Tencent-Tiny 的任务调度汇编代码,主要用于弹栈压栈等处理工作。
注意:如果使用的编译器是 GCC,则选择
arch\arm\arm-v7m\cortex-m4\gcc
目录下的适配文件。
tos_fault.c:是针对TencnetOS-tiny硬件故障追踪功能的支持,此功能可以在 tos_config.h 中配置,如果加入的话,需要将功能中原有的 HardFault_Handler 屏蔽。
4.3 添加内核源码
内核源码 kernel 目录下包含 core 和 pm 两个目录,其中 core 目录下的代码为基础内核,pm 目录下的代码为低功耗组件。进行基础移植时无需添加 pm 目录下的代码,只需添加全部的基本内核源码(kernel/core 目录下),如下图所示:
4.4 添加cmsis_os源码
cmsis_os是TencentOS-tiny为兼容cmsis标准而适配的OS抽象层,可以简化用户将业务从其他RTOS迁移到TencentOS-tiny的工作量。
TencentOS-tiny 提供CMSIS-RTOS 1.0和2.0接口,当前使用的是1.0。
cmsis_os.c:在 osal\cmsis_os 目录中;
4.5 添加tos_config
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stm32f4xx.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 0x4000 // 配置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
4.7 添加头文件
5. 修改stm32f4xx_it.c代码
5.1 添加tos头文件
在 stm32f4xx_it.c 中添加 tos_k.h 头文件,用于调用API函数。
5.2 修改PendSV_Handler 中断函数
TencentOS-tiny内核中已经对pendSV异常进行了处理,在 PendSV_Handler 函数前添加 __weak 关键字(弱定义);
5.3 修改SysTick_handle中断函数
TencentOS-tiny内核需要Systick提供时钟节拍,在 SysTick_Handler 函数中添加 TencentOS tiny 的调度处理函数,如下图:
tos_knl_is_running() 函数判断内核是否正在运行。
os_tick_handler() 函数是系统用于更新时基用的。
6. 修改usart.c代码
6.1 printf函数重定向
在 usart.c 中添加 fputc 函数,用于重定义 putc 函数,可以是 printf 函数从串口1打印输出。
int fputc(int ch, FILE *f)//将 printf 函数重定向到串口1
{
if (ch == '\n')
{
HAL_UART_Transmit(&huart1, (void *)"\r", 1,30000);
}
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
出现错误是因为缺 stdio.h 头文件,只需要在 main.h 文件中添加即可,如下图所示。
7. 修改mian.c代码
7.1 添加cmsis_os.h头文件
cmsis_os.h 头文件中包含TencentOS-tiny 相关头文件。
7.2 添加Task函数
// 定义任务栈大小和优先级参数等
#define TASK_STK_SIZE 1024
extern void OS_TaskEntry(void *arg);
osThreadDef(OS_TaskEntry, osPriorityNormal,1,TASK_STK_SIZE);
__weak void OS_TaskEntry(void *arg) // 任务入口函数
{
while (1)
{
printf("This is a demo task,please use your task enrty!\r\n");
osDelay(1000);
}
}
7.3 内核初始化,创建Task,开启调度
osKernelInitialize();
osThreadCreate(osThread(OS_TaskEntry), NULL);
osKernelStart();
三、验证TencentOS-tiny移植结果
1. 点此按钮对工程进行编译。
2. 编译后,输出此信息表示编译成功。
3. 连接硬件并上电后,点击此按钮即可完成程序下载。