Uboot23之uart初始化

本文详细解析了U-Boot启动过程中的lowlevel_init.S函数,包括检查复位状态、IO恢复、关闭看门狗、时钟初始化、DDR内存初始化等关键步骤,并介绍了如何通过串口打印OK来验证初始化成功。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间: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.youkuaiyun.com/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"

### RK3566 U-Boot GPIO 初始化配置教程 对于RK3566平台,在U-Boot阶段初始化GPIO涉及多个方面的工作,包括但不限于设置引脚的功能、方向以及初始电平等。基于不同版本的U-Boot和具体的硬件设计需求,实现细节可能有所差异。 #### 修改`board_f.c`文件以支持特定于RK3566的GPIO操作 为了自定义GPIO的行为,通常需要编辑位于源码中的`/u-boot/common/board_f.c`这样的文件来加入针对目标芯片特性的处理逻辑。例如: ```c #include <linux/io.h> #define GPIO_BASE_ADDR 0xFF7C_0000 // 假设这是RK3566上GPIO寄存器基地址[^1] // 定义具体要控制的GPIO端口及其偏移量 #define GPIOX_DR_OFFSET 0x0000 #define GPIOX_DDR_OFFSET 0x0004 unsigned int *gpio_data_register; unsigned int *gpio_direction_register; void init_gpio(void){ gpio_data_register = (unsigned int*)(GPIO_BASE_ADDR + GPIOX_DR_OFFSET); gpio_direction_register = (unsigned int*)(GPIO_BASE_ADDR + GPIOX_DDR_OUTPUT); // 设置某些位为输出模式 writel((readl(gpio_direction_register)|OUTPUT_PIN_MASK), gpio_direction_register); // 将指定管脚拉高或拉低 if(HIGH_LEVEL_REQUIRED){ setbits_le32(gpio_data_register, OUTPUT_PIN_MASK); }else{ clrbits_le32(gpio_data_register, OUTPUT_PIN_MASK); } } ``` 这段代码展示了如何通过访问内存映射I/O区域内的专用寄存器来进行基本的GPIO配置。需要注意的是实际开发过程中应当参照最新的官方文档确认确切的寄存器位置和其他参数值[^4]。 #### 设备树中描述GPIO属性 除了直接编程外,现代嵌入式Linux系统往往依赖设备树(Device Tree)来传递有关外围接口的信息给内核及引导加载程序。因此,在适当的位置添加关于所需GPIO资源的相关节点也是必要的步骤之一。这可以通过调整`.dts`(device tree source) 文件完成: ```diff &iomux { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart0_default>; + pinctrl-gpios: gpios@0 { + compatible = "rockchip,rk3566-pinctrl"; + rockchip,pins = < + /* Pin number */ + 0x0A /* Function code for output */ + ROCKCHIP_PULL_NONE + ROCKCHIP_DRIVE_STRENGTH_DEFAULT + ROCKCHIP_SCHMITT_NORMAL>; + }; }; ``` 上述片段说明了怎样向现有的设备树结构里引入新的子节点用于表达一组预设好的GPIO特性集合[^2]。 #### 编译并测试更改后的固件 最后一步就是编译整个项目并将生成的目标镜像烧录到目标板卡上去验证效果。确保遵循标准流程执行这些任务可以减少潜在的风险因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值