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,235 @@
|
||||
/* Default linker script, for normal executables */
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
|
||||
"elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000);
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
|
||||
.rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rel.iplt :
|
||||
{
|
||||
PROVIDE_HIDDEN (__rel_iplt_start = .);
|
||||
*(.rel.iplt)
|
||||
PROVIDE_HIDDEN (__rel_iplt_end = .);
|
||||
}
|
||||
.rela.iplt :
|
||||
{
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
}
|
||||
.rel.plt :
|
||||
{
|
||||
*(.rel.plt)
|
||||
}
|
||||
.rela.plt :
|
||||
{
|
||||
*(.rela.plt)
|
||||
}
|
||||
.init :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
} =0
|
||||
.plt : { *(.plt) }
|
||||
.iplt : { *(.iplt) }
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
|
||||
} =0
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} =0
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
|
||||
PROVIDE_HIDDEN (__exidx_start = .);
|
||||
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
|
||||
PROVIDE_HIDDEN (__exidx_end = .);
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
|
||||
.gcc_except_table.*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
|
||||
.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
/* . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); */
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
__bss_start__ = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we don't
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 32 / 8 : 1);
|
||||
}
|
||||
_bss_end__ = . ; __bss_end__ = . ;
|
||||
. = ALIGN(32 / 8);
|
||||
. = ALIGN(32 / 8);
|
||||
__end__ = . ;
|
||||
_end = .; PROVIDE (end = .);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3 */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.stack 0x80000 :
|
||||
{
|
||||
_stack = .;
|
||||
*(.stack)
|
||||
}
|
||||
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
|
||||
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
extern int __bss_start__;
|
||||
extern int __bss_end__;
|
||||
|
||||
extern void kernel_main( unsigned int r0, unsigned int r1, unsigned int atags );
|
||||
|
||||
void _cstartup( unsigned int r0, unsigned int r1, unsigned int r2 )
|
||||
{
|
||||
int* bss = &__bss_start__;
|
||||
int* bss_end = &__bss_end__;
|
||||
|
||||
/*
|
||||
Clear the BSS section
|
||||
|
||||
See http://en.wikipedia.org/wiki/.bss for further information on the
|
||||
BSS section
|
||||
|
||||
See https://sourceware.org/newlib/libc.html#Stubs for further
|
||||
information on the c-library stubs
|
||||
*/
|
||||
while( bss < bss_end )
|
||||
*bss++ = 0;
|
||||
|
||||
/* We should never return from main ... */
|
||||
kernel_main( r0, r1, r2 );
|
||||
|
||||
/* ... but if we do, safely trap here */
|
||||
while(1)
|
||||
{
|
||||
/* EMPTY! */
|
||||
}
|
||||
}
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/* For more information about this file, please visit:
|
||||
https://sourceware.org/newlib/libc.html#Stubs
|
||||
|
||||
These are the newlib C-Library stubs for the valvers Raspberry-Pi bare-metal
|
||||
tutorial */
|
||||
|
||||
/*
|
||||
Graceful failure is permitted by returning an error code. A minor
|
||||
complication arises here: the C library must be compatible with development
|
||||
environments that supply fully functional versions of these subroutines.
|
||||
Such environments usually return error codes in a global errno. However,
|
||||
the Red Hat newlib C library provides a macro definition for errno in the
|
||||
header file errno.h, as part of its support for reentrant routines (see
|
||||
Reentrancy).
|
||||
|
||||
The bridge between these two interpretations of errno is straightforward:
|
||||
the C library routines with OS interface calls capture the errno values
|
||||
returned globally, and record them in the appropriate field of the
|
||||
reentrancy structure (so that you can query them using the errno macro from
|
||||
errno.h).
|
||||
|
||||
This mechanism becomes visible when you write stub routines for OS
|
||||
interfaces. You must include errno.h, then disable the macro, like this:
|
||||
*/
|
||||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
/* Required include for fstat() */
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Required include for times() */
|
||||
#include <sys/times.h>
|
||||
|
||||
/* Prototype for the UART write function */
|
||||
#include "rpi/aux.h"
|
||||
|
||||
/* A pointer to a list of environment variables and their values. For a minimal
|
||||
environment, this empty list is adequate: */
|
||||
char *__env[1] = {0};
|
||||
char **environ = __env;
|
||||
|
||||
/* A helper function written in assembler to aid us in allocating memory */
|
||||
extern caddr_t _get_stack_pointer(void);
|
||||
|
||||
|
||||
/* Never return from _exit as there's no OS to exit to, so instead we trap
|
||||
here */
|
||||
void _exit( int status )
|
||||
{
|
||||
/* Stop the compiler complaining about unused variables by "using" it */
|
||||
(void)status;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* TRAP HERE */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* There's currently no implementation of a file system because there's no
|
||||
file system! */
|
||||
int _close( int file )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Transfer control to a new process. Minimal implementation (for a system
|
||||
without processes): */
|
||||
int execve( char *name, char **argv, char **env )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Create a new process. Minimal implementation (for a system without
|
||||
processes): */
|
||||
int fork( void )
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Status of an open file. For consistency with other minimal implementations
|
||||
in these examples, all files are regarded as character special devices. The
|
||||
sys/stat.h header file required is distributed in the include subdirectory
|
||||
for this C library. */
|
||||
int _fstat( int file, struct stat *st )
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Process-ID; this is sometimes used to generate strings unlikely to conflict
|
||||
with other processes. Minimal implementation, for a system without
|
||||
processes: */
|
||||
int getpid( void )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Query whether output stream is a terminal. For consistency with the other
|
||||
minimal implementations, which only support output to stdout, this minimal
|
||||
implementation is suggested: */
|
||||
int _isatty(int file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Send a signal. Minimal implementation: */
|
||||
int kill( int pid, int sig )
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Establish a new name for an existing file. Minimal implementation: */
|
||||
int link( char *old, char *new )
|
||||
{
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Set position in a file. Minimal implementation: */
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Open a file. Minimal implementation: */
|
||||
int open( const char *name, int flags, int mode )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Read from a file. Minimal implementation: */
|
||||
int _read( int file, char *ptr, int len )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Increase program data space. As malloc and related functions depend on this,
|
||||
it is useful to have a working implementation. The following suffices for a
|
||||
standalone system; it exploits the symbol _end automatically defined by the
|
||||
GNU linker. */
|
||||
caddr_t _sbrk( int incr )
|
||||
{
|
||||
extern char _end;
|
||||
static char* heap_end = 0;
|
||||
char* prev_heap_end;
|
||||
|
||||
if( heap_end == 0 )
|
||||
heap_end = &_end;
|
||||
|
||||
prev_heap_end = heap_end;
|
||||
heap_end += incr;
|
||||
|
||||
return (caddr_t)prev_heap_end;
|
||||
}
|
||||
|
||||
|
||||
/* Status of a file (by name). Minimal implementation: */
|
||||
int stat( const char *file, struct stat *st )
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Timing information for current process. Minimal implementation: */
|
||||
clock_t times( struct tms *buf )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Remove a file's directory entry. Minimal implementation: */
|
||||
int unlink( char *name )
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Wait for a child process. Minimal implementation: */
|
||||
int wait( int *status )
|
||||
{
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void outbyte( char b )
|
||||
{
|
||||
RPI_AuxMiniUartWrite( b );
|
||||
}
|
||||
|
||||
/* Write to a file. libc subroutines will use this system routine for output to
|
||||
all files, including stdout—so if you need to generate any output, for
|
||||
example to a serial port for debugging, you should make your minimal write
|
||||
capable of doing this. The following minimal implementation is an
|
||||
incomplete example; it relies on a outbyte subroutine (not shown; typically,
|
||||
you must write this in assembler from examples provided by your hardware
|
||||
manufacturer) to actually perform the output. */
|
||||
int _write( int file, char *ptr, int len )
|
||||
{
|
||||
int todo;
|
||||
|
||||
for( todo = 0; todo < len; todo++ )
|
||||
outbyte(*ptr++);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -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
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
|
||||
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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rpi/aux.h"
|
||||
#include "rpi/armtimer.h"
|
||||
#include "rpi/gpio.h"
|
||||
#include "rpi/interrupts.h"
|
||||
#include "rpi/mailbox-interface.h"
|
||||
#include "rpi/systimer.h"
|
||||
#include "kernel/util.h"
|
||||
|
||||
/** Main function - we'll never return from here */
|
||||
void kernel_main( unsigned int r0, unsigned int r1, unsigned int atags )
|
||||
{
|
||||
int width = SCREEN_WIDTH, height = SCREEN_HEIGHT, bpp = SCREEN_DEPTH;
|
||||
int x, y, pitch = 0;
|
||||
colour_t current_colour;
|
||||
volatile unsigned char* fb = NULL;
|
||||
int pixel_offset;
|
||||
int r, g, b, a;
|
||||
float cd = COLOUR_DELTA;
|
||||
unsigned int frame_count = 0;
|
||||
|
||||
/* Write 1 to the LED init nibble in the Function Select GPIO
|
||||
peripheral register to enable LED pin as an output */
|
||||
RPI_GetGpio()->LED_GPFSEL |= LED_GPFBIT;
|
||||
|
||||
/* Enable the timer interrupt IRQ */
|
||||
RPI_GetIrqController()->Enable_Basic_IRQs = RPI_BASIC_ARM_TIMER_IRQ;
|
||||
|
||||
/* Setup the system timer interrupt */
|
||||
/* Timer frequency = Clk/256 * 0x400 */
|
||||
RPI_GetArmTimer()->Load = 0x400;
|
||||
|
||||
/* Setup the ARM Timer */
|
||||
RPI_GetArmTimer()->Control =
|
||||
RPI_ARMTIMER_CTRL_23BIT |
|
||||
RPI_ARMTIMER_CTRL_ENABLE |
|
||||
RPI_ARMTIMER_CTRL_INT_ENABLE |
|
||||
RPI_ARMTIMER_CTRL_PRESCALE_256;
|
||||
|
||||
/* Enable interrupts! */
|
||||
_enable_interrupts();
|
||||
|
||||
/* Initialise the UART */
|
||||
RPI_AuxMiniUartInit( 115200, 8 );
|
||||
|
||||
/* Print to the UART using the standard libc functions */
|
||||
printf( "Valvers.com ARM Bare Metal Tutorials\r\n" );
|
||||
printf( "Initialise UART console with standard libc\r\n\n" );
|
||||
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_GET_BOARD_MODEL );
|
||||
RPI_PropertyAddTag( TAG_GET_BOARD_REVISION );
|
||||
RPI_PropertyAddTag( TAG_GET_FIRMWARE_VERSION );
|
||||
RPI_PropertyAddTag( TAG_GET_BOARD_MAC_ADDRESS );
|
||||
RPI_PropertyAddTag( TAG_GET_BOARD_SERIAL );
|
||||
RPI_PropertyAddTag( TAG_GET_MAX_CLOCK_RATE, TAG_CLOCK_ARM );
|
||||
RPI_PropertyProcess();
|
||||
|
||||
rpi_mailbox_property_t* mp;
|
||||
mp = RPI_PropertyGet( TAG_GET_BOARD_MODEL );
|
||||
|
||||
if( mp )
|
||||
printf( "Board Model: %d\r\n", mp->data.value_32 );
|
||||
else
|
||||
printf( "Board Model: NULL\r\n" );
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_BOARD_REVISION );
|
||||
|
||||
if( mp )
|
||||
printf( "Board Revision: %d\r\n", mp->data.value_32 );
|
||||
else
|
||||
printf( "Board Revision: NULL\r\n" );
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_FIRMWARE_VERSION );
|
||||
|
||||
if( mp )
|
||||
printf( "Firmware Version: %d\r\n", mp->data.value_32 );
|
||||
else
|
||||
printf( "Firmware Version: NULL\r\n" );
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_BOARD_MAC_ADDRESS );
|
||||
|
||||
if( mp )
|
||||
printf( "MAC Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\r\n",
|
||||
mp->data.buffer_8[0], mp->data.buffer_8[1], mp->data.buffer_8[2],
|
||||
mp->data.buffer_8[3], mp->data.buffer_8[4], mp->data.buffer_8[5] );
|
||||
else
|
||||
printf( "MAC Address: NULL\r\n" );
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_BOARD_SERIAL );
|
||||
|
||||
if( mp )
|
||||
printf( "Serial Number: %8.8X%8.8X\r\n",
|
||||
mp->data.buffer_32[0], mp->data.buffer_32[1] );
|
||||
else
|
||||
printf( "Serial Number: NULL\r\n" );
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_MAX_CLOCK_RATE );
|
||||
|
||||
if( mp )
|
||||
printf( "Maximum ARM Clock Rate: %dHz\r\n", mp->data.buffer_32[1] );
|
||||
else
|
||||
printf( "Maximum ARM Clock Rate: NULL\r\n" );
|
||||
|
||||
/* Ensure the ARM is running at it's maximum rate */
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_SET_CLOCK_RATE, TAG_CLOCK_ARM, mp->data.buffer_32[1] );
|
||||
RPI_PropertyProcess();
|
||||
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_GET_CLOCK_RATE, TAG_CLOCK_ARM );
|
||||
RPI_PropertyProcess();
|
||||
|
||||
mp = RPI_PropertyGet( TAG_GET_CLOCK_RATE );
|
||||
|
||||
if( mp )
|
||||
printf( "Set ARM Clock Rate: %dHz\r\n", mp->data.buffer_32[1] );
|
||||
else
|
||||
printf( "Set ARM Clock Rate: NULL\r\n" );
|
||||
|
||||
/* Initialise a framebuffer... */
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_ALLOCATE_BUFFER );
|
||||
RPI_PropertyAddTag( TAG_SET_PHYSICAL_SIZE, SCREEN_WIDTH, SCREEN_HEIGHT );
|
||||
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, SCREEN_WIDTH, SCREEN_HEIGHT * 2 );
|
||||
RPI_PropertyAddTag( TAG_SET_DEPTH, SCREEN_DEPTH );
|
||||
RPI_PropertyAddTag( TAG_GET_PITCH );
|
||||
RPI_PropertyAddTag( TAG_GET_PHYSICAL_SIZE );
|
||||
RPI_PropertyAddTag( TAG_GET_DEPTH );
|
||||
RPI_PropertyProcess();
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_GET_PHYSICAL_SIZE ) ) )
|
||||
{
|
||||
width = mp->data.buffer_32[0];
|
||||
height = mp->data.buffer_32[1];
|
||||
|
||||
printf( "Initialised Framebuffer: %dx%d ", width, height );
|
||||
}
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_GET_DEPTH ) ) )
|
||||
{
|
||||
bpp = mp->data.buffer_32[0];
|
||||
printf( "%dbpp\r\n", bpp );
|
||||
}
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_GET_PITCH ) ) )
|
||||
{
|
||||
pitch = mp->data.buffer_32[0];
|
||||
printf( "Pitch: %d bytes\r\n", pitch );
|
||||
}
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_ALLOCATE_BUFFER ) ) )
|
||||
{
|
||||
fb = (unsigned char*)mp->data.buffer_32[0];
|
||||
printf( "Framebuffer address: %8.8X\r\n", (unsigned int)fb );
|
||||
}
|
||||
|
||||
/* Never exit as there is no OS to exit to! */
|
||||
current_colour.r = 0x4B;
|
||||
current_colour.g = 0x00;
|
||||
current_colour.b = 0x82;
|
||||
current_colour.a = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
/* Produce a colour spread across the screen */
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
// current_colour.r += ( 1.0 / height );
|
||||
|
||||
for( x = 0; x < width; x++ )
|
||||
{
|
||||
pixel_offset = ( x * ( bpp >> 3 ) ) + ( y * pitch );
|
||||
|
||||
r = (int)( current_colour.r * 0xFF ) & 0xFF;
|
||||
g = (int)( current_colour.g * 0xFF ) & 0xFF;
|
||||
b = (int)( current_colour.b * 0xFF ) & 0xFF;
|
||||
a = (int)( current_colour.a * 0xFF ) & 0xFF;
|
||||
|
||||
|
||||
if( bpp == 32 )
|
||||
{
|
||||
/* Four bytes to write */
|
||||
fb[ pixel_offset++ ] = r;
|
||||
fb[ pixel_offset++ ] = g;
|
||||
fb[ pixel_offset++ ] = b;
|
||||
fb[ pixel_offset++ ] = a;
|
||||
}
|
||||
else if( bpp == 24 )
|
||||
{
|
||||
/* Three bytes to write */
|
||||
fb[ pixel_offset++ ] = r;
|
||||
fb[ pixel_offset++ ] = g;
|
||||
fb[ pixel_offset++ ] = b;
|
||||
}
|
||||
else if( bpp == 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! */
|
||||
}
|
||||
|
||||
// current_colour.b += ( 1.0 / width );
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll through the green colour */
|
||||
/*
|
||||
current_colour.g += cd;
|
||||
if( current_colour.g > 1.0 )
|
||||
{
|
||||
current_colour.g = 1.0;
|
||||
cd = -COLOUR_DELTA;
|
||||
}
|
||||
else if( current_colour.g < 0.0 )
|
||||
{
|
||||
current_colour.g = 0.0;
|
||||
cd = COLOUR_DELTA;
|
||||
}
|
||||
*/
|
||||
|
||||
frame_count++;
|
||||
if( calculate_frame_count )
|
||||
{
|
||||
calculate_frame_count = 0;
|
||||
|
||||
/* Number of frames in a minute, divided by seconds per minute */
|
||||
float fps = (float)frame_count / 60;
|
||||
printf( "FPS: %.2f\r\n", fps );
|
||||
|
||||
frame_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
# 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.
|
||||
|
||||
# A CMake toolchain file so we can cross-compile for the Rapsberry-Pi bare-metal
|
||||
|
||||
include(CMakeForceCompiler)
|
||||
|
||||
# usage
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-arm-none-eabi.cmake ../
|
||||
|
||||
# The Generic system name is used for embedded targets (targets without OS) in
|
||||
# CMake
|
||||
set( CMAKE_SYSTEM_NAME Generic )
|
||||
set( CMAKE_SYSTEM_PROCESSOR BCM2835 )
|
||||
|
||||
# Set a toolchain path. You only need to set this if the toolchain isn't in
|
||||
# your system path. Don't forget a trailing path separator!
|
||||
set( TC_PATH "" )
|
||||
|
||||
# The toolchain prefix for all toolchain executables
|
||||
set( CROSS_COMPILE arm-none-eabi- )
|
||||
|
||||
# specify the cross compiler. We force the compiler so that CMake doesn't
|
||||
# attempt to build a simple test program as this will fail without us using
|
||||
# the -nostartfiles option on the command line
|
||||
CMAKE_FORCE_C_COMPILER( ${TC_PATH}${CROSS_COMPILE}gcc GNU )
|
||||
|
||||
# We must set the OBJCOPY setting into cache so that it's available to the
|
||||
# whole project. Otherwise, this does not get set into the CACHE and therefore
|
||||
# the build doesn't know what the OBJCOPY filepath is
|
||||
set( CMAKE_OBJCOPY ${TC_PATH}${CROSS_COMPILE}objcopy
|
||||
CACHE FILEPATH "The toolchain objcopy command " FORCE )
|
||||
|
||||
# Set the CMAKE C flags (which should also be used by the assembler!
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfp" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv6zk" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mtune=arm1176jzf-s" )
|
||||
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
|
||||
set( CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
|
||||
|
||||
|
||||
Reference in new issue
Block a user