打印

ARM11 OK6410 的 串口问题

[复制链接]
2381|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
.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 $@ [        DISCUZ_CODE_347        ]lt;

uart.o : uart.c
        $(CC) $(CFLAGS) -o $@ [        DISCUZ_CODE_347        ]lt;

main.o : main.c
        $(CC) $(CFLAGS) -o $@ [        DISCUZ_CODE_347        ]lt;

clock.o : clock.S
        $(CC) $(CFLAGS) -o $@ [        DISCUZ_CODE_347        ]lt;

delay.o : delay.S
        $(CC) $(CFLAGS) -o $@ [        DISCUZ_CODE_347        ]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可以看到程序运行不正常,串口不能正常收发。我以前利用这种方法写过流水灯,就能正常运行。不知道是什么原因?
求大神指导啊!




相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

2

帖子

0

粉丝