From e5ae7f10f3e144f4a08ee7a66b4105a5aa86e6e7 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 4 Jan 2018 11:47:43 -0500 Subject: initrd, lcd, file cleanup --- Makefile | 54 +++-- README.md | 4 +- clock.c | 62 ------ heap.c | 38 ---- include/gpio.h | 45 ++++ include/initrd.h | 23 ++ include/lcd.h | 14 ++ initrd/test.txt | 1 + initrd/two.bin | 3 + lib/liblua.a | Bin 0 -> 172446 bytes link.ld | 13 +- main.c | 75 ------- mkinitrd.sh | 4 + src/clock.c | 62 ++++++ src/gpio.c | 44 ++++ src/heap.c | 38 ++++ src/initrd.c | 90 ++++++++ src/lcd.c | 117 +++++++++++ src/main.c | 56 +++++ src/startup_stm32l476xx.s | 524 ++++++++++++++++++++++++++++++++++++++++++++++ src/stdlib.c | 17 ++ src/stm32l4xx_it.c | 34 +++ src/system_stm32l4xx.c | 44 ++++ src/task.c | 108 ++++++++++ startup_stm32l476xx.s | 524 ---------------------------------------------- stm32l4xx_it.c | 32 --- system_stm32l4xx.c | 44 ---- task.c | 108 ---------- 28 files changed, 1271 insertions(+), 907 deletions(-) delete mode 100644 clock.c delete mode 100644 heap.c create mode 100644 include/gpio.h create mode 100644 include/initrd.h create mode 100644 include/lcd.h create mode 100644 initrd/test.txt create mode 100644 initrd/two.bin create mode 100644 lib/liblua.a delete mode 100644 main.c create mode 100755 mkinitrd.sh create mode 100644 src/clock.c create mode 100644 src/gpio.c create mode 100644 src/heap.c create mode 100644 src/initrd.c create mode 100644 src/lcd.c create mode 100644 src/main.c create mode 100644 src/startup_stm32l476xx.s create mode 100644 src/stdlib.c create mode 100644 src/stm32l4xx_it.c create mode 100644 src/system_stm32l4xx.c create mode 100644 src/task.c delete mode 100644 startup_stm32l476xx.s delete mode 100644 stm32l4xx_it.c delete mode 100644 system_stm32l4xx.c delete mode 100644 task.c diff --git a/Makefile b/Makefile index 48175ff..87dd3a0 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,44 @@ +CROSS = arm-none-eabi- +CC = gcc +AS = as +AR = ar +OBJCOPY = objcopy + MCUFLAGS = -mthumb -mcpu=cortex-m4 -CFLAGS = -Iinclude $(MCUFLAGS) - -all: - arm-none-eabi-as $(MCUFLAGS) startup_stm32l476xx.s -c -o out/startup_stm32l476xx.o - arm-none-eabi-gcc $(CFLAGS) system_stm32l4xx.c -c -o out/system_stm32l4xx.o - arm-none-eabi-gcc $(CFLAGS) stm32l4xx_it.c -c -o out/stm32l4xx_it.o - arm-none-eabi-gcc $(CFLAGS) clock.c -c -o out/clock.o - arm-none-eabi-gcc $(CFLAGS) heap.c -c -o out/heap.o - arm-none-eabi-gcc $(CFLAGS) task.c -c -o out/task.o - arm-none-eabi-gcc $(CFLAGS) main.c -c -o out/main.o - arm-none-eabi-gcc $(CFLAGS) -T link.ld out/*.o -o out/main.elf - arm-none-eabi-objcopy -O ihex out/main.elf main.hex +AFLAGS = $(MCUFLAGS) +CFLAGS = $(MCUFLAGS) -Iinclude -ffreestanding -Wall -Werror -Wextra +OFLAGS = -O ihex + +CFILES = $(wildcard src/*.c) +AFILES = $(wildcard src/*.s) + +OUTDIR = out +OFILES = $(patsubst src/%.c, $(OUTDIR)/%.o, $(CFILES)) \ + $(patsubst src/%.s, $(OUTDIR)/%.asm.o, $(AFILES)) + +LIBDIR = -Llib +LIBS = -llua + +HEX = main.hex + +all: $(HEX) + +$(HEX): $(OFILES) + @echo " LINK " $(HEX) + @$(CROSS)$(OBJCOPY) -B arm -I binary -O elf32-littlearm initrd.img out/initrd.img.o + @$(CROSS)$(CC) $(CFLAGS) $(LIBDIR) $(LIBS) -T link.ld out/*.o -o out/main.elf + @$(CROSS)$(OBJCOPY) $(OFLAGS) out/main.elf $(HEX) + +$(OUTDIR)/%.o: src/%.c + @echo " CC " $< + @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@ + +$(OUTDIR)/%.asm.o: src/%.s + @echo " AS " $< + @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@ clean: - rm -rf out/* + @echo " CLEAN" + @rm -rf out/* + + diff --git a/README.md b/README.md index 56c56fd..f2e4a04 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,6 @@ Required packages: * openocd * make -Use run.sh to upload the final output to the processor. +Use ```run.sh``` to upload the final output to the processor. + +To make an initrd, add files to ```initrd/``` and then run ```./mkinitrd.sh```. diff --git a/clock.c b/clock.c deleted file mode 100644 index ab92386..0000000 --- a/clock.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -#define STK_CTRL *((uint32_t *)0xE000E010) -#define STK_LOAD *((uint32_t *)0xE000E014) -#define STK_VAL *((uint32_t *)0xE000E018) -#define STK_CALIB *((uint32_t *)0xE000E01C) - -// ticks since init -static uint32_t ticks = 0; - -void clock_init(void) -{ - // turn on HSI (16MHz) - RCC->CR |= RCC_CR_HSION; - while ((RCC->CR & RCC_CR_HSIRDY) != RCC_CR_HSIRDY); - - // get PLLR to 80MHz (max) - // VCO = C * (N/M) -> 16 * (10/1) = 160 - // SCLK = VCO / R = 160 / 2 = 80 MHz - RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLSRC); - RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSI; - RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLM); - RCC->PLLCFGR |= 10 << RCC_PLLCFGR_PLLN_Pos; - RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLR); // /2 - RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN; // PLLR on - - // start PLL - RCC->CR |= RCC_CR_PLLON; - while ((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY); - - // set system clock to PLL - RCC->CFGR &= ~(RCC_CFGR_SW); - RCC->CFGR |= RCC_CFGR_SW_PLL; - while ((RCC->CFGR & RCC_CFGR_SWS_PLL) != RCC_CFGR_SWS_PLL); - - // SysTick init. 80MHz / 80000 = 1kHz, ms precision - STK_LOAD = 80000; - STK_CTRL |= 0x07; // no div, interrupt, enable -} - -void delay(uint32_t count) -{ - uint32_t target = ticks + count; - while (ticks < target); -} - -__attribute__ ((naked)) -void SysTick_Handler(void) -{ - uint32_t lr; - asm("mov %0, lr" : "=r" (lr)); - - // just keep counting - ticks++; - - if (!(ticks % 10)) - SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; - - asm("mov lr, %0; bx lr" :: "r" (lr)); -} - diff --git a/heap.c b/heap.c deleted file mode 100644 index 0433a1f..0000000 --- a/heap.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -#define RAM_END 0x20018000 - -//extern void *end; -//extern uint32_t _total_ram; -static uint32_t offset = 0; - -__attribute__ ((section(".data"))) -uint8_t heap[8192]; -void *end = heap; - -void heap_init(void) -{ - // what to do... -} - -uint32_t heap_available(void) -{ - return 0;// return _total_ram - offset; -} - -void *hmalloc(uint32_t size) -{ - void *alloc = end + offset; - offset += size; - return alloc; -} - -void *hcalloc(uint32_t count, uint32_t size) -{ - uint32_t total = count * size; - void *alloc = hmalloc(total); - for (uint32_t i = 0; i < total; i++) - ((uint8_t *)alloc)[i] = 0; - return alloc; -} diff --git a/include/gpio.h b/include/gpio.h new file mode 100644 index 0000000..25b32fe --- /dev/null +++ b/include/gpio.h @@ -0,0 +1,45 @@ +#ifndef GPIO_H_ +#define GPIO_H_ + +#include + +#define GPIO_PORT(p, b) GPIO##p, b + +enum GPIO_MODE +{ + INPUT = 0, + OUTPUT, + ALTERNATE, + ANALOG +}; + +enum GPIO_TYPE +{ + PUSHPULL = 0, + OPENDRAIN +}; + +enum GPIO_SPEED +{ + LOW = 0, + MEDIUM, + HIGH, + VERYHIGH +}; + +enum GPIO_PUPD +{ + NOPUPD, + PULLUP, + PULLDOWN +}; + +void gpio_init(void); + +void gpio_pupd(GPIO_TypeDef *port, uint8_t pin, uint8_t pupd); +void gpio_type(GPIO_TypeDef *port, uint8_t pin, uint8_t type); +void gpio_mode(GPIO_TypeDef *port, uint8_t pin, uint8_t mode); +void gpio_dout(GPIO_TypeDef *port, uint8_t pin, uint8_t val); +uint8_t gpio_din(GPIO_TypeDef *port, uint8_t pin); + +#endif // GPIO_H_ diff --git a/include/initrd.h b/include/initrd.h new file mode 100644 index 0000000..9c7a9de --- /dev/null +++ b/include/initrd.h @@ -0,0 +1,23 @@ +#ifndef INITRD_H_ +#define INITRD_H_ + +#include + +typedef struct +{ + char signature[8]; +} __attribute__ ((packed)) initrd_header; + +typedef struct +{ + char name[16]; + uint8_t unused[32]; + char size[10]; + char sig[2]; +} __attribute__ ((packed)) initrd_file; + +uint8_t initrd_validate(void); +char *initrd_getfile(const char *name); +uint32_t initrd_getfilesize(const char *name); + +#endif // INITRD_H_ diff --git a/include/lcd.h b/include/lcd.h new file mode 100644 index 0000000..0962e08 --- /dev/null +++ b/include/lcd.h @@ -0,0 +1,14 @@ +#ifndef LCD_H_ +#define LCD_H_ + +#include + +void lcd_init(void); + +void lcd_puts(const char *s); +void lcd_puti(int i); +void lcd_puth(int h); +void lcd_putb(uint8_t b); +void lcd_clear(void); + +#endif // LCD_H_ diff --git a/initrd/test.txt b/initrd/test.txt new file mode 100644 index 0000000..af5626b --- /dev/null +++ b/initrd/test.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/initrd/two.bin b/initrd/two.bin new file mode 100644 index 0000000..b3f1928 --- /dev/null +++ b/initrd/two.bin @@ -0,0 +1,3 @@ +print "yay" + +yesyesye diff --git a/lib/liblua.a b/lib/liblua.a new file mode 100644 index 0000000..d5a4c6b Binary files /dev/null and b/lib/liblua.a differ diff --git a/link.ld b/link.ld index 8877898..13e5cca 100644 --- a/link.ld +++ b/link.ld @@ -35,9 +35,6 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20018000; /* end of RAM */ -_Min_Stack_Size = 0x0400; /* 1k min. stack */ -_Min_Heap_Size = 0x0400; /* 1k min. heap */ - /* Specify the memory areas */ MEMORY { @@ -82,14 +79,14 @@ SECTIONS . = ALIGN(8); } >FLASH - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH - .preinit_array : + .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) @@ -146,10 +143,7 @@ SECTIONS ._user_heap_stack : { . = ALIGN(4); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; + *(._user_heap_stack) . = ALIGN(4); } >RAM @@ -166,4 +160,3 @@ SECTIONS .ARM.attributes 0 : { *(.ARM.attributes) } } -_total_ram = _estack - _end; diff --git a/main.c b/main.c deleted file mode 100644 index 9a95465..0000000 --- a/main.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - -/** - * Accomplishments: - * - GPIO in/out - * - got to 80MHz clock - * - basic heap - * - multitask, can exit - */ - -void pulse(uint8_t byte); -void kmain(void); - -int main(void) -{ - asm("cpsid i"); - - // prepare flash latency for 40MHz operation - FLASH->ACR &= ~(FLASH_ACR_LATENCY); - FLASH->ACR |= FLASH_ACR_LATENCY_4WS; - - RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; // A clk enable - GPIOA->MODER &= ~(GPIO_MODER_MODE5 | GPIO_MODER_MODE6); // A5 -> output, A0 input - GPIOA->MODER |= GPIO_MODER_MODE5_0 | GPIO_MODER_MODE6_0; - GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD5 | GPIO_PUPDR_PUPD6); - GPIOA->PUPDR |= GPIO_PUPDR_PUPD5_0 | GPIO_PUPDR_PUPD6_0; // pulldown for button (1) - //if (GPIOA->IDR & 0x01) - - clock_init(); - task_init(kmain); - - while (1); -} - -void task(void); -void kmain(void) -{ - asm("cpsie i"); - - task_start(task, 1024); - while (1) { - GPIOA->BSRR |= 1 << 6; - delay(500); - GPIOA->BRR |= 1 << 6; - delay(500); - } -} - -void task(void) -{ - while (1) { - GPIOA->BSRR |= 1 << 5; - delay(200); - GPIOA->BRR |= 1 << 5; - delay(200); - } -} - - -void _exit(int code) -{ for (;;); } - -void pulse(uint8_t byte) -{ - int8_t i = 7; - do { - GPIOA->BSRR |= 1 << 5; - delay((byte & (1 << i)) ? 400 : 100); - GPIOA->BRR |= 1 << 5; - delay((byte & (1 << i)) ? 100 : 400); - } while (--i >= 0); -} diff --git a/mkinitrd.sh b/mkinitrd.sh new file mode 100755 index 0000000..eb47fd8 --- /dev/null +++ b/mkinitrd.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo "Making initrd.img..." +rm -f initrd.img +arm-none-eabi-ar r initrd.img initrd/* diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..ab92386 --- /dev/null +++ b/src/clock.c @@ -0,0 +1,62 @@ +#include +#include + +#define STK_CTRL *((uint32_t *)0xE000E010) +#define STK_LOAD *((uint32_t *)0xE000E014) +#define STK_VAL *((uint32_t *)0xE000E018) +#define STK_CALIB *((uint32_t *)0xE000E01C) + +// ticks since init +static uint32_t ticks = 0; + +void clock_init(void) +{ + // turn on HSI (16MHz) + RCC->CR |= RCC_CR_HSION; + while ((RCC->CR & RCC_CR_HSIRDY) != RCC_CR_HSIRDY); + + // get PLLR to 80MHz (max) + // VCO = C * (N/M) -> 16 * (10/1) = 160 + // SCLK = VCO / R = 160 / 2 = 80 MHz + RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLSRC); + RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSI; + RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLM); + RCC->PLLCFGR |= 10 << RCC_PLLCFGR_PLLN_Pos; + RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLR); // /2 + RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN; // PLLR on + + // start PLL + RCC->CR |= RCC_CR_PLLON; + while ((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY); + + // set system clock to PLL + RCC->CFGR &= ~(RCC_CFGR_SW); + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS_PLL) != RCC_CFGR_SWS_PLL); + + // SysTick init. 80MHz / 80000 = 1kHz, ms precision + STK_LOAD = 80000; + STK_CTRL |= 0x07; // no div, interrupt, enable +} + +void delay(uint32_t count) +{ + uint32_t target = ticks + count; + while (ticks < target); +} + +__attribute__ ((naked)) +void SysTick_Handler(void) +{ + uint32_t lr; + asm("mov %0, lr" : "=r" (lr)); + + // just keep counting + ticks++; + + if (!(ticks % 10)) + SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; + + asm("mov lr, %0; bx lr" :: "r" (lr)); +} + diff --git a/src/gpio.c b/src/gpio.c new file mode 100644 index 0000000..c2617ee --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,44 @@ +#include + +void gpio_init(void) +{ + // enable clocks + RCC->AHB2ENR |= 0xFF; +} + +void gpio_pupd(GPIO_TypeDef *port, uint8_t pin, uint8_t pupd) +{ + port->PUPDR &= ~(0x03 << (2 * pin)); + port->PUPDR |= pupd << (2 * pin); +} + +void gpio_speed(GPIO_TypeDef *port, uint8_t pin, uint8_t speed) +{ + port->OSPEEDR &= ~(0x03 << (2 * pin)); + port->OSPEEDR |= speed << (2 * pin); +} + +void gpio_type(GPIO_TypeDef *port, uint8_t pin, uint8_t type) +{ + port->OTYPER &= ~(1 << pin); + port->OTYPER |= type << pin; +} + +void gpio_mode(GPIO_TypeDef *port, uint8_t pin, uint8_t mode) +{ + port->MODER &= ~(0x03 << (2 * pin)); + port->MODER |= mode << (2 * pin); +} + +void gpio_dout(GPIO_TypeDef *port, uint8_t pin, uint8_t val) +{ + if (val) + port->BSRR |= (1 << pin); + else + port->BRR |= (1 << pin); +} + +uint8_t gpio_din(GPIO_TypeDef *port, uint8_t pin) +{ + return port->IDR & (1 << pin); +} diff --git a/src/heap.c b/src/heap.c new file mode 100644 index 0000000..1eba901 --- /dev/null +++ b/src/heap.c @@ -0,0 +1,38 @@ +#include +#include + +#define RAM_END 0x20018000 + +#define HEAP_SIZE (16 * 1024) + +static uint32_t offset = 0; + +__attribute__ ((section("._user_heap_stack"))) +uint8_t heap[HEAP_SIZE]; +void *end = heap; + +void heap_init(void) +{ + // what to do... +} + +uint32_t heap_available(void) +{ + return HEAP_SIZE - offset; +} + +void *hmalloc(uint32_t size) +{ + void *alloc = end + offset; + offset += size; + return alloc; +} + +void *hcalloc(uint32_t count, uint32_t size) +{ + uint32_t total = count * size; + void *alloc = hmalloc(total); + for (uint32_t i = 0; i < total; i++) + ((uint8_t *)alloc)[i] = 0; + return alloc; +} diff --git a/src/initrd.c b/src/initrd.c new file mode 100644 index 0000000..7b68c40 --- /dev/null +++ b/src/initrd.c @@ -0,0 +1,90 @@ +#include + +extern uint8_t _binary_initrd_img_start[]; +extern uint8_t _binary_initrd_img_size[]; + +static const void *initrd_start = (void *)_binary_initrd_img_start; +static const uint32_t initrd_size = (uint32_t)_binary_initrd_img_size; + +static const char *initrd_sig = "!\n"; + +uint8_t initrd_validate(void) +{ + initrd_header *header = (initrd_header *)initrd_start; + for (uint8_t i = 0; i < 8; i++) { + if (header->signature[i] != initrd_sig[i]) + return 0; + } + + return 1; +} + +uint8_t initrd_nametest(char *file, const char *want) +{ + for (uint8_t i = 0; i < 16; i++) { + if (want[i] == '\0') + return (file[i] == '/'); + else if (want[i] != file[i]) + return 0; + } + + return 0; +} + +uint32_t pow10(uint8_t n) +{ + uint32_t i = 1; + while (n--) + i *= 10; + return i; +} + +uint32_t initrd_getsize(initrd_file *file) +{ + uint32_t size = 0; + char *p = file->size + 10; + while (*--p == ' '); + + for (int8_t i = p - file->size, j = 0; i >= 0; i--, j++) + size += (*p-- - '0') * pow10(j); + + return size; +} + +initrd_file *initrd_getfileptr(const char *name) +{ + initrd_file *file = (initrd_file *)(initrd_start + sizeof(initrd_header)); + uint32_t offset = sizeof(initrd_header); + + while (offset < initrd_size) { + if (initrd_nametest(file->name, name)) + return file; + uint32_t size = initrd_getsize(file) + sizeof(initrd_file); + offset += size; + file += size; + } + + return 0; +} + +char *initrd_getfile(const char *name) +{ + initrd_file *file = initrd_getfileptr(name); + if (file == 0) + return 0; + + + char *ptr = (char *)((void *)file + sizeof(initrd_file)); + ptr[initrd_getsize(file) - 1] = 0; + return ptr; +} + +uint32_t initrd_getfilesize(const char *name) +{ + initrd_file *file = initrd_getfileptr(name); + if (file == 0) + return 0; + + return initrd_getsize(file); +} + diff --git a/src/lcd.c b/src/lcd.c new file mode 100644 index 0000000..ca1c1a6 --- /dev/null +++ b/src/lcd.c @@ -0,0 +1,117 @@ +#include +#include +#include + +#define LCD_D0 GPIO_PORT(A, 0) +#define LCD_D1 GPIO_PORT(A, 1) +#define LCD_D2 GPIO_PORT(A, 4) +#define LCD_D3 GPIO_PORT(B, 0) +#define LCD_D4 GPIO_PORT(C, 1) +#define LCD_D5 GPIO_PORT(C, 0) +#define LCD_D6 GPIO_PORT(C, 2) +#define LCD_D7 GPIO_PORT(C, 3) +#define LCD_E GPIO_PORT(C, 12) +#define LCD_RS GPIO_PORT(C, 10) + +#define lcd_data() gpio_dout(LCD_RS, 1) + +void lcd_pulse(void) +{ + gpio_dout(LCD_E, 1); + delay(1); + gpio_dout(LCD_E, 0); +} + +void lcd_byte(uint8_t byte) +{ + gpio_dout(LCD_D0, byte & 0x01); + gpio_dout(LCD_D1, byte & 0x02); + gpio_dout(LCD_D2, byte & 0x04); + gpio_dout(LCD_D3, byte & 0x08); + gpio_dout(LCD_D4, byte & 0x10); + gpio_dout(LCD_D5, byte & 0x20); + gpio_dout(LCD_D6, byte & 0x40); + gpio_dout(LCD_D7, byte & 0x80); +} + +void lcd_cmd(uint8_t cmd) +{ + gpio_dout(LCD_RS, 0); + lcd_byte(cmd); + lcd_pulse(); +} + +void lcd_putchar(int c) +{ + lcd_data(); + lcd_byte((uint8_t)c); + lcd_pulse(); +} + +static int lcd_index = 0; +void lcd_puts(const char *s) +{ + lcd_cmd(0x06); + while (*s) { + lcd_putchar(*s++); + if (++lcd_index == 0x10) { + lcd_cmd(0x80 | 0x40); + } else if (lcd_index == 0x20) { + lcd_cmd(0x80); + lcd_index = 0; + } + } +} + +extern char *itoa(int n, int base); +void lcd_puti(int i) +{ + lcd_puts(itoa(i, 10)); +} + +void lcd_puth(int h) +{ + lcd_puts(itoa(h, 16)); +} + +void lcd_putb(uint8_t b) +{ + lcd_puts(itoa(b, 2)); +} + +void lcd_clear(void) +{ + lcd_cmd(0x01); + delay(2); + lcd_index = 0; +} + +void lcd_init(void) +{ + gpio_mode(LCD_D0, OUTPUT); + gpio_mode(LCD_D1, OUTPUT); + gpio_mode(LCD_D2, OUTPUT); + gpio_mode(LCD_D3, OUTPUT); + gpio_mode(LCD_D4, OUTPUT); + gpio_mode(LCD_D5, OUTPUT); + gpio_mode(LCD_D6, OUTPUT); + gpio_mode(LCD_D7, OUTPUT); + gpio_mode(LCD_E, OUTPUT); + gpio_mode(LCD_RS, OUTPUT); + gpio_dout(LCD_D0, 0); + gpio_dout(LCD_D1, 0); + gpio_dout(LCD_D2, 0); + gpio_dout(LCD_D3, 0); + gpio_dout(LCD_D4, 0); + gpio_dout(LCD_D5, 0); + gpio_dout(LCD_D6, 0); + gpio_dout(LCD_D7, 0); + gpio_dout(LCD_E, 0); + gpio_dout(LCD_RS, 0); + + lcd_cmd(0x38); + lcd_cmd(0x10); + lcd_cmd(0x0D); + delay(5); + lcd_clear(); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e71e712 --- /dev/null +++ b/src/main.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + * Accomplishments: + * - GPIO in/out + * - got to 80MHz clock + * - basic heap + * - multitask, can exit + * - gpio lib + * - lcd support + * - initrd support + * - lua? + */ + +void pulse(uint8_t byte); +void kmain(void); + +int main(void) +{ + asm("cpsid i"); + + // prepare flash latency for 40MHz operation + FLASH->ACR &= ~(FLASH_ACR_LATENCY); + FLASH->ACR |= FLASH_ACR_LATENCY_4WS; + + //MPU->CTRL |= MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk; + clock_init(); + gpio_init(); + + gpio_mode(GPIOA, 5, OUTPUT); + + task_init(kmain); + + while (1); +} + +void task(void); +void kmain(void) +{ + asm("cpsie i"); + + lcd_init(); + + char *s = initrd_getfile("test.txt"); + lcd_puts(s); + + while (1) + delay(100); +} + diff --git a/src/startup_stm32l476xx.s b/src/startup_stm32l476xx.s new file mode 100644 index 0000000..57b11cb --- /dev/null +++ b/src/startup_stm32l476xx.s @@ -0,0 +1,524 @@ +/** + ****************************************************************************** + * @file startup_stm32l476xx.s + * @author MCD Application Team + * @brief STM32L476xx devices vector table GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address, + * - Configure the clock system + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * 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. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +//.equ BootRAM, 0xF1E0F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* Atollic update: set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex-M4. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_PVM_IRQHandler + .word TAMP_STAMP_IRQHandler + .word RTC_WKUP_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word CAN1_TX_IRQHandler + .word CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_TIM15_IRQHandler + .word TIM1_UP_TIM16_IRQHandler + .word TIM1_TRG_COM_TIM17_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word DFSDM1_FLT3_IRQHandler + .word TIM8_BRK_IRQHandler + .word TIM8_UP_IRQHandler + .word TIM8_TRG_COM_IRQHandler + .word TIM8_CC_IRQHandler + .word ADC3_IRQHandler + .word FMC_IRQHandler + .word SDMMC1_IRQHandler + .word TIM5_IRQHandler + .word SPI3_IRQHandler + .word UART4_IRQHandler + .word UART5_IRQHandler + .word TIM6_DAC_IRQHandler + .word TIM7_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_IRQHandler + .word DMA2_Channel5_IRQHandler + .word DFSDM1_FLT0_IRQHandler + .word DFSDM1_FLT1_IRQHandler + .word DFSDM1_FLT2_IRQHandler + .word COMP_IRQHandler + .word LPTIM1_IRQHandler + .word LPTIM2_IRQHandler + .word OTG_FS_IRQHandler + .word DMA2_Channel6_IRQHandler + .word DMA2_Channel7_IRQHandler + .word LPUART1_IRQHandler + .word QUADSPI_IRQHandler + .word I2C3_EV_IRQHandler + .word I2C3_ER_IRQHandler + .word SAI1_IRQHandler + .word SAI2_IRQHandler + .word SWPMI1_IRQHandler + .word TSC_IRQHandler + .word LCD_IRQHandler + .word 0 + .word RNG_IRQHandler + .word FPU_IRQHandler + + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_PVM_IRQHandler + .thumb_set PVD_PVM_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM15_IRQHandler + .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM16_IRQHandler + .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM17_IRQHandler + .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak DFSDM1_FLT3_IRQHandler + .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler + + .weak TIM8_BRK_IRQHandler + .thumb_set TIM8_BRK_IRQHandler,Default_Handler + + .weak TIM8_UP_IRQHandler + .thumb_set TIM8_UP_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_IRQHandler + .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak DFSDM1_FLT2_IRQHandler + .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler + + .weak COMP_IRQHandler + .thumb_set COMP_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak SAI2_IRQHandler + .thumb_set SAI2_IRQHandler,Default_Handler + + .weak SWPMI1_IRQHandler + .thumb_set SWPMI1_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak LCD_IRQHandler + .thumb_set LCD_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/stdlib.c b/src/stdlib.c new file mode 100644 index 0000000..e7bf622 --- /dev/null +++ b/src/stdlib.c @@ -0,0 +1,17 @@ +#include + +void _exit(int code) +{ + (void)code; + for (;;); +} + +char *itoa(int n, int base) +{ + static char buf[16]; + char *p = buf + 15; + *p = '\0'; + do *--p = "0123456789ABCDEF"[n % base]; + while (n /= base); + return p; +} diff --git a/src/stm32l4xx_it.c b/src/stm32l4xx_it.c new file mode 100644 index 0000000..2aac023 --- /dev/null +++ b/src/stm32l4xx_it.c @@ -0,0 +1,34 @@ +#include + +void NMI_Handler(void) {} + +void HardFault_Handler(void) +{ + GPIOA->BSRR |= (1 << 5) | (1 << 6); + while (1); +} + +void MemManage_Handler(void) +{ + GPIOA->BSRR |= (1 << 5) | (1 << 6); + while (1); +} + +void BusFault_Handler(void) +{ + GPIOA->BSRR |= (1 << 5) | (1 << 6); + while (1); +} + +void UsageFault_Handler(void) +{ + GPIOA->BSRR |= (1 << 5) | (1 << 6); + while (1); +} + +void SVC_Handler(void) { + +} + +void DebugMon_Handler(void) {} + diff --git a/src/system_stm32l4xx.c b/src/system_stm32l4xx.c new file mode 100644 index 0000000..4c22bfe --- /dev/null +++ b/src/system_stm32l4xx.c @@ -0,0 +1,44 @@ +#include "stm32l476xx.h" + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set MSION bit */ + RCC->CR |= RCC_CR_MSION; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000U; + + /* Reset HSEON, CSSON , HSION, and PLLON bits */ + RCC->CR &= 0xEAF6FFFFU; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x00001000U; + + /* Reset HSEBYP bit */ + RCC->CR &= 0xFFFBFFFFU; + + /* Disable all interrupts */ + RCC->CIER = 0x00000000U; + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + diff --git a/src/task.c b/src/task.c new file mode 100644 index 0000000..a34988a --- /dev/null +++ b/src/task.c @@ -0,0 +1,108 @@ +#include +#include +#include + +typedef struct { + uint32_t *sp; + uint8_t use; + uint32_t *stack; + void (*code)(void); +} task_t; + +#define MAX_TASKS 4 + +static task_t tasks[MAX_TASKS]; +static volatile int next_idx = 0; + +static uint8_t task_enable = 0; + +void task_init(void (*init)(void)) +{ + for (int i = 0; i < MAX_TASKS; i++) + tasks[i].use = 0; + + task_start(init, 1024); + asm("\ + msr psp, %0; \ + mrs r0, control; \ + orr r0, r0, #3; \ + msr control, r0; \ + isb; \ + " :: "r" (tasks[0].sp)); + + task_enable = 1; + init(); +} + +extern void _exit(int); +void task_exit(void) +{ + // TODO free stack? + asm("cpsid i"); // hope to catch next_idx + tasks[next_idx].use = 0; + asm("cpsie i"); + while (1); // bye +} + +void task_start(void (*task)(void), uint16_t stackSize) +{ + asm("cpsid i"); // just to be safe + + for (int i = 0; i < MAX_TASKS; i++) { + if (tasks[i].use == 0) { + tasks[i].stack = hmalloc(stackSize); + tasks[i].sp = tasks[i].stack + stackSize - 16; + tasks[i].sp[13] = (uint32_t)task_exit; + tasks[i].sp[14] = (uint32_t)task; + tasks[i].sp[15] = 0x01000000; + tasks[i].use = 1; + tasks[i].code = task; + asm("cpsie i"); + return; + } + } + + // TODO handle error +} + +__attribute__ ((naked)) +void PendSV_Handler(void) +{ + if (task_enable == 0) + asm("bx lr"); + + // save state + asm("\ + cpsid i; \ + isb; \ + dsb; \ + mrs r0, psp; \ + stmdb r0!, {r4-r11}; \ + mov %0, r0; \ + " : "=r" (tasks[next_idx].sp)); + + // find next task (round-robin style) + do { + if (++next_idx == MAX_TASKS) { + next_idx = 0; + break; // task 0 better exist + } + } while (tasks[next_idx].use == 0); + + // restore + asm("\ + mov r0, %0; \ + ldmia r0!, {r4-r11}; \ + msr psp, r0; \ + isb; \ + dsb; \ + " :: "r" (tasks[next_idx].sp)); + + // end + asm("\ + mov r0, #0xFFFFFFFD; \ + cpsie i; \ + bx r0; \ + "); +} + diff --git a/startup_stm32l476xx.s b/startup_stm32l476xx.s deleted file mode 100644 index 57b11cb..0000000 --- a/startup_stm32l476xx.s +++ /dev/null @@ -1,524 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32l476xx.s - * @author MCD Application Team - * @brief STM32L476xx devices vector table GCC toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address, - * - Configure the clock system - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * 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. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss - -//.equ BootRAM, 0xF1E0F85F -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* Atollic update: set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - -LoopForever: - b LoopForever - -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * - * @param None - * @retval : None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex-M4. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler - .word PVD_PVM_IRQHandler - .word TAMP_STAMP_IRQHandler - .word RTC_WKUP_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_2_IRQHandler - .word CAN1_TX_IRQHandler - .word CAN1_RX0_IRQHandler - .word CAN1_RX1_IRQHandler - .word CAN1_SCE_IRQHandler - .word EXTI9_5_IRQHandler - .word TIM1_BRK_TIM15_IRQHandler - .word TIM1_UP_TIM16_IRQHandler - .word TIM1_TRG_COM_TIM17_IRQHandler - .word TIM1_CC_IRQHandler - .word TIM2_IRQHandler - .word TIM3_IRQHandler - .word TIM4_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C2_EV_IRQHandler - .word I2C2_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word USART2_IRQHandler - .word USART3_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word DFSDM1_FLT3_IRQHandler - .word TIM8_BRK_IRQHandler - .word TIM8_UP_IRQHandler - .word TIM8_TRG_COM_IRQHandler - .word TIM8_CC_IRQHandler - .word ADC3_IRQHandler - .word FMC_IRQHandler - .word SDMMC1_IRQHandler - .word TIM5_IRQHandler - .word SPI3_IRQHandler - .word UART4_IRQHandler - .word UART5_IRQHandler - .word TIM6_DAC_IRQHandler - .word TIM7_IRQHandler - .word DMA2_Channel1_IRQHandler - .word DMA2_Channel2_IRQHandler - .word DMA2_Channel3_IRQHandler - .word DMA2_Channel4_IRQHandler - .word DMA2_Channel5_IRQHandler - .word DFSDM1_FLT0_IRQHandler - .word DFSDM1_FLT1_IRQHandler - .word DFSDM1_FLT2_IRQHandler - .word COMP_IRQHandler - .word LPTIM1_IRQHandler - .word LPTIM2_IRQHandler - .word OTG_FS_IRQHandler - .word DMA2_Channel6_IRQHandler - .word DMA2_Channel7_IRQHandler - .word LPUART1_IRQHandler - .word QUADSPI_IRQHandler - .word I2C3_EV_IRQHandler - .word I2C3_ER_IRQHandler - .word SAI1_IRQHandler - .word SAI2_IRQHandler - .word SWPMI1_IRQHandler - .word TSC_IRQHandler - .word LCD_IRQHandler - .word 0 - .word RNG_IRQHandler - .word FPU_IRQHandler - - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_PVM_IRQHandler - .thumb_set PVD_PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM15_IRQHandler - .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM16_IRQHandler - .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM17_IRQHandler - .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak DFSDM1_FLT3_IRQHandler - .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler - - .weak TIM8_BRK_IRQHandler - .thumb_set TIM8_BRK_IRQHandler,Default_Handler - - .weak TIM8_UP_IRQHandler - .thumb_set TIM8_UP_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_IRQHandler - .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak ADC3_IRQHandler - .thumb_set ADC3_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - - .weak DFSDM1_FLT0_IRQHandler - .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler - - .weak DFSDM1_FLT1_IRQHandler - .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler - - .weak DFSDM1_FLT2_IRQHandler - .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler - - .weak COMP_IRQHandler - .thumb_set COMP_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - - .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak SWPMI1_IRQHandler - .thumb_set SWPMI1_IRQHandler,Default_Handler - - .weak TSC_IRQHandler - .thumb_set TSC_IRQHandler,Default_Handler - - .weak LCD_IRQHandler - .thumb_set LCD_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32l4xx_it.c b/stm32l4xx_it.c deleted file mode 100644 index dc6dc16..0000000 --- a/stm32l4xx_it.c +++ /dev/null @@ -1,32 +0,0 @@ -#include - -void NMI_Handler(void) {} - -void HardFault_Handler(void) -{ - GPIOA->BSRR |= (1 << 5) | (1 << 6); - while (1); -} - -void MemManage_Handler(void) -{ - GPIOA->BSRR |= (1 << 5) | (1 << 6); - while (1); -} - -void BusFault_Handler(void) -{ - GPIOA->BSRR |= (1 << 5) | (1 << 6); - while (1); -} - -void UsageFault_Handler(void) -{ - GPIOA->BSRR |= (1 << 5) | (1 << 6); - while (1); -} - -void SVC_Handler(void) {} - -void DebugMon_Handler(void) {} - diff --git a/system_stm32l4xx.c b/system_stm32l4xx.c deleted file mode 100644 index 4c22bfe..0000000 --- a/system_stm32l4xx.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "stm32l476xx.h" - -/************************* Miscellaneous Configuration ************************/ -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -void SystemInit(void) -{ - /* FPU settings ------------------------------------------------------------*/ - #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif - - /* Reset the RCC clock configuration to the default reset state ------------*/ - /* Set MSION bit */ - RCC->CR |= RCC_CR_MSION; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000U; - - /* Reset HSEON, CSSON , HSION, and PLLON bits */ - RCC->CR &= 0xEAF6FFFFU; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = 0x00001000U; - - /* Reset HSEBYP bit */ - RCC->CR &= 0xFFFBFFFFU; - - /* Disable all interrupts */ - RCC->CIER = 0x00000000U; - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - diff --git a/task.c b/task.c deleted file mode 100644 index b77d4f5..0000000 --- a/task.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include - -typedef struct { - uint32_t *sp; - uint8_t use; - uint32_t *stack; - void (*code)(void); -} task_t; - -#define MAX_TASKS 4 - -static task_t tasks[MAX_TASKS]; -static int next_idx = 0; - -void task_init(void (*init)(void)) -{ - for (int i = 0; i < MAX_TASKS; i++) - tasks[i].use = 0; - - task_start(init, 1024); - asm("\ - msr psp, %0; \ - mrs r0, control; \ - orr r0, r0, #2; \ - msr control, r0; \ - isb; \ - " :: "r" (tasks[0].sp)); - - init(); - - // force switch to tasking, call pendsv - //SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; -} - -extern void _exit(int); -void task_exit(void) -{ - // TODO free stack? - asm("cpsid i"); // hope to catch next_idx - tasks[next_idx].use = 0; - asm("cpsie i"); - while (1); // bye - //_exit(0); -} - -void task_start(void (*task)(void), uint16_t stackSize) -{ - asm("cpsid i"); // just to be safe - - for (int i = 0; i < MAX_TASKS; i++) { - if (tasks[i].use == 0) { - tasks[i].stack = hmalloc(stackSize); - tasks[i].sp = tasks[i].stack + stackSize - 16; - tasks[i].sp[13] = (uint32_t)task_exit; - tasks[i].sp[14] = (uint32_t)task; - tasks[i].sp[15] = 0x01000000; - tasks[i].use = 1; - tasks[i].code = task; - asm("cpsie i"); - return; - } - } - - // TODO handle error -} - -__attribute__ ((naked)) -void PendSV_Handler(void) -{ - // save state - //stmdb r0!, {r4-r11}; - asm("\ - cpsid i; \ - isb; \ - dsb; \ - mrs r0, psp; \ - stmdb r0!, {r4-r11}; \ - mov %0, r0; \ - " : "=r" (tasks[next_idx].sp)); - - // find next task (round-robin style) - do { - if (++next_idx == MAX_TASKS) { - next_idx = 0; - break; // task 0 better exist - } - } while (tasks[next_idx].use == 0); - - // restore - //ldmia r0!, {r4-r11}; - asm("\ - mov r0, %0; \ - ldmia r0!, {r4-r11}; \ - msr psp, r0; \ - isb; \ - dsb; \ - " :: "r" (tasks[next_idx].sp)); - - // end - asm("\ - mov r0, #0xFFFFFFFD; \ - cpsie i; \ - bx r0; \ - "); -} - -- cgit v1.2.3