This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC2000 nested Interrupts /Realview

Dear People,

I am interested to use the Nested Interrupt in Software in a simple way shown in Examples, but in current RealView Tools it is not possible to access the Registers SP, LR, PSR via Inline Assembly with Assembler Macros.
Macros for GCC and legacy Keil Tools:

// Macros for Interrupt Nesting
#define IENABLE
__asm { MRS LR, SPSR }
__asm { STMFD SP!, {LR} }
__asm { MSR CPSR_c, #0x1F }
__asm { STMFD SP!, {LR} }

#define IDISABLE
__asm { LDMFD SP!, {LR} }
__asm { MSR CPSR_c, #0x92 }
__asm { LDMFD SP!, {LR} }
__asm { MSR SPSR_cxsf, LR }

Instead of the Macros, Mr. Dietmar Wengler developed the following Assembler Functions for Embedded Assembler:

nested_irq_enable:
STMFD SP!, {R0}
MOV R0, LR
MRS LR, SPSR
STMFD SP!, {LR}
MSR CPSR_c, #0x1F
STMFD SP!, {LR}
BX R0

nested_irq_disable:
MOV R0, LR
LDMFD SP!, {LR}
MSR CPSR_c, #0x92
LDMFD SP!, {LR}
MSR SPSR_cxsf, LR
MOV LR, R0
LDMFD SP!, {R0}
BX LR

could you tell me how can i the call the nested_irq_enable and the nested_irq_disable in the c-Code. I use the Realview Compiler.

Thanks.

  • you can put them in a separate function:

    void __asm disable(foo)
    {
      STMFD SP!, {R0}
      MOV R0, LR
      MRS LR, SPSR
      STMFD SP!, {LR}
      MSR CPSR_c, #0x1F
      STMFD SP!, {LR}
      BX R0
    

    which you can call from C code (maybe it is not a bad idea to make this a SWI function).

  • Hello Micheal,

    i get even so the error: #7: unrecognized token

    Thanks

  • So use a token that is recognised, then!!

  • Replace the "foo" above with "void". Sorry...

  • I get 2x unrecognized token. the unrecognized tokens in that case are in place: STMFD SP!, {R0} and MOV R0, LR

  • Hello Michael,
    i made the function as SWI function:

    void __swi(0) __asm nestedIrqEnable(void);

    void __SWI_0 (void){

    STMFD SP!, {R0}

    MOV R0, LR

    MRS LR, SPSR

    STMFD SP!, {LR}

    MSR CPSR_c, #0x1F

    STMFD SP!, {LR}

    BX R0

    }
    =====================================================
    But i get the errors:
    Intrp.c(21): error: #20: identifier "STMFD" is undefined
    Intrp.c(21): error: #65: expected a ";"
    Intrp.c(25): error: #10: "#" not expected here
    Intrp.c(28): warning: #12-D: parsing restarts here after previous syntax error

    Thanks

  • try this syntax:

    void __asm __swi(0) disable_interrupts(void) ;
    void __asm __SWI_0                                (void)
    

  • could you tell me Michael what the advantage of SWI in that case

    Thanks

  • A SWI function blocks all IRQ sources as long as it is executed (and a little bit more), but not against FIQ source(s). You don't have to do it, if you guarantee that
    1. The context of the processor is always restored correctly after an IRQ.
    2. your code does not tamper with R13.
    3. your code does not have an explicit/implicit dependency of IRQ sources.
    4. there are probably additional reasons...

  • Hello Michael,

    the 1. variant with separate function worked wonderful.

    =======================================================
    1. Variant:

    void __asm nestedIrqEnable(void){

    STMFD SP!, {R0}

    MOV R0, LR

    MRS LR, SPSR

    STMFD SP!, {LR}

    MSR CPSR_c, #0x1F

    STMFD SP!, {LR}

    BX R0
    }

    void __asm nestedIrqDisable(void){

    MOV R0, LR

    LDMFD SP!, {LR}

    MSR CPSR_c, #0x92

    LDMFD SP!, {LR}

    MSR SPSR_cxsf, LR

    MOV LR, R0

    LDMFD SP!, {R0}

    BX LR
    }

    the 2. Variant with SWI-function:
    2. Variant: by this variant the variable intrp_count in the eint1_srv() interrupt subroutine is not inceremented.

    ====================================================

    void __asm __swi(0) nestedIrqEnable(void);

    void __asm __SWI_0(void) { //Nested Interrupts Entry: STMFD SP!, {R0}

    MOV R0, LR

    MRS LR, SPSR

    STMFD SP!, {LR}

    MSR CPSR_c, #0x1F

    STMFD SP!, {LR}

    BX R0
    }

    void __asm __swi(1) nestedIrqDisable(void);
    void __asm __SWI_1 (void) {//Nested Interrupts Exit:
    MOV R0, LR

    LDMFD SP!, {LR}

    MSR CPSR_c, #0x92

    LDMFD SP!, {LR}

    MSR SPSR_cxsf, LR

    MOV LR, R0

    LDMFD SP!, {R0}

    BX LR
    }

    /* Create a long time delay */

    void delay (void) {

    int i;

    for (i = 0; i < 0x50000; i++) {

    ;

    }

    }

    void eint1_srv (void) __irq {

    EXTINT = 2; // Clear EINT1 interrupt flag

    nestedIrqEnable(); // allow nested interrupts

    delay (); // wait a long time

    ++intrp_count; // increment interrupt count

    nestedIrqDisable(); // disable interrupt nesting

    VICVectAddr = 0; // Acknowledge Interrupt

    }
    ======================================================

    I tested previously the SWI-Mode in the same Project with the folowing code in conjunction with the below SWI.s file:
    int __swi(0) swi_sum(int x, int y);
    int __SWI_0 (int x, int y){

    return (x+y);

    }

    int __swi(1) swi_mul (int x, int y);
    int __SWI_1 (int x, int y){

    return (x*y);

    }
    ===================
    SWI.S:
    T_Bit EQU 0x20

    PRESERVE8 ;8-Byte aligned Stack

    AREA SWI_Area, CODE, READONLY

    ARM

    EXPORT SWI_Handler

    SWI_Handler

    STMFD SP!, {R12, LR} ; Store R12, LR

    MRS R12, SPSR ; Get SPSR

    STMFD SP!, {R8, R12} ; Store R8, SPSR

    TST R12, #T_Bit ; Check Thumb Bit LDRNEH R12, [LR,#-2] ; Thumb: Load Halfword

    BICNE R12, R12, #0xFF00

    ; Extract SWI Number LDREQ R12, [LR,#-4] ;
    ARM: Load Word BICEQ R12, R12, #0xFF000000

    ; Extract SWI Number

    LDR R8, SWI_Count

    CMP R12, R8

    BHS SWI_Dead ;
    Overflow ADR R8, SWI_Table

    LDR R12, [R8,R12,LSL #2] ; Load
    SWI Function Address MOV LR, PC ; Return Address

    BX R12 ; Call SWI Function

    LDMFD SP!, {R8, R12} ; Load R8, SPSR

    MSR SPSR_cxsf, R12 ; Set SPSR

    LDMFD SP!, {R12, PC}^ ; Restore R12 and Return

    SWI_Dead B SWI_Dead ; None Existing SWI

    SWI_Cnt EQU (SWI_End-SWI_Table)/4

    SWI_Count DCD SWI_Cnt

    IMPORT __SWI_0

    IMPORT __SWI_1

    SWI_Table DCD __SWI_0 ; SWI 0 Function Entry DCD __SWI_1 ; SWI 1 Function Entry

    ; ...
    SWI_End

    END
    ====================================================
    The code for the swi_sum and swi_mul functioned.

    Thank you for your Help.

  • I cannot read this. please re-post using the proper tags.

  • Hello Michael here is the reposted question,

    the 1. variant with separate function worked wonderful.

    1. Variant:

    void __asm nestedIrqEnable(void){
    
    STMFD SP!, {R0}
    
    MOV R0, LR
    
    MRS LR, SPSR
    
    STMFD SP!, {LR}
    
    MSR CPSR_c, #0x1F
    
    STMFD SP!, {LR}
    
    BX R0
    }
    
    void __asm nestedIrqDisable(void){
    
    MOV R0, LR
    
    LDMFD SP!, {LR}
    
    MSR CPSR_c, #0x92
    
    LDMFD SP!, {LR}
    
    MSR SPSR_cxsf, LR
    
    MOV LR, R0
    
    LDMFD SP!, {R0}
    
    BX LR
    }
    

    By the 2. Variant with SWI-function the variable intrp_count in the eint1_srv() interrupt subroutine is not inceremented.

    2. Variant:

    void __asm __swi(0) nestedIrqEnable(void);
    
    void __asm __SWI_0(void) { //Nested Interrupts Entry: STMFD SP!, {R0}
    
    MOV R0, LR
    
    MRS LR, SPSR
    
    STMFD SP!, {LR}
    
    MSR CPSR_c, #0x1F
    
    STMFD SP!, {LR}
    
    BX R0
    }
    
    void __asm __swi(1) nestedIrqDisable(void);
    void __asm __SWI_1 (void) {//Nested Interrupts Exit:
    MOV R0, LR
    
    LDMFD SP!, {LR}
    
    MSR CPSR_c, #0x92
    
    LDMFD SP!, {LR}
    
    MSR SPSR_cxsf, LR
    
    MOV LR, R0
    
    LDMFD SP!, {R0}
    
    BX LR
    }
    
    /* Create a long time delay */
    
    void delay (void) {
    
    int i;
    
    for (i = 0; i < 0x50000; i++) {
    
    ;
    
    }
    
    }
    
    void eint1_srv (void) __irq {
    
    EXTINT = 2; // Clear EINT1 interrupt flag
    
    nestedIrqEnable(); // allow nested interrupts
    
    delay (); // wait a long time
    
    ++intrp_count; // increment interrupt count
    
    nestedIrqDisable(); // disable interrupt nesting
    
    VICVectAddr = 0; // Acknowledge Interrupt
    
    }
    


    I tested previously the SWI-Mode in the same Project with the folowing code in conjunction with the below SWI.s file

    nt __swi(0) swi_sum(int x, int y);
    int __SWI_0 (int x, int y){
    return (x+y);
    }
    int __swi(1) swi_mul (int x, int y);
    int __SWI_1 (int x, int y){
    return (x*y);
    }
    

    SWI.S-File:

    T_Bit EQU 0x20
    
    PRESERVE8 ;8-Byte aligned Stack
    
    AREA SWI_Area, CODE, READONLY
    
    ARM
    
    EXPORT SWI_Handler
    
    SWI_Handler
    
    STMFD SP!, {R12, LR} ; Store R12, LR
    
    MRS R12, SPSR ; Get SPSR
    
    STMFD SP!, {R8, R12} ; Store R8, SPSR
    
    TST R12, #T_Bit ; Check Thumb Bit LDRNEH R12, [LR,#-2] ; Thumb: Load Halfword
    
    BICNE R12, R12, #0xFF00
    
    ; Extract SWI Number LDREQ R12, [LR,#-4] ;
    ARM: Load Word BICEQ R12, R12, #0xFF000000
    
    ; Extract SWI Number
    
    LDR R8, SWI_Count
    
    CMP R12, R8
    
    BHS SWI_Dead ;
    Overflow ADR R8, SWI_Table
    
    LDR R12, [R8,R12,LSL #2] ; Load
    SWI Function Address MOV LR, PC ; Return Address
    
    BX R12 ; Call SWI Function
    
    LDMFD SP!, {R8, R12} ; Load R8, SPSR
    
    MSR SPSR_cxsf, R12 ; Set SPSR
    
    LDMFD SP!, {R12, PC}^ ; Restore R12 and Return
    
    SWI_Dead B SWI_Dead ; None Existing SWI
    
    SWI_Cnt EQU (SWI_End-SWI_Table)/4
    
    SWI_Count DCD SWI_Cnt
    
    IMPORT __SWI_0
    
    IMPORT __SWI_1
    
    SWI_Table DCD __SWI_0 ; SWI 0 Function Entry DCD __SWI_1 ; SWI 1 Function Entry
    
    ; ...
    SWI_End
    
    END
    


    The code for the swi_sum and swi_mul functioned.

    Thank you for your Help