天天看點

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

第八章建立HAL版本MDK工程

在前面的章節我們介紹了STM32H7xx官方固件包的一些知識,本章我們将講解建立HAL庫版本的MDK工程的詳細步驟。我們把本章建立好的工程放在CD光牒裡,路徑:4,程式源碼\2,标準例程-HAL庫版本\實驗0 基礎入門實驗\實驗0-3,建立工程實驗-HAL庫版本,大家在學習建立工程過程中間遇到一些問題,可以直接打開這個工程,然後對比學習。​

本章将分為如下三個小節:​

8.1 建立HAL庫版本MDK工程​

8.2 下載下傳驗證​

8.3 分散加載檔案簡介​

8.1 建立HAL庫版本MDK工程​

本節我們将教大家如何建立一個STM32H750的HAL庫版本MDK5工程。為了友善大家參考,我們将本節最終建立好的工程模闆存放在A盤:4、程式源碼\2,标準例程-HAL庫版本\實驗0 基礎入門實驗\實驗0-3,建立工程實驗-HAL庫版本,如遇建立工程問題,請打開該實驗對比。​

整個建立過程比較複雜,我們将其拆分為5個步驟進行講解,請準備大概2個小時時間,耐心細緻的做完!對你後續的學習非常有幫助!​

在建立工程之前,首先我們要做如下準備:​

1、 STM32Cube官方固件包:我們使用的固件包版本是STM32Cube_FW_H7_V1.6.0,固件包路徑:A盤à8,STM32參考資料à1,STM32CubeH7固件包。​

2、開發環境搭建:參考本書第三章相關内容。​

8.1.1建立工程檔案夾​

建立工程檔案夾分為2個步驟:1,建立工程檔案夾;2,拷貝工程相關檔案。​

1. 建立工程檔案夾​

首先我們在桌面建立一個工程根目錄檔案夾,後續的工程檔案都将在這個檔案夾裡建立,我們把這個檔案夾重命名為:實驗0-3,建立工程實驗-HAL庫版本。如圖8.1.1.1所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.1.1 建立工程根目錄檔案夾​

為了讓工程的檔案目錄結構更加清晰易懂,我們會在工程根目錄檔案夾下建立以下幾個檔案夾,每個檔案夾名稱及其作用如表8.1.1.1所示:​

名稱​ 作用​
Drivers​ 存放與硬體相關的驅動層檔案​​
Middlewares​ 存放正點原子提供的中間層元件檔案和第三方中間層檔案​
Output​ 存放工程編譯輸出檔案​
Projects​ 存放MDK工程檔案​
User​ 存放HAL庫使用者配置檔案、main.c、中斷處理檔案,以及分散加載檔案​

表8.1.1.1 工程根目錄建立檔案夾及其作用​

建立完成以後,最後得到我們的工程根目錄檔案夾如圖8.1.1.2所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.1.2 工程根目錄檔案夾​

另外我們的工程根檔案目錄下還有一個名為keilkill.bat的可執行檔案,輕按兩下便可執行。其作用是删除編譯器編譯後的無關檔案,減少工程占用的記憶體,友善打包。還有一個名為readme的記事本檔案,其作用是介紹本實驗的各種資訊。​

工程根目錄及其相關檔案夾建立好以後,我們需要拷貝一些工程相關檔案過來(主要是在Drivers檔案夾裡面),以便等下的建立工程需要。​

2. 拷貝工程相關檔案​

接下來,我們按圖8.1.1.2的根目錄檔案夾順序介紹每個檔案夾及其需要拷貝的檔案。​

Drivers檔案夾​

該檔案夾用于存放與硬體相關的驅動層檔案,一般包括如表8.1.1.2所示的三個檔案夾:​

檔案夾名稱​ 作用​
BSP​ 存放開發闆闆級支援包驅動代碼,如各種外設驅動​
CMSIS​ 存放CMSIS底層代碼,如啟動檔案(.s檔案)、stm32h7xx.h等​
STM32H7xx_HAL_Driver​ 存放HAL庫驅動代碼源檔案​
SYSTEM​ 存放正點原子系統級核心驅動代碼,如sys.c、delay.c和usart.c​

表8.1.1.2 Drivers包含檔案夾​

BSP檔案夾,用于存放正點原子提供的闆級支援包驅動代碼,如:LED、蜂鳴器、按鍵等。本章我們暫時用不到該檔案夾,不過可以先建好備用。​

CMSIS檔案夾,用于存放CMSIS底層代碼(ARM和ST提供),如:啟動檔案(.s檔案)、stm32h7xx.h等各種頭檔案。該檔案夾我們可以直接從STM32CubeH7固件包(路徑:A盤à8,STM32參考資料à1,STM32CubeH7固件包)裡面拷貝,不過由于固件包裡面的CMISIS相容了太多晶片,導緻非常大(300多MB),是以我們根據實際情況,對其進行了大幅精簡,精簡後的CMSIS檔案夾大小為2.3MB左右。精簡後的CMSIS檔案夾大家可以在:A盤à4,程式源碼à1,标準例程-HAL庫版本檔案夾裡面的任何一個實驗的Drivers檔案夾裡面拷貝過來。​

SYSTEM檔案夾,用于存放正點原子提供的系統級核心驅動代碼,如:sys.c、delay.c和usart.c等,友善大家快速搭建自己的工程。該檔案同樣可以從:A盤à4,程式源碼à1,标準例程-HAL庫版本檔案夾裡面的任何一個實驗的Drivers檔案夾裡面拷貝過來。​

