STM32從入門到RTOS
ARM處理器
ARM(Advanced RISC Machine)是一個32位精簡指令集(RISC)處理器架構(gòu),應(yīng)用于許多嵌入式系統(tǒng)設(shè)計中。自從ARMv7系列架構(gòu)開始,ARM公司推出了Cortex系列,并根據(jù)不同的應(yīng)用場景推出了Cortex-M,Cortex-A和Cortex-R三款不同方向的產(chǎn)品。

Cortex-M3與STM32
ARM代表了一種芯片標(biāo)準(zhǔn),體現(xiàn)了芯片的架構(gòu)設(shè)計,而具體涉及到存儲器容量,片上外設(shè),IO引腳數(shù)等實現(xiàn),則是由不同的芯片廠商進(jìn)行設(shè)計的,比如當(dāng)前最主流的STM32芯片,它是由ARM公司提供內(nèi)核,意法半導(dǎo)體公司(ST)基于此內(nèi)核進(jìn)行設(shè)計的。

Cortex-M3是一個32位處理器內(nèi)核,屬于ARMv7架構(gòu),哈佛體系結(jié)構(gòu),其內(nèi)部數(shù)據(jù)存取路徑、寄存器、存儲器接口均是32位,如STM32F1系列。
Cortex-M4是在Cortex-M3的基礎(chǔ)上強化了運算能力,新加了浮點、DSP、并行計算等,用以滿足需要有效且易于使用的控制和信號處理功能混合的數(shù)字信號控制市場,如STM32F4系列。
STM32產(chǎn)品命名規(guī)則
以常見搭載最小系統(tǒng)設(shè)計的STM32F103C8T6為例:
STM32:表示32位MCU
F103:表示基礎(chǔ)型
C:表示芯片上含48個引腳
8:表示閃存容量為64K字節(jié)
T:表示QFP封裝
6:表示工作溫度范圍在-40°C到85°C

STM32F103x系列
內(nèi)核:ARM Cortex-M3 32位的RISC內(nèi)核。
工作頻率:72MHz。
內(nèi)置高速存儲器,具有豐富的增強I/O端口和連接到兩條APB總線的外設(shè),所有型號的器件都包含2個12位的ADC、7個定時器,還包含標(biāo)準(zhǔn)的通信接口。
根據(jù)內(nèi)存大小進(jìn)行分類
小容量產(chǎn)品(16K至32K字節(jié)):STM32F103x4和STM32F103x6
中等容量產(chǎn)品(64K至128K字節(jié)):STM32F103x8和STM32F103xB
大容量產(chǎn)品(256K至512K字節(jié)):STM32F103xC、STM32F103xD和STM32F103xE
Cortex-M3總線接口
Cortex-M3總線接口基于AHB-Lite(Advanced High Performance Bus 高級高性能總線)和APB(Advanced Peripheral Bus 高級外圍總線)協(xié)議。
I-Code:指令總線,AHB‐Lite 總線協(xié)議的 32 位總線,負(fù)責(zé)取址操作。
D-Code:數(shù)據(jù)總線,AHB‐Lite 總線協(xié)議的 32 位總線,負(fù)責(zé)數(shù)據(jù)訪問操作。
System:系統(tǒng)總線(AHB),AHB‐Lite 總線協(xié)議的 32 位總線,負(fù)責(zé)所有數(shù)據(jù)的傳送。
AHB to APB:在AHB和2個APB總線間提供同步連接,APB1操作速度限于36MHz,APB2操作于全速(最高72MHz)。
外設(shè)總線(外部私有):外設(shè)總線(APB),基于APB總線協(xié)議的 32 位總線,掛載著片上外設(shè)。

硬件準(zhǔn)備
開發(fā)板 STM32F103C8T6 核心板,也稱STM32 Blue Pill

下載器/調(diào)試器 推薦STLink(意法半導(dǎo)體公司出品)或 JLink(Segger公司出品)
有一種U盤形狀的STLink V2調(diào)試器,容易丟失固件后無法識別使用,不推薦


以上兩種調(diào)試器均支持如下接口協(xié)議
JTAG:Joint Test Action Group,聯(lián)合測試工作組規(guī)定的一種仿真協(xié)議,它是一種國際標(biāo)準(zhǔn)測試協(xié)議。
SWD:Serial Wire Debugging,串行調(diào)試接口。

由于最小板只支持4針的SWD接口,這里連線方式如下。

串口通信?可選,用于查看日志,USB轉(zhuǎn)TTL芯片類型任選一種 CH340或PL2303。Windows10可通過Microsoft Store搜索安裝串口調(diào)試助手觀察串口數(shù)據(jù)。
內(nèi)存結(jié)構(gòu)
Cortext-M3缺少內(nèi)存管理單元(MMU),所有端口設(shè)備、存儲空間通過絕對地址訪問。32位對應(yīng)的4G大小的空間分成8大塊:代碼、SRAM、外設(shè)、外部RAM、外部設(shè)備、專用外設(shè)總線-內(nèi)部、專用外設(shè)總線-外部、特定廠商。具體細(xì)節(jié)請參考《The Definitive Guide To ARM Cortex M3》2.5 THE MEMORY MAP,其中
RAM 地址從 0x2000 0000 開始,用于運行時堆棧
Flash地址從 0x0800 0000 開始,用于存放程序代碼

啟動過程
STM32可通過設(shè)置BOOT(核心板上兩個黃色跳線)選擇不同的啟動方式,當(dāng)選用Flash啟動時,0x0800 0000 將映射到 0x0000 0000,通電后從Flash讀取第一條指令。請參考《The Definitive Guide To ARM Cortex M3》3.7 RESET SEQUENCE

芯片上電復(fù)位后,將會將從0x0000 0000 讀取棧頂指針,從0x0000 0004 讀取復(fù)位中斷程序(ResetHandler)地址。

Cortext-M3棧向下增長(先壓棧后存儲)所以SP的初始值應(yīng)該是棧頂上的第一個地址,比如使用0x20007C00到0x20007FFF(1 KB)作為棧區(qū),SP的值應(yīng)該為0x20008000

代碼原理
在使用IDE開發(fā)之前,先使用最基本的代碼描述程序的執(zhí)行原理。
核心板上有2個LED,紅色為電源指示、藍(lán)色對應(yīng)PC13,可通過設(shè)置GPIOC_13的高低電位控制藍(lán)色LED的閃爍。
STM32F103C8T6僅有64K的Flash和20K的SRAM,所以MSP初始值不能超過0x20005000。通過__asm__指令設(shè)置棧頂為0x20001000,復(fù)位后從main函數(shù)開始執(zhí)行。

STM32端口均為通用IO接口GPIO(General-purpose input/output Port),通過設(shè)置是否啟用、輸入輸出模式達(dá)到節(jié)能、端口復(fù)用的目的。使用前需要進(jìn)行一些基礎(chǔ)設(shè)置。通過查找手冊找到GPIOC的控制寄存器地址。

設(shè)置RCC_APB2ENR 外設(shè)時鐘使能寄存器 的IOPCEN位為1,使GPIO_C有效

設(shè)置GPIOx_CRH高位配置寄存器,配置推挽輸出模式,直接給LED供電

通過BSRR 端口位設(shè)置/清除寄存器 的BR13/BS13位,使PC13輸出高低電位

使用arm-none-eabi-gcc編譯上述代碼。

鏈接文件內(nèi)容如下,只是將程序放置到代碼段0x0起始位置。

將輸出bin文件通過STLinkUtility 或 STM32CubeProgrammer?工具燒錄即可。由于沒有引用任何外部庫代碼,生成的文件只有108Bytes。

如果出現(xiàn)Can not connect to target錯誤,杜邦線可能斷了或接觸不良
STMCubeIDE
STMCubeIDE是意法半導(dǎo)體基于Eclipse構(gòu)建的開發(fā)工具,可以快速生成項目框架。?https://www.st.com/en/development-tools/stm32cubeide.html

GPIO / PC13為GPIO_Output模式
RCC / High Speed Clock 高速時鐘源為Crystal/Ceramic Resonator?晶振/ 外部陶瓷振蕩器
SYS / Debug調(diào)試模式為Serial Wire



保存設(shè)置后,提示自動生成代碼。只要在指定區(qū)域編寫用戶代碼,后續(xù)修改ioc的配置可重新生成代碼。這里通過HAL庫函數(shù)修改GPIOC的狀態(tài),跟蹤這些庫函數(shù)可以看到,GPIOC、GPIOC_BASE等均是對應(yīng)寄存器的地址定義。
編寫時可通過 Alt+/ 激活代碼提示

點擊Run按鈕IDE將自動構(gòu)建并下載文件到芯片,Debug模式也可以在代碼中設(shè)置斷點調(diào)試。Memory Regions窗口會展示空間使用狀況,由于使用HAL庫,F(xiàn)lash的空間占用了增長到4.59KB。

中斷和異常
Cortex-M3內(nèi)核支持256個中斷,其中包含了16個內(nèi)核中斷(異常)和240個外部中斷,并且具有256級的可編程中斷設(shè)置。

其中SysTick是一個24位的系統(tǒng)節(jié)拍定時器,具有自動重載和溢出中斷功能,可以由這個定時器獲得一定的時間間隔。如果在SysTick位置放置一個函數(shù),定時檢查任務(wù)狀態(tài)并進(jìn)行上下文切換(將寄存器狀態(tài)寫入當(dāng)前任務(wù)的控制塊TCB中,找到下一個可執(zhí)行的任務(wù)并恢復(fù)寄存器狀態(tài)),就達(dá)到分時調(diào)度的效果,比如同等優(yōu)先級任務(wù)進(jìn)行輪詢調(diào)度。

