(2)uboot详解——处理器工作模式

时间:2021-05-28 01:24:26

(2)uboot详解——处理器工作模式


前面一篇文章我们了解到当开发板上电以后,会将uboot的前4k内容复制到stepping stone中运行,现在来分析这4k代码到底做了些什么。

从前面一篇文章的最后一张图可以看到uboot的运行流程,当reset以后,uboot做的第一个动作就是设置cpu的运行模式,这篇文章将详细介绍cpu运行模式的相关知识。

人有生老病死,如果把我们的计算机比作一个生命的话,那么它也有一个生老病死的一个过程,唯一的区别是它没有情绪,没有高兴和悲伤,也不会发脾气,更不会无理取闹,因为对它来说,任何事件的发生都是有原因的,要么是硬件问题,要么是程序问题,它总是勤勤恳恳的按照我们的程序指令一条一条的执行着。然而,虽然它没有自己的情绪,但是它却有着作为“生命”基本的特征,开机是它“生命”开始,死机是它“生命”的结束,死法有多种,谁都不知道会是哪一种,也许是发烧过热了,也许是温度太低芯片出问题了,也许是短路了,也许是正常关机了等等,这些都不重要,重要的是它能够通过重启”活过来“,而我们却不行。。

上面扯远了,回到正题。作为”生命“,它在不同的情况下会处于不同的状态,它”生病“时,会进入异常模式,它休克时会进入中止模式,它需要先处理其他事情时会进入中断模式,它迷茫时会进入未定义指令终止模式,它正常工作在用户模式或系统模式,虽然这样类比不太恰当,也不够严密,但我又不是科学家,管他呢。

开发板刚上电的时候就像是一个baby,它需要受到”保护“,需要一个”成长的环境“,同时也要被教导该做什么,怎么做,所以板子reset的时候,首先需要进入到一种保护模式中,在这个模式中完成一些硬件的初始化和寄存器的配置,这个模式的名称叫:管理模式


ARM 有七种模式:

处理器工作模式

   特权模式

异常模式

说明

用户(user)模式

 

 

用户程序运行模式

系统(system)模式

该组模式下可以

任意访问系统资源

 

运行特权级的操作系统任务

一般中断(IRQ)模式

通常由系统异常状态

切换进该组模式

普通中断模式

快速中断(FIQ)模式

快速中断模式