STM32H7xx_HAL_Driver檔案夾,用于存放ST提供的H7xx HAL庫驅動代碼。該檔案夾我們可以直接從STM32CubeH7固件包裡面拷貝。直接拷貝“STM32CubeH7固件包àDrivers”路徑下的“STM32H7xx_HAL_Driver”檔案夾到我們工程的Drivers下,隻保留Inc和Src檔案夾即可。​

執行完以上操作後,Drivers檔案夾最終結構如圖8.1.1.3所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.1.3 工程根目錄下的Drivers檔案夾​

關于工程根目錄下的Drivers檔案操作到這裡就完成了,可以說步驟是有點多。在此過程遇到問題的話,請大家多參考我們提供的實驗0-3,建立工程實驗-HAL庫版本工程,一步步操作。​

Middlewares檔案夾​

該檔案夾用于存放正點原子和其他第三方提供的中間層代碼(元件/Lib等),如:USMART、MALLOC、TEXT、FATFS、USB、LWIP、各種OS、各種GUI等等。本章我們暫時用不到該檔案夾,不過可以先建好備用,後面的實驗将會陸續添加各種檔案。​

Output檔案夾​

該檔案夾用于存放編譯器編譯工程輸出的中間檔案,比如:.hex、.bin、.o檔案等等。這裡不需要操作,後面隻需要在MDK裡面設定該檔案夾為編譯過程中間檔案的存放檔案夾就行。​

Projects檔案夾​

該檔案夾用于存放編譯器(MDK、IAR等)工程檔案,我們主要用MDK,為了友善區分,我們在該檔案夾下建立:MDK-ARM檔案夾,用于存放MDK的工程檔案,如圖8.1.1.4所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.1.4 在Projects檔案夾下建立MDK-ARM檔案夾​

User檔案夾​

User檔案夾用于存放HAL庫使用者配置檔案、main.c檔案、中斷處理檔案,以及分散加載檔案。​

我們首先從官方固件包裡面直接拷貝官方的模闆工程下的HAL庫使用者配置檔案和中斷處理檔案到我們的User檔案夾裡。官方的模闆工程路徑:STM32Cube_FW_H7_V1.6.0\Projects\ STM32H750B-DK\Templates\Template_Project,打開Template_Project檔案夾,如圖8.1.1.8所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.1.8 官方模闆工程根目錄​

我們需要的檔案就在Inc和Src檔案夾裡面,在這兩個檔案夾裡面找到:stm32h7xx_it.c、stm32h7xx_it.h、stm32h7xx_hal_conf.h這三個檔案,并且拷貝到我們的User檔案夾下。​

最後在User檔案夾下建立一個命名為SCRIPT的檔案夾,用于存放分散加載檔案。分散加載檔案直接在我們的實驗0-2,建立工程實驗-HAL庫版本工程對應位置拷貝過來,後面再給大家講解。main.c檔案我們也是放在User檔案夾裡面的,後面在MDK裡面教大家建立.c檔案并儲存。 ​

8.1.2建立一個工程架構​

首先,打開MDK軟體。然後點選ProjectàNew uVision Project如圖8.1.2.1所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.1 建立MDK工程​

然後彈出工程命名和儲存的操作視窗,我們将工程檔案儲存路徑設定在上一節建立的工程檔案夾内,具體路徑為:桌面à實驗0-2,建立工程實驗-寄存器版本àProjectsàMDK-ARM,工程名字我們取:atk_h750,最後點選儲存即可。具體操作視窗如圖8.1.2.2所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.2 儲存工程界面​

之後,彈出器件選擇對話框,如圖8.1.2.3所示。因為MiniPRO STM32H750開發闆所使用的STM32型号為STM32H750VBT6,是以我們選擇:STMicroelectronicsàSTM32H7 SeriesàSTM32H750àSTM32H750VBTx(如果使用的是其他系列的晶片,選擇相應的型号就可以了,特别注意:一定要安裝對應的器件pack才會顯示這些内容哦!!如果沒得選擇,請關閉MDK,然後安裝 A盤:6,軟體資料\1,軟體\MDK5\ Keil.STM32H7xx_DFP.2.5.0.pack這個安裝包後重試)。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.3 器件選擇界面​

點選OK,MDK會彈出Manage Run-Time Environment對話框,如圖8.1.2.4所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.2.1.4 Manage Run-Time Environment界面​

這是MDK5新增的一個功能,在這個界面,我們可以添加自己需要的元件,進而友善建構開發環境,不過這裡我們不做介紹。是以在圖8.1.2.4所示界面,我們直接點選Cancel,即可,得到如圖8.1.2.5所示界面:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.5 工程初步建立​

此時,我們打開MDK-ARM檔案夾,會看到MDK在該檔案夾下自動建立了3個檔案夾(DebugConfig、Listings和Objects),如圖8.1.2.6所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.6 MDK建立工程時自動建立的檔案夾​

這三個檔案夾的作用如表8.1.2.1所示:​

檔案夾​ 作用​
DebugConfig​ 用于存放調試設定資訊檔案(.dbgconf),不可删除!​
Listings​ 用于存放編譯過程産生的連結清單等檔案​
Objects​ 用于存放編譯過程産生的調試資訊、.hex、預覽、.lib檔案等​

