### 一、文件、目錄許可權和所有者 簡介:用戶對一個文件或目錄具有訪問許可權,這些訪問許可權決定了誰能訪問,以及如何範圍這些文件和目錄。通過設置許可權可以限制或允許以下三種用戶訪問: - 文件的用戶所有者(屬主) - 文件的組群所有者(用戶所在組的同組用戶) - 系統中的其他用戶 在linux系統中,每一 ...
使用Free Pascal開發STM32程式
前言
大部分人都知道嵌入式開發,一般用的都是C語言,但是實際上,除C語言之外還有許多語言都可以開發,本文將介紹使用Free Pascal(簡稱FPC)開發STM32程式的方法。
你可以進Free Pascal的官網看看,其第一段話就是說這個編譯器支持多少處理器多少操作系統的,事實上其支持絕大多數你知道的和不知道的處理器和系統(甚至開發版本還支持龍芯架構的Linux平臺),當然本文的主題肯定不是教你怎麼用這個編譯器給各種各樣的平臺和架構開發程式,而是講述如何使用構建其有關STM32的開發環境。
STM32系列是ST公司推出的微控制器(MCU)產品,有諸多的型號,但是所有MCU的內核都是基於Arm公司的Cortex-M處理器內核。對應到Free Pascal來說,其編譯目標處理器架構(Target CPU)是Arm,而目標操作系統(Target OS)是Embedded(嵌入式,可以理解為裸機系統)。當然由於各種Cortex-M內核,所以還要區分目標處理器(Target Processor)內核,比如ARMV7M、ARMV7EM等。
目錄
目錄開發環境搭建
由於Free Pascal官網並不提供arm-embedded目標的編譯器,所以我們需要使用一款叫fpcupdeluxe的軟體來安裝,同時,我們一般使用Lazarus IDE作為開發環境,可以在官網下載,或者通過fpcupdeluxe安裝,也可以自己構建。
個人建議:對於新手或者不想麻煩的,使用fpcupdeluxe安裝所有環境就行了;對於已經安裝了Lazarus的,可以只安裝編譯器。
我自己是用fpcupdeluxe安裝了穩定版編譯器和開發版編譯器,同時使用git拉取代碼構建了穩定版和開發版的Lazarus。
如果你是使用FPC的老手,估計已經安裝了Lazarus用來開發,可以跳過部分內容,如果你熟悉fpcupdeluxe這款軟體,也可以部分內容。
註意:由於眾所周知的原因,請在安裝前確保網路通暢,可以正常訪問github.com和gitlab.com這兩個網站
其中gitlab主要是安裝FPC和Lazarus的時候用到,而github主要是安裝交叉編譯器的時候用到。
本文會給出一些常見的問題及解決方法,主要是我自己遇到的。
下載使用fpcupdeluxe
fpcupdeluxe的GitHub鏈接是https://github.com/LongDirtyAnimAlf/fpcupdeluxe,在發佈頁面,可以看到許多不同的二進位文件,對於Windows系統,我們一般下載32位的(fpcupdeluxe-i386-win32.exe)比較好,當然64位的(fpcupdeluxe-x86_64-win64.exe)也是可以的,這裡要註意的是,下載的版本會影響預設生成的編譯器版本,當然可以改。對於Linux系統,基本上下64位的就行了,至於是qt5(fpcupdeluxe-x86_64-linux-qt5)、qt6(fpcupdeluxe-x86_64-linux-qt6)還是gtk(fpcupdeluxe-x86_64-linux)就自己看著選。
下載完成後放到一個單獨的文件夾,然後運行軟體。
註意第一步先改安裝的文件夾,這裡的建議是不要改安裝的版本(當然如果你要開發版本的話就改trunk),根據需求點Only FPC
或者Install/update FPC+Lazarus
然後等著吧,這裡會有很多問題,我後面會列出來的。
點擊左下角的Setup+
按鈕進入設置界面,這裡有很多細節可以說明。
如果你安裝Lazarus,建議按照圖裡的加上-O3 -Xs -g-
以及去掉Debug的勾,然後勾上左邊的兩個,否則不用改別的。最後點右下角的OK就行了。
常見安裝問題
下麵說一說安裝時候可能遇到的問題以及一些解決方法。
只要網可以搞定,大部分都不是問題(人家國外的開發者基本上不會考慮到網路問題的,畢竟他們很少懂我們的特色),咱們搞技術的,搞定這些應該都是基本能力。
界面卡死
這個基本出在第一次安裝的時候,因為需要下載一些bootstrap的文件,如果你經常這樣的話,建議按如下步驟來:
- 記住當前正在下載的文件,任務管理器關掉進程
- 找到你的安裝目錄,然後進入fpcbootstrap文件夾,刪掉大小0KB的文件
- 重新打開軟體,點擊安裝,接著卡死重覆之前步驟,或者打開設置掛代理
- 或者可以去GitHub給作者提issue,讓他想辦法加點其他鏈接
註意,用任務管理器關閉進程,這個軟體的代理設置是不會保存的,最好在修改完需要的設置後,關掉軟體再重新打開。
只要你能成功一次,以後需要在其他文件夾安裝這個,就可以把文件提前複製過去了,這些文件基本上可以用幾年。
如果你還知道其他解決辦法,歡迎補充。
git clone很久不動
基本上超過半小時一直卡git clone,可以確定是你的網訪問gitlab有問題了,建議方法是掛代理,不過要在git裡面設置。
HTTP使用:
git config --global http.proxy 127.0.0.1:7890
HTTPS使用:
git config --global https.proxy 127.0.0.1:7890
要取消代理設置,使用:
git config --global --unset http.proxy
git config --global --unset https.proxy
這些設置應該會保存到 C:\Users\用戶名\.gitconfig
提示編譯失敗
這個只有在你選擇安裝trunk的時候有可能出現,因為開發人員有時候或提交無法編譯的代碼,這很正常,建議等一段時間再安裝/更新,或者你可以去gitlab倉庫(鏈接軟體上就有)看代碼的提交記錄,看流水線的狀態就可以判斷能不能編譯了。
安裝交叉編譯器
如圖步驟所示,到底選armv7em還是armv7m,這個去st官網查你的晶元型號,一般F103的Cortex-M3要選armv7m,而F4系列的Cortex-M4要選armv7em,都有的話依次全都安裝了就行。
點擊Install compiler
之後,第一次安裝的話會彈出對話框提示沒有需要的文件,然後提示你可以下載,這個要選是,然後它會從GitHub下載所需的文件,所以要確保GitHub網路暢通。
下載使用OpenOCD
OpenOCD全稱(Open On-Chip Debugger),是一個用來在嵌入式設備調試的工具。
你可以在官方存儲庫的發佈頁面下載最新的Windows二進位文件,如果你需要Linux或者macOS的,則可以去這個頁面下載。註意,這兩個頁面都是GitHub的。
解壓到文件夾後,記得配置環境變數,然後在終端用命令openocd
就可以使用了,不過你還需要一個配置文件。
配置文件基本寫法如下:
source [find interface/xxx.cfg]
source [find target/xxx.cfg]
find後面的路徑可以在openocd文件夾下的share\scripts\
找到,自己翻一翻用的什麼調試器和晶元。
比如我用的配置文件是這樣的:
source [find interface/cmsis-dap.cfg]
source [find target/stm32f4x.cfg]
假如上述文件保存為stm32.cfg
,那麼需要
openocd -f stm32.cfg
就可以連接了。
也可以直接將其保存為openocd.cfg
,這樣就可以直接在終端執行openocd
而不用加-f
參數指定配置文件了。
啟動效果如圖:
記住埠3333,這個是給gdb調試用的,後面我們要用到。
配置Lazarus
啟動Lazarus,如果是第一次安裝,可能會彈出一個對話框,這個應該沒啥問題,特別簡單的配置後面就不說了,包括可能啟動的時候是英文怎麼改中文什麼的。
如果你已經安裝了Lazarus,但是通過fpcupdeluxe安裝了新的編譯器,那麼你需要在設置界面修改編譯器路徑。
點開菜單的工具,然後點選項,彈出的選項對話框預設應該會顯示環境-文件,如果不是就在左邊點一下就行了。
找到右邊的編譯器可執行文件選項,改成用fpcupdeluxe安裝的fpc編譯器位置,一般路徑是安裝路徑\fpc\bin\處理器-操作系統\fpc.exe
,同理下麵的FPC源代碼目錄就是安裝路徑\fpcsrc
,改完後點確定,然後回到主界面點菜單的工具,然後點重新掃碼FPC源代碼目錄,這樣之後再點菜單的文件-重啟就行了。
接下來再配置一下調試器,同樣打開工具-選項,然後找到左邊的調試器-調試器後端,預設應該是這樣的:
我們點這裡的添加,然後依次填名稱,選擇調試器類型,選擇調試器路徑,修改選項,具體如圖所示:
改完調試器以後,註意如果你要調試本機程式,記得點左上角的下拉框改回來。
示例
建立工程
在Lazarus菜單中選擇工程-新建工程,然後在彈出來的對話框選擇簡單程式,你應該會看到只有沒幾行代碼,然後按Ctrl+S保持到一個文件夾里。
接著點菜單的工程-工程選項,在彈出的對話框左邊選擇編譯器選項-配置和目標,找到右邊的目標平臺,有3個下拉框,改法如圖:
其中目標處理器看情況改,如果你的是F1系列就要改ARMV7M,而我用的F4就是ARMV7EM。
接著再看左邊,選擇調試,然後右邊按照如圖的改法:
註意,如果你用的是3.0之後的Lazarus,可能會多選項,註意,都保持預設不要動!我們就只改2個選項。
還有,如果你在編譯和鏈接那邊改了優化,會調試不了的,預設O1就行了。
然後再回到左邊選自定義選項,然後在右邊輸入-WpXXX
,註意大小寫,比如我的是-WpSTM32F407ZG
。
具體可以改什麼,可以在編譯器文件夾找到ppcrossarm.exe並執行ppcrossarm -i
,我也在這裡給出當前版本的所有目標:
LPC810M021FN8,LPC811M001FDH16,LPC812M101FDH16,LPC812M101FD20
LPC812M101FDH20,LPC1110FD20,LPC1111FDH20_002,LPC1111FHN33_101
LPC1111FHN33_102,LPC1111FHN33_103,LPC1111FHN33_201,LPC1111FHN33_202
LPC1111FHN33_203,LPC1112FD20_102,LPC1112FDH20_102,LPC1112FDH28_102
LPC1112FHN33_101,LPC1112FHN33_102,LPC1112FHN33_103,LPC1112FHN33_201
LPC1112FHN24_202,LPC1112FHN33_202,LPC1112FHN33_203,LPC1112FHI33_202
LPC1112FHI33_203,LPC1113FHN33_201,LPC1113FHN33_202,LPC1113FHN33_203
LPC1113FHN33_301,LPC1113FHN33_302,LPC1113FHN33_303,LPC1113FBD48_301
LPC1113FBD48_302,LPC1113FBD48_303,LPC1114FDH28_102,LPC1114FN28_102
LPC1114FHN33_201,LPC1114FHN33_202,LPC1114FHN33_203,LPC1114FHN33_301
LPC1114FHN33_302,LPC1114FHN33_303,LPC1114FHN33_333,LPC1114FHI33_302
LPC1114FHI33_303,LPC1114FBD48_301,LPC1114FBD48_302,LPC1114FBD48_303
LPC1114FBD48_323,LPC1114FBD48_333,LPC1115FBD48_303,LPC11C12FBD48_301
LPC11C14FBD48_301,LPC11C22FBD48_301,LPC11C24FBD48_301
LPC11D14FBD100_302,LPC1224FBD48_101,LPC1224FBD48_121,LPC1224FBD64_101
LPC1224FBD64_121,LPC1225FBD48_301,LPC1225FBD48_321,LPC1225FBD64_301
LPC1225FBD64_321,LPC1226FBD48_301,LPC1226FBD64_301,LPC1227FBD48_301
LPC1227FBD64_301,LPC12D27FBD100_301,LPC1311FHN33,LPC1311FHN33_01
LPC1313FHN33,LPC1313FHN33_01,LPC1313FBD48,LPC1313FBD48_01,LPC1315FHN33
LPC1315FBD48,LPC1316FHN33,LPC1316FBD48,LPC1317FHN33,LPC1317FBD48
LPC1317FBD64,LPC1342FHN33,LPC1342FBD48,LPC1343FHN33,LPC1343FBD48
LPC1345FHN33,LPC1345FBD48,LPC1346FHN33,LPC1346FBD48,LPC1347FHN33
LPC1347FBD48,LPC1347FBD64,LPC2114,LPC2124,LPC2194,LPC1754,LPC1756
LPC1758,LPC1764,LPC1766,LPC1768,AT91SAM7S256,AT91SAM7SE256,AT91SAM7X256
AT91SAM7XC256,STM32F030C6,STM32F030C8,STM32F030F4,STM32F030K6
STM32F030R8,STM32F050C4,STM32F050C6,STM32F050F4,STM32F050F6,STM32F050G4
STM32F050G6,STM32F050K4,STM32F050K6,STM32F051C4,STM32F051C6,STM32F051C8
STM32F051K4,STM32F051K6,STM32F051K8,STM32F051R4,STM32F051R6,STM32F051R8
STM32F091CC,STM32F091CB,STM32F091RC,STM32F091RB,STM32F091VC,STM32F091VB
STM32F100X4,STM32F100X6,STM32F100X8,STM32F100XB,STM32F100XC,STM32F100XD
STM32F100XE,STM32F101X4,STM32F101X6,STM32F101X8,STM32F101XB,STM32F101XC
STM32F101XD,STM32F101XE,STM32F101XF,STM32F101XG,STM32F102X4,STM32F102X6
STM32F102X8,STM32F102XB,STM32F103X4,STM32F103X6,STM32F103X8,STM32F103XB
STM32F103XC,STM32F103XD,STM32F103XE,STM32F103XF,STM32F103XG,STM32F107X8
STM32F107XB,STM32F107XC,STM32F105R8,STM32F105RB,STM32F105RC,STM32F105V8
STM32F105VB,STM32F105VC,STM32F107RB,STM32F107RC,STM32F107VB,STM32F107VC
STM32F401CB,STM32F401RB,STM32F401VB,STM32F401CC,STM32F401RC,STM32F401VC
DISCOVERYF401VC,STM32F401CD,STM32F401RD,STM32F401VD,STM32F401CE
STM32F401RE,NUCLEOF401RE,STM32F401VE,STM32F407VG,DISCOVERYF407VG
STM32F407IG,STM32F407ZG,STM32F407VE,STM32F407ZE,STM32F407IE,STM32F411CC
STM32F411RC,STM32F411VC,STM32F411CE,STM32F411RE,NUCLEOF411RE
STM32F411VE,DISCOVERYF411VE,STM32F429VG,STM32F429ZG,STM32F429IG
STM32F429VI,STM32F429ZI,DISCOVERYF429ZI,STM32F429II,STM32F429VE
STM32F429ZE,STM32F429IE,STM32F429BG,STM32F429BI,STM32F429BE,STM32F429NG
STM32F429NI,STM32F429NE,STM32F446MC,STM32F446RC,STM32F446VC,STM32F446ZC
STM32F446ME,STM32F446RE,NUCLEOF446RE,STM32F446VE,STM32F446ZE
STM32F745XE,STM32F745XG,STM32F746XE,STM32F746XG,STM32F756XE,STM32F756XG
LM3S1110,LM3S1133,LM3S1138,LM3S1150,LM3S1162,LM3S1165,LM3S1166,LM3S2110
LM3S2139,LM3S6100,LM3S6110,LM3S1601,LM3S1608,LM3S1620,LM3S1635,LM3S1636
LM3S1637,LM3S1651,LM3S2601,LM3S2608,LM3S2620,LM3S2637,LM3S2651,LM3S6610
LM3S6611,LM3S6618,LM3S6633,LM3S6637,LM3S8630,LM3S1911,LM3S1918,LM3S1937
LM3S1958,LM3S1960,LM3S1968,LM3S1969,LM3S2911,LM3S2918,LM3S2919,LM3S2939
LM3S2948,LM3S2950,LM3S2965,LM3S6911,LM3S6918,LM3S6938,LM3S6950,LM3S6952
LM3S6965,LM3S8930,LM3S8933,LM3S8938,LM3S8962,LM3S8970,LM3S8971,LM3S5951
LM3S5956,LM3S1B21,LM3S2B93,LM3S5B91,LM3S9B81,LM3S9B90,LM3S9B92,LM3S9B95
LM3S9B96,LM3S5D51,LM4F120H5,SC32442B,XMC4500X1024,XMC4500X768
XMC4502X768,XMC4504X512,ALLWINNER_A20,MK20DX128VFM5,MK20DX128VFT5
MK20DX128VLF5,MK20DX128VLH5,TEENSY30,MK20DX128VMP5,MK20DX32VFM5
MK20DX32VFT5,MK20DX32VLF5,MK20DX32VLH5,MK20DX32VMP5,MK20DX64VFM5
MK20DX64VFT5,MK20DX64VLF5,MK20DX64VLH5,MK20DX64VMP5,MK20DX128VLH7
MK20DX128VLK7,MK20DX128VLL7,MK20DX128VMC7,MK20DX256VLH7,MK20DX256VLK7
MK20DX256VLL7,MK20DX256VMC7,TEENSY31,TEENSY32,MK20DX64VLH7,MK20DX64VLK7
MK20DX64VMC7,MK22FN512CAP12,MK22FN512CBP12,MK22FN512VDC12
MK22FN512VLH12,MK22FN512VLL12,MK22FN512VMP12,FREEDOM_K22F
MK64FN1M0VDC12,MK64FN1M0VLL12,FREEDOM_K64F,MK64FN1M0VLQ12
MK64FN1M0VMD12,MK64FX512VDC12,MK64FX512VLL12,MK64FX512VLQ12
MK64FX512VMD12,ATSAM3X8E,ARDUINO_DUE,FLIP_N_CLICK,NRF51422_XXAA
NRF51422_XXAB,NRF51422_XXAC,NRF51822_XXAA,NRF51822_XXAB,NRF51822_XXAC
NRF52832_XXAA,NRF52840_XXAA,THUMB2_BARE
可以看到支持大量的平臺,而不只是STM32!
編寫運行
寫一個經典的blink程式,來測試一下能不能正常使用。
這裡我用的是某原子的F407的板子,兩個LED接的的GPIOF的Pin9和Pin10,根據F4系列的文檔看了寄存器的定義,於是寫了這些代碼:
program stm32_blink;
procedure Delay(cnt:UInt32); // 延遲指定的迴圈次數
begin
while cnt>0 do
begin
Dec(cnt);
asm
nop // 這個nop很關鍵,不然開不開優化速度會差很多
end;
end;
end;
var
// 這裡用到了位打包數組,這種數組可以簡化位操作,對於GPIO這種寄存器內部都是連續單元的很有用
gpf_moder:bitpacked array[0..15] of 0..3 absolute GPIOF.MODER;
//gpf_otyper:bitpacked array[0..15] of 0..1 absolute GPIOF.OTYPER; // 用不著
//gpf_ospeedr:bitpacked array[0..15] of 0..3 absolute GPIOF.OSPEEDR; // 用不著
gpf_pupdr:bitpacked array[0..15] of 0..3 absolute GPIOF.PUPDR;
gpf_odr:bitpacked array[0..15] of 0..1 absolute GPIOF.ODR;
begin
// 這裡沒有修改RCC,用的預設的HSI時鐘
// 置位,表示使能GPIOF
RCC.AHB1ENR:=RCC.AHB1ENR or %100000;
// GPIOF Pin 9
gpf_moder[9]:=1; // 設置輸出模式
//gpf_ospeedr[9]:=0; // 不改預設就是0,表示低速,我們沒必要改
//gpf_otyper[9]:=0; // 不改預設就是0,表示推輓,也沒必要改
gpf_pupdr[9]:=1; // 上拉
gpf_odr[9]:=1; // 關燈
// GPIOF Pin 10
gpf_moder[10]:=1;
//gpf_ospeedr[10]:=0;
//gpf_otyper[10]:=0;
gpf_pupdr[10]:=1;
gpf_odr[10]:=1;
// 主迴圈
while True do
begin
gpf_odr[10]:=0; // 開燈10
Delay(1000000); // 延遲,具體多少看情況
gpf_odr[9]:=0; // 開燈9
gpf_odr[10]:=1; // 關燈10
Delay(500000); // 延遲
gpf_odr[9]:=1; // 關燈9,此時全部關燈
Delay(500000); // 延遲
end;
end.
代碼部分基本的都有註釋,有關語言機制以及其他什麼的不在本文的範圍,不能說和C比哪個好,但是編譯速度那是真的快。
然後你就可以按照正常調試,下斷點什麼的,接著按F9一鍵運行了,註意按了以後可能要等幾秒鐘。
結束調試就按Ctrl+F2,或者左邊的面板上應該也有按鈕可以點,註意單步是F8和F7不是F10和F11,你還可以按Ctrl+Alt+D查看彙編情況。
這個時候看一下OpenOCD的那個控制台視窗,可以看到有關調試的信息列印出來哦。
結語
用Free Pascal開發STM32是完全可行的,而且開發調試非常方便,只不過沒有庫寫起代碼來比較麻煩,需要對寄存器進行直接的操作,當然也可以自己封裝一個庫來用。可能還是受限於語言的流行度,這方面資料非常稀少,就連官方Wiki也沒有很詳細的內容,我也希望有更多的人能瞭解到Free Pascal,瞭解Pascal語言及編譯器的最新發展。
如果以後有機會,可以多講一講有關這方面的東西。