Zhou licong: Analysis of startup code of the lpc21xx/lpc22xx series of ARM7

Source: Internet
Author: User

Reprinted please indicate the source

Author: Pony

 

I am not an expert either. I just have some experience. I am just a saying of my family.

 

SVC_STACK_LEGTH         EQU         0FIQ_STACK_LEGTH         EQU         0IRQ_STACK_LEGTH         EQU         256ABT_STACK_LEGTH         EQU         0UND_STACK_LEGTH         EQU         0NoInt       EQU 0x80USR32Mode   EQU 0x10SVC32Mode   EQU 0x13SYS32Mode   EQU 0x1fIRQ32Mode   EQU 0x12FIQ32Mode   EQU 0x11

The above lines of code do not need to be analyzed too much. Just define a few symbols and think of equ as # define in C. For the specific defined values, I will explain the code below.

 

IMPORT __use_no_semihosting_swi

The purpose of the above statement is to disable the semihosting mechanism in the code. what is semihostiong? There are many websites. here, it only indicates that semihosting is mainly used for debugging and is usually disabled in the code of the release version.

 

IMPORT  FIQ_Exception                   IMPORT  __main                             IMPORT  TargetResetInit

The above three lines declare the External labels to be introduced for use below.

 

EXPORT  bottom_of_heapEXPORT  StackUsrEXPORT  ResetEXPORT __user_initial_stackheap

The above four lines are the label declaration to be used for other files

 

AREA    vectors,CODE,READONLY        ENTRY

The above line declares the Assembly file entry. The entire file is executed from here.

 