表8.1.2.1 三個檔案夾及其作用​

編譯過程産生的連結清單、調試資訊、預覽、lib等檔案,統稱為中間檔案。為了統一管理,友善使用,我們會把輸出在Listings和Objects檔案夾的内容,統一改為輸出到Output檔案夾(通過魔術棒設定),我們先把MDK自動生成的這兩個檔案夾(Listings和Objects)删除。​

至此,我們還隻是建了一個架構,還有好幾個步驟要做,比如添加檔案、魔術棒設定、編寫main.c等。​

8.1.3添加檔案​

本節将分5個步驟:1,設定工程名和分組名;2,添加啟動檔案;3,添加SYSTEM源碼4,添加 User 源碼;5,添加 STM32H7xx_HAL_Driver 源碼。​

1. 設定工程名和分組名​

在ProjectàTarget上右鍵,選擇Manage Project Items…(方法一)或在菜單欄點選品字形紅綠白圖示(方法二)進入工程管理界面,如圖8.1.3.1所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.1 進入工程管理界面​

在工程管理界面,我們可以執行設定工程名字(Project Targets)、分組名字(Groups)以及添加每個分組的檔案(Files)等操作。我們設定工程名字為:Template,并設定四個分組:Startup(存放啟動檔案)、User(存放main.c等使用者代碼)、Drivers/SYSTEM(存放系統級驅動代碼)、Readme(存放工程說明檔案),如圖8.1.3.2所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.2 設定工程名和分組名​

設定好之後,我們點選OK,回到MDK主界面,可以看到我們設定的工程名和分組名如圖8.1.3.3所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.3 設定成功​

這裡我們隻是建立了一個簡單的工程,并沒有添加BSP、Middlewares等分組,後面随着工程複雜程度的增加,我們需要一步步添加對應的分組。​

注意:為了讓工程結構清晰,我們會盡量讓MDK的工程分組和我們前面建立的工程檔案夾對應起來,由于MDK分組不支援多級目錄,是以我們将路徑也帶入分組命名裡面,以便區分。如:User分組對應User檔案夾裡面的源碼,Drivers/SYSTEM分組,對應Drivers/SYSTEM檔案夾裡面的源碼,Drivers/BSP分組對應Drivers/BSP檔案夾裡面的源碼等。​

2. 添加啟動檔案​

啟動檔案(.s檔案)包含STM32的啟動代碼,其主要作用包括:1、堆棧(SP)的初始化;2、初始化程式計數器(PC);3、設定向量表異常事件的入口位址;4、調用main函數等,是每個工程必不可少的一個檔案,我們在本書第九章會有詳細介紹。​

啟動檔案由ST官方提供,存放在STM32CubeH7軟體包的:DriversàCMSISàDevice àSTàSTM32H7xxàSourceàTemplatesàarm檔案夾下。因為我們開發闆使用的是STM32H750VBT6,對應的啟動檔案為:startup_stm32h750xx.s,為了節省空間,在精簡版CMSIS檔案夾裡面我們把其他啟動檔案都删了。

關于啟動檔案的說明,我們就介紹這麼多,接下來我們看如何添加啟動檔案到工程裡面。我們有兩種方法給MDK的分組添加檔案:1,輕按兩下Project下的分組名添加。2,進入工程管理界面添加。​

這了我們使用方法1添加(路徑:實驗0-3,建立工程實驗-HAL庫版本\Drivers\CMSIS\​

Device\ST\STM32H7xx\Source\Templates\arm),如圖8.1.3.4所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.4 輕按兩下分組添加啟動檔案(startup_stm32h750xx.s)​

上圖中,我們也可以點選Add按鈕進行檔案添加。添加完後,點選Close,完成啟動檔案​

添加,得到工程分組如圖8.1.3.5所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.5 啟動檔案添加成功​

3. 添加SYSTEM源碼​

這裡我們在工程管理界面(方法2)進行SYSTEM源碼添加。點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

按鈕,進入工程管理界面,選中Drivers/SYSTEM分組,然後點選:Add Files,進入檔案添加對話框,依次添加delay.c、sys.c和usart.c到該分組下,如圖8.1.3.6所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.6 添加SYSTEM源碼​

注意:這些源碼都是在第8.1.1小節的第二步拷貝過來的,如果之前沒拷貝,是找不到這些源碼的。添加完成後,如圖8.1.3.7所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.7 SYSTEM源碼添加完成​

4. 添加User源碼​

這裡我們在工程管理界面(方法2)進行User源碼添加。點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

按鈕,進入工程管理界面,選中User分組,然後點選:Add Files,進入檔案添加對話框,依次添加stm32h7xx_it.c和system_stm32h7xx.c到該分組下,如圖8.1.3.8所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.8 添加User源碼​

注意:這些源碼都是在第8.1.1小節的第二步拷貝過來的,如果之前沒拷貝,是找不到這些源碼的。添加完成後,如圖8.1.3.9所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.9 User源碼添加完成​

5. 添加STM32H7xx_HAL_Driver源碼​

接下來我們往Drivers/STM32H7xx_HAL_Driver分組裡添加檔案。點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

