pcDuino裸板程序-led

最近調驅動時,調試led時遇到了點問題,因而回過頭來再寫個led裸板程序。在我寫的pcDuino第一個裸板程序uart的基礎上,再寫個led裸板程序仍是很輕鬆的。不少人以爲沒有必要寫什麼pcDuino裸板程序,以爲沒啥意義。我以爲能夠用來熟悉硬件,特別是想作底層驅動開發,以及系統移植,熟悉底層硬件仍是有用的。其實作底層驅動開發,也是跟硬件打交道,硬件相關的操做和裸板程序是同樣的。下面介紹怎樣在pcDuino上跑一個最簡單的led裸板程序。php

開發環境:
系統:ubuntu 10.04.4
單板:pcDuino
編譯器:arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2linux

目標:實現pcDuino上的TX_LED閃爍ubuntu

1、硬件介紹ide

仔細看pcDuino上的原理圖和pcDuino的手冊,發現兩者不是徹底對應的,仍是以原理圖爲準。根據原理圖知道TX_LED是接到PH15上,能夠當作普通IO口用,不須要連跳線工具

2、編寫源代碼oop

主要是看手冊30.Port Controller,根據手冊寫led初始化程序主要包括設爲輸出、是能上拉及Multi-Driving寄存器設置。包括start.S、main.c、clock.c、clock.h、Makefile,下面貼出所有代碼測試

文件start.S:ui

  1. <p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">[plain] view plaincopyprint?.global _start</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">_start:
  2. ldr sp, =0x00007f00</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">b main</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">.global _start</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">_start:
  3. ldr sp, =0x00007f00</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">b main</p>
複製代碼