Reset        LDR     PC, ResetAddr        LDR     PC, UndefinedAddr        LDR     PC, SWI_Addr        LDR     PC, PrefetchAddr        LDR     PC, DataAbortAddr        DCD     0xb9205f80        LDR     PC, [PC, #-0xff0]        LDR     PC, FIQ_Addr

The above rows show the configuration of the interrupt vector table. The sequence of the interrupt vector table cannot be changed. As defined by arm, refer to relevant books. Here are several questions to explain.

First, for DCD 0xb9205f80, this position is a reserved position according to the distribution chart of the interrupt vector table of ARM7. But why should we use the value 0xb9205f80.

According to Zhou licong, The NXP series of lpc21xx and lpc22xx require that "the 32-bit sum of all data in the interrupt vector table is 0, otherwise the program cannot run offline ", I decompiled the axd and added the eight machine codes in the interrupt vector table: 0xe59ff018*6 + 0xe51ffff0 + 0xb9205f80. That's right. The result is zero. however, I encountered a problem, that is, I changed the value 0xb9205f80 to any value, and the program runs normally. the problem is coming soon ...... (Hope you can give me some advice ).

 

 

2. About ldr pc, [PC, #-0xff0]. here we should have put IRQ interrupted. Why is that. I mentioned this in one of my blog articles.

The third-level assembly line structure of ARM7 leads the PC to point to the last eight bytes of the current command. IRQ should have been placed at 0x00000018. ldr pc, [PC, #-0xff0] After this statement is executed, the current Pc value is 0x00000018 + 8-0xff0. the result is 0xfffff030. take a look at the lpc22xx manual. this address is vicvectaddr. that is to say, this address should have been placed in the entry address of the IRQ service program, but this address is placed in the vicvectaddr register. there is a section in the English manual about vicvectaddr.
Description. It is easy to understand what is going on after reading it: vector address register. When an IRQ interrupt occurs, the IRQ service routine can read this register and jump to the value read

 

ResetAddr           DCD     ResetInitUndefinedAddr       DCD     UndefinedSWI_Addr            DCD     SoftwareInterruptPrefetchAddr        DCD     PrefetchAbortDataAbortAddr       DCD     DataAbortNouse               DCD     0IRQ_Addr            DCD     0FIQ_Addr            DCD     FIQ_Handler

These rows allocate memory space for the interrupt labels in the above interrupt vector table, that is, their execution addresses. at first, I had a question: why don't I use ldr pc, resetinit, or DCD for a transfer? Then I went online and checked it, the address in the LDR command must be within the range of 4 kb for the current command address. You can use DCD to transfer the address to the entire program space.

 

Undefined        B       UndefinedSoftwareInterrupt                             B       SoftwareInterrupt  PrefetchAbort        B       PrefetchAbortDataAbort        B       DataAbortFIQ_Handler        STMFD   SP!, {R0-R3, LR}        BL      FIQ_Exception        LDMFD   SP!, {R0-R3, LR}        SUBS    PC,  LR,  #4

These lines do not need to be explained too much, but explain how to execute the above exceptions.

 

Initstack mov r0, LR; Set Management Mode stack MSR cpsr_c, #0xd3 LDR sp, stacksvc; Set interruption mode stack MSR cpsr_c, #0xd2 LDR sp, stackirq; set the fast interrupt mode stack MSR cpsr_c, #0xd1 LDR sp, stackfiq; set the stop mode stack MSR cpsr_c, #0xd7 LDR sp, stackabt; set the undefined mode stack MSR cpsr_c, # 0xdb LDR sp, stackund; set the system mode stack MSR cpsr_c, # 0xdf LDR sp, = stackusr mov PC, R0

The above is a sub-function named initstack. Yisi. This function sets the stack in seven arm working modes. There are three points to talk about this piece of code.

First, MSR cpsr_c, # 0xdf, set the arm working mode to the system mode or the user mode, because the system mode and user mode share the same register group. when 0xdf is used to assign values to the CPSR register, IRQ interruption is disabled (you can check the detailed description of crsr). When the code is executed normally, the processor is in the user mode, therefore, IRQ interruption will not be executed. therefore, if you use this startup code of Zhou ligong, change 0xdf to 0x5f when your program needs to be interrupted. I have seen many people say on the Internet that using Zhou ligong's ads Engineering Template cannot be interrupted. In many cases, this is the reason.

 

Second, not all stacks in each mode are set. For example, if FIQ is not used in your program, you do not need to set a stack with a fast interruption.

 

Third, pay attention to the LDR sp, = stackusr statement. The other statements do not contain the = sign. Why should we use the equal sign? This is the difference between the LDR pseudo command and the LDR command. LDR sp, = stackusr is to load the address represented by stackusr to SP, LDR sp, stackund loads the content of the stackund address to the sp. Note the following:

StackSvc           DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4

We can see that all labels without "=" have been initialized with DCD, and what is stackusr? It is determined by the following statement.

// Startup. s file area stacks, Data, noinitstackusr // Distributed File stacks 0x40002000 uninit {startup. O (stacks )}

In this case, stackusr must be 0x40000000 ~ A number between 0x400020000. In user mode, the stack space is it.

 

 

ResetInit        BL      InitStack        BL      TargetResetInit        B       __main

The processor enters the function through the interrupt vector table after power-on reset. The main function of __main is to initialize the library function of C and enter the main function of C.

 

__user_initial_stackheap       LDR   r0,=bottom_of_heap;    LDR   r1,=StackUsrMOV   pc,lr

_ User_initial_stackheap is a library function of ads. If files are loaded discretely in the program, this function must be implemented. the Application Stack and heap are established during the C library function initialization process. You can change the location of the stack and heap by redirecting the corresponding subroutine. the stack address has been specified in the distributed file. This function should not modify their values. return the base addresses of heap and stack respectively with R0 and R1. for more information about the storage mechanism of ads, you can go online.

 

StackSvc           DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4  AREA    MyStacks, DATA, NOINIT, ALIGN=2SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  ;Stack spaces for Administration ModeIrqStackSpace      SPACE   IRQ_STACK_LEGTH * 4  ;Stack spaces for Interrupt ReQuest ModeFiqStackSpace      SPACE   FIQ_STACK_LEGTH * 4  ;Stack spaces for Fast Interrupt reQuest ModeAbtStackSpace      SPACE   ABT_STACK_LEGTH * 4  ;Stack spaces for Suspend ModeUndtStackSpace     SPACE   UND_STACK_LEGTH * 4  ;Stack spaces for Undefined Mode

The above code is used to allocate space for stacks in various modes. The position of mystacksa is specified in the distributed file.

 

If: Def: en_crp if.> = 0x1fc info 1, "/nthe data at 0x000001fc must be 0x87654321. /nplease delete some source before this line. "endifcrpdata while. <0x1fc NOP wendcrpdata1 DCD 0x87654321;/* when the data is 0x87654321, user code be protected. when the value is 0x87654321, the user program is protected */endif

The above lines are actually used by the encryption chip. The lpc21xx and lpc22xx series of ARM7. When you select relinflash for your project, the code is written into flash, and the chip is encrypted at the same time, in the encrypted state, the JTAG cannot read the chip or perform single-step debugging. to decrypt the JTAG, you must use the ISP to completely erase it. the above code means to put 0x87654321 data at address 0x1fc to implement the encryption function, but the premise is that if: Def: en_crp, that is, the macro en_cpp is defined. this macro is automatically defined by ads when relinflash is selected. then, let's talk about the 0x87654321 problem.
The lpc2100 family of ARM7 microcontroller is the world's first encrypting ARM chip. The encryption method is to set the specified data on the specified address through the user program. According to Philips, the chip is encrypted when the flash Address 0x000001fc in the chip is 0x87654321 for the lpc2100 chip (except for the lpc2106/2105/2104 chip.

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.