一、代码分析

  上一节已经分析了链接文件,知道了首先代码是从 _start 开始,之后设置了中断向量表,然后从 start.s 开始运行。

  • _start:vectors.S (arch\arm\lib)
  • reset:start.S (arch\arm\cpu\arm920t)
  • _main:crt0.S (arch\arm\lib)
  • board_init_f:Board_f.c (common)

1.1 vectors.S

  vectors.S 为软件起始,标记_start,在此文件中,主要是定义异常向量定义表,定义了发生异常后,所做的处理,程序的一开头,就跳转到  reset 中去运行了,其实这才是程序真正开始运行了

  

1.2 start.S

1.2.1 arm 的工作模式

  • ARM微处理器的工作状态一般有两种,并可在两种状态之间切换:

    • 第一种为ARM状态,此时处理器执行32位的字对齐的ARM指令;
    • 第二种为Thumb状态,此时处理器执行16位的、半字对齐的Thumb指令。
  • 工作模式有:
    • 用户模式(usr , User Mode)。ARM处理器正常的程序执行状态。 
    • 快速中断模式(fiq , Fast Interrupt Request Mode)。用于高速数据传输或通道处理。当触发快速中断时进入此模式。
    • 外部中断模式 ( irq , Interrupt Request Mode )。用于通用的中断处理。当触发外部中断时进入此模式。
    • 管理模式 ( svc , Supervisor Mode )。操作系统使用的保护模式。在系统复位或者执行软件中断指令SWI时进入。 
    • 数据访问终止模式 ( abt , Abort Mode )。当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护。
    • 系统模式(sys , System Mode )。运行具有特权的操作系统任务。
    • 未定义指令中止模式 ( und , Undefined Mode )。当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

1.2.2 ARM 状态的寄存器与 Thumb 状态的寄存器之间的关系

  • ARM 与 Thumb 状态寄存器之间有如下关系:

    • Thumb 状态的 R0-R7 与 ARM 状态的 R0-R7 相同
    • Thumb 状态的 CPSR 和 SPSR 与 ARM 状态的 CPSR 和 SPSR 相同
    • Thumb 状态的 SP 映射到 ARM 状态的 R13
    • Thumb 状态的 LR 映射到 ARM 状态的 R14
    • Thumb 状态的程序计数器映射到 ARM 状态的程序计数器(R15)

  

1.2.3 程序状态寄存器

  ARM920T 包含了一个当前程序状态寄存器(Current Program Status Register-CPSR),另外还有 5 个用于异常程序处理的程序状态保存寄存器(Saved Program Status Registers-SPSR) 。这些寄存器的功能为:

  • 保存最近已处理的 ALU 操作的信息
  • 控制中断的使能与禁止
  • 设置处理器的运行模式

  程序状态寄存器的格式为:  

  

  • 状态代码标志位

    • N,Z,C 和 V 位为状态代码标志位。算术或逻辑操作结果可能会改变这些位,并检验以决定是否应该执行某
      条指令
    • 在 ARM 状态,所有指令都可能为条件执行
    • 在 Thumb 状态,只有分支指令才能条件执行
  • 控制位
    • PSR (包含 I,F,T 和 M[4:0])的末端 8 位统称为控制位。 当发生异常时将会改变这些位。如果处理器运行在特
      权模式,它们也可由软件控制。

  

  

  ARM上电一启动,就是首先将自己设置位 SVC32模式:

  1. /*
  2. * set the cpu to SVC32 mode
  3. */
  4. mrs r0, cpsr /* 移动状态/标志位,从 CPSR 到寄存器 r0 */
  5. bic r0, r0, #0x1f /* 将r0 中的后5位清0,bic:(位清除)指令对 r0 中的值 和 0x1f(0x0001 1111) 的反码按位进行逻辑“与”运算。 */
  6. orr r0, r0, #0xd3 /* 将r0 与 0xd3(0x1101 0011) 进行或运算,变成SVC 模式*/
  7. msr cpsr, r0 /* 移动状态/标志位,从寄存器数据到 CPSR */

1.2.4 关闭看门狗

  • WTCON:看门狗定时器控制器。

    • WTCON 寄存器允许用户使能或禁止看门狗定时器、从 4 个不同源选择时钟信号、使能或禁止中断和使能或禁止看门狗定时器输出。
    • 看门狗定时器是用于恢复 S3C2440 上电后若有故障重时新启动;如果不希望控制器重新启动,则应该禁止看门狗定时器。
    • 如果用户希望使用看门狗定时器作为普通定时器,则应使能中断并且禁止看门狗定时器。   

  

1.2.5 屏蔽中断

  • 程序状态寄存器(PSR)的 F 位和 I 位:

    • 如果 ARM920T CPU 中的 PSR 的 F 位被置位为 1,CPU 不会接受来自中断控制器的快中断请求(FIQ)。
    • 同样的如果 PSR 的 I 位被置位为 1,CPU 不会接受来自中断控制器的中断请求(IRQ)。
    • 因此,中断控制器可以通过清除 PSR 的 F 位和 I 位为 0 并且设置 INTMSK 的相应位为 0 来接收中断
  • 中断屏蔽寄存器 :INTMSK
    • 此寄存器表明如果中断相应的屏蔽位被置位为 1 则禁止该中断。
    • 如果某个 INTMSK 的中断屏蔽位为 0,将正常服务中断。
    • 如果 INTMSK 的中断屏蔽位为 1 并且产生了中断,将置位源挂起位。
    • 此寄存器由 32 位组成,其每一位都都涉及一个中断源。
    • 如果某个指定为被设置为 1,则 CPU 不会去服务来自相应中断源(请注意即使在这种情况中,SRCPND 寄存器的相应位也设置为 1)的中断请求。
    • 如果屏蔽位为 0,则可以服务中断请求。

  

1.2.6 设置始终分频

  • S3C2440A 中的时钟控制逻辑可以产生必须的时钟信号:

    • CPU时钟信号:FCLK,FCLK 是提供给 ARM920T 的时钟。 Fclk 最高 400MHz
    • AHB总线外设时钟信号:HCLK,HCLK 是提供给用于 ARM920T,存储器控制器,中断控制器,LCD 控制器,DMA 和 USB 主机模块的 AHB
      总线的时钟。
      Hclk 最高 136MHz
    • APB总线外设始终信号:PCLK,PCLK 是提供给用于外设如 WDT,IIS,I2C,PWM 定时器,MMC/SD 接口,ADC,UART,GPIO,RTC 和
      SPI 的 APB 总线的时钟。
      Pclk 最高 68MHz
  • S3C2440A 包含两个锁相环(PLL) :一个提供给 FCLK、HCLK 和 PCLK,另一个专用于USB 模块(48MHz)
    • UPLL 产生时钟运作 USB 主机/设备
    • MPLL 产生时钟运作 1.3V 下最高 400MHz 的 MCU ,300MHz 下 1.20V   
  • 时钟控制逻辑可以不使用 PLL 来减慢时钟,并且可以由软件连接或断开各外设模块的时钟,以降低功耗。
  • 主时钟源来自一个外部晶振(XTIpll)或外部时钟(EXTCLK)
    • 模式控制引脚(OM3 和 OM2)的组合关系的并为 S3C2440A 选择时钟源。 JZ2440开发板上OM2和OM3接地,为低电平 00
    • 下图是引导启动(boot-up)时,时钟源的选择

  

    • 可以看出我们的时钟源:MPLL开启,UPLL开启,主时钟源为晶振,USB时钟源为晶振  
    • 虽然 MPLL 在复位后就开始, MPLL 输出 (Mpll) 并没有作为系统时钟, 直到软件写入有效值来设置 MPLLCON寄存器。
    • 在设置此值之前, 是将外部晶振或外部时钟源提供的时钟直接作为系统时钟。
    • 即使用户不想改变 MPLLCON 寄存器的默认值,用户也应当写入与之相同的值到 MPLLCON 寄存器寄存器中。
      即是说我们在设置时钟分频之前,需要设置MPLLCON寄存器的值
    • FCLKOUT 必须大于 200MHz(这并不意味着 ARM 内核必须在高于 200MHz 下运行)
  • S3C2440A 还支持对 FCLK、 HCLK 和 PCLK 之间分频比例的选择。 该比例由 CLKDIVN 控制寄存器中的 HDIVN和 PDIVN 所决定

  

  • 总结操作时钟的步骤:

    • 首先是 硬件管脚 OM2和 OM3 确定时钟的模式
    • 其次是 设置 MPLLCON 寄存器的值  
    • 最后是 设置时钟分频
  • PLL控制寄存器

  

  • MPLL和UPLL时钟频率计算

    • Fin:输入频率,由原理图可以知道,XTIpll 和  XTOpll 引脚接入的为 12MHZ晶振
    • m,p,s:分频,对应PLLCON的位如下:

  

  

  注意:当你设置 MPLL 和 UPLL 的值时,你必须首先设置 UPLL 值再设置 MPLL 值。 (大约需要 7 个 NOP 的间隔)

  • 时钟分频寄存器:CLKDIVN

  

  

  需要注意的是,如果 HDIVN 不为 0,CPU 总线模式应该使用以下指令使其从快总线模式改变为异步总线模式(S3C2440不支持同步总线模式)。

  如果 HDIVN 不为 0 并且 CPU 总线模式为快总线模式,CPU 运行在 HCLK。 在不影响 HCLK 和PCLK 的情况下
