STM32MP157 Linux系統(tǒng)移植開發(fā)篇17:Linux內(nèi)核攝像頭驅(qū)動移植
本文章為《STM32MP157 Linux系統(tǒng)移植開發(fā)篇》系列中的一篇,筆者使用的開發(fā)平臺為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。stm32mp157是ARM雙核,2個A7核,1個M4核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實時操作系統(tǒng),STM32MP157開發(fā)板所以既可以學(xué)嵌入式linux,也可以學(xué)stm32單片機。
針對FS-MP1A開發(fā)板,除了Linux系統(tǒng)移植篇外,還包括其他多系列教程,包括Cortex-A7開發(fā)篇、Cortex-M4開發(fā)篇、擴展板驅(qū)動移植篇、Linux應(yīng)用開發(fā)篇、FreeRTOS系統(tǒng)移植篇、Linux驅(qū)動開發(fā)篇、硬件設(shè)計篇、人工智能機器視覺篇、Qt應(yīng)用編程篇、Qt綜合項目實戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群459754978,感謝關(guān)注。
關(guān)于FS-MP1A開發(fā)板:
手機淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?
鏈接:https://item.taobao.com/item.htm?id=622457259672
1.實驗原理
DCMI(Digital Camera Interface),DCMI是一個同步并行接口,能夠從外部8bit、10bit、12bit或14bit的CMOS攝像頭接收高速數(shù)據(jù)流,支持不同的數(shù)據(jù)格式:YCbCr4:2:2/RGB565漸進(jìn)式視頻和壓縮數(shù)據(jù)(JPEG)。

FS-MP1A可以外接8bit的COM Camera,接口定義如下:

接口與MPU管腳對應(yīng)關(guān)系如下:





