1. 簡介
由於客戶項目需求,需要在STM32的硬件平臺上實現USB轉串口的功能,由於ST公司基於STM32硬件平臺實現了相應的USB庫以方便開發者進行開發,因此,在SylixOS下實現USB轉串口功能時對該USB庫進行了移植。由於該USB庫的實現是基於STM32的裸機代碼實現,因此在移植的過程中,不需要做過多的修改。
下面章節主要介紹在移植STM32的USB轉串口驅動到SylixOS下遇到的問題以及對應的解決方法。對於其中的有些解決方法在移植STM32其他外設驅動的過程中也依然適用。
2. 移植遇到的問題及解決方法
2.1 非對齊內存訪問錯誤
在移植完USB轉串口驅動後,燒寫SylixOS到STM32後,在運行過程中提示非法非對齊內存訪問的錯誤,並且在產生該問題後會導致系統一直重啓。調試過程中發現代碼運行到數據拷貝的語句發生錯誤,具體代碼如程序清單2.1所示。
程序清單2.1 非對齊內存訪問錯誤
USB_OTG_STS USB_OTG_WritePacket(USB_OTG_CORE_HANDLE *pdev, uint8_t *src, uint8_t ch_ep_num, uint16_t len) { USB_OTG_STS status = USB_OTG_OK; if (pdev->cfg.dma_enable == 0) { uint32_t count32b = 0, i= 0; __IO uint32_t *fifo; count32b = (len + 3) / 4; fifo = pdev->regs.DFIFO[ch_ep_num]; for (i = 0; i < count32b; i++) { USB_OTG_WRITE_REG32(fifo, *((__packed uint32_t *)src)); src += 4; } } return status; }
運行過程中發現src的地址在會出現非四字節對齊的情況,並且在該情況發生後系統便會宕機重啓,對於該種問題可增加一個臨時變量解決,具體解決方法如程序清單2.2所示。
程序清單2.2 非對齊內存訪問錯誤解決方法
USB_OTG_STS USB_OTG_WritePacket(USB_OTG_CORE_HANDLE *pdev, uint8_t *src, uint8_t ch_ep_num, uint16_t len) { USB_OTG_STS status = USB_OTG_OK; if (pdev->cfg.dma_enable == 0) { uint32_t count32b = 0, i = 0; __IO uint32_t *fifo; uint32_t data = 0; count32b = (len + 3) / 4; fifo = pdev->regs.DFIFO[ch_ep_num]; for (i = 0; i < count32b; i++) { if (((uint32_t) src) % 4 == 0) { USB_OTG_WRITE_REG32(fifo, *((__packed uint32_t *)src)); } else { lib_memcpy(&data, src, 4); USB_OTG_WRITE_REG32(fifo, data); } src += 4; } } return status; }
2.2 中斷優先級設置不當導致進入”Hard Fault”中斷
STM32採用的中斷控制器是NVIC,全稱爲Nested Vector Interrupt Controller,人們一般稱之爲“嵌套中斷向量控制器”,是用來管理中斷嵌套的,核心任務就是在於其優先級的管理。NVIC給每個中斷賦予先佔優先級和次佔優先級。具體關係描述如下:
1) 擁有較高先佔優先級的中斷可以打斷先佔優先級較低的中斷;
2) 若兩個先佔優先級的中斷同時掛起,則優先執行次佔優先級較高的中斷;
3) 若兩個掛起的中斷兩個優先級都一致,則優先執行位於中斷向量表中位置較高的中斷;
4) 無論任何時刻,次佔優先級都不會造成中斷嵌套,即中斷嵌套完全是由先佔優先級決定的。
在調試USB轉串口的過程中,由於系統tick中斷的先佔優先級被設置爲0(最高優先級)導致系統不停的重啓。需要注意的是,在對外設初始化的過程中,需要對外設中斷優先級進行手動設置,否則該外設中斷的先佔優先級將默認爲0。對於STM32的外設中斷優先級可以使用ST公司提供的庫函數進行設置,函數原型如程序清單2.3所示。
程序清單2.3 設置中斷優先級函數原型
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
函數HAL_NVIC_SetPriority原型分析:
參數IRQn是中斷號;
參數PreemptPriority是先佔優先級;
參數SubPriority是子優先級。
通常情況下,將外設中斷的先佔優先級設置爲0xF(最低優先級)。