How to access GPIO using mamp in TI AM335x CPU
Base on Beaglebone Black
C
Library development note
Author : Cai , Meng-Lun ,
(VegetableAvenger) , 2013/12/19
Introduction
:
這份筆記的內容正式涵蓋了BBBio library的內容,這份文件將介紹如何再Beaglebone black上利用C語言與mmap來進行GPIO的操作,以user space的方式來控制硬體,而不用去撰寫專用的Device Driver,同時粗略的介紹一下AM335x的System Interconnect架構,以瞭解module的布局方式以及Clock manager的管理,最後將演示一段透過BBBio library,使用按鈕開關來控制LED閃爍速度的程式碼。
This
note contain :
-
AM335x System Interconnect Architecture
- AM335x GPIO module introduction
- Memory map of AM335x GPIO module
- Enable/Disable Clock of GPIO module via CM_PER/CM_WKUP register
- GPIO register
- Get BBBio
- LED Demo
部份文字內容或圖片 reference from :
AM335x Technical Reference Manual
AM335x
System Interconnect Architecture :
AM335x的interconnect Architecture 為2-Level架構,由L3與L4組成,而L3則分為L3F與L3S,而L4則是分為L4_FAST、L4_PER與L4_WKUP,結構如圖1所示,由其可看出L4_PER與L4_WKUP是掛接在L3_S下,而L4_FAST則是接在L3F下。
圖1、L3 Topology (AM335x TRM page 1231)
而GPIO模組則是分佈在L4之中,GPIO 0掛在L4_WKUP,GPIO 1~3掛在L4_PER中,整體上如圖2所示。
圖2、L4 Topology (AM335x TRM page 1234)
瞭解GPIO模組所屬的Interconnect Topology有助於瞭解各module間的Clock互動情形,即瞭解module所屬的Clock Domain,像是GPIO 1~3所處的Clock Domain為PD_PER_L4LS_GCLK,而GPIO 0 則處在PD_WKUP_L4_WKUP_GCLK這個Clock domain上,而透過圖2的L4 Topology布局方式便可以清楚的瞭解為何GPIO模組會處於不同的Clock Domain上。
為了要讓module省電,所以沒有必要使用的module其Clock常處於Disable的狀態,而每一個GPIO模組擁有其各自的register來控制是否Disable Clock,瞭解其Clock domain之後,便可以搜尋其對應的Clock control register,接著才可以在需要使用時,將GPIO的Clock Enable/Disable,下表為各GPIO的Clock control register:
GPIO
|
Clock Domain
|
Speed
|
Clock Control Register
|
GPIO 0
|
PD_WKUP_L4_WKUP_GCLK
|
100M Hz
|
CM_WKUP_GPIO0_CLKCTRL
|
GPIO 1
|
PD_PER_L4LS_GCLK
|
100M Hz
|
CM_PER_GPIO1_CLKCTRL
|
GPIO 2
|
PD_PER_L4LS_GCLK
|
100M Hz
|
CM_PER_GPIO2_CLKCTRL
|
GPIO 3
|
PD_PER_L4LS_GCLK
|
100M Hz
|
CM_PER_GPIO3_CLKCTRL
|
表1、GPIO Clock Domain
AM335x
GPIO Module Introduction :
AM335x 擁有4組GPIO module,GPIO 0、GPIO 1、GPIO 2與GPIO 3,每一個module有32支接腳,故總共有128支GPIO的腳位可以使用,每支腳位提供以下的基本功能:
-
Data Input/ Output
- Debounce cell
- Synchronous interrupt
- Wake-up request (Only GPIO 0)
本筆記主要記錄最基本的Data Input/Output,Debouncing為次章節介紹,而剩餘功能尚未完整測試。
基本上每一組GPIO都提供了1~3的基本功能,而GPIO 0 則額外提供了Wake-Pp的功能,是與其他GPIO較為不同的地方,如圖3所示,可以發現GPIO 0的模組配置較GPIO 1~3不同,而圖中各GPIO module的PIDBCLK則為Debouncing
Clock的輸入訊號,而POINTRPEND1 /2則是用來產生interrupt的訊號。
圖3、GPIO0~3 Module Integeration (AM335x TRM
page 4630)
由圖3可知,GPIO模組操作起來所需要的條件並沒有很多,若是不考慮wake up功能的話,基本上GPIO 0~3功能是一樣的,只需要注意在L4 WakeUP Interconnect和L4 Peripgeral Interconnect的Clock有輸入進GPIO模組,接著只要在GPIO module相對應的register之中進行操作,即可控制pin腳的狀態。
Memory
map of AM335x GPIO module
接著從AM335x之中,查出GPIO對應的Memory Map的位址,以利用mmap進行存取動作
AM335x TRM,page .171,Table 2-2. L4_WKUP
Peripheral Memory Map。
AM335x TRM,page .173~174,Table 2-3. L4_PER
Peripheral Memory Map。
Region Name
|
Start Address
|
End Address
|
Size
|
Description
|
CM_PER
|
0x44E0_0000
|
0x44E0_3FFF
|
0x4000
|
Clock
Module Peripheral Registers
|
CM_WKUP
|
0x44E0_0400
|
0x44E0_04FF
|
0x100
|
Clock
Module Wakeup Registers
|
GPIO0
|
0x44E0_7000
|
0x44E0_7FFF
|
0x1000
|
GPIO register
|
GPIO1
|
0x4804_C000
|
0x4804_CFFF
|
0x1000
| |
GPIO2
|
0x481A_C000
|
0x481A_CFFFF
|
0x1000
| |
GPIO3
|
0x481A_E000
|
0x481A_EFFFF
|
0x1000
|
表2、GPIO Memory map
Enable/Disable
Clock of GPIO module via CM_PER/CM_WKUP register
在Clock上要特別注意,由先前提過的表1可知,GPIO 0 屬於PD_WKUP_L4_WKUP_GCLK的Clock domain,控制Register為CM_WKUP_GPIO0_CLKCTRL,而GPIO 1~3屬於PD_PER_L4LS_GCLK的Clock domain,控制Register為CM_PER_GPIOx_CLKCTRL (x為1~3),要小心不要控制錯了,名字是有差別的。
而GPIO模組基本上會有2組Clock的輸入:Interface Clock與Debouncing Clock,Interface Clock由L4 Iterface提供,100MHz的頻率,而Debouncing Clock則是可選的(不需要就Disable沒關係),為32.768KHz,如果interface clock 沒有Enable,那整組GPIO的register access 都會error,並回傳”Bus Error”的選項。
瞭解要控制的Register之後,接著就是去看他的格式,相對應的頁數列於表3,而基本上這4個reigister的控制參數格式是一模一樣的,如圖4所示,因此我們只需要將Bit 0~1的MODULEMODE欄位設為0x2 (Enable)即可打開相對應GPIO的Clock。
Register Name
|
Page
|
Session
|
CM_WKUP_GPIO0_CLKCTRL
|
983
|
Session
8.1.12.2.3
|
CM_PER_GPIO1_CLKCTRL
|
947
|
Session
8.1.12.1.29
|
CM_PER_GPIO2_CLKCTRL
|
948
|
Session
8.1.12.1.30
|
CM_PER_GPIO3_CLKCTRL
|
949
|
Session
8.1.12.1.31
|
表3、GPIO Clock Register page Reference
而這裡有一個需要注意的欄位,OPTFCLKEN_GPIO_x_GDBCLK (bit 18),這個欄位是用來Enable/Disable Debouncing Clock的,即圖3的PIDBCLK。
圖4、GPIO Clock Register format
mmap程式碼:
於BBBio/BBBio.c,iolib_init fnuction之中,需要map 2+4個map,分別是控制Clokc的:CM_PER與CM_WKUP,和GPIO module的GPIO0~3。
其中需要特別注意CM_WKUP,其memory map位址為0x44E0_0400,這個位址直接下去mmap,會回傳error,同時error code為:EINVAL,這是因為0x44E0_0400這個address並沒有alignment page,這裡的page為4K,所以mmap沒有辦法map;不過這是可以處理的,在BBBio中,先mmap CM_PER (0x44E0_0000)這個register,在透過offset 0x400,存取CM_WKUP,即可mmap CM_WKUP,因為在mmap CM_PER時,其map的length已經涵蓋了CM_WKUP。
cm_per_addr
= mmap(忽略参數) ;
cm_wkup_addr
=(void *)cm_per_addr + 0x400 ;
|
Enable/Disable程式碼:
於BBBio/BBBio.c,BBBIO_sys_Enable_GPIO與BBBIO_sys_Disable_GPIO fnuction之中,
GPIO
register
GPIO
module基本上需要:Input、Output、I/O方向設定,3個功能,而AM335x的GPIO module則是將這些功能透過以下register控制
Action
|
Register Name
|
Offset
|
I/O
Setting
|
GPIO_OE
|
0x134
|
Input
|
GPIO_DATAIN
|
0x138
|
Output
|
GPIO_CLEARDATAOUT
GPIO_SETDATAOUT
GPIO_DATAOUT
|
0x190
0x194
0x13C
|
表4、GPIO Control Register
I/O Setting:
透過GPIO_OE register來控制PIN腳是要Inpout還是Output,一次設定整組的GPIO I/O status,共32bit,每一個bit對應1個腳位,bit設為0代表output,設為1代表Input。
例如:GPIO 0的GPIO_OE register bit 0代表 GPIO 0 [0]這支pin腳,若是寫入0x00000001,代表將pin0腳位設為input,其他設為output。
請特別注意:建議透過邏輯運算| (or),來進行操作,因為有些GPIO不是你可以亂動的,以Beaglebone black來說,其外部接角插槽只有96pin,而且有些pin不是GPIO,代表不是每一個GPIO都有拉出去,若是你亂改到非外拉的腳位狀態,或許會造成系統/裝置錯誤,因此,設定數值前請三思並檢查。
透過GPIO_DATAIN來取得PIN腳目前輸入的狀態,一次讀入整組的GPIO input status,共32bit,每一個bit對應1個腳位,例如GPIO 0的GPIO_DATAIN register bit 0代表 GPIO 0 [0]這支pin腳,因此讀出GPIO_DATAIN的數值之後,你需要自己利用邏輯運算& (and),來判斷需要的腳位狀態。
Output Setting:
Output的設定就比較有趣了,這裡我將他分成2種操作模式:獨立控制和直接控制。
直接控制代表一次操作下,可以一次控制一整組的GPIO狀態,Pin可為0 也可為1。
模式
|
Register
|
解說
|
獨立控制
|
GPIO_CLEARDATAOUT
GPIO_SETDATAOUT
|
設定Pin腳輸出0
設定Pin腳輸出1
|
直接控制
|
GPIO_DATAOUT
|
設定GPIO輸出
|
表5、GPIO Output
Control Register
假設你需要將8個LED 同一時間一次點亮,那你可以使用獨立控制或是直接控制,但若是同一時間下,需要點亮4個,滅掉4個LED,那就只能使用直接控制的功能,否則你必須使用2次獨立控制的register,先下GPIO_SETDATAOUT 亮4個,在下GPIO_CLEARDATAOUT指令滅4個。
一次寫入代表寫入整組的GPIO Output status,共32bit,每一個bit對應1個腳位;要讓某pin腳設為1則在GPIO_SETDATAOUT相對應的bit上寫入1,要設為0,則在GPIO_CLEARDATAOUT上寫入1,你沒看錯,都是寫入1,因為這2個register分別用來進行Output 0和Output 1,寫入1代表此PIN腳要進行設定,寫入0則沒有任何效果。
直接控制的寫入方式就很直覺了,一樣一次寫入代表寫入整組的GPIO Output status,共32bit,每一個bit對應1個腳位;要某pin腳設為1則在GPIO_DATAOUT相對應的bit上寫入1,要設為0,則在GPIO_DATAOUT上寫入0,跟一般的用法無異。
請特別注意:以上運算一樣建議透過邏輯運算| (or),來進行操作,因為有些GPIO不是你可以亂動的,以Beaglebone black來說,其外部接角插槽只有96pin,而且有些pin不是GPIO,代表不是每一個GPIO都有拉出去,若是你亂改到非外拉的腳位狀態,或許會造成系統/裝置錯誤,因此,設定數值前請三思並檢查。
Get BBBio
BBBio為Shabaz開發,Cai,Meng-Lun維護的Beaglebone black I/O library,為一套自由軟體,任何人可以自由更改,沒有授權問題,目前置放於github :
https://github.com/VegetableAvenger/BBBIOlib
圖5為實際範例圖和電路圖,詳細的程式碼請參閱BBBio library中的Demo/Deno_LED_GPIO/
圖5、LED Demo & CircuitLayout
太棒了!
回覆刪除台灣竟然有人玩BBB,玩得如此的棒。
謝謝,還在摸索階段中,歡迎一起討論!!
刪除我有用了你的lib寫了與DS1302 RTC的讀寫, 若你有需要當library內的sample
回覆刪除可以給你
真是太感謝你了! 不過這個library的license是free software,所以demo的部分也會是free software,不知道你會介意嗎?
刪除不會介意!取之free software,用之於社會free software
回覆刪除不過...我英文很破! 屆時還要麻煩你的地方還很多
那要準備哪些東西給你(照片,圖...)
可能要麻煩你把source code發給我!
刪除my email : r7418529@gmail.com
順便告訴我你用的IC或者是module的型號??
圖的話....如果你方便的話,可以請你標明一下接腳嗎? 我再把BBBio library的Visio file發給你。
感謝!