From 6dea259ea2dd0afc4b610961e211d77460cfd0c6 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 9 Jul 2014 18:47:59 +1000 Subject: Example added for FreeRTOS on Raspberry Pi --- .../example-FreeRTOS/Drivers/interrupts.c | 166 +++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c (limited to 'boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c') diff --git a/boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c b/boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c new file mode 100644 index 00000000..9908b7c4 --- /dev/null +++ b/boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c @@ -0,0 +1,166 @@ +/** + * Integrated Interrupt Controller for RaspberryPi. + * @author James Walmsley + **/ + +#include "interrupts.h" +#include "bcm2835_intc.h" + +static INTERRUPT_VECTOR g_VectorTable[BCM2835_INTC_TOTAL_IRQ]; + + +typedef struct { + unsigned long IRQBasic; // Pending 0 + unsigned long Pending1; + unsigned long Pending2; + unsigned long FIQCtrl; + unsigned long Enable1; + unsigned long Enable2; + unsigned long EnableBasic; + unsigned long Disable1; + unsigned long Disable2; + unsigned long DisableBasic; +} BCM2835_INTC_REGS; + +static volatile BCM2835_INTC_REGS * const pRegs = (BCM2835_INTC_REGS *) (BCM2835_BASE_INTC); + +/** + * Enables all IRQ's in the CPU's CPSR register. + **/ +static void irqEnable() { + __asm volatile("mrs r0,cpsr"); // Read in the cpsr register. + __asm volatile("bic r0,r0,#0x80"); // Clear bit 8, (0x80) -- Causes IRQs to be enabled. + __asm volatile("msr cpsr_c, r0"); // Write it back to the CPSR register +} + +static void irqDisable() { + __asm volatile("mrs r0,cpsr"); // Read in the cpsr register. + __asm volatile("orr r0,r0,#0x80"); // Set bit 8, (0x80) -- Causes IRQs to be disabled. + __asm volatile("msr cpsr_c, r0"); // Write it back to the CPSR register. + +} + +#define clz(a) \ + ({ unsigned long __value, __arg = (a); \ + asm ("clz\t%0, %1": "=r" (__value): "r" (__arg)); \ + __value; }) + +/** + * This is the global IRQ handler on this platform! + * It is based on the assembler code found in the Broadcom datasheet. + * + **/ +void irqHandler() { + register unsigned long ulMaskedStatus; + register unsigned long irqNumber; + + ulMaskedStatus = pRegs->IRQBasic; + + /* Bits 7 through 0 in IRQBasic represent interrupts 64-71 */ + if (ulMaskedStatus & 0xFF) { + irqNumber=64 + 31; + } + + /* Bit 8 in IRQBasic indicates interrupts in Pending1 (interrupts 31-0) */ + else if(ulMaskedStatus & 0x100) { + ulMaskedStatus = pRegs->Pending1; + irqNumber = 0 + 31; + } + + /* Bit 9 in IRQBasic indicates interrupts in Pending2 (interrupts 63-32) */ + else if(ulMaskedStatus & 0x200) { + ulMaskedStatus = pRegs->Pending2; + irqNumber = 32 + 31; + } + + else { + // No interrupt avaialbe, so just return. + return; + } + + /* Keep only least significant bit, in case multiple interrupts have occured */ + ulMaskedStatus&=-ulMaskedStatus; + /* Some magic to determine number of interrupt to serve */ + irqNumber=irqNumber-clz(ulMaskedStatus); + /* Call interrupt handler */ + g_VectorTable[irqNumber].pfnHandler(irqNumber, g_VectorTable[irqNumber].pParam); +} + + +static void stubHandler(int nIRQ, void *pParam) { + /** + * Actually if we get here, we should probably disable the IRQ, + * otherwise we could lock up this system, as there is nothing to + * ackknowledge the interrupt. + **/ +} + +int InitInterruptController() { + int i; + for(i = 0; i < BCM2835_INTC_TOTAL_IRQ; i++) { + g_VectorTable[i].pfnHandler = stubHandler; + g_VectorTable[i].pParam = (void *) 0; + } + return 0; +} + + + +int RegisterInterrupt(int nIRQ, FN_INTERRUPT_HANDLER pfnHandler, void *pParam) { + if(nIRQ<0 || nIRQ>71) + return -1; + + irqDisable(); + { + g_VectorTable[nIRQ].pfnHandler = pfnHandler; + g_VectorTable[nIRQ].pParam = pParam; + } + irqEnable(); + return 0; +} + +int EnableInterrupt(int nIRQ) { + /* Datasheet says "All other bits are unaffected", and I'm counting on that. */ + unsigned int mask=1<<(nIRQ%32); + + if(nIRQ >=0 && nIRQ <=31) { + pRegs->Enable1 = mask; + } else + if(nIRQ >=32 && nIRQ <=63){ + pRegs->Enable2 = mask; + } else + if(nIRQ >= 64 && nIRQ <= 71) { // Basic IRQ enables + pRegs->EnableBasic = mask; + } else + return -1; + + return 0; +} + +int DisableInterrupt(int nIRQ) { + /* Datasheet says "All other bits are unaffected", and I'm counting on that. */ + unsigned int mask=1<<(nIRQ%32); + + if(nIRQ >=0 && nIRQ <=31) { + pRegs->Disable1 = mask; + } else + if(nIRQ >=32 && nIRQ <=63){ + pRegs->Disable2 = mask; + } else + if(nIRQ >= 64 && nIRQ <= 71) { + pRegs->DisableBasic = mask; + } else + return -1; + + return 0; +} + +int EnableInterrupts() { + irqEnable(); + return 0; +} + +int DisableInterrupts() { + irqDisable(); + return 0; +} -- cgit v1.2.3