原理圖網(wǎng)絡(luò)編號對應(yīng)管腳管腳功能管腳功能碼DCMI_D0PH9DCMI_D0AF13DCMI_D1PH10DCMI_D0AF13DCMI_D2PH11DCMI_D0AF13DCMI_D3PH12DCMI_D0AF13DCMI_D4PH14DCMI_D0AF13DCMI_D5PI4DCMI_D0AF13DCMI_D6PB8DCMI_D0AF13DCMI_D7PE6DCMI_D0AF13DCMI_RESETPA3GPIOANALOGDCMI_PWDNPA4GPIOANALOGDCMI_PIXCKPA6DCMI_PIXCLKAF13DCMI_VSYNCPB7DCMI_VSYNCAF13
DCMI設(shè)備樹節(jié)點
參考文檔:
Documentation/devicetree/bindings/media/st,stm32-dcmi.txt
Documentation/devicetree/bindings/media/video-interfaces.txt
內(nèi)核中ST對STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp151.dtsi
stm32mp151中dcmi定義如下:
dcmi: dcmi@4c006000 {
compatible = "st,stm32-dcmi";
reg = <0x4c006000 0x400>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
resets = <&rcc CAMITF_R>;
clocks = <&rcc DCMI>;
clock-names = "mclk";
dmas = <&dmamux1 75 0x400 0xe0000001>;
dma-names = "tx";
status = "disabled";
};
上述代碼只對dcmi做了基本的初始化,并沒有針對不同的硬件設(shè)計做適配,所以需結(jié)合硬件補全設(shè)備樹節(jié)點信息。
參考幫助文檔及內(nèi)核中其它STM32MP157設(shè)備樹中對于dcmi的定義,修改dcmi內(nèi)容如下:
&dcmi {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&dcmi_pins_a>;
pinctrl-1 = <&dcmi_sleep_pins_a>;
port {
dcmi_0: endpoint {
remote-endpoint = <&ov5640_0>;
bus-width = <8>;
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <1>;
pclk-max-frequency = <77000000>;
};
};
};
由于stm32mp15-pinctrl.dtsi中對于DCMI管腳的定義與FS-MP1A實際使用管腳一致,所以無需修改
CMOS Camera設(shè)備樹節(jié)點
FS-MP1A支持多款COMS Camera,本節(jié)以ov5640為例:
參考文檔:
Documentation/devicetree/bindings/media/i2c/ov5640.txt
參考幫助文檔及內(nèi)核中其它STM32MP157設(shè)備樹中對于ov5640的定義,修改dcmi內(nèi)容如下:
ov5640: camera@3c {
compatible = "ovti,ov5640";
reg = <0x3c>;
clocks = <&clk_ext_camera>;
clock-names = "xclk";
DOVDD-supply = <&v2v8>;
powerdown-gpios = <&gpioa 4 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
reset-gpios = <&gpioa 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
rotation = <180>;
status = "okay";
port {
ov5640_0: endpoint {
remote-endpoint = <&dcmi_0>;
bus-width = <8>;
data-shift = <2>; /* lines 9:2 are used */
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <1>;
pclk-max-frequency = <77000000>;
};
};
};
2.8V電源定義
前文已經(jīng)說過如何添加電源節(jié)點,本節(jié)不再重復(fù),在根節(jié)點添加&v2v8節(jié)點,內(nèi)容如下:
v2v8_audio: regulator-v2v8 {
compatible = "regulator-fixed";
regulator-name = "v2v8";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
regulator-boot-on;
};
24M時鐘定義
參考文檔:
Documentation/devicetree/bindings/clock/fixed-clock.yaml
參考幫助文檔或內(nèi)核中其他設(shè)備樹文件,對于時鐘的定義,增加內(nèi)容如下:
clocks {
clk_ext_camera: clk-ext-camera {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
};
2.實驗?zāi)康?/h1>
熟悉基于Linux操作系統(tǒng)下的攝像頭設(shè)備驅(qū)動移植配置過程。
3.實驗平臺
華清遠(yuǎn)見開發(fā)環(huán)境,F(xiàn)S-MP1A平臺;
4.實驗步驟
導(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
增加DCMI設(shè)備樹節(jié)點
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下內(nèi)容:
&dcmi {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&dcmi_pins_a>;
pinctrl-1 = <&dcmi_sleep_pins_a>;
port {
dcmi_0: endpoint {
remote-endpoint = <&ov5640_0>;
bus-width = <8>;
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <1>;
pclk-max-frequency = <77000000>;
};
};
};
增加OV5640節(jié)點
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件,在I2C5節(jié)點中添加OV5640設(shè)備信息,紅色字體為增加內(nèi)容:
&i2c5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_pins_a>;
……
ov5640: camera@3c {
compatible = "ovti,ov5640";
reg = <0x3c>;
clocks = <&clk_ext_camera>;
clock-names = "xclk";
DOVDD-supply = <&v2v8>;
powerdown-gpios = <&gpioa 4 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
reset-gpios = <&gpioa 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
rotation = <180>;
status = "okay";
port {
ov5640_0: endpoint {
remote-endpoint = <&dcmi_0>;
bus-width = <8>;
data-shift = <2>; /* lines 9:2 are used */
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <1>;
pclk-max-frequency = <77000000>;
};
};
};
};
增加2.8V電源和24M時鐘
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件,在根節(jié)點最后添加2.8V電源和24M時鐘,紅色字體為增加內(nèi)容:
/ {
memory@c0000000 {
device_type = "memory";
reg = <0xc0000000 0x20000000>;
};
……
v2v8: regulator-2p8v {
compatible = "regulator-fixed";
regulator-name = "v2v8";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
regulator-boot-on;
};
clocks {
clk_ext_camera: clk-ext-camera {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
};
};
配置內(nèi)核
配置內(nèi)核支持ov5640,并列出主要選項,如下
linux@ubuntu:$ make menuconfig
Device Drivers --->
<*> Multimedia support --->
[*] V4L platform devices --->
<*> STM32 Digital Camera Memory Interface (DCMI) support
I2C Encoders, decoders, sensors and other helper chips --->
<*> OmniVision OV5640 sensor support
編譯內(nèi)核及設(shè)備樹
linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
重啟測試
將編譯好的設(shè)備樹和內(nèi)核鏡像拷貝到/tftpboot目錄下,通過tftp引導(dǎo)內(nèi)核,系統(tǒng)啟動后啟動信息中包含如下信息:

在屏幕的界面上選擇“Camera preview”應(yīng)用進(jìn)入攝像頭預(yù)覽程序,啟動界面后即可看到攝像頭實時采集的圖像。

硬件平臺:華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)
部分開發(fā)教程下載:加QQ群459754978,群文件里有。
淘寶購買鏈接:華清遠(yuǎn)見stm32mp157 linux開發(fā)板stm32單片機arm開發(fā)嵌入式學(xué)習(xí)板
手機淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?