Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions ports/bare-rpi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
include ../../py/mkenv.mk

# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h

# include py core make definitions
include $(TOP)/py/py.mk

CROSS_COMPILE = arm-none-eabi-

OBJCPY=$(CROSS_COMPILE)objcopy
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)

CFLAGS = $(INC) -Wall -std=c99 -nostdlib -marm -mcpu=arm1176jzf-s $(COPT)

#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -ggdb
else
CFLAGS += -Os -DNDEBUG
endif

CCVERSION:=$(shell $(CC) --version | sed 's/[ ]/\n/g' | grep "\." | xargs | awk '{ print $$1 }')
ARMGCCLIBPATH=/usr/lib/gcc/arm-none-eabi/$(CCVERSION)

LDFLAGS = -nostdlib -T kernel.ld -Map=$@.map --cref
LIBS = -L$(ARMGCCLIBPATH) -lgcc

SRC_LIB = $(addprefix lib/,\
libc/string0.c )

SRC_C = \
main.c \
uart.c \
gpio.c \

SRC_S = \
start.s

OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(SRC_LIB:.c=.o))

all: $(BUILD)/firmware.img

list: $(BUILD)/firmware.elf
$(CROSS_COMPILE)objdump -d $(BUILD)/firmware.elf > $(BUILD)/firmware.list

$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(Q)$(SIZE) $@

$(BUILD)/firmware.img: $(BUILD)/firmware.elf
$(OBJCPY) $(BUILD)/firmware.elf -O binary $(BUILD)/firmware.img

include $(TOP)/py/mkrules.mk
120 changes: 120 additions & 0 deletions ports/bare-rpi/gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "gpio.h"

volatile pios_gpio_t* const pios_gpio = (volatile pios_gpio_t* const) (PIOS_IO_BASE + PIOS_GPIO_BASE);

void __attribute__((optimize("O0"))) wait ( int sec ) {
while ( sec > 0 ) {
int counter = 0x400000;
while ( counter > 0 )
counter--;
sec--;
}
}

void __attribute__((optimize("O1"))) pios_wasteCycles ( uint32_t cycles ) {
cycles++;
while ( cycles > 0 ) {
cycles--;
}
}

void pios_gpio_pullBulk ( uint32_t p[2], uint32_t pull ) {
if ( pull == PIOS_GPIO_PULL_UP ||
pull == PIOS_GPIO_PULL_DOWN ||
pull == PIOS_GPIO_PULL_OFF) {
pios_gpio->pullControlEnable = pull;
pios_wasteCycles ( 150 );

pios_gpio->pullControlClock[0] = p[0];
pios_gpio->pullControlClock[1] = p[1];
pios_wasteCycles ( 150 );

//pios_gpio->pullControlEnable = PIOS_GPIO_PULL_OFF;
pios_gpio->pullControlClock[0] = 0;
pios_gpio->pullControlClock[1] = 0;
}
else {
pios_gpio->pullControlEnable = PIOS_GPIO_PULL_OFF;
}
}

void pios_gpio_pullControl ( uint32_t pin, uint32_t pull ) {
if ( pin > 53 )
return;

uint32_t p[2]={0};
uint32_t i = 0;
if ( pin > 31 ) {
i++;
pin-=32;
}

p[i] = (1 << pin);

pios_gpio_pullBulk ( p, pull );
}

uint32_t pios_gpio_read ( uint32_t pin ) {
if ( pin > 53 )
return PIOS_GPIO_LOW;

volatile uint32_t* base = &pios_gpio->level[0];
if ( pin > 31 ) {
base++;
pin -= 32;
}

uint32_t val = *base;
return ( ((val & (1<<pin)) == 0) ? PIOS_GPIO_LOW : PIOS_GPIO_HIGH );
}

void pios_gpio_write ( uint32_t pin, uint32_t val ) {
if ( pin > 53 )
return;

volatile uint32_t* base = &pios_gpio->outputset[0];
if ( val == PIOS_GPIO_LOW ) {
base = &pios_gpio->outputclear[0];
}

if ( pin > 31 ) {
base++;
pin -= 32;
}
(*base) = 1 << pin;
}

void pios_gpio_pinmode ( uint32_t pin, uint32_t val ) {
if ( val > 7 )
return;

if ( pin > 53 )
return;

volatile uint32_t *base = &pios_gpio->fn_select[0];
while ( pin >= 10 ) {
base++;
pin-=10;
}

uint32_t v = *base;
v &= ~(7 << ((pin<<1) + pin)); /// move the 7 pin*3 times, so it masks the correct bits
v |= (val << ((pin<<1) + pin));
*base = v;
}

int pios_gpio_getPinmode ( uint32_t pin ) {
if ( pin > 53 )
return -1;

volatile uint32_t *base = &pios_gpio->fn_select[0];
while ( pin >= 10 ) {
base++;
pin-=10;
}

uint32_t v = *base;
v = v >> ((pin<<1)+pin) ;
v &= 7; /// move the 7 pin*3 times, so it masks the correct bits
return v;
}
124 changes: 124 additions & 0 deletions ports/bare-rpi/gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/**
* \file gpio.h
* \author Stefan Naumann
* \date 26th May 2017
* \brief interfaces for using the GPIO-connectors on the Raspberry Pi;
* memory map of the registers and some functions for using the basic-features
* of the GPIO-pins
**/

#ifndef PIOS_GPIO
#define PIOS_GPIO

#include <stdint.h>

#define PIOS_IO_BASE 0x20000000

/// the base offset address of the GPIO-registers in memory
#define PIOS_GPIO_BASE 0x200000

/// constant for the low-signal level of a pin
#define PIOS_GPIO_LOW 0
/// constant for the high-signal level of a pin
#define PIOS_GPIO_HIGH 1

/// the mode INPUT as constant
#define PIOS_GPIO_INPUT 0
/// the mode OUTPUT as constant
#define PIOS_GPIO_OUTPUT 1
/// alternative function 0
#define PIOS_GPIO_ALT0 4
/// alternative function 1
#define PIOS_GPIO_ALT1 5
/// alternative function 2
#define PIOS_GPIO_ALT2 6
/// alternative function 3
#define PIOS_GPIO_ALT3 7
/// alternative function 4
#define PIOS_GPIO_ALT4 3
/// alternative function 5
#define PIOS_GPIO_ALT5 2

/// pull the level up
#define PIOS_GPIO_PULL_UP 2
/// pull the level down
#define PIOS_GPIO_PULL_DOWN 1
/// turn the pulling off
#define PIOS_GPIO_PULL_OFF 0

/**
* \brief a mapping of the memory-registers of the GPIO-controller
**/
struct _pios_gpio_t {
uint32_t fn_select[6]; ///< function select registers for the Pins
uint32_t pad1;
uint32_t outputset[2]; ///< registers for setting the levels HIGH
uint32_t pad2;
uint32_t outputclear[2]; ///< registers for setting the levels LOW
uint32_t pad3;
uint32_t level[2]; ///< the levels of the pins for reading
uint32_t pad4;
uint32_t eventDetect[2]; ///< indicates whether an event has occured (whathever is enabled)
uint32_t pad5;
uint32_t risingEdgeDetect[2]; ///< en/disable rising edge for the eventDetect-field
uint32_t pad6;
uint32_t fallingEdgeDetect[2]; ///< en/disable falling edge for the eventDetect
uint32_t pad7;
uint32_t highDetect[2]; ///< en/disable HIGH as event for eventDetect
uint32_t pad8;
uint32_t lowDetect[2]; ///< en/disable LOW as event for eventDetect
uint32_t pad9;
uint32_t asyncRisingEdgeDetect[2]; ///< en/disable rising edge as asynchronous event for eventDetect (i.e. not bound to system clock)
uint32_t pad10;
uint32_t asyncFallingEdgeDetect[2]; ///< en/disable falling edge as asynchronous event for eventDetect (i.e. not bound to system clock)
uint32_t pad11;
uint32_t pullControlEnable; ///< set the pull-mode (i.e. UP, DOWN or OFF)
uint32_t pullControlClock[2]; ///< set pins for pulling (see the manual for the exact algorithm)
} typedef pios_gpio_t;

/// struct mapping the GPIO-controller-registers
extern volatile pios_gpio_t* const pios_gpio;

void __attribute__((optimize("O0"))) wait ( int sec );

/**
* \brief pull up or down a set of pins
* \param p an array which represents the GPIO-pins and their on-values for pulling
* \param pull the direction for the voltage-pull
* \note this is a lower-level implementation of the pios_gpio_pudControl-function, use that if unsure
**/
void pios_gpio_pullBulk ( uint32_t p[2], uint32_t pull );
/**
* \brief pull up or down a specific pin
* \param pin GPIO-Pin
* \param pull the direction for the voltage-pull
**/
void pios_gpio_pullControl ( uint32_t pin, uint32_t pull );
/**
* \brief reads the value of the GPIO-pin (set as input)
* \param pin the GPIO pin you want the state of (in [0, 53])
* \return the state of the GPIO-Pin (i.e. HIGH or LOW-signal level),
* always returns LOW if the input is invalid
**/
uint32_t pios_gpio_read ( uint32_t pin );
/**
* \brief writes a value to the GPIO-Pin (i.e. writes 1 to set or 1 to clear)
* \param pin GPIO-Pin
* \param val output-value (1 for on, 0 for off)
**/
void pios_gpio_write ( uint32_t pin, uint32_t val );
/**
* \brief sets the PIN into the mode we want
* \param pin GPIO-Pin
* \param val GPIO-Mode
* \return NONE
**/
void pios_gpio_pinmode ( uint32_t pin, uint32_t val );
/**
* \brief read the mode of the pin and return it
* \param pin the pin to be read
* \return the current mode of the pin
**/
int pios_gpio_getPinmode ( uint32_t pin );

#endif
14 changes: 14 additions & 0 deletions ports/bare-rpi/kernel.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
SECTIONS {
. = 0x8000;
.init . : { *(.init) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000;
heap_start = .;
. = . + 0x800000;
heap_end = .;
. = . + 0x800000;
stack_top = .;
}
79 changes: 79 additions & 0 deletions ports/bare-rpi/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/mperrno.h"
#include "py/gc.h"

#include "uart.h"
#include "gpio.h"

extern char heap_end, heap_start;

void do_str(const char *src, mp_parse_input_kind_t input_kind) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
qstr source_name = lex->source_name;
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true);
mp_call_function_0(module_fun);
nlr_pop();
} else {
// uncaught exception
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
}

int main(int argc, char **argv) {
pios_uart_init();
pios_uart_puts ("Hello World!\n\r");

gc_init ( &heap_start, &heap_end );

mp_init();
do_str("print('Hello World')", MP_PARSE_FILE_INPUT);
do_str("i = 0\nwhile ( i < 10 ) :\n print ( i );\n i=i+1\n", MP_PARSE_FILE_INPUT);

mp_deinit();
return 0;
}

void gc_collect(void) {
}

void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
pios_uart_write ( str, len );
}


mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
mp_raise_OSError(MP_ENOENT);
}

mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_NO_EXIST;
}

mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);

void nlr_jump_fail(void *val) {
while (1);
}

void NORETURN __fatal_error(const char *msg) {
while (1);
}

#ifndef NDEBUG
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("Assertion failed");
}
#endif
Loading