ARM11 OK6410 的 串口问题

[复制链接]
2846|0
 楼主| luochenchen 发表于 2013-6-14 09:03 | 显示全部楼层 |阅读模式
最近在学习裸奔ARM11的OK6410 开发板,写了个串口程序,开发环境为Windows 7 64bit + Ubuntu 13.04, 开发环境参照飞凌嵌入式的使用手册搭建。但是裸机代码参考韦东山老师的裸机代码,主要功能是:Win7和开发板通过串口相连,然后Win7 通过串口向开发板发送字符,开发板再将字符原封不动的返回。如果字符是 0 -9 , a - f, A - F, 则以开发板上的4位LED显示,否则,关闭LED灯。程序代码如下:
clock.S : 配置ARM的PLL
  1. .global         clock_init



  2. clock_init:


  3.         /*      设置Lock_Time */
  4.         ldr             r0, =0x7E00F000
  5.         ldr             r1, =0x0000FFFF

  6.         str             r1, [r0] @APLL_LOCK
  7.         str             r1, [r0, #4]    @MPLL_LOCK
  8.         str             r1, [r0, #8]    @EPLL_LOCK

  9. #define OTHERS  0x7e00f900
  10.         ldr             r0, = OTHERS
  11.         ldr             r1, [r0]
  12.         bic             r1, r1, #0xc0  /* 1100 0000 SYNCMUX设置为 MOUT,且ARM设置为异步模式*/
  13.         str             r1, [r0]

  14. loop1:  /* 等待, 知道CPU进入异步模式 */
  15.         ldr             r0, =0x7e00f900
  16.         ldr             r1, [r0]
  17.         and             r1, r1, #0xf00 /*[11:8] SYNCACK :确认ARM是否进入异步模式 */
  18.         cmp             r1, #0
  19.         bne             loop1


  20. /* 配置时钟分频寄存器 */
  21. #define ARM_RATIO       0
  22. #define HCLKX2_RATIO    1
  23. #define HCLK_RATIO      1
  24. #define PCLK_RATIO      3
  25. #define MPLL_RATIO      0

  26. #define CLK_DIV0        0x7E00F020
  27.         ldr             r0, =CLK_DIV0
  28.         ldr             r1, = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
  29.         str             r1, [r0]

  30. /* 配置APLL : Out = MDIV * Fin / (PDIV * 2^SDIV)*/
  31. #define APLL_CON                0x7E00F00c
  32. #define APLL_CON_VAL    ((1 << 31) | (266 << 16) | (3 << 8) | (1))
  33.         ldr             r0, =APLL_CON
  34.         ldr             r1, =APLL_CON_VAL  [url=home.php?mod=space&uid=88907]@out[/url] = 266 * 12 / (3 * 2^1) = 532MHz
  35.         str             r1, [r0]

  36. /* 配置MPLL : Out = MDIV * Fin / (PDIV * 2^SDIV)*/
  37. #define MPLL_CON                0x7E00F010
  38. #define MPLL_CON_VAL    ((1 << 31) | (266 << 16) | (3 << 8) | (1))
  39.         ldr             r0, =MPLL_CON
  40.         ldr             r1, =MPLL_CON_VAL  [url=home.php?mod=space&uid=72445]@[/url] Out = 266 * 12 / (3 * 2^1) = 532MHz
  41.         str             r1, [r0]

  42.         /* Initial the CLK_SRC register: select the clock source */
  43.         ldr             r0, =0x7E00F01c
  44.         ldr             r1, =0x03 /* select the MPLL and the APLL */
  45.         str             r1, [r0]


  46.         /* return from fucntion call */
  47.         mov             pc, lr
uart.c : 配置串口,通信波特率为115200, 8个数据位,无校验,1个停止位
  1. #define ULCON0  (*(volatile unsigned long *)0x7F005000)
  2. #define UCON0   (*(volatile unsigned long *)0x7F005004)
  3. #define UFCON0  (*(volatile unsigned long *)0x7f005008)
  4. #define UMCON0  (*(volatile unsigned long *)0x7f00500c)
  5. #define UTRSTAT0 (*(volatile unsigned long *)0x7f005010)
  6. #define UFSTAT0 (*(volatile unsigned long *)0x7f005018)
  7. #define UTXH0   (*(volatile unsigned char *)0x7F005020)
  8. #define URXH0   (*(volatile unsigned char *)0x7F005024)
  9. #define UBRDIV0 (*(volatile unsigned short *)0x7f005028)
  10. #define UDIVSLOT0       (*(volatile unsigned short *)0x7f00502c)

  11. #define GPACON          (*(volatile unsigned long *)0x7f008000)

  12. void init_uart()
  13. {
  14.         GPACON &= ~0xff;
  15.         GPACON |= 0x22; //0010 : RXD[0] & TXD[0]

  16.         /* ULCON0 */
  17.         ULCON0 = 0x3;/* Data: 8bit Stop bits: 1 Parity Mode: No  */
  18.         UCON0 = 0x5; /* 中断请求或者轮询从Uart 接收/发送缓冲区收发数据 选择PCLK作为UART波特率时钟,DIV_VAL = (PCLK / ((b/s) * 16)) - 1 */
  19.         UFCON0 = 0x1;  /*FIFO enable  */

  20.         UMCON0 = 0;/* nRTS 无效 */

  21.         UBRDIV0 = 35;

  22.         UDIVSLOT0 = 0x1;
  23. }

  24. /* UFSTAT0: UART0 的FIFO状态寄存器 */
  25. /**
  26. * bit 14: Tx FIFO Full 发送FIFO满时自动置位
  27. * bit 13-8: Tx FIFO 数据中的数量
  28. *
  29. * bit 6: Rx FIFO Full 接收FIFO满时,该位置1
  30. * bit 5-0: Rx FIFO 数据中的数量。
  31. */
  32. /**
  33. * URXH0 : 接收缓冲寄存器 0x7F005024
  34. * 低8bit为接收的数据;
  35. */
  36. char getchar(void)
  37. {
  38.         while ((UFSTAT0 & 0x7f) == 0)
  39.           ;
  40.         return URXH0;
  41. }
  42. /**
  43. * UTXH0: 发送缓冲寄存器 低8位为要发送的数据
  44. */
  45. void putchar(char c)
  46. {
  47.         while (UFSTAT0 & (1 << 14))
  48.           ;
  49.         UTXH0 = c;
  50. }
start.S  启动代码
  1. .global _start
  2. .extern clock_init
  3. .extern main



  4. _start:
  5.         /* 设置协处理器,设置外设的基地址*/
  6.         ldr             r0, =0x70000000
  7.         orr             r0, r0, #0x13
  8.         mcr             p15, 0, r0, c15, c2, 4

  9.         /* 关闭看门狗 */
  10.         ldr             r0, =0x7E004000
  11.         mov             r1, #0
  12.         str             r1, [r0]

  13.         /* 设置时钟 */
  14.         bl clock_init

  15.         /* 设置堆栈 */
  16.         ldr     sp, = 8 * 1024
  17.         bl main

  18. halt:
  19.         b halt
main.c
  1. int main(void)
  2. {
  3.         char c;
  4.         int i;

  5.         LEDCON = 0x1111;
  6.         LEDDAT = 0xf;

  7.         init_uart();

  8.         while (1) {
  9.                 c = getchar();

  10.                 int c1;
  11.                 if (c >= '0' & c <= '9')
  12.                         c1 = c - '0';
  13.                 else if (c >= 'A' & c <= 'F')
  14.                         c1 = c - 'A' + 10;
  15.                 else if (c >= 'a' & c <= 'f')
  16.                         c1 = c - 'a' + 10;
  17.                 else
  18.                         c1 = 0;

  19.                 LEDDAT = ~c1 & 0x0f;

  20.                 putchar(c);
  21.         }
  22. }
delay.S /*  没用到,可以直接无视 */
  1. .global clock_delay

  2. /*  the udly will be passed by r0 */
  3. clock_delay:

  4.         cmp             r0, #0
  5.         beq             loop_end
  6. loop:
  7.         ldr             r1, =532000 /* 1ms at 532MHz */
  8. inner:
  9.         sub             r1, r1, #1
  10.         cmp             r1, #0
  11.         bne             inner
  12. outter:
  13.         sub             r0, r0, #1
  14.         cmp             r0, #0
  15.         bne             loop

  16. loop_end:
  17.         /* return from the function call*/
  18.         mov             pc, lr
上述写的延时函数有问题,我设置ARM的时钟频率为532MHz,原以为延时函数内层赋值 532000应该为1ms,即使后来ARM开启流水线执行,多条语句一起执行,那么延时应该小于1ms 左右,但是实际代码执行通过LED可知,6个左右的内层循环就将近1S了。百思不得其解啊,莫非延时函数的执行不是ARM内核来执行?



Makefile
  1. CC               = arm-linux-gcc
  2. CFLAGS   = -c -Wall -fno-stack-protector -fno-builtin
  3. LD               = arm-linux-ld
  4. LDFLAGS  = -Ttext 0x0 -nostdlib ####-Ttext 如果为0 是烧写到Nand FLASH的起始位置,如果为 0x50000000 是烧写到SDRAM中直接运行
  5. OBJDUMP  = arm-linux-objdump
  6. OBJCOPY  = arm-linux-objcopy
  7. OBJ              = start.o uart.o clock.o main.o delay.o

  8. uart.bin : uart.elf

  9.         $(OBJCOPY)      -O binary uart.elf uart.bin
  10.         cp uart.bin ~/nfs_root/chenchen -f

  11. uart.elf: $(OBJ)
  12.         $(LD) $(LDFLAGS) -o uart.elf $(OBJ)
  13.         $(OBJDUMP) -d uart.elf > uart.dis

  14. start.o : start.S
  15.         $(CC) $(CFLAGS) -o $@ lt;

  16. uart.o : uart.c
  17.         $(CC) $(CFLAGS) -o $@ lt;

  18. main.o : main.c
  19.         $(CC) $(CFLAGS) -o $@ lt;

  20. clock.o : clock.S
  21.         $(CC) $(CFLAGS) -o $@ lt;

  22. delay.o : delay.S
  23.         $(CC) $(CFLAGS) -o $@ lt;

  24. clean:
  25.         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可以看到程序运行不正常,串口不能正常收发。我以前利用这种方法写过流水灯,就能正常运行。不知道是什么原因?
求大神指导啊!




您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

2

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部