U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析

2024-01-25 17:08

本文主要是介绍U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析
本文主要分析与U-Boot启动过程相关的汇编代码lowlevel_init.S,目标平台以PXA270为例。
文件位于board/myboard/lowlevel_init.S,主要执行内存相关的初始化
  • 把链接寄存器LR(即R14)的值转存到寄存器R10中,以便lowlevel_init完成后恢复执行
.globl lowlevel_init
lowlevel_init:
    mov      r10, lr 
  • 按顺序初始化GPIO寄存器: GPSR GPCR GRER GFER GPDR GAFR PSSR
/* Set up GPIO pins first */
   ldr      r0,   =GPSR0
   ldr      r1,   =CFG_GPSR0_VAL
   str      r1,   [r0]
   .....
  • 初始化内存控制器
/* Initlialize Memory Controller */
   @ skip memory init if we're run in ram(must be a JTAG run)
   mov r0, pc
   ldr r1, =0xa0000000
   and r0, r0, r1    /* 把当前PC寄存器的值与0xa0000000逻辑与*/
   cmp r0, r1        /* 如果结果等于0xa0000000,说明uboot是从RAM启动的 */
   beq mem_init_done    /* 那么就需要跳过RAM初始化, 直接跳转到mem_init_done执行 */

/* 具体的初始化操作与目标板有很大相关性,下面以我的PXA270开发板为例 */

mem_init:
   @ get memory controller base address
   ldr     r1,  =MEMC_BASE    /* 内存控制器基地址 */
  • 初始化内存控制器 Step 1

