cleanup root and unfuck CMakeLists.txt

This commit is contained in:
Amrit Panesar committed 2016-10-19 00:56:35 -07:00
1 parent ad4461fde6
commit 8b4c71951e
37 files changed
+25 -17

No files matched your search

+42
View File
@@ -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! */
}
}
+33
View File
@@ -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
+15
View File
@@ -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)
{
}
+141
View File
@@ -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
+79
View File
@@ -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;
}
+187
View File
@@ -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
+53
View File
@@ -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
+115
View File
@@ -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 );
}
+211
View File
@@ -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
+177
View File
@@ -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)
{
}
+76
View File
@@ -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
+252
View File
@@ -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;
}
+170
View File
@@ -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
+77
View File
@@ -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;
}
+77
View File
@@ -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
+20
View File
@@ -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 */
}
}
+54
View File
@@ -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