U-boot(三):start.S

        本文主要探讨x210的uboot的start.S文件,也是uboot启动的第一阶段。

头文件

        config.h
                config.h == x210_sd.h,由mkconfig脚本生成,包含了开发板的配置宏 

root@kaxi-virtual-machine:~/qt_x210v3s_160307/uboot/include# cat config.h
/* Automatically generated - do not edit */
#include <configs/x210_sd.h>


        version.h

#ifndef __VERSION_H__
#define __VERSION_H__#ifndef DO_DEPS_ONLY
#include "version_autogenerated.h"
#endif#endif  /* __VERSION_H__ */

root@kaxi-virtual-machine:~/qt_x210v3s_160307/uboot/include# cat version_autogenerated.h 
#define U_BOOT_VERSION "U-Boot 1.3.4"

        定义uboot版本号,uboot启动时打印的版本信息


        asm/proc/domain.h
                asm/proc/domain.h == include/asm-arm/proc-armv/domain.h

        regs.h
                regs.h == s5pc110.h

16字节头

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED).word 0x2000.word 0x0.word 0x0.word 0x0
#endif

        定义16字节头,用于存放校验信息

异常向量表构建

.globl _start
_start: b    resetldr    pc, _undefined_instructionldr    pc, _software_interruptldr    pc, _prefetch_abortldr    pc, _data_abortldr    pc, _not_usedldr    pc, _irqldr    pc, _fiq_undefined_instruction:.word undefined_instruction
_software_interrupt:.word software_interrupt
_prefetch_abort:.word prefetch_abort
_data_abort:.word data_abort
_not_used:.word not_used
_irq:.word irq
_fiq:.word fiq
_pad:.word 0x12345678 /* now 16*4=64 */
/** the actual reset code*/reset:/** set the cpu to SVC32 mode and IRQ & FIQ disable*/@;mrs    r0,cpsr@;bic    r0,r0,#0x1f@;orr    r0,r0,#0xd3@;msr    cpsr,r0msr    cpsr_c, #0xd3        @ I & F disable, Mode: 0x13 - SVC

        将CPU设置为禁止FIQ和IRQ,置于ARM状态设置SVC模式
        CPU复位默认进入SVC模式,uboot工作于SVC模式

        .balignl 16,0xdeadbeef.    对齐访问效率快,是硬件要求

TEXT_BASE

_TEXT_BASE:.word    TEXT_BASE
root@kaxi-virtual-machine:~/qt_x210v3s_160307/uboot/board/samsung/x210# cat config.mk 
TEXT_BASE = 0xc3e00000
x210_nand_config :      unconfig@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk


        定义uboot链接地址(0xc3e00000)
        make x210_sd_config(调用mkconfig脚本)  ==>  uboot/board/samsung/x210/config.mk


CFG_PHY_UBOOT_BASE

_TEXT_PHY_BASE:.word    CFG_PHY_UBOOT_BASE

        CFG_PHY_UBOOT_BASE为0x33e0000是uboot在DDR中的物理地址


cpu_init_crit(设置L2、L1cache、MMU)
    bl    disable_l2cache                // 禁止L2 cache
    bl    set_l2cache_auxctrl_cycle    // l2 cache相关初始化
    bl    enable_l2cache                // 使能l2 cache
    刷新L1 cache、icache、dcache。
    关闭MMU

cpu_init_crit:bl    disable_l2cachebl    set_l2cache_auxctrl_cyclebl    enable_l2cache/** Invalidate L1 I/D*/mov    r0, #0                  @ set up for MCRmcr    p15, 0, r0, c8, c7, 0   @ invalidate TLBsmcr    p15, 0, r0, c7, c5, 0   @ invalidate icache/** disable MMU stuff and caches*/mrc    p15, 0, r0, c1, c0, 0bic    r0, r0, #0x00002000     @ clear bits 13 (--V-)bic    r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)orr    r0, r0, #0x00000002     @ set bit 1 (--A-) Alignorr    r0, r0, #0x00000800     @ set bit 12 (Z---) BTBmcr     p15, 0, r0, c1, c0, 0

启动介质选择