,可以用此特性改变 CPU 频率为一半或更多。

  应当谨慎设置 CLKDIVN,不要使其超过 HCLK 和 PCLK 的最大值。

  

  但我们启动的时候,我们的MMU还没有进行初始化,这个时候我们不用设置MMU,并且,在启动过程中,我们会关闭MMU,所以模式的改变不需要。

  最后的代码为:

  1. #if defined(CONFIG_S3C24X0)
  2. #if defined(CONFIG_S3C2400)
  3. # define pWTCON 0x15300000
  4. # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */
  5. # define CLKDIVN 0x14800014 /* clock divisor register */
  6. #else
  7. # define pWTCON 0x53000000 /* 看门狗定时器控制寄存器,地址位 0x53000000,复位值 0x8021 */
  8. # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */
  9. # define INTSUBMSK 0x4A00001C
  10. # define MPLLCON 0x4C000004 /* MPLL 配置寄存器 */
  11. # define UPLLCON 0x4C00000C /* UPLL 配置寄存器 */
  12. # define CLKDIVN 0x4C000014 /* 时钟分频寄存器 */
  13. # define S3C2440_MPLL_400MHZ ((0x5c<<) | (0x01<<) | (0x01)) /* 配置 MPLL 时钟为400MHZ*/
  14. # define S3C2440_UPLL_48MHZ ((0x56<<) | (0x02<<) | (0x02)) /* 配置 MPLL 时钟为48MHZ*/
  15.  
  16. #endif /* endif CONFIG_S3C2400 */
  17.  
  18. /* 关闭看门狗 */
  19. ldr r0, =pWTCON /* 将 存储器地址 所指地址处连续的4个字节(1个字)的数据传送到目的寄存器r0中。*/
  20. mov r1, #0x0 /* 将 0x0 存入寄存器 r1 中 */
  21. str r1, [r0] /* 从源寄存器 r1 中将一个32位的字数据传送到存储器r0中。 */
  22.  
  23. /* 屏蔽中断 */
  24. mov r1, #0xffffffff /* 将 0xffffffff 存入寄存器 r1 中 */
  25. ldr r0, =INTMSK /* 将 存储器地址 所指地址处连续的4个字节(1个字)的数据传送到目的寄存器r0中。*/
  26. str r1, [r0] /* 从源寄存器 r1 中将一个32位的字数据传送到存储器r0中。 */
  27.  
  28. /* UPLLCON = S3C2440_UPLL_48MHZ */
  29. ldr r0, =MPLLCON
  30. ldr r1, =S3C2440_UPLL_48MHZ
  31. str r1, [r0]
  32.  
  33. NOP
  34. NOP
  35. NOP
  36. NOP
  37. NOP
  38. NOP
  39. NOP
  40.  
  41. /* MPLLCON = S3C2440_MPLL_400MHZ */
  42. ldr r0, =MPLLCON
  43. ldr r1, =S3C2440_MPLL_400MHZ
  44. str r1, [r0]
  45.  
  46. /* 设置时钟分频 */
  47. ldr r0, =CLKDIVN
  48. mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8 0000 0101
  49. str r1, [r0]
  50.  
  51. #endif /* endif CONFIG_S3C24X0*/

    

