2013年12月27日 星期五

Beaglebone Black I/O library 開發歷程(三) - GPIO module


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,同時粗略的介紹一下AM335xSystem 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 :

AM335xinterconnect Architecture 2-Level架構,由L3L4組成,而L3則分為L3FL3S,而L4則是分為L4_FASTL4_PERL4_WKUP,結構如圖1所示,由其可看出L4_PERL4_WKUP是掛接在L3_S下,而L4_FAST則是接在L3F下。





1L3 Topology (AM335x TRM page 1231)

GPIO模組則是分佈在L4之中,GPIO 0掛在L4_WKUPGPIO 1~3掛在L4_PER中,整體上如圖2所示。




2L4 Topology (AM335x TRM page 1234)


瞭解GPIO模組所屬的Interconnect Topology有助於瞭解各module間的Clock互動情形,即瞭解module所屬的Clock Domain,像是GPIO 1~3所處的Clock DomainPD_PER_L4LS_GCLK,而GPIO 0 則處在PD_WKUP_L4_WKUP_GCLK這個Clock domain上,而透過圖2L4 Topology布局方式便可以清楚的瞭解為何GPIO模組會處於不同的Clock Domain上。

為了要讓module省電,所以沒有必要使用的moduleClock常處於Disable的狀態,而每一個GPIO模組擁有其各自的register來控制是否Disable Clock,瞭解其Clock domain之後,便可以搜尋其對應的Clock control register,接著才可以在需要使用時,將GPIOClock Enable/Disable,下表為各GPIOClock 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

1GPIO Clock Domain

AM335x GPIO Module Introduction :

AM335x 擁有4GPIO moduleGPIO 0GPIO 1GPIO 2GPIO 3,每一個module32支接腳,故總共有128GPIO的腳位可以使用,每支腳位提供以下的基本功能:
  1. Data Input/ Output
  2. Debounce cell
  3. Synchronous interrupt
  4. Wake-up request (Only GPIO 0)

本筆記主要記錄最基本的Data Input/OutputDebouncing為次章節介紹,而剩餘功能尚未完整測試。

基本上每一組GPIO都提供了1~3的基本功能,而GPIO 0 則額外提供了Wake-Pp的功能,是與其他GPIO較為不同的地方,如圖3所示,可以發現GPIO 0的模組配置較GPIO 1~3不同,而圖中各GPIO modulePIDBCLK則為Debouncing Clock的輸入訊號,而POINTRPEND1 /2則是用來產生interrupt的訊號。

 


3GPIO0~3 Module Integeration (AM335x TRM page 4630)

由圖3可知,GPIO模組操作起來所需要的條件並沒有很多,若是不考慮wake up功能的話,基本上GPIO 0~3功能是一樣的,只需要注意在L4 WakeUP InterconnectL4 Peripgeral InterconnectClock有輸入進GPIO模組,接著只要在GPIO module相對應的register之中進行操作,即可控制pin腳的狀態。


Memory map of AM335x GPIO module

接著從AM335x之中,查出GPIO對應的Memory Map的位址,以利用mmap進行存取動作

AM335x TRMpage .171Table 2-2. L4_WKUP Peripheral Memory Map

AM335x TRMpage .173~174Table 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

2GPIO Memory map
 

Enable/Disable Clock of GPIO module via CM_PER/CM_WKUP register

Clock上要特別注意,由先前提過的表1可知,GPIO 0 屬於PD_WKUP_L4_WKUP_GCLKClock domain,控制RegisterCM_WKUP_GPIO0_CLKCTRL,而GPIO 1~3屬於PD_PER_L4LS_GCLKClock domain,控制RegisterCM_PER_GPIOx_CLKCTRL (x1~3),要小心不要控制錯了,名字是有差別的。

GPIO模組基本上會有2Clock的輸入:Interface ClockDebouncing ClockInterface ClockL4 Iterface提供,100MHz的頻率,而Debouncing Clock則是可選的(不需要就Disable沒關係),為32.768KHz,如果interface clock 沒有Enable,那整組GPIOregister access 都會error,並回傳Bus Error的選項。

