字元設備字元設備 (char device) 和普通檔案系統的區別 : 普通檔案系統可以來回讀 / 寫, 而大多字元設備僅僅是資料通道, 只能順序讀 / 寫 應用程式使用標準系統調用打開 (open) 讀取(read) 寫(write) 和關閉 (close), 完全好像這個設備是一個普通檔一樣 初

Similar documents
华恒家庭网关方案

static struct file_operations gpio_ctl_fops={ ioctl: gpio_ctl_ioctl, open : gpio_open, release: gpio_release, ; #defineled1_on() (GPBDAT &= ~0x1) #def

The golden pins of the PCI card can be oxidized after months or years

<4D F736F F D20C7B6C8EBCABDCFB5CDB3BFAAB7A2CAB5D1E9CBC42E646F63>

C/C++ - 文件IO

Microsoft Word - 实用案例.doc

CC213

epub 33-8

Microsoft PowerPoint - C_Structure.ppt

CC213

0 0 = 1 0 = 0 1 = = 1 1 = 0 0 = 1

untitled

プログラムの設計と実現II

Microsoft Word - Mail2000_SecurityPatch_

新・明解C言語入門編『索引』

投影片 1

TPM BIOS Infineon TPM Smart TPM Infineon TPM Smart TPM TPM Smart TPM TPM Advanced Mode...8

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

新・解きながら学ぶC言語


第一章 基礎篇 第一章基礎篇 1-1 Linux 入門 Linux 究竟是什麼? 用最簡單的話說,Linux 是一個作業系統 它是一位赫爾辛基大學學生 Linus Torvalds(Linux 是 Linus's UNIX 的縮寫 ) 在 1991 年 10 月創造的 Linux 本身實

(Microsoft Word - wes _\246p\246\363\250\317\245\316LED\277O\305\343\245\334\252\254\272A.doc)

新版 明解C言語入門編

A Preliminary Implementation of Linux Kernel Virus and Process Hiding

C++ 程式設計

09 Linux Linux Linux Linux 009.indd /9/4 下午 12:11:10

EK-STM32F

Microsoft Word - Prog1-981.docx

C 1

提纲 1 2 OS Examples for 3

投影片 1

投影片 1

Microsoft Word - ACL chapter02-5ed.docx

投影片 1

1

第一章 概论

( )... 5 ( ) ( )

Lab GPIO:嵌入式硬體平台輸出入實驗

投影片 1

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

NEXT SDT2.51 C:\ARM251 SDT2.51 ARM SDT 2.51 ARM PROJECT MANAGER SDT 2

第一次寫Linux Driver就上手

C语言的应用.PDF

1

Microsoft PowerPoint - 移植Qt for Embedded Linux

untitled

PICkit2 燒寫器編程器調試器

<4D F736F F D20C7B6C8EBCABD6C696E7578BBF9B4A1CAB5D1E92E646F63>

JLX

Microsoft Word - PS2_linux_guide_cn.doc

FY.DOC

Microsoft PowerPoint - 9-Linux Kernel.ppt

一个开放源码的嵌入式仿真环境 ― SkyEye

1

新版 明解C++入門編

逢 甲 大 學

ebook35-14

<A4E2BEF7B4FAB8D5B3F8A F52322E786C7378>

1

Abstract arm linux tool-chain root NET-Start! 2

Application Note Format

CU0594.pdf

ebook50-15


网名 鱼树 的学员聂龙浩, 学习 韦东山 Linux 视频第 2 期 时所写的笔记很详细, 供大家参考 也许有错漏, 请自行分辨 目录 驱动框架分析 内核中的理解 : 内核这样理解 :... 2 RTC 测试 RTC:

Python a p p l e b e a r c Fruit Animal a p p l e b e a r c 2-2

根據 一手住宅物業銷售條例 第 60 條所備存的成交記錄冊 Register of Transactions kept for the purpose of section 60 of the Residential Properties (First-hand Sales) Ordinance 第

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

C/C++ - 字符输入输出和字符确认

自由軟體教學平台

Microsoft Word - cr_xi_supported_platforms_tw.doc

第3章.doc

P4i45GL_GV-R50-CN.p65

C/C++语言 - C/C++数据

Microsoft PowerPoint - Chapter7-DriverDevices.ppt

Ch03_嵌入式作業系統建置_01

考 試 日 期 :2016/04/24 教 室 名 稱 :602 電 腦 教 室 考 試 時 間 :09: 二 技 企 管 一 胡 宗 兒 中 文 輸 入 四 技 企 四 甲 林 姿 瑄 中 文 輸 入 二 技 企 管 一

ActiveX Control

Microsoft Word - ISSFA-0109_B_SM59264_WDT_ APN_TC_.doc

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

Microsoft Word - Delta Controller ASCII_RTU_TC

(Microsoft Word -

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

untitled

C C

audiogram3 Owners Manual

***********************************************************************************

01 用 ActionScript 3.0 開始認識 Flash CS3 Flash 是應用在網路上非常流行且高互動性的多媒體技術, 由於擁有向量圖像體積小的優點, 而且 Flash Player 也很小巧精緻, 很快的有趣的 Flash 動畫透過設計師的創意紅遍了整個網際網路 雖然很多人都對 Fl

AutoCAD 用戶如何使用 ArchiCAD

Microsoft Word - InoTouch Editor编程软件手册 doc

Microsoft Word - RM Domingo for Linux針對Linux Kernel、Device Driver的除錯實習.doc

PIC_SERVER (11) SMTP ( ) ( ) PIC_SERVER (10) SMTP PIC_SERVER (event driven) PIC_SERVER SMTP 1. E-

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha

bingdian001.com

Microsoft Word - 正文.doc

untitled

untitled

投影片 1

Microsoft Word - linux命令及建议.doc

投影片 1

Transcription:

第十章驅動程式的設計 為了瞭解嵌入式 Linux 系統中驅動程式的開發過程, 以及掌握如何運行和載入驅動程式, 在嵌入式 Linux 系統中嘗試添加一個驅動程式於 Linux 核心程式中 10-1.linux 設備驅動程式概述 設備驅動可以理解為作業系統的一部分, 對於一個特定的硬體設備來說, 其對應的 設備驅動程式是不同的 比如網卡, 音效卡, 鍵盤, 滑鼠以及顯卡等 對於作業系統來說, 掛 接的設備越多, 所需要的設備驅動程式也越多 對於嵌入式系統設計過程中, 沒有通用的 驅動程式可使用 設備驅動程式是 Linux 核心的重要組成部分 像作業系統的其他部分一樣, 驅動 程式在一個高優先順序的環境下工作, 如果發送錯誤則可能會引起嚴重的問題 系統 調用 (System call) 是作業系統核心與應用程式之間的介面 驅動程式則是作業系統 核心與機器硬體的介面 設備驅動程式能夠直接訪問硬體的代碼, 必須為應用程式提供系統調用 (System call) 以便應用程式能訪問設備 在 LINUX 中, 主要有三種設備即 : 字元設備 區 塊設備和網路設備 與此相關主要有三類設備驅動程式 : 字元設備驅動程式, 區塊設備 驅動程式和網路設備驅動程式 他們的系統調用是一致的, 採用統一的介面, 此介面定義在資料結構 file_operations 中 應用程式使用設備就像使用讀寫普通的 檔一樣方便, 例如使用相同的 open( ) close() read() write() 等, 透過這些指令 的使用真正做到與設備無關 通常 Linux 驅動程式介面分為如下四層 : (1) 應用程式進程與核心的介面 ; (2) 核心與檔案系統的介面 ; (3) 檔案系統與設備驅動程式的介面 ; (4) 設備驅動程式與硬體設備的介面 每個驅動程式都有個 file_operations 的資料結構, 包含了一系列的函數指標, 可以指 向自己所開發的介面如 open() 等 核心中有兩個表, 一個用於字元設備驅動程式 ; 一 個用於區塊設備驅動程式 這個兩個表用於保存指向 file_operation 資料結構的指 標, 驅動程式內部函數的位址保存在這一結構 1

字元設備字元設備 (char device) 和普通檔案系統的區別 : 普通檔案系統可以來回讀 / 寫, 而大多字元設備僅僅是資料通道, 只能順序讀 / 寫 應用程式使用標準系統調用打開 (open) 讀取(read) 寫(write) 和關閉 (close), 完全好像這個設備是一個普通檔一樣 初始化字元設備時, 它的設備驅動程式向 Linux 登記, 並在字元設備向量表中增加一個 device_struct 資料結構條目, 這個設備的主設備識別字 ( 例如, 對於 tty 設備的主設備識別字是 4) 用做這個向量表的索引 一個設備的主設備識別字是固定的 chrdevs 向量表維護已經登記的字元設備檔 區塊設備區塊設備 (block device) 是檔案系統的物質基礎, 它也支援像檔一樣訪問 這種為打開的區塊特殊檔提供正確的檔案系統操作組的機制和字元設備的十分相似 Linux 用 blkdevs 向量表維護已經登記的區塊設備檔 它像 chrdevs 向量表一樣, 使用設備的主設備號作為索引 與字元設備不同, 區塊設備進行分類,SCSI 是其中一類, 而 IDE 是另一類 網路設備驅動對於每一個網路介面, 都用一個 device 的資料結構表示 通常, 網路設備是一個物理設備, 如乙太網卡, 但軟體也可以作為網路設備, 典型的是回送設備 (loopback). 在核心啟動時, 系統通過網路設備驅動程式登記已經存在的網路設備 設備用標準的支援網路的機制來把收到的資料轉送到相應的網路層 關於網路設備驅動更詳細的資訊請查看相關資料 10-2. 設備驅動程式的設備號 入口點以及載入 Linux 系統通過設備號來區分不同設備 設備號由兩部分組成 : 主設備號和次設備號 主設備號指明對應哪些設備驅動, 這種對應關係是固定不變並作為核心資源的一部份存在 需要注意的是, 同一個主設備號可以對應兩個不同的設備驅動, 一個可以是字元設備另一個可以是區塊設備 次設備號區分被一個設備驅動控制下的某個獨立的設備 比如, 同一個類型的 USB 2

設備可以在系統中有幾個, 它們使用次設備編號加以區分, 而設備驅動可以只對應一個 在 /proc/devices 中列出了系統中處於活動狀態設備的主設備號, 所謂的活動狀態是指與該設備對應的設備驅動已經被系統核心裝載 設備入口點也可以理解為 設備檔控制碼, 一個設備的入口點和磁片上的普通檔案系統一樣, 可以刪除 (rm), 移動 (mv) 和複製 (cp) 等 我們可以在檔案系統中使用 mknod 命令創建一個設備入口點或者通過系統調用 mknof 來創建 在檔案系統中創建了設備入口點並沒有代表回應的設備驅動和硬體已經準備好, 只是代表了和設備驅動通信的一部分 下面給一個創建字元設備入口點的實例 : mknod /dev/testchar c 100 0 其中 c 代表字元設備, 如果想創建塊設備則用 b 代替 c 參數 100 代表該設備的主設備號,0 代表該設備的次設備號 對於現有 Linux 作業系統,/dev 目錄是必不可少的, 這個目錄包含了所有 Linux 系統所知道的字元設備, 區塊設備和網路設備 操作字元設備的方法非常簡單 打開一個字元設備就像打開一個文字檔案一樣, 只不過讀 / 寫 檔 的操作實際上是操作設備的過程, 可以使用正常的檔操作命令 cat 或者 shell 重定向語法實現和設備的資料交換 在 Linux 下載入驅動程式可以採用動態和靜態兩種方式 靜態載入就是把驅動程式直接編譯到核心裡, 系統啟動後可以直接調用 靜態載入的缺點是調試起來比較麻煩, 每次修改一個地方都要重新編譯下載核心, 效率較低 動態載入利用了 Linux 的模組程式 (module) 特性, 可以在系統啟動後用 insmod 命令把驅動程式 (.o 檔 ) 添加上去, 在不需要的時候用 rmmod 命令來卸載 在嵌入式產品裡可以先用動態載入的方式來調試, 調試完畢後再編譯到核心裡 設備驅動程式在載入時首先需要調用入口函數 init_module(), 該函數完成設備驅動的初始化工作, 比如暫存器置位元, 結構體附值等一系列工作 其中最重要的一個工作就是向核心註冊該設備 對於字元設備調用 register_chrdev() 完成註冊, 對於區塊設備需要調用 register_blkdev() 完成註冊 註冊成功後, 該設備獲得了系統分配的主設備號, 自定義的次設備號, 並建立起與檔案系統的關聯 設備在卸載的時候, 需要回收回應的資源, 令設備的回應暫存器值重定並從系統中登出該設備 系統調用部分則是對設備的操作過程, 比如 open,read,write,ioctl 等操作 3

10-3.Linux 下字元設備驅動的添加範例 本節將以實例的方式介紹如何在核心裡添加一個字元設備驅動 功能說明 : 在模組載入的時候輸出模組載入提示資訊 模組卸載的時候輸出模組卸載提示資訊 1. 字元設備的驅動原始程式 mydrv.c: 編寫符合上面功能的驅動根源程式 mydrv.c, 根源程式的代碼如下 : #include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/iobuf.h> #include <linux/kernel.h> #include <linux/major.h> #include <asm/uaccess.h> #include <asm/hardware.h> #include <asm/arch/mainstone.h> #include <asm/io.h> #include <linux/vmalloc.h> #define IOPORT_MAJOR 220 /* 定義主設備號 */ int mydrv_open(struct inode*,struct file*); // 函數聲明 int mydrv_release(struct inode*,struct file*); int mydrv_ctl(struct inode*,struct file*,unsigned int,unsigned long); static struct file_operations mydrv_ctl_fops={ ioctl: mydrv_ctl, open : mydrv _open, release: mydrv _release, }; 所有的作業系統將硬體設備當作檔處理, 所有外設的操作就封裝在這個 file_operations 結構體裡面就是檔的 open/read/write/close 等操作, 剩餘的都放到一個 ioctl 函數裡面做處理 } static int init mydrv_init(void) { int err=0; err=register_chrdev(ioport_major,"mydrv",& mydrv _ctl_fops); if(err) { printk("fail to register mydrv device.\n"); return -1; } printk("success to register mydrv device.\n"); return 0; int mydrv_open(struct inode *inode,struct file *fllp) { printk("open mydrv devices\n"); return 0; 4

} int mydrv_release(struct inode *inode,struct file *filp) { printk("release this mydrv device\n"); return 0; } int mydrv_ctl_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg) { printk("in mydrv_ctl function.\n"); return 0; } module_init(mydrv_init); module_exit(mydrv_release); 驅動程式中相關函數函數說明 file_operations 資料結構 inode 資料結構和 file 資料結構 : 核心通過 file 結構識別設備, 通過 file_operations 資料結構提供檔案系統的入口點函數, 也就是訪問設備驅動的函數 file_operations 定義在 <linux/fs.h> 中的函數指標表 這個結構中的每一個成員的名字都對應著一個系統調用 在應用程式利用系統調用 (System call) 對設備檔進行諸如 read/write 操作時, 系統調用通過設備檔的主設備好找到相應的設備驅動程式, 然後讀取這個資料結構相應的函數指標, 接著把控制權交給該函數, 這是 Linux 的設備驅動程式工作的基本原理 從某種意義上說, 寫驅動程式的任務之一就是完成 file_operations 中的函數指標 檔案系統處理的檔所需要的資訊在 inode( 索引結點 ) 資料結構中 inode 資料結構提供了關於特別設備檔 /dev/drivername, 這裡的 DriverName 可能是任何一個設備檔, 如 hda0 的資訊 file 資料結構主要用於與檔案系統對應的設備驅動程式使用 當然, 其他設備驅動程式也可以使用, 它提供有關被打開的檔的資訊 register_chrdev 函數設備驅動程式所提供的入口點, 在設備驅動程式初始化的時候向系統進行登記, 以便系統適當的時候調用 在 Linux 系統中, 通過調用 register_chrdev 向系統註冊字元型設備驅動程式 register_chrdev 在 fs/devices.c 資料中的定義如下 int register_chrdev(unsigned int major,const char *name,struct file_operations *fops) 5

參數中的 major 是為設備驅動程式向系統申請的主設備好, 如果 major 為 0, 則系統為該設備驅動程式動態分配一個主設備號, 不過系統分配的這個主設備是臨時的 在這裡我們的 major 為 220(IOPORT_MAJOR), 這樣該字元設備驅動程式的主設備號為 220,name 是設備名, 這裡設備名為 mydrv fops 就是前面所說的對各個調用的入口的說明, 在這裡,fops 為 mydrv_ctl_fops register_chrdev 函數返回 0 表示成功, 返回 -INVAL 表示申請的主設備號非法, 一般來說是主設備號大於系統所允許的最大設備號 返回 -EBUSY 表示所申請的主設備號正被其他設備驅動程式使用 如果動態分配主設備號成功, 則此函數將返回所分配的主設備號 如果 register_chardev 操 作成功, 則設備名就會出現在 /proc/devices( 教學平台的嵌入式 Linux 平台下 ) 檔 中, 可以通過 cat /proc/devices 來查看工作設備的資訊 該驅動程式的 Makefile 的檔如下 : ############################################################################ CROSS= /usr/local/arm/3.3.2/bin/arm-linux- CFLAGS=-D KERNEL CFLAGS+=-DMODULE CFLAGS+=-I/home/dlp/dma270l/linux-2.6.9/include CFLAGS+=-I/ home/dlp/dma270l/linux-2.6.9/include/linux CFLAGS+=-I/usr/local/arm/3.3.2/arm-linux/include CFLAGS+=-Wall -Wstrict-prototypes -Wno-trigraphs -Os -mapcs CFLAGS+=-fno-strict-aliasing -fno-common -fno-common -pipe -mapcs-32 CFLAGS+=-march=armv4 -mtune=arm9tdmi -mshort-load-bytes -msoft-float CFLAGS+=-DKBUILD_BASENAME=mydrvdrv all:mydrvdrv.o mydrvdrv.o: mydrvdrv.c $(CROSS)gcc $(CFLAGS) -c -o mydrvdrv.o mydrvdrv.c clean: rm -f *.o ############################################################################ 注意 :1 CROSS=/usr/local/arm/3.3.2/bin/arm-linux- 交叉編譯器的位置要設置正確 2)CFLAGS+=-I/home/dlp/dma270l/linux-2.6.9/include CFLAGS+=-I/ home/dlp/dma270l/linux-2.6.9/include /linux CFLAGS+=-I/usr/local/arm/3.3.2/arm-linux/include 這幾個函式庫檔的路徑也要設置正確 將 mydrv.c 和這個 Mafile 放置在同一個新建目錄下, 進入這個目錄, 輸入 make 後, 編譯成功後將在這個目錄下生成一個 mydrv.ko 的資料 將 mydrv.ko 複製到 /tmp 目 錄下 動態載入設備驅動模組 : #insmod mydrv.ko 如果載入成功, 可以通過 cat /proc/devices 查看該設備的相關資訊 6

卸載設備驅動模組 : #rmmod mydrv 該驅動相應的測試應用程式 mydrv_test.c mydrv_test.c 測試程式的原始程式碼如下 : #include <stdio.h> #include <stdlib.h> //system #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <linux/delay.h> #include <sys/ioctl.h> #define DEVICE_MYDRVTEST "/dev/mydrv" // 設備節點 int main(int argc, char *argv[]) { int fd; int val=-1; fd=open(device_ MYDRVTEST,O_RDONLY);// 打開設備 if(fd<0) { } perror("can not open device"); exit(1); } ioctl(fd,0,10); close(fd); return 0; 將 mydrv_test.c 放置在一個新建目錄下, 進入該目錄下, 輸入命令 : /usr/local/arm/3.3.2/bin/arm-linux-gcc o mydrv_test mydrv_test.c 編譯成功後, 將在該目錄下生成 mydrv_test 可執行檔, 要注意交叉編譯工具 arm-linux-gcc 的路徑要設置正確, 這裡是 /usr/local/arm/3.3.2/bin 驅動程式的功能測試步驟如下 : (1) 先讓 DMA-PXA270L 開發板平台進入 Linux 環境, 利用超級終端來顯示,Linux 進入命令行的模式下 (2) 輸入命令 cd /tmp, 進入 tmp 目錄, 因為 /tmp 是在 SDRAM 中, 可以放資料 (3) 將 mydrv.o 和 mydrv_test 複製到 /tmp 目錄下 (4) 複製完成後, 接下來我們要進行真正的載入和運行的工作了 改變 mydrv_test 的屬性, 命令如下 : tmp#chmod 755 mydrv_test (5) 載入 mydrv.o 模組 :insmod mydrv.o 7

(6) 建立 mydrv 設備節點 :mknod /dev/mydrv c 220 0 /dev/mydrv 為該設備驅動程式的設備名,c 表明該設備為字元設備,220 為該設備的 主設備編號,0 為次設備編號 (7) 執行 mydrv_test 程式 :./mydrv_test mydrv_test 程式運行起來後, 有相應的功能選項說明 上面的步驟只是教你如何將自己的驅動和引用程式添加到根檔案系統中, 根檔案系統運行後, 要驗證該驅動, 可參閱以上步驟 如果需要自動載入驅動, 則需要 將相關命令添加到 linuxrc 資料中 10-4 LED 跑馬燈實驗 此實驗目的是瞭解 PXA270 的 I/O 埠特性, 以及掌握 PXA270 的 I/O 埠的使用 PXA27X 系列處理器通常情況下有 121 個可程式化功能輸入 / 輸出 GPIO 埠接腳, 但是在 PXA270 處理器只有 119 個可程式化功能輸入 / 輸出 GPIO 埠接腳, 其中的 GPIO119 與 GPIO120 兩埠沒被引出 這些接腳是 <GPIO0-118>, 其特性如下表 : 每一個埠都可以有軟體設置來滿足各種系統配置和設計需求 在啟動程式之前你必須定義每個接腳的功能 如果接腳沒有配置為可程式化功能, 這個接腳被配置為 I/O 埠 GPIO 接腳的控制暫存器總共有 36 個相應的 32 位暫存器, 暫存器說明如下 : 狀態暫存器 (GPLRx) GPIO 的狀態暫存器 GPLR 可以監視每一個 GPIO 接腳的狀態 ( 輸入或輸出 ), 共有四個暫存器 GPLR0~GPLR3 控制暫存器 (GPSRx,GPCRx) 如果埠配置為輸出埠, 資料能被寫到控制暫存器對應的位元 控制暫存器 GPSR 8

定義為位置每一個接腳的功能, 共有四個暫存器 GPSR0~GPSR3; 控制暫存 器 GPCR 定義為清零每一個接腳的功能, 共有四個暫存器 GPCR0~GPCR3 埠配置暫存器 (GPDRx) 在 PXA270 中, 大部分的接腳是可程式化的 所以, 對於每個接腳要求定義一個功能 埠控制暫存器 (GPDR) 定義每一個接腳為輸入或輸出的功能, 共有四個暫存器 GPDR0~GPDR3 上升緣 / 下降緣監視暫存器 (GRERx & GFERx) 埠上升緣 / 下降緣監視暫存器控制著每個埠的上升緣 / 下降緣監視的使能或禁止 上升緣監視暫存器 GRER(GRER0~GRER3) 對應每個接腳的監視上升緣致能 ; 下降緣監視暫存器 GFER(GFER0~GFER3) 對應每個接腳的監視下降緣使能 邊緣狀態暫存器 (GEDRx) GPIO 的邊緣狀態暫存器 GEDR 可以監視每一個 GPIO 接腳邊緣的狀態 ( 上升 下降 ), 共有 4 個暫存器 GEDR0~GEDR3 可程式化功能暫存器 (GAFR_Lx, GAFR_Ux) 可程式化功能暫存器配置每個 GPIO 接腳為通用的 IO 介面或者是多功能暫 存器, 共有 8 個暫存器 本實驗涉及到的 I/O 埠暫存器介紹 在本實驗中, 由埠 GPIO3 GPIO4 控制核心板上的 D4 D5 兩個 LED 指示燈, 9

埠 GPIO19 GPIO99 GPIO188 GPIO89 控制底板上的 D3 D4 D5 D6 四個 LED 指示燈 主要涉及 GPIO 埠的控制暫存器有 GPDR GPSR GPCR GAFR_L GAFR_U GPIO 埠的第一組暫存器位址和位定義如下, 其他的位址和位元定義及詳細資訊可查看 PXA270 用戶技術手冊 Register Address R/W Description GPDR0 0x40E0000C R/W Set Pin Direction 0=Pin configured as an input 1=Pin configured as an output GPDR2 0x40E00014 R/W Set Pin Direction 0=Pin configured as an input 1=Pin configured as an output GPDR3 0x40E0010C R/W Set Pin Direction 0=Pin configured as an input 1=Pin configured as an output GPSR0 0x40E00018 W Set Output Pin State 0=Pin level unaffected 1=Pin level high(one) GPSR2 0x40E00020 W Set Output Pin State 0=Pin level unaffected 1=Pin level high(one) GPSR3 0x40E00118 W Set Output Pin State 0=Pin level unaffected 1=Pin level high(one) GPCR0 0x40E00024 W Clear Output Pin State 0=Pin level unaffected 1=Pin level low(zero) GPCR2 0x40E0002C W Clear Output Pin State 0=Pin level unaffected 1=Pin level low(zero) GPCR3 0x40E00124 W Clear Output Pin State 0=Pin level unaffected 1=Pin level low(zero) 10

GAFR0_U 0x40E00058 R/W As alternate functions or generic GPIO pin 0b00=Used as a general-purpose I/O 0b01=Used for its alternate funtion 1. 0b10=Used for its alternate funtion 2. 0b11=Used for its alternate funtion 3. GAFR2_U 0x40E00068 R/W As alternate functions or generic GPIO pin 0b00=Used as a general-purpose I/O 0b01=Used for its alternate funtion 1. 0b10=Used for its alternate funtion 2. 0b11=Used for its alternate funtion 3. GAFR3_L 0x40E0006C R/W As alternate functions or generic GPIO pin 0b00=Used as a general-purpose I/O 0b01=Used for its alternate funtion 1. 0b10=Used for its alternate funtion 2. 0b11=Used for its alternate funtion 3. 埠配置暫存器 GPDR0 11

埠配置暫存器 GPDR2 埠配置暫存器 GPDR3 控制暫存器 GPSR0 12

控制暫存器 GPSR2 控制暫存器 GPSR3 13

控制暫存器 GPCR0 控制暫存器 GPCR2 14

控制暫存器 GPCR3 可程式化功能暫存器 GAFR0_U 15

可程式化功能暫存器 GAFR2_U 可程式化功能暫存器 GAFR3_L 16

LED 跑馬燈實驗 4. 個 LED 指示燈的介面電路 4 個 LED 指示燈的介面電路如下 : 實驗步驟 (1) DMA-PXA270L 開發板開機重新啟動, 進入 blob 命令終端 ; (2) 在 blob 終端輸入 ledflash 命令, 運行 led 跑馬燈實驗 (3) 觀察底板上的 D3 D4 D5 D6 LED 燈 17

跑馬燈程式編程實例 設置 D3 D4 D5 D6 對應埠 GPIO19 GPIO99 GPIO188 GPIO89 功能為一般 GPIO 方向為輸出 : // GAFR0_U ~(0xc0); uregtempvalue = (ReadReg(xlli_GPIOREGS_PHYSICAL_BASE, & xlli_gafr0_u_offset)) WriteReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gafr0_u_offset, uregtempvalue); // GAFR2_U 18

9-5 GPIO 按鍵實驗 編寫一個通過 GPIO 實現的按鍵控制程式 實驗目的 瞭解 GPIO 按鍵實現原理 學習 GPIO 控制程式的編寫 獨立式按鍵原理介紹 : 一個 IO 埠接一個按鍵到另外一個輸出為低的 IO 埠, 並通過一電阻上拉至高電位, CPU 根據相關 IO 埠的電平來判斷是否有鍵按下 當無鍵按下時,IO 埠被拉至高電位, 當有鍵按下時,IO 埠被按鍵短路到低電位 IO 埠, 此時 IO 埠呈低電位,CPU 讀取到該埠狀態, 識別到相應的鍵按下而去執行相應的程式 本設計是通過一個 GPIO 實現上拉的功能 相關 GPIO: KEY_IN0 KEY_IN1 KEY_IN2 KEY_IN3 分別對應與 GPIO97 GPIO102 GPIO101 GPIO100 相連接,KEY_OUT0 與 GPIO96 相連接, 在沒有按鍵按下的時起到拉高 IO 埠的作用 GPDR: 設置 GPIO 的方向 ; 19

GPSR: 設置 GPIO 為高電位 ; GAFR: 設置 IO 埠的基本功能 : 20

實驗步驟 DMA-PXA270L 開發平台開機重啟, 進入 blob 命令終端介面 ; 在 blob 終端輸入 keytest 命令, 運行 GPIO 按鍵實驗 分別按下 DMA-PXA270L 底板上的 S1 S2 S3 S4 進行測試, 終端會列印相關資訊 : 21

7-5.6 GPIO 按鍵程式編程實例 GPIO97 GPIO102 GPIO101 GPIO100 GPIO96 設置為一般 GPIO 功能 : uregtempvalue = (ReadReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gafr3_l_offset)) & ~(0x3f0f); WriteReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gafr3_l_offset, uregtempvalue); // GAFR3_L GPIO97 GPIO102 GPIO101 GPIO100 設置為輸入方向,GPIO96 設置為輸出方向 : uregtempvalue = (ReadReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gpdr3_offset)) & ~(0x72); WriteReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gpdr3_offset, uregtempvalue); // GPDR3 uregtempvalue = (ReadReg(xlli_GPIOREGS_PHYSICAL_BASE, 22

xlli_gpdr3_offset)) (0x1); WriteReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gpdr3_offset, uregtempvalue); // GPDR3 GPIO96 設置為輸出低電位 : WriteReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gpcr3_offset, 0x1); // GPCR3 讀取 GPLR 暫存器, 判斷 GPIO97 GPIO102 GPIO101 GPIO100 是否 為低電位, 是低電位說明對應按鍵被按下 : uregtempvalue = (ReadReg(xlli_GPIOREGS_PHYSICAL_BASE, xlli_gplr3_offset)) & (0x72); switch (uregtempvalue) { case 0x70: printf("key_in0 (S1) DOWN.\n"); break; case 0x62: printf("key_in3 (S4) DOWN.\n"); break; case 0x52: printf("key_in2 (S3) DOWN.\n"); break; case 0x32: printf("key_in1 (S2) DOWN.\n"); break; default: printf("no KEY DOWN.\n"); } 上面是關於該實驗涉及到的部分代碼, 完整的代碼請參閱 dma-blob-xscale.tar.gz 原始碼 23