Example added for FreeRTOS on Raspberry Pi
This commit is contained in:
parent
ab9ce99647
commit
6dea259ea2
13 changed files with 1058 additions and 0 deletions
|
@ -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…
Add table
Reference in a new issue