/* Read booting information */ldr    r0, =PRO_ID_BASEldr    r1, [r0,#OMR_OFFSET]bic    r2, r1, #0xffffffc1/* NAND BOOT */cmp    r2, #0x0        @ 512B 4-cyclemoveq    r3, #BOOT_NANDcmp    r2, #0x2        @ 2KB 5-cyclemoveq    r3, #BOOT_NANDcmp    r2, #0x4        @ 4KB 5-cycle    8-bit ECCmoveq    r3, #BOOT_NANDcmp    r2, #0x6        @ 4KB 5-cycle    16-bit ECCmoveq    r3, #BOOT_NANDcmp    r2, #0x8        @ OneNAND Muxmoveq    r3, #BOOT_ONENAND/* SD/MMC BOOT */cmp     r2, #0xcmoveq   r3, #BOOT_MMCSD    /* NOR BOOT */cmp     r2, #0x14moveq   r3, #BOOT_NOR    /* Uart BOOTONG failed */cmp     r2, #(0x1<<4)moveq   r3, #BOOT_SEC_DEVldr    r0, =INF_REG_BASEstr    r3, [r0, #INF_REG3_OFFSET]

        寄存器(0xE0000004)存储OM引脚接法,用于判断启动介质是Nand还是SD等


设置栈(SRAM栈)并调用lowlevel_init

/** Go setup Memory and board specific bits prior to relocation.*/ldr    sp, =0xd0036000 /* end of sram dedicated to u-boot */sub    sp, sp, #12    /* set stack */mov    fp, #0bl    lowlevel_init    /* go setup pll,mux,memory */

        设置栈(0xd0036000,第一次),当前代码在SRAM运行,DDR未初始化


lowlevel_init.S
        
uboot/board/samsumg/x210/lowlevel_init.S

push    {lr}


                由于lowlevel_init.S还调用了其他函数,防止之前的lr被覆盖(bl    lowlevel_init处的地址),需先入栈

        检查复位状态

/* check reset status  */ldr    r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)ldr    r1, [r0]bic    r1, r1, #0xfff6ffffcmp    r1, #0x10000beq    wakeup_reset_precmp    r1, #0x80000beq    wakeup_reset_from_didle

                CPU允许复位情况:冷上电、热启动、睡眠唤醒等
                依据复位状态初始化DDR:冷上电DDR需初始化,热启动或低功耗不需要

        IO状态恢复

/* IO Retention release */ldr    r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)ldr    r1, [r0]ldr    r2, =IO_RET_RELorr    r1, r1, r2str    r1, [r0]

        关看门狗

/* Disable Watchdog */ldr    r0, =ELFIN_WATCHDOG_BASE    /* 0xE2700000 */mov    r1, #0str    r1, [r0]

        SRAM,SROM的GPIO设置

/* SRAM(2MB) init for SMDKC110 *//* GPJ1 SROM_ADDR_16to21 */ldr    r0, =ELFIN_GPIO_BASEldr    r1, [r0, #GPJ1CON_OFFSET]bic    r1, r1, #0xFFFFFFldr    r2, =0x444444orr    r1, r1, r2str    r1, [r0, #GPJ1CON_OFFSET]ldr    r1, [r0, #GPJ1PUD_OFFSET]ldr    r2, =0x3ffbic    r1, r1, r2str    r1, [r0, #GPJ1PUD_OFFSET]/* GPJ4 SROM_ADDR_16to21 */ldr    r1, [r0, #GPJ4CON_OFFSET]bic    r1, r1, #(0xf<<16)ldr    r2, =(0x4<<16)orr    r1, r1, r2str    r1, [r0, #GPJ4CON_OFFSET]ldr    r1, [r0, #GPJ4PUD_OFFSET]ldr    r2, =(0x3<<8)bic    r1, r1, r2str    r1, [r0, #GPJ4PUD_OFFSET]/* CS0 - 16bit sram, enable nBE, Byte base address */ldr    r0, =ELFIN_SROM_BASE    /* 0xE8000000 */mov    r1, #0x1str    r1, [r0]

        供电锁存

/* PS_HOLD pin(GPH0_0) set to high */ldr    r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)ldr    r1, [r0]orr    r1, r1, #0x300    orr    r1, r1, #0x1    str    r1, [r0]

        判断执行代码位置