PendSV是一個可掛起的系統(tǒng)服務(wù),配置為最低優(yōu)先級,它會在其他異常執(zhí)行完畢后再執(zhí)行,而且任何異常都可以中斷它。用戶代碼可直接請求一個PendSV,讓出CPU進(jìn)行任務(wù)切換如果某個IRQ正在活動并且被 SysTick搶占,它將懸起一個 PendSV異常,等SysTick、ISR執(zhí)行完畢后緩期執(zhí)行上下文切換。這樣可以避免中斷對上下文切換的干擾。

SysTick、PendSV異常是所有RTOS實現(xiàn)的核心。
μC/OS IIII移植
開源、商業(yè)化收費,是Micrium公司開發(fā)的一款嵌入式實時操作系統(tǒng),代碼規(guī)范符合ANSI-C標(biāo)準(zhǔn),簡潔干凈非常適合學(xué)習(xí)。最早出自于1992 年美國嵌入式系統(tǒng)專家Jean J.Labrosse 在《嵌入式系統(tǒng)編程》雜志的文章連載。1998年發(fā)布的第二代,通過嚴(yán)格的測試,2000年獲得DO-178BA級認(rèn)證,得到美國聯(lián)邦航空管理局FAA的認(rèn)證,可以用在飛行器上。2009年發(fā)行第三代,經(jīng)過了全新的設(shè)計,具有高度可移植性,沒有任務(wù)數(shù)目的限制。
官網(wǎng)提供了系統(tǒng)移植例程,這里可以參考STM32F107的
鏈接:https://pan.baidu.com/s/14qwunKCyeArTFGCYIIizbw? 提取碼:hadl
創(chuàng)建RTOS,將解壓后的uC-CPU, uC-LIB, uCOS-III 拷貝進(jìn)去
創(chuàng)建uC-Config,將EvalBoards中uCOS-III、BSP下的文件拷貝進(jìn)去

添加RTOS到Source Location

IDE使用gcc編譯器進(jìn)行構(gòu)建,所以uC-CPU、uC-LIB、uCOS-III目錄中ARM-Cortext-M3只保留GNU(RealView對應(yīng)Keil公司的MDK編譯器)。其余的可直接刪掉,或者右鍵Resource Configurations / Exclude from Build..

將所有包含代碼的目錄添加到Include Paths

清除bsp.h僅保留cpu.h的引用

清除bsp.c的無效內(nèi)容

使用Ctrl+B進(jìn)行嘗試編譯,此時剩下BSP_CPU_ClkFreq報錯。引用stm32f1xx_hal.h后重寫該方法,使用HAL_RCC_GetHCLKFreq獲取HCLK時鐘頻率

修改Core/Src/stm32f1xx_it.c

修改uCOS-III/Ports/ARM-Cortex-M3/Generic/GNU/os_cpu_a.s,使ucOS的PendSV替換掉默認(rèn)的函數(shù)功能


使用uCOS提供的函數(shù)重寫main方法

重新編譯后下載,uCOS可以正常運行。
FreeRTOS移植
開源、免費,2003年由Richard Barry創(chuàng)建,是除Linux以外最受歡迎的嵌入式操作系統(tǒng)。2017年作者加入亞馬遜擔(dān)任首席工程師,F(xiàn)reeRTOS也由亞馬遜管理,商業(yè)化版本為OpenRTOS。

從https://github.com/FreeRTOS/FreeRTOS-Kernel獲取系統(tǒng)源碼;
將FreeRTOS下的文件、include、portable下的GCC/ARM_CM3和MemMang拷貝到新建的RTOS源碼目錄;MemMang下每個文件代表不同的內(nèi)存管理方式,這里選用heap_2方式。
將FreeRTOS\Demo\CORTEX_STM32F103_GCC_Rowley\FreeRTOSConfig.h拷貝到include目錄。

添加到構(gòu)建路徑中

使用FreeRTOS的xPortPendSVHandler、vPortSVCHandler并替換默認(rèn)的異常Handler。
此處configTOTAL_HEAP_SIZE代表堆可用RAM總量,無需大內(nèi)存時可調(diào)小。

注釋掉默認(rèn)的PendSV_Handler、SVC_Handler,并在SysTick_Handler中啟動RTOS心跳

編寫測試程序以驗證是否移植成功。

串口通信
在項目配置中可以通過啟用USART1進(jìn)行串口通信,對應(yīng)PA9、PA10管腳生效,并生成usart.h和usart.c文件

重定義底層實現(xiàn),將printf函數(shù)的數(shù)據(jù)內(nèi)容通過husart1串口發(fā)送出去。

效果如下
