Multiple platform support

This commit is contained in:
Romain Goyet
2015-08-03 21:04:13 +02:00
parent 6e602c514b
commit 067c53d705
51 changed files with 268 additions and 119 deletions

View File

@@ -1,35 +1,16 @@
TOOLCHAIN=arm-none-eabi
COMPILER=llvm
ifeq ($(COMPILER),llvm)
CC=clang
CXX=clang++
else
CC=$(TOOLCHAIN)-gcc
CXX=$(TOOLCHAIN)-g++
PLATFORM ?= stm32f429
#PLATFORM=simulator
include Makefile.$(PLATFORM)
ifndef USE_LIBA
$(error Makefile.PLATFORM should define USE_LIBA)
endif
LD=$(TOOLCHAIN)-ld.bfd
GDB=$(TOOLCHAIN)-gdb
OBJCOPY=$(TOOLCHAIN)-objcopy
# Compiler flags
# Note: We're using CFLAGS, CXXFLAGS, and SFLAGS. SFLAGS are shared flags for both C and C++
# Flags - Arch
ifeq ($(COMPILER),llvm)
SFLAGS += -target thumbv7em-unknown-eabi
else
SFLAGS += -mthumb -march=armv7e-m -mfloat-abi=softfp
endif
SFLAGS += -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
SFLAGS += -DUSE_LIBA=$(USE_LIBA)
# Flags - Header search path
SFLAGS += -Ilib -I.
#-Iexternal/freertos/include -Iexternal -Iexternal/freertos/portable/GCC/ARM_CM4F -Iexternal/newlib/libc/include
# Flags - Building options
SFLAGS += -Wall -ffreestanding -nostdinc
SFLAGS += -Wall
# Flags - Optimizations
ifeq ($(PRODUCTION),1)
@@ -42,7 +23,7 @@ endif
# Language-specific flags
CFLAGS = -std=c99
CXXFLAGS = -std=c++11 -fno-exceptions -fno-unwind-tables -fno-rtti -nostdlib
CXXFLAGS = -std=c++11 -fno-exceptions -fno-unwind-tables -fno-rtti
products := boot.elf boot.hex boot.bin
@@ -51,17 +32,41 @@ products := boot.elf boot.hex boot.bin
lib/private/mem5.o: CFLAGS += -w
objs += src/hello.o
#objs += src/hello.o
.PHONY: default info
default: info clean boot.elf
default: clean boot.elf
ifeq ($(VERBOSE),1)
info:
@echo "========= BUILD SETTINGS ======"
@echo "PLATFORM = $(PLATFORM)"
@echo "CC = $(CC)"
@echo "CXX = $(CXX)"
@echo "LD = $(LD)"
@echo "CFLAGS = $(CFLAGS)"
@echo "CXXFLAGS = $(CXXFLAGS)"
@echo "SFLAGS = $(SFLAGS)"
@echo "LDFLAGS = $(LDFLAGS)"
@echo "==============================="
else
info:
endif
include boot/Makefile
ifeq ($(USE_LIBA),0)
LDFLAGS += -lc -lc++ -lcrt1.o
else
SFLAGS += -ffreestanding -nostdinc -nostdlib
include liba/Makefile
include libaxx/Makefile
include platform/Makefile
endif
include ion/Makefile
include kandinsky/Makefile
include poincare/Makefile
objs += src/hello.o
run: boot.elf
$(GDB) -x gdb_script.gdb boot.elf
@@ -81,7 +86,7 @@ boot.bin: boot.elf
boot.elf: $(objs)
@echo "LD $@"
@$(LD) -T platform/stm32f429/boot/flash.ld $(objs) -o $@
@$(LD) $(LDFLAGS) $(objs) -o $@
%.o: %.c
@echo "CC $@"

7
Makefile.simulator Normal file
View File

@@ -0,0 +1,7 @@
CC=clang
CXX=clang++
LD=ld
#GDB=gdb
#OBJCOPY=$(TOOLCHAIN)-objcopy
USE_LIBA=0

27
Makefile.stm32f429 Normal file
View File

