时间:2018.4.6 作者:Tom 工作:HWE 说明:如需转载,请注明出处。已注明转载
1:
/* for UART */
bl uart_asm_init
--------------------------------------- uart_asm_init 代码解析开始--------------------------------------------
。。。。。。。。。。。。
uart_asm_init:
/* set GPIO(GPA) to enable UART */
@ GPIO setting for UART
ldr r0, =ELFIN_GPIO_BASE
#define ELFIN_GPIO_BASE 0xE0200000
ldr r1, =0x22222222
str r1, [r0, #GPA0CON_OFFSET]
#define GPA0CON_OFFSET 0x000
将此系列的GPIO全部配成UART相关的功能,即当做串口使用。
ldr r1, =0x2222
str r1, [r0, #GPA1CON_OFFSET]
#define GPA1CON_OFFSET 0x020
// HP V210 use. SMDK not use.
#if defined(CONFIG_VOGUES)
ldr r1, =0x100
str r1, [r0, #GPC0CON_OFFSET]
ldr r1, =0x4
str r1, [r0, #GPC0DAT_OFFSET]
#endif
上面没用到,我们不管
ldr r0, =ELFIN_UART_CONSOLE_BASE @0Xe290 0800
我们使用了第2个UART,实际板子上对应着我们的串口2。因此使用这一行宏定义。
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET)
#define ELFIN_UART_BASE 0XE2900000
#define ELFIN_UART3_OFFSET 0x0800
mov r1, #0x0
str r1, [r0, #UFCON_OFFSET]
str r1, [r0, #UMCON_OFFSET]
#define UFCON_OFFSET 0x08
#define UMCON_OFFSET 0x0C
上述操作是不使用FIFO和CTS和RTS
mov r1, #0x3
str r1, [r0, #ULCON_OFFSET]
#define ULCON_OFFSET 0x00
参照第一张图可以知道,此操作是设置传输单位为8bit。
ldr r1, =0x3c5
str r1, [r0, #UCON_OFFSET]
#define UCON_OFFSET 0x04
设置为中断请求或者查询模式(目前我们已经禁止了中断,因此最终会使用查询模式),使用正常传输、正常工作,使能中断延时,电平采样。
ldr r1, =UART_UBRDIV_VAL
str r1, [r0, #UBRDIV_OFFSET]
#define UART_UBRDIV_VAL 34
#define UART_UDIVSLOT_VAL 0xDDDD
#define UBRDIV_OFFSET 0x28
#define UDIVSLOT_OFFSET 0x2C
ldr r1, =UART_UDIVSLOT_VAL
str r1, [r0, #UDIVSLOT_OFFSET]
默认使用的是PCLK,也就是66MHz。
ldr r1, =0x4f4f4f4f O的ASCII码是4F
str r1, [r0, #UTXH_OFFSET] @'O'
#define UTXH_OFFSET 0x20
其中8~31位是保留的,可以不用加上4F。
mov pc, lr
--------------------------------------- uart_asm_init 代码解析结束--------------------------------------------
bl tzpc_init
这个函数没用过,不知道。这个函数的主要作用是防御和保护,可以理解为防火墙。具体的信息可参考:
https://blog.csdn.net/guyongqiangx/article/details/78020257。
#if defined(CONFIG_ONENAND)
bl onenandcon_init
#endif
#if defined(CONFIG_NAND)
/* simple init for NAND */
bl nand_asm_init
#endif
上述没用到,不管。
/* check reset status */
这个检查复位状态,前面已经分析过了。
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
ldr r1, [r0]
bic r1, r1, #0xfffeffff
cmp r1, #0x10000
beq wakeup_reset_pre
/* ABB disable */
这个寄存器在数据手册中查不到。
ldr r0, =0xE010C300
orr r1, r1, #(0x1<<23)
str r1, [r0]
/* Print 'K' */
打印一个K,整合在一起就是OK。所以我们开发板上电之后就是打印OK。
ldr r0, =ELFIN_UART_CONSOLE_BASE
ldr r1, =0x4b4b4b4b
str r1, [r0, #UTXH_OFFSET]
pop {pc}
返回前通过串口打印'K'
分析;lowlevel_init.S执行完如果没错那么就会串口打印出"OK"字样。这应该是我们uboot中看到的最早的输出信息。
wakeup_reset_from_didle:
/* Wait when APLL is locked */
ldr r0, =ELFIN_CLOCK_POWER_BASE
lockloop:
ldr r1, [r0, #APLL_CON0_OFFSET]
and r1, r1, #(1<<29)
cmp r1, #(1<<29)
bne lockloop
beq exit_wakeup
下面是各种复位状态情况下恢复到正常工作状态所要做的一些操作。不看了。
wakeup_reset_pre:
mrc p15, 0, r1, c1, c0, 1 @Read CP15 Auxiliary control register
and r1, r1, #0x80000000 @Check L2RD is disable or not
cmp r1, #0x80000000
bne wakeup_reset @if L2RD is not disable jump to wakeup_reset
bl disable_l2cache
bl v7_flush_dcache_all
/* L2 cache enable at sleep.S of kernel
* bl enable_l2cache
*/
wakeup_reset:
/* init system clock */
bl system_clock_init
bl mem_ctrl_asm_init
bl tzpc_init
#if defined(CONFIG_ONENAND)
bl onenandcon_init
#endif
#if defined(CONFIG_NAND)
bl nand_asm_init
#endif
exit_wakeup:
/*Load return address and jump to kernel*/
ldr r0, =(INF_REG_BASE+INF_REG0_OFFSET)
ldr r1, [r0] /* r1 = physical address of s5pc110_cpu_resume function*/
mov pc, r1 /*Jump to kernel */
nop
nop
总结回顾:lowlevel_init.S中总共做了哪些事情:
检查复位状态、IO恢复、关看门狗、开发板供电锁存、时钟初始化、DDR初始化、串口初始化并打印'O'、tzpc初始化、打印'K'。
其中值得关注的:关看门狗、开发板供电锁存、时钟初始化、DDR初始化、打印"OK"