Example added for FreeRTOS on Raspberry Pi
This commit is contained in:
parent
ab9ce99647
commit
6dea259ea2
@ -0,0 +1,45 @@
|
||||
#ifndef _BCM2835_INTC_H_
|
||||
#define _BCM2835_INTC_H_
|
||||
|
||||
//#include "bcm2835.h"
|
||||
|
||||
#define BCM2835_INTC_TOTAL_IRQ 64 + 8
|
||||
|
||||
#define BCM2835_BASE_INTC (0x2000B200)
|
||||
#define BCM2835_INTC_IRQ_BASIC (BCM2835_BASE_INTC + 0x00)
|
||||
#define BCM2835_IRQ_PENDING1 (BCM2835_BASE_INTC + 0x04)
|
||||
#define BCM2835_IRQ_PENDING2 (BCM2835_BASE_INTC + 0x08)
|
||||
#define BCM2835_IRQ_FIQ_CTRL (BCM2835_BASE_INTC + 0x0C)
|
||||
#define BCM2835_IRQ_ENABLE1 (BCM2835_BASE_INTC + 0x10)
|
||||
#define BCM2835_IRQ_ENABLE2 (BCM2835_BASE_INTC + 0x14)
|
||||
#define BCM2835_IRQ_ENABLE_BASIC (BCM2835_BASE_INTC + 0x18)
|
||||
#define BCM2835_IRQ_DISABLE1 (BCM2835_BASE_INTC + 0x1C)
|
||||
#define BCM2835_IRQ_DISABLE2 (BCM2835_BASE_INTC + 0x20)
|
||||
#define BCM2835_IRQ_DISABLE_BASIC (BCM2835_BASE_INTC + 0x24)
|
||||
|
||||
|
||||
|
||||
|
||||
#define BCM2835_IRQ_ID_AUX 29
|
||||
#define BCM2835_IRQ_ID_SPI_SLAVE 43
|
||||
#define BCM2835_IRQ_ID_PWA0 45
|
||||
#define BCM2835_IRQ_ID_PWA1 46
|
||||
#define BCM2835_IRQ_ID_SMI 48
|
||||
#define BCM2835_IRQ_ID_GPIO_0 49
|
||||
#define BCM2835_IRQ_ID_GPIO_1 50
|
||||
#define BCM2835_IRQ_ID_GPIO_2 51
|
||||
#define BCM2835_IRQ_ID_GPIO_3 52
|
||||
#define BCM2835_IRQ_ID_I2C 53
|
||||
#define BCM2835_IRQ_ID_SPI 54
|
||||
#define BCM2835_IRQ_ID_PCM 55
|
||||
#define BCM2835_IRQ_ID_UART 57
|
||||
|
||||
|
||||
#define BCM2835_IRQ_ID_TIMER_0 64
|
||||
#define BCM2835_IRQ_ID_MAILBOX_0 65
|
||||
#define BCM2835_IRQ_ID_DOORBELL_0 66
|
||||
#define BCM2835_IRQ_ID_DOORBELL_1 67
|
||||
#define BCM2835_IRQ_ID_GPU0_HALTED 68
|
||||
|
||||
|
||||
#endif
|
134
boards/base/RaspberryPi/example-FreeRTOS/Drivers/gpio.c
Normal file
134
boards/base/RaspberryPi/example-FreeRTOS/Drivers/gpio.c
Normal file
@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Quick and very Dirty GPIO API.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned long GPFSEL[6]; ///< Function selection registers.
|
||||
unsigned long Reserved_1;
|
||||
unsigned long GPSET[2];
|
||||
unsigned long Reserved_2;
|
||||
unsigned long GPCLR[2];
|
||||
unsigned long Reserved_3;
|
||||
unsigned long GPLEV[2];
|
||||
unsigned long Reserved_4;
|
||||
unsigned long GPEDS[2];
|
||||
unsigned long Reserved_5;
|
||||
unsigned long GPREN[2];
|
||||
unsigned long Reserved_6;
|
||||
unsigned long GPFEN[2];
|
||||
unsigned long Reserved_7;
|
||||
unsigned long GPHEN[2];
|
||||
unsigned long Reserved_8;
|
||||
unsigned long GPLEN[2];
|
||||
unsigned long Reserved_9;
|
||||
unsigned long GPAREN[2];
|
||||
unsigned long Reserved_A;
|
||||
unsigned long GPAFEN[2];
|
||||
unsigned long Reserved_B;
|
||||
unsigned long GPPUD[1];
|
||||
unsigned long GPPUDCLK[2];
|
||||
//Ignoring the reserved and test bytes
|
||||
} BCM2835_GPIO_REGS;
|
||||
|
||||
volatile BCM2835_GPIO_REGS * const pRegs = (BCM2835_GPIO_REGS *) (0x20200000);
|
||||
|
||||
|
||||
void SetGpioFunction(unsigned int pinNum, unsigned int funcNum) {
|
||||
|
||||
int offset = pinNum / 10;
|
||||
|
||||
unsigned long val = pRegs->GPFSEL[offset]; // Read in the original register value.
|
||||
|
||||
int item = pinNum % 10;
|
||||
val &= ~(0x7 << (item * 3));
|
||||
val |= ((funcNum & 0x7) << (item * 3));
|
||||
pRegs->GPFSEL[offset] = val;
|
||||
}
|
||||
|
||||
void SetGpioDirection(unsigned int pinNum, enum GPIO_DIR dir) {
|
||||
SetGpioFunction(pinNum,dir);
|
||||
}
|
||||
|
||||
void SetGpio(unsigned int pinNum, unsigned int pinVal) {
|
||||
unsigned long offset=pinNum/32;
|
||||
unsigned long mask=(1<<(pinNum%32));
|
||||
|
||||
if(pinVal) {
|
||||
pRegs->GPSET[offset]|=mask;
|
||||
} else {
|
||||
pRegs->GPCLR[offset]|=mask;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadGpio(unsigned int pinNum) {
|
||||
return ((pRegs->GPLEV[pinNum/32])>>(pinNum%32))&1;
|
||||
}
|
||||
|
||||
void EnableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type)
|
||||
{
|
||||
unsigned long mask=(1<<pinNum);
|
||||
unsigned long offset=pinNum/32;
|
||||
|
||||
switch(type) {
|
||||
case DETECT_RISING:
|
||||
pRegs->GPREN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_FALLING:
|
||||
pRegs->GPFEN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_HIGH:
|
||||
pRegs->GPHEN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_LOW:
|
||||
pRegs->GPLEN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_RISING_ASYNC:
|
||||
pRegs->GPAREN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_FALLING_ASYNC:
|
||||
pRegs->GPAFEN[offset]|=mask;
|
||||
break;
|
||||
case DETECT_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DisableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type)
|
||||
{
|
||||
unsigned long mask=~(1<<(pinNum%32));
|
||||
unsigned long offset=pinNum/32;
|
||||
|
||||
switch(type) {
|
||||
case DETECT_RISING:
|
||||
pRegs->GPREN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_FALLING:
|
||||
pRegs->GPFEN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_HIGH:
|
||||
pRegs->GPHEN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_LOW:
|
||||
pRegs->GPLEN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_RISING_ASYNC:
|
||||
pRegs->GPAREN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_FALLING_ASYNC:
|
||||
pRegs->GPAFEN[offset]&=mask;
|
||||
break;
|
||||
case DETECT_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearGpioInterrupt(unsigned int pinNum)
|
||||
{
|
||||
unsigned long mask=(1<<(pinNum%32));
|
||||
unsigned long offset=pinNum/32;
|
||||
|
||||
pRegs->GPEDS[offset]=mask;
|
||||
}
|
48
boards/base/RaspberryPi/example-FreeRTOS/Drivers/gpio.h
Normal file
48
boards/base/RaspberryPi/example-FreeRTOS/Drivers/gpio.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
/* GPIO event detect types */
|
||||
enum DETECT_TYPE {
|
||||
DETECT_NONE,
|
||||
DETECT_RISING,
|
||||
DETECT_FALLING,
|
||||
DETECT_HIGH,
|
||||
DETECT_LOW,
|
||||
DETECT_RISING_ASYNC,
|
||||
DETECT_FALLING_ASYNC
|
||||
};
|
||||
|
||||
/* GPIO pull up or down states */
|
||||
enum PULL_STATE {
|
||||
PULL_DISABLE,
|
||||
PULL_UP,
|
||||
PULL_DOWN,
|
||||
PULL_RESERVED
|
||||
};
|
||||
|
||||
/* Pin data direction */
|
||||
enum GPIO_DIR {
|
||||
GPIO_IN,
|
||||
GPIO_OUT
|
||||
};
|
||||
|
||||
/* GPIO pin setup */
|
||||
void SetGpioFunction (unsigned int pinNum, unsigned int funcNum);
|
||||
/* A simple wrapper around SetGpioFunction */
|
||||
void SetGpioDirection (unsigned int pinNum, enum GPIO_DIR dir);
|
||||
|
||||
/* Set GPIO output level */
|
||||
void SetGpio (unsigned int pinNum, unsigned int pinVal);
|
||||
|
||||
/* Read GPIO pin level */
|
||||
int ReadGpio (unsigned int pinNum);
|
||||
|
||||
/* GPIO pull up/down resistor control function (NOT YET IMPLEMENTED) */
|
||||
int PudGpio (unsigned int pinNum, enum PULL_STATE state);
|
||||
|
||||
/* Interrupt related functions */
|
||||
void EnableGpioDetect (unsigned int pinNum, enum DETECT_TYPE type);
|
||||
void DisableGpioDetect (unsigned int pinNum, enum DETECT_TYPE type);
|
||||
void ClearGpioInterrupt (unsigned int pinNum);
|
||||
|
||||
#endif
|
166
boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c
Normal file
166
boards/base/RaspberryPi/example-FreeRTOS/Drivers/interrupts.c
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Integrated Interrupt Controller for RaspberryPi.
|
||||
* @author James Walmsley <james@fullfat-fs.co.uk>
|
||||
**/
|
||||
|
||||
#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;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Tiny Interrupt Manager
|
||||
*
|
||||
* @author James Walmsley <james@fullfat-fs.co.uk>
|
||||
* This code is licensed under the GNU GPLv3 license.
|
||||
**/
|
||||
|
||||
#ifndef _INTERRUPTS_H_
|
||||
#define _INTERRUPTS_H_
|
||||
|
||||
typedef void (*FN_INTERRUPT_HANDLER)(int nIRQ, void *pParam);
|
||||
|
||||
typedef struct {
|
||||
FN_INTERRUPT_HANDLER pfnHandler; ///< Function that handles this IRQn
|
||||
void *pParam; ///< A special parameter that the use can pass to the IRQ.
|
||||
} INTERRUPT_VECTOR;
|
||||
|
||||
int InitInterruptController ();
|
||||
int RegisterInterrupt (int nIRQ, FN_INTERRUPT_HANDLER pfnHandler, void *pParam);
|
||||
int EnableInterrupt (int nIRQ);
|
||||
int DisableInterrupt (int nIRQ);
|
||||
int EnableInterrupts ();
|
||||
int DisableInterrupts ();
|
||||
|
||||
#endif
|
24
boards/base/RaspberryPi/example-FreeRTOS/Drivers/mmio.h
Normal file
24
boards/base/RaspberryPi/example-FreeRTOS/Drivers/mmio.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* mmio.h - access to MMIO registers */
|
||||
|
||||
#ifndef MMIO_H
|
||||
#define MMIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// write to MMIO register
|
||||
static inline void mmio_write(uint32_t reg, uint32_t data) {
|
||||
uint32_t *ptr = (uint32_t*)reg;
|
||||
asm volatile("str %[data], [%[reg]]"
|
||||
: : [reg]"r"(ptr), [data]"r"(data));
|
||||
}
|
||||
|
||||
// read from MMIO register
|
||||
static inline uint32_t mmio_read(uint32_t reg) {
|
||||
uint32_t *ptr = (uint32_t*)reg;
|
||||
uint32_t data;
|
||||
asm volatile("ldr %[data], [%[reg]]"
|
||||
: [data]"=r"(data) : [reg]"r"(ptr));
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif // #ifndef MMIO_H
|
125
boards/base/RaspberryPi/example-FreeRTOS/Drivers/uart.c
Normal file
125
boards/base/RaspberryPi/example-FreeRTOS/Drivers/uart.c
Normal file
@ -0,0 +1,125 @@
|
||||
/* uart.c - UART initialization & communication */
|
||||
/* Reference material:
|
||||
* http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
||||
* Chapter 13: UART
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <mmio.h>
|
||||
#include <uart.h>
|
||||
|
||||
enum {
|
||||
// The GPIO registers base address.
|
||||
GPIO_BASE = 0x20200000,
|
||||
|
||||
// The offsets for reach register.
|
||||
|
||||
// Controls actuation of pull up/down to ALL GPIO pins.
|
||||
GPPUD = (GPIO_BASE + 0x94),
|
||||
|
||||
// Controls actuation of pull up/down for specific GPIO pin.
|
||||
GPPUDCLK0 = (GPIO_BASE + 0x98),
|
||||
|
||||
// The base address for UART.
|
||||
UART0_BASE = 0x20201000,
|
||||
|
||||
// The offsets for reach register for the UART.
|
||||
UART0_DR = (UART0_BASE + 0x00),
|
||||
UART0_RSRECR = (UART0_BASE + 0x04),
|
||||
UART0_FR = (UART0_BASE + 0x18),
|
||||
UART0_ILPR = (UART0_BASE + 0x20),
|
||||
UART0_IBRD = (UART0_BASE + 0x24),
|
||||
UART0_FBRD = (UART0_BASE + 0x28),
|
||||
UART0_LCRH = (UART0_BASE + 0x2C),
|
||||
UART0_CR = (UART0_BASE + 0x30),
|
||||
UART0_IFLS = (UART0_BASE + 0x34),
|
||||
UART0_IMSC = (UART0_BASE + 0x38),
|
||||
UART0_RIS = (UART0_BASE + 0x3C),
|
||||
UART0_MIS = (UART0_BASE + 0x40),
|
||||
UART0_ICR = (UART0_BASE + 0x44),
|
||||
UART0_DMACR = (UART0_BASE + 0x48),
|
||||
UART0_ITCR = (UART0_BASE + 0x80),
|
||||
UART0_ITIP = (UART0_BASE + 0x84),
|
||||
UART0_ITOP = (UART0_BASE + 0x88),
|
||||
UART0_TDR = (UART0_BASE + 0x8C),
|
||||
};
|
||||
|
||||
/*
|
||||
* delay function
|
||||
* int32_t delay: number of cycles to delay
|
||||
*
|
||||
* This just loops <delay> times in a way that the compiler
|
||||
* wont optimize away.
|
||||
*/
|
||||
static void delay(int32_t count) {
|
||||
asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n"
|
||||
: : [count]"r"(count) : "cc");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize UART0.
|
||||
*/
|
||||
void uart_init() {
|
||||
// Disable UART0.
|
||||
mmio_write(UART0_CR, 0x00000000);
|
||||
// Setup the GPIO pin 14 && 15.
|
||||
|
||||
// Disable pull up/down for all GPIO pins & delay for 150 cycles.
|
||||
mmio_write(GPPUD, 0x00000000);
|
||||
delay(150);
|
||||
|
||||
// Disable pull up/down for pin 14,15 & delay for 150 cycles.
|
||||
mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15));
|
||||
delay(150);
|
||||
|
||||
// Write 0 to GPPUDCLK0 to make it take effect.
|
||||
mmio_write(GPPUDCLK0, 0x00000000);
|
||||
|
||||
// Clear pending interrupts.
|
||||
mmio_write(UART0_ICR, 0x7FF);
|
||||
|
||||
// Set integer & fractional part of baud rate.
|
||||
// Divider = UART_CLOCK/(16 * Baud)
|
||||
// Fraction part register = (Fractional part * 64) + 0.5
|
||||
// UART_CLOCK = 3000000; Baud = 115200.
|
||||
|
||||
// Divider = 3000000/(16 * 115200) = 1.627 = ~1.
|
||||
// Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
|
||||
mmio_write(UART0_IBRD, 1);
|
||||
mmio_write(UART0_FBRD, 40);
|
||||
|
||||
// Enable FIFO & 8 bit data transmissio (1 stop bit, no parity).
|
||||
mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
|
||||
|
||||
// Mask all interrupts.
|
||||
mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) |
|
||||
(1 << 6) | (1 << 7) | (1 << 8) |
|
||||
(1 << 9) | (1 << 10));
|
||||
|
||||
// Enable UART0, receive & transfer part of UART.
|
||||
mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit a byte via UART0.
|
||||
* uint8_t Byte: byte to send.
|
||||
*/
|
||||
void uart_putc(uint8_t byte) {
|
||||
// wait for UART to become ready to transmit
|
||||
while (1) {
|
||||
if (!(mmio_read(UART0_FR) & (1 << 5))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mmio_write(UART0_DR, byte);
|
||||
}
|
||||
|
||||
/*
|
||||
* print a string to the UART one character at a time
|
||||
* const char *str: 0-terminated string
|
||||
*/
|
||||
void uart_puts(const char *str) {
|
||||
while (*str) {
|
||||
uart_putc(*str++);
|
||||
}
|
||||
}
|
25
boards/base/RaspberryPi/example-FreeRTOS/Drivers/uart.h
Normal file
25
boards/base/RaspberryPi/example-FreeRTOS/Drivers/uart.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* uart.h - UART initialization & communication */
|
||||
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Initialize UART0.
|
||||
*/
|
||||
void uart_init();
|
||||
|
||||
/*
|
||||
* Transmit a byte via UART0.
|
||||
* uint8_t Byte: byte to send.
|
||||
*/
|
||||
void uart_putc(uint8_t byte);
|
||||
|
||||
/*
|
||||
* print a string to the UART one character at a time
|
||||
* const char *str: 0-terminated string
|
||||
*/
|
||||
void uart_puts(const char *str);
|
||||
|
||||
#endif // #ifndef UART_H
|
139
boards/base/RaspberryPi/example-FreeRTOS/FreeRTOSConfig.h
Normal file
139
boards/base/RaspberryPi/example-FreeRTOS/FreeRTOSConfig.h
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to distribute
|
||||
>>! a combined work that includes FreeRTOS without being obliged to provide
|
||||
>>! the source code for proprietary components outside of the FreeRTOS
|
||||
>>! kernel.
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 24000000 )
|
||||
#define configPERIPHERAL_CLOCK_HZ ( 40000000UL )
|
||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
|
||||
#define configISR_STACK_SIZE ( 250 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 4096 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 3
|
||||
#define configQUEUE_REGISTRY_SIZE 0
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
#define configUSE_APPLICATION_TASK_TAG 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
|
||||
|
||||
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
|
||||
(lowest) to 0 (1?) (highest). */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
|
||||
|
||||
|
||||
/* This is the value being used as per the ST library which permits 16
|
||||
priority values, 0 to 15. This must correspond to the
|
||||
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
|
||||
NVIC value of 255. */
|
||||
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
73
boards/base/RaspberryPi/example-FreeRTOS/Makefile
Normal file
73
boards/base/RaspberryPi/example-FreeRTOS/Makefile
Normal file
@ -0,0 +1,73 @@
|
||||
# build environment
|
||||
PREFIX ?= /your compiler path/gcc-arm-none-eabi-4_8-2014q1
|
||||
ARCH ?= $(PREFIX)/bin/arm-none-eabi
|
||||
|
||||
CC = ${ARCH}-gcc
|
||||
CPP = ${ARCH}-g++
|
||||
AS = ${ARCH}-as
|
||||
LD = ${ARCH}-ld
|
||||
AR = ${ARCH}-ar
|
||||
OBJCOPY = ${ARCH}-objcopy
|
||||
|
||||
PLATFORM = raspi
|
||||
LINKER_SCRIPT = raspberrypi.ld
|
||||
|
||||
CFLAGS = -march=armv6z -g -Wall -Wextra
|
||||
ASFLAGS = -g
|
||||
|
||||
CFLAGS_FOR_TARGET = #-mcpu=arm1176jzf-s
|
||||
ASFLAGS_FOR_TARGET = #-mcpu=arm1176jzf-s
|
||||
LDFLAGS = #--error-unresolved-symbols
|
||||
|
||||
GFXLIB := ../uGFX
|
||||
include $(GFXLIB)/gfx.mk
|
||||
include $(GFXLIB)/drivers/gdisp/framebuffer/driver.mk
|
||||
|
||||
OSLIB := ../FreeRTOS
|
||||
MODULES := $(OSLIB)/Source/portable/GCC/RaspberryPi
|
||||
MODULES += $(OSLIB)/Source/portable/MemMang
|
||||
MODULES += $(OSLIB)/Source
|
||||
MODULES += Drivers
|
||||
|
||||
SRC_DIR := $(MODULES)
|
||||
INC_DIR := $(addsuffix /include,$(SRC_DIR))
|
||||
BUILD_DIR := $(addsuffix /build,$(SRC_DIR))
|
||||
|
||||
INCLUDEDIRS := $(OSLIB)/Source/portable/GCC/RaspberryPi
|
||||
INCLUDEDIRS += $(OSLIB)/Source/include
|
||||
INCLUDEDIRS += Drivers
|
||||
INCLUDEDIRS += $(GFXINC)
|
||||
|
||||
INCLUDES := $(addprefix -I,$(INCLUDEDIRS))
|
||||
|
||||
ASRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.s))
|
||||
AOBJ := $(ASRC:.s=.o)
|
||||
CSRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
|
||||
CSRC += $(GFXSRC)
|
||||
COBJ := $(CSRC:.c=.o)
|
||||
|
||||
vpath %.c $(SRC_DIR)
|
||||
vpath %.cpp $(SRC_DIR)
|
||||
vpath %.s $(SRC_DIR)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) $(CFLAGS) -c -o $*.o $<
|
||||
|
||||
%.o: %.s
|
||||
$(AS) $(ASFLAGS_FOR_TARGET) $(INCLUDES) $(ASFLAGS) -o $*.o $<
|
||||
|
||||
OBJ = $(AOBJ) $(COBJ)
|
||||
|
||||
bin/kernel.img: bin/kernel.elf
|
||||
${OBJCOPY} -O binary $< $@
|
||||
|
||||
bin/kernel.elf: LDFLAGS += -L "$(PREFIX)/lib/gcc/arm-none-eabi/4.8.3" -lgcc
|
||||
bin/kernel.elf: LDFLAGS += -L "$(PREFIX)/arm-none-eabi/lib" -lc
|
||||
bin/kernel.elf: $(OBJ)
|
||||
${LD} $(OBJ) -Map bin/kernel.map -o $@ -T $(LINKER_SCRIPT) ${LDFLAGS}
|
||||
|
||||
clean:
|
||||
rm -f bin/*.elf bin/*.img bin/*.map $(OBJ)
|
||||
|
||||
|
||||
|
82
boards/base/RaspberryPi/example-FreeRTOS/main.c
Normal file
82
boards/base/RaspberryPi/example-FreeRTOS/main.c
Normal file
@ -0,0 +1,82 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#include "Drivers/interrupts.h"
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
static void displayTask(void *pvParameters) {
|
||||
coord_t width, height;
|
||||
// Get the screen size
|
||||
width = gdispGetWidth();
|
||||
height = gdispGetHeight();
|
||||
|
||||
// Code Here
|
||||
gdispDrawBox(10, 10, width/2, height/2, Yellow);
|
||||
gdispFillArea(width/2, height/2, width/2-10, height/2-10, Blue);
|
||||
gdispDrawLine(5, 30, width-50, height-40, Red);
|
||||
|
||||
while(1)
|
||||
{
|
||||
vTaskDelay(1000);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the systems main entry, some call it a boot thread.
|
||||
*
|
||||
* -- Absolutely nothing wrong with this being called main(), just it doesn't have
|
||||
* -- the same prototype as you'd see in a linux program.
|
||||
**/
|
||||
int main(void) {
|
||||
|
||||
DisableInterrupts();
|
||||
InitInterruptController();
|
||||
|
||||
// Initialize and clear the display
|
||||
gfxInit();
|
||||
|
||||
xTaskCreate(displayTask,
|
||||
(portCHAR *)"Display Task",
|
||||
128,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
/*
|
||||
* We should never get here, but just in case something goes wrong,
|
||||
* we'll place the CPU into a safe loop.
|
||||
*/
|
||||
while(1) {
|
||||
;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
||||
{
|
||||
( void ) pcTaskName;
|
||||
( void ) pxTask;
|
||||
|
||||
/* Run time task stack overflow checking is performed if
|
||||
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook function is
|
||||
called if a task stack overflow is detected. Note the system/interrupt
|
||||
stack is not checked. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationTickHook( void )
|
||||
{
|
||||
/* This function will be called by each tick interrupt if
|
||||
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
|
||||
added here, but the tick hook is called from an interrupt context, so
|
||||
code must not attempt to block, and only the interrupt safe FreeRTOS API
|
||||
functions can be used (those that end in FromISR()). */
|
||||
}
|
70
boards/base/RaspberryPi/example-FreeRTOS/raspberrypi.ld
Normal file
70
boards/base/RaspberryPi/example-FreeRTOS/raspberrypi.ld
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* BlueThunder Linker Script for the raspberry Pi!
|
||||
*
|
||||
*
|
||||
*
|
||||
**/
|
||||
MEMORY
|
||||
{
|
||||
RESERVED (r) : ORIGIN = 0x00000000, LENGTH = 32K
|
||||
INIT_RAM (rwx) : ORIGIN = 0x00008000, LENGTH = 32K
|
||||
RAM (rwx) : ORIGIN = 0x00010000, LENGTH = 128M
|
||||
}
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
/*
|
||||
* Our init section allows us to place the bootstrap code at address 0x8000
|
||||
*
|
||||
* This is where the Graphics processor forces the ARM to start execution.
|
||||
* However the interrupt vector code remains at 0x0000, and so we must copy the correct
|
||||
* branch instructions to 0x0000 - 0x001C in order to get the processor to handle interrupts.
|
||||
*
|
||||
*/
|
||||
.init : {
|
||||
KEEP(*(.init))
|
||||
} > INIT_RAM = 0
|
||||
|
||||
.module_entries : {
|
||||
__module_entries_start = .;
|
||||
KEEP(*(.module_entries))
|
||||
KEEP(*(.module_entries.*))
|
||||
__module_entries_end = .;
|
||||
__module_entries_size = SIZEOF(.module_entries);
|
||||
} > INIT_RAM
|
||||
|
||||
|
||||
/**
|
||||
* This is the main code section, it is essentially of unlimited size. (128Mb).
|
||||
*
|
||||
**/
|
||||
.text : {
|
||||
*(.text)
|
||||
} > RAM
|
||||
|
||||
/*
|
||||
* Next we put the data.
|
||||
*/
|
||||
.data : {
|
||||
*(.data)
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
__bss_end = .;
|
||||
} > RAM
|
||||
|
||||
/**
|
||||
* Place HEAP here???
|
||||
**/
|
||||
|
||||
/**
|
||||
* Stack starts at the top of the RAM, and moves down!
|
||||
**/
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
}
|
||||
|
102
boards/base/RaspberryPi/example-FreeRTOS/startup.s
Normal file
102
boards/base/RaspberryPi/example-FreeRTOS/startup.s
Normal file
@ -0,0 +1,102 @@
|
||||
.extern system_init
|
||||
.extern __bss_start
|
||||
.extern __bss_end
|
||||
.extern vFreeRTOS_ISR
|
||||
.extern vPortYieldProcessor
|
||||
.extern DisableInterrupts
|
||||
.extern main
|
||||
.section .init
|
||||
.globl _start
|
||||
;;
|
||||
_start:
|
||||
;@ All the following instruction should be read as:
|
||||
;@ Load the address at symbol into the program counter.
|
||||
|
||||
ldr pc,reset_handler ;@ Processor Reset handler -- we will have to force this on the raspi!
|
||||
;@ Because this is the first instruction executed, of cause it causes an immediate branch into reset!
|
||||
|
||||
ldr pc,undefined_handler ;@ Undefined instruction handler -- processors that don't have thumb can emulate thumb!
|
||||
ldr pc,swi_handler ;@ Software interrupt / TRAP (SVC) -- system SVC handler for switching to kernel mode.
|
||||
ldr pc,prefetch_handler ;@ Prefetch/abort handler.
|
||||
ldr pc,data_handler ;@ Data abort handler/
|
||||
ldr pc,unused_handler ;@ -- Historical from 26-bit addressing ARMs -- was invalid address handler.
|
||||
ldr pc,irq_handler ;@ IRQ handler
|
||||
ldr pc,fiq_handler ;@ Fast interrupt handler.
|
||||
|
||||
;@ Here we create an exception address table! This means that reset/hang/irq can be absolute addresses
|
||||
reset_handler: .word reset
|
||||
undefined_handler: .word undefined_instruction
|
||||
swi_handler: .word vPortYieldProcessor
|
||||
prefetch_handler: .word prefetch_abort
|
||||
data_handler: .word data_abort
|
||||
unused_handler: .word unused
|
||||
irq_handler: .word vFreeRTOS_ISR
|
||||
fiq_handler: .word fiq
|
||||
|
||||
reset:
|
||||
;@ In the reset handler, we need to copy our interrupt vector table to 0x0000, its currently at 0x8000
|
||||
|
||||
mov r0,#0x8000 ;@ Store the source pointer
|
||||
mov r1,#0x0000 ;@ Store the destination pointer.
|
||||
|
||||
;@ Here we copy the branching instructions
|
||||
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9} ;@ Load multiple values from indexed address. ; Auto-increment R0
|
||||
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9} ;@ Store multiple values from the indexed address. ; Auto-increment R1
|
||||
|
||||
;@ So the branches get the correct address we also need to copy our vector table!
|
||||
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9} ;@ Load from 4*n of regs (8) as R0 is now incremented.
|
||||
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9} ;@ Store this extra set of data.
|
||||
|
||||
|
||||
;@ Set up the various STACK pointers for different CPU modes
|
||||
;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
|
||||
mov r0,#0xD2
|
||||
msr cpsr_c,r0
|
||||
mov sp,#0x8000
|
||||
|
||||
;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
|
||||
mov r0,#0xD1
|
||||
msr cpsr_c,r0
|
||||
mov sp,#0x4000
|
||||
|
||||
;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
|
||||
mov r0,#0xD3
|
||||
msr cpsr_c,r0
|
||||
mov sp,#0x8000000
|
||||
|
||||
ldr r0, =__bss_start
|
||||
ldr r1, =__bss_end
|
||||
|
||||
mov r2, #0
|
||||
|
||||
zero_loop:
|
||||
cmp r0,r1
|
||||
it lt
|
||||
strlt r2,[r0], #4
|
||||
blt zero_loop
|
||||
|
||||
bl DisableInterrupts
|
||||
|
||||
|
||||
;@ mov sp,#0x1000000
|
||||
b main ;@ We're ready?? Lets start main execution!
|
||||
.section .text
|
||||
|
||||
undefined_instruction:
|
||||
b undefined_instruction
|
||||
|
||||
prefetch_abort:
|
||||
b prefetch_abort
|
||||
|
||||
data_abort:
|
||||
b data_abort
|
||||
|
||||
unused:
|
||||
b unused
|
||||
|
||||
fiq:
|
||||
b fiq
|
||||
|
||||
hang:
|
||||
b hang
|
||||
|
Loading…
Reference in New Issue
Block a user