文件main.c:google

  1. <p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">[plain] view plaincopyprint?#include 「clock.h」</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">#define PH_CFG1 (*(volatile unsigned int *)0x01c20900)
  2. #define PH_DAT (*(volatile unsigned int *)0x01c2090C)
  3. #define PH_DRI (*(volatile unsigned int *)0x01c20910)
  4. #define PH_PULL (*(volatile unsigned int *)0x01c20918)
  5. void gpio_init()
  6. {
  7. /*PCDUINO GPIO4–PH9:
  8. *bit[6:4]:PH9_SELECT 001:OUTPUT
  9. *PCDUINO GPIO5–PH10:
  10. *bit[10:8]:PH10_SELECT 001:OUTPUT
  11. */
  12. PH_CFG1 |= ((0×1<<4)|(0×1<<8)|(0X1<<28));
  13. PH_DRI = 0XFFFFFFFF;
  14. PH_PULL = 0X55555555;
  15. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">void delay()
  16. {
  17. volatile int i = 0×300000;
  18. while (i–);
  19. }
  20. int main(void)
  21. {
  22. char c;
  23. clock_init(); /* 初始化時鐘 */
  24. gpio_init();</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">while (1)
  25. {
  26. PH_DAT = 0×00;
  27. delay();
  28. PH_DAT = 0xffff;
  29. delay();
  30. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">return 0;
  31. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">#include "clock.h"</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">#define PH_CFG1 (*(volatile unsigned int *)0x01c20900)
  32. #define PH_DAT (*(volatile unsigned int *)0x01c2090C)
  33. #define PH_DRI (*(volatile unsigned int *)0x01c20910)
  34. #define PH_PULL (*(volatile unsigned int *)0x01c20918)
  35. void gpio_init()
  36. {
  37. /*PCDUINO GPIO4–PH9:
  38. *bit[6:4]:PH9_SELECT 001:OUTPUT
  39. *PCDUINO GPIO5–PH10:
  40. *bit[10:8]:PH10_SELECT 001:OUTPUT
  41. */
  42. PH_CFG1 |= ((0×1<<4)|(0×1<<8)|(0X1<<28));
  43. PH_DRI = 0XFFFFFFFF;
  44. PH_PULL = 0X55555555;
  45. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">void delay()
  46. {
  47. volatile int i = 0×300000;
  48. while (i–);
  49. }
  50. int main(void)
  51. {
  52. char c;
  53. clock_init(); /* 初始化時鐘 */
  54. gpio_init();</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">while (1)
  55. {
  56. PH_DAT = 0×00;
  57. delay();
  58. PH_DAT = 0xffff;
  59. delay();
  60. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">return 0;
  61. }
  62. 文件clock.c:</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">[plain] view plaincopyprint?#define CPU_AHB_APB0_CFG (*(volatile unsigned int *)0x01c20054)
  63. #define PLL1_CFG (*(volatile unsigned int *)0x01c20000)
  64. #define APB1_CLK_DIV_CFG (*(volatile unsigned int *)0x01c20058)
  65. #define APB1_GATE (*(volatile unsigned int *)0x01c2006C)</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">void sdelay(unsigned long loops)
  66. {
  67. __asm__ volatile("1:\n" "subs %0, %1, #1\n"
  68. "bne 1b":"=r" (loops):"0"(loops));
  69. }
  70. void clock_init(void)
  71. {
  72. /*AXI_DIV_1[1:0] AXI_CLK_DIV_RATIO 00:/1 AXI Clock source is CPU clock
  73. *AHB_DIV_2[5:4] AHP_CLK_DIV_RATIO 01:/2 AHB Clock source is AXI CLOCK
  74. *APB0_DIV_1[9:8] APB0_CLK_RATIO 00:/2 APB0 clock source is AHB2 clock
  75. *CPU_CLK_SRC_OSC24M[17:16] CPU_CLK_SRC_SEL 01:OSC24M
  76. */
  77. CPU_AHB_APB0_CFG = ((0<<0)|(0×1<<4)|(0<<8)|(1<<16));</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">/*bit31:PLL1_Enable 1:Enable
  78. *bit25:EXG_MODE 0×0:Exchange mode
  79. *bit[17:16]:PLL1_OUT_EXT_DIVP 0×0:P=1
  80. *bit[12:8]:PLL1_FACTOR_N 0×10:Factor=16,N=16
  81. *bit[5:4]:PLL1_FACTOR_K 0×0:K=1
  82. *bit3:SIG_DELT_PAT_IN 0×0
  83. *bit2:SIG_DELT_PAT_EN 0×0
  84. *bit[1:0]PLL1_FACTOR_M 0×0:M=1
  85. *The PLL1 output=(24M*N*K)/(M*P)=(24M*16*1)/(1*1)=384M is for the coreclk
  86. */
  87. PLL1_CFG = 0xa1005000;</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">sdelay(200);</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">CPU_AHB_APB0_CFG = ((0<<0)|(0×1<<4)|(0<<8)|(2<<16));//CPU_CLK_SRC_SEL 10:PLL1</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">/*uart clock source is apb1,config apb1 clock*/
  88. /*bit[25:24]:APB1_CLK_SRC_SEL 00:OSC24M
  89. *bit[17:16]:CLK_RAT_N 0X0:1 The select clock source is pre-divided by 2^1
  90. *bit[4:0]:CLK_RAT_M 0×0:1 The pre-devided clock is divided by(m+1)
  91. */
  92. APB1_CLK_DIV_CFG = ((0<<5)|(0<<16)|(0<<24));
  93. /*open the clock for uart0*/
  94. /*bit16:UART0_APB_GATING 1:pass 0:mask*/
  95. APB1_GATE = (0×1<<16);
  96. }</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">#define CPU_AHB_APB0_CFG (*(volatile unsigned int *)0x01c20054)
  97. #define PLL1_CFG (*(volatile unsigned int *)0x01c20000)
  98. #define APB1_CLK_DIV_CFG (*(volatile unsigned int *)0x01c20058)
  99. #define APB1_GATE (*(volatile unsigned int *)0x01c2006C)</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">void sdelay(unsigned long loops)
  100. {
  101. __asm__ volatile("1:\n" "subs %0, %1, #1\n"
  102. "bne 1b":"=r" (loops):"0"(loops));
  103. }
  104. void clock_init(void)
  105. {
  106. /*AXI_DIV_1[1:0] AXI_CLK_DIV_RATIO 00:/1 AXI Clock source is CPU clock
  107. *AHB_DIV_2[5:4] AHP_CLK_DIV_RATIO 01:/2 AHB Clock source is AXI CLOCK
  108. *APB0_DIV_1[9:8] APB0_CLK_RATIO 00:/2 APB0 clock source is AHB2 clock
  109. *CPU_CLK_SRC_OSC24M[17:16] CPU_CLK_SRC_SEL 01:OSC24M
  110. */
  111. CPU_AHB_APB0_CFG = ((0<<0)|(0×1<<4)|(0<<8)|(1<<16));</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">/*bit31:PLL1_Enable 1:Enable
  112. *bit25:EXG_MODE 0×0:Exchange mode
  113. *bit[17:16]:PLL1_OUT_EXT_DIVP 0×0:P=1
  114. *bit[12:8]:PLL1_FACTOR_N 0×10:Factor=16,N=16
  115. *bit[5:4]:PLL1_FACTOR_K 0×0:K=1
  116. *bit3:SIG_DELT_PAT_IN 0×0
  117. *bit2:SIG_DELT_PAT_EN 0×0
  118. *bit[1:0]PLL1_FACTOR_M 0×0:M=1
  119. *The PLL1 output=(24M*N*K)/(M*P)=(24M*16*1)/(1*1)=384M is for the coreclk
  120. */
  121. PLL1_CFG = 0xa1005000;</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">sdelay(200);</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">CPU_AHB_APB0_CFG = ((0<<0)|(0×1<<4)|(0<<8)|(2<<16));//CPU_CLK_SRC_SEL 10:PLL1</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">/*uart clock source is apb1,config apb1 clock*/
  122. /*bit[25:24]:APB1_CLK_SRC_SEL 00:OSC24M
  123. *bit[17:16]:CLK_RAT_N 0X0:1 The select clock source is pre-divided by 2^1
  124. *bit[4:0]:CLK_RAT_M 0×0:1 The pre-devided clock is divided by(m+1)
  125. */
  126. APB1_CLK_DIV_CFG = ((0<<5)|(0<<16)|(0<<24));
  127. /*open the clock for uart0*/
  128. /*bit16:UART0_APB_GATING 1:pass 0:mask*/
  129. APB1_GATE = (0×1<<16);
  130. }</p>
複製代碼

文件·clock.h:spa

  1. [plain] view plaincopyprint?void clock_init(void);
複製代碼

void clock_init(void);文件·Makefile:

  1. <p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">[plain] view plaincopyprint?led.bin:start.S main.c clock.c
  2. arm-none-linux-gnueabi-gcc -nostdlib -c start.S -o start.o
  3. arm-none-linux-gnueabi-gcc -nostdlib -c main.c -o main.o
  4. arm-none-linux-gnueabi-gcc -nostdlib -c clock.c -o clock.o
  5. arm-none-linux-gnueabi-ld -Ttext 0xD0020010 start.o main.o clock.o -o led_elf
  6. arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">clean:
  7. rm -rf *.o *.bin led_elf *.dis</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">led.bin:start.S main.c clock.c
  8. arm-none-linux-gnueabi-gcc -nostdlib -c start.S -o start.o
  9. arm-none-linux-gnueabi-gcc -nostdlib -c main.c -o main.o
  10. arm-none-linux-gnueabi-gcc -nostdlib -c clock.c -o clock.o
  11. arm-none-linux-gnueabi-ld -Ttext 0xD0020010 start.o main.o clock.o -o led_elf
  12. arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin</p><p style="margin-bottom: 1.714285714rem; border: 0px; vertical-align: baseline; ">clean:
  13. rm -rf *.o *.bin led_elf *.dis</p>
複製代碼

代碼確實很簡單,上面也有看手冊時留下的註釋,就不分析了,有問題留言吧。

3、編譯、測試

1.安裝交叉編譯鏈,給個連接 http://code.google.com/p/smp-on-qemu/downloads/list

選擇arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2並下載。而後在ubuntu下直接解壓便可,過程就不說了,還不清楚的看Ubuntu 10.04.4開發環境配置。

2.編譯

  1. change@change :~$ cd Si/A10/2_led/
  2. change@change :~/Si/A10/2_led$ ls
  3. clock.c clock.h main.c Makefile mksunxiboot start.S
  4. change@change :~/Si/A10/2_led$ make
  5. arm-none-linux-gnueabi-gcc -nostdlib -c start.S -o start.o
  6. arm-none-linux-gnueabi-gcc -nostdlib -c main.c -o main.o
  7. arm-none-linux-gnueabi-gcc -nostdlib -c clock.c -o clock.o
  8. arm-none-linux-gnueabi-ld -Ttext 0xD0020010 start.o main.o clock.o -o led_elf
  9. arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin
  10. change@change :~/Si/A10/2_led$ ./mksunxiboot led.bin leds.bin
  11. File size: 0×154
  12. Load size: 0×154
  13. Read 0×154 bytes
  14. Write 0×200 bytes
  15. change@change :~/Si/A10/2_led$
複製代碼
其中有個./mksunxiboot led.bin leds.bin要注意,不通過mksunxiboot工具 的.bin文件,pcDuino是運行不了的。這個工具在官網上都有下。如今的處理啓動都很複雜,內有固化有bl0代碼,在跳轉到bl1時須要校驗程序的合法性,這個工具mksunxiboot簡單點少就是給咱們程序加了點頭部,讓處理器可以識別咱們寫的代碼。你能夠分析led.bin和leds.bin的反彙編代碼,就一目瞭然了。這部分感興趣的能夠一塊兒討論。

3.測試

上面生成的leds.bin就能夠放到板子上運行了。爲了避免破會NAND中的系統,直接放到tf卡運行。不用擔憂那個先啓動,看全志手冊就知道pcDuino默認先從tf卡啓動,只有tf卡沒有啓動的引導程序纔會跳到NAND啓動。插上tf卡到PC機

  1. change@change:~/Si/A10/2_led$ sudo dd if=/dev/zero of=/dev/sdb bs=1M count=1
  2. 1+0 records in
  3. 1+0 records out
  4. 1048576 bytes (1.0 MB) copied, 0.425886 s, 2.5 MB/s
  5. change@change:~/Si/A10/2_led$ sudo dd if=leds.bin of=/dev/sdb bs=1024 seek=8
  6. 0+1 records in
  7. 0+1 records out
  8. 512 bytes (512 B) copied, 0.00600667 s, 85.2 kB/s
  9. change@change:~/Si/A10/2_led$
複製代碼

而後取下tf卡,插到pcDuino上,RX LED就開始閃爍了。若是你手上有led,接到GPIO四、GPIO5也會閃爍。


相關文章
相關標籤/搜索