使用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關聯的功能做介紹。