按鈕,進入工程管理界面,選中Drivers/STM32H7xx_HAL_Driver分組,然後點選:Add Files,進入檔案添加對話框,依次添加stm32h7xx_hal.c、stm32h7xx_hal_cortex.c、stm32h7xx_hal_dma.c、stm32h7xx_hal_gpio.c、stm32h7xx_hal_pwr.c、stm32h7xx_hal_pwr_ex.c、stm32h7xx_hal_rcc.c、stm32h7xx_hal_rcc_ex.c、stm32h7xx_hal_uart.c、stm32h7xx_hal_uart_ex.c、stm32h7xx_hal_usart.c和stm32h7xx_hal_usart_ex.c到該分組下,如圖8.1.3.10所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.10 添加STM32H7xx_HAL_Driver源碼​

添加完成後,如圖8.1.3.11所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.3.11 STM32H7xx_HAL_Driver源碼添加完成​

可以看到分組中有些.c檔案有個小鑰匙的符号,這是因為官方的固件包的檔案設定了隻讀權限,我們取消隻讀權限就好了,方法如圖8.1.2.12所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.2.12 取消工程檔案夾的隻讀權限​

8.1.4魔術棒設定​

為避免編寫代碼和編譯報錯,我們需要通過魔術棒對MDK工程進行相關設定。在MDK主界面,點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

(魔術棒圖示,即Options for Target按鈕),進入工程設定對話框,我們将進行如下幾個頁籤的設定。​

1. 設定Target頁籤​

在魔術棒àTarget頁籤裡面,我們進行如圖8.1.4.1所示設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.1 Target頁籤設定​

上圖中,我們設定晶片所使用的外部晶振頻率為8Mhz,選擇ARM Compiler版本為:Use default compiler version 5(即AC5編譯器)。​

這裡我們說明一下AC5和AC6編譯的差異,如表8.1.4.2所示:​

對比項​ AC5​ AC6​ 說明​
中文支援​ 較好​ 較差​ AC6對中文支援極差,goto​definition無法使用,誤報等​
代碼相容性​ 較好​ 較差​ AC6對某些代碼優化可能導緻運作異常,需慢慢調試​
編譯速度​ 較慢​ 較快​ AC6編譯速度比AC5快 ​
文法檢查​ 一般​ 嚴格​ AC6文法檢查非常嚴格,代碼嚴謹性較好​

表8.1.4.1 AC5&AC6簡單對比​

由于AC5對中文支援比較好,且相容性相對好一點,為了避免不必要的麻煩,我們推薦大家使用AC5編譯器。為了讓大家自由選擇,我們正點原子的源碼,也是支援AC6編譯器的,不過在頁籤設定上稍有差異,具體差異如表8.1.4.2所示:​

頁籤​ AC5​ AC6​ 說明​
Target​ 選擇AC5編譯器​ 選擇AC6編譯器​ 選擇對應的編譯器​
C/C++​

Misc Controls​

無需設定​

Misc Controls設定:​

-Wno-invalid-source-encoding​

AC6需設定編譯選項以關閉對漢字的錯誤警告,AC5則不要​

表8.1.4.2 AC5&AC6設定差異​

2. 設定Output頁籤​

在魔術棒àOutput頁籤裡面,進行如圖8.1.4.2所示設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.2 設定Output頁籤​

注意,我們勾選:Browse Information,用于輸出浏覽資訊,這樣就可以使用go to definition檢視函數/變量的定義,對我們後續調試代碼比較有幫助,如果不需要調試代碼,則可以去掉這個勾選,以提高編譯速度。​

3. 設定Listing頁籤​

在魔術棒àListing頁籤裡面,進行如圖8.1.4.3所示設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.3 設定Listing頁籤​

經過Output和Listing這兩步設定,原來存儲在Objects和Listings檔案夾的内容(中間檔案)就都改為輸出到Output檔案夾了。​

4. 設定C/C++頁籤​

在魔術棒àC/C++頁籤裡面,進行如圖8.1.4.4所示設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.4 設定C/C++頁籤​

在②處設定了全局宏定義:STM32H750xx,用于定義所用STM32型号,在stm32h7xx.h裡面會用到該宏定義。​

在③處設定了優化等級為-O0,可以得到最好的調試效果,當然為了提高優化效果提升性能并降低代碼量,可以設定-O1~-O3,數字越大效果越明顯,不過也越容易出問題。注意:當使用AC6編譯器的時候,這裡推薦預設使用-O1優化。​

在④處勾選C99模式,即使用C99 C語言标準。​

在⑤處,我們可以進行頭檔案包含路徑設定,點選此按鈕,進行如圖8.1.4.5所示設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.5 設定頭檔案包含路徑​

上圖中我們設定了4個頭檔案包含路徑,其中3個在Drivers檔案夾下,一個在User檔案夾下。為避免頻繁設定頭檔案包含路徑,正點原子最新源碼的include全部使用相對路徑,也就是我們隻需要在頭檔案包含路徑裡面指定一個檔案夾,那麼該檔案夾下的其他檔案夾裡面的源碼,如果全部是使用相對路徑,則無需再設定頭檔案包含路徑了,直接在include裡面就指明了頭檔案所在。​

關于相對路徑,這裡大家記住3點:​

1,預設路徑就是指MDK工程所在的路徑,即.uvprojx檔案所在路徑(檔案夾)​

2,“./”表示目前目錄(相對目前路徑,也可以寫做“.\”)​

3,“../”表示目前目錄的上一層目錄(也可以寫做“..\”)​

