Discussion Forum

enable_irq()/disable_irq() in ARMCC V4

Next Thread | Thread List | Previous Thread Start a Thread | Settings

DetailsMessage
Author
George Brindeiro
Posted
12-Aug-2011 14:32 GMT
Toolset
ARM
New! enable_irq()/disable_irq() in ARMCC V4

Hi everyone,

I have posted to this forum a couple months ago about using the enable_irq()/disable_irq() instruction intrinsics in RealView Compiler (ARMCC V4.0.0.728). In that occasion, I set up two software interrupts for calling such intrinsics, as they only have the intended effect when not in User Mode.

Just now, though, I realized that interrupts were not being disabled. I know for a fact that my SWI are set up appropriately, because they change the value of a flag I set up. Does anyone have any clue what could be happening? Documentation seems to be pretty clear about the fact that one enters supervisor mode during SWI, and that would be appropriate for enabling/disabling interrupts, but I must be missing something.

Relevant source code

void __SWI_8 (void)
{
  __enable_irq();
  __enable_fiq();
  interrupts_enabled = 1;
}

void __SWI_9 (void)
{
  __disable_irq();
  __disable_fiq();
  interrupts_enabled = 0;
}

Relevant links

Instruction Intrinsics
http://www.keil.com/support/man/docs/armcc/armcc_chdfgfab.htm

disable_irq()
http://www.keil.com/support/man/docs/armccref/armccref_CJAFBCBB.htm

enable_irq()
http://www.keil.com/support/man/docs/armccref/armccref_CJAEAEHA.htm

ARMCC: MODIFY IRQ FLAG TO ENABLE/DISABLE INTERRUPTS (RealView Compiler V3)
http://www.keil.com/support/docs/3229.htm

Thanks in advance,
--
George Andrew Brindeiro
Robotron Automation and Technology

Author
George Brindeiro
Posted
15-Aug-2011 18:35 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

Can anyone help me figure out what is going on?

Author
Last Zeusti
Posted
15-Aug-2011 20:07 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

too long since i did this.

when you go into the swi, the processor switches to another dedicated CPSR. you changing irq and fiq change the CPSR of the swi.

when you leave swi the original cpsr gets restored. you disabling irq and fiq are only good in side the swi.

can be bad detail but consept is right.

always yo're freind.

Zeusti

ARM programmer and chef management engineer and desine consultant (retyred)

Author
ex ARM Zeusti
Posted
15-Aug-2011 20:22 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

i never said rtfm but u can look at the hitex insiders guides. they r good.

http://www.hitex.co.uk/index.php?id=download-insiders-guides0

also look for the abi. real ARM experts know it.

Always yo're freind.

Zeusti.

zeusti@supercomputersforyouandyoremum.com

Author
George Brindeiro
Posted
15-Aug-2011 20:44 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

Zeusti,

Thanks for the reply, you have a good point.

I have read the hitex manuals, and was aware of the dedicated CPSR, but I guess I thought the intrinsics would change the CPSR in User Mode through the SPSR in Supervisor Mode.

I'll check if I can make it work by writing some inline assembly, and get back to this topic.

--
George Andrew Brindeiro
Robotron Automation and Technology

Author
George Brindeiro
Posted
17-Aug-2011 19:10 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4
SWI_Handler
                 :
                 :
                BICEQ   R12, R12, #0xFF000000  ; Extract SWI Number

; add code to enable/disable the global IRQ flag
                CMP     R12,#0xFE         ; disable IRQ implemented as __SWI 0xFE
                BEQ     disable_IRQ
                CMP     R12,#0xFF         ; enable IRQ implemented as __SWI 0xFF
                BEQ     enable_IRQ

                LDR     R8, SWI_Count
                 :
                 :
SWI_End

disable_IRQ
                LDMFD   SP!, {R8, R12}    ; Load R8, SPSR
                ORR     R12, R12, #0x80   ; Set IRQ flag to disable it
                MSR     SPSR_cxsf, R12    ; Set SPSR
                LDMFD   SP!, {R12, PC}^   ; Restore R12 and Return

enable_IRQ
                LDMFD   SP!, {R8, R12}    ; Load R8, SPSR
                BIC     R12, R12, #0x80   ; Set IRQ flag to disable it
                MSR     SPSR_cxsf, R12    ; Set SPSR
                LDMFD   SP!, {R12, PC}^   ; Restore R12 and Return

                END

Can someone explain why LDMFD R8 and R12, and then restore to R12 and PC?
How come SPSR is in R12? I thought one should use MRS to load the CPSR/SPSR.

Thanks,
--
George Andrew Brindeiro
Robotron Automation and Technology

Author
George Brindeiro
Posted
17-Aug-2011 19:47 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

I tried doing the following:

void __SWI_8 (void)
{
  //__enable_irq();
  //__enable_fiq();
  int temp;

   __asm
  {
     MRS     temp, SPSR_cxsf        // Get SPSR
     ORR     temp, temp, #0xC0      // Set IRQ/FIQ flag to disable
     MSR     SPSR_cxsf, temp        // Set SPSR
  }

  interrupts_enabled = 1;
}

void __SWI_9 (void)
{
  //__disable_irq();
  //__disable_fiq();
  int temp;

  __asm
  {
     MRS     temp, SPSR_cxsf        // Get SPSR
     BIC     temp, temp, #0xC0      // Clear IRQ/FIQ flag to enable
     MSR     SPSR_cxsf, temp        // Set SPSR
  }

  interrupts_enabled = 0;
}

