1 Undefined instruction
Let's first look at the format of instructions in ARM:
Note: The corresponding bits at the top of this table are from high to low, so 0Xdeadc0de is an undefined instruction (easy to understand)
2 Interrupt vector table
Undefined exceptions, first look at the interrupt vector table:
After the board is powered on, the CPU starts executing from address 0, first executing the reset operation, and after triggering an exception, it will jump to the corresponding address to enter the exception handler, so we need to start at address 0 and follow the instructions of the interrupt vector table to write the corresponding exception handler, as follows:
.text
.global _start
_start:
/* Exception vector table */
bl reset /* 0X0 Reset Power-on reset, start executing the program from address 0, in order: turn off the watchdog, configure the clock system, initialize sdram, copy the code to sdram (relocation), clear the .bcc segment, enter the main function*/
ldr pc, =und_addr /* 0X4 Undefined instruction */
// bl do_swi /* 0X8 Software Interrupt */
// bl do_ap /* 0XC Abort(prefetch) */
// bl do_ad /* 0X10 Abort(data) */
// bl do_re /* 0X14 Reserved */
// bl do_irq /* 0X18 IRQ */
// bl do_fiq /* 0X1C FIQ */
3 Set an undefined instruction
Artificially introduce an undefined instruction. If you encounter an undefined instruction, such as the following instruction 0Xeeadc0de: (Correction: Change 0Xdeadc0de to 0Xeeadc0de, because 0Xdeadc0de is actually a conditional execution statement. Only when the condition is triggered will the following code be executed)
When the CPU executes here, it will fetch the instruction. If it finds that this is an undefined instruction, it will automatically trigger the und exception. The CPU will find the address mapping of the und handler in the interrupt vector table and execute the und handler through the jump instruction.
4 Calling C functions
The und processing function can be written in C language and called in assembly, but pay attention to the passing of parameters:
The C function is as follows:
void Und_Process( unsigned int cpsr )
{
puts("nrEnter Und_Process!!!nrCPSR is:");//Print prompt information and enter the und processing program
printHex( cpsr ); // Output the value of the CPSR register to confirm the current mode
puts("nr");
}
The und exception handling function prints some information.
The parameters are passed in assembly as follows:
mrs r0, cpsr /* mrs reads the value of the register and passes the parameter to the following function through the r0 register*/
==Note: == The und processing function written in C must use the stack!!! Although we have set the stack pointer sp in the assembly (it is in management mode after power-on, so the stack pointer sp in management mode is set), but for exception mode, each exception mode has its own stack pointer!!! As follows:
Therefore, after entering the und processing program, you must first set the sp_und stack pointer to allocate space for the called C processing function, and just point it to an unused space, such as
ldr sp, =0x34000000 /* points to the highest address of 64M SDRAM*/
Now you can call the C function!
5 UND exception handler
With the und exception handler, you can call the handler function in assembly, but there are other operations for the exception handler in assembly.
The und exception handler in assembly is as follows:
und_addr:
.word do_und
/* und exception handling, before entering the exception, the hardware completes the following: copy CPSR to SPSR, store the address of the interrupted instruction in lr*/
do_und:
ldr sp, =0x34000000 /* und's stack pointer, pointing to the highest address of 64M SDRAM, allocating space for C function*/
stmdb sp!, {r0-r12,lr} /* Save the scene*/
mrs r0, cpsr /* mrs reads the value of the register and passes the parameter to the following function through the r0 register*/
bl Und_Process
ldmia sp!, {r0-r12, pc}^ /* Restore the scene, note: be sure to add ! to save the changes of sp*/
After the und exception is triggered, before entering the exception program processing, the hardware will perform some operations:
1. Copy CPSR to SPSR
2. M4-M0 in CPSR is automatically set to 11011, entering und mode
3. Store the address of the interrupted instruction in the lr register
4. The program jumps to the address (und) of the interrupt vector table 0X4 to execute the interrupt exception handler
In the exception handler, the following operations are performed:
1. Set up the stack through sp_und
2. Save the scene, including r0~r12 registers and lr register. Saving lr is also necessary because lr contains the return address after the exception is handled.
3. Call C processing function
4. Restore the scene, use ldmia sp!, {r0-r12,pc}^ to restore the values of each register, assign the value of the lr register to the pc register (to be verified, ia is the order), ^ and restore the value in SPSR to CPSR
6 Assembly source code
.text
.global _start
_start:
/* Exception vector table */
bl reset /* 0X0 Reset Power-on reset, start executing the program from address 0, in order: turn off the watchdog, configure the clock system, initialize sdram, copy the code to sdram (relocation), clear the .bcc segment, enter the main function*/
ldr pc, =und_addr /* 0X4 Undefined instruction */
// bl do_swi /* 0X8 Software Interrupt */
// bl do_ap /* 0XC Abort(prefetch) */
// bl do_ad /* 0X10 Abort(data) */
// bl do_re /* 0X14 Reserved */
// bl do_irq /* 0X18 IRQ */
// bl do_fiq /* 0X1C FIQ */
und_addr:
.word do_und
/* und exception handling, before entering the exception, the hardware completes the following: copy CPSR to SPSR, store the address of the interrupted instruction in lr*/
do_und:
ldr sp, =0x34000000 /* und's stack pointer, pointing to the highest address of 64M SDRAM, allocating space for C function*/
stmdb sp!, {r0-r12,lr} /* Save the scene*/
mrs r0, cpsr /* mrs reads the value of the register and passes the parameter to the following function through the r0 register*/
bl Und_Process
ldmia sp!, {r0-r12, pc}^ /* Restore the scene, note: be sure to add ! to save the changes of sp*/
.align 4
reset:
/* Disable watchdog */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]
/* Set MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]
/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
/* Set the CPU to work in asynchronous mode */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
/* Set MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
* m = MDIV+8 = 92+8=100
* p = PDIV+2 = 1+2 = 3
* s = SDIV = 1
* FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
/* Once the PLL is set, the lock time will be locked until the PLL output is stable
* Then the CPU operates at the new frequency FCLK
*/
/* Set up memory: sp stack */
/* Distinguish whether it is NOR/NAND startup
* Write 0 to address 0, then read it out
* If you get 0, it means the content at address 0 has been modified, it corresponds to ram, this is nand boot
* Otherwise, it is NOR start
*/
mov r1, #0
ldr r0, [r1] /* read out the original value backup */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2? If they are equal, it means NAND boot*/
ldr sp, =0x40000000+4096 /* Assume that it is NOR startup*/
moveq sp, #4096 /* nand start */
streq r0, [r1] /* restore the original value */
/* When relocating the code, first initialize SDRAM, then copy the code, then clear the .bss segment (to prevent memory access errors), and finally execute the main function, which is executed in the relocated SDRAM*/
bl sdram_init
//bl sdram_init2 /* Uses an array with initial values, not position-independent code*/
/* Relocate the entire program in text, rodata, and data segments*/
bl copy2sdram
/* Clear BSS segment */
bl clean_bss
ldr pc, =UartInit
UartInit:
bl uart0_init
/* Introduce the und instruction to trigger the und exception*/
und_test:
.word 0Xeeadc0de
//bl main /* Use BL command for relative jump, the program is still executed in NOR/sram*/
ldr pc, =main /* Absolute jump, jump to SDRAM */
halt:
b halt
7. Notes
LR and PC
When an exception occurs, the current interrupted address will be automatically saved in the lr register by the hardware. You can view the value of the address to be stored in the lr register in the corresponding table:
It can be found that when the und exception occurs, the value of the lr register is PC+4 (ARM instruction set)
Save the scene
Save the scene, that is, save registers r0~r12 (after entering the exception mode, the hardware will save the CPSR to the SPSR)
So when saving r0~r12, the lr register is also saved:
stmdb sp!, { r0-r12, lr }
Perform the opposite operation when restoring the site:
ldmia sp!, { r0-r12, pc }^ /* ia: read first and then add ^ will restore the value of spsr to cpsr*/
Interrupt vector table jump
When jumping, use ldr pc, =do_und (to prevent errors due to relocation). The C function of bl Und_Process below is also in SDRAM, which is the running address after relocation.
In fact, ldr pc, =do_und is a pseudo instruction, which stores the value of do_und (that is, the first address of the und exception handler) in memory, then reads the memory and assigns a value to pc. This memory is often immediately following the assembly file, but when the assembly file is too large (more than 4K, the value outside the 4K address will not be read when NAND is started), it may cause an error.
You can indirectly place the value of do_und in the assembly file:
und_addr:
.word do_und
In this way, only the following are required in the interrupt vector table:
ldr pc. = und_addr
As shown:
Program execution order
The memory execution order of the program is:
1.0 Address b reset
2.0X4 address ldr pc, =und_addr
3. The next memory space is the relocation related code
4.ldr pc, =sdram jumps to the relocated code to execute the program (all codes are copied to SDRAM 0X30000000)
Previous article:S3C2440—12.Key interrupt
Next article:ARM—Exception interrupt handling
Recommended ReadingLatest update time:2024-11-16 11:48
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Today at 10:00: AMS audio experts analyze active noise reduction headphone design, technology trends, and potential applications
- The BLE mobile app required for RSL10 BLE development is not easy to install through Google Play, APK file downloads are collected
- MSP430F5529 serial port clock and SPI clock configuration issues
- [Evaluation of SGP40] + UART communication + use of at32f407 development board
- Solid-state devices versus vacuum tubes: Will the two coexist for a long time?
- [Atria AT32WB415 Review] 5. Bluetooth Low Energy Version (BLE) Official Demo Review
- This amplifier is a bit figurative, isn't it?
- ad19.0.10 3D display problem
- Why is there only one channel with data when using STM32's TIMER to capture DMA?
- The concept and function of PA and LNA in Bluetooth module