/* when we already run in ram, we don't need to relocate U-Boot.* and actually, memory controller must be configured before U-Boot* is running in ram.*/ldr    r0, =0xff000fffbic    r1, pc, r0        /* r0 <- current base addr of code */ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram */bic    r2, r2, r0        /* r0 <- current base addr of code */cmp     r1, r2                  /* compare r0, r1                  */beq     1f            /* r0 == r1 then skip sdram init   */

                对比运行地址和链接地址来判断在SRAM中(不相等)还是DDR中(相等),从而决定是否要时钟和DDR初始化


        system_clock_init,x210_sd.h有时钟相关配置值
        mem_ctrl_asm_init(uboot/cpu/s5pc11x/s5pc110/cpu_init.S)初始化DDR
        uboot中DMC0的256MB内存地址范围为0x30000000-0x3FFFFFFF
        uboot物理地址范围为:0x30000000-0x4FFFFFFF共512MB,30000000-3FFFFFFF为DMC0,40000000-4FFFFFFF为DMC1
        uart_asm_init初始化串口,发送'O',
        tzpc_init,trust zone初始化
        通过串口打印'K'


设置栈(33E00000,DDR栈,二次)和重定位

/* get ready to call C functions */ldr    sp, _TEXT_PHY_BASE    /* setup temp stack pointer */sub    sp, sp, #12mov    fp, #0            /* no previous frame, so fp=0 *//* when we already run in ram, we don't need to relocate U-Boot.* and actually, memory controller must be configured before U-Boot* is running in ram.*/ldr    r0, =0xff000fffbic    r1, pc, r0        /* r0 <- current base addr of code */ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram */bic    r2, r2, r0        /* r0 <- current base addr of code */cmp     r1, r2                  /* compare r0, r1                  */beq     after_copy        /* r0 == r1 then skip flash copy   */#if defined(CONFIG_EVT1)/* If BL1 was copied from SD/MMC CH2 */ldr    r0, =0xD0037488ldr    r1, [r0]ldr    r2, =0xEB200000cmp    r1, r2beq     mmcsd_boot
#endifldr    r0, =INF_REG_BASEldr    r1, [r0, #INF_REG3_OFFSET]cmp    r1, #BOOT_NAND        /* 0x0 => boot device is nand */beq    nand_bootcmp    r1, #BOOT_ONENAND    /* 0x1 => boot device is onenand */beq    onenand_bootcmp     r1, #BOOT_MMCSDbeq     mmcsd_bootcmp     r1, #BOOT_NORbeq     nor_bootcmp     r1, #BOOT_SEC_DEVbeq     mmcsd_bootnand_boot:mov    r0, #0x1000bl    copy_from_nandb    after_copyonenand_boot:bl    onenand_bl2_copyb    after_copymmcsd_boot:
#if DELETEldr     sp, _TEXT_PHY_BASE      sub     sp, sp, #12mov     fp, #0
#endifbl      movi_bl2_copyb       after_copynor_boot:bl      read_hwordb       after_copy

        冷启动uboot的16kb从SD卡加载到SRAM中运行,要加载第二部分(SD卡)到DDR中(33e00000)
        D0037488内存地址(SRAM)是硬件设置,根据SD启动的通道修改值,EB000000为SD1启动,EB200000为SD2启动
        start.S的260确定MMCSD启动,278将BOOT_MMCSD写入INF_REG3寄存器,322读去并和和BOOT_MMCSD对比确定从MMCSD启动,跳转到mmcsd_boot
        uboot/cpu/s5pc11x/movi.c中调用movi_bl2_copy函数完成重定位

copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,CFG_PHY_UBOOT_BASE, 0);

                2表示通道2
                MOVI_BL2_POS第二部分在SD卡中的开始扇区,和烧录uboot烧录位置相同
                MOVI_BL2_BLKCNT是uboot长度占用的扇区数
                CFG_PHY_UBOOT_BASE是重定位将第二部分复制到DDR中的起始地址(33E00000)

虚拟地址映射

after_copy:#if defined(CONFIG_ENABLE_MMU)
enable_mmu:/* enable domain access */ldr    r5, =0x0000ffffmcr    p15, 0, r5, c3, c0, 0        @load domain access register/* Set the TTB register */ldr    r0, _mmu_table_baseldr    r1, =CFG_PHY_UBOOT_BASEldr    r2, =0xfff00000bic    r0, r0, r2orr    r1, r0, r1mcr    p15, 0, r1, c2, c0, 0/* Enable the MMU */
mmu_on:mrc    p15, 0, r0, c1, c0, 0orr    r0, r0, #1mcr    p15, 0, r0, c1, c0, 0nopnopnopnop
#endif

        MMU实现虚拟地址到物理地址映射,在CP15协处理器中进行控制
        cp15的c3寄存器是使能域访问,及控制访问权限
        cp15的c2寄存器是设置TTB(转换表基地址)
        转换表是虚拟地址映射的关键包含表索引和表项,表索引对应虚拟地址,表项对应物理地址,表索引和表项构成转换表单元,可对内存块进行虚拟地址转换(ARM中包含3种块大小:细表1KB、粗表4KB、段1MB),转换表由转换表单元构成,每个单元对应1个内存块,整体对应整个内存空间(0-4G)的映射
        转换表在内存中,将基地址TTB设置到cp15的c2寄存器中,MMU工作时自动调用
        cp15的c1寄存器使能MMU单元