This compiles, and I thought it would work, but obviously it doesn't...

I checked the output of the compiler, I don't see any reference (except for comments) to my asm code. Specifically, this is what I get:

                  __SWI_8 PROC
;;;49
;;;50     void __SWI_8 (void)
000084  e59f1040          LDR      r1,|L1.204|
;;;51     {
;;;52       //__enable_irq();
;;;53       //__enable_fiq();
;;;54       int temp;
;;;55
;;;56        __asm
;;;57       {
;;;58          MRS     temp, SPSR             // Get SPSR
;;;59          ORR     temp, temp, #0xC0      // Set IRQ/FIQ flag to disable
;;;60          MSR     SPSR, temp             // Set SPSR
;;;61       }
;;;62
;;;63       interrupts_enabled = 1;
000088  e3a00001          MOV      r0,#1
00008c  e5c10000          STRB     r0,[r1,#0]  ; interrupts_enabled
;;;64     }
000090  e12fff1e          BX       lr
;;;65
                          ENDP

                  __SWI_9 PROC
;;;66     void __SWI_9 (void)
000094  e59f1030          LDR      r1,|L1.204|
;;;67     {
;;;68       //__disable_irq();
;;;69       //__disable_fiq();
;;;70       int temp;
;;;71
;;;72       __asm
;;;73       {
;;;74          MRS     temp, SPSR             // Get SPSR
;;;75          BIC     temp, temp, #0xC0      // Clear IRQ/FIQ flag to enable
;;;76          MSR     SPSR, temp             // Set SPSR
;;;77       }
;;;78
;;;79       interrupts_enabled = 0;
000098  e3a00000          MOV      r0,#0
00009c  e5c10000          STRB     r0,[r1,#0]  ; interrupts_enabled
;;;80     }
0000a0  e12fff1e          BX       lr
;;;81
                          ENDP

Any tips on where I'm wrong? This should be relatively straightforward.

Thanks,
--
George Andrew Brindeiro
Robotron Automation and Technology

Author
John Linq
Posted
18-Aug-2011 01:58 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

http://www.keil.com/support/man/docs/armcc/armcc_Chdgddcj.htm

Restrictions on inline assembly operations

Some low-level features that are available in the ARM assembler armasm, such as branching and writing to PC, are not supported.

Registers such as r0-r3, sp, lr, and the NZCV flags in the CPSR must be used with caution. If you use C or C++ expressions, these might be used as temporary registers and NZCV flags might be corrupted by the compiler when evaluating the expression. See Virtual registers.

The pc, lr, and sp registers cannot be explicitly read or modified using inline assembly code because there is no direct access to any physical registers. However, you can use the following intrinsics described in the Compiler Reference Guide to access these registers:

Author
George Brindeiro
Posted
18-Aug-2011 18:55 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

Hi John,

Thanks for the reply, but I did not directly access these registers.

Maybe you were confused by the second code section I posted... that is the assembly output of the compiler, not my code. Note that the code I posted in the first code section is commented out with semi-colons, and the corresponding assembly code follows.

Anyone else?

--
George Andrew Brindeiro
Robotron Automation and Technology

Author
John Linq
Posted
19-Aug-2011 02:20 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

Sorry for my limited knowledge.

I did not notice this:
http://www.keil.com/support/man/docs/armcc/armcc_Chdgbbia.htm
There is no virtual Processor Status Register (PSR). Any references to the PSR are always to the physical PSR.

Hope my second try would be better.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/1472.html

Note that CPSR_c is used instead of CPSR in the MSR instruction, to avoid altering the condition code flags.
A better implementation is:

/* NewState=1 will enable IRQ, NewState=0 will disable IRQ */
/* ARM core must be in a privileged mode, e.g. supervisor  */
void ChangeIRQ(unsigned int NewState)
{
    int my_cpsr;

    __asm
    {
    MRS my_cpsr, CPSR                        /* get current program status */
    ORR my_cpsr, my_cpsr, #0x80              /* set IRQ disable bit flag */
    BIC my_cpsr, my_cpsr, NewState, LSL #7   /* reset IRQ bit with new value */
    MSR CPSR_c, my_cpsr                      /* store updated program status */
    }
}


which compiles into:

ChangeIRQ
    MRS r1,CPSR
    ORR r1,r1,#0x80
    BIC r0,r1,r0,LSL #7
    MSR CPSR_c,r0
    MOV pc,lr
Author
John Linq
Posted
19-Aug-2011 02:30 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

A corrected link to the mentioned code:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3746.html

Author
George Brindeiro
Posted
19-Aug-2011 18:35 GMT
Toolset
ARM
New! RE: enable_irq()/disable_irq() in ARMCC V4

Hi,

I had to make some modifications to the code, but essentially it worked. For instance, that code assumes that the program is in Privileged Mode. In that case, I have to change the SPSR and not the CPSR, if I want interrupts to be enabled/disabled in User Mode.

I added that code with some modifications to my SWI code and the assembler output is consistent (the inline assembly part is showing in the code). Whenever I am able to test on the board, I'll post the final SWI code.

Thanks for the link!
--
George Andrew Brindeiro
Robotron Automation and Technology

Next Thread | Thread List | Previous Thread Start a Thread | Settings