11、S3C2440 裸機 — GPIO

11.1 GPIO 介紹

11.1.1 GPIO 管腳

GPIO 便是輸入輸出端口,S3C2440A 包含了 130 個多功能輸入/輸出口引腳而且它們爲以下顯示的八個端口:linux

  • 端口 A(GPA):25 位輸出端口
  • 端口 B(GPB):11 位輸入/輸出端口
  • 端口 C(GPC):16 位輸入/輸出端口
  • 端口 D(GPD):16 位輸入/輸出端口
  • 端口 E(GPE):16 位輸入/輸出端口
  • 端口 F(GPF):8 位輸入/輸出端口
  • 端口 G(GPG):16 位輸入/輸出端口
  • 端口 H(GPH):9 位輸入/輸出端口
  • 端口 J(GPJ):13 位輸入/輸出端口

GPIO 的功能便是用於 CPU 採集外設信號(INPUT),CPU 輸出控制信號(OUTPUT),還有一種功能稱爲管腳複用功能,便是 GPIO 用於其餘信號功能,好比地址,串口等共呢個,GPIO 屬於 SOC 的內部外設。shell

GPIO 的使用須要寄存器配置。緩存

11.1.2 GPIO 寄存器

  • 端口配置寄存器:GPACON --- GPJCON,即配置輸入或是輸出,仍是配置爲第三功能
  • 端口數據寄存器:GPADAT---GPJDAT,用於數據的寫入或讀取
  • 端口上拉寄存器:GPBUP---GPJUP,端口上拉寄存器控制每一個端口組的使能/禁止上拉電阻。
    • 當相應位爲 0 時使能引腳的上拉電阻。當爲 1 時禁止上拉電阻。
    • 若是使能了上拉電阻,那麼上拉電阻與引腳的功能設置無關(輸入、輸出、DATAn、EINTn 等等)
  • 雜項控制寄存器:
    • 此寄存器控制睡眠模式,USB 引腳和 CLKOUT 選擇的數據端口上拉電阻。
  • 外部中斷控制寄存器:
    • 24 個外部中斷由各類信號方式觸發。
    • EXTINT 寄存器爲外部中斷請求配置信號觸發方式爲低電平觸發、高電平觸發、降低沿觸發、上升沿觸發或雙邊沿觸發。
    • 因爲每一個外部中斷引腳包含一個數字濾波器,中斷控制能夠確認請求信號是否長於 3 個時鐘。

11.2 GPIO 控制 LED 

11.2.1 原理圖

  

  

  • 從原理圖上能夠看出,三個燈的控制是由 GPF4 - GPF6 控制的。
  • 因爲 LED 由 3.3V 高電平供電,則 GPF4- GPF6 引腳必需要設置爲低電平,造成壓差點亮 LED

11.2.2 GPF 控制寄存器

  • GPF 主要涉及到三個寄存器:
    • GPFCON:端口配置寄存器,配置各個 I/O 管腳是輸入/輸出功能,仍是第三功能,此寄存器的地址是 0x56000050
    • GPFDAT:數據寄存器,用於管腳發送或是接收數據,地址是 0x56000054
    • GPFUP:上拉寄存器,地址爲 0x56000058,須要才用這個寄存器
  • 注意 GPF 控制器的復位值,初始化值便是此值。
  • 具體配置查看芯片手冊

11.3 彙編控制 LED

  •  指令的執行時間:
    • 通常單片機指令執行時間是固定的,參考手冊,而在高性能的嵌入式 SOC 中,指令執行時間與各方面的因素有關,好比:緩存,內存,硬盤上的傳輸開銷,指令開銷,因此在高性能 SOC 上討論指令的執行時間沒有意義。
    • 考慮到多發射、超標量、超流水線、亂序執行、追蹤緩存等設計愈來愈複雜,僅評價單條指令耗時比單片機要困可貴多
    • 更由意義的指標是通過統計分析的 CPI、MIPS 數據。
    • 1MHz = 1us
    • 1GHz = 1ns
  • 通常狀況下,裸機中精確延時採用定時器,若是延時在 20 us 下的話,定時器不是太合適,須要彙編輔助完成
  • 若是更小的時間要求,那麼表示硬件沒法知足當前需求

