#define save_context_from_irq()
#define restore_context()
#define enable_IRQ_and_FIQ()
#define disable_IRQ_and_FIQ()


typedef int miosix_private::interrupt_t


void miosix::IRQfind_next_thread ()
void system_reboot ()
void miosix_private::disable_interrupts ()
void miosix_private::enable_interrupts ()
interrupt_t miosix_private::disable_and_save_interrupts ()
void miosix_private::restore_interrupts (interrupt_t i)
bool miosix_private::are_interrupts_enabled ()
int miosix_private::atomic_swap (int newval, int *var)

Detailed Description

Miosix drivers API

Contains functions and macros that can be used to write drivers for hardware peripherals. These functions, plus the IRQ methods of the Queue class provide a way to transfer data between an interrupt routine and user code, and a way to cause preemption inside an interrupt routine to wake a higher priority Thread waiting on some hardware peripheral.

Define Documentation

#define disable_IRQ_and_FIQ (  ) 


{                                                                               \
 asm volatile(".set  I_BIT, 0x80                        \n\t"                   \
              ".set  F_BIT, 0x40                        \n\t"                   \
              "mrs r0, cpsr                             \n\t"                   \
              "orr r0, r0, #I_BIT|F_BIT                 \n\t"                   \
              "msr cpsr_c, r0                           \n\t"                   \
              :::"r0");                                                         \
Disable interrupts (both irq and fiq)
If you are not using FIQ you should use miosix_private::enable_interrupts()

#define enable_IRQ_and_FIQ (  ) 


{                                                                               \
 asm volatile(".set  I_BIT, 0x80                        \n\t"                   \
              ".set  F_BIT, 0x40                        \n\t"                   \
              "mrs r0, cpsr                             \n\t"                   \
              "and r0, r0, #~(I_BIT|F_BIT)              \n\t"                   \
              "msr cpsr_c, r0                           \n\t"                   \
              :::"r0");                                                         \
Enable interrupts (both irq and fiq)
If you are not using FIQ you should use miosix_private::disable_interrupts() FIQ means fast interrupts, is another level of interrupts available in the ARM7 cpu. They are not used in miosix, and are available to the user. The main advantage of FIQ is that they can even interrupt IRQ, so they have a so high priority that can interrupt the kernel itself.
The disadvantage is that, since can interrupt the kernel at any time, all functions, including those marked as IRQ cannot be called when IRQ and FIQ are disabled. Therefore, data transfer between user code and FIQ is more difficult to implement than IRQ. Another disadvantage is that they are only available in the ARM cpu, so if the kernel will be ported to another cpu, they won't be available.
To use FIQ the user must change the code of the default FIQ interrupt routine defined in miosix/drivers/interrupts.cpp
By default FIQ are enabled but no peripheral is associated with FIQ, so no FIQ interrupts will occur.

#define restore_context (  ) 


{                                                                               \
        asm volatile(   /*load ctxsave and dereference the pointer*/            \
                    /*also add 64 to make it point to "top of stack"*/          \
                    "ldr        lr,=ctxsave             \n\t"                   \
                    "ldr        lr,[lr]                 \n\t"                   \
                    "add        lr,lr,#64               \n\t"                   \
                    /*restore spsr*/                                            \
                    /*after this instructions, lr points to ctxsave[15] (return address)*/  \
                    "ldmda      lr!,{r1}                \n\t"                   \
                    "msr        spsr,r1                 \n\t"                   \
                    /*restore all thread registers except pc*/                  \
                    "ldmdb      lr,{r0-lr}^             \n\t"                   \
                    /*add a nop as required after ldm ^ (read ARM reference about ldm(2))*/ \
                    "nop                                \n\t"                   \
                    /*now that lr points to return address, return from interrupt*/         \
                    "ldr        lr,[lr]                 \n\t"                   \
                    "movs       pc,lr                   \n\t");                 \
Restore context in an IRQ where save_context_from_irq() (or save_context_from_swi() ) is used. Must be the last line of an IRQ where a context switch can happen. The IRQ must be "naked" to prevent the compiler from generating context restore.

#define save_context_from_irq (  ) 


{                                                                               \
        asm volatile(   /*Adjust lr, because the return address in a ISR has a 4 bytes offset*/ \
                    "sub        lr,lr,#4                \n\t");                 \
        save_context_from_swi();                                                \
Save context from an IRQ
Must be the first line of an IRQ where a context switch can happen. The IRQ must be "naked" to prevent the compiler from generating context save.

Typedef Documentation

typedef int miosix_private::interrupt_t

Definition of a type that can hold interrupt status.

Function Documentation

bool miosix_private::are_interrupts_enabled (  ) 

This function returns true if interrupts are enabled

int miosix_private::atomic_swap ( int  newval,
int *  var 

Atomic swap, may be used to implement critical sections efficiently. If the cpu supports it implemented using the cpu assembler intruction, else emulated by disabling the kernel. The implementation on the ARM7 cpu uses the dedicated assembler instruction.

newval new value to be written to var
var pointer to a variable
old value stored in var

interrupt_t miosix_private::disable_and_save_interrupts (  ) 

This function stores the interrupt status in the return value, and if interrupts are enabled, disables them (irq only).

interrupt status

void miosix_private::disable_interrupts (  ) 

disable interrupts (irq only) Note that this does not disable fiq.

void miosix_private::enable_interrupts (  ) 

enable interrupts (irq only)

void miosix::IRQfind_next_thread (  ) 

This function is used to developed interrupt driven peripheral drivers.
Can be used ONLY inside an IRQ (and not when interrupts are disabled) to find next thread in READY status. If the kernel is paused, does nothing. Can be used for example if an IRQ causes a higher priority thread to be woken, to change context. Note that to use this function the IRQ must use the macros to save/restore context defined in portability.h

void miosix_private::restore_interrupts ( interrupt_t  i  ) 

This function restores the interrupt status in the condition before disable_and_save_interrupts() was called.

i interrupt status, as returned by disable_and_save_interrupts()

void system_reboot (  ) 

Used after an unrecoverable error condition to restart the system, even from within an interrupt routine.

Generated on Fri Jun 19 15:19:04 2009 for Miosix by  doxygen 1.5.6