天天看點

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

成就更好的自己

近期的項目需要在RTT下,使用SD卡運作FAT檔案系統,而且還能通過USB将這個SD卡虛拟化成大容量可儲存設備,在項目初期遇到了一些小問題,記錄一下,防止别的朋友踩坑。

文章概覽:

初始化後FAT頭檔案的包含問題;

RTT與CubeMX生成的其他模組檔案的相容;

測試平台:STM32F407VGT6

STM32CubeMX版本:6.1.2

HAL庫版本:1.16.1

RTT元件包版本:3.1.3

目錄

FAT頭檔案包含問題

RTT與CubeMX其他模組檔案的相容

FAT頭檔案包含問題

以往來說,筆者都是比較懶,都是像下面一樣将各種外設的xx.h檔案和自己寫的一些xx.h檔案都包含到main.h中,然後一些自定義的或者其他的.c檔案直接包含main.h檔案即可,這樣的做法簡單無腦。

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

但是在cubeMX生成的FAT工程裡,将fatfs.h包含在main.h中就瘋狂報錯,具體如下:

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容
RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

我在網上查了半天,就看到了兩個人跟我遇見的問題一樣但是問而無果,是以這裡把報錯當做代碼引用一下,增加編譯報錯關鍵字來讓有同樣問題的人搜到這篇部落格。

error type>(36): error:  #20: identifier "Diskio_drvTypeDef" is undefined

  extern Diskio_drvTypeDef  USER_Driver;

../FATFS/App/fatfs.h(37): error:  #20: identifier "FATFS" is undefined

  extern FATFS SDFatFS; /* File system object for SD logical drive */

../FATFS/App/fatfs.h(38): error:  #20: identifier "FIL" is undefined

  extern FIL SDFile; /* File object for SD */

../FATFS/App/fatfs.h(41): error:  #20: identifier "FATFS" is undefined

  extern FATFS USERFatFS; /* File system object for USER logical drive */

../FATFS/App/fatfs.h(42): error:  #20: identifier "FIL" is undefined

  extern FIL USERFile; /* File object for USER */

../Middlewares/Third_Party/FatFs/src/ff_gen_drv.c: 0 warnings, 6 errors

compiling syscall.c...

../Middlewares/Third_Party/FatFs/src/ff_gen_drv.h(57): error:  #20: identifier "_VOLUMES" is undefined

    uint8_t                 is_initialized[_VOLUMES];

../FATFS/App/fatfs.h(37): error:  #20: identifier "FATFS" is undefined

  extern FATFS SDFatFS; /* File system object for SD logical drive */

../FATFS/App/fatfs.h(38): error:  #20: identifier "FIL" is undefined

  extern FIL SDFile; /* File object for SD */

../FATFS/App/fatfs.h(41): error:  #20: identifier "FATFS" is undefined

  extern FATFS USERFatFS; /* File system object for USER logical drive */

../FATFS/App/fatfs.h(42): error:  #20: identifier "FIL" is undefined
           

剛開始我以為這樣做沒有問題,但是解決報錯将近兩個小時後覺得根據文法和編譯原理的知識仍然沒有解決,是以就嘗試恢複到代碼初始生成的狀态。當我把頭檔案恢複到main.c以後就不報錯了。

到此為止,就是因為頭檔案的不當包含出現的問題,這樣讓我想出了幾個利害關系:

  • 根據MDK的編譯機制,如果寫在一起,對其中任意一個頭檔案進行修改就會對所有包含這個頭檔案的.c檔案進行重新編譯,這樣很費時間;
  • 會讓整個工程雜亂無序,不符合高内聚低耦合的程式設計宗旨;
  • 對于程式的移植會出現各種各樣想不通看不懂的問題;
  • 對于開源程式來說會讓使用者不利于閱讀與部分移植;

雖然并沒有分析出包含在main.h中到底有什麼錯誤,但是也确實該改掉這種方式了,這個問題就到此為止吧!

RTT與CubeMX其他模組檔案的相容

問題描述:

之前一直使用的RTT隻是用到了UART,TIM,IIC等簡單的外設,這次一下子開了很多複雜功能就出現了一些問題。按照之前的RTT移植過程的配置都沒出現什麼問題,這一次配置完成後編譯0error0warning但是shell界面隻出現了版本輸出,不顯示msh>的指令行提示。

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

很快就鎖定了問題所在,但是在此之前需要先介紹一下幾個知識點。

問題分析:

  • msh(或者說shell)實質上是一個程序,隻要是程序就要參與時間片輪轉排程才能運作,一個任務隻要不讓出cpu的使用權,其他任務就永遠不會被輪到執行。
RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容
  • RTT的任務排程與輪轉是依靠單個任務中使用rt_thread_mDelay()函數,是使自己暫時挂起來讓出cpu的使用權。
  • Main函數實質上是一個程序,如果main不結束且者main函數中沒有rt_thread_mDelay()讓出資源或者在某一個程序中卡死,都會使程式卡死,導緻其他程序無法使用cpu。

回到正題,msh配置沒問題但是不顯示說明目前的程序并沒有讓出cpu的使用權,進而說明程式在某個地方陷入循環或者卡死。進過Debug後發現程式卡死在初始化的MX_USB_DEVICE_Init(),這是USB的初始化,進而深入查找在其調用的USB底層檔案看到了一個裸機開發熟悉的函數HAL_Delay(),就是他讓程式卡死的。為什麼呢?再來幾個知識點。

  • HAL庫的HAL_Delay函數的原理是使用systick核心滴答定時器進行精準定時進而延時的,在裸機開發中經常使用到。
  • RTT的時基定時器預設也是systick核心滴答定時器,通過這個定時器控制程序排程和時間片輪轉,進而控制程序排程。由rt_thread_mDelay()函數進行調用控制。

是以在RTT系統中不能出現HAL_Delay函數,否則會使程式卡死。在MX_USB_DEVICE_Init()中的底層配置中調用了這個函數,是以程式卡死在這裡。然後我又查了一下,我滴乖乖,SDIO和USB的操作中都不同程度的存在HAL_Delay函數,原因在于RTT與FAT一樣屬于第三方的軟體包,不是ST官方的東西,是以在相容性上與CubeMX生成的其他檔案會有差異與相容問題,不過由于HAL庫的全面與強大,通常這種相容問題都隻需要進行小部分修改即可解決。

解決辦法:

因為HAL_Delay()函數存在的地方不少,是以直接替換這個函數不太合适。是以我們直接修改HAL_Delay()的定義。在stm32f4xx_hal.c檔案中,包含rtthread.h檔案,然後找到HAL_Delay()函數,将函數體全部注釋,因為rt_thread_mdelay()函數的傳入參數與HAL_Delay()傳入參數類型一緻,直接加一句rt_thread_mdelay(Delay)即可;

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

或者由于HAL_Delay()是_week弱定義,我們可以直接在main.c中使用者代碼區重新定義一個void HAL_Delay(uint32_t Delay),内容就一句話rt_thread_mdelay(Delay);這樣重新生成代碼時就不會擔心被删掉。

RT-Thread&&STM32開發系列(2):FAT頭檔案包含報錯與RTT和CubeMX檔案相容問題成就更好的自己目錄FAT頭檔案包含問題RTT與CubeMX其他模組檔案的相容

問題解決!!!

寫在最後,未來幾期部落格就以目前的項目為Handle來寫,涉及STM32外設開發,子產品開發,RTT開發,項目完成的時候打算開源到gitee上,敬請期待。

繼續閱讀