【RTOS】TencentOS tiny 移植到STM32F429(基于CubeMX)
參考資料:TencentOS tiny 內(nèi)核移植參考指南(Keil版)
一、前言
事例工程將完成以下內(nèi)容
軟件定時(shí)器(函數(shù)型)——使用TencentOS tiny定時(shí)器:500ms翻轉(zhuǎn)LED0
任務(wù)一——使用阻塞式ADC函數(shù)獲取采樣值,轉(zhuǎn)化為電壓值,并且進(jìn)行格式化完成后釋放信號(hào)量
任務(wù)二——消耗信號(hào)量,使用阻塞式串口發(fā)送函數(shù):顯示“TencentOS tin”與ADC采樣值、電壓值
任務(wù)三——消耗信號(hào)量,使用硬件FMC總線配置TFTLCD:顯示“TencentOS tin”與ADC采樣值、電壓值
方案二:
軟件定時(shí)器(函數(shù)型)——使用TencentOS tiny定時(shí)器:500ms開關(guān)LED0
軟件定時(shí)器(任務(wù)型)——使用阻塞式ADC函數(shù)獲取采樣值,轉(zhuǎn)化為電壓值,并且進(jìn)行格式化存入郵箱
任務(wù)——獲得郵件,使用阻塞式串口發(fā)送函數(shù):顯示“TencentOS tin”與ADC采樣值、電壓值
任務(wù)——獲得郵件,使用硬件FMC總線配置TFTLCD:顯示“TencentOS tin”與ADC采樣值、電壓值
二、使用STM32CubeMX新建裸機(jī)工程
1.選擇MCU型號(hào)
2.配置調(diào)試接口:Pinout & Configuration=>System Core=>SYS=>Debug
3.配置RCC:Pinout & Configuration=>System Core=>RCC=>HSE/LSE
此處高低速全部設(shè)置了外部時(shí)鐘
4.配置串口USART:Pinout & Configuration=>Connectivity=>USART1=>Mode
5.配置時(shí)鐘:Clock Configuration=>
6.配置ADC:Pinout & Configuration=>Analog=>ADC1=>IN5
此處使用ADC1通道5,單次12位右對(duì)齊,其中查閱芯片數(shù)據(jù)手冊(cè)可知ADC的掛在APB2上且時(shí)鐘不應(yīng)該高于36MHz,PCLK2設(shè)為了90MHz故要進(jìn)行四分頻
7.配置FMC:Pinout & Configuration=>Connectivity=>FMC
從原理圖看出
片選NE1
類型選擇LCD
寄存器選擇A18
數(shù)據(jù)線16條
T_XXX為觸屏相關(guān)內(nèi)容,事例工程暫忽略,請(qǐng)根據(jù)需求進(jìn)行配置
更多FMC內(nèi)容請(qǐng)參考vitoswwang大佬的CubeMX教程
8、配置GPIO:Pinout & Configuration=>System Core=>GPIO
LED0陽(yáng)極是接了3.3v,故MCU推挽輸出低電平才是點(diǎn)亮
LCD_BL是LCD背光控制,輸出速度應(yīng)該設(shè)為Very High
9.準(zhǔn)備TencentOS tiny的源碼
TencentOS tiny的源碼已經(jīng)開源,github-為:https://github.com/Tencent/TencentOS-tiny.git
由于本事例只用到TencentOS tiny的內(nèi)核,所以這里只需要用到 arch、board、kernel、osal四個(gè)目錄下的源碼。
三、內(nèi)核移植
1. 代碼目錄規(guī)劃
找到arch、kernel、osal文件夾,board目錄下則放入我們前面生成的裸機(jī)工程代碼,我們移植的開發(fā)板取名叫ALIENTEK_Apollo_STM32F429,裸機(jī)代碼全部拷貝到下面即可,如下圖所示:
接下來(lái)進(jìn)入TencentOS-tiny\board\ALIENTEK_Apollo_STM32F429\MDK-ARM目錄,打開keil工程,我們開始添加TencentOS tiny的內(nèi)核代碼。
2. 添加arch平臺(tái)代碼
tos_cpu.c是TencentOS tiny 的CPU適配文件,包括堆棧初始化,中斷適配,
port_s.S 文件是TencentOS tiny的任務(wù)調(diào)度匯編代碼,主要做彈棧壓棧等處理的,
port_c.c適配systick等。
比如現(xiàn)在我們移植的芯片是STM32F429IG,是ARM Cortex M4核,使用的編譯器是KEIL,所以我們選擇arch\arm\arm-v7m\cortex-m0+\armcc下的適配代碼
3. 添加lcd驅(qū)動(dòng)庫(kù)
lcd驅(qū)動(dòng)庫(kù)由廠家編寫,此處放入Src目錄下,放入工程方式同上
以下內(nèi)容與文檔一致
4. 添加內(nèi)核源碼
內(nèi)核源碼kerne目錄下包含core和pm兩個(gè)目錄,其中core下為基礎(chǔ)內(nèi)核,pm是內(nèi)核中的低功耗組件;基礎(chǔ)移植的時(shí)候可以不添加pm目錄下的代碼,如下圖所示,添加全部基本內(nèi)核源碼:
5. 添加cmsis os源碼
cmsis os是TencentOS tiny為了兼容cmsis標(biāo)準(zhǔn)而適配的OS抽象層,可以簡(jiǎn)化大家將業(yè)務(wù)從其他RTOS遷移到TencentOS tiny的工作量。
6. 添加TencentOS tiny頭文件目錄
添加頭文件目錄前,我們?cè)谝浦驳墓こ棠夸浵滦略鲆粋€(gè) TOS_CONFIG文件夾,用于存放TencentOS tiny的配置頭文件,也就是接下來(lái)要新建的tos_config.h文件;
TencentOS tiny所有要添加的頭文件目錄如下:
7. 新建TencentOS tiny系統(tǒng)配置文件 tos_config.h
#ifndef _TOS_CONFIG_H_ #define _TOS_CONFIG_H_ #include "stm32f4xx.h" // 目標(biāo)芯片頭文件,用戶需要根據(jù)情況更改 #define TOS_CFG_TASK_PRIO_MAX 10u // 配置TencentOS tiny默認(rèn)支持的最大優(yōu)先級(jí)數(shù)量 #define TOS_CFG_ROUND_ROBIN_EN 0u // 配置TencentOS tiny的內(nèi)核是否開啟時(shí)間片輪轉(zhuǎn) #define TOS_CFG_OBJECT_VERIFY_EN 1u // 配置TencentOS tiny是否校驗(yàn)指針合法 #define TOS_CFG_TASK_DYNAMIC_CREATE_EN 1u // TencentOS tiny 動(dòng)態(tài)任務(wù)創(chuàng)建功能宏 #define TOS_CFG_EVENT_EN 1u // TencentOS tiny 事件模塊功能宏 #define TOS_CFG_MMBLK_EN 1u //配置TencentOS tiny是否開啟內(nèi)存塊管理模塊 #define TOS_CFG_MMHEAP_EN 1u //配置TencentOS tiny是否開啟動(dòng)態(tài)內(nèi)存模塊 #define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u // TencentOS tiny 默認(rèn)動(dòng)態(tài)內(nèi)存池功能宏 #define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x100 // 配置TencentOS tiny默認(rèn)動(dòng)態(tài)內(nèi)存池大小 #define TOS_CFG_MUTEX_EN 1u // 配置TencentOS tiny是否開啟互斥鎖模塊 #define TOS_CFG_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否開啟消息隊(duì)列模塊 #define TOS_CFG_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否開啟消息郵箱模塊 #define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否開啟優(yōu)先級(jí)消息隊(duì)列模塊 #define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否開啟優(yōu)先級(jí)消息郵箱模塊 #define TOS_CFG_TIMER_EN 1u // 配置TencentOS tiny是否開啟軟件定時(shí)器模塊 #define TOS_CFG_PWR_MGR_EN 0u // 配置TencentOS tiny是否開啟外設(shè)電源管理模塊 #define TOS_CFG_TICKLESS_EN 0u // 配置Tickless 低功耗模塊開關(guān) #define TOS_CFG_SEM_EN 1u // 配置TencentOS tiny是否開啟信號(hào)量模塊 #define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u // 配置TencentOS tiny是否開啟任務(wù)棧深度檢測(cè) #define TOS_CFG_FAULT_BACKTRACE_EN 0u // 配置TencentOS tiny是否開啟異常棧回溯功能 #define TOS_CFG_IDLE_TASK_STK_SIZE 128u // 配置TencentOS tiny空閑任務(wù)棧大小 #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配置成函數(shù)模式 #endif
按照上面的模板配置好TencentOS tiny的各項(xiàng)功能后,將tos_config.h 文件放入要移植的board工程目錄下即可
四、創(chuàng)建TencentOS tiny任務(wù),測(cè)試移植結(jié)果
1. 修改部分代碼
在stm32f4xx_it.c文件中的PendSV_Handler函數(shù)前添加___weak關(guān)鍵字,因?yàn)樵摵瘮?shù)在TencentOS tiny的調(diào)度匯編中已經(jīng)重新實(shí)現(xiàn);同時(shí)在SysTick_Handler函數(shù)中添加TencentOS tiny的調(diào)度處理函數(shù),如下圖所示:
2. 編寫TencentOS tiny 測(cè)試內(nèi)容
#include "lcd.h" #include "stdio.h" #include "cmsis_os.h" //timer(管理邏輯為函數(shù)):翻轉(zhuǎn)LED k_timer_t led_tmr; void led_timer_cb(void *pdata); //task1:使用阻塞式ADC函數(shù) #define ADC1_STK_SIZE 256 void adc_entry(void *pdata); osThreadDef(adc_entry, osPriorityNormal, 1, ADC1_STK_SIZE); //task2:串口顯示 #define USART1_STK_SIZE 256 void usart_entry(void *pdata); osThreadDef(usart_entry, osPriorityNormal, 2, USART1_STK_SIZE); //task3:LCD顯示 #define LCD_STK_SIZE 256 void lcd_entry(void *pdata); osThreadDef(lcd_entry, osPriorityNormal, 2, LCD_STK_SIZE); //信號(hào)量 k_sem_t adc_cplt; void led_timer_cb(void *pdata) { HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); } void adc_entry(void *pdata) { while(1) { HAL_ADC_Start(&hadc1); if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10)) { adc1_in5_value = HAL_ADC_GetValue(&hadc1); adc1_in5_volt = adc1_in5_value * 330 / 4096;//單位:10mv } HAL_ADC_Stop(&hadc1); sprintf((char *)str_buff, "Value:%4d|||||Voltage:%d.%d%dV", adc1_in5_value,(adc1_in5_volt/100)%10,(adc1_in5_volt/10)%10,adc1_in5_volt%10);//23 osDelay(500); tos_sem_post_all(&adc_cplt);//釋放信號(hào)量 } } void usart_entry(void *pdata) { k_err_t err; while (K_TRUE) { err = tos_sem_pend(&adc_cplt, TOS_TIME_FOREVER); if (err != K_ERR_NONE) { continue; } HAL_UART_Transmit(&huart1,str_1,sizeof(str_1),10000); HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000); } } void lcd_entry(void *pdata) { k_err_t err; while (K_TRUE) { err = tos_sem_pend(&adc_cplt, TOS_TIME_FOREVER); if (err != K_ERR_NONE) { continue; } TFTLCD_Clear(GBLUE);//清屏背景顏色為青藍(lán)色 TFTLCD_ShowStr(10,90,200,16,16,lcd_id); //顯示TFTLCD驅(qū)動(dòng)芯片型號(hào) TFTLCD_ShowStr(10,150,736,32,32,str_buff); TFTLCD_ShowStr(120,240,700,32,32,str_1); } }
如圖:
繼續(xù)在main.c 的mian函數(shù)中硬件外設(shè)初始化代碼后添加TencentOS tiny的初始化代碼:
TFTLCD_Init(); sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//將LCD ID格式化到lcd_id數(shù)組。 osKernelInitialize(); //TOS Tiny kernel initialize tos_sem_create(&adc_cplt, 0);// Create TOS Tiny sem tos_timer_create(&led_tmr, 500, 500, led_timer_cb, K_NULL, TOS_OPT_TIMER_PERIODIC);// Create TOS Tiny timer:翻轉(zhuǎn)LED tos_timer_start(&led_tmr);///Start TOS Timer osThreadCreate(osThread(adc_entry), NULL);// Create TOS Tiny task:使用阻塞式ADC函數(shù) osThreadCreate(osThread(usart_entry), NULL);// Create TOS Tiny task:串口顯示 osThreadCreate(osThread(lcd_entry), NULL);// Create TOS Tiny task:TFTLCD顯示 osKernelStart();//Start TOS Tiny
如圖:
3.編譯下載測(cè)試TencentOS tiny移植結(jié)果
選擇調(diào)試下載器
編譯后下載
串口:
LCD:
IoT 嵌入式 開源 硬件開發(fā)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。