cleanup root and unfuck CMakeLists.txt
This commit is contained in:
1 parent
ad4461fde6
commit
8b4c71951e
37 files changed
+25
-17
No files matched your search
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
arm-016-util.c
|
||||
*/
|
||||
#include "util.h"
|
||||
|
||||
void setColor(volatile unsigned char* fb, colour_t pixel, long x, long y, long pitch)
|
||||
{
|
||||
int pixel_offset = ( x * ( SCREEN_DEPTH >> 3 ) ) + ( y * pitch );
|
||||
|
||||
int r = (int)( pixel.r * 0xFF ) & 0xFF;
|
||||
int g = (int)( pixel.g * 0xFF ) & 0xFF;
|
||||
int b = (int)( pixel.b * 0xFF ) & 0xFF;
|
||||
int a = (int)( pixel.a * 0xFF ) & 0xFF;
|
||||
|
||||
if( SCREEN_DEPTH == 32 )
|
||||
{
|
||||
/* Four bytes to write */
|
||||
fb[ pixel_offset++ ] = r;
|
||||
fb[ pixel_offset++ ] = g;
|
||||
fb[ pixel_offset++ ] = b;
|
||||
fb[ pixel_offset++ ] = a;
|
||||
}
|
||||
else if( SCREEN_DEPTH == 24 )
|
||||
{
|
||||
/* Three bytes to write */
|
||||
fb[ pixel_offset++ ] = r;
|
||||
fb[ pixel_offset++ ] = g;
|
||||
fb[ pixel_offset++ ] = b;
|
||||
}
|
||||
else if( SCREEN_DEPTH == 16 )
|
||||
{
|
||||
/* Two bytes to write */
|
||||
/* Bit pack RGB565 into the 16-bit pixel offset */
|
||||
*(unsigned short*)&fb[pixel_offset] = ( (r >> 3) << 11 ) | ( ( g >> 2 ) << 5 ) | ( b >> 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Palette mode. TODO: Work out a colour scheme for
|
||||
packing rgb into an 8-bit palette! */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
arm-016-util.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef arm_016_util
|
||||
#define arm_016_util
|
||||
|
||||
#define SCREEN_WIDTH 1920
|
||||
#define SCREEN_HEIGHT 1080
|
||||
#define SCREEN_DEPTH 24 /* 16 or 32-bit */
|
||||
|
||||
#define COLOUR_DELTA 0.05 /* Float from 0 to 1 incremented by this amount */
|
||||
|
||||
typedef struct {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
} colour_t;
|
||||
|
||||
|
||||
#define dickbuttHeight 352
|
||||
#define dickbuttWidth 624
|
||||
#define dickbuttBytes 658945
|
||||
|
||||
extern const int dickbutt[dickbuttBytes];
|
||||
|
||||
|
||||
extern void setColor(volatile unsigned char* fb, colour_t pixel, long x, long y, long pitch);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "armtimer.h"
|
||||
|
||||
static rpi_arm_timer_t* rpiArmTimer = (rpi_arm_timer_t*)RPI_ARMTIMER_BASE;
|
||||
|
||||
rpi_arm_timer_t* RPI_GetArmTimer(void)
|
||||
{
|
||||
return rpiArmTimer;
|
||||
}
|
||||
|
||||
void RPI_ArmTimerInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013-2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_ARMTIMER_H
|
||||
#define RPI_ARMTIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/** @brief See the documentation for the ARM side timer (Section 14 of the
|
||||
BCM2835 Peripherals PDF) */
|
||||
#define RPI_ARMTIMER_BASE ( PERIPHERAL_BASE + 0xB400 )
|
||||
|
||||
/** @brief 0 : 16-bit counters - 1 : 23-bit counter */
|
||||
#define RPI_ARMTIMER_CTRL_23BIT ( 1 << 1 )
|
||||
|
||||
#define RPI_ARMTIMER_CTRL_PRESCALE_1 ( 0 << 2 )
|
||||
#define RPI_ARMTIMER_CTRL_PRESCALE_16 ( 1 << 2 )
|
||||
#define RPI_ARMTIMER_CTRL_PRESCALE_256 ( 2 << 2 )
|
||||
|
||||
/** @brief 0 : Timer interrupt disabled - 1 : Timer interrupt enabled */
|
||||
#define RPI_ARMTIMER_CTRL_INT_ENABLE ( 1 << 5 )
|
||||
#define RPI_ARMTIMER_CTRL_INT_DISABLE ( 0 << 5 )
|
||||
|
||||
/** @brief 0 : Timer disabled - 1 : Timer enabled */
|
||||
#define RPI_ARMTIMER_CTRL_ENABLE ( 1 << 7 )
|
||||
#define RPI_ARMTIMER_CTRL_DISABLE ( 0 << 7 )
|
||||
|
||||
|
||||
/** @brief Section 14.2 of the BCM2835 Peripherals documentation details
|
||||
the register layout for the ARM side timer */
|
||||
typedef struct {
|
||||
|
||||
/** The timer load register sets the time for the timer to count down.
|
||||
This value is loaded into the timer value register after the load
|
||||
register has been written or if the timer-value register has counted
|
||||
down to 0. */
|
||||
volatile uint32_t Load;
|
||||
|
||||
/** This register holds the current timer value and is counted down when
|
||||
the counter is running. It is counted down each timer clock until the
|
||||
value 0 is reached. Then the value register is re-loaded from the
|
||||
timer load register and the interrupt pending bit is set. The timer
|
||||
count down speed is set by the timer pre-divide register. */
|
||||
volatile uint32_t Value;
|
||||
|
||||
/** The standard SP804 timer control register consist of 8 bits but in the
|
||||
BCM implementation there are more control bits for the extra features.
|
||||
Control bits 0-7 are identical to the SP804 bits, albeit some
|
||||
functionality of the SP804 is not implemented. All new control bits
|
||||
start from bit 8 upwards. */
|
||||
volatile uint32_t Control;
|
||||
|
||||
/** The timer IRQ clear register is write only. When writing this register
|
||||
the interrupt-pending bit is cleared. When reading this register it
|
||||
returns 0x544D5241 which is the ASCII reversed value for "ARMT". */
|
||||
volatile uint32_t IRQClear;
|
||||
|
||||
/** The raw IRQ register is a read-only register. It shows the status of
|
||||
the interrupt pending bit. 0 : The interrupt pending bits is clear.
|
||||
1 : The interrupt pending bit is set.
|
||||
|
||||
The interrupt pending bits is set each time the value register is
|
||||
counted down to zero. The interrupt pending bit can not by itself
|
||||
generates interrupts. Interrupts can only be generated if the
|
||||
interrupt enable bit is set. */
|
||||
volatile uint32_t RAWIRQ;
|
||||
|
||||
/** The masked IRQ register is a read-only register. It shows the status
|
||||
of the interrupt signal. It is simply a logical AND of the interrupt
|
||||
pending bit and the interrupt enable bit. 0 : Interrupt line not
|
||||
asserted. 1 :Interrupt line is asserted, (the interrupt pending and
|
||||
the interrupt enable bit are set.) */
|
||||
volatile uint32_t MaskedIRQ;
|
||||
|
||||
/** This register is a copy of the timer load register. The difference is
|
||||
that a write to this register does not trigger an immediate reload of
|
||||
the timer value register. Instead the timer load register value is
|
||||
only accessed if the value register has finished counting down to
|
||||
zero. */
|
||||
volatile uint32_t Reload;
|
||||
|
||||
/** The Pre-divider register is not present in the SP804. The pre-divider
|
||||
register is 10 bits wide and can be written or read from. This
|
||||
register has been added as the SP804 expects a 1MHz clock which we do
|
||||
not have. Instead the pre-divider takes the APB clock and divides it
|
||||
down according to:
|
||||
|
||||
timer_clock = apb_clock/(pre_divider+1)
|
||||
|
||||
The reset value of this register is 0x7D so gives a divide by 126. */
|
||||
volatile uint32_t PreDivider;
|
||||
|
||||
/** The free running counter is not present in the SP804. The free running
|
||||
counter is a 32 bits wide read only register. The register is enabled
|
||||
by setting bit 9 of the Timer control register. The free running
|
||||
counter is incremented immediately after it is enabled. The timer can
|
||||
not be reset but when enabled, will always increment and roll-over.
|
||||
|
||||
The free running counter is also running from the APB clock and has
|
||||
its own clock pre-divider controlled by bits 16-23 of the timer
|
||||
control register.
|
||||
|
||||
This register will be halted too if bit 8 of the control register is
|
||||
set and the ARM is in Debug Halt mode. */
|
||||
volatile uint32_t FreeRunningCounter;
|
||||
|
||||
} rpi_arm_timer_t;
|
||||
|
||||
|
||||
extern rpi_arm_timer_t* RPI_GetArmTimer(void);
|
||||
extern void RPI_ArmTimerInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
#include "aux.h"
|
||||
#include "base.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static aux_t* auxillary = (aux_t*)AUX_BASE;
|
||||
|
||||
|
||||
aux_t* RPI_GetAux( void )
|
||||
{
|
||||
return auxillary;
|
||||
}
|
||||
|
||||
/* Define the system clock frequency in MHz for the baud rate calculation.
|
||||
This is clearly defined on the BCM2835 datasheet errata page:
|
||||
http://elinux.org/BCM2835_datasheet_errata */
|
||||
#define SYS_FREQ 250000000
|
||||
|
||||
void RPI_AuxMiniUartInit( int baud, int bits )
|
||||
{
|
||||
volatile int i;
|
||||
|
||||
/* As this is a mini uart the configuration is complete! Now just
|
||||
enable the uart. Note from the documentation in section 2.1.1 of
|
||||
the ARM peripherals manual:
|
||||
|
||||
If the enable bits are clear you will have no access to a
|
||||
peripheral. You can not even read or write the registers */
|
||||
auxillary->ENABLES = AUX_ENA_MINIUART;
|
||||
|
||||
/* Disable interrupts for now */
|
||||
/* auxillary->IRQ &= ~AUX_IRQ_MU; */
|
||||
|
||||
auxillary->MU_IER = 0;
|
||||
|
||||
/* Disable flow control,enable transmitter and receiver! */
|
||||
auxillary->MU_CNTL = 0;
|
||||
|
||||
/* Decide between seven or eight-bit mode */
|
||||
if( bits == 8 )
|
||||
auxillary->MU_LCR = AUX_MULCR_8BIT_MODE;
|
||||
else
|
||||
auxillary->MU_LCR = 0;
|
||||
|
||||
auxillary->MU_MCR = 0;
|
||||
|
||||
/* Disable all interrupts from MU and clear the fifos */
|
||||
auxillary->MU_IER = 0;
|
||||
|
||||
auxillary->MU_IIR = 0xC6;
|
||||
|
||||
/* Transposed calculation from Section 2.2.1 of the ARM peripherals
|
||||
manual */
|
||||
auxillary->MU_BAUD = ( SYS_FREQ / ( 8 * baud ) ) - 1;
|
||||
|
||||
/* Setup GPIO 14 and 15 as alternative function 5 which is
|
||||
UART 1 TXD/RXD. These need to be set before enabling the UART */
|
||||
RPI_SetGpioPinFunction( RPI_GPIO14, FS_ALT5 );
|
||||
RPI_SetGpioPinFunction( RPI_GPIO15, FS_ALT5 );
|
||||
|
||||
RPI_GetGpio()->GPPUD = 0;
|
||||
for( i=0; i<150; i++ ) { }
|
||||
RPI_GetGpio()->GPPUDCLK0 = ( 1 << 14 );
|
||||
for( i=0; i<150; i++ ) { }
|
||||
RPI_GetGpio()->GPPUDCLK0 = 0;
|
||||
|
||||
/* Disable flow control,enable transmitter and receiver! */
|
||||
auxillary->MU_CNTL = AUX_MUCNTL_TX_ENABLE;
|
||||
}
|
||||
|
||||
|
||||
void RPI_AuxMiniUartWrite( char c )
|
||||
{
|
||||
/* Wait until the UART has an empty space in the FIFO */
|
||||
while( ( auxillary->MU_LSR & AUX_MULSR_TX_EMPTY ) == 0 ) { }
|
||||
|
||||
/* Write the character to the FIFO for transmission */
|
||||
auxillary->MU_IO = c;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013-2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_AUX_H
|
||||
#define RPI_AUX_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/* Although these values were originally from the BCM2835 Arm peripherals PDF
|
||||
it's clear that was rushed and has some glaring errors - so these values
|
||||
may appear to be different. These values have been changed due to data on
|
||||
the elinux BCM2835 datasheet errata:
|
||||
http://elinux.org/BCM2835_datasheet_errata */
|
||||
|
||||
#define AUX_BASE ( PERIPHERAL_BASE + 0x215000 )
|
||||
|
||||
#define AUX_ENA_MINIUART ( 1 << 0 )
|
||||
#define AUX_ENA_SPI1 ( 1 << 1 )
|
||||
#define AUX_ENA_SPI2 ( 1 << 2 )
|
||||
|
||||
#define AUX_IRQ_SPI2 ( 1 << 2 )
|
||||
#define AUX_IRQ_SPI1 ( 1 << 1 )
|
||||
#define AUX_IRQ_MU ( 1 << 0 )
|
||||
|
||||
#define AUX_MULCR_8BIT_MODE ( 3 << 0 ) /* See errata for this value */
|
||||
#define AUX_MULCR_BREAK ( 1 << 6 )
|
||||
#define AUX_MULCR_DLAB_ACCESS ( 1 << 7 )
|
||||
|
||||
#define AUX_MUMCR_RTS ( 1 << 1 )
|
||||
|
||||
#define AUX_MULSR_DATA_READY ( 1 << 0 )
|
||||
#define AUX_MULSR_RX_OVERRUN ( 1 << 1 )
|
||||
#define AUX_MULSR_TX_EMPTY ( 1 << 5 )
|
||||
#define AUX_MULSR_TX_IDLE ( 1 << 6 )
|
||||
|
||||
#define AUX_MUMSR_CTS ( 1 << 5 )
|
||||
|
||||
#define AUX_MUCNTL_RX_ENABLE ( 1 << 0 )
|
||||
#define AUX_MUCNTL_TX_ENABLE ( 1 << 1 )
|
||||
#define AUX_MUCNTL_RTS_FLOW ( 1 << 2 )
|
||||
#define AUX_MUCNTL_CTS_FLOW ( 1 << 3 )
|
||||
#define AUX_MUCNTL_RTS_FIFO ( 3 << 4 )
|
||||
#define AUX_MUCNTL_RTS_ASSERT ( 1 << 6 )
|
||||
#define AUX_MUCNTL_CTS_ASSERT ( 1 << 7 )
|
||||
|
||||
#define AUX_MUSTAT_SYMBOL_AV ( 1 << 0 )
|
||||
#define AUX_MUSTAT_SPACE_AV ( 1 << 1 )
|
||||
#define AUX_MUSTAT_RX_IDLE ( 1 << 2 )
|
||||
#define AUX_MUSTAT_TX_IDLE ( 1 << 3 )
|
||||
#define AUX_MUSTAT_RX_OVERRUN ( 1 << 4 )
|
||||
#define AUX_MUSTAT_TX_FIFO_FULL ( 1 << 5 )
|
||||
#define AUX_MUSTAT_RTS ( 1 << 6 )
|
||||
#define AUX_MUSTAT_CTS ( 1 << 7 )
|
||||
#define AUX_MUSTAT_TX_EMPTY ( 1 << 8 )
|
||||
#define AUX_MUSTAT_TX_DONE ( 1 << 9 )
|
||||
#define AUX_MUSTAT_RX_FIFO_LEVEL ( 7 << 16 )
|
||||
#define AUX_MUSTAT_TX_FIFO_LEVEL ( 7 << 24 )
|
||||
|
||||
|
||||
#define FSEL0(x) ( x )
|
||||
#define FSEL1(x) ( x << 3 )
|
||||
#define FSEL2(x) ( x << 6 )
|
||||
#define FSEL3(x) ( x << 9 )
|
||||
#define FSEL4(x) ( x << 12 )
|
||||
#define FSEL5(x) ( x << 15 )
|
||||
#define FSEL6(x) ( x << 18 )
|
||||
#define FSEL7(x) ( x << 21 )
|
||||
#define FSEL8(x) ( x << 24 )
|
||||
#define FSEL9(x) ( x << 27 )
|
||||
|
||||
#define FSEL10(x) ( x )
|
||||
#define FSEL11(x) ( x << 3 )
|
||||
#define FSEL12(x) ( x << 6 )
|
||||
#define FSEL13(x) ( x << 9 )
|
||||
#define FSEL14(x) ( x << 12 )
|
||||
#define FSEL15(x) ( x << 15 )
|
||||
#define FSEL16(x) ( x << 18 )
|
||||
#define FSEL17(x) ( x << 21 )
|
||||
#define FSEL18(x) ( x << 24 )
|
||||
#define FSEL19(x) ( x << 27 )
|
||||
|
||||
#define FSEL20(x) ( x )
|
||||
#define FSEL21(x) ( x << 3 )
|
||||
#define FSEL22(x) ( x << 6 )
|
||||
#define FSEL23(x) ( x << 9 )
|
||||
#define FSEL24(x) ( x << 12 )
|
||||
#define FSEL25(x) ( x << 15 )
|
||||
#define FSEL26(x) ( x << 18 )
|
||||
#define FSEL27(x) ( x << 21 )
|
||||
#define FSEL28(x) ( x << 24 )
|
||||
#define FSEL29(x) ( x << 27 )
|
||||
|
||||
#define FSEL30(x) ( x )
|
||||
#define FSEL31(x) ( x << 3 )
|
||||
#define FSEL32(x) ( x << 6 )
|
||||
#define FSEL33(x) ( x << 9 )
|
||||
#define FSEL34(x) ( x << 12 )
|
||||
#define FSEL35(x) ( x << 15 )
|
||||
#define FSEL36(x) ( x << 18 )
|
||||
#define FSEL37(x) ( x << 21 )
|
||||
#define FSEL38(x) ( x << 24 )
|
||||
#define FSEL39(x) ( x << 27 )
|
||||
|
||||
#define FSEL40(x) ( x )
|
||||
#define FSEL41(x) ( x << 3 )
|
||||
#define FSEL42(x) ( x << 6 )
|
||||
#define FSEL43(x) ( x << 9 )
|
||||
#define FSEL44(x) ( x << 12 )
|
||||
#define FSEL45(x) ( x << 15 )
|
||||
#define FSEL46(x) ( x << 18 )
|
||||
#define FSEL47(x) ( x << 21 )
|
||||
#define FSEL48(x) ( x << 24 )
|
||||
#define FSEL49(x) ( x << 27 )
|
||||
|
||||
#define FSEL50(x) ( x )
|
||||
#define FSEL51(x) ( x << 3 )
|
||||
#define FSEL52(x) ( x << 6 )
|
||||
#define FSEL53(x) ( x << 9 )
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile unsigned int IRQ;
|
||||
volatile unsigned int ENABLES;
|
||||
|
||||
volatile unsigned int reserved1[((0x40 - 0x04) / 4) - 1];
|
||||
|
||||
volatile unsigned int MU_IO;
|
||||
volatile unsigned int MU_IER;
|
||||
volatile unsigned int MU_IIR;
|
||||
volatile unsigned int MU_LCR;
|
||||
volatile unsigned int MU_MCR;
|
||||
volatile unsigned int MU_LSR;
|
||||
volatile unsigned int MU_MSR;
|
||||
volatile unsigned int MU_SCRATCH;
|
||||
volatile unsigned int MU_CNTL;
|
||||
volatile unsigned int MU_STAT;
|
||||
volatile unsigned int MU_BAUD;
|
||||
|
||||
volatile unsigned int reserved2[(0x80 - 0x68) / 4];
|
||||
|
||||
volatile unsigned int SPI0_CNTL0;
|
||||
volatile unsigned int SPI0_CNTL1;
|
||||
volatile unsigned int SPI0_STAT;
|
||||
volatile unsigned int SPI0_IO;
|
||||
volatile unsigned int SPI0_PEEK;
|
||||
|
||||
volatile unsigned int reserved3[(0xC0 - 0x94) / 4];
|
||||
|
||||
volatile unsigned int SPI1_CNTL0;
|
||||
volatile unsigned int SPI1_CNTL1;
|
||||
volatile unsigned int SPI1_STAT;
|
||||
volatile unsigned int SPI1_IO;
|
||||
volatile unsigned int SPI1_PEEK;
|
||||
} aux_t;
|
||||
|
||||
extern aux_t* RPI_GetAux( void );
|
||||
extern void RPI_AuxMiniUartInit( int baud, int bits );
|
||||
extern void RPI_AuxMiniUartWrite( char c );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013-2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_BASE_H
|
||||
#define RPI_BASE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef RPI2
|
||||
#define PERIPHERAL_BASE 0x3F000000UL
|
||||
#else
|
||||
#define PERIPHERAL_BASE 0x20000000UL
|
||||
#endif
|
||||
|
||||
typedef volatile uint32_t rpi_reg_rw_t;
|
||||
typedef volatile const uint32_t rpi_reg_ro_t;
|
||||
typedef volatile uint32_t rpi_reg_wo_t;
|
||||
|
||||
typedef volatile uint64_t rpi_wreg_rw_t;
|
||||
typedef volatile const uint64_t rpi_wreg_ro_t;
|
||||
|
||||
|
||||
int GET32(int index);
|
||||
void PUT32(int index, int value);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gpio.h"
|
||||
|
||||
static rpi_gpio_t* rpiGpio = (rpi_gpio_t*)RPI_GPIO_BASE;
|
||||
|
||||
|
||||
rpi_gpio_t* RPI_GetGpio(void)
|
||||
{
|
||||
return rpiGpio;
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioPinFunction( rpi_gpio_pin_t gpio, rpi_gpio_alt_function_t func )
|
||||
{
|
||||
rpi_reg_rw_t* fsel_reg = &((rpi_reg_rw_t*)rpiGpio)[ gpio / 10 ];
|
||||
rpi_reg_rw_t fsel_copy = *fsel_reg;
|
||||
fsel_copy &= ~( FS_MASK << ( ( gpio % 10 ) * 3 ) );
|
||||
fsel_copy |= (func << ( ( gpio % 10 ) * 3 ) );
|
||||
*fsel_reg = fsel_copy;
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioOutput( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
RPI_SetGpioPinFunction( gpio, FS_OUTPUT );
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioInput( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
RPI_SetGpioPinFunction( gpio, FS_INPUT );
|
||||
}
|
||||
|
||||
|
||||
rpi_gpio_value_t RPI_GetGpioValue( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
rpi_gpio_value_t result = RPI_IO_UNKNOWN;
|
||||
|
||||
switch( gpio / 32 )
|
||||
{
|
||||
case 0:
|
||||
result = rpiGpio->GPLEV0 & ( 1 << gpio );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
result = rpiGpio->GPLEV1 & ( 1 << ( gpio - 32 ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( result != RPI_IO_UNKNOWN )
|
||||
{
|
||||
if( result )
|
||||
result = RPI_IO_HI;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void RPI_ToggleGpio( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
if( RPI_GetGpioValue( gpio ) )
|
||||
RPI_SetGpioLo( gpio );
|
||||
else
|
||||
RPI_SetGpioHi( gpio );
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioHi( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
switch( gpio / 32 )
|
||||
{
|
||||
case 0:
|
||||
rpiGpio->GPSET0 = ( 1 << gpio );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rpiGpio->GPSET1 = ( 1 << ( gpio - 32 ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioLo( rpi_gpio_pin_t gpio )
|
||||
{
|
||||
switch( gpio / 32 )
|
||||
{
|
||||
case 0:
|
||||
rpiGpio->GPCLR0 = ( 1 << gpio );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rpiGpio->GPCLR1 = ( 1 << ( gpio - 32 ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RPI_SetGpioValue( rpi_gpio_pin_t gpio, rpi_gpio_value_t value )
|
||||
{
|
||||
if( ( value == RPI_IO_LO ) || ( value == RPI_IO_OFF ) )
|
||||
RPI_SetGpioLo( gpio );
|
||||
else if( ( value == RPI_IO_HI ) || ( value == RPI_IO_ON ) )
|
||||
RPI_SetGpioHi( gpio );
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013-2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_GPIO_H
|
||||
#define RPI_GPIO_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/** The base address of the GPIO peripheral (ARM Physical Address) */
|
||||
#define RPI_GPIO_BASE ( PERIPHERAL_BASE + 0x200000UL )
|
||||
|
||||
#if defined( RPIBPLUS ) || defined( RPI2 )
|
||||
#define LED_GPFSEL GPFSEL4
|
||||
#define LED_GPFBIT 21
|
||||
#define LED_GPSET GPSET1
|
||||
#define LED_GPCLR GPCLR1
|
||||
#define LED_GPIO_BIT 15
|
||||
#define LED_ON() do { RPI_GetGpio()->LED_GPCLR = ( 1 << LED_GPIO_BIT ); } while( 0 )
|
||||
#define LED_OFF() do { RPI_GetGpio()->LED_GPSET = ( 1 << LED_GPIO_BIT ); } while( 0 )
|
||||
#else
|
||||
#define LED_GPFSEL GPFSEL1
|
||||
#define LED_GPFBIT 18
|
||||
#define LED_GPSET GPSET0
|
||||
#define LED_GPCLR GPCLR0
|
||||
#define LED_GPIO_BIT 16
|
||||
#define LED_ON() do { RPI_GetGpio()->LED_GPSET = ( 1 << LED_GPIO_BIT ); } while( 0 )
|
||||
#define LED_OFF() do { RPI_GetGpio()->LED_GPCLR = ( 1 << LED_GPIO_BIT ); } while( 0 )
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FS_INPUT = 0,
|
||||
FS_OUTPUT,
|
||||
FS_ALT5,
|
||||
FS_ALT4,
|
||||
FS_ALT0,
|
||||
FS_ALT1,
|
||||
FS_ALT2,
|
||||
FS_ALT3,
|
||||
} rpi_gpio_alt_function_t;
|
||||
|
||||
/* A mask to be able to clear the bits in the register before setting the
|
||||
value we require */
|
||||
#define FS_MASK (7)
|
||||
|
||||
typedef enum {
|
||||
RPI_GPIO0 = 0,
|
||||
RPI_GPIO1,
|
||||
RPI_GPIO2,
|
||||
RPI_GPIO3,
|
||||
RPI_GPIO4,
|
||||
RPI_GPIO5,
|
||||
RPI_GPIO6,
|
||||
RPI_GPIO7,
|
||||
RPI_GPIO8,
|
||||
RPI_GPIO9,
|
||||
RPI_GPIO10 = 10,
|
||||
RPI_GPIO11,
|
||||
RPI_GPIO12,
|
||||
RPI_GPIO13,
|
||||
RPI_GPIO14,
|
||||
RPI_GPIO15,
|
||||
RPI_GPIO16,
|
||||
RPI_GPIO17,
|
||||
RPI_GPIO18,
|
||||
RPI_GPIO19,
|
||||
RPI_GPIO20 = 20,
|
||||
RPI_GPIO21,
|
||||
RPI_GPIO22,
|
||||
RPI_GPIO23,
|
||||
RPI_GPIO24,
|
||||
RPI_GPIO25,
|
||||
RPI_GPIO26,
|
||||
RPI_GPIO27,
|
||||
RPI_GPIO28,
|
||||
RPI_GPIO29,
|
||||
RPI_GPIO30 = 30,
|
||||
RPI_GPIO31,
|
||||
RPI_GPIO32,
|
||||
RPI_GPIO33,
|
||||
RPI_GPIO34,
|
||||
RPI_GPIO35,
|
||||
RPI_GPIO36,
|
||||
RPI_GPIO37,
|
||||
RPI_GPIO38,
|
||||
RPI_GPIO39,
|
||||
RPI_GPIO40 = 40,
|
||||
RPI_GPIO41,
|
||||
RPI_GPIO42,
|
||||
RPI_GPIO43,
|
||||
RPI_GPIO44,
|
||||
RPI_GPIO45,
|
||||
RPI_GPIO46,
|
||||
RPI_GPIO47,
|
||||
RPI_GPIO48,
|
||||
RPI_GPIO49,
|
||||
RPI_GPIO50 = 50,
|
||||
RPI_GPIO51,
|
||||
RPI_GPIO52,
|
||||
RPI_GPIO53,
|
||||
} rpi_gpio_pin_t;
|
||||
|
||||
|
||||
/** The GPIO Peripheral is described in section 6 of the BCM2835 Peripherals
|
||||
documentation.
|
||||
|
||||
There are 54 general-purpose I/O (GPIO) lines split into two banks. All
|
||||
GPIO pins have at least two alternative functions within BCM. The
|
||||
alternate functions are usually peripheral IO and a single peripheral
|
||||
may appear in each bank to allow flexibility on the choice of IO voltage.
|
||||
Details of alternative functions are given in section 6.2. Alternative
|
||||
Function Assignments.
|
||||
|
||||
The GPIO peripheral has three dedicated interrupt lines. These lines are
|
||||
triggered by the setting of bits in the event detect status register. Each
|
||||
bank has its’ own interrupt line with the third line shared between all
|
||||
bits.
|
||||
|
||||
The Alternate function table also has the pull state (pull-up/pull-down)
|
||||
which is applied after a power down. */
|
||||
typedef struct {
|
||||
rpi_reg_rw_t GPFSEL0;
|
||||
rpi_reg_rw_t GPFSEL1;
|
||||
rpi_reg_rw_t GPFSEL2;
|
||||
rpi_reg_rw_t GPFSEL3;
|
||||
rpi_reg_rw_t GPFSEL4;
|
||||
rpi_reg_rw_t GPFSEL5;
|
||||
rpi_reg_ro_t Reserved0;
|
||||
rpi_reg_wo_t GPSET0;
|
||||
rpi_reg_wo_t GPSET1;
|
||||
rpi_reg_ro_t Reserved1;
|
||||
rpi_reg_wo_t GPCLR0;
|
||||
rpi_reg_wo_t GPCLR1;
|
||||
rpi_reg_ro_t Reserved2;
|
||||
rpi_reg_wo_t GPLEV0;
|
||||
rpi_reg_wo_t GPLEV1;
|
||||
rpi_reg_ro_t Reserved3;
|
||||
rpi_reg_wo_t GPEDS0;
|
||||
rpi_reg_wo_t GPEDS1;
|
||||
rpi_reg_ro_t Reserved4;
|
||||
rpi_reg_wo_t GPREN0;
|
||||
rpi_reg_wo_t GPREN1;
|
||||
rpi_reg_ro_t Reserved5;
|
||||
rpi_reg_wo_t GPFEN0;
|
||||
rpi_reg_wo_t GPFEN1;
|
||||
rpi_reg_ro_t Reserved6;
|
||||
rpi_reg_wo_t GPHEN0;
|
||||
rpi_reg_wo_t GPHEN1;
|
||||
rpi_reg_ro_t Reserved7;
|
||||
rpi_reg_wo_t GPLEN0;
|
||||
rpi_reg_wo_t GPLEN1;
|
||||
rpi_reg_ro_t Reserved8;
|
||||
rpi_reg_wo_t GPAREN0;
|
||||
rpi_reg_wo_t GPAREN1;
|
||||
rpi_reg_ro_t Reserved9;
|
||||
rpi_reg_wo_t GPAFEN0;
|
||||
rpi_reg_wo_t GPAFEN1;
|
||||
rpi_reg_ro_t Reserved10;
|
||||
rpi_reg_wo_t GPPUD;
|
||||
rpi_reg_wo_t GPPUDCLK0;
|
||||
rpi_reg_wo_t GPPUDCLK1;
|
||||
rpi_reg_ro_t Reserved11;
|
||||
} rpi_gpio_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
RPI_IO_LO = 0,
|
||||
RPI_IO_HI,
|
||||
RPI_IO_ON,
|
||||
RPI_IO_OFF,
|
||||
RPI_IO_UNKNOWN,
|
||||
} rpi_gpio_value_t;
|
||||
|
||||
|
||||
extern rpi_gpio_t* RPI_GetGpio(void);
|
||||
extern void RPI_SetGpioPinFunction( rpi_gpio_pin_t gpio, rpi_gpio_alt_function_t func );
|
||||
extern void RPI_SetGpioOutput( rpi_gpio_pin_t gpio );
|
||||
extern void RPI_SetGpioInput( rpi_gpio_pin_t gpio );
|
||||
extern rpi_gpio_value_t RPI_GetGpioValue( rpi_gpio_pin_t gpio );
|
||||
extern void RPI_SetGpioHi( rpi_gpio_pin_t gpio );
|
||||
extern void RPI_SetGpioLo( rpi_gpio_pin_t gpio );
|
||||
extern void RPI_SetGpioValue( rpi_gpio_pin_t gpio, rpi_gpio_value_t value );
|
||||
extern void RPI_ToggleGpio( rpi_gpio_pin_t gpio );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "armtimer.h"
|
||||
#include "base.h"
|
||||
#include "gpio.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
/** @brief The BCM2835/6 Interupt controller peripheral at it's base address */
|
||||
static rpi_irq_controller_t* rpiIRQController =
|
||||
(rpi_irq_controller_t*)RPI_INTERRUPT_CONTROLLER_BASE;
|
||||
|
||||
volatile int calculate_frame_count = 0;
|
||||
|
||||
/**
|
||||
@brief Return the IRQ Controller register set
|
||||
*/
|
||||
rpi_irq_controller_t* RPI_GetIrqController( void )
|
||||
{
|
||||
return rpiIRQController;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The Reset vector interrupt handler
|
||||
|
||||
This can never be called, since an ARM core reset would also reset the
|
||||
GPU and therefore cause the GPU to start running code again until
|
||||
the ARM is handed control at the end of boot loading
|
||||
*/
|
||||
void __attribute__((interrupt("ABORT"))) reset_vector(void)
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
LED_ON();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The undefined instruction interrupt handler
|
||||
|
||||
If an undefined intstruction is encountered, the CPU will start
|
||||
executing this function. Just trap here as a debug solution.
|
||||
*/
|
||||
void __attribute__((interrupt("UNDEF"))) undefined_instruction_vector(void)
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
/* Do Nothing! */
|
||||
LED_ON();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The supervisor call interrupt handler
|
||||
|
||||
The CPU will start executing this function. Just trap here as a debug
|
||||
solution.
|
||||
*/
|
||||
void __attribute__((interrupt("SWI"))) software_interrupt_vector(void)
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
/* Do Nothing! */
|
||||
LED_ON();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The prefetch abort interrupt handler
|
||||
|
||||
The CPU will start executing this function. Just trap here as a debug
|
||||
solution.
|
||||
*/
|
||||
void __attribute__((interrupt("ABORT"))) prefetch_abort_vector(void)
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
LED_ON();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The Data Abort interrupt handler
|
||||
|
||||
The CPU will start executing this function. Just trap here as a debug
|
||||
solution.
|
||||
*/
|
||||
void __attribute__((interrupt("ABORT"))) data_abort_vector(void)
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
LED_ON();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The IRQ Interrupt handler
|
||||
|
||||
This handler is run every time an interrupt source is triggered. It's
|
||||
up to the handler to determine the source of the interrupt and most
|
||||
importantly clear the interrupt flag so that the interrupt won't
|
||||
immediately put us back into the start of the handler again.
|
||||
*/
|
||||
void __attribute__((interrupt("IRQ"))) interrupt_vector(void)
|
||||
{
|
||||
static int lit = 0;
|
||||
static int ticks = 0;
|
||||
static int seconds = 0;
|
||||
|
||||
/* Clear the ARM Timer interrupt - it's the only interrupt we have
|
||||
enabled, so we want don't have to work out which interrupt source
|
||||
caused us to interrupt */
|
||||
RPI_GetArmTimer()->IRQClear = 1;
|
||||
|
||||
ticks++;
|
||||
if( ticks > 1 )
|
||||
{
|
||||
ticks = 0;
|
||||
|
||||
/* Calculate the FPS once a minute */
|
||||
seconds++;
|
||||
if( seconds > 59 )
|
||||
{
|
||||
seconds = 0;
|
||||
calculate_frame_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flip the LED */
|
||||
if( lit )
|
||||
{
|
||||
LED_OFF();
|
||||
lit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LED_ON();
|
||||
lit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief The FIQ Interrupt Handler
|
||||
|
||||
The FIQ handler can only be allocated to one interrupt source. The FIQ has
|
||||
a full CPU shadow register set. Upon entry to this function the CPU
|
||||
switches to the shadow register set so that there is no need to save
|
||||
registers before using them in the interrupt.
|
||||
|
||||
In C you can't see the difference between the IRQ and the FIQ interrupt
|
||||
handlers except for the FIQ knowing it's source of interrupt as there can
|
||||
only be one source, but the prologue and epilogue code is quite different.
|
||||
It's much faster on the FIQ interrupt handler.
|
||||
|
||||
The prologue is the code that the compiler inserts at the start of the
|
||||
function, if you like, think of the opening curly brace of the function as
|
||||
being the prologue code. For the FIQ interrupt handler this is nearly
|
||||
empty because the CPU has switched to a fresh set of registers, there's
|
||||
nothing we need to save.
|
||||
|
||||
The epilogue is the code that the compiler inserts at the end of the
|
||||
function, if you like, think of the closing curly brace of the function as
|
||||
being the epilogue code. For the FIQ interrupt handler this is nearly
|
||||
empty because the CPU has switched to a fresh set of registers and so has
|
||||
not altered the main set of registers.
|
||||
*/
|
||||
void __attribute__((interrupt("FIQ"))) fast_interrupt_vector(void)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_INTERRUPTS_H
|
||||
#define RPI_INTERRUPTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/** @brief See Section 7.5 of the BCM2836 ARM Peripherals documentation, the base
|
||||
address of the controller is actually xxxxB000, but there is a 0x200 offset
|
||||
to the first addressable register for the interrupt controller, so offset the
|
||||
base to the first register */
|
||||
#define RPI_INTERRUPT_CONTROLLER_BASE ( PERIPHERAL_BASE + 0xB200 )
|
||||
|
||||
/** @brief Bits in the Enable_Basic_IRQs register to enable various interrupts.
|
||||
See the BCM2835 ARM Peripherals manual, section 7.5 */
|
||||
#define RPI_BASIC_ARM_TIMER_IRQ (1 << 0)
|
||||
#define RPI_BASIC_ARM_MAILBOX_IRQ (1 << 1)
|
||||
#define RPI_BASIC_ARM_DOORBELL_0_IRQ (1 << 2)
|
||||
#define RPI_BASIC_ARM_DOORBELL_1_IRQ (1 << 3)
|
||||
#define RPI_BASIC_GPU_0_HALTED_IRQ (1 << 4)
|
||||
#define RPI_BASIC_GPU_1_HALTED_IRQ (1 << 5)
|
||||
#define RPI_BASIC_ACCESS_ERROR_1_IRQ (1 << 6)
|
||||
#define RPI_BASIC_ACCESS_ERROR_0_IRQ (1 << 7)
|
||||
|
||||
|
||||
/** @brief The interrupt controller memory mapped register set */
|
||||
typedef struct {
|
||||
volatile uint32_t IRQ_basic_pending;
|
||||
volatile uint32_t IRQ_pending_1;
|
||||
volatile uint32_t IRQ_pending_2;
|
||||
volatile uint32_t FIQ_control;
|
||||
volatile uint32_t Enable_IRQs_1;
|
||||
volatile uint32_t Enable_IRQs_2;
|
||||
volatile uint32_t Enable_Basic_IRQs;
|
||||
volatile uint32_t Disable_IRQs_1;
|
||||
volatile uint32_t Disable_IRQs_2;
|
||||
volatile uint32_t Disable_Basic_IRQs;
|
||||
} rpi_irq_controller_t;
|
||||
|
||||
extern volatile int calculate_frame_count;
|
||||
|
||||
/* Found in the *start.S file, implemented in assembler */
|
||||
extern void _enable_interrupts( void );
|
||||
extern rpi_irq_controller_t* RPI_GetIrqController( void );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mailbox.h"
|
||||
#include "mailbox-interface.h"
|
||||
|
||||
/* Make sure the property tag buffer is aligned to a 16-byte boundary because
|
||||
we only have 28-bits available in the property interface protocol to pass
|
||||
the address of the buffer to the VC. */
|
||||
static int pt[8192] __attribute__((aligned(16)));
|
||||
static int pt_index = 0;
|
||||
|
||||
|
||||
void RPI_PropertyInit( void )
|
||||
{
|
||||
/* Fill in the size on-the-fly */
|
||||
pt[PT_OSIZE] = 12;
|
||||
|
||||
/* Process request (All other values are reserved!) */
|
||||
pt[PT_OREQUEST_OR_RESPONSE] = 0;
|
||||
|
||||
/* First available data slot */
|
||||
pt_index = 2;
|
||||
|
||||
/* NULL tag to terminate tag list */
|
||||
pt[pt_index] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Add a property tag to the current tag list. Data can be included. All data is uint32_t
|
||||
@param tag
|
||||
*/
|
||||
void RPI_PropertyAddTag( rpi_mailbox_tag_t tag, ... )
|
||||
{
|
||||
va_list vl;
|
||||
va_start( vl, tag );
|
||||
|
||||
pt[pt_index++] = tag;
|
||||
|
||||
switch( tag )
|
||||
{
|
||||
case TAG_GET_FIRMWARE_VERSION:
|
||||
case TAG_GET_BOARD_MODEL:
|
||||
case TAG_GET_BOARD_REVISION:
|
||||
case TAG_GET_BOARD_MAC_ADDRESS:
|
||||
case TAG_GET_BOARD_SERIAL:
|
||||
case TAG_GET_ARM_MEMORY:
|
||||
case TAG_GET_VC_MEMORY:
|
||||
case TAG_GET_DMA_CHANNELS:
|
||||
/* Provide an 8-byte buffer for the response */
|
||||
pt[pt_index++] = 8;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
pt_index += 2;
|
||||
break;
|
||||
|
||||
case TAG_GET_CLOCKS:
|
||||
case TAG_GET_COMMAND_LINE:
|
||||
/* Provide a 256-byte buffer */
|
||||
pt[pt_index++] = 256;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
pt_index += 256 >> 2;
|
||||
break;
|
||||
|
||||
case TAG_ALLOCATE_BUFFER:
|
||||
case TAG_GET_MAX_CLOCK_RATE:
|
||||
case TAG_GET_MIN_CLOCK_RATE:
|
||||
case TAG_GET_CLOCK_RATE:
|
||||
pt[pt_index++] = 8;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
pt[pt_index++] = va_arg( vl, int );
|
||||
pt[pt_index++] = 0;
|
||||
break;
|
||||
|
||||
case TAG_SET_CLOCK_RATE:
|
||||
pt[pt_index++] = 12;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Clock ID */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Rate (in Hz) */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Skip turbo setting if == 1 */
|
||||
break;
|
||||
|
||||
case TAG_GET_PHYSICAL_SIZE:
|
||||
case TAG_SET_PHYSICAL_SIZE:
|
||||
case TAG_TEST_PHYSICAL_SIZE:
|
||||
case TAG_GET_VIRTUAL_SIZE:
|
||||
case TAG_SET_VIRTUAL_SIZE:
|
||||
case TAG_TEST_VIRTUAL_SIZE:
|
||||
case TAG_GET_VIRTUAL_OFFSET:
|
||||
case TAG_SET_VIRTUAL_OFFSET:
|
||||
pt[pt_index++] = 8;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
|
||||
if( ( tag == TAG_SET_PHYSICAL_SIZE ) ||
|
||||
( tag == TAG_SET_VIRTUAL_SIZE ) ||
|
||||
( tag == TAG_SET_VIRTUAL_OFFSET ) ||
|
||||
( tag == TAG_TEST_PHYSICAL_SIZE ) ||
|
||||
( tag == TAG_TEST_VIRTUAL_SIZE ) )
|
||||
{
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Width */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Height */
|
||||
}
|
||||
else
|
||||
{
|
||||
pt_index += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case TAG_GET_ALPHA_MODE:
|
||||
case TAG_SET_ALPHA_MODE:
|
||||
case TAG_GET_DEPTH:
|
||||
case TAG_SET_DEPTH:
|
||||
case TAG_GET_PIXEL_ORDER:
|
||||
case TAG_SET_PIXEL_ORDER:
|
||||
case TAG_GET_PITCH:
|
||||
pt[pt_index++] = 4;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
|
||||
if( ( tag == TAG_SET_DEPTH ) ||
|
||||
( tag == TAG_SET_PIXEL_ORDER ) ||
|
||||
( tag == TAG_SET_ALPHA_MODE ) )
|
||||
{
|
||||
/* Colour Depth, bits-per-pixel \ Pixel Order State */
|
||||
pt[pt_index++] = va_arg( vl, int );
|
||||
}
|
||||
else
|
||||
{
|
||||
pt_index += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TAG_GET_OVERSCAN:
|
||||
case TAG_SET_OVERSCAN:
|
||||
pt[pt_index++] = 16;
|
||||
pt[pt_index++] = 0; /* Request */
|
||||
|
||||
if( ( tag == TAG_SET_OVERSCAN ) )
|
||||
{
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Top pixels */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Bottom pixels */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Left pixels */
|
||||
pt[pt_index++] = va_arg( vl, int ); /* Right pixels */
|
||||
}
|
||||
else
|
||||
{
|
||||
pt_index += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported tags, just remove the tag from the list */
|
||||
pt_index--;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the tags are 0 terminated to end the list and update the buffer size */
|
||||
pt[pt_index] = 0;
|
||||
|
||||
va_end( vl );
|
||||
}
|
||||
|
||||
|
||||
int RPI_PropertyProcess( void )
|
||||
{
|
||||
int result;
|
||||
|
||||
#if( PRINT_PROP_DEBUG == 1 )
|
||||
printf( "%s Length: %d\r\n", __func__, pt[PT_OSIZE] );
|
||||
#endif
|
||||
/* Fill in the size of the buffer */
|
||||
pt[PT_OSIZE] = ( pt_index + 1 ) << 2;
|
||||
pt[PT_OREQUEST_OR_RESPONSE] = 0;
|
||||
|
||||
#if( PRINT_PROP_DEBUG == 1 )
|
||||
for( i = 0; i < (pt[PT_OSIZE] >> 2); i++ )
|
||||
printf( "Request: %3d %8.8X\r\n", i, pt[i] );
|
||||
#endif
|
||||
RPI_Mailbox0Write( MB0_TAGS_ARM_TO_VC, (unsigned int)pt );
|
||||
|
||||
result = RPI_Mailbox0Read( MB0_TAGS_ARM_TO_VC );
|
||||
|
||||
#if( PRINT_PROP_DEBUG == 1 )
|
||||
for( i = 0; i < (pt[PT_OSIZE] >> 2); i++ )
|
||||
printf( "Response: %3d %8.8X\r\n", i, pt[i] );
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
rpi_mailbox_property_t* RPI_PropertyGet( rpi_mailbox_tag_t tag )
|
||||
{
|
||||
static rpi_mailbox_property_t property;
|
||||
int* tag_buffer = NULL;
|
||||
|
||||
property.tag = tag;
|
||||
|
||||
/* Get the tag from the buffer. Start at the first tag position */
|
||||
int index = 2;
|
||||
|
||||
while( index < ( pt[PT_OSIZE] >> 2 ) )
|
||||
{
|
||||
/* printf( "Test Tag: [%d] %8.8X\r\n", index, pt[index] ); */
|
||||
if( pt[index] == tag )
|
||||
{
|
||||
tag_buffer = &pt[index];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Progress to the next tag if we haven't yet discovered the tag */
|
||||
index += ( pt[index + 1] >> 2 ) + 3;
|
||||
}
|
||||
|
||||
/* Return NULL of the property tag cannot be found in the buffer */
|
||||
if( tag_buffer == NULL )
|
||||
return NULL;
|
||||
|
||||
/* Return the required data */
|
||||
property.byte_length = tag_buffer[T_ORESPONSE] & 0xFFFF;
|
||||
memcpy( property.data.buffer_8, &tag_buffer[T_OVALUE], property.byte_length );
|
||||
|
||||
return &property;
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_MAILBOX_INTERFACE_H
|
||||
#define RPI_MAILBOX_INTERFACE_H
|
||||
|
||||
/**
|
||||
@brief An enum of the RPI->Videocore firmware mailbox property interface
|
||||
properties. Further details are available from
|
||||
https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
|
||||
*/
|
||||
typedef enum {
|
||||
/* Videocore */
|
||||
TAG_GET_FIRMWARE_VERSION = 0x1,
|
||||
|
||||
/* Hardware */
|
||||
TAG_GET_BOARD_MODEL = 0x10001,
|
||||
TAG_GET_BOARD_REVISION,
|
||||
TAG_GET_BOARD_MAC_ADDRESS,
|
||||
TAG_GET_BOARD_SERIAL,
|
||||
TAG_GET_ARM_MEMORY,
|
||||
TAG_GET_VC_MEMORY,
|
||||
TAG_GET_CLOCKS,
|
||||
|
||||
/* Config */
|
||||
TAG_GET_COMMAND_LINE = 0x50001,
|
||||
|
||||
/* Shared resource management */
|
||||
TAG_GET_DMA_CHANNELS = 0x60001,
|
||||
|
||||
/* Power */
|
||||
TAG_GET_POWER_STATE = 0x20001,
|
||||
TAG_GET_TIMING,
|
||||
TAG_SET_POWER_STATE = 0x28001,
|
||||
|
||||
/* Clocks */
|
||||
TAG_GET_CLOCK_STATE = 0x30001,
|
||||
TAG_SET_CLOCK_STATE = 0x38001,
|
||||
TAG_GET_CLOCK_RATE = 0x30002,
|
||||
TAG_SET_CLOCK_RATE = 0x38002,
|
||||
TAG_GET_MAX_CLOCK_RATE = 0x30004,
|
||||
TAG_GET_MIN_CLOCK_RATE = 0x30007,
|
||||
TAG_GET_TURBO = 0x30009,
|
||||
TAG_SET_TURBO = 0x38009,
|
||||
|
||||
/* Voltage */
|
||||
TAG_GET_VOLTAGE = 0x30003,
|
||||
TAG_SET_VOLTAGE = 0x38003,
|
||||
TAG_GET_MAX_VOLTAGE = 0x30005,
|
||||
TAG_GET_MIN_VOLTAGE = 0x30008,
|
||||
TAG_GET_TEMPERATURE = 0x30006,
|
||||
TAG_GET_MAX_TEMPERATURE = 0x3000A,
|
||||
TAG_ALLOCATE_MEMORY = 0x3000C,
|
||||
TAG_LOCK_MEMORY = 0x3000D,
|
||||
TAG_UNLOCK_MEMORY = 0x3000E,
|
||||
TAG_RELEASE_MEMORY = 0x3000F,
|
||||
TAG_EXECUTE_CODE = 0x30010,
|
||||
TAG_GET_DISPMANX_MEM_HANDLE = 0x30014,
|
||||
TAG_GET_EDID_BLOCK = 0x30020,
|
||||
|
||||
/* Framebuffer */
|
||||
TAG_ALLOCATE_BUFFER = 0x40001,
|
||||
TAG_RELEASE_BUFFER = 0x48001,
|
||||
TAG_BLANK_SCREEN = 0x40002,
|
||||
TAG_GET_PHYSICAL_SIZE = 0x40003,
|
||||
TAG_TEST_PHYSICAL_SIZE = 0x44003,
|
||||
TAG_SET_PHYSICAL_SIZE = 0x48003,
|
||||
TAG_GET_VIRTUAL_SIZE = 0x40004,
|
||||
TAG_TEST_VIRTUAL_SIZE = 0x44004,
|
||||
TAG_SET_VIRTUAL_SIZE = 0x48004,
|
||||
TAG_GET_DEPTH = 0x40005,
|
||||
TAG_TEST_DEPTH = 0x44005,
|
||||
TAG_SET_DEPTH = 0x48005,
|
||||
TAG_GET_PIXEL_ORDER = 0x40006,
|
||||
TAG_TEST_PIXEL_ORDER = 0x44006,
|
||||
TAG_SET_PIXEL_ORDER = 0x48006,
|
||||
TAG_GET_ALPHA_MODE = 0x40007,
|
||||
TAG_TEST_ALPHA_MODE = 0x44007,
|
||||
TAG_SET_ALPHA_MODE = 0x48007,
|
||||
TAG_GET_PITCH = 0x40008,
|
||||
TAG_GET_VIRTUAL_OFFSET = 0x40009,
|
||||
TAG_TEST_VIRTUAL_OFFSET = 0x44009,
|
||||
TAG_SET_VIRTUAL_OFFSET = 0x48009,
|
||||
TAG_GET_OVERSCAN = 0x4000A,
|
||||
TAG_TEST_OVERSCAN = 0x4400A,
|
||||
TAG_SET_OVERSCAN = 0x4800A,
|
||||
TAG_GET_PALETTE = 0x4000B,
|
||||
TAG_TEST_PALETTE = 0x4400B,
|
||||
TAG_SET_PALETTE = 0x4800B,
|
||||
TAG_SET_CURSOR_INFO = 0x8011,
|
||||
TAG_SET_CURSOR_STATE = 0x8010
|
||||
|
||||
} rpi_mailbox_tag_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
TAG_STATE_REQUEST = 0,
|
||||
TAG_STATE_RESPONSE = 1,
|
||||
} rpi_tag_state_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PT_OSIZE = 0,
|
||||
PT_OREQUEST_OR_RESPONSE = 1,
|
||||
} rpi_tag_buffer_offset_t;
|
||||
|
||||
typedef enum {
|
||||
T_OIDENT = 0,
|
||||
T_OVALUE_SIZE = 1,
|
||||
T_ORESPONSE = 2,
|
||||
T_OVALUE = 3,
|
||||
} rpi_tag_offset_t;
|
||||
|
||||
typedef struct {
|
||||
int tag;
|
||||
int byte_length;
|
||||
union {
|
||||
int value_32;
|
||||
unsigned char buffer_8[256];
|
||||
int buffer_32[64];
|
||||
} data;
|
||||
} rpi_mailbox_property_t;
|
||||
|
||||
typedef enum {
|
||||
TAG_CLOCK_RESERVED = 0,
|
||||
TAG_CLOCK_EMMC,
|
||||
TAG_CLOCK_UART,
|
||||
TAG_CLOCK_ARM,
|
||||
TAG_CLOCK_CORE,
|
||||
TAG_CLOCK_V3D,
|
||||
TAG_CLOCK_H264,
|
||||
TAG_CLOCK_ISP,
|
||||
TAG_CLOCK_SDRAM,
|
||||
TAG_CLOCK_PIXEL,
|
||||
TAG_CLOCK_PWM,
|
||||
} rpi_tag_clock_id_t;
|
||||
|
||||
extern void RPI_PropertyInit( void );
|
||||
extern void RPI_PropertyAddTag( rpi_mailbox_tag_t tag, ... );
|
||||
extern int RPI_PropertyProcess( void );
|
||||
extern rpi_mailbox_property_t* RPI_PropertyGet( rpi_mailbox_tag_t tag );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "mailbox.h"
|
||||
|
||||
/* Mailbox 0 mapped to it's base address */
|
||||
static mailbox_t* rpiMailbox0 = (mailbox_t*)RPI_MAILBOX0_BASE;
|
||||
|
||||
void RPI_Mailbox0Write( mailbox0_channel_t channel, int value )
|
||||
{
|
||||
/* For information about accessing mailboxes, see:
|
||||
https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes */
|
||||
|
||||
/* Add the channel number into the lower 4 bits */
|
||||
value &= ~(0xF);
|
||||
value |= channel;
|
||||
|
||||
/* Wait until the mailbox becomes available and then write to the mailbox
|
||||
channel */
|
||||
while( ( rpiMailbox0->Status & ARM_MS_FULL ) != 0 ) { }
|
||||
|
||||
/* Write the modified value + channel number into the write register */
|
||||
rpiMailbox0->Write = value;
|
||||
}
|
||||
|
||||
|
||||
int RPI_Mailbox0Read( mailbox0_channel_t channel )
|
||||
{
|
||||
/* For information about accessing mailboxes, see:
|
||||
https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes */
|
||||
int value = -1;
|
||||
|
||||
/* Keep reading the register until the desired channel gives us a value */
|
||||
while( ( value & 0xF ) != channel )
|
||||
{
|
||||
/* Wait while the mailbox is empty because otherwise there's no value
|
||||
to read! */
|
||||
while( rpiMailbox0->Status & ARM_MS_EMPTY ) { }
|
||||
|
||||
/* Extract the value from the Read register of the mailbox. The value
|
||||
is actually in the upper 28 bits */
|
||||
value = rpiMailbox0->Read;
|
||||
}
|
||||
|
||||
/* Return just the value (the upper 28-bits) */
|
||||
return value >> 4;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_MAILBOX_H
|
||||
#define RPI_MAILBOX_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#define RPI_MAILBOX0_BASE ( PERIPHERAL_BASE + 0xB880 )
|
||||
|
||||
/* The available mailbox channels in the BCM2835 Mailbox interface.
|
||||
See https://github.com/raspberrypi/firmware/wiki/Mailboxes for
|
||||
information */
|
||||
typedef enum {
|
||||
MB0_POWER_MANAGEMENT = 0,
|
||||
MB0_FRAMEBUFFER,
|
||||
MB0_VIRTUAL_UART,
|
||||
MB0_VCHIQ,
|
||||
MB0_LEDS,
|
||||
MB0_BUTTONS,
|
||||
MB0_TOUCHSCREEN,
|
||||
MB0_UNUSED,
|
||||
MB0_TAGS_ARM_TO_VC,
|
||||
MB0_TAGS_VC_TO_ARM,
|
||||
} mailbox0_channel_t;
|
||||
|
||||
/* These defines come from the Broadcom Videocode driver source code, see:
|
||||
brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/arm_control.h */
|
||||
enum mailbox_status_reg_bits {
|
||||
ARM_MS_FULL = 0x80000000,
|
||||
ARM_MS_EMPTY = 0x40000000,
|
||||
ARM_MS_LEVEL = 0x400000FF,
|
||||
};
|
||||
|
||||
/* Define a structure which defines the register access to a mailbox.
|
||||
Not all mailboxes support the full register set! */
|
||||
typedef struct {
|
||||
volatile unsigned int Read;
|
||||
volatile unsigned int reserved1[((0x90 - 0x80) / 4) - 1];
|
||||
volatile unsigned int Poll;
|
||||
volatile unsigned int Sender;
|
||||
volatile unsigned int Status;
|
||||
volatile unsigned int Configuration;
|
||||
volatile unsigned int Write;
|
||||
} mailbox_t;
|
||||
|
||||
extern void RPI_Mailbox0Write( mailbox0_channel_t channel, int value );
|
||||
extern int RPI_Mailbox0Read( mailbox0_channel_t channel );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "systimer.h"
|
||||
|
||||
static rpi_sys_timer_t* rpiSystemTimer = (rpi_sys_timer_t*)RPI_SYSTIMER_BASE;
|
||||
|
||||
rpi_sys_timer_t* RPI_GetSystemTimer(void)
|
||||
{
|
||||
return rpiSystemTimer;
|
||||
}
|
||||
|
||||
void RPI_WaitMicroSeconds( uint32_t us )
|
||||
{
|
||||
volatile uint32_t ts = rpiSystemTimer->counter_lo;
|
||||
|
||||
while( ( rpiSystemTimer->counter_lo - ts ) < us )
|
||||
{
|
||||
/* BLANK */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Part of the Raspberry-Pi Bare Metal Tutorials
|
||||
Copyright (c) 2013-2015, Brian Sidebotham
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPI_SYSTIMER_H
|
||||
#define RPI_SYSTIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#define RPI_SYSTIMER_BASE ( PERIPHERAL_BASE + 0x3000 )
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t control_status;
|
||||
volatile uint32_t counter_lo;
|
||||
volatile uint32_t counter_hi;
|
||||
volatile uint32_t compare0;
|
||||
volatile uint32_t compare1;
|
||||
volatile uint32_t compare2;
|
||||
volatile uint32_t compare3;
|
||||
} rpi_sys_timer_t;
|
||||
|
||||
|
||||
extern rpi_sys_timer_t* RPI_GetSystemTimer(void);
|
||||
extern void RPI_WaitMicroSeconds( uint32_t us );
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user