buildroot构建项目(四)--- u-boot 2017.11 适配开发板修改 2 ---- 系统启动初始化之一的更多相关文章

  1. buildroot构建项目(六)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之三

    一.内存控制器 在关闭了MMU和caches 之后 就进入lowlevel_init 函数,对内存控制器进行初始化.lowlevel_init.S (board\samsung\mini2440) 1 ...

  2. buildroot构建项目(五)--- u-boot 2017.11 适配开发板修改 3 ---- 系统启动初始化之二

    一.cpu_init_crit 当执行完时钟初始化后,程序执行: bl    cpu_init_crit 跳转到CPU初始化处进行,在其中主要是执行 caches 的关闭 和 MMU的关闭,之后跳转到 ...

  3. buildroot构建项目(八)--- u-boot 2017.11 适配开发板修改 5 ---- 系统启动初始化之五

    执行完 board_init_f 后,跳回到 crt0.S中继续执行汇编语言 ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp, ...

  4. buildroot构建项目(七)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之四

    设置完寄存器控制器后,则跳出cpu_init_crit,进入_main 函数.即进入crt0.S (arch\arm\lib)  跟着代码流程慢慢走 一.crt0.S 1.1 第一步执行代码 /* 预 ...

  5. buildroot构建项目(三)--- u-boot 2017.11 适配开发板修改 1

    当前虽然编译成功了,但是对于我们自己的目标板并不太适用.还得做一系列得修改. 一.lds 文件分析 u-boot 中最重要得链接文件即是,u-boot.lds.我们可以查看我们编译出来得 u-boot ...

  6. buildroot构建项目(二)--- u-boot 2017.11 建立 2440 开发板

    一.准备工作 在建立之前,先需要将下载的u-boot 拷贝一份出来解压,在此工程下进行更改和创建.同时根据前面搜索到的 mini2440开发板所在的版本,下载一份u-boot 拷贝出 mini2440 ...

  7. buildroot构建项目(一)---buildroot介绍

    1.1 什么是buildroot Buildroot是Linux平台上一个构建嵌入式Linux系统的框架.整个Buildroot是由Makefile脚本和Kconfig配置文件构成的.你可以和编译Li ...

  8. iTOP-IMX6UL 实战项目:ssh 服务器移植到 arm 开发板

    实验环境:迅为提供的Ubuntu12.04.2 以及虚拟机 编译器:arm-2009q3 编译器 开发板系统:QT系统   开发板使用手册中给Windows 系统安装了 ssh 客户端,给 Ubunt ...

  9. 迅为iTOP-4412物联网开发板入门学习高手进阶项目开发超树莓派

    免费视频教程: 为初学者精心录制的整套视频教程全部免费,随IT技术发展而不断增添的视频教程仍然免费!一支有经验的工程师团队会始终成为您的后盾. 项目实战---全开源: 手机远程控制开发板 门禁系统 W ...

随机推荐

  1. HADOOP实战

    一.软件版本Centos6.5.VMware 10CDH5.2.0(Hadoop 2.5.0)Hive-0.13 sqoop-1.4.5 二.学完课程之后,您可以:①.一个人搞定企业Hadoop平台搭 ...

  2. jenkins--svn+Email自动触发1(作业设置)

    项目名称设置: svn设置: 触发构建设置: 构建加入sonar-scanner代码扫描: 邮件设置: 邮件触发器配置:

  3. 网络流Dinic模板

    #include <iostream> #include <cstdio> #include <cstring> #include <queue> #d ...

  4. 【Gym - 101164I】Cubes(dfs,剪枝)

    BUPT2017 wintertraining(15) #4 A - I.Cubes Gym - 101164I 题意 将n拆成最少个立方数相加的形式. 题解 根据n的范围,立方数最大不超过400的立 ...

  5. Leetcode 189.旋转数组 By Python

    给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 ...

  6. 自学Linux Shell13.3-获得用户输入(read命令)

    Bash shell提供了一些不同的方法来从用户处获得数据,包括以下3中方法: 命令行参数(添加在名利后面的数据) 命令行选项(可修改命令行为的单个字母)主要getopt.getopts命令 直接从键 ...

  7. emwin 之消息 WM_INIT_DIALOG

    @2018-08-09 小记 消息 WM_INIT_DIALOG 在创建窗口时首先发送且只在创建窗口时发送即只发送这一次

  8. 洛谷 P2764 最小路径覆盖问题 解题报告

    P2764 最小路径覆盖问题 问题描述: 给定有向图\(G=(V,E)\).设\(P\) 是\(G\) 的一个简单路(顶点不相交)的集合.如果\(V\) 中每个顶点恰好在\(P\) 的一条路上,则称\ ...

  9. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  10. Python文件和异常

    程序和运行时数据是在内存中驻留的,涉及到数据交换的地方,通常是磁盘.网络等,因此需要IO接口. IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单 ...