舉例來說,上圖中:..\..\Drivers\CMSIS\Device\ST\STM32H7xx\Include,前面兩個“..\”,表示Drivers檔案夾在目前MDK工程所在檔案夾(MDK-ARM)的上2級目錄下,具體解釋如圖8.1.4.6所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.6 ..\..\Drivers\CMSIS\Device\ST\STM3H7xx\Include的解釋​

上圖表示根據頭檔案包含路徑:..\..\Drivers\CMSIS\Device\ST\STM32H7xx\Include,編譯器可以找到⑥處所包含的這些頭檔案,即代碼裡面可以直接include這些頭檔案使用。​

再舉個例子,在完成如圖6.1.4.5所示的頭檔案包含路徑設定以後,我們在代碼裡面編寫:​

#include "./SYSTEM/sys/sys.h"      

即表示目前頭檔案包含路徑所訓示的4個檔案夾裡面,肯定有某一個檔案夾包含了:SYSTEM/sys/sys.h的路徑,實際上就是在Drivers檔案夾下面,兩者結合起來就相當于:​

#include "../../Drivers/SYSTEM/sys/sys.h"      

這就是相對路徑。它既可以減少頭檔案包含路徑設定(即減少MDK配置步驟,免去頻繁設定頭檔案包含路徑的麻煩),同時又可以很友善的知道頭檔案具體在那個檔案夾,是以我們推薦在編寫代碼的時候使用相對路徑。​

關于相對路徑,我們就介紹這麼多,大家搞不明白的可以在網上搜尋相關資料學習,也可以在後面的學習,分析我們其他源碼,慢慢體會,總之不難,但是好用。​

最後,我們如果使用AC6編譯器,則在圖6.1.4.4的Misc Controls處需要設定:-Wno-invalid-source-encoding,避免中文編碼報錯,如果使用AC5編譯器,則不需要該設定!!​

5. 設定Debug頁籤​

在魔術棒àDebug頁籤裡面,進行如圖8.1.4.7所示設定: ​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.7 Debug頁籤設定​

圖中,我們選擇使用:CMSIS-DAP仿真器,使用SW模式,并設定最大時鐘頻率為10Mhz,以得到最高下載下傳速度。當我們将仿真器和開發闆連接配接好,并給開發闆供電以後,仿真器就會找到開發闆晶片,并在SW Device視窗顯示晶片的IDCODE、Device Name等資訊(圖中⑤處),當無法找到時,請檢查供電和仿真器連接配接狀況。​

6. 設定Utilities頁籤​

在魔術棒àDebug頁籤裡面,進行如圖8.1.4.8所示設定: ​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.8 Utilities頁籤設定​

圖中⑥處下載下傳算法STM32H750,是MDK預設添加的,針對STM32H750系列産品。除此之外,我們還要添加[email protected]算法,點選⑦處按鈕添加即可。添加好算法後,設定算法使用的 RAM 位址和大小,這裡設定的起始位址為:0X2000 0000(DTCM),大小為:0X3000。必須按這個大小設定,否則下載下傳會出錯(無法加載算法)。​

7.添加分散加載檔案​

由于STM32H750VBT6晶片内部的FLASH的空間比較少(隻有128KB)。對于大的工程,這個FLASH空間是不夠用的,為了解決這個問題,同時友善後續工程的建立,我們統一使用分散加載的方式來決定FLASH記憶體的配置設定,而不用MDK預設的設定。關于分散加載是什麼?我們後面8.3小節會講解,請大家先跟着我們把建立工程完成。​

分散加載的檔案已經為大家準備好了,可以在實驗0-3,建立工程實驗-HAL庫版本\User\SCRIPT,或者在(A盤)/程式源碼/STM32啟動檔案/分散加載_HAL庫版本/SCRIPT中拷貝qspi_code.scf檔案到我們的工程User\SCRIPT路徑下,如圖8.1.4.9所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.9 拷貝分散加載檔案到工程​

注意:這裡的分散加載檔案寄存器跟HAL庫是不一樣的,我們建立HAL庫工程,是以必需用HAL庫版本的分散加載檔案。​

接下來我們需要對MDK進行配置,相當于把分散加載檔案關聯到工程裡。方法:點選魔術棒

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

,inker頁籤à取消勾選:Use Memory Layout from Target DialogàScatter File路徑à選擇SCRIPT檔案夾à 選擇qspi_code.scf檔案,然後,在disable Warnings一欄,添加:6314,6329,屏蔽6314和6329這兩個警告。如不屏蔽,當分散加載裡面有某些段(section)沒用到,則會報警告,是以我們需要屏蔽這兩個警告。如圖8.1.4.10所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.4.10 添加分散加載檔案​

至此,添加分散加載檔案的相應操作就完成了。​

8.1.5添加main.c,并編寫代碼​

在MDK主界面,點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

,建立一個main.c檔案,并儲存在User檔案夾下。然後輕按兩下User分組,彈出添加檔案的對話框,将User檔案夾下的main.c檔案添加到User分組下。得到如圖8.1.5.1所示的界面:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.1在User分組下加入main.c檔案​

至此,我們就可以開始編寫我們自己的代碼了。我們在main.c檔案裡面輸入如下代碼:​

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"

void led_init(void);  /* LED初始化函數聲明 */

