AIO-3399JD4 開發(fā)板上的 AD 接口有兩種,分別為:溫度傳感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。其中:
-
TS-ADC(Temperature Sensor):支持兩通道,時(shí)鐘頻率必須低于800KHZ
-
SAR-ADC(Successive Approximation Register):支持六通道單端10位的SAR-ADC,時(shí)鐘頻率必須小于13MHZ。
內(nèi)核采用工業(yè) I/O 子系統(tǒng)來控制 ADC,該子系統(tǒng)主要為 AD 轉(zhuǎn)換或者 DA 轉(zhuǎn)換的傳感器設(shè)計(jì)。
下面以SAR-ADC使用ADC風(fēng)扇為例子,介紹 ADC 的基本配置方法。
配置DTS節(jié)點(diǎn)
AIO-3399JD4 SAR-ADC 的 DTS 節(jié)點(diǎn)在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 文件中定義,如下所示:
用戶首先需在DTS文件中添加ADC的資源描述:
這里申請(qǐng)的是SARADC通道3,在 AIO-3399JD4 中是不提供給客戶外部使用的,而且也沒有風(fēng)扇接口,這里只是提供一個(gè)參考, 客戶可自行參考這個(gè)例子 運(yùn)用SARADC通道0 去做自己的一些開發(fā)。
在驅(qū)動(dòng)文件中匹配 DTS 節(jié)點(diǎn)
用戶驅(qū)動(dòng)可參考Firefly adc demo :kernel/drivers/adc/adc-firefly-demo.c,這是一個(gè)偵測(cè)Firefly-rk3399風(fēng)扇狀態(tài)的驅(qū)動(dòng)。 首先在驅(qū)動(dòng)文件中定義 of_device_id 結(jié)構(gòu)體數(shù)組:
然后將該結(jié)構(gòu)體數(shù)組填充到要使用 ADC 的 platform_driver 中:
接著在firefly_adc_probe中對(duì)DTS所添加的資源進(jìn)行解析:
獲取 AD 通道
注:iio_channel_get 通過 probe 函數(shù)傳進(jìn)來的參數(shù) pdev 獲取 IIO 通道結(jié)構(gòu)體,probe 函數(shù)如下:
讀取 AD 采集到的原始數(shù)據(jù)
調(diào)用 iio_read_channel_raw 函數(shù)讀取 AD 采集的原始數(shù)據(jù)并存入 val 中。
使用標(biāo)準(zhǔn)電壓將 AD 轉(zhuǎn)換的值轉(zhuǎn)換為用戶所需要的電壓值。其計(jì)算公式如下:
注:
-
Vref 為標(biāo)準(zhǔn)電壓
-
n 為 AD 轉(zhuǎn)換的位數(shù)
-
Vresult 為用戶所需要的采集電壓
-
raw 為 AD 采集的原始數(shù)據(jù)
例如,標(biāo)準(zhǔn)電壓為 1.8V,AD 采集位數(shù)為 10 位,AD 采集到的原始數(shù)據(jù)為 568,則:
-
功能:獲取 iio 通道描述
-
參數(shù):
-
dev: 使用該通道的設(shè)備描述指針
-
consumer_channel: 該設(shè)備所使用的 IIO 通道描述指針
-
-
功能:釋放 iio_channel_get 函數(shù)獲取到的通道
-
參數(shù):
-
chan:要被釋放的通道描述指針
-
-
功能:讀取 chan 通道 AD 采集的原始數(shù)據(jù)。
-
參數(shù):
-
chan:要讀取的采集通道指針
-
val:存放讀取結(jié)果的指針
-
Demo程序使用
在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi中使能adc_demo,將”disabled” 改為 “okay”:
編譯內(nèi)核,燒錄內(nèi)核到Firefly-RK3399 開發(fā)板上,然后插拔風(fēng)扇時(shí),會(huì)打印內(nèi)核log信息如下:
獲取所有ADC值
有個(gè)便捷的方法可以查詢到每個(gè)SARADC的值:
為何按上面的步驟申請(qǐng)SARADC,會(huì)出現(xiàn)申請(qǐng)報(bào)錯(cuò)的情況?
驅(qū)動(dòng)需要獲取ADC通道來使用時(shí),需要對(duì)驅(qū)動(dòng)的加載時(shí)間進(jìn)行控制,必須要在saradc初始化之后。saradc是使用module_platform_driver()進(jìn)行平臺(tái)設(shè)備驅(qū)動(dòng)注冊(cè),最終調(diào)用的是module_init()。所以用戶的驅(qū)動(dòng)加載函數(shù)只需使用比module_init()優(yōu)先級(jí)低的,例如:late_initcall(),就能保證驅(qū)動(dòng)的加載的時(shí)間比saradc初始化時(shí)間晚,可避免出錯(cuò)。
GPIO, 全稱 General-Purpose Input/Output(通用輸入輸出),是一種軟件運(yùn)行期間能夠動(dòng)態(tài)配置和控制的通用引腳。 RK3399有5組GPIO bank:GPIO0~GPIO4,每組又以 A0~A7, B0~B7, C0~C7, D0~D7 作為編號(hào)區(qū)分(不是所有 bank 都有全部編號(hào),例如 GPIO4 就只有 C0~C7, D0~D2)。 所有的GPIO在上電后的初始狀態(tài)都是輸入模式,可以通過軟件設(shè)為上拉或下拉,也可以設(shè)置為中斷腳,驅(qū)動(dòng)強(qiáng)度都是可編程的。 每個(gè) GPIO 口除了通用輸入輸出功能外,還可能有其它復(fù)用功能,例如 GPIO2_A2,可以利用成以下功能:
-
GPIO2_A2
-
CIF_D2
每個(gè) GPIO 口的驅(qū)動(dòng)電流、上下拉和重置后的初始狀態(tài)都不盡相同,詳細(xì)情況請(qǐng)參考《RK3399 規(guī)格書》中的 “Chapter 10 GPIO” 一章。 RK3399 的 GPIO 驅(qū)動(dòng)是在以下 pinctrl 文件中實(shí)現(xiàn)的:
其核心是填充 GPIO bank 的方法和參數(shù),并調(diào)用 gpiochip_add 注冊(cè)到內(nèi)核中。
本文以TP_RST(GPIO0_B4)和LCD_RST(GPIO4_D5)這兩個(gè)通用GPIO口為例寫了一份簡(jiǎn)單操作GPIO口的驅(qū)動(dòng),在SDK的路徑為:
以下就以該驅(qū)動(dòng)為例介紹GPIO的操作。
首先在DTS文件中增加驅(qū)動(dòng)的資源描述:
這里定義了一個(gè)腳作為一般的輸出輸入口:
AIO-3399JD4 的dts對(duì)引腳的描述與Firefly-RK3288有所區(qū)別,GPIO0_B4被描述為:<&gpio0 12 GPIO_ACTIVE_HIGH>,這里的12來源于:8+4=12,其中8是因?yàn)镚PIO0_B4是屬于GPIO0的B組,如果是A組的話則為0,如果是C組則為16,如果是D組則為24,以此遞推,而4是因?yàn)锽4后面的4。 GPIO_ACTIVE_HIGH表示高電平有效,如果想要低電平有效,可以改為:GPIO_ACTIVE_LOW,這個(gè)屬性將被驅(qū)動(dòng)所讀取。
然后在probe函數(shù)中對(duì)DTS所添加的資源進(jìn)行解析,代碼如下:
of_get_named_gpio_flags 從設(shè)備樹中讀取 firefly-gpio 和 firefly-irq-gpio 的 GPIO 配置編號(hào)和標(biāo)志,gpio_is_valid 判斷該 GPIO 編號(hào)是否有效,gpio_request 則申請(qǐng)占用該 GPIO。如果初始化過程出錯(cuò),需要調(diào)用 gpio_free 來釋放之前申請(qǐng)過且成功的 GPIO 。 在驅(qū)動(dòng)中調(diào)用 gpio_direction_output 就可以設(shè)置輸出高還是低電平,這里默認(rèn)輸出從DTS獲取得到的有效電平GPIO_ACTIVE_HIGH,即為高電平,如果驅(qū)動(dòng)正常工作,可以用萬用表測(cè)得對(duì)應(yīng)的引腳應(yīng)該為高電平。 實(shí)際中如果要讀出 GPIO,需要先設(shè)置成輸入模式,然后再讀取值:
下面是常用的 GPIO API 定義:
在Firefly的例子程序中還包含了一個(gè)中斷引腳,GPIO口的中斷使用與GPIO的輸入輸出類似,首先在DTS文件中增加驅(qū)動(dòng)的資源描述:
IRQ_TYPE_EDGE_RISING表示中斷由上升沿觸發(fā),當(dāng)該引腳接收到上升沿信號(hào)時(shí)可以觸發(fā)中斷函數(shù)。 這里還可以配置成如下:
然后在probe函數(shù)中對(duì)DTS所添加的資源進(jìn)行解析,再做中斷的注冊(cè)申請(qǐng),代碼如下:
調(diào)用gpio_to_irq把GPIO的PIN值轉(zhuǎn)換為相應(yīng)的IRQ值,調(diào)用gpio_request申請(qǐng)占用該IO口,調(diào)用request_irq申請(qǐng)中斷,如果失敗要調(diào)用free_irq釋放,該函數(shù)中g(shù)pio_info-firefly_irq是要申請(qǐng)的硬件中斷號(hào),firefly_gpio_irq是中斷函數(shù),gpio_info->firefly_irq_mode是中斷處理的屬性,”firefly-gpio”是設(shè)備驅(qū)動(dòng)程序名稱,gpio_info是該設(shè)備的device結(jié)構(gòu),在注冊(cè)共享中斷時(shí)會(huì)用到。
如何定義 GPIO 有哪些功能可以復(fù)用,在運(yùn)行時(shí)又如何切換功能呢?以 I2C4 為例作簡(jiǎn)單的介紹。
查規(guī)格表可知,I2C4_SDA 與 I2C4_SCL 的功能定義如下:
在 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi 里有:
此處,跟復(fù)用控制相關(guān)的是 pinctrl- 開頭的屬性:
-
pinctrl-names 定義了狀態(tài)名稱列表: default (i2c 功能) 和 gpio 兩種狀態(tài)。
-
pinctrl-0 定義了狀態(tài) 0 (即 default)時(shí)需要設(shè)置的 pinctrl: &i2c4_xfer
-
pinctrl-1 定義了狀態(tài) 1 (即 gpio)時(shí)需要設(shè)置的 pinctrl: &i2c4_gpio
這些 pinctrl 在kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi中這樣定義:
RK_FUNC_1,RK_FUNC_GPIO 的定義在 kernel/include/dt-bindings/pinctrl/rk.h 中:
另外,像”1 11”,”1 12”這樣的值是有編碼規(guī)則的,編碼方式與上一小節(jié)”輸入輸出”描述的一樣,”1 11”代表GPIO1_B3,”1 12”代表GPIO1_B4。
在復(fù)用時(shí),如果選擇了 “default” (即 i2c 功能),系統(tǒng)會(huì)應(yīng)用 i2c4_xfer 這個(gè) pinctrl,最終將 GPIO1_B3 和 GPIO1_B4 兩個(gè)針腳切換成對(duì)應(yīng)的 i2c 功能;而如果選擇了 “gpio” ,系統(tǒng)會(huì)應(yīng)用 i2c4_gpio 這個(gè) pinctrl,將 GPIO1_B3 和 GPIO1_B4 兩個(gè)針腳還原為 GPIO 功能。
我們看看 i2c 的驅(qū)動(dòng)程序 kernel/drivers/i2c/busses/i2c-rockchip.c 是如何切換復(fù)用功能的:
首先是調(diào)用 of_get_gpio 取出設(shè)備樹中 i2c4 結(jié)點(diǎn)的 gpios 屬于所定義的兩個(gè) gpio:
然后是調(diào)用 devm_gpio_request 來申請(qǐng) gpio,接著是調(diào)用 pinctrl_lookup_state 來查找 “gpio” 狀態(tài),而默認(rèn)狀態(tài) “default” 已經(jīng)由框架保存到 i2c->dev-pins->default_state 中了。
最后調(diào)用 pinctrl_select_state 來選擇是 “default” 還是 “gpio” 功能。
下面是常用的復(fù)用 API 定義:
在復(fù)雜的片上系統(tǒng)(SOC)中,設(shè)計(jì)者一般會(huì)將系統(tǒng)的供電分為多個(gè)獨(dú)立的block,這稱作電源域(Power Domain),這樣做有很多好處,例如:
-
在IO-Domain的DTS節(jié)點(diǎn)統(tǒng)一配置電壓域,不需要每個(gè)驅(qū)動(dòng)都去配置一次,便于管理;
-
依照的是Upstream的做法,以后如果需要Upstream比較方便;
-
IO-Domain的驅(qū)動(dòng)支持運(yùn)行過程中動(dòng)態(tài)調(diào)整電壓域,例如PMIC的某個(gè)Regulator可以1.8v和3.3v的動(dòng)態(tài)切換,一旦Regulator電壓發(fā)生改變,會(huì)通知IO-Domain驅(qū)動(dòng)去重新設(shè)置電壓域。
AIO-3399C原理圖上的 Power Domain Map 表以及配置如下表所示:
通過RK3399 SDK的原理圖可以看到bt656-supply 的電壓域連接的是vcc18_dvp, vcc_io是從PMIC RK808的VLDO1出來的; 在DTS里面可以找到vcc1v8_dvp, 將bt656-supply = <&vcc18_dvp>。 其他路的配置也類似,需要注意的是如果這里是其他PMIC,所用的Regulator也不一樣,具體以實(shí)際電路情況為標(biāo)準(zhǔn)。
IO指令
GPIO調(diào)試有一個(gè)很好用的工具,那就是IO指令,AIO-3399C的Android系統(tǒng)默認(rèn)已經(jīng)內(nèi)置了IO指令,使用IO指令可以實(shí)時(shí)讀取或?qū)懭朊總€(gè)IO口的狀態(tài),這里簡(jiǎn)單介紹IO指令的使用。 首先查看 io 指令的幫助:
從幫助上可以看出,如果要讀或者寫一個(gè)寄存器,可以用:
使用示例:
-
查看GPIO1_B3引腳的復(fù)用情況
-
從主控的datasheet查到GPIO1對(duì)應(yīng)寄存器基地址為:0xff320000
-
從主控的datasheet查到GPIO1B_IOMUX的偏移量為:0x00014
-
GPIO1_B3的iomux寄存器地址為:基址(Operational Base) + 偏移量(offset)=0xff320000+0x00014=0xff320014
-
用以下指令查看GPIO1_B3的復(fù)用情況:
-
從datasheet查到[7:6]:
因此可以確定該GPIO被復(fù)用為 i2c4sensor_sda。
-
如果想復(fù)用為GPIO,可以使用以下指令設(shè)置:
GPIO調(diào)試接口
Debugfs文件系統(tǒng)目的是為開發(fā)人員提供更多內(nèi)核數(shù)據(jù),方便調(diào)試。 這里GPIO的調(diào)試也可以用Debugfs文件系統(tǒng),獲得更多的內(nèi)核信息。 GPIO在Debugfs文件系統(tǒng)中的接口為 /sys/kernel/debug/gpio,可以這樣讀取該接口的信息:
從讀取到的信息中可以知道,內(nèi)核把GPIO當(dāng)前的狀態(tài)都列出來了,以GPIO0組為例,gpio-2(GPIO0_A2)作為3G模塊的電源控制腳(vcc3v3_3g),輸出高電平(out hi)。
Q1: 如何將PIN的MUX值切換為一般的GPIO?
A1: 當(dāng)使用GPIO request時(shí)候,會(huì)將該P(yáng)IN的MUX值強(qiáng)制切換為GPIO,所以使用該pin腳為GPIO功能的時(shí)候確保該pin腳沒有被其他模塊所使用。
Q2: 為什么我用IO指令讀出來的值都是0x00000000?
A2: 如果用IO命令讀某個(gè)GPIO的寄存器,讀出來的值異常,如 0x00000000或0xffffffff等,請(qǐng)確認(rèn)該GPIO的CLK是不是被關(guān)了,GPIO的CLK是由CRU控制,可以通過讀取datasheet下面CRU_CLKGATE_CON* 寄存器來查到CLK是否開啟,如果沒有開啟可以用io命令設(shè)置對(duì)應(yīng)的寄存器,從而打開對(duì)應(yīng)的CLK,打開CLK之后應(yīng)該就可以讀到正確的寄存器值了。
Q3: 測(cè)量到PIN腳的電壓不對(duì)應(yīng)該怎么查?
A3: 測(cè)量該P(yáng)IN腳的電壓不對(duì)時(shí),如果排除了外部因素,可以確認(rèn)下該pin所在的io電壓源是否正確,以及IO-Domain配置是否正確。
Q4: gpio_set_value()與gpio_direction_output()有什么區(qū)別?
A4: 如果使用該GPIO時(shí),不會(huì)動(dòng)態(tài)的切換輸入輸出,建議在開始時(shí)就設(shè)置好GPIO 輸出方向,后面拉高拉低時(shí)使用gpio_set_value()接口,而不建議使用gpio_direction_output(), 因?yàn)間pio_direction_output接口里面有mutex鎖,對(duì)中斷上下文調(diào)用會(huì)有錯(cuò)誤異常,且相比 gpio_set_value,gpio_direction_output 所做事情更多,浪費(fèi)。
AIO-3399JD4 開發(fā)板上有 9 個(gè)片上 I2C 控制器,各個(gè) I2C 的使用情況如下表:
本文主要描述如何在該開發(fā)板上配置 I2C。
配置 I2C 可分為兩大步驟:
-
定義和注冊(cè) I2C 設(shè)備
-
定義和注冊(cè) I2C 驅(qū)動(dòng)
下面以配置 GSL3680 為例。
在注冊(cè)I2C設(shè)備時(shí),需要結(jié)構(gòu)體 i2c_client 來描述 I2C 設(shè)備。然而在標(biāo)準(zhǔn)Linux中,用戶只需要提供相應(yīng)的 I2C 設(shè)備信息,Linux就會(huì)根據(jù)所提供的信息構(gòu)造 i2c_client 結(jié)構(gòu)體。
用戶所提供的 I2C 設(shè)備信息以節(jié)點(diǎn)的形式寫到 dts 文件中,如下所示:
定義 I2C 驅(qū)動(dòng)
在定義 I2C 驅(qū)動(dòng)之前,用戶首先要定義變量 of_device_id 和 i2c_device_id 。
of_device_id 用于在驅(qū)動(dòng)中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
定義變量 i2c_device_id:
i2c_driver 如下所示:
注:變量id_table指示該驅(qū)動(dòng)所支持的設(shè)備。
注冊(cè) I2C 驅(qū)動(dòng)
使用i2c_add_driver函數(shù)注冊(cè) I2C 驅(qū)動(dòng)。
在調(diào)用 i2c_add_driver 注冊(cè) I2C 驅(qū)動(dòng)時(shí),會(huì)遍歷 I2C 設(shè)備,如果該驅(qū)動(dòng)支持所遍歷到的設(shè)備,則會(huì)調(diào)用該驅(qū)動(dòng)的 probe 函數(shù)。
通過 I2C 收發(fā)數(shù)據(jù)
在注冊(cè)好 I2C 驅(qū)動(dòng)后,即可進(jìn)行 I2C 通訊。
-
向從機(jī)發(fā)送信息:
-
向從機(jī)讀取信息:
Q1: 通信失敗,出現(xiàn)這種log:”timeout, ipd: 0x00, state: 1”該如何調(diào)試?
A1: 請(qǐng)檢查硬件上拉是否給電。
Q2: 調(diào)用i2c_transfer返回值為-6?
A2: 返回值為-6表示為NACK錯(cuò)誤,即對(duì)方設(shè)備無應(yīng)答響應(yīng),這種情況一般為外設(shè)的問題,常見的有以下幾種情況:
-
I2C地址錯(cuò)誤,解決方法是測(cè)量I2C波形,確認(rèn)是否I2C 設(shè)備地址錯(cuò)誤;
-
I2C slave 設(shè)備不處于正常工作狀態(tài),比如未給電,錯(cuò)誤的上電時(shí)序等;
-
時(shí)序不符合 I2C slave設(shè)備所要求也會(huì)產(chǎn)生Nack信號(hào)。
Q3: 當(dāng)外設(shè)對(duì)于讀時(shí)序要求中間是stop信號(hào)不是repeat start信號(hào)的時(shí)候,該如何處理?
A3: 這時(shí)需要調(diào)用兩次i2c_transfer, I2C read 拆分成兩次,修改如下:
AIO-3399JD4 開發(fā)板上使用紅外收發(fā)傳感器 IR (耳機(jī)接口和recovery之間)實(shí)現(xiàn)遙控功能,在IR接口處接上紅外接收器。本文主要描述在開發(fā)板上如何配置紅外遙控器。
其配置步驟可分為兩個(gè)部分:
-
修改內(nèi)核驅(qū)動(dòng):內(nèi)核空間修改,Linux 和 Android 都要修改這部分的內(nèi)容。
-
修改鍵值映射:用戶空間修改(僅限 Android 系統(tǒng))。
在 Linux 內(nèi)核中,IR 驅(qū)動(dòng)僅支持 NEC 編碼格式。以下是在內(nèi)核中配置紅外遙控的方法。 所涉及到的文件
定義相關(guān)數(shù)據(jù)結(jié)構(gòu)
以下是定義數(shù)據(jù)結(jié)構(gòu)的步驟:
注:第一列為鍵值,第二列為要響應(yīng)的按鍵碼。
如何獲取用戶碼和IR 鍵值
在 remotectl_do_something 函數(shù)中獲取用戶碼和鍵值:
注:用戶可以使用 DBG_CODE() 函數(shù)打印用戶碼。
使用下面命令可以使能DBG_CODE打?。?/p>
將 IR 驅(qū)動(dòng)編譯進(jìn)內(nèi)核
將 IR 驅(qū)動(dòng)編譯進(jìn)內(nèi)核的步驟如下所示:
(1)、向配置文件 drivers/input/remotectl/Kconfig 中添加如下配置:
(2)、修改 drivers/input/remotectl 路徑下的 Makefile,添加如下編譯選項(xiàng):
(3)、在 kernel 路徑下使用 make menuconfig ,按照如下方法將IR驅(qū)動(dòng)選中。
保存后,執(zhí)行 make 命令即可將該驅(qū)動(dòng)編進(jìn)內(nèi)核。
Android 鍵值映射
文件 /system/usr/keylayout/ff420030_pwm.kl 用于將 Linux 層獲取的鍵值映射到 Android 上對(duì)應(yīng)的鍵值。用戶可以添加或者修改該文件的內(nèi)容以實(shí)現(xiàn)不同的鍵值映射。
該文件內(nèi)容如下所示:
注:通過 adb 修改該文件重啟后即可生效。
如下圖是通過按紅外遙控器按鈕,所產(chǎn)生的波形,主要由head,Control,information,signed free這四部分組成,具體可以參考RC6 Protocol。
AIO-3399JD4開發(fā)板默認(rèn)外置支持了兩個(gè)LCD屏接口,一個(gè)是LVDS,一個(gè)是EDP,接口對(duì)應(yīng)板子上的位置如下圖:
另外板子也支持MIPI屏幕,但需要注意的是MIPI和LVDS是復(fù)用的,使用MIPI之后不能使用LVDS。MIPI接口如下圖:
如Android7.1,由于使用的是mipi轉(zhuǎn)lvds,AIO-3399JD4默認(rèn)的配置文件kernel/arch/arm64/configs/firefly_defconfig已經(jīng)把LCD相關(guān)的配置設(shè)置好了,如果自己做了修改,請(qǐng)注意把以下配置加上:
引腳配置
LVDS屏
AIO-3399JD4的SDK有LVDS DSI的DTS文件:kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-aiojd4-lvds-HSX101H40C.dts,從該文件中我們可以看到以下語句:
保存配置并編譯內(nèi)核,把kernel.img 燒到AIO-3399JD4板子上 我們可以使用串口輸入命令,就可以看到藍(lán)燈不停的間隔閃爍
用戶還可以使用 cat 命令獲取 trigger 的可用值:
與攝像頭相關(guān)的代碼目錄如下:
設(shè)置攝像頭相關(guān)的引腳和時(shí)鐘,即可完成配置過程。
從以下攝像頭接口原理圖可知,需要配置的引腳有:MIPI_PDN0_CAM和MIPI_RST。
mipi接口
MIPI_PDN0_CAM 對(duì)應(yīng) RK3399 的 GPIO2_A0;
MIPI_RST 對(duì)應(yīng)GPIO0_B0;
在開發(fā)板中,這兩個(gè)引腳都是在 cam_board.xml 中設(shè)置。
配置 Android
修改device/rockchip/rk3399/XXX_PRODUCT/cam_board.xml 來注冊(cè)攝像頭:
最后執(zhí)行:
即可完成內(nèi)核的編譯。
終端下可以直接修改/system/etc/cam_board.xml調(diào)試各參數(shù)并重啟生效
1.無法打開攝像頭,首先確定sensor I2C是否通信。若不通則可檢查mclk以及供電是否正常(Power/PowerDown/Reset/Mclk/I2cBus)分別排查 2.支持列表? 13M? OV13850/IMX214-0AQH5 8M? OV8825/OV8820/OV8858-Z(R1A)/OV8858-R2A 5M? OV5648/OV5640 2M? OV2680 詳細(xì)資料可查詢SDK/RKDocs
AIO-3399JD4開發(fā)板上引出有 3 路 PWM 輸出,分別為:
PWM0 屏背光
PWM2 VDDLOG供電
PWM3 紅外IR
本章主要描述如何配置 PWM。
RK3399的 PWM 驅(qū)動(dòng)為: kernel/drivers/pwm/pwm-rockchip.c
配置 PWM 主要有以下三大步驟:配置 PWM DTS 節(jié)點(diǎn)、配置 PWM 內(nèi)核驅(qū)動(dòng)、控制 PWM 設(shè)備。
配置 PWM DTS節(jié)點(diǎn)
在 DTS 源文件kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi 添加 PWM DTS 配置,如下所示:
pwm_id:需要申請(qǐng)的pwm通道數(shù)。
min_period:周期時(shí)長(zhǎng)最小值。
max_period:周期時(shí)長(zhǎng)最大值。
duty_ns:pwm 的占空比激活的時(shí)長(zhǎng),單位 ns。
用戶可在其它驅(qū)動(dòng)文件中使用以上步驟生成的 PWM 節(jié)點(diǎn)。具體方法如下:
(1)、在要使用 PWM 控制的設(shè)備驅(qū)動(dòng)文件中包含以下頭文件:
該頭文件主要包含 PWM 的函數(shù)接口。
(2)、申請(qǐng) PWM使用
函數(shù)申請(qǐng) PWM。 例如:
(3)、配置 PWM使用
配置 PWM 的占空比, 例如:
(4)、使能PWM 函數(shù)
用于使能 PWM,例如:
(5)控制 PWM 輸出主要使用以下接口函數(shù):
功能:用于申請(qǐng) pwm
功能:用于釋放所申請(qǐng)的 pwm
功能:用于配置 pwm 的占空比
功能:使能 pwm
功能:禁止 pwm
參考Demo:kernel/drivers/pwm/pwm-firefly.c
通過內(nèi)核豐富的debug接口查看pwm注冊(cè)狀態(tài),adb shell或者串口進(jìn)入android終端 cat /sys/kernel/debug/pwm —注冊(cè)是否成功,成功則返回接口名和寄存器地址
Pwm無法注冊(cè)成功:
dts配置文件是否打開對(duì)應(yīng)的pwm。
pwm所在的io口是否被其他資源占用,可以根據(jù)報(bào)錯(cuò)的返回值去查看原因。
SPI是一種高速的,全雙工,同步串行通信接口,用于連接微控制器、傳感器、存儲(chǔ)設(shè)備等。 AIO-3399JD4 SPI引出來了一路SPI2(可復(fù)用GPIO)給外部使用。 AIO-3399JD4 開發(fā)板提供了 SPI2(單片選)接口,具體位置如下圖:
SPI以主從方式工作,這種模式通常有一個(gè)主設(shè)備和一個(gè)或多個(gè)從設(shè)備,需要至少4根線,分別是:
Linux內(nèi)核用CPOL和CPHA的組合來表示當(dāng)前SPI的四種工作模式:
CPOL:表示時(shí)鐘信號(hào)的初始電平的狀態(tài),0為低電平,1為高電平。CPHA:表示在哪個(gè)時(shí)鐘沿采樣,0為第一個(gè)時(shí)鐘沿采樣,1為第二個(gè)時(shí)鐘沿采樣。SPI的四種工作模式波形圖如下:
下面以 W25Q128FV Flash模塊為例簡(jiǎn)單介紹SPI驅(qū)動(dòng)的編寫。
硬件連接
AIO-3399JD4 與 W25Q128FV 硬件連接如下表:
在kernel/drivers/spi/Kconfig中添加對(duì)應(yīng)的驅(qū)動(dòng)文件配置:
在kernel/drivers/spi/Makefile中添加對(duì)應(yīng)的驅(qū)動(dòng)文件名:
config中選中所添加的驅(qū)動(dòng)文件,如:
配置DTS節(jié)點(diǎn)
在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi中添加SPI驅(qū)動(dòng)結(jié)點(diǎn)描述,如下所示:
status:如果要啟用SPI,則設(shè)為okay,如不啟用,設(shè)為disable。
spi-demo@00:由于本例子使用CS0,故此處設(shè)為00,如果使用CS1,則設(shè)為01。
compatible:這里的屬性必須與驅(qū)動(dòng)中的結(jié)構(gòu)體:of_device_id 中的成員compatible 保持一致。
reg:此處與spi-demo@00保持一致,本例設(shè)為:0x00。
spi-max-frequency:此處設(shè)置spi使用的最高頻率。Firefly-RK3399最高支持48000000。
spi-cpha,spi-cpol:SPI的工作模式在此設(shè)置,本例所用的模塊SPI工作模式為SPI_MODE_0或者SPI_MODE_3,這里我們選用SPI_MODE_0,如果使用SPI_MODE_3,spi_demo中打開spi-cpha和spi-cpol即可。
spidev0: 由于spi_demo與spidev0使用一樣的硬件資源,需要把spidev0關(guān)掉才能打開spi_demo
定義SPI驅(qū)動(dòng)
在內(nèi)核源碼目錄kernel/drivers/spi/中創(chuàng)建新的驅(qū)動(dòng)文件,如:spi-firefly-demo.c 在定義 SPI 驅(qū)動(dòng)之前,用戶首先要定義變量 of_device_id 。 of_device_id 用于在驅(qū)動(dòng)中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
此處的compatible與DTS文件中的保持一致。
spi_driver定義如下所示:
注冊(cè)SPI設(shè)備
在初始化函數(shù)static int __init spidev_init(void)中向內(nèi)核注冊(cè)SPI驅(qū)動(dòng): spi_register_driver(&firefly_spi_driver);
如果內(nèi)核啟動(dòng)時(shí)匹配成功,則SPI核心會(huì)配置SPI的參數(shù)(mode、speed等),并調(diào)用firefly_spi_probe。
讀寫 SPI 數(shù)據(jù)
firefly_spi_probe中使用了兩種接口操作讀取W25Q128FV的ID: firefly_spi_read_w25x_id_0接口直接使用了spi_transfer和spi_message來傳送數(shù)據(jù)。 firefly_spi_read_w25x_id_1接口則使用SPI接口spi_write_then_read來讀寫數(shù)據(jù)。
成功后會(huì)打印:
打開SPI demo
spi-firefly-demo默認(rèn)沒有打開,如果需要的話可以使用以下補(bǔ)丁打開demo驅(qū)動(dòng):
常用SPI接口
下面是常用的 SPI API 定義:
Linux提供了一個(gè)功能有限的SPI用戶接口,如果不需要用到IRQ或者其他內(nèi)核驅(qū)動(dòng)接口,可以考慮使用接口spidev編寫用戶層程序控制SPI設(shè)備。 在 Firefly-RK3399 開發(fā)板中對(duì)應(yīng)的路徑為: /dev/spidev0.0
spidev對(duì)應(yīng)的驅(qū)動(dòng)代碼: kernel/drivers/spi/spidev.c
內(nèi)核config需要選上SPI_SPIDEV:
DTS配置如下:
詳細(xì)使用說明請(qǐng)參考文檔 spidev 。
Q1: SPI數(shù)據(jù)傳送異常
A1: 確保 SPI 4個(gè)引腳的 IOMUX 配置正確, 確認(rèn) TX 送數(shù)據(jù)時(shí),TX 引腳有正常的波形,CLK 頻率正確,CS 信號(hào)有拉低,mode 與設(shè)備匹配。
RK3399有12 個(gè)Timers (timer0-timer11),有12 個(gè)Secure Timers(stimer0~stimer11) 和 2 個(gè)Timers(pmutimer0~pmutimer1), 我們主要用到的是Timers(timer0-timer11)時(shí)鐘頻率為24MHZ ,工作模式有 free-running 和 user-defined count 模式
user-defined count:Timer 先載入初始值到 TIMERn_LOAD_COUNT3 和 TIMER_LOADn_COUNT2寄存器, 當(dāng)時(shí)間累加的值在寄存器TIMERn_LOAD_COUNT1和TIMERn_LOAD_COUNT0時(shí),將不會(huì)自動(dòng)載入到計(jì)數(shù)寄存器。 用戶需要重新關(guān)閉計(jì)數(shù)器和然后重新設(shè)置計(jì)數(shù)器相關(guān)才能繼續(xù)工作。
free-running:Timer先載入初始值到TIMER_LOAD_COUNT3 和 TIMER_LOAD_COUNT2寄存器, 當(dāng)時(shí)間累加的值在寄存器TIMERn_LOAD_COUNT1和TIMERn_LOAD_COUNT0時(shí),Timer將一直自動(dòng)加載計(jì)數(shù)寄存器。
1.在 dts 文件中定義 Timer 的相關(guān)配置 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi
其中定義的Timer0 的寄存器和中斷號(hào)和時(shí)鐘等
其他Timer 對(duì)應(yīng)的中斷號(hào)可看如下圖片
2.對(duì)應(yīng)的驅(qū)動(dòng)文件Kernel/drivers/clocksource/rockchip_timer.c
1.寄存器如下圖片
文件kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-port.dtsi 有spi轉(zhuǎn)uart相關(guān)節(jié)點(diǎn)的定義:
可以看到,在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-aiojd4.dts文件中使能該節(jié)點(diǎn)即可使用。另外,由于我們板子使用的spi轉(zhuǎn)uart串口模塊掛到spi1上,所以還要使能spi1節(jié)點(diǎn)。如下:
注意:由于spi1_rxd和spi1_txd兩個(gè)腳可復(fù)用為uart4_rx和uart4_tx,所以要留意關(guān)閉掉uart4的使用,如下:
配置好串口后,硬件接口對(duì)應(yīng)軟件上的節(jié)點(diǎn)分別為:
用戶可以根據(jù)不同的接口使用不同的主機(jī)的 USB 轉(zhuǎn)串口適配器向開發(fā)板的串口收發(fā)數(shù)據(jù),例如RS485的調(diào)試步驟如下:
(1) 連接硬件
將開發(fā)板RS485 的A、B、GND 引腳分別和主機(jī)串口適配器(USB轉(zhuǎn)485轉(zhuǎn)串口模塊)的 A、B、GND 引腳相連。
(2) 打開主機(jī)的串口終端
在終端打開kermit,并設(shè)置波特率:
/dev/ttyUSB0 為 USB 轉(zhuǎn)串口適配器的設(shè)備文件
(3) 發(fā)送數(shù)據(jù)
RS485 的設(shè)備文件為 /dev/ttysWK0。在設(shè)備上運(yùn)行下列命令:
主機(jī)中的串口終端即可接收到字符串“firefly RS485 test…”
(4) 接收數(shù)據(jù)
首先在設(shè)備上運(yùn)行下列命令:
然后在主機(jī)的串口終端輸入字符串 “Firefly RS485 test…”,設(shè)備端即可見到相同的字符串。
-->
-
嵌入式主板
+關(guān)注
關(guān)注
7文章
6095瀏覽量
36080 -
安卓
+關(guān)注
關(guān)注
5文章
2140瀏覽量
58192 -
Firefly
+關(guān)注
關(guān)注
2文章
541瀏覽量
7324
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
fireflyCORE-3399PRO主板JD4燒寫固件簡(jiǎn)介

fireflyCORE-3399主板JD4--FAQs方案

fireflyCORE-3399主板JD4接口定義

fireflyCORE-3399主板JD4產(chǎn)品簡(jiǎn)介
Core 3399Pro JD4文檔Core 3399Pro JD4核心板產(chǎn)品規(guī)格書

Core 3399 JD4工具Erase IDB Tool

Core 3399 JD4固件Android 7.1系統(tǒng)

Core 3399 JD4固件Debian

Core 3399 JD4文檔AIO 3399JD4產(chǎn)品規(guī)格書

Core 3399 JD4文檔AIO 3399JD4 Product Specifications

Core 3399 JD4文檔mb jd4 rk3399&3399pro v1.1.pdf

Core 3399 JD4 V2文檔AIO 3399JD4產(chǎn)品規(guī)格

Core 3399 JD4 V2文檔MB JD4 RK3399/3399Pro V1.1貼片圖

Core 3399 JD4 V2文檔mb jd4 rk3399/3399pro v1.1

評(píng)論