再次设置栈(三次,DDR)

skip_hw_init:/* Set up the stack                            */
stack_setup:
#if defined(CONFIG_MEMORY_UPPER_CODE)ldr    sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)
#elseldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */sub    r0, r0, #CFG_MALLOC_LEN    /* malloc area                      */sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#if defined(CONFIG_USE_IRQ)sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endifsub    sp, r0, #12        /* leave 3 words for abort-stack    */#endif

        栈设置在uboot起始地址上方2MB处,安全栈空间是:2MB减去uboot大小

清理bss

clear_bss:ldr    r0, _bss_start        /* find start of bss segment        */ldr    r1, _bss_end        /* stop here                        */mov     r2, #0x00000000        /* clear                            */clbss_l:str    r2, [r0]        /* clear loop...                    */add    r0, r0, #4cmp    r0, r1ble    clbss_l

执行二阶段代码

ldr    pc, _start_armboot_start_armboot:.word start_armboot#if defined(CONFIG_ENABLE_MMU)
_mmu_table_base:.word mmu_table
#endif

        start_armboot在uboot/lib_arm/board.c

uboot一阶段
       
构建异常向量表,启动介质选择,设置CPU为SVC模式,关看门狗,开发板供电置锁,时钟初始化,DDR初始化,串口初始化并打印"OK",重定位,建立映射表并开启MMU,清理bss,跳转到第二阶段

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

el-date-picker ie模式下 初始化未赋值;未清空

el-date-picker ie模式下 初始化未赋值;未清空 给 dete-picker 加key属性 eg:

接口自动化测试实战:JMeter+Ant+Jenkins+钉钉机器人群通知完美结合

前言 一、本地JAVA环境安装配置,安装JAVA8和JAVA17 二、安装和配置Jmeter 三、安装和配置ant 四、jmeter + ant配置 五、jenkins安装和配置持续构建项目 六、jenkins配置流程 前言 搭建jmeter+ant+jenkins环境有些前提条件,那就是要先配置好java环境,本地java环境…

redis的高可用

redis-cli -h 192.168.233.10 -p 6379 redis的数据类型的增删改查 redis的高可用在集群当中有一个非常重要的指标&#xff0c;提供正常服务的时间的百分比(365天) 99.9% redis的高可用含义更加广泛&#xff0c;正常服务是指标之一&#xff0c;数据容量的扩展&#xff0c;数据…

2023亚太杯数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

给新手教师的成长建议

随着教育的不断发展和进步&#xff0c;越来越多的新人加入到教师这个行列中来。从学生到教师&#xff0c;这是一个华丽的转身&#xff0c;需要我们不断地学习和成长。作为一名新手老师&#xff0c;如何才能快速成长呢&#xff1f;以下是一名老师教师给的几点建议&#xff1a; 一…

人工智能对我们的生活影响有多大

随着科技的飞速发展&#xff0c;人工智能已经渗透到我们生活的方方面面&#xff0c;并且越来越受到人们的关注。从智能语音助手到自动驾驶汽车&#xff0c;从智能家居系统到医疗诊断&#xff0c;人工智能技术正在改变着我们的生活方式。那么&#xff0c;人工智能对我们的生活影…

使用 RAFT 的光流:第 1 部分

一、说明 在这篇文章中&#xff0c;我们将了解一种旗舰的光流深度学习方法&#xff0c;该方法获得了 2020 年 ECCV 最佳论文奖&#xff0c;并被引用超过 1000 次。它也是KITTI基准测试中许多性能最佳的模型的基础。该模型称为 RAFT&#xff1a;Recurrent All-Pairs Field Trans…

微信表情太大怎么缩小?一分钟教会你!

在微信的较早版本中&#xff0c;单个表情的最大体积限制为500KB&#xff0c;而在后续版本中&#xff0c;这一限制已经放宽。目前&#xff0c;微信允许上传的单个表情最大体积为2MB。所以&#xff0c;我们只需要把图片或者GIF缩小到2MB即可&#xff0c;下面就向大家介绍三种实用…

