使用STM32CubeIDE移植腾讯物联网OS TencentOS tinyd到STM32
TencentTiny-OS、STM32F103C8和STM32CubeIDE
前言概要
腾讯最近发布了自己的IoT操作系统TencentOS tiny,具备小体积、低功耗、集成主流IoT协议栈、和自家IoT Hub无缝结合、安全、移植性等等优势。可以移植到多种主流MCU上,并且提供了详尽的移植说明和使用文档。
对个人而言,还是能兼容多种MCU平台以及和自家IoT Hub的无缝整合最具吸引力。
如果是用腾讯IoT的话,确实可以减少开发测试人力成本,实现多硬件平台的兼容,让产品快速测试、开发和上线交付。
STM32F103X系列是使用非常广泛的中档MCU,属于arm-v7m系列cortex-m3核,因为便宜好用厂商支持多,大量廉价开发板也都用它。因此,TencentOS tiny对其有完备的移植支持,提供了全套移植代码。
STM32CubeIDE则是ST收购了Atollic之后,基于原来的TrueStudio(已停止更新)推出的全功能开发IDE,
自带gcc工具链,CubeMX无缝整合,功能强大,非常好用,推荐使用(其实基本就是原来的TrueStudio,基于Eclipse CDT)。
因为TencentOS tiny官网的移植说明是基于Makefile的,配置繁琐易出错,不方便。
所以本文使用ST官方推荐的All in one式的STM32CubeIDE,把移植过程做一个简单步骤的说明。
(TencentOS tiny已经把所有大多数STM系列的移植代码都完成,因此本文实际只是个编译流程)
需要用的软件:
- STM32CubeMX
- STM32CubeIDE
- TencentOS tiny
需要用的硬件:
- STM32F103FC8开发板
- STLink V2调试器
链接
TencentOS tiny
- TencentOS tiny Github:https://github.com/Tencent/TencentOS-tiny
- TencentOS tiny 官网地址:https://cloud.tencent.com/product/tos-tiny
STM32CubeIDE
- TSTM32CubeIDE 官网地址
一、STM32CubeMX生成工程
这一步基本可以参照TencentOS tiny 官网的说明
https://github.com/Tencent/TencentOS-tiny/blob/master/doc/TencentOS-tiny-porting-gcc.md,
只是中间需要注意打开SWD调试选项和最终生成工程的类型。
- 创建工程,选择MCU为STM32F103C8
- 设定SYS,打开SWD调试选项
CubeMX默认不打开SWD调试,感觉是个坑,不注意这一点,第一次下载之后,STLink就再也连不少设备了。只能用:开发板的RST接地->再次连接->RST悬空的方式重新下载, 非常麻烦。
详细请参照该篇文章 - 使用内部LSE,如需使用外部晶振,在RCC中打开
5. 配置串口1,串口2,串口1用于日志,串口2保留用于以后和ESP8266通信接入腾讯IoT-Hub
6. 设置工程名、工程属性
7. 设置代码生成规则
9. 选择使用HAL(默认选项)
10. 生成工程
二、STM32CubeIDE工程设置和移植代码修改
- 复制以下TencentOS-tiny的代码到工程下的src目录
- arch
- board
- kernel
- osal
复制完成后,因为F103是armv7m m3核,STM32CubeIDE的内置工具链是gcc系列,所以
- 在arm目录下,除下面之外的目录和文件全部删除(否则会参与编译出现重复定义等错误)
- arm\arm-v7m\common
- arm\arm-v7m\cortex-m3\gcc - 在board目录下,只保留
- board\NUCLEO_STM32F103RB\TOS_CONFIG 目录
初次之外的所有目录和文件也都删除,并将目录名改为STM32F103C8
(借用STM32F103RB的配置头文件)
打开生成的TencentOS-tiny-STMF103工程,刷新工程即可看到添加后代码文件,正确修改后的文件结构如下图:
- 工程设置
打开工程属性,在C++ General -> Paths and Symbols 追加下面的目录:
- kernel/core/include
- kernel/pm/include
- arch/arm/arm-v7m/cortex-m3/gcc
- arch/arm/arm-v7m/common/include
- osal/cmsis_os
- board/STM32F103C8/TOS_CONFIG
如下图:
- 修改中断代码
(注意将添加代码置于USER CODE BEGIN和 USER CODE END 注释块中间,这样在CubeMX重新生成依赖代码时依然可以保留有自己的代码)
修改stm32f1xx_it.c文件:
- 增加头文件引用
/* USER CODE BEGIN Includes */
#include "tos.h"
/* USER CODE END Includes */
- 将PendSV_Handler中断函数标记为__weak
__weak void PendSV_Handler(void)
{
}
- 在SysTick_Handler中断函数添加如下代码:
void SysTick_Handler(void)
{
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
if( tos_knl_is_running() ) {
tos_knl_irq_enter();
tos_tick_handler();
tos_knl_irq_leave();
}
/* USER CODE END SysTick_IRQn 1 */
}
4. 增加demo代码和启动代码
修改main.c文件:
- 头文件引用
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "cmsis_os.h"
/* USER CODE END Includes */
- 添加demo代码(2个任务交替打印串口)
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//task1
#define TASK1_STK_SIZE 512
void task1(void *pdata);
osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
//task2
#define TASK2_STK_SIZE 512
void task2(void *pdata);
osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);
void task1(void *pdata)
{
int count = 1;
char buffer[64] = {0};
while(1) {
snprintf(buffer, sizeof(buffer), "task 1 %04d\r\n", count++);
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 0xFFFF);
//HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
osDelay(2000);
}
}
void task2(void *pdata)
{
int count = 1;
char buffer[64] = {0};
while(1) {
snprintf(buffer, sizeof(buffer), "task 2 %04d\r\n", count++);
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 0xFFFF);
osDelay(1000);
}
}
/* USER CODE END 0 */
- main函数中添加启动代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
osKernelInitialize(); //TOS Tiny kernel initialize
osThreadCreate(osThread(task1), NULL);// Create task1
osThreadCreate(osThread(task2), NULL);// Create task2
osKernelStart(); //Start TOS Tiny
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
三、编译工程和调试
- 如果配置正确,即可正常编译成功如下:
- 如果STLink已经正确配置好(SWD),就可以进行调试了:
将开发板的PA10(RX),PA9(TX)分别接USB转TTL的TX和RX引脚后打开串口,就
可以观察到串口上的日志输出,表示TencentOS tiny已经正常跑起来了。如下:
四、代码下载
为了方便参考,生成的代码已经放到csdn上,下载后即可编译。
下载连接
后续将与腾讯IoT-Hub关联的功能做介绍。