int main(void)
{
 sys_cache_enable();  /* 打開L1-Cache */
 HAL_Init();   /* 初始化HAL庫 */
 sys_stm32_clock_init(240, 2, 2, 4);  /* 設定時鐘, 480Mhz */
 delay_init(480);   /* 延時初始化 */
 led_init();   /* LED初始化 */
 while(1)
 { 
 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);  /* PB4置1 */ 
 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET);  /* PE5置0 */ 
 delay_ms(500);
 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);  /* PE5置1 */
 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_RESET);  /* PE6置0 */
 delay_ms(500); 
 HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_SET);  /* PE6置1 */
 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);  /* PB4置0 */
 delay_ms(500);
 }
}

/**
初始化LED相關IO口, 并使能時鐘
無
無
 */
void led_init(void)
{
 GPIO_InitTypeDef gpio_init_struct;
 __HAL_RCC_GPIOB_CLK_ENABLE(); /* PB4時鐘使能 */
 __HAL_RCC_GPIOE_CLK_ENABLE(); /* PE6時鐘使能 */
 __HAL_RCC_GPIOE_CLK_ENABLE(); /* PE5時鐘使能 */

 gpio_init_struct.Pin = GPIO_PIN_4;  /* LED0引腳 */
 gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;  /* 推挽輸出 */
 gpio_init_struct.Pull = GPIO_PULLUP;  /* 上拉 */
 gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;  /* 高速 */
 HAL_GPIO_Init(GPIOB, &gpio_init_struct);  /* 初始化LED0引腳 */

 gpio_init_struct.Pin = GPIO_PIN_6;  /* LED1引腳 */
 HAL_GPIO_Init(GPIOE, &gpio_init_struct);  /* 初始化LED1引腳 */

 gpio_init_struct.Pin = GPIO_PIN_5;  /* LED2引腳 */
 HAL_GPIO_Init(GPIOE, &gpio_init_struct);  /* 初始化LED2引腳 */
}      

此部分代碼,在A盤à4,程式源碼à1,标準例程-HAL庫版本à實驗0 基礎入門實驗à實驗0-3,建立最工程實驗-HAL庫版本àUseràmain.c裡面有,大家可以自己輸入,也可以直接拷貝。強烈建議自己輸入,以加深對程式的了解和印象!!​

注意,這裡的include就是使用的相對路徑,關于相對路徑,請參考前面C/C++頁籤設定章節進行學習。​

編寫完main.c,我們點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

(Rebuild)按鈕,編譯整個工程,編譯結果如下圖所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.2 編譯結果​

編譯結果可以看到1個錯誤,0個警告。這個錯誤說找不到main.h,因為我們也不需要用到main.h,輕按兩下這個錯誤會彈出下面的stm32h7xx_it.c檔案對應包含main.h的語句。我們隻需要把它删除,然後重新編譯,如圖8.1.5.3所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.3 删除包含main.h的語句​

編譯後發現又有一個警告,警告HAL_IncTick函數沒有聲明,如圖8.1.5.4所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.4 編譯報警告​

因為這個函數是在stm32h7xx_hal.c定義了,并且在stm32h7xx_hal.h聲明了。我們把stm32h7xx_hal.h包含進來即可。這裡還有一個原因是整個工程沒有包含stm32h7xx_hal.h的語句,我們需要用到它,是以在這裡把它包含進來。官方的main.h是有包含這個頭檔案的。我們不用main.h檔案,我們在stm32h7xx_it.c檔案剛才删除包含main.h的語句的位置,編寫包含stm32h7xx_hal.h語句,如圖8.1.5.5所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.5 包含stm32h7xx_hal.h頭檔案到工程​

再進行編譯就會發現0錯誤0警告,結果如圖8.1.5.6所示。​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.1.5.6 編譯結果​

編譯結果提示:代碼總大小(Porgram Size)為:FLASH占用13520位元組(Code + RO + RW),SRAM占用2008位元組(RW + ZI);并成功建立了Hex檔案(可執行檔案,放在Output目錄下)。​

總結:如果編譯提示有錯誤/警告,請根據提示,從第一個錯誤/警告開始解決,直到0錯誤0警告。如果出錯,很有可能是之前的操作存在問題,請對照教程找問題。​

另外,我們在Readme分組下還沒有添加任何檔案,由于隻是添加一個說明性質的檔案(.txt),并不是工程必備檔案,是以這裡我們就不添加了,開發闆CD光牒的源碼我們是有添加的,大家可以去參考一下。​

至此,建立HAL庫版本MDK工程完成。​

8.2 下載下傳驗證​

這裡我們繼續使用DAP仿真器下載下傳,在MDK主界面,點選:

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

(下載下傳按鈕,也可以按鍵盤快捷鍵:F8),就可以将代碼下載下傳到開發闆,如圖8.2.1所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.2.1 下載下傳成功​

上圖提示:Application running…,則表示代碼下載下傳成功,且開始運作。此時,看到RGB的紅、藍、綠三種燈輪流亮,類跑馬燈。如果有朋友沒能下載下傳成功,請看第四章尋找問題,或者直接對照我們提供的實驗0-3,建立工程實驗-HAL庫版本工程設定。​

8.3 分散加載檔案簡介​

ARM晶片用于在連結時指定存儲器配置設定方案的檔案,稱之為分散加載檔案(.sct),它可以将不同的代碼(.o檔案)放在不同的存儲空間。關于分散加載的詳細介紹,請參考:A盤à8,STM32參考資料à4,分散加載à分散加載檔案淺釋.pdf,這是周立功公司的一份文檔資料,詳細介紹了.sct檔案的基礎概念、文法及應用執行個體說明,對學習分散加載非常有幫助,請大家務必先學習一下這個文檔。​