如何给面试官解释什么是分布式和集群?

分布式&#xff08;distributed&#xff09; 是指在多台不同的服务器中部署不同的服务模块&#xff0c;通过远程调用协同工作&#xff0c;对外提供服务。 集群&#xff08;cluster&#xff09; 是指在多台不同的服务器中部署相同应用或服务模块&#xff0c;构成一个集群&#…

(论文阅读40-45)图像描述1

40.文献阅读笔记&#xff08;m-RNN&#xff09; 简介 题目 Explain Images with Multimodal Recurrent Neural Networks 作者 Junhua Mao, Wei Xu, Yi Yang, Jiang Wang, Alan L. Yuille, arXiv:1410.1090 原文链接 http://arxiv.org/pdf/1410.1090.pdf 关键词 m-RNN、…

Java面试题07

1.线程池都有哪些状态&#xff1f; 线程池的状态有RUNNING&#xff08;运行中&#xff09;、SHUTDOWN&#xff08;关闭中&#xff0c;不接受新任务&#xff09;、 STOP&#xff08;立即关闭&#xff0c;中断正在执行任务的线程&#xff09;和TERMINATED&#xff08;终止&#x…

数字化转型与企业创新—基于中国上市公司年报的经验证据(2007-2022年)

参照潘红波&#xff08;2022&#xff09;的做法&#xff0c;对来自中南大学学报《数字化转型与企业创新—基于中国上市公司年报的经验证据》一文中的基准回归部分进行复刻。文章实证检验数字化转型对企业创新的影响。用年报词频衡量 一、数据介绍 数据名称&#xff1a;数字化转…

【C++心愿便利店】No.14---C++之探索list底层原理

文章目录 前言一、list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1.2.6 list operations1.2.7 list的迭代器失效 二、list的模拟实现2.1 定义一个结构体实现list的…

深入分析TaskView源码之触摸相关

问题背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;android 10以后TaskView作为替代ActivityView的容器&#xff0c;在课程的分屏pip自由窗口专题也进行了相关的详细介绍分析。 这里再补充一下相关的TaskView和桌面内嵌情况下的触摸分析 主要问题点&#xff…

【经验分享】Ubuntu如何设置swap交换

我的Linux小鸡内存只有512兆&#xff0c;经常爆内存&#xff0c;导致很多应用没有办法一直正常运行&#xff0c;可以通过设置swap来缓解一下&#xff0c;虽然和内存的速度无法媲美&#xff0c;但是能一定程度缓解一下问题 文章目录 1. 创建一个交换文件2. 设置正确的权限3. 设置…

腾讯云标准型s5和s6有什么区别?CPU处理器有差异吗?

腾讯云服务器CVM标准型S5和S6有什么区别&#xff1f;都是标准型云服务器&#xff0c;标准型S5是次新一代云服务器规格&#xff0c;标准型S6是最新一代的云服务器&#xff0c;S6实例的CPU处理器主频性能要高于S5实例&#xff0c;同CPU内存配置下的标准型S6实例要比S5实例性能更好…

【开源】基于JAVA的社区买菜系统

项目编号&#xff1a; S 011 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S011&#xff0c;文末获取源码。} 项目编号&#xff1a;S011&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 数据中心模块2.1…

OpenLDAP配置web管理界面PhpLDAPAdmin服务-centos9stream

之前已经发了一篇关于centos9下面配置openldap多主高可用集群的内容&#xff0c;不会配置ldap集群的请参考&#xff1a;服务器集群配置LDAP统一认证高可用集群&#xff08;配置tsl安全链接&#xff09;-centos9stream-openldap2.6.2-CSDN博客 这里跟着前篇文章详细说明如何配置…

RESTful API 设计指南——为什么要用(上)

引言 在上一篇中&#xff1a;RESTful API 设计指南——开篇词 我们介绍了几个十分有争议的案例&#xff1a; 所有的接口都使用Post请求不管成功还是失败&#xff0c;HTTP状态码都返回200API命名千奇百怪 本章我们来深入分析一下&#xff0c;为什么不要像案例中所说的那样干…

Vscode GDB 查看内存的值

在VSCode的GDB图形界面中&#xff0c;你可以使用"调试控制台(Debug Console)"来查看malloc返回的地址里的值。以下是具体的步骤&#xff1a; 首先&#xff0c;你需要在你的代码中设置一个断点&#xff0c;这个断点应该在malloc函数调用之后&#xff0c;这样你可以获…