管理(supervisor模式

提供操作系统使用的一种保护模式,swi命令状态

中止(abort模式

虚拟内存管理和内存数据访问保护

未定义指令终止(undefined)模式

支持通过软件仿真硬件的协处理


(1)用户模式:用户模式是用户程序的工作模式,它运行在操作系统的用户态,它没有权限去操作其它硬件资源,只能执行处理自己的数据,也不能切换到其它模式下,要想访问硬件资源或切换到其它模式只能通过软中断或产生异常。

(2)系统模式:系统模式是特权模式,不受用户模式的限制。用户模式和系统模式共用一套寄存器,操作系统在该模式下可以方便的访问用户模式的寄存器,而且操作系统的一些特权任务可以使用这个模式访问一些受控的资源。

(3)一般中断模式:一般中断模式也叫普通中断模式,用于处理一般的中断请求,通常在硬件产生中断信号之后自动进入该模式,该模式为特权模式,可以*访问系统硬件资源。

(4)快速中断模式:快速中断模式是相对一般中断模式而言的,它是用来处理对时间要求比较紧急的中断请求,主要用于高速数据传输及通道处理中。

(5)管理模式:管理模式是CPU上电后默认模式,因此在该模式下主要用来做系统的初始化,软中断处理也在该模式下,当用户模式下的用户程序请求使用硬件资源时通过软件中断进入该模式。

(6)中止模式:中止模式用于支持虚拟内存或存储器保护,当用户程序访问非法地址,没有权限读取的内存地址时,会进入该模式,linux下编程时经常出现的segment fault通常都是在该模式下抛出返回的。

(7)未定义模式:未定义模式用于支持硬件协处理器的软件仿真,CPU在指令的译码阶段不能识别该指令操作时,会进入未定义模式。


每种模式下对应的arm状态寄存器:

(2)uboot详解——处理器工作模式

虽然放在这里讲寄存器有点早,但是下面介绍的内容有依赖于它,所以在这里先解释一下这张表。

这张表是datasheet里面截取下来的,本来还有一张是thumb state,但是我放弃了,我想自己也不会想去了解arm thumb状态的工作原理了,就像现在舍弃使用单片机一样。

从上面这张表中可以看出:

1. 不管在哪种模式下,r0~r7,r15和CPSR寄存器都是大家公用的,因为他们都没有用三角号进行标记(用三角号标记的表示这个寄存器是该模式独有的),这里共用的寄存器一共有10个

2. r8~r12是管理模式,用户模式,系统模式,中止模式,一般中断模式和指令未定义模式6个模式所共有的,也就是说,只有快速中断模式使用自己的r8~r12(因为在FIQ下这几个私有寄存器里的数据在模式切换时可以不用入栈保存),这里共用的寄存器一共有5个

3. 从图中可以看出,除了system&user共用r13和r14 (sp lr)以外(因为用户模式有时候需要切换到特权模式下执行,所以他们公用sp 和 lr),其他每一种模式都有自己的r13和r14寄存器(因为在每种模式下都有自己的栈空间用于执行程序和保存返回地址),这里共用的寄存器一共有2个

4. 除了共用的寄存器,剩下的就是私有的寄存器了,通过数三角形可以知道一般用的私有寄存器有15个(上面有15个灰三角),下面的私有状态寄存器有5个,所以私有寄存器一共有20个

 (system&user模式下没有SPSR寄存器,因为这两种模式不是异常模式,它不需要SPSR寄存器)

正如文档所说“ARM920T has a total of 37 registers - 31 general-purpose 32-bit registers and6status registers- but these cannot
all be seen at once
.”
  ,那么这37个寄存器是哪些呢,就是我们上面所说的 10+5+2=17 个共用寄存器和20个私有寄存器

共用寄存器和私有寄存器有什么区别呢?

公用寄存器在切换模式的时候,共用者间使用的寄存器是相同的;而在cpu切换到当前模式时,私有寄存器是只能够自己使用的,其他模式是不能够使用你的私有寄存器的,这样说可能不好理解,比如:

r3寄存器是所有模式共用的寄存器,那么当处理器从user模式切换到 IRQ模式的时候,仍然IRQ模式仍然可以使用r3寄存器,里面的数据也是可以读取和写入的

但是r13寄存器不是所有模式共用的寄存器,当处理器从user模式切换到 IRQ模式的时候,在user模式下,r13是可以被使用的,但是在IRQ模式下,r13是不可用的,因为它看不到r13了,取而代之的是r13_irq,IRQ模式有它自己的r13_irq寄存器,而且r13_irq寄存器只有它自己可见,别的模式是看不见IRQ模式的私有寄存器(r13_irq)的。

正如上面标橙色部分(but these cannot all be seen at once)所说:虽然有这么多寄存器,但是他们是不能够在同一模式下看到全部的,要看到某种模式下的私有寄存器,只有切换到那种模式下才能看到。


与arm处理器模式相关的寄存器,其实就是两个:CPSR     SPSR

 SPSR是一个32位的寄存器,它其实就是CPSR备份,用来保存切换到该模式之前的状态,之所以用户模式和系统模式没有SPSR,是因为通常CPU大部分时间都工作在用户模式下,当产生异常或系统调用的时候会分别切换进另外几种模式,保存用户模式下的状态,当切换回原模式的时候,直接恢复SPSR的值到CPSR就可以了,因此,用户模式和系统模式下不需要SPSR寄存器。

下面将对CPSR寄存器进行分析:

(2)uboot详解——处理器工作模式

条件标志位
N
——本位设置成当前指令运算结果的bit[31]的值。当两个表示的有符号整数运算时,n=1表示运算结果为负数,n=0表示结果为正书或零。

Z——z=1表示运算的结果为零;z=0表示运算的结果不为零。对于CMP指令,Z=1表示进行比较的两个数大小相等。

C——下面分四种情况讨论C的设置方法:
在加法指令中(包括比较指令CMP),当结果产生了进位,则C=1,表示无符号运算发生上溢出;其他情况C=0。
在减法指令中(包括减法指令CMP),当运算中发生错位,则C=0,表示无符号运算数发生下溢出;其他情况下C=1。
对于包含移位操作的非加减运算指令,C中包含最后一次溢出的的位的数值。对于其他非加减运算指令,C位的值通常不受影响。

V——对于加减运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号为溢出;通常其他指令不影响V位。

CPSR的低八位I、F、T、M[4:0]统称为控制位。当异常中断发生时这些位发生变化。在特权级的处理器模式下,软件可以修改这些控制位。

中断禁止位I,F

当I=1时禁止IRQ中断

当F=1时禁止FIQ中断

T控制位

T控制位用于控制指令执行的状态,即说明本指令是ARM指令还是Thumb指令。

T控制位含义如下:
T=0表示执行ARM指令
T=1表示执行Thumb指令
对于ARM V5以及更高版本的非T系列处理器,T控制位的含义如下
T=0表示执行ARM指令
T=1表示强制下一条执行的指令产生未定指令中断

***M控制位***
M控制位控制处理器模式,具体含义如下:

M[4:0] 处理器模式    可访问的寄存器
(2)uboot详解——处理器工作模式

CPSR中的其他位
这些位用于将来扩展。应用软件不要操作这些位。



了解了arm处理器工作模式的相关知识后,下面将使用一个例子来演示一下工作模式的配置过程,这个例子是使用开发板上的led来显示当前cpu的处理模式。

(2)uboot详解——处理器工作模式

(2)uboot详解——处理器工作模式

(2)uboot详解——处理器工作模式

(2)uboot详解——处理器工作模式

上图是开发板的led与cpu的电路连接图和对应的配置寄存器,从图中可以看出,要让led1,2,3,4亮,只要让cpu的GPB5,6,7,8引脚输出低电平就可以了。

要让cpu的GPB引脚输出低电平,要先将cpu对应引脚的设为输出引脚,这个通过设置GPBCON(控制寄存器)就可以设置了,然后将要给引脚上的状态写到GPBDAT里面。

比如我们用如下代码让led全亮:

            LDR     R0,=0x56000010      @ R0设为GPBCON寄存器。此寄存器
@ 用于选择端口B各引脚的功能:
@ 是输出、是输入、还是其他
MOV R1,#0x15400
STR R1,[R0] @ 设置GPB5为输出口, 位[10:9]=0b01
LDR R0,=0x56000014 @ R0设为GPBDAT寄存器。此寄存器
@ 用于读/写端口B各引脚的数据
MOV R1,#0x00000000 @ 此值改为0x00000020,
@ 可让LED1熄灭
STR R1,[R0] @ GPB5输出0,LED1点亮
首先将GPB5,GPB6,GPB7,GPB8引脚都设置成输出模式,所以bit17到bit10设置成01010101,即0x15400=b10101010000000000; 然后将所有的灯都点亮,所以GPBDAT的bit5,6,7,8都设为0,所以 给GPBDAT寄存器所有位都设置为0。

当cpu运行完第4行命令的时候,GPB5,6,7,8引脚就可以输出电平了,0是低电平,1是高电平;

当cpu运行完第10行命令的时候,我们设置在GPBDAT中的数据就设置到对应的引脚上了,因为我们写入的全是0,所以GPB5,6,7,8引脚上的电平全部是低电平,从led电路图中就可以看出,如果nLED_1,2,3,4都接了低电平,那么他们就会全部点亮了。


说完了怎么点亮led灯,我们就可以开始写设置cpu模式的程序(cpu_mode.S)了,下面是cpu_mode.S的汇编代码:

@cpu_mode

.text
.global _start
_start:
/*
* set the cpu to SVC32 mode
*/
mrsr0, cpsr
bicr0, r0, #0x1f
orrr0, r0, #0xd3
msrcpsr, r0

and r1,r0,#0b10011
cmp r1,#0b10011
bleq led_on

main_loop:
b main_loop

led_on:
ldr r0,=0x56000010
mov r1,#0x15400
str r1,[r0]

ldr r0,=0x56000014
mov r1,#0x100
str r1,[r0]
mov pc,lr

下面是对应的Makefile: 

cpu_mode.bin:cpu_mode.S
arm-linux-gcc -g -c -o cpu_mode.o cpu_mode.S
arm-linux-ld -Ttext 0x000 -g cpu_mode.o -o cpu_mode_elf
arm-linux-objcopy -O binary -S cpu_mode_elf cpu_mode.bin

clean:
rm -rf cpu_mode.bin *.o cpu_mode_elf

上面两个文件有几点需要说明:

1.这两个文件是在Linux下编译的,而且需要预先有交叉编译工具,如果没有安装,可以从这里下载   

2.汇编语言使用的是arm汇编语言,每一种处理器的汇编语言都有所差异,所以需要参看对应的文档编写程序

3.这里没有使用window下的工具(ADS、keil)编译裸机文件,以后也不会,个人喜欢Linux这种开放式过程,不习惯windows工具的封装,虽然只要点几个按钮就可以快速完成一个二进制文件的编译,但这种方式不能让自己对程序编译过程有个好的把握,所以宁愿多写几行Makefile,多调整一下lds文件,也不想贪图Windows工具的快捷方便,所以有意顺畅的阅读后面的内容,请先了解一下gcc编译的链接过程和一些连接文件的一些知识


上面两个文件放在同一个目录,然后make一下就能生成二进制文件了

cpu_mode.bin

将这个二进制文件烧到norflash中就能够运行并看到效果了(注:如果烧写到nandflash中,需要先初始化SDRAM)

下图是运行效果,当前模式是管理模式(0b10011)时,让led1,2,3点亮,led4灭

(2)uboot详解——处理器工作模式



总结:

这篇文章分析了arm 处理器的运行模式,介绍了每种模式下会使用到哪些处理器,分析了CSPR寄存器相应位的作用以及怎么设置处理器的运行模式,然后介绍了怎么根据datasheet来设置led的状态,最后用一个实例演示了切换处理器模式到管理模式的操作。

后面依然会按照第一篇文章 中介绍的流程进行分析,下一篇文章将分析看门狗相关的内容。


(2)uboot详解——处理器工作模式



转载请声明!