本節,我們僅對.sct檔案進行一個簡介,友善大家學習。​

首先明确一個概念:MDK編譯任何STM32工程,都會需要用到分散加載檔案。分散加載檔案的來源有兩種方式:​

  1. 通過MDK自己生成;​

2,通過使用者指定(使用者自己編寫);​

首先,我們來看MDK自己生成的.sct檔案。​

選擇本章建立工程àMDK的魔術棒àLinker頁籤裡面,進行如圖8.3.1所示的設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.3.1 勾選Use Memory Layout from Target Dialog選項​

勾選Use Memory Layout from Target Dialog選項後,MDK就會根據Target頁籤裡面的相關設定來決定存儲器配置設定,如圖8.3.2所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.2.2 MDK預設的存儲器配置設定​

标号①,是MDK的隻讀存儲區域(ROM)和可讀寫存儲區域(RAM)的配置區域。​

标号②處,說明預設将所有的代碼(Code + RO Data + RW Data)都存放到IROM1指定的位址範圍上。其起始位址為:0X0800 0000,大小為:0X20000。​

标号③處,說明預設将所有的變量及堆棧(RW Data + ZI Data)都存放在IRAM1和IRAM2指定的位址範圍上。IRAM1的起始位址為:0X2000 0000,大小為:0X20000;IRAM2的起始位址為:0X2400 0000,大小為:0X80000;變量的具體位置由編譯器自動配置設定。​

在完成以上兩步操作以後,對MDK進行一次編譯,在編譯成功後,MDK會自動生成一個以工程名命名的.sct檔案,存放在Output檔案夾裡面,如圖8.2.3所示:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.2.3 MDK自動生成的分散加載檔案​

打開上圖中的test.sct檔案,其内容如下:​

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00020000 { ; load region size_region
 ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
 *.o (RESET, +First)
 *(InRoot$$Sections)
 .ANY (+RO)
 .ANY (+XO)
 }
 RW_IRAM1 0x20000000 0x00020000 { ; RW data
 .ANY (+RW +ZI)
 }
 RW_IRAM2 0x24000000 0x00080000 {
 .ANY (+RW +ZI)
 }
}      

LR_IROM1是一個加載域,起始位址為:0X0800 0000,大小為:0X0002 0000。它包含三個運作域分别是:​

ER_IROM1運作域,起始位址為:0X0800 0000,大小為:0X0002 0000。​

RW_IRAM1運作域,起始位址為:0X2000 0000,大小為:0X0002 0000。​

RW_IRAM2運作域,起始位址為:0X2400 0000,大小為:0X0008 0000。​

其中:​

ER_IROM1為ROM區域,存放:Code + RO Data + RW Data等隻讀資料,由:.ANY (+RO)指定,即所有隻讀資料,都存放在這個區域。​

RW_IRAM1和RW_IRAM2為RAM區域,存放:RW Data + ZI Data等可讀寫資料,由:.ANY (+RW +ZI)指定,即所有的可讀寫資料,都存放在這兩個區域,具體存放位置由MDK編譯器自動配置設定。​

*.o (RESET, +First):表示優先(+FIRST)将RESET(即中斷向量表)段放這個域的起始位置,實際上就是把中斷向量表拷貝到最開始的位置。​

* (InRoot$$Sections):表示将所有用到的庫段放到root區,如:__main.o、__scatter*.o和__dc*.o等。​

以上,就是MDK自動生成的.sct檔案簡介。​

接下來,我們看使用者指定.sct檔案的實作方式。選擇本章建立工程àMDK的魔術棒àLinker頁籤裡面,進行如圖8.3.4所示的設定:​

《MiniPRO H750開發指南》第八章 建立HAL版本MDK工程

圖8.2.4 取消Use Memory Layout from Target Dialog選項​

标号①,取消Use Memory Layout from Target Dialog選項,使用使用者自定義分散加載檔案。​

标号②,建立工程時,已選擇SCRIPT\qspi_code_scf.scf分散加載檔案。​

标号③,點選Edit按鈕,即可在MDK裡面打開qspi_code_scf.scf分散加載檔案。​

qspi_code.scf的内容如下: ​

#! armcc -E
;#! armclang -E --target=arm-arm-none-eabi -mcpu=cortex-m7 -xc
/* 使用說明 
! armclang -E --target=arm-arm-none-eabi -mcpu=cortex-m7 -xc, 用于AC6編譯報錯(L6709E錯誤)時,請使用此設定
!armcc -E, 用于AC5編譯報錯(L6709E錯誤)時,請使用此設定
注意,設定必須放本檔案第一行!否則還是報錯!請注意調整順序!
*/

/**
 **********************************************************************************************
 * @file main.c
正點原子團隊(ALIENTEK)
 * @version V1.0
 * @date 2020-03-13
分散加載檔案(.scf檔案)
廣州市星翼電子科技有限公司
 **********************************************************************************************
 * @attention
 *
 **********************************************************************************************
 */

#define m_stmflash_start 0X08000000 /* m_stmflash(STM32内部FLASH)域起始位址 */
#define m_stmflash_size 0X20000 /* m_stmflash(STM32内部FLASH)大小,H750是128KB */

