- .global clock_init
- clock_init:
- /* 设置Lock_Time */
- ldr r0, =0x7E00F000
- ldr r1, =0x0000FFFF
- str r1, [r0] @APLL_LOCK
- str r1, [r0, #4] @MPLL_LOCK
- str r1, [r0, #8] @EPLL_LOCK
- #define OTHERS 0x7e00f900
- ldr r0, = OTHERS
- ldr r1, [r0]
- bic r1, r1, #0xc0 /* 1100 0000 SYNCMUX设置为 MOUT,且ARM设置为异步模式*/
- str r1, [r0]
- loop1: /* 等待, 知道CPU进入异步模式 */
- ldr r0, =0x7e00f900
- ldr r1, [r0]
- and r1, r1, #0xf00 /*[11:8] SYNCACK :确认ARM是否进入异步模式 */
- cmp r1, #0
- bne loop1
- /* 配置时钟分频寄存器 */
- #define ARM_RATIO 0
- #define HCLKX2_RATIO 1
- #define HCLK_RATIO 1
- #define PCLK_RATIO 3
- #define MPLL_RATIO 0
- #define CLK_DIV0 0x7E00F020
- ldr r0, =CLK_DIV0
- ldr r1, = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
- str r1, [r0]
- /* 配置APLL : Out = MDIV * Fin / (PDIV * 2^SDIV)*/
- #define APLL_CON 0x7E00F00c
- #define APLL_CON_VAL ((1 << 31) | (266 << 16) | (3 << 8) | (1))
- ldr r0, =APLL_CON
- ldr r1, =APLL_CON_VAL [url=home.php?mod=space&uid=88907]@out[/url] = 266 * 12 / (3 * 2^1) = 532MHz
- str r1, [r0]
- /* 配置MPLL : Out = MDIV * Fin / (PDIV * 2^SDIV)*/
- #define MPLL_CON 0x7E00F010
- #define MPLL_CON_VAL ((1 << 31) | (266 << 16) | (3 << 8) | (1))
- ldr r0, =MPLL_CON
- ldr r1, =MPLL_CON_VAL [url=home.php?mod=space&uid=72445]@[/url] Out = 266 * 12 / (3 * 2^1) = 532MHz
- str r1, [r0]
- /* Initial the CLK_SRC register: select the clock source */
- ldr r0, =0x7E00F01c
- ldr r1, =0x03 /* select the MPLL and the APLL */
- str r1, [r0]
- /* return from fucntion call */
- mov pc, lr
uart.c : 配置串口,通信波特率为115200, 8个数据位,无校验,1个停止位
- #define ULCON0 (*(volatile unsigned long *)0x7F005000)
- #define UCON0 (*(volatile unsigned long *)0x7F005004)
- #define UFCON0 (*(volatile unsigned long *)0x7f005008)
- #define UMCON0 (*(volatile unsigned long *)0x7f00500c)
- #define UTRSTAT0 (*(volatile unsigned long *)0x7f005010)
- #define UFSTAT0 (*(volatile unsigned long *)0x7f005018)
- #define UTXH0 (*(volatile unsigned char *)0x7F005020)
- #define URXH0 (*(volatile unsigned char *)0x7F005024)
- #define UBRDIV0 (*(volatile unsigned short *)0x7f005028)
- #define UDIVSLOT0 (*(volatile unsigned short *)0x7f00502c)
- #define GPACON (*(volatile unsigned long *)0x7f008000)
- void init_uart()
- {
- GPACON &= ~0xff;
- GPACON |= 0x22; //0010 : RXD[0] & TXD[0]
- /* ULCON0 */
- ULCON0 = 0x3;/* Data: 8bit Stop bits: 1 Parity Mode: No */
- UCON0 = 0x5; /* 中断请求或者轮询从Uart 接收/发送缓冲区收发数据 选择PCLK作为UART波特率时钟,DIV_VAL = (PCLK / ((b/s) * 16)) - 1 */
- UFCON0 = 0x1; /*FIFO enable */
- UMCON0 = 0;/* nRTS 无效 */
- UBRDIV0 = 35;
- UDIVSLOT0 = 0x1;
- }
- /* UFSTAT0: UART0 的FIFO状态寄存器 */
- /**
- * bit 14: Tx FIFO Full 发送FIFO满时自动置位
- * bit 13-8: Tx FIFO 数据中的数量
- *
- * bit 6: Rx FIFO Full 接收FIFO满时,该位置1
- * bit 5-0: Rx FIFO 数据中的数量。
- */
- /**
- * URXH0 : 接收缓冲寄存器 0x7F005024
- * 低8bit为接收的数据;
- */
- char getchar(void)
- {
- while ((UFSTAT0 & 0x7f) == 0)
- ;
- return URXH0;
- }
- /**
- * UTXH0: 发送缓冲寄存器 低8位为要发送的数据
- */
- void putchar(char c)
- {
- while (UFSTAT0 & (1 << 14))
- ;
- UTXH0 = c;
- }
start.S 启动代码
- .global _start
- .extern clock_init
- .extern main
- _start:
- /* 设置协处理器,设置外设的基地址*/
- ldr r0, =0x70000000
- orr r0, r0, #0x13
- mcr p15, 0, r0, c15, c2, 4
- /* 关闭看门狗 */
- ldr r0, =0x7E004000
- mov r1, #0
- str r1, [r0]
- /* 设置时钟 */
- bl clock_init
- /* 设置堆栈 */
- ldr sp, = 8 * 1024
- bl main
- halt:
- b halt
main.c
- int main(void)
- {
- char c;
- int i;
- LEDCON = 0x1111;
- LEDDAT = 0xf;
- init_uart();
- while (1) {
- c = getchar();
- int c1;
- if (c >= '0' & c <= '9')
- c1 = c - '0';
- else if (c >= 'A' & c <= 'F')
- c1 = c - 'A' + 10;
- else if (c >= 'a' & c <= 'f')
- c1 = c - 'a' + 10;
- else
- c1 = 0;
- LEDDAT = ~c1 & 0x0f;
- putchar(c);
- }
- }
delay.S /* 没用到,可以直接无视 */
- .global clock_delay
- /* the udly will be passed by r0 */
- clock_delay:
- cmp r0, #0
- beq loop_end
- loop:
- ldr r1, =532000 /* 1ms at 532MHz */
- inner:
- sub r1, r1, #1
- cmp r1, #0
- bne inner
- outter:
- sub r0, r0, #1
- cmp r0, #0
- bne loop
- loop_end:
- /* return from the function call*/
- mov pc, lr
上述写的延时函数有问题,我设置ARM的时钟频率为532MHz,原以为延时函数内层赋值 532000应该为1ms,即使后来ARM开启流水线执行,多条语句一起执行,那么延时应该小于1ms 左右,但是实际代码执行通过LED可知,6个左右的内层循环就将近1S了。百思不得其解啊,莫非延时函数的执行不是ARM内核来执行?
Makefile
- CC = arm-linux-gcc
- CFLAGS = -c -Wall -fno-stack-protector -fno-builtin
- LD = arm-linux-ld
- LDFLAGS = -Ttext 0x0 -nostdlib ####-Ttext 如果为0 是烧写到Nand FLASH的起始位置,如果为 0x50000000 是烧写到SDRAM中直接运行
- OBJDUMP = arm-linux-objdump
- OBJCOPY = arm-linux-objcopy
- OBJ = start.o uart.o clock.o main.o delay.o
- uart.bin : uart.elf
- $(OBJCOPY) -O binary uart.elf uart.bin
- cp uart.bin ~/nfs_root/chenchen -f
- uart.elf: $(OBJ)
- $(LD) $(LDFLAGS) -o uart.elf $(OBJ)
- $(OBJDUMP) -d uart.elf > uart.dis
- start.o : start.S
- $(CC) $(CFLAGS) -o $@ lt;
- uart.o : uart.c
- $(CC) $(CFLAGS) -o $@ lt;
- main.o : main.c
- $(CC) $(CFLAGS) -o $@ lt;
- clock.o : clock.S
- $(CC) $(CFLAGS) -o $@ lt;
- delay.o : delay.S
- $(CC) $(CFLAGS) -o $@ lt;
- clean:
- rm $(OBJ) *.bin *.dis *.elf
在Linux环境下 Make,即可生成可执行文件 uart.bin,通过NFS文件系统,用Uboot的nfs 命令将uart.bin 烧写到0x50000000 内存处,然后再用nand命令,将该段内存烧写到Nand Flash 的起始处。然后断电,上电重新运行,可以看到程序正常运行。
但是,我把链接参数改成 -Ttext 0x50000000, 然后直接将uart.bin 烧写到 0x50000000 处,然后 go 0x500000000可以看到程序运行不正常,串口不能正常收发。我以前利用这种方法写过流水灯,就能正常运行。不知道是什么原因?
求大神指导啊!