@****************************************************************************
@  Step 1
@
   
   @ Step 1a
    /* Initlialize Static Memory Control register */
    /*  初始化MSCx寄存器需要设置 */
    /* RBUFFx —— Return Data Buffer vs. Streaming Behavior */
    /* RRRx —— ROM/SRAM Recovery Time */
    /* RDNx —— ROM Delay Next Access */
    /* RDFx —— The ROM Delay First Access */
    /* RBWx —— ROM Bus Width */
    /* RTx —— ROM Type */
   @ write msc0, read back to ensure data latches
   ldr     r2,   =CFG_MSC0_VAL
   str     r2,   [r1, #MSC0_OFFSET]
   ldr     r2,   [r1, #MSC0_OFFSET]    /* Ensure that the new value has been accepted and programmed */
   ......

   @ Step 1b
    /* 配置PCMCIA和CF需要设置下面这些寄存器 */
   @ MECR —— Expansion Memory (PC Card/CompactFlash) Bus Configuration register 
   @ MCMEMx —— PC Card Interface Common Memory Space Socket 0/1 Timing Configuration register
   @ MCATTx —— PC Card Interface Attribute Space Socket 0/1 Timing Configuration register
   @ MCIOx —— PC Card Interface I/O Space Socket 0/1 Timing Configuration register

   @ Step 1c
   @ fly-by-dma is defeatured on this part
   @ write flycnfg —— Fly-by DMA DVAL<1:0> polarities
   @ldr     r2,  =CFG_FLYCNFG_VAL
   @str     r2,  [r1, #FLYCNFG_OFFSET]

   @ Step 1d
   @ fetch platform value of mdcnfg —— SDRAM Configuration register
   @
   ldr     r2,  =CFG_MDCNFG_VAL

   @ disable all sdram banks
   @
   bic     r2,  r2,  #(MDCNFG_DE0 | MDCNFG_DE1)
   bic     r2,  r2,  #(MDCNFG_DE2 | MDCNFG_DE3)
   str r2, [r1, #MDCNFG_OFFSET]

   @ Step 1e
   @ write MDREFR —— SDRAM Refresh Control register
   ldr r3, = CFG_MDREFR_VAL
   ldr r2, = 0xFFF    /* DRI mask */
   and r3, r3, r2
   ldr r4, [r1, #MDREFR_OFFSET]    /* reset value */
   bic r4, r4, r2    /* clear DRI field  —— SDRAM Refresh Interval for All Partitions */
   orr r4, r4, r3
   orr r4, r4, #MDREFR_K0RUN    /* SDCLK0 Run Control/Status */
   bic r4, r4, #MDREFR_K0DB2    /* SDCLK0 Divide by 2 Control/Status */
   bic r4, r4, #MDREFR_K0DB4    /* SDCLK0 Divide by 4 Control/Status */
   bic r4, r4, #MDREFR_K2FREE   /* SDCLK<2> Free-Running Control */
   bic r4, r4, #MDREFR_K1FREE
   bic r4, r4, #MDREFR_K0FREE
   orr r4, r4, #MDREFR_SLFRSH  /* SDRAM Self-Refresh Control/Status, Self-refresh enabled */
   /* write back MDREFR */
   str r4, [r1, #MDREFR_OFFSET]
  • 初始化内存控制器 Step 2
@ Step 2
   @ Configure synchronus flash memory
  • 初始化内存控制器 Step 3
@ Step 3
   @ Configure SDRAM
   ldr r2, =CFG_MDREFR_VAL
   bic r2, #MDREFR_APD    /* SDRAM/Synchronous Static Memory Auto-Power-Down Enable */
   str r2, [r1, #MDREFR_OFFSET]
   ldr r3, [r1, #MDREFR_OFFSET]        @ read back to make sure write action completed

  • 初始化内存控制器 Step 4
@ Step 4
   @ write initial value of mdcnfg, w/o enabling sdram banks
   @
   ldr r2, =CFG_MDCNFG_VAL
   bic r2,  r2,  #(MDCNFG_DE0 | MDCNFG_DE1)
   bic r2,  r2,  #(MDCNFG_DE2 | MDCNFG_DE3)
   str r2, [r1, #MDCNFG_OFFSET]

   @ldr r2, = CFG_MDREFR_VAL
   @str r2, [r1, #MDREFR_OFFSET]
  • 初始化内存控制器 Step 5
@ Step 5
   @ pause for 200 uSecs
   @
   ldr r3, =OSCR       @ reset the OS Timer Count to zero
   mov r2, #0
   str r2, [r3]
   ldr r4, =0x300            @ really 0x2E1 is about 200usec, so 0x300 should be plenty ——3.25MHz clock
1:
   ldr r2, [r3]    /* r2读OS Timer Count*/
   cmp r4, r2    /* 比较OS Timer Count和r4 */
   bgt 1b        /* 如果时间没到就循环 */
  • 初始化内存控制器 Step 6
@ Step 6
   @ Disable XScale Data Cache
   mov    r0, #0x78                @turn everything off
   mcr    p15, 0, r0, c1, c0, 0      @(caches off, MMU off, etc.)    /* 设置协处理器P15 */
  • 初始化内存控制器 Step 7 - 11
@ Step 7
   @ Access memory *not yet enabled* for CBR refresh cycles (8) *NOTE: hardware reset only
   @ - CBR is generated for all banks

   ldr     r2, =CFG_DRAM_BASE
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]
   str     r2, [r2]

   @ Step 8
   @ Enable data cache

   @ Step 9
   @ Enable SDRAM

   @fetch current mdcnfg value
   ldr     r3,  [r1, #MDCNFG_OFFSET]
   orr     r3,  r3,  #MDCNFG_DE0    /* enable sdram bank0 */

   @write back mdcnfg, enabling the sdram bank(s)
   str     r3,  [r1, #MDCNFG_OFFSET]

   @ Step 10
   @ write mdmrs —— SDRAM Mode Register Set Configuration Register
   @
   ldr     r2,  =CFG_MDMRS_VAL
   str     r2,  [r1, #MDMRS_OFFSET]

   @ Step 11
   @ Enable MDREFR[APD] optionally
   ldr r2, =CFG_MDREFR_VAL
   str r2, [r1, #MDREFR_OFFSET]
  • Done Memory Init
mem_init_done:

   @********************************************************************
   @ Disable (mask) all interrupts at the interrupt controller
   @

   @ clear the interrupt level register (use IRQ, not FIQ)
   @
   mov     r1, #0
   ldr     r2,  =ICLR
   str     r1,  [r2]

   @ Set interrupt mask register
   @
   ldr     r1,  =CFG_ICMR_VAL    /* set ICMR = 0, no interrupts enabled */
   ldr     r2,  =ICMR
   str     r1,  [r2]

   @ ********************************************************************
   @ Disable the peripheral clocks, and set the core clock
   @

    @ Turn Off ALL on-chip peripheral clocks for re-configuration
    @
    ldr     r1,  =CKEN    /*clock enable register */
    mov     r2,  #0
    str     r2,  [r1]

   @ set core clocks
   @
   ldr     r1,  =CCCR    /* core clock configuration register */
   ldr     r2,  [r1, #0]
   ldr r3, =(CCCR_L_MASK | CCCR_2N_MASK)
   bic r2, r2, r3
   /* Run-Mode-to-Oscillator Ratio (L) creates the nominal run mode frequency by multiplying the 13-MHz processor oscillator by L. */
   /* Turbo-Mode-to-Run-Mode Ratio (N) creates the nominal turbo-mode frequency by multiplying the run-mode frequency by N. */
   /* core freq: Normal 208MHz, Turbo 312MHz */
   ldr r3, =(16 | 3<<7)    /* Turbo-Mode-to-Run-Mode Ratio, N = 3/2 */
   orr r2, r2, r3              /*  Run-Mode-to-Oscillator Ratio = 16*13 MHz,  */
   str     r2,  [r1]

#ifdef ENABLE32KHZ
   @ enable the 32Khz oscillator for RTC and PowerManager
   @
   ldr     r1,  =OSCC    /* oscillator configuration register */
   mov     r2,  #OSCC_OON    /* 32.768kHz OON (write-once only bit) */
   str     r2,  [r1]

   @ NOTE:  spin here until OSCC.OOK get set,
   @        meaning the PLL has settled.
   @
60:
   ldr     r2, [r1]
   ands    r2, r2, #1    /* r2 = r2 & 0x1, 取出最低位数据 */
   beq     60b
#endif

    @ Turn on needed clocks
    @
   ldr     r1,  =CKEN
   ldr     r2,  =CFG_CKEN_VAL
   str     r2,  [r1]
  • lowlevel_init完成
   mov   pc, r10    /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */

@ End lowlevel_init

这篇关于U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/643979

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热