STM32MP157 Linux系統(tǒng)移植開發(fā)篇9:Linux內(nèi)核eMMC驅(qū)動(dòng)移植
本文章為《STM32MP157 Linux系統(tǒng)移植開發(fā)篇》系列中的一篇,筆者使用的開發(fā)平臺(tái)為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。stm32mp157是ARM雙核,2個(gè)A7核,1個(gè)M4核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實(shí)時(shí)操作系統(tǒng),STM32MP157開發(fā)板所以既可以學(xué)嵌入式linux,也可以學(xué)stm32單片機(jī)。
針對FS-MP1A開發(fā)板,除了Linux系統(tǒng)移植篇外,還包括其他多系列教程,包括Cortex-A7開發(fā)篇、Cortex-M4開發(fā)篇、擴(kuò)展板驅(qū)動(dòng)移植篇、Linux應(yīng)用開發(fā)篇、FreeRTOS系統(tǒng)移植篇、Linux驅(qū)動(dòng)開發(fā)篇、硬件設(shè)計(jì)篇、人工智能機(jī)器視覺篇、Qt應(yīng)用編程篇、Qt綜合項(xiàng)目實(shí)戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群459754978,感謝關(guān)注。
關(guān)于FS-MP1A開發(fā)板:
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?
鏈接:https://item.taobao.com/item.htm?id=622457259672
1.實(shí)驗(yàn)原理
參考原理圖可知eMMC使用的是sdmmc2總線,當(dāng)前所使用的設(shè)備樹文件中沒有sdmmc2的支持,所以需要增加相關(guān)內(nèi)容才能正常驅(qū)動(dòng)eMMC。

由于在使STM32MP1芯片很多管腳為多功能復(fù)用管腳,且很多管腳具備同樣的功能,所以移植eMMC時(shí)需要確認(rèn)硬件設(shè)計(jì)是使用的是那些管腳,根據(jù)原理圖確認(rèn)后管腳對應(yīng)關(guān)系為:
原理圖網(wǎng)絡(luò)編號對應(yīng)管腳管腳功能管腳功能碼SD2_DATA0PB14SDMMC2_D0AF9SD2_DATA1PB15SDMMC2_D1AF9SD2_DATA2PB3SDMMC2_D2AF9SD2_DATA3PB4SDMMC2_D3AF9SD2_DATA4PA8SDMMC2_D4AF9SD2_DATA5PA9SDMMC2_D5AF10SD2_DATA6PE5SDMMC2_D6AF9SD2_DATA7PD3SDMMC2_D7AF9SD2_CLKPE3SDMMC2_CKAF9SD2_CMDPG6SDMMC2_CMDAF10
eMMC設(shè)備樹節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/mmc/mmc-controller.yaml
Documentation/devicetree/bindings/mmc/mmci.txt
內(nèi)核中ST對STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp151.dtsi
stm32mp151中sdmmc2定義如下:
sdmmc2: sdmmc@58007000 {
compatible = "arm,pl18x", "arm,primecell";
arm,primecell-periphid = <0x00253180>;
reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC2_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
max-frequency = <120000000>;
status = "disabled";
};
上述代碼只對sdmmc2做了基本的初始化,并沒有針對不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。
eMMC有8根數(shù)據(jù)線,且eMMC無需熱插拔等功能,結(jié)合硬件信息添加sdmmc2節(jié)點(diǎn)信息,也可參考內(nèi)核中其他設(shè)備樹文件中相關(guān)描述,比如stm32mp15xx-edx.dtsi關(guān)于sdmmc2的描述符合我們的要求,內(nèi)容如下:
&sdmmc2 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>;
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>;
non-removable;
no-sd;
no-sdio;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&vdd>;
mmc-ddr-3_3v;
status = "okay";
};
管腳定義
在內(nèi)核中STM32MP1默認(rèn)管腳定義在文件arch/arm/dts/stm32mp15-pinctrl.dtsi中,查看文件中是否有需要的管腳定義:
查看后確認(rèn)有sdmmc2的管腳定義,且與FS-MP1A硬件使用情況一致,定義如下:
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
};
sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
pins3 {
pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-open-drain;
bias-pull-up;
};
};
sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
};
};
sdmmc2_b4_pins_b: sdmmc2-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-push-pull;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-disable;
};
};
sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
slew-rate = <1>;
drive-push-pull;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-disable;
};
pins3 {
pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-open-drain;
bias-disable;
};
};
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
};
};
2.實(shí)驗(yàn)?zāi)康?/h1>
熟悉基于Linux操作系統(tǒng)下的塊設(shè)備驅(qū)動(dòng)移植配置過程。
3.實(shí)驗(yàn)平臺(tái)
華清遠(yuǎn)見開發(fā)環(huán)境,F(xiàn)S-MP1A平臺(tái);
4.實(shí)驗(yàn)步驟
1.導(dǎo)入交叉編譯工具鏈
linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
2.添加eMMC設(shè)備樹配置
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件
在原有sdmmc1節(jié)點(diǎn)下添加如下內(nèi)容:
&sdmmc2 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>;
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>;
non-removable;
no-sd;
no-sdio;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&vdd>;
mmc-ddr-3_3v;
status = "okay";
};
3.配置內(nèi)核
由于內(nèi)核源碼默認(rèn)配置已經(jīng)支持eMMC,本節(jié)列出主要選項(xiàng),如下
linux@ubuntu:$ make menuconfig
Device Drivers --->
<*> MMC/SD/SDIO card support --->
[*] STMicroelectronics STM32 SDMMC Controller
4.編譯內(nèi)核級設(shè)備樹:
linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
5.重啟測試
將編譯好的設(shè)備樹和內(nèi)核鏡像拷貝到/tftpboot目錄下,通過tftp引導(dǎo)內(nèi)核,重啟設(shè)備后可以看到如下啟動(dòng)信息:

由于eMMC中有出廠預(yù)
裝的FS-MP1A系統(tǒng),所以可以正常完成文件系統(tǒng)掛載進(jìn)入系統(tǒng):

硬件平臺(tái):華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)
部分開發(fā)教程下載:加QQ群459754978,群文件里有。
部分視頻課程收看:華清遠(yuǎn)見研發(fā)中心的個(gè)人空間_嗶哩嗶哩_Bilibili
淘寶購買鏈接:華清遠(yuǎn)見stm32mp157 linux開發(fā)板stm32單片機(jī)arm開發(fā)嵌入式學(xué)習(xí)板