最近调驱动时,调试led时遇到了点问题,于是回过头来再写个led裸板程序。在我写的pcDuino第一个裸板程序uart的基础上,再写个led裸板程序还是很轻松的。很多人觉得没有必要写什么pcDuino裸板程序,觉得没啥意义。我觉得可以用来熟悉硬件,特别是想做底层驱动开发,以及系统移植,熟悉底层硬件还是有用的。其实做底层驱动开发,也是跟硬件打交道,硬件相关的操作和裸板程序是一样的。下面介绍怎样在pcDuino上跑一个最简单的led裸板程序。
开发环境:
宿主机:ubuntu 12.04 64位
目标机:pcDuino V2
编译器:arm-linux-gnueabihf-gcc (4.6)
目标:实现pcDuino上的TX_LED闪烁
文档说明:
命令提示符 $ 表示在pcDuino上面运行的指令;
命令提示符 # 表示在x86_64的linux主机上运行的指令
命令提示符 > 表示在u-boot状态下运行的指令
仔细看pcDuino上的原理图和pcDuino的手册,发现二者不是完全对应的,还是以原理图为准。根据原理图知道TX_LED是接到PH15上,可以当做普通IO口用,不需要连跳线
主要是看手册30.Port Controller,根据手册写led初始化程序主要包括设为输出、是能上拉及Multi-Driving寄存器设置。包括start.S、main.c、clock.c、clock.h、Makefile,下面贴出全部代码
1 2 3 4 5 6 |
. _start _start ldr = b main |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include "clock.h" #define PH_CFG1 (*(volatile unsigned int *)0x01c20900) #define PH_DAT (*(volatile unsigned int *)0x01c2090C) #define PH_DRI (*(volatile unsigned int *)0x01c20910) #define PH_PULL (*(volatile unsigned int *)0x01c20918) void gpio_init { /*PCDUINO GPIO4--PH9: *bit[6:4]:PH9_SELECT 001:OUTPUT *PCDUINO GPIO5--PH10: *bit[10:8]:PH10_SELECT 001:OUTPUT */ PH_CFG1 |= ( PH_DRI 0XFFFFFFFF PH_PULL 0X55555555 } void delay { volatile i = 0x300000 while ( } int main { char c clock_init /* 初始化时钟 */ gpio_init while ( { PH_DAT = 0x00 delay PH_DAT = 0xffff delay } return 0 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#define CPU_AHB_APB0_CFG (*(volatile unsigned int *)0x01c20054) #define PLL1_CFG (*(volatile unsigned int *)0x01c20000) #define APB1_CLK_DIV_CFG (*(volatile unsigned int *)0x01c20058) #define APB1_GATE (*(volatile unsigned int *)0x01c2006C) void sdelay long loops { __asm__ "subs %0, %1, #1\n" "bne 1b" ( } void clock_init { /*AXI_DIV_1[1:0] AXI_CLK_DIV_RATIO 00:/1 AXI Clock source is CPU clock *AHB_DIV_2[5:4] AHP_CLK_DIV_RATIO 01:/2 AHB Clock source is AXI CLOCK *APB0_DIV_1[9:8] APB0_CLK_RATIO 00:/2 APB0 clock source is AHB2 clock *CPU_CLK_SRC_OSC24M[17:16] CPU_CLK_SRC_SEL 01:OSC24M */ CPU_AHB_APB0_CFG = ( /*bit31:PLL1_Enable 1:Enable *bit25:EXG_MODE 0x0:Exchange mode *bit[17:16]:PLL1_OUT_EXT_DIVP 0x0:P=1 *bit[12:8]:PLL1_FACTOR_N 0x10:Factor=16,N=16 *bit[5:4]:PLL1_FACTOR_K 0x0:K=1 *bit3:SIG_DELT_PAT_IN 0x0 *bit2:SIG_DELT_PAT_EN 0x0 *bit[1:0]PLL1_FACTOR_M 0x0:M=1 *The PLL1 output=(24M*N*K)/(M*P)=(24M*16*1)/(1*1)=384M is for the coreclk */ PLL1_CFG = 0xa1005000 sdelay CPU_AHB_APB0_CFG = ( /*uart clock source is apb1,config apb1 clock*/ /*bit[25:24]:APB1_CLK_SRC_SEL 00:OSC24M *bit[17:16]:CLK_RAT_N 0X0:1 The select clock source is pre-divided by 2^1 *bit[4:0]:CLK_RAT_M 0x0:1 The pre-devided clock is divided by(m+1) */ APB1_CLK_DIV_CFG = ( /*open the clock for uart0*/ /*bit16:UART0_APB_GATING 1:pass 0:mask*/ APB1_GATE = ( } |
1 |
void clock_init |
1 2 3 4 5 6 7 8 9 |
led main clock arm - - start - start arm - - main - main arm - - clock - clock arm - 0xD0020010 start main clock led_elf arm - binary - led_elf clean rm - |
1.编译
change@change :~$ cd Si/A10/2_led/
change@change :~/Si/A10/2_led$ ls
clock.c clock.h main.c Makefile mksunxiboot start.S
change@change :~/Si/A10/2_led$ make
arm-none-linux-gnueabi-gcc -nostdlib -c start.S -o start.o
arm-none-linux-gnueabi-gcc -nostdlib -c main.c -o main.o
arm-none-linux-gnueabi-gcc -nostdlib -c clock.c -o clock.o
arm-none-linux-gnueabi-ld -Ttext 0xD0020010 start.o main.o clock.o -o led_elf
arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin
change@change :~/Si/A10/2_led$ ./mksunxiboot led.bin leds.bin
File size: 0x154
Load size: 0x154
Read 0x154 bytes
Write 0x200 bytes
change@change :~/Si/A10/2_led$
其中有个./mksunxiboot led.bin leds.bin要注意,不经过mksunxiboot工具 的.bin文件,pcDuino是运行不了的。这个工具在官网上都有下。现在的处理启动都很复杂,内有固化有bl0代码,在跳转到bl1时需要校验程序的合法性,这个工具mksunxiboot简单点少就是给我们程序加了点头部,让处理器能够识别我们写的代码。你可以分析led.bin和leds.bin的反汇编代码,就一目了然了。这部分感兴趣的可以一起讨论。
2.测试
上面生成的leds.bin就可以放到板子上运行了。为了不破会NAND中的系统,直接放到tf卡运行。不用担心那个先启动,看全志手册就知道pcDuino默认先从tf卡启动,只有tf卡没有启动的引导程序才会跳到NAND启动。插上tf卡到PC机
[email protected]:~/Si/A10/2_led$ sudo dd if=/dev/zero of=/dev/sdb bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.425886 s, 2.5 MB/s
[email protected]:~/Si/A10/2_led$ sudo dd if=leds.bin of=/dev/sdb bs=1024 seek=8
0+1 records in
0+1 records out
512 bytes (512 B) copied, 0.00600667 s, 85.2 kB/s
[email protected]:~/Si/A10/2_led$
然后取下tf卡,插到pcDino上,RX LED就开始闪烁了。如果你手上有led,接到GPIO4、GPIO5也会闪烁。