[Bare metal development] Reset interrupt service function (assembly implementation)

Table of contents

1. Implementation steps of Reset interrupt service function

2. Assembly to implement the Reset interrupt service function

1. Disable/enable global interrupts

2. Set the SP pointer

3. Clear the .bss section

4. Complete Reset interrupt service function


1. Implementation steps of Reset interrupt service function

The basic steps to implement the Reset interrupt service function are as follows:

  • Set the SP pointer in each mode . When an interrupt occurs, it will enter the corresponding working mode. To run the program in each working mode, the stack must be used, so we need to initialize the stack pointer in different modes.
  • Clear the bss segment.
  • Jump to main function.

Sometimes, in order to prevent the execution of the interrupt service function from being interrupted by other higher priority interrupts, we can disable global interrupts at the beginning (disable IRQ and FIQ interrupts), and then enable global interrupts at the end.

  • Disable global interrupts
  • Set the SP pointer in each mode .
  • Clear the bss segment .
  • Turn on global interrupts
  • Jump to main function

2. Assembly to implement the Reset interrupt service function

1. Disable/enable global interrupts

Here we can operate the CPSR register to achieve it, but assembly provides us with simple and fast instructions to disable/enable global interrupts

instruction describe
cpsid i Disable IRQ interrupt
cpsie i Enable IRQ interrupt
cpsid f Prohibited FIQ Suspended
cpsie f Enable FIQ interrupt

2. Set the SP pointer

ARM has a total of nine working modes, but we are not going to set them one by one here, only set some that may be used, such as SVC, IRQ, USER, SYS, etc. Because SYS and USER modes share one SP pointer, that is, they share one stack, so you can choose one of the two to set. ( The stack in each mode is given a size of 2 M )

The SP settings in each mode are similar:

  • Modify the CPSR register to switch to a certain mode
  • Set the SP pointer in this mode (R13 register)

/* 切换到 SVC 模式 */
mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
orr r0, r0, #0x13           @ 让 r0 的低五位或上 10011(0x13),结果保存到 r0
msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
ldr sp,=0x80200000          @ 设置栈指针

/* 切换到 SYS 模式 */
mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
orr r0, r0, #0x1f           @ 让 r0 的低五位或上 11111(0x1f),结果保存到 r0
msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
ldr sp,=0x80400000          @ 设置栈指针

/* 切换到 IRQ 模式 */   
mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
orr r0, r0, #0x12           @ 让 r0 的低五位或上 10010(0x12),结果保存到 r0
msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
ldr sp,=0x80600000          @ 设置栈指针

3. Clear the .bss section

4. Complete Reset interrupt service function

/* 复位中断 */ 
Reset_Handler:
    cpsid i                     /* 禁止IRQ */
    cpsid f                     /* 禁止FIQ */

    /* 切换到 SVC 模式 */
    mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
    bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
    orr r0, r0, #0x13           @ 让 r0 的低五位或上 10011(0x13),结果保存到 r0
    msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
    ldr sp,=0x80200000          @ 设置栈指针

    /* 切换到 SYS 模式 */
    mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
    bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
    orr r0, r0, #0x1f           @ 让 r0 的低五位或上 11111(0x1f),结果保存到 r0
    msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
    ldr sp,=0x80400000          @ 设置栈指针

    /* 切换到 IRQ 模式 */   
    mrs r0, cpsr                @ 将 cpsr 寄存器的内容读取到 r0 寄存器
    bic r0, r0, #0x1f           @ 将 r0 的低五位清零,运算结果放到 r0
    orr r0, r0, #0x12           @ 让 r0 的低五位或上 10010(0x12),结果保存到 r0
    msr cpsr, r0                @ 将 r0 的值写入到 cpsr 寄存器
    ldr sp,=0x80600000          @ 设置栈指针

    /* bss 段清零 */
    ldr r0, =__bss_start
    ldr r1, =__bss_end
    mov r2, #0
    bl bss_loop                 @ 跳转到 bss_loop,LR寄存器自动保存下一条指令地址

    cpsie f                     /* 使能FIQ */
    cpsie i                     /* 使能IRQ */

    b main                      @ 跳转到 main 函数

bss_loop:
    stmia, r0!, {0}
    cmp r0, r1
    bne bss_loop

    mov pc, lr                  @ 清零完毕后回到原位置

Jump instruction reference: b, bl jump instruction

Guess you like

Origin blog.csdn.net/challenglistic/article/details/131231054