Example added for FreeRTOS on Raspberry Pi

This commit is contained in:
inmarket 2014-07-09 18:47:59 +10:00
parent ab9ce99647
commit 6dea259ea2
13 changed files with 1058 additions and 0 deletions

View File

@ -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

View 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;
}

View 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

View 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;
}

View File

@ -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

View 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

View 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++);
}
}

View 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

View 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 */

View 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)

View 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()). */
}

View 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);
}

View 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