龙空技术网

详解ARM中的启动代码

回首依然看见故乡 537

前言:

此时兄弟们对“c语言开机自动启动代码”都比较注重,同学们都需要分析一些“c语言开机自动启动代码”的相关内容。那么小编同时在网摘上收集了一些有关“c语言开机自动启动代码””的相关知识,希望咱们能喜欢,你们快快来了解一下吧!

知道为什么要关看门狗吗???

关看门狗

如果在启动代码过程中,我们忘记喂狗/没有时间去喂狗,那么看门狗就会触发,从而重启系统。因此我们要在启动代码的时候将看门狗关闭

但是在210开发板上,在IROM开始的时候就把开门狗关闭了

        ldr r0, =WTCON        ldr r1, =0x0        str r1, [r0]
汇编写启动代码之设置栈和调用C语言

怎么让一个C语言代码运行起来

C语言运行主要是需要一个栈

因为C语言中的局部变量都是存放在栈中,假如没有栈,或者说栈空间的地址都是非法地址,那么当把一个局部变量放到一个栈中的时候,程序就死机了

平时写C语言,写单片机的时候为什么不需要设置栈

平时写业务代码的时候,根本就不需要设置栈,还是可以正常运行,那是因为我们的编译器和单片机帮助我们做了很多事情:

1.在单片机中,在硬件初始化的时候,都会提供一个默认可用的栈。

2.在编写应用程序的时候,编译器在链接的时候会自动给我们添加一个头,这个头实际上就是一段引导我们的C程序能够执行的一段汇编源代码,也是因为这个汇编代码,帮助我们C语言程序设置了栈

CPU模式和各种模式下的栈

我们知道,在ARM中的37个寄存器中,7种ARM模式中都有他们独立的SP,也就是堆栈指针,所以我认为,每种模式都有他们独立的栈。

怎么去设置栈

设置栈,主要是看现在我们的CPU处于什么样的模式,根据不同模式设置不同的栈即可

因为系统复位后会进入SVC模式,所以我们要找到SVC模式下SP堆栈指针应该指向哪里,那就可以设置栈

这个时候代码应该这么写:

#define SVC_STACK 0xd0037d80@

设置SVC栈

ldr sp, =SVC_STACK

为什么是0xd0037d80而不是0xd0037780

因为栈是向下生长的,堆是向上生长的。

因为栈是向下生长的,所以就能证明我们数组越界访问会出现系统无限循环问题。。

汇编程序和C程序互相调用

在汇编文件中设置栈后面加上以下的这句话:

bl led_flash

新建一个Led.c文件,在里面实现led_flash函数

void led_blink(void){        rGPJ0CON = 0x11111111;         while (1)         {              rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));              // 延时              delay();              // led灭             rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));              // 延时              delay();         }}
汇编写启动代码之开iCache

什么是cache,什么是iCache

计算机应用基础告诉我们,cache是高速缓存区

单片机应用基础告诉我们iCache,实际上就是指令缓冲区

为什么要用iCache

iCache主要是用于消除CPU和寄存器和DDR之间的尴尬问题

因为ARM是RISC架构,所以CPU不能直接操作内存,需要通过寄存器来操作。

但是CPU和寄存器和CACHE以及DDR存在以下关系:

1、在容量上:

CPU < 寄存器 < cache < DDR

2、在速度上:

CPU > 寄存器 > cache > DDR

因为如果没有cache,但是DDR速度又很慢,这个时候CPU就会很空闲:

指令平时是存放在flash/硬盘中,运行的时候从flash/硬件中读取指令到DDR中,然后再从DDR读到寄存器,最后从寄存器读到CPU中去运行。

如果直接从DDR->寄存器->CPU,那么因为DDR本来速度就慢,所以会造成CPU速度慢,效率低。

如果用到了icache,这个时候就变成了DDR->ICACHE->寄存器->CPU,这个时候icache会把CPU下几条代码对应的指令读取,这个时候如果CPU要读取下一条指令,刚好(大部分情况也会这样),cache检查到自己的缓存指令中存在了要运行的那条指令,则会拿到给CPU,如果没有这条指令(比如跳转函数,刚好这条指令不存在于icache当前暂存的指令集中),那么会从DDR中读取对应的指令交给CPU,然后运行,icache会重新清缓存,重新缓存下几条指令

所以,要写代码的时候高效,从汇编的角度和CPU的角度来看,减少跳转函数的次数,确实会高效一点..在做低端平台的时候,确实也感受到这种情况..

汇编代码读写cp15来操作icache

实际上,在irom 中已经初始化了icache

mrc p15,0,r0,c1,c0,0; // 读出cp15的c1到r0中bic r0, r0, #(1<<12) // bit12 置0  关icacheorr r0, r0, #(1<<12) // bit12 置1  开icachemcr p15,0,r0,c1,c0,0;

如果关闭了icache,然后再运行我们的闪烁LED程序,我们会看到LED灯明显变慢,不是延时函数的问题,也不是人品的问题,是icache关了,这个时候DDR就会明显拖慢CPU的速度,所以执行一句代码的时间就变长,指令执行速度变慢,从而把整个代码的执行时间加长,就会看到闪烁明显变慢

如果开启了icache,就会看到之前正常的现象

也证明了Irom在初始化的时候打开了icache,虽然数据手册没说,但是现象表明了一切。

标签: #c语言开机自动启动代码