瞭解要控制的Register之後,接著就是去看他的格式,相對應的頁數列於表3,而基本上這4reigister的控制參數格式是一模一樣的,如圖4所示,因此我們只需要將Bit 0~1MODULEMODE欄位設為0x2 (Enable)即可打開相對應GPIOClock




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

3GPIO Clock Register page Reference
 

而這裡有一個需要注意的欄位,OPTFCLKEN_GPIO_x_GDBCLK (bit 18),這個欄位是用來Enable/Disable Debouncing Clock的,即圖3PIDBCLK



4GPIO Clock Register format
 

mmap程式碼:

BBBio/BBBio.ciolib_init fnuction之中,需要map 2+4map,分別是控制Clokc的:CM_PERCM_WKUP,和GPIO moduleGPIO0~3

其中需要特別注意CM_WKUP,其memory map位址為0x44E0_0400,這個位址直接下去mmap,會回傳error,同時error code為:EINVAL,這是因為0x44E0_0400這個address並沒有alignment page,這裡的page4K,所以mmap沒有辦法map;不過這是可以處理的,在BBBio中,先mmap CM_PER (0x44E0_0000)這個register,在透過offset 0x400,存取CM_WKUP,即可mmap CM_WKUP,因為在mmap CM_PER時,其maplength已經涵蓋了CM_WKUP



cm_per_addr = mmap(忽略参數) ;

cm_wkup_addr =(void *)cm_per_addr + 0x400 ;

Enable/Disable程式碼:

BBBio/BBBio.cBBBIO_sys_Enable_GPIOBBBIO_sys_Disable_GPIO fnuction之中,
 

GPIO register

GPIO module基本上需要:InputOutputI/O方向設定,3個功能,而AM335xGPIO 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

4GPIO Control Register

I/O Setting

透過GPIO_OE register來控制PIN腳是要Inpout還是Output,一次設定整組的GPIO I/O status,共32bit,每一個bit對應1個腳位,bit設為0代表output,設為1代表Input

例如:GPIO 0GPIO_OE register bit 0代表 GPIO 0 [0]這支pin腳,若是寫入0x00000001,代表將pin0腳位設為input,其他設為output

請特別注意:建議透過邏輯運算| (or),來進行操作,因為有些GPIO不是你可以亂動的,以Beaglebone black來說,其外部接角插槽只有96pin,而且有些pin不是GPIO,代表不是每一個GPIO都有拉出去,若是你亂改到非外拉的腳位狀態,或許會造成系統/裝置錯誤,因此,設定數值前請三思並檢查。

 Input Setting

透過GPIO_DATAIN來取得PIN腳目前輸入的狀態,一次讀入整組的GPIO input status,共32bit,每一個bit對應1個腳位,例如GPIO 0GPIO_DATAIN register bit 0代表 GPIO 0 [0]這支pin腳,因此讀出GPIO_DATAIN的數值之後,你需要自己利用邏輯運算& (and),來判斷需要的腳位狀態。

Output Setting

Output的設定就比較有趣了,這裡我將他分成2種操作模式:獨立控制直接控制

 獨立控制代表一次操作下,只可以控制腳位是輸出0還是1

直接控制代表一次操作下,可以一次控制一整組的GPIO狀態,Pin可為0 也可為1



模式

Register

解說

獨立控制

GPIO_CLEARDATAOUT

GPIO_SETDATAOUT

設定Pin腳輸出0

設定Pin腳輸出1

直接控制

GPIO_DATAOUT

設定GPIO輸出

5GPIO Output Control Register

假設你需要將8LED 同一時間一次點亮,那你可以使用獨立控制或是直接控制,但若是同一時間下,需要點亮4個,滅掉4LED,那就只能使用直接控制的功能,否則你必須使用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,因為這2register分別用來進行Output 0Output 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

BBBioShabaz開發,Cai,Meng-Lun維護的Beaglebone black I/O library,為一套自由軟體,任何人可以自由更改,沒有授權問題,目前置放於github :

https://github.com/VegetableAvenger/BBBIOlib

 LED Demo

5為實際範例圖和電路圖,詳細的程式碼請參閱BBBio library中的Demo/Deno_LED_GPIO/




 

5LED Demo & CircuitLayout