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

Nested Interrupt Question

Hi,

I have very long function that I want to be executed on time, even if other long functions (less important) are running in my main loop.

So my Idea was to write this function in an interrupt, that can be interrupted by my other, short interrupts (communication etc.)

I am trying to use the IENABLE and IDISABLE macros for the interruptable interrupt, but they don't seem to have any effect (or even cause crashes)

I'm using STR91FAM with uvision3 and ARM-ELF-GCC

Any ideas?

  • As far as I can recall, there macros apply to the Keil ARM compiler, not RealView.
    Maybe something like this will do, or maybe there are intrinsic functions to do it...?

    void __asm enable_nested_interrupts(void)
    {
        MOV     R0, LR
    
        MRS     LR, SPSR                ; Copy SPSR_irq to LR
        PUSH    {LR}                    ; Save SPSR_irq
        MSR     CPSR_c, #0x1F           ; Enable IRQ (Sys Mode)
        PUSH    {LR}                    ; Save LR
    
        MOV     LR, R0
    
        BX LR
    }
    
    void __asm disable_nested_interrupts(void)
    {
        MOV     R0, LR
    
        POP     {LR}                    ; Restore LR
        MSR     CPSR_c, #0x92           ; Disable IRQ (IRQ Mode)
        POP     {LR}                    ; Restore SPSR_irq to LR
        MSR     SPSR_cxsf, LR           ; Copy LR to SPSR_irq
    
        MOV     LR, R0
    
        BX LR
    }
    

    Note that I just scribbled this, and that you may be able to find a better solution rather than nested interrupts.

  • Those functions look pretty much like the macros I'm already using:

    
    #define IENABLE asm(" MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \ 
    asm("STMFD SP!, {LR} "); /* Save SPSR_irq */ \ 
    asm("MSR CPSR_c, #0x1F "); /* Switch to SYS mode with IRQ enabled*/ \ 
    asm("STMFD SP!, {LR} ") ; /* Save SYS mode LR */
    
    #define IDISABLE asm("LDMFD SP!, {LR}") ; /* Restore SYS mode LR */ \ 
    asm("MSR CPSR_c, #0x92") ; /* Switch to IRQ mode with IRQ disabled*/ \ 
    asm("LDMFD SP!, {R0}") ; /* Restore SPSR_irq to R0 */ \ 
    asm("MSR SPSR_cxsf, R0") ; /* Copy R0 to SPSR_irq */
    
    

    I want to call my big function whenever a complete data package is received via SPI, so I placed these lines at the end of the SPI interrupt:

    if(SPI_TransferCompleted)
    {
       SPI_TransferCompleted = 0;
       IENABLE;
       BigFunction();
       IDISABLE;
    }
    // write any value to VIC1 VAR
    VIC1->VAR = 0xFF;
    

    I can compile this, but the controller behaves awkwardly and crashes after a few seconds