start.S source code:
.globl _start
_start:
// 0 address
b reset // When resetting, the CPU jumps to address 0. In fact, after resetting, the CPU is in management mode (svc)
ldr pc, =undefined_instruction //When the CPU encounters an unrecognizable instruction, address 4, the instruction goes to the memory to read the link address of un..
ldr pc, _vector_swi // When executing the swi instruction, enter the swi mode, address 8, this instruction directly reads the current address of _vector_swi
b halt @ldr pc, _prefetch_abort // Prefetch abort exception
b halt @ldr pc, _data_abort // Data access exception
b halt @ldr pc, _not_used // not used
ldr pc, _irq // 0x18 interrupt exception
b halt @ldr pc, _fiq // Fast interrupt exception
_irq :
.word vector_irq
_vector_swi:
.word vector_swi
vector_swi:
// 1. Save the scene
ldr sp, =0x56000000 //sp is r13 of svc mode, need to be reset
stmdb sp!, {r0-r12, lr} // lr is the next instruction address of swi
// 2. Handle exceptions
mrs r0, cpsr
ldr r1, =swi_str
bl print_cpsr
// 3. Restore the scene
ldmia sp!, {r0-r12, pc}^ // ^ means restore spsr to cpsr
sw_str:
.word 0x00697773 // swi
undefined_instruction:
// 1. Save the scene
ldr sp, =0x55000000
stmdb sp!, {r0-r12, lr}
// 2. Handle exceptions
mrs r0, cpsr
ldr r1, =and_str
bl print_cpsr
// 3. Restore the scene
ldmia sp!, {r0-r12, pc}^ // ^ means restore spsr to cpsr
and_str:
.word 0x00646e75 // and
usr_str:
.word 0x00727375 // usr
vector_irq:
// 1. Save the scene
ldr sp, =0x54000000
sub lr, lr, #4
stmdb sp!, {r0-r12, lr} // lr is the next instruction address of swi
// 2. Handle exceptions
// 2.1 Identify which interrupt it is
// 2.2 Call its processing function
// 3. Restore the scene
ldmia sp!, {r0-r12, pc}^ // ^ means restore spsr to cpsr
reset:
// Hardware related settings
// Peri port setup
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
// Turn off the watchdog
// Write 0 to WTCON (0x7E004000)
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
// Set up the stack
ldr sp, =8*1024
// Set the clock
bl clock_init
bl ddr_init
bl init_uart
//Copy the program's code segment and data segment to its link address
adr r0, _start // Get the current address of the _start instruction: 0
ldr r1, =_start // _start link address 0x51000000
ldr r2, =bss_start // Starting link address of bss segment
sub r2, r2, r1
cmp r0,r1
beq clean_bss
bl copy2ddr
cmp r0, #0
bne halt
// Clear BSS
// Clear the memory corresponding to the BSS segment
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
move r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr //jump to DDR to run
on_ddr:
mrs r0, cpsr //Read the value of the status register into r0
bic r0,r0,#0x1f //clear the last 5 bits
orr r0,r0,#0x10 //Set the fourth position to 1
msr cpsr,r0 // Enter user mode and assign the value of r0 to the program status register
ldr sp, =0x57000000 //sp in user mode
ldr r1, =usr_str
bl print_cpsr
it is
// CPU enters svc mode
// Save the previous cpsr to spsr_svc
// Switch to r13_svc, r14_svc
// Store the address of the next instruction of swi (bl hello) in r14(lr)_svc
// Jump to address 8
bl hello
undef: //After executing the hello function, the undefined instruction will be executed, thus entering the undefined instruction interrupt
.word 0xff000000
// cpu enters Undefined mode
// Save the previous cpsr to spsr_und
// Switch to r13_und, r14_und
// Store the address of the next instruction in r14(lr)_und
// Jump to address 4
swi_ret:
bl main
halt:
b stop
====================================================================
illustrate:
①After the above code is powered on and reset, the CPU is in management mode (svc). Execute b reset at address 0 to jump to reset: and continue running. After initializing the relevant hardware, the last 5 bits of cpsr will be cleared and the fourth bit will be set to 1. After entering user mode to set the stack, it will run in user mode (usr). That is, when the processor starts, it first enters supervisor mode (svc), and then enters other modes except user mode, mainly completing the stack settings of each mode, and finally enters user mode to run user programs; when a swi soft interrupt occurs, the CPU enters svc mode.
②Swi soft interrupt is mainly used to switch from usr mode (applications usually run in usr mode) to svc mode. Among the 7 modes of arm (there are more than 7), usr mode is the only non-privileged mode, and the others are privileged modes, such as fiq, und, etc. The switch between them can directly change the lower 5 bits of the cpsr register mode or when an exception such as fiq, und occurs, the purpose of switching can be achieved; while usr mode is not a privileged mode and there is no way to change the lower 5 bits of the cpsr register to switch. If you want to switch to a privileged mode, you can only call the swi instruction, which will help it enter the svc mode.
③If it was originally in svc mode, it would enter und (Undefined) mode after an undefined instruction exception occurs, and you need to reset the sp stack pointer at this time; if it was already in svc mode when the swi instruction was executed, then it would still be in svc mode after the swi soft interrupt occurs, and you do not need to set the sp stack pointer at this time (in the tiny4412 exception experiment, because the running uboot is already in svc mode, you need to pay attention to the sp pointer).
④ Only when handling swi and und exceptions does lr point to the next instruction. When other exceptions occur, lr points to the next two instructions. Each instruction on ARM is 32 bits long, i.e. 4 bytes. The swi instruction is also 32 bits and the value following it occupies the lower 24 bits of the instruction. Therefore, the value of the swi instruction can be obtained in the program, as follows:
unsigned long *pdo_swi = 0x75000000;
*pdo_swi = do_swi; //First put the interrupt processing function do_swi address at 0x75000000
When a swi exception occurs, the program will automatically jump to the exception vector entry: "b swi\n"
Then jump to swi to execute:
"swi:\n"
"stmfd sp!, {r0-r12, lr}\n"
//Protect the scene and push the relevant registers in the usr mode into the stack.
//The storage order is to store lr, r12....r0 first, and finally sp points to the address of r0
"mov r0, sp\n" //Transfer the sp pointing to the r0 address in the previous step in the usr mode to the r0 register
"mov r3, #0x75000000\n"
"ldr r3, [r3]\n"
"blx r3\n" //Call interrupt processing function do_swi, the parameters are placed in r0
//regs[0] == r0
//regs[1] == r1
//.....
//regs[12] == r12
//regs[13] == lr
void do_swi(unsigned long regs[]) //regs points to address r0 in usr mode
{
//According to the stacking order, regs[13] is the lr value in usr mode, that is, the address of the next instruction when a swi exception occurs
//regs[13] - 4 = lr - 4; the address of the previous instruction is also the address of the swi exception
unsigned long *instr = regs[13] - 4;
//According to the ARM instruction is 32 bits, the swi instruction is also 32 bits and the value following it occupies the lower 24 bits of the instruction to get the value value
printf("swi: 0x%x\n", *instr & 0xffffff);
}
====================================================================
Note the usage of exceptions in the operating system:
①The purpose of SWI exception interrupt is: when the application is running in user mode (usr), when the application calls the open/read/write function, it needs to call the kernel function. How to enter the kernel? In fact, the open/read/write function is a SWI #VAL instruction with different parameters. Once this instruction is executed, the CPU will have an exception. The cpu will enter the svc mode and jump to a fixed address. The kernel code is placed in the address. The kernel code determines the #VAL parameter value brought by the SWI instruction. If it is an open function, it calls the sys_open function, etc.
②Use of undefined instruction exception: for debugging, how to set a breakpoint when the program is executed? When the program is running, take out the instruction where you want to set the breakpoint, save it, and replace it with an undefined instruction. When the program runs to the instruction, an undefined instruction exception will occur, and enter the undefined instruction exception handling function. Some code can be placed in the handling function, such as waiting for the user to enter other instructions. If the user wants to check certain registers and certain memory, you can check the register memory and return the result. When you want to continue running, restore the replaced instruction and let the program run again from here.
Stack order
Previous article:ARM working mode and big-endian and small-endian storage modes
Next article:OK6410 bare metal NAND Flash operation to update firmware
Recommended ReadingLatest update time:2024-11-23 15:08
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- The development space of integrated circuits is very broad
- RL78 LCD controller display principle help
- DSP hardware implements large-scale FIR or multiply-add algorithms
- Remote update of altera loading chip epcs128
- Improved full-bridge phase-shifted ZVS-PWM DC converter
- Solution to the problem of AD20 freezing when starting
- Understand the factors that determine the different performance of ARM core MCUs
- 【Zero Knowledge ESP8266】HTTP WEB Server Example
- Japanese telecom giant counts company trips as business trips and free flights
- Free Download | Keysight Technologies invites you to experience various test software