#define m_qspiflash_start 0X90000000 /* m_qspiflash(外擴QSPI FLASH)域起始位址 */
#define m_qspiflash_size 0X800000 /* m_qspiflash(外擴QSPI FLASH)大小,W25Q64是8MB */

#define m_stmsram_start 0X24000000 /* m_stmsram(STM32内部RAM)域起始位址,定義在D1,AXI SRAM */
#define m_stmsram_size 0X80000 /* m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB */

LR_m_stmflash m_stmflash_start m_stmflash_size /* LR_m_stmflash加載域 */
{
/* ER_m_stmfalsh運作域,起始位址為:m_stmflash_start,大小為:m_stmflash_size */
ER_m_stmflash m_stmflash_start m_stmflash_size { 
/* 優先(+FIRST)将RESET(中斷向量表)段放這個域,實際上就是把中斷向量表拷貝到m_stmflash_start */
是一個段名,表示中斷向量表(在.s檔案定義);+FIRST表示時第一個要加載的. */
*.o (RESET, +First) 
将所有的庫段(C/C++标準庫)放在root region.如__main.o,__scatter*.o等 */
 * (InRoot$$Sections) 
 * (Veneer$$Code)
 libinit.o
 libinit2.o
 libshutdown.o
 libshutdown2.o
 __rtentry.o
 __rtentry2.o
 __rtentry4.o
 rtexit.o
 rtexit2.o

 use_no_semi_2.o
 heapauxi.o
 use_no_semi.o
 sys_stackheap_outer.o
 exit.o
 libspace.o
 fpinit.o
 lludivv7m.o
 startup_stm32h750xx.o

 rt_locale_intlibspace.o
 lc_numeric_c.o
 lc_ctype_c.o

 main.o
 sys.o
 usart.o
 delay.o
 pwr.o

的QSPI接口不支援讀時寫,是以必須把以下3個檔案放到内部FLASH,以保證可以
對QSPI FLASH的寫入 */
 qspi.o
 norflash.o
 norflash_ex.o

針對HAL庫驅動添加到内部的檔案 */
 system_stm32h7xx.o
 stm32h7xx_hal.o
 stm32h7xx_hal_cortex.o
 stm32h7xx_hal_rcc.o
 stm32h7xx_hal_rcc_ex.o
 stm32h7xx_hal_gpio.o
 stm32h7xx_hal_dma.o
 stm32h7xx_hal_dma_ex.o
 stm32h7xx_hal_qspi.o
 stm32h7xx_hal_pwr.o
 stm32h7xx_hal_pwr_ex.o
}
/* RW_m_stmsram運作域,起始位址為:m_stmsram_start,大小為:m_stmsram_size. */
 RW_m_stmsram m_stmsram_start m_stmsram_size { 
将所有用到的RAM都放在這個區域 */
 }
}

LR_m_qspiflash m_qspiflash_start m_qspiflash_size /* LR_m_qspiflash加載域 */
{
/* ER_m_qspiflash加載域,起始位址為:m_qspiflash_start,大小為:m_qspiflash_size */
 ER_m_qspiflash m_qspiflash_start m_qspiflash_size { 
将隻讀資料(+RO)放這個域,任意配置設定.相當于程式就是存放在這個域的 */
 }
}      

相比于MDK自己生成的分散加載檔案,我們自己編寫的相對複雜一些,qspi_code.scf分散加載檔案包含2個加載域,3個運作域,分别是:​

LR_m_stmflash加載域,起始位址為:m_stmflash_start(宏定義,實際值:0X0800 0000),大小為:m_stmflash_size(宏定義,實際值:0X20000)。它包含二個運作域分别是:​

ER_m_stmflash運作域,起始位址為:m_stmflash_start(宏定義,實際值:0X0800 0000),大小為:m_stmflash_size(宏定義,實際值:0X20000)。​

RW_m_stmsram運作域,起始位址為:m_stmsram_start(宏定義,實際值:0X2400 0000)大小為:m_stmsram_size(宏定義,實際值:0X80000)。​

LR_m_qspiflash加載域,起始位址為:m_qspiflash_start(宏定義,實際值:0X9000 0000)大小為:m_qspiflash_size(宏定義,實際值:0X80000)。它包含一個運作域:​

ER_m_qspiflash運作域,起始位址為:m_qspiflash_start(宏定義,實際值:0X9000 0000)大小為:m_qspiflash_size(宏定義,實際值:0X80000)。​

具體的存儲器配置設定情況為:​

ER_m_stmflash運作域,包含:*.o (RESET, +First)開始到delay.o結束的相關代碼,這些代碼運作在内部FLASH,可以得到最佳的性能。需要注意的是:這些代碼大部分都是必須放到内部FLASH,否則無法正常運作!!​

ER_m_qspiflash運作域,所有沒有在ER_m_stmflash運作域指定的代碼,都被放在這個運作域,這些代碼運作在外部SPI FLASH,速度比内部FLASH慢一些。​

RW_m_stmsram運作域,所有變量及堆棧(RW Data + ZI Data)都存放在這個運作域。​

以上分散加載檔案,由正點原子編寫,為了友善大家使用,不用頻繁修改.sct檔案,特意将.ANY ROM區域放在外部SPI FLASH,這樣大家在新增.c參與編譯時,預設就是存放在外部SPI FLASH的,這樣使用起來就更友善。​

注意事項:​

1、如果你新增的代碼,對速度有要求,可以将其對應的.o添加到内部FLASH,即放在:ER_m_stmflash運作域。​