11.4 C語言控制 LED

 makefile多線程

 1 # 獲取當前工做目錄
 2 CURRDIR = $(shell pwd)
 3 
 4 # 頭文件所在目錄
 5 INCDIR = $(CURRDIR)
 6 
 7 # 交叉編譯工具鏈的絕對路徑
 8 CROSS_COMPILE = ~/work/s3c2440/tools/gcc-3.4.5-glibc-2.3.6/bin/arm-linux-
 9 
10 # 編譯器工具
11 AS            = $(CROSS_COMPILE)as
12 LD            = $(CROSS_COMPILE)ld
13 CC            = $(CROSS_COMPILE)gcc
14 CPP            = $(CC) -E
15 AR            = $(CROSS_COMPILE)ar
16 NM            = $(CROSS_COMPILE)nm
17 STRIP        = $(CROSS_COMPILE)strip
18 OBJCOPY        = $(CROSS_COMPILE)objcopy
19 OBJDUMP        = $(CROSS_COMPILE)objdump
20 
21 # 編譯器標識位設置
22 CFLAGS :=
23 AFLAGS :=
24 LDFLAGS :=
25 CFLAGS    :=
26 AFLAGSL    :=
27 
28 # 目標文件設置
29 objs := startup.o led.o
30 
31 all: clean s3c2440.bin
32 
33 
34 # 執行編譯的過程
35 s3c2440.bin: $(objs)
36     $(LD) -Ttext 0x00000000 -o s3c2440_elf $^
37     $(OBJCOPY) -O binary -S s3c2440_elf $@
38     $(OBJDUMP) -D -m arm s3c2440_elf > s3c2440.dis
39 
40 
41 %.o:%.c
42     $(CC)  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding -c -o $@ $<
43 
44 %.o:%.S
45     $(CC)  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding -c -o $@ $<
46 
47 clean:
48     rm -f *.bin *_elf *.dis *.o

startup.S函數

 1 .text
 2 .global _start
 3 
 4 _start:
 5     ldr    r0, =0x53000000         @ WATCHDOG寄存器地址
 6     mov    r1, #0x0
 7     str    r1, [r0]                @ 寫入0,禁止WATCHDOG,不然CPU會不斷重啓
 8 
 9     ldr sp, =1024*4             @ 設置堆棧,注意:不能大於4k, 由於如今可用的內存只有4K
10                                 @ nand flash中的代碼在復位後會移到內部ram中,此ram只有4K
11 
12     bl main                     @ 調用 C 程序的 main 函數
13 
14 halt_loop:
15     b halt_loop

led.c工具

 1 /**
 2  * 將0x56000050 強轉爲 unsigned long 型指針,並取這個地址的值
 3  * volatile 關鍵字:防止編譯器優化,在應用層上多線程變量,在嵌入式中外設寄存器
 4  */
 5 #define GPFCON      (*(volatile unsigned long *)0x56000050)
 6 #define GPFDAT      (*(volatile unsigned long *)0x56000054)
 7 #define GPFUP       (*(volatile unsigned long *)0x56000058)
 8 
 9 /** 設置 GPFCON 的 4 5 6 引腳爲輸出 */
10 #define GPF4_OUT    (1 << (4 * 2))
11 #define GPF5_OUT    (1 << (5 * 2))
12 #define GPF6_OUT    (1 << (6 * 2))
13 
14 static void delay_ms(unsigned long ms);
15 
16 int main(void)
17 {
18     /** 將LED1-3對應的GPF4/5/6三個引腳設爲輸出 */
19     GPFCON = GPF4_OUT | GPF5_OUT | GPF6_OUT;
20 
21     unsigned long i = 0;
22     while(1){
23         delay_ms(500);
24         GPFDAT = (~(i<<4));         // 根據i的值,點亮LED1,2,4
25         if(++i == 8)
26             i = 0;
27     }
28 }
29 
30 static void delay_ms(unsigned long ms)
31 {
32     unsigned int i;
33 
34     while(ms--) {
35         for(i = 0; i < 1200; i++);
36     }
37 }
相關文章
相關標籤/搜索