@@ -0,0 +1,27 @@
TOOLCHAIN=arm-none-eabi
COMPILER=llvm
ifeq ($(COMPILER),llvm)
CC=clang
CXX=clang++
else
CC=$(TOOLCHAIN)-gcc
CXX=$(TOOLCHAIN)-g++
endif
LD=$(TOOLCHAIN)-ld.bfd
GDB=$(TOOLCHAIN)-gdb
OBJCOPY=$(TOOLCHAIN)-objcopy
# Flags - Arch
ifeq ($(COMPILER),llvm)
SFLAGS += -target thumbv7em-unknown-eabi
else
SFLAGS += -mthumb -march=armv7e-m -mfloat-abi=softfp
endif
SFLAGS += -mcpu=cortex-m4 -mfpu=fpv4-sp-d16
LDFLAGS += -T boot/stm32f429/flash.ld
# Platform configuration
USE_LIBA=1

2
boot/Makefile Normal file
View File

@@ -0,0 +1,2 @@
objs += boot/boot.o
include boot/$(PLATFORM)/Makefile

3
boot/README.txt Normal file
View File

@@ -0,0 +1,3 @@
Boot
Code in boot is responsible for creating an executable that can be started on the PLATFORM.

20
boot/boot.c Normal file
View File

@@ -0,0 +1,20 @@
#if USE_LIBA
#include <liba.h>
#endif
#if USE_ION
#include <ion.h>
#endif
#include <src/hello.h>
void boot() {
#if USE_LIBA
liba_init();
#endif
#if USE_ION
ion_ini();
#endif
hello();
}

6
boot/boot.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef PLATFORM_PLATFORM_H
#define PLATFORM_PLATFORM_H
void boot();
#endif

1
boot/simulator/Makefile Normal file
View File

@@ -0,0 +1 @@
objs += $(addprefix boot/simulator/, main.o)

5
boot/simulator/main.c Normal file
View File

@@ -0,0 +1,5 @@
#include <boot/boot.h>
int main(int argc, char * argv[]) {
boot();
}

1
boot/stm32f429/Makefile Normal file
View File

@@ -0,0 +1 @@
objs += $(addprefix boot/stm32f429/, isr.o crt0.o)

View File

