Masking global interrupts from AT91 Thumb code

classic Classic list List threaded Threaded
2 messages Options
mpthompson mpthompson
Reply | Threaded
Open this post in threaded view
|

Masking global interrupts from AT91 Thumb code

Over the last few days I've been working on getting Atmel's USB handling infrastructure for Communication Device Class (CDC) running for eLua for the AT91SAM7S256.  Ralph Hempel already blazed the trial here and gave me a LOT of help and encouragement to an otherwise daunting task.  During this process I came across a solution to a situation that I think may help others working with AT91 ARMs.  

With eLua being compiled under the control of scons, I have yet to determine how to conditionally compile some code with the ARM instruction set and other code with the Thumb instruction set.  Additionally, there is also the issue of controlling the optimization level on a per file basis to handle optimization bugs in certain critical code.

In any case, I needed to mask interrupts at the processor level, but all C code in the project is compiled as Thumb code (except for the C startup assembly files) which doesn't give access to the CPSR register to mask interrupts.  Using Google I was only able to find helper routines that required the processor to be in ARM instruction mode or required the '-mthumb-interwork' option on all C code which gave me grief when linking eLua against other libraries.  

In any case, to make a long story short, using hints and code snips from around the Internet I ended up creating my own helper routines that allow the masking of processor IRQ and FIQ interrupts from Thumb code.  They are only about 10 lines of in-line assembly.  I thought other people working eLua might find these useful when dealing with interrupt level drivers.

The helper functions to enable/disable interrupts within Thumb code are shown below.  I've done in-line assembly for AVR microcontrollers within GCC, but this is my first foray into ARM/Thumb assembly code.  As far as I can tell, these functions work as intended, but please let me know if there are better ways to implement these functions.  

BTW, USB support is now working beautifully with eLua and I get the Lua prompt over a USB virtual com port.  Thanks Ralph!!!

Mike Thompson

----------------------------------------------------------------
#include <interrupts.h>

//
// The AT91 is based on the ARM7TDMI microcontroller core.
// This microcontroller core implements two physically independent
// sources of interrupt:
//
// FIQ - Fast Interrupt
// IRQ - Normal Interrupt
//
// Both of these interrupts can be enabled/disabled at core level, by
// clearing/setting the corresponding bit in the CPSR (Current Processor
// Status Register):
//
// FIQ - bit 6 (clear = enabled, set = disabled)
// IRQ - bit 7 (clear = enabled, set = disabled)
//
// The code below is specifically created to mask interrupts within
// code compiled for the thumb instruction set.  To do this, the code
// will first switch the AT91 to the ARM instruction set, disable the
// interrupts by clearing the proper bits in the CPSR.  The original
// value of the CPSR is returned so that it can be later restored to
// return the interrupt bits to their previous values.
//

// Disable interrupts at the processor level.
unsigned long DisableInterrupts(void)
{
    unsigned long savedCpsr;

    asm volatile (
        // Switch on ARM mode.
        // Involves uncoditional jump and mode switch (opcode bx).
        // The lowest bit in the address signals whether are (bit cleared)
        // or thumb should be selected (bit set).  
        ".align 4 \n"
        " mov r0, pc \n"
        " bx r0 \n"
        ".arm \n"

        // Save CPSR, mask interrupts and set updated CPSR.
        " mrs r0, cpsr \n"
        " mov %0, r0 \n"
        " orr r0, r0, #(0x80|0x40)\n"
        " msr cpsr_c, r0 \n"

        // Switch to thumb mode.
        // Lower bit of destination is set to 1.
        " add r0, pc, #1 \n"
        " bx r0 \n"
        ".align 2 \n"
        ".thumb \n"
        : "=r" (savedCpsr)
        : // no inputs
        : "r0"
    );

    return savedCpsr;
}


// Restore interrupts at the processor level to a previous state.
void RestoreInterrupts(unsigned long savedCpsr)
{
    asm volatile (
        // Switch on ARM mode.
        // Involves uncoditional jump and mode switch (opcode bx).
        // The lowest bit in the address signals whether are (bit cleared)
        // or thumb should be selected (bit set).  
        ".align 4 \n"
        " mov r0, pc \n"
        " bx r0 \n"
        ".arm \n"

        // Update CPSR supplied by caller.
        " msr cpsr_c, %0 \n"

        // Switch to thumb mode.
        // Lower bit of destination is set to 1.
        " add r0, pc, #1 \n"
        " bx r0 \n"
        ".align 2 \n"
        ".thumb \n"
        : // no outputs
        : "r" (savedCpsr)
        : "r0"
    );
}


Dean Hall Dean Hall
Reply | Threaded
Open this post in threaded view
|

Re: Masking global interrupts from AT91 Thumb code

Good job Mike.  I hope your USB code gets mainlined so I can take a  
peek.
Here is a SConscript that I used in PyMite to build some files in ARM  
mode and others in Thumb mode using two environments, envarm and env,  
respecitvely:

http://pymite.python-hosting.com/file/trunk/src/platform/at91sam7s-ek/SConscript

Background info: the scons build starts in trunk/SConstruct.  The user  
types "scons PLATFORM=<platform>" where <platform> is the name of a  
directory in src/platform/.  The SConstruct calls the SConscript in  
the platform directory where platform-specific stuff happens, like  
defining the toolchain, compiler args, cdefs and options for the VM.  
The SConscript in platform then calls ../../vm/SConscript to build the  
VM as a library.  Back in the platform directory, the VM library is  
linked to main.c and any platform-specific files using platform linker  
scripts.

It took a lot of scouring the SCons manual and trial-and-error to get  
the PyMite scons build working, but I like the result.  However, I  
still haven't been able to completely replace my Makefiles yet.

!!Dean


On Apr 1, 2009, at 13:31 , mpthompson wrote:

>
> Over the last few days I've been working on getting Atmel's USB  
> handling infrastructure for Communication Device Class (CDC) running  
> for eLua for the AT91SAM7S256.  Ralph Hempel already blazed the  
> trial here and gave me a LOT of help and encouragement to an  
> otherwise daunting task.  During this process I came across a  
> solution to a situation that I think may help others working with  
> AT91 ARMs.
>
> With eLua being compiled under the control of scons, I have yet to  
> determine how to conditionally compile some code with the ARM  
> instruction set and other code with the Thumb instruction set.  
> Additionally, there is also the issue of controlling the  
> optimization level on a per file basis to handle optimization bugs  
> in certain critical code.

_______________________________________________
Elua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev