AIO-3399JD4 開發(fā)板上的 AD 接口有兩種,分別為:溫度傳感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。其中:
-
TS-ADC(Temperature Sensor):支持兩通道,時鐘頻率必須低于800KHZ
-
SAR-ADC(Successive Approximation Register):支持六通道單端10位的SAR-ADC,時鐘頻率必須小于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的資源描述:
這里申請的是SARADC通道3,在 AIO-3399JD4 中是不提供給客戶外部使用的,而且也沒有風(fēng)扇接口,這里只是提供一個參考, 客戶可自行參考這個例子 運(yùn)用SARADC通道0 去做自己的一些開發(fā)。
在驅(qū)動文件中匹配 DTS 節(jié)點(diǎn)
用戶驅(qū)動可參考Firefly adc demo :kernel/drivers/adc/adc-firefly-demo.c,這是一個偵測Firefly-rk3399風(fēng)扇狀態(tài)的驅(qū)動。 首先在驅(qū)動文件中定義 of_device_id 結(jié)構(gòu)體數(shù)組:
然后將該結(jié)構(gòu)體數(shù)組填充到要使用 ADC 的 platform_driver 中:
接著在firefly_adc_probe中對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)扇時,會打印內(nèi)核log信息如下:
獲取所有ADC值
有個便捷的方法可以查詢到每個SARADC的值:
為何按上面的步驟申請SARADC,會出現(xiàn)申請報錯的情況?
驅(qū)動需要獲取ADC通道來使用時,需要對驅(qū)動的加載時間進(jìn)行控制,必須要在saradc初始化之后。saradc是使用module_platform_driver()進(jìn)行平臺設(shè)備驅(qū)動注冊,最終調(diào)用的是module_init()。所以用戶的驅(qū)動加載函數(shù)只需使用比module_init()優(yōu)先級低的,例如:late_initcall(),就能保證驅(qū)動的加載的時間比saradc初始化時間晚,可避免出錯。
GPIO, 全稱 General-Purpose Input/Output(通用輸入輸出),是一種軟件運(yùn)行期間能夠動態(tài)配置和控制的通用引腳。 RK3399有5組GPIO bank:GPIO0~GPIO4,每組又以 A0~A7, B0~B7, C0~C7, D0~D7 作為編號區(qū)分(不是所有 bank 都有全部編號,例如 GPIO4 就只有 C0~C7, D0~D2)。 所有的GPIO在上電后的初始狀態(tài)都是輸入模式,可以通過軟件設(shè)為上拉或下拉,也可以設(shè)置為中斷腳,驅(qū)動強(qiáng)度都是可編程的。 每個 GPIO 口除了通用輸入輸出功能外,還可能有其它復(fù)用功能,例如 GPIO2_A2,可以利用成以下功能:
-
GPIO2_A2
-
CIF_D2
每個 GPIO 口的驅(qū)動電流、上下拉和重置后的初始狀態(tài)都不盡相同,詳細(xì)情況請參考《RK3399 規(guī)格書》中的 “Chapter 10 GPIO” 一章。 RK3399 的 GPIO 驅(qū)動是在以下 pinctrl 文件中實(shí)現(xiàn)的:
其核心是填充 GPIO bank 的方法和參數(shù),并調(diào)用 gpiochip_add 注冊到內(nèi)核中。
本文以TP_RST(GPIO0_B4)和LCD_RST(GPIO4_D5)這兩個通用GPIO口為例寫了一份簡單操作GPIO口的驅(qū)動,在SDK的路徑為:
以下就以該驅(qū)動為例介紹GPIO的操作。
首先在DTS文件中增加驅(qū)動的資源描述:
這里定義了一個腳作為一般的輸出輸入口:
AIO-3399JD4 的dts對引腳的描述與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,這個屬性將被驅(qū)動所讀取。
然后在probe函數(shù)中對DTS所添加的資源進(jìn)行解析,代碼如下:
of_get_named_gpio_flags 從設(shè)備樹中讀取 firefly-gpio 和 firefly-irq-gpio 的 GPIO 配置編號和標(biāo)志,gpio_is_valid 判斷該 GPIO 編號是否有效,gpio_request 則申請占用該 GPIO。如果初始化過程出錯,需要調(diào)用 gpio_free 來釋放之前申請過且成功的 GPIO 。 在驅(qū)動中調(diào)用 gpio_direction_output 就可以設(shè)置輸出高還是低電平,這里默認(rèn)輸出從DTS獲取得到的有效電平GPIO_ACTIVE_HIGH,即為高電平,如果驅(qū)動正常工作,可以用萬用表測得對應(yīng)的引腳應(yīng)該為高電平。 實(shí)際中如果要讀出 GPIO,需要先設(shè)置成輸入模式,然后再讀取值:
下面是常用的 GPIO API 定義:
在Firefly的例子程序中還包含了一個中斷引腳,GPIO口的中斷使用與GPIO的輸入輸出類似,首先在DTS文件中增加驅(qū)動的資源描述:
IRQ_TYPE_EDGE_RISING表示中斷由上升沿觸發(fā),當(dāng)該引腳接收到上升沿信號時可以觸發(fā)中斷函數(shù)。 這里還可以配置成如下:
然后在probe函數(shù)中對DTS所添加的資源進(jìn)行解析,再做中斷的注冊申請,代碼如下:
調(diào)用gpio_to_irq把GPIO的PIN值轉(zhuǎn)換為相應(yīng)的IRQ值,調(diào)用gpio_request申請占用該IO口,調(diào)用request_irq申請中斷,如果失敗要調(diào)用free_irq釋放,該函數(shù)中g(shù)pio_info-firefly_irq是要申請的硬件中斷號,firefly_gpio_irq是中斷函數(shù),gpio_info->firefly_irq_mode是中斷處理的屬性,”firefly-gpio”是設(shè)備驅(qū)動程序名稱,gpio_info是該設(shè)備的device結(jié)構(gòu),在注冊共享中斷時會用到。
如何定義 GPIO 有哪些功能可以復(fù)用,在運(yùn)行時又如何切換功能呢?以 I2C4 為例作簡單的介紹。
查規(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è)置的 pinctrl: &i2c4_xfer
-
pinctrl-1 定義了狀態(tài) 1 (即 gpio)時需要設(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ù)用時,如果選擇了 “default” (即 i2c 功能),系統(tǒng)會應(yīng)用 i2c4_xfer 這個 pinctrl,最終將 GPIO1_B3 和 GPIO1_B4 兩個針腳切換成對應(yīng)的 i2c 功能;而如果選擇了 “gpio” ,系統(tǒng)會應(yīng)用 i2c4_gpio 這個 pinctrl,將 GPIO1_B3 和 GPIO1_B4 兩個針腳還原為 GPIO 功能。
我們看看 i2c 的驅(qū)動程序 kernel/drivers/i2c/busses/i2c-rockchip.c 是如何切換復(fù)用功能的:
首先是調(diào)用 of_get_gpio 取出設(shè)備樹中 i2c4 結(jié)點(diǎn)的 gpios 屬于所定義的兩個 gpio:
然后是調(diào)用 devm_gpio_request 來申請 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ì)者一般會將系統(tǒng)的供電分為多個獨(dú)立的block,這稱作電源域(Power Domain),這樣做有很多好處,例如:
-
在IO-Domain的DTS節(jié)點(diǎn)統(tǒng)一配置電壓域,不需要每個驅(qū)動都去配置一次,便于管理;
-
依照的是Upstream的做法,以后如果需要Upstream比較方便;
-
IO-Domain的驅(qū)動支持運(yùn)行過程中動態(tài)調(diào)整電壓域,例如PMIC的某個Regulator可以1.8v和3.3v的動態(tài)切換,一旦Regulator電壓發(fā)生改變,會通知IO-Domain驅(qū)動去重新設(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)試有一個很好用的工具,那就是IO指令,AIO-3399C的Android系統(tǒng)默認(rèn)已經(jīng)內(nèi)置了IO指令,使用IO指令可以實(shí)時讀取或?qū)懭朊總€IO口的狀態(tài),這里簡單介紹IO指令的使用。 首先查看 io 指令的幫助:
從幫助上可以看出,如果要讀或者寫一個寄存器,可以用:
使用示例:
-
查看GPIO1_B3引腳的復(fù)用情況
-
從主控的datasheet查到GPIO1對應(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時候,會將該P(yáng)IN的MUX值強(qiáng)制切換為GPIO,所以使用該pin腳為GPIO功能的時候確保該pin腳沒有被其他模塊所使用。
Q2: 為什么我用IO指令讀出來的值都是0x00000000?
A2: 如果用IO命令讀某個GPIO的寄存器,讀出來的值異常,如 0x00000000或0xffffffff等,請確認(rèn)該GPIO的CLK是不是被關(guān)了,GPIO的CLK是由CRU控制,可以通過讀取datasheet下面CRU_CLKGATE_CON* 寄存器來查到CLK是否開啟,如果沒有開啟可以用io命令設(shè)置對應(yīng)的寄存器,從而打開對應(yīng)的CLK,打開CLK之后應(yīng)該就可以讀到正確的寄存器值了。
Q3: 測量到PIN腳的電壓不對應(yīng)該怎么查?
A3: 測量該P(yáng)IN腳的電壓不對時,如果排除了外部因素,可以確認(rèn)下該pin所在的io電壓源是否正確,以及IO-Domain配置是否正確。
Q4: gpio_set_value()與gpio_direction_output()有什么區(qū)別?
A4: 如果使用該GPIO時,不會動態(tài)的切換輸入輸出,建議在開始時就設(shè)置好GPIO 輸出方向,后面拉高拉低時使用gpio_set_value()接口,而不建議使用gpio_direction_output(), 因?yàn)間pio_direction_output接口里面有mutex鎖,對中斷上下文調(diào)用會有錯誤異常,且相比 gpio_set_value,gpio_direction_output 所做事情更多,浪費(fèi)。
AIO-3399JD4 開發(fā)板上有 9 個片上 I2C 控制器,各個 I2C 的使用情況如下表:
本文主要描述如何在該開發(fā)板上配置 I2C。
配置 I2C 可分為兩大步驟:
-
定義和注冊 I2C 設(shè)備
-
定義和注冊 I2C 驅(qū)動
下面以配置 GSL3680 為例。
在注冊I2C設(shè)備時,需要結(jié)構(gòu)體 i2c_client 來描述 I2C 設(shè)備。然而在標(biāo)準(zhǔn)Linux中,用戶只需要提供相應(yīng)的 I2C 設(shè)備信息,Linux就會根據(jù)所提供的信息構(gòu)造 i2c_client 結(jié)構(gòu)體。
用戶所提供的 I2C 設(shè)備信息以節(jié)點(diǎn)的形式寫到 dts 文件中,如下所示:
定義 I2C 驅(qū)動
在定義 I2C 驅(qū)動之前,用戶首先要定義變量 of_device_id 和 i2c_device_id 。
of_device_id 用于在驅(qū)動中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
定義變量 i2c_device_id:
i2c_driver 如下所示:
注:變量id_table指示該驅(qū)動所支持的設(shè)備。
注冊 I2C 驅(qū)動
使用i2c_add_driver函數(shù)注冊 I2C 驅(qū)動。
在調(diào)用 i2c_add_driver 注冊 I2C 驅(qū)動時,會遍歷 I2C 設(shè)備,如果該驅(qū)動支持所遍歷到的設(shè)備,則會調(diào)用該驅(qū)動的 probe 函數(shù)。
通過 I2C 收發(fā)數(shù)據(jù)
在注冊好 I2C 驅(qū)動后,即可進(jìn)行 I2C 通訊。
-
向從機(jī)發(fā)送信息:
-
向從機(jī)讀取信息:
Q1: 通信失敗,出現(xiàn)這種log:”timeout, ipd: 0x00, state: 1”該如何調(diào)試?
A1: 請檢查硬件上拉是否給電。
Q2: 調(diào)用i2c_transfer返回值為-6?
A2: 返回值為-6表示為NACK錯誤,即對方設(shè)備無應(yīng)答響應(yīng),這種情況一般為外設(shè)的問題,常見的有以下幾種情況:
-
I2C地址錯誤,解決方法是測量I2C波形,確認(rèn)是否I2C 設(shè)備地址錯誤;
-
I2C slave 設(shè)備不處于正常工作狀態(tài),比如未給電,錯誤的上電時序等;
-
時序不符合 I2C slave設(shè)備所要求也會產(chǎn)生Nack信號。
Q3: 當(dāng)外設(shè)對于讀時序要求中間是stop信號不是repeat start信號的時候,該如何處理?
A3: 這時需要調(diào)用兩次i2c_transfer, I2C read 拆分成兩次,修改如下:
AIO-3399JD4 開發(fā)板上使用紅外收發(fā)傳感器 IR (耳機(jī)接口和recovery之間)實(shí)現(xiàn)遙控功能,在IR接口處接上紅外接收器。本文主要描述在開發(fā)板上如何配置紅外遙控器。
其配置步驟可分為兩個部分:
-
修改內(nèi)核驅(qū)動:內(nèi)核空間修改,Linux 和 Android 都要修改這部分的內(nèi)容。
-
修改鍵值映射:用戶空間修改(僅限 Android 系統(tǒng))。
在 Linux 內(nèi)核中,IR 驅(qū)動僅支持 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打印:
將 IR 驅(qū)動編譯進(jìn)內(nèi)核
將 IR 驅(qū)動編譯進(jìn)內(nèi)核的步驟如下所示:
(1)、向配置文件 drivers/input/remotectl/Kconfig 中添加如下配置:
(2)、修改 drivers/input/remotectl 路徑下的 Makefile,添加如下編譯選項(xiàng):
(3)、在 kernel 路徑下使用 make menuconfig ,按照如下方法將IR驅(qū)動選中。
保存后,執(zhí)行 make 命令即可將該驅(qū)動編進(jìn)內(nèi)核。
Android 鍵值映射
文件 /system/usr/keylayout/ff420030_pwm.kl 用于將 Linux 層獲取的鍵值映射到 Android 上對應(yīng)的鍵值。用戶可以添加或者修改該文件的內(nèi)容以實(shí)現(xiàn)不同的鍵值映射。
該文件內(nèi)容如下所示:
注:通過 adb 修改該文件重啟后即可生效。
如下圖是通過按紅外遙控器按鈕,所產(chǎn)生的波形,主要由head,Control,information,signed free這四部分組成,具體可以參考RC6 Protocol。
AIO-3399JD4開發(fā)板默認(rèn)外置支持了兩個LCD屏接口,一個是LVDS,一個是EDP,接口對應(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è)置好了,如果自己做了修改,請注意把以下配置加上:
引腳配置
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)的引腳和時鐘,即可完成配置過程。
從以下攝像頭接口原理圖可知,需要配置的引腳有:MIPI_PDN0_CAM和MIPI_RST。
mipi接口
MIPI_PDN0_CAM 對應(yīng) RK3399 的 GPIO2_A0;
MIPI_RST 對應(yīng)GPIO0_B0;
在開發(fā)板中,這兩個引腳都是在 cam_board.xml 中設(shè)置。
配置 Android
修改device/rockchip/rk3399/XXX_PRODUCT/cam_board.xml 來注冊攝像頭:
最后執(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ū)動為: kernel/drivers/pwm/pwm-rockchip.c
配置 PWM 主要有以下三大步驟:配置 PWM DTS 節(jié)點(diǎn)、配置 PWM 內(nèi)核驅(qū)動、控制 PWM 設(shè)備。
配置 PWM DTS節(jié)點(diǎn)
在 DTS 源文件kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi 添加 PWM DTS 配置,如下所示:
pwm_id:需要申請的pwm通道數(shù)。
min_period:周期時長最小值。
max_period:周期時長最大值。
duty_ns:pwm 的占空比激活的時長,單位 ns。
用戶可在其它驅(qū)動文件中使用以上步驟生成的 PWM 節(jié)點(diǎn)。具體方法如下:
(1)、在要使用 PWM 控制的設(shè)備驅(qū)動文件中包含以下頭文件:
該頭文件主要包含 PWM 的函數(shù)接口。
(2)、申請 PWM使用
函數(shù)申請 PWM。 例如:
(3)、配置 PWM使用
配置 PWM 的占空比, 例如:
(4)、使能PWM 函數(shù)
用于使能 PWM,例如:
(5)控制 PWM 輸出主要使用以下接口函數(shù):
功能:用于申請 pwm
功能:用于釋放所申請的 pwm
功能:用于配置 pwm 的占空比
功能:使能 pwm
功能:禁止 pwm
參考Demo:kernel/drivers/pwm/pwm-firefly.c
通過內(nèi)核豐富的debug接口查看pwm注冊狀態(tài),adb shell或者串口進(jìn)入android終端 cat /sys/kernel/debug/pwm —注冊是否成功,成功則返回接口名和寄存器地址
Pwm無法注冊成功:
dts配置文件是否打開對應(yīng)的pwm。
pwm所在的io口是否被其他資源占用,可以根據(jù)報錯的返回值去查看原因。
SPI是一種高速的,全雙工,同步串行通信接口,用于連接微控制器、傳感器、存儲設(shè)備等。 AIO-3399JD4 SPI引出來了一路SPI2(可復(fù)用GPIO)給外部使用。 AIO-3399JD4 開發(fā)板提供了 SPI2(單片選)接口,具體位置如下圖:
SPI以主從方式工作,這種模式通常有一個主設(shè)備和一個或多個從設(shè)備,需要至少4根線,分別是:
Linux內(nèi)核用CPOL和CPHA的組合來表示當(dāng)前SPI的四種工作模式:
CPOL:表示時鐘信號的初始電平的狀態(tài),0為低電平,1為高電平。CPHA:表示在哪個時鐘沿采樣,0為第一個時鐘沿采樣,1為第二個時鐘沿采樣。SPI的四種工作模式波形圖如下:
下面以 W25Q128FV Flash模塊為例簡單介紹SPI驅(qū)動的編寫。
硬件連接
AIO-3399JD4 與 W25Q128FV 硬件連接如下表:
在kernel/drivers/spi/Kconfig中添加對應(yīng)的驅(qū)動文件配置:
在kernel/drivers/spi/Makefile中添加對應(yīng)的驅(qū)動文件名:
config中選中所添加的驅(qū)動文件,如:
配置DTS節(jié)點(diǎn)
在kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi中添加SPI驅(qū)動結(jié)點(diǎn)描述,如下所示:
status:如果要啟用SPI,則設(shè)為okay,如不啟用,設(shè)為disable。
spi-demo@00:由于本例子使用CS0,故此處設(shè)為00,如果使用CS1,則設(shè)為01。
compatible:這里的屬性必須與驅(qū)動中的結(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ū)動
在內(nèi)核源碼目錄kernel/drivers/spi/中創(chuàng)建新的驅(qū)動文件,如:spi-firefly-demo.c 在定義 SPI 驅(qū)動之前,用戶首先要定義變量 of_device_id 。 of_device_id 用于在驅(qū)動中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
此處的compatible與DTS文件中的保持一致。
spi_driver定義如下所示:
注冊SPI設(shè)備
在初始化函數(shù)static int __init spidev_init(void)中向內(nèi)核注冊SPI驅(qū)動: spi_register_driver(&firefly_spi_driver);
如果內(nèi)核啟動時匹配成功,則SPI核心會配置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ù)。
成功后會打印:
打開SPI demo
spi-firefly-demo默認(rèn)沒有打開,如果需要的話可以使用以下補(bǔ)丁打開demo驅(qū)動:
常用SPI接口
下面是常用的 SPI API 定義:
Linux提供了一個功能有限的SPI用戶接口,如果不需要用到IRQ或者其他內(nèi)核驅(qū)動接口,可以考慮使用接口spidev編寫用戶層程序控制SPI設(shè)備。 在 Firefly-RK3399 開發(fā)板中對應(yīng)的路徑為: /dev/spidev0.0
spidev對應(yīng)的驅(qū)動代碼: kernel/drivers/spi/spidev.c
內(nèi)核config需要選上SPI_SPIDEV:
DTS配置如下:
詳細(xì)使用說明請參考文檔 spidev 。
Q1: SPI數(shù)據(jù)傳送異常
A1: 確保 SPI 4個引腳的 IOMUX 配置正確, 確認(rèn) TX 送數(shù)據(jù)時,TX 引腳有正常的波形,CLK 頻率正確,CS 信號有拉低,mode 與設(shè)備匹配。
RK3399有12 個Timers (timer0-timer11),有12 個Secure Timers(stimer0~stimer11) 和 2 個Timers(pmutimer0~pmutimer1), 我們主要用到的是Timers(timer0-timer11)時鐘頻率為24MHZ ,工作模式有 free-running 和 user-defined count 模式
user-defined count:Timer 先載入初始值到 TIMERn_LOAD_COUNT3 和 TIMER_LOADn_COUNT2寄存器, 當(dāng)時間累加的值在寄存器TIMERn_LOAD_COUNT1和TIMERn_LOAD_COUNT0時,將不會自動載入到計(jì)數(shù)寄存器。 用戶需要重新關(guān)閉計(jì)數(shù)器和然后重新設(shè)置計(jì)數(shù)器相關(guān)才能繼續(xù)工作。
free-running:Timer先載入初始值到TIMER_LOAD_COUNT3 和 TIMER_LOAD_COUNT2寄存器, 當(dāng)時間累加的值在寄存器TIMERn_LOAD_COUNT1和TIMERn_LOAD_COUNT0時,Timer將一直自動加載計(jì)數(shù)寄存器。
1.在 dts 文件中定義 Timer 的相關(guān)配置 kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi
其中定義的Timer0 的寄存器和中斷號和時鐘等
其他Timer 對應(yīng)的中斷號可看如下圖片
2.對應(yīng)的驅(qū)動文件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兩個腳可復(fù)用為uart4_rx和uart4_tx,所以要留意關(guān)閉掉uart4的使用,如下:
配置好串口后,硬件接口對應(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文章
6097瀏覽量
36143 -
安卓
+關(guān)注
關(guān)注
5文章
2148瀏覽量
58358 -
Firefly
+關(guān)注
關(guān)注
2文章
541瀏覽量
7406
發(fā)布評論請先 登錄
fireflyCORE-3399PRO主板JD4燒寫固件簡介

fireflyCORE-3399主板JD4--FAQs方案

fireflyCORE-3399主板JD4接口定義

fireflyCORE-3399主板JD4產(chǎn)品簡介
Core 3399Pro JD4工具SDDiskTool

Core 3399Pro JD4文檔Core 3399Pro JD4核心板產(chǎn)品規(guī)格書

Core 3399 JD4工具SD Firmware Tool

Core 3399 JD4解合包工具(Linux)

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文檔MB JD4 RK3399/3399Pro V1.1貼片圖

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

評論