@@ -1,5 +1,6 @@
#include <stdint.h>
#include <string.h>
#include <boot/boot.h>
extern char _data_section_start_flash;
extern char _data_section_start_ram;
@@ -7,8 +8,6 @@ extern char _data_section_end_ram;
extern char _bss_section_start_ram;
extern char _bss_section_end_ram;
void init();
void abort() {
// TODO: #ifdef NDEBUG, maybe trigger a reset?
while (1) {
@@ -32,7 +31,7 @@ void _start(void) {
size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram);
memset(&_bss_section_start_ram, 0, bssSectionLength);
init();
boot();
abort();
}

View File

@@ -144,9 +144,9 @@ SECTIONS {
} >SRAM
.ccm_heap : {
_ccm_heap_start = .;
_liba_heap_start = .;
. += LENGTH(CCM);
_ccm_heap_end = .;
_liba_heap_end = .;
} >CCM
.ccm_stack : {

3
ion/Makefile Normal file
View File

@@ -0,0 +1,3 @@
SFLAGS += -Iion/include -DKD_CONFIG_H=1
include ion/src/platform/$(PLATFORM)/Makefile
objs += $(addprefix ion/src/, ion.o)

3
ion/README.txt Normal file
View File

@@ -0,0 +1,3 @@
ION is the hardware abstraction layer. It does I/O.
It exposes a set of headers that are implemented for various hardwares (device, simulator)

18
ion/include/ion.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef ION_ION_H
#define ION_ION_H
#include <stdint.h>
void ion_init();
void ion_display_on();
void ion_display_off();
extern void * ion_framebuffer_address;
extern uint16_t ion_framebuffer_width;
extern uint16_t ion_framebuffer_height;
extern uint8_t ion_framebuffer_bits_per_pixel;
char ion_getchar();
#endif

View File

@@ -0,0 +1,3 @@
#include <ion.h>
#define KD_FRAMEBUFFER_ADDRESS ion_framebuffer_address
#define KD_FRAMEBUFFER_WIDTH ion_framebuffer_width

6
ion/src/ion.c Normal file
View File

@@ -0,0 +1,6 @@
#include <ion.h>
void * ion_framebuffer_address = 0;
uint16_t ion_framebuffer_width = 0;
uint16_t ion_framebuffer_height = 0;
uint8_t ion_framebuffer_bits_per_pixel = 0;

View File

@@ -0,0 +1,2 @@
objs += $(addprefix ion/src/platform/simulator/, init.o)
#objs += $(addprefix ion/src/drivers/, ili9341/ili9341.o fx92kbd/fx92kbd.o)

View File

@@ -0,0 +1,4 @@
#include <ion.h>
void ion_init() {
}

View File

@@ -0,0 +1,2 @@
objs += $(addprefix ion/src/platform/stm32f429/, platform.o init.o display.o init_kbd.o)
objs += $(addprefix ion/src/drivers/, ili9341/ili9341.o fx92kbd/fx92kbd.o)

View File

@@ -14,7 +14,7 @@
* SCL | PF7 | SPI clock
* SDI/SDO | PF9 | SPI data
*
* The entry point is init_lcd();
* The entry point is init_display();
*
* Some info regarding the built-in LCD panel of the STM32F429I Discovery:
* -> The pin EXTC of the ili9341 is not connected to Vdd. It reads as "0", and
@@ -25,39 +25,32 @@
* It doesn't seem right though, because some extended commands do work...
*/
#include <assert.h>
#include "registers.h"
#include <platform/platform.h>
#include <platform/ili9341/ili9341.h>
#include <ion.h>
#include "platform.h"
#include "registers/registers.h"
#include <ion/src/drivers/ili9341/ili9341.h>
extern char _framebuffer_start;
extern char _framebuffer_end;
void ion_display_on() {
}
void ion_display_off() {
}
static void init_spi_interface();
static void init_rgb_interface();
static void init_panel();
static void check_framebuffer();
void init_lcd() {
void init_display() {
/* This routine is responsible for initializing the LCD panel.
* Its interface with the outer world is the framebuffer: after execution of
* this routine, everyone can expect to write to the LCD by writing to the
* framebuffer. */
Platform.framebuffer_width = 240;
Platform.framebuffer_height = 320;
Platform.framebuffer_bits_per_pixel = 8;
Platform.framebuffer_address = &_framebuffer_start;
init_spi_interface();
init_rgb_interface();
init_panel();
#ifndef NDEBUG
check_framebuffer();
#endif
}
// SPI interface
@@ -190,11 +183,11 @@ static void init_rgb_timings() {
// seems to match our hardware. Here are the values of interest:
int lcd_panel_hsync = 10;
int lcd_panel_hbp = 20;
int lcd_panel_hadr = Platform.framebuffer_width;
int lcd_panel_hadr = ion_framebuffer_width;
int lcd_panel_hfp = 10;
int lcd_panel_vsync = 2;
int lcd_panel_vbp = 2;
int lcd_panel_vadr = Platform.framebuffer_height;
int lcd_panel_vadr = ion_framebuffer_height;
int lcd_panel_vfp = 4;
// The LCD-TFT programmable synchronous timings are:
@@ -275,13 +268,13 @@ static void init_rgb_layers() {
LTDC_LPFCR(LTDC_LAYER1) = LTDC_PF_L8;
LTDC_LCFBAR(LTDC_LAYER1) = (uint32_t)Platform.framebuffer_address;
LTDC_LCFBAR(LTDC_LAYER1) = (uint32_t)ion_framebuffer_address;
LTDC_LCFBLR(LTDC_LAYER1) =
LTDC_CFBLL(Platform.framebuffer_width + 3) | // Number of bytes per lines in the framebuffer. 240 * 4 (RGBA888). +3, per doc;
LTDC_CFBP(Platform.framebuffer_width); // Width of a line in bytes
LTDC_CFBLL(ion_framebuffer_width + 3) | // Number of bytes per lines in the framebuffer. 240 * 4 (RGBA888). +3, per doc;
LTDC_CFBP(ion_framebuffer_width); // Width of a line in bytes
LTDC_LCFBLNR(LTDC_LAYER1) = LTDC_CFBLNR(Platform.framebuffer_height); // Number of lines
LTDC_LCFBLNR(LTDC_LAYER1) = LTDC_CFBLNR(ion_framebuffer_height); // Number of lines
// STEP 8 : Enable layer 1
// Don't enable color keying nor color look-up table
@@ -304,11 +297,10 @@ static void gpio_c2_write(bool pin_state);
static void gpio_d13_write(bool pin_state);
static void init_panel() {
ili9341_t * panel = &(Platform.display);
panel->chip_select_pin_write = gpio_c2_write;
panel->data_command_pin_write = gpio_d13_write;
panel->spi_write = spi_5_write;
ili9341_initialize(panel);
Platform.display.chip_select_pin_write = gpio_c2_write;
Platform.display.data_command_pin_write = gpio_d13_write;
Platform.display.spi_write = spi_5_write;
ili9341_initialize(&(Platform.display));
}
static void spi_5_write(char * data, size_t size) {
@@ -330,11 +322,3 @@ void gpio_c2_write(bool pin_state) {
void gpio_d13_write(bool pin_state) {
REGISTER_SET_VALUE(GPIO_ODR(GPIOD), ODR(13), pin_state);
}
// Framebuffer checks
static void check_framebuffer() {
assert(&_framebuffer_start == Platform.framebuffer_address);
char * fb_end = &_framebuffer_start + (Platform.framebuffer_width*Platform.framebuffer_height*Platform.framebuffer_bits_per_pixel/8);
assert(&_framebuffer_end == fb_end);
}

View File

@@ -0,0 +1 @@
void init_display();

View File

@@ -0,0 +1,21 @@
#include <ion.h>
#include "display.h"
#include "init_kbd.h"
extern char _framebuffer_start;
extern char _framebuffer_end;
void ion_init() {
ion_framebuffer_address = &_framebuffer_start;
ion_framebuffer_width = 240;
ion_framebuffer_height = 320;
ion_framebuffer_bits_per_pixel = 8;
#if DEBUG
char * computed_framebuffer_end = ion_framebuffer_address + (ion_framebuffer_width*ion_framebuffer_height*ion_framebuffer_bits_per_pixel)/8;
assert(&_framebuffer_end == computed_framebuffer_end);
#endif
init_kbd();
init_display();
}

View File

@@ -8,10 +8,11 @@
#include <assert.h>
#include <stdint.h>
#include "registers.h"
#include <stdlib.h>
#include "platform.h"
#include "registers/registers.h"
#include "init_kbd.h"
#include <platform/fx92kbd/fx92kbd.h>
#include <platform/platform.h>
#include <ion/src/drivers/fx92kbd/fx92kbd.h>
// The row pins are driven high or low in software.
static gpio_pin_t row_pins[] = {
@@ -141,7 +142,7 @@ char charFromKey[] = {
' ', // FX92_KEY_NONE = 0,
};
char getc() {
char ion_getchar() {
char character = ' ';
while (character == ' ') {
fx92kbd_key_t key = fx92kbd_getkey(&Platform.keyboard);

View File

@@ -0,0 +1,9 @@
#include <ion/src/drivers/ili9341/ili9341.h>
#include <ion/src/drivers/fx92kbd/fx92kbd.h>
typedef struct {
ili9341_t display;
fx92kbd_t keyboard;
} platform_t;
extern platform_t Platform;

View File

@@ -10,10 +10,10 @@
#define BIT_MASK(high, low) ((((uint32_t)1<<((high)-(low)+1))-1)<<(low))
#define BIT_VALUE(value, high, low) (((value)<<(low))&BIT_MASK(high, low))
#include "registers/rcc.h"
#include "registers/gpio.h"
#include "registers/spi.h"
#include "registers/ltdc.h"
#include "rcc.h"
#include "gpio.h"
#include "spi.h"
#include "ltdc.h"
#define REGISTER_FIELD_MASK(field) (BIT_MASK(HIGH_BIT_##field,LOW_BIT_##field))
#define REGISTER_FIELD_VALUE(field, value) (BIT_VALUE(value,HIGH_BIT_##field,LOW_BIT_##field))

View File

@@ -1,10 +1,28 @@
#ifndef KANDINSKY_CONFIG_H
#define KANDINSKY_CONFIG_H
#ifdef KD_CONFIG_H
#include "kandinsky_config.h"
#endif
#ifndef KD_FRAMEBUFFER_ADDRESS
#error Kandinsky expects KD_FRAMEBUFFER_ADDRESS to be defined to the start of the framebuffer
#endif
#ifndef KD_FRAMEBUFFER_WIDTH
#error Kandinsky expects KD_FRAMEBUFFER_WIDTH to be defined to the width of the framebuffer
#endif
// FIXME: #define this
typedef uint8_t KDColor;
/*
#include <platform/platform.h>
#define KD_FRAMEBUFFER_ADDRESS Platform.framebuffer_address
#define KD_FRAMEBUFFER_WIDTH Platform.framebuffer_width
typedef uint8_t KDColor;
*/
#endif

View File

@@ -2,4 +2,4 @@ SFLAGS += -Iliba/include
liba/src/external/sqlite/mem5.o: CFLAGS += -w
objs += $(addprefix liba/src/, assert.o errno.o malloc.o memcpy.o memset.o strlen.o external/sqlite/mem5.o)
objs += $(addprefix liba/src/, assert.o errno.o liba.o malloc.o memcpy.o memset.o strlen.o external/sqlite/mem5.o)

View File

@@ -1,5 +1,7 @@
liba is an adhoc libc.
Warning: you must call "liba_init()" before using liba.
We need a very small subset of the functionality provided by the standard C
library. We could use an available libc implementation, but those are usually
way to large and may have problematic licenses.

6
liba/include/liba.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef LIBA_LIBA_H
#define LIBA_LIBA_H
void liba_init();
#endif

23
liba/src/liba.c Normal file
View File

@@ -0,0 +1,23 @@
#include <liba.h>
#include <private/memconfig.h>
int memsys5Init(void *NotUsed);
heap_config_t HeapConfig;
extern char _liba_heap_start;
extern char _liba_heap_end;
static void liba_init_heap() {
HeapConfig.nHeap = (&_liba_heap_end - &_liba_heap_start);
HeapConfig.pHeap = &_liba_heap_start;
HeapConfig.mnReq = 1;
HeapConfig.bMemstat = 0;
HeapConfig.xLog = 0;
memsys5Init(0);
}
void liba_init() {
liba_init_heap();
}

View File

@@ -1,6 +1,8 @@
#include <stdlib.h>
#include <string.h>
#include <private/memconfig.h>
// Memsys headers cannot be included easily so we rewrite them here
void memsys5FreeUnsafe(void *pOld);
void * memsys5MallocUnsafe(int nByte);
void * memsys5Realloc(void *pPrior, int nBytes);

View File

@@ -1,4 +0,0 @@
objs += platform/platform.o
objs += $(addprefix platform/stm32f429/, boot/isr.o boot/crt0.o init.o init_lcd.o init_heap.o init_kbd.o)
objs += platform/ili9341/ili9341.o
objs += platform/fx92kbd/fx92kbd.o

View File

@@ -1,18 +0,0 @@
#ifndef PLATFORM_H
#define PLATFORM_H
#include <platform/fx92kbd/fx92kbd.h>
#include <platform/ili9341/ili9341.h>
typedef struct {
int framebuffer_width;
int framebuffer_height;
int framebuffer_bits_per_pixel;
char * framebuffer_address;
fx92kbd_t keyboard;
ili9341_t display;
} platform_t;
extern platform_t Platform;
#endif

View File

@@ -1,11 +0,0 @@
#include "init_lcd.h"
#include "init_heap.h"
#include "init_kbd.h"
#include <src/hello.h>
void init() {
init_kbd();
init_lcd();
init_heap();
hello();
}

View File

@@ -1 +0,0 @@
void init_lcd();

View File

@@ -2,12 +2,11 @@ extern "C" {
#include "hello.h"
#include <kandinsky.h>
#include <stdlib.h>
#include <platform/stm32f429/init_kbd.h>
#include <ion.h>
}
#include <poincare.h>
void hello() {
/*char letter = 'Z';
@@ -62,7 +61,7 @@ void hello() {
int index = 0;
while (1) {
char character = getc();
char character = ion_getchar();
if (character == 'X') {
input[index] = 0;
index = 0;