|
ARM Boot 示例 程序主要作用是通过串口下载VxWorks 到ARM Flash ROM,主要过程是初始化 ARM 硬件,初始化串口UART1,从串口接收VxWorks image 到DRAM,初始化Flash ROM.最后将DRAM 中的VxWorks 写入Flash ROM. ARM 串口与PC 机串口连接,由 PC 机下载(download)VxWorks 到主板Flash ROM. 该程序对学习和理解ARM 编程很有帮助.为了便于理解,这里我全部采用实际地 址,不用宏定义. 程序语言为 ARM 汇编 ,具体寄存器接口定义参见ARM 硬件手册 VramBaseAddress EQU 0xC0000000 ;DRAM 起始地址,在ARM 硬 件地址映射定义, Length1 EQU 0x100 FlashBase EQU 0x70000000 ;Flash 的基地址,在Boot 模式下,为0x70000000 MMUCP CP 15 ;协处理器15 AREA |C$$code|, CODE, READONLY ENTRY EXPORT main main MOV r14, #0x70 ;设置MMU 无效, 32 位模式, Little endian MCR MMUCP, 0, r14, c1, c0, 0 MRS r14, CPSR BIC r14, r14, #0x1f ;Mask ORR r14, r14, #0xc0 0x13 ;关闭所有 IRQ FIQ, 用SVC32 模式 MSR CPSR, r14 LDR r11, =0x80000000 ;内部寄存器基地址 0x80000000 LDR r12, =0x80001000 MOV r0, #0 STR r0, [r11, #0x280] ;disable 所有中断 STR r0, [r12, #0x280] LDR r0, =0x840100 ;在系统控制寄存器SYSCON1 中 STR r0, [r11, #0x100] ;使能外部时钟 EXCKEN 和串口 UART1 LDR r0, =0x06 ;在系统控制寄存器SYSCON2 中 STR r0, [r12, #0x100] ;使能16-bit DRAM, 键盘KBD6 LDR r0, =0x03010100 ;在存储控制寄存器MEMCFG1 中 STR r0, [r11, #0x180] ;设置外设数据线宽度 CS0:16 位,CS1,2:32 位,CS3:8 位 ;特别注意: 1. 如设置线宽为16 位,由于CPU 是32 位,CPU 会把32 位数据分两次操作写 入,每次写16 位,这样对32 位的外设来说是一种浪费 例如: LDR r0, =0x10000000 LDR r1, =0x12345678 STR r1,[r0] 实际情况是 第一次写入地址0x10000000 的数据是 0x1234 第二次写入地址0x10000002 的数据是 0x5678 示波器上观察的情况是一个片选信号/CS 低电平范围内,有两个写入信号/WE 低 电平. 2. 如设置线宽为32 位,CPU 会把32 位数据一次写入,如果外设是16 位的话, 如ISA 网卡,就会造成高16 位丢失. 例如: LDR r0, =0x10000000 LDR r1, =0x12345678 STR r1,[r0] 实际情况是 一次写入地址0x10000000 的数据是 0x12345678 LDR r0, = 0xff ;DRAM 刷新率refresh rate, 设置要适当,否则数据丢失 STR r0, [r11, #0x200] LDR r13, =0xc0020000 ;设置堆栈 Stack, r13 为 ARM 定义的堆栈指针 ;Init OK LDR r0, =receiving_msg BL printmsg BL dram_test ;跳转指令,执行测试DRAM LDR r0, =startloader_cmdmsg BL printmsg BL Beep LDR r0, =0x60005 ;设置波特率 38400, 8 位 LDR r11, =0x80000000 STR r0, [r11, #0x4c0] ;初始化串口 UART ;Receive data and save it to buffer ;开始接收数据 LDR r12, =SaveAddr ;First 8 bytes are start address and length ;Receive address LDR r5, =0x4 ;Read first 4 bytes MOV r0, #0 rx_loop1 LDR r1, [r11, #0x140] ;检查系统状态寄存器 System Status Register 1 TST r1, #0x00400000 ;UART1 Rx 是否为空 BNE rx_loop1 ;等待数据 Wait data LDR r1, [r11, #0x480] ;读数据 Read data AND r1, r1, #0xff ORR r0, r1, r0, ROR #8 SUBS r5, r5, #1 BNE rx_loop1 MOV r0, r0, ROR #8 STR r0, [r12] ADD r12, r12, #4 ;Receive count LDR r12, =Count LDR r5, =0x4 ;Read second 4 bytes MOV r0, #0 rx_loop2 LDR r1, [r11, #0x140] ;检查系统状态寄存器 System Status Register 1 TST r1, #0x00400000 ;UART1 Rx 是否为空 BNE rx_loop2 ;等待数据 Wait data LDR r1, [r11, #0x480] ;读数据 Read data AND r1, r1, #0xff ORR r0, r1, r0, ROR #8 SUBS r5, r5, #1 BNE rx_loop2 MOV r0, r0, ROR #8 STR r0, [r12] MOV r6, r0 ;Save the count to r6 ;Receive data MOV r5, r0 MOV r9, #0 LDR r10, =BufferBase MOV r12, #0 rx_loop3 LDR r1, [r11, #0x140] ;System Status Register 1 TST r1, #0x00400000 ;UART1 Rx Empty BNE rx_loop3 ;Wait data LDR r1, [r11, #0x480] ;Read data AND r1, r1, #0xff STRB r1, [r10, r12] ADD r12, r12, #1 nextbyte ;读下一个字节 SUBS r5, r5, #1 BNE rx_loop3 ;Receive data OK ;数据接收完毕 MOV r1, #0x31 BL send_char MOV r1, #0x0d BL send_char MOV r1, #0x0a BL send_char ;Save it to Flash ROM 把数据写入Flash ROM
|