汇编写启动代码之关看门狗、设置栈、调用C、开关icache

关看门狗(watch dog timer)

在正常情况下,系统软件每过一段时间会自动进行一次喂狗(即将看门狗定时器置0重新定时)。但是如果设备跑飞,死机,系统无法自动喂狗。那么等到看门狗定时器计时时间到了,就会自动将设备复位。在一些特殊环境下的无人值守设备中,这种自动发现问题然后复位的技术就很重要。

那为什么要关看么狗?

答:我们在启动代码处,不方便喂狗,所以索性把看门狗关了,等以后需要的时候再开启。

物理特性:定时器,硬件上就是SOC的内部外设,所以不需要原理图分析

关键寄存器:WTCON(0xE2700000),其中bit5位开关。

#define WTCON 0xE2700000
.........省略别的代码
//
第一步关看门狗 ldr r0, =WTCON ldr r1, =0x0 str r1, [r0]

设置栈

  • 由于C语言的局部变量是存在栈中的,所以调用C语言的前提是设置好栈。
  • 在单片机中,硬件一开始已经设置了一个栈,所以我们可以直接用C语言。
  • 在应用程序中,我们编写的C语言程序其实不是全部,编译器在链接的时候会自动添加一个头,这个头通过汇编帮C语言设置的了栈。
  • 在嵌入式程序中,必须自己手动的用汇编编写栈。

注意:在ARM的37个寄存器中,每个模式下都有自己独立的SP寄存器(r13),这样各个模式下的栈不会互相产生干扰。

由于我们的板子在系统复位后默认为SVC模式,所以我们只需要在此模式下,用汇编设置SP就可以了。

  #define SVC_STACK 0xD0037D80 
  //
设置栈 ldr sp, =SVC_STACK //从这里开始可以调用C语言了 bl led_blink //运用bl来调用C语言中的函数

在.c文件中写一个led_blink文件

#define GPJ0CON     0xE0200240
#define GPJ0DAT     0xE0200244
#define rGPJ0CON     *((volatile unsigned int *)GPJ0CON) 
#define rGPJ0DAT     *((volatile unsigned int *)GPJ0DAT)
void delay(void);
//该函数要实现led闪烁的效果
void led_blink(void)
{    
    rGPJ0CON = 0x11111111;
    rGPJ0DAT = (1<<3)|(1<<4)|(1<<5);
    while(1)
    {
        //led点亮
        rGPJ0DAT = (0<<3)|(0<<4)|(0<<5);
        delay();
        //led灭
        rGPJ0DAT = (1<<3)|(1<<4)|(1<<5);
        delay();
    }
}

void delay(void)
{
    volatile unsigned int i = 1000000;
    while(i--);
}

 关icache

cache:高速缓存

  • 容量:CPU<寄存器<cache<DDR
  • 速度:CPU>寄存器>cache>DDR
  • 由于DDR的速度远远不及CPU,所以加上cache可用于做缓冲,否则CPU的速度会被DDR严重拖慢。
  • 现在几乎所以的CPU都带cache的
//第三步:开/关icache
    mrc p15,0,r0,c1,c0,0;            //读出cp15的c1到r0中
    bic r0,    r0, #(0<<12)            //bit12置0,关icache
   // orr r0, r0, #(1<<12)            //bit12置1,开icache
    mrc p15,0,r0,c1,c0,0;
原文地址:https://www.cnblogs.com/jxjl/p/6994148.html