From 0a1e9969a2739035737caebced7df571728ef621 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski <q3k@q3k.org> Date: Sun, 28 Jul 2019 16:35:29 +0200 Subject: [PATCH] l0dables: after review --- l0dables/blinky/meson.build | 2 +- l0dables/lib/crt.s | 51 +++++++++++++++++++------------------ l0dables/lib/hardware.c | 30 ++++++++++++++++------ l0dables/lib/meson.build | 2 +- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/l0dables/blinky/meson.build b/l0dables/blinky/meson.build index 9a2fdb4c..9a5c199d 100644 --- a/l0dables/blinky/meson.build +++ b/l0dables/blinky/meson.build @@ -4,7 +4,7 @@ elf = executable( name + '.elf', 'main.c', build_by_default: true, - dependencies: [l0dable_startup, api_caller, periphdriver], + dependencies: [l0dable_startup, api_caller], link_whole: [l0dable_startup_lib], link_args: [ '-Wl,-Map=' + meson.current_build_dir() + '/' + name + '.map', diff --git a/l0dables/lib/crt.s b/l0dables/lib/crt.s index be63692f..b811c4e6 100644 --- a/l0dables/lib/crt.s +++ b/l0dables/lib/crt.s @@ -4,9 +4,10 @@ * Also known as a startup file. * * We provide the following to l0dables: - * - a 8k stack. * - calling GCC initializers. * - an ISR vector. + * + * The stack is provided by l0der. */ .syntax unified @@ -39,11 +40,11 @@ __isr_vector: .long 0 /* Reserved */ .long PendSV_Handler /* PendSV Handler */ .long SysTick_Handler /* SysTick Handler */ - + /* Device-specific Interrupts */ .long PF_IRQHandler /* 0x10 0x0040 16: Power Fail */ .long WDT0_IRQHandler /* 0x11 0x0044 17: Watchdog 0 */ - .long USB_IRQHandler /* 0x12 0x0048 18: USB */ + .long DefaultHandler /* 0x12 0x0048 18: USB, used by core0, unoverridable */ .long RTC_IRQHandler /* 0x13 0x004C 19: RTC */ .long TRNG_IRQHandler /* 0x14 0x0050 20: True Random Number Generator */ .long TMR0_IRQHandler /* 0x15 0x0054 21: Timer 0 */ @@ -55,7 +56,7 @@ __isr_vector: .long RSV11_IRQHandler /* 0x1B 0x006C 27: Reserved */ .long RSV12_IRQHandler /* 0x1C 0x0070 28: Reserved */ .long I2C0_IRQHandler /* 0x1D 0x0074 29: I2C0 */ - .long UART0_IRQHandler /* 0x1E 0x0078 30: UART 0 */ + .long DefaultHandler /* 0x1E 0x0078 30: UART 0, used by core0, unoverridable */ .long UART1_IRQHandler /* 0x1F 0x007C 31: UART 1 */ .long SPI1_IRQHandler /* 0x20 0x0080 32: SPI1 */ .long SPI2_IRQHandler /* 0x21 0x0084 33: SPI2 */ @@ -65,8 +66,8 @@ __isr_vector: .long RSV21_IRQHandler /* 0x25 0x0094 37: Reserved */ .long RSV22_IRQHandler /* 0x26 0x0098 38: Reserved */ .long FLC0_IRQHandler /* 0x27 0x009C 39: Flash Controller */ - .long GPIO0_IRQHandler /* 0x28 0x00A0 40: GPIO0 */ - .long GPIO1_IRQHandler /* 0x29 0x00A4 41: GPIO2 */ + .long DefaultHandler /* 0x28 0x00A0 40: GPIO0, used by core0, unoverridable */ + .long DefaultHandler /* 0x29 0x00A4 41: GPIO2, used by core0, unoverridable */ .long RSV26_IRQHandler /* 0x2A 0x00A8 42: GPIO3 */ .long TPU_IRQHandler /* 0x2B 0x00AC 43: Crypto */ .long DMA0_IRQHandler /* 0x2C 0x00B0 44: DMA0 */ @@ -133,7 +134,7 @@ __isr_vector: .long RSV89_IRQHandler /* 0x69 0x01A4 105: UART 4 */ .long RSV90_IRQHandler /* 0x6A 0x01A8 106: UART 5 */ .long RSV91_IRQHandler /* 0x6B 0x01AC 107: Camera IF */ - .long RSV92_IRQHandler /* 0x6C 0x01B0 108: I3C */ + .long RSV92_IRQHandler /* 0x6C 0x01B0 108: I3C */ .long HTMR0_IRQHandler /* 0x6D 0x01B4 109: HTmr */ .long HTMR1_IRQHandler /* 0x6E 0x01B8 109: HTmr */ @@ -157,27 +158,33 @@ Reset_Handler: blx r0 /* - * Spin forever. + * C code done, spin forever. * TODO(q3k): let epicardium know we're done. */ .spin: bl .spin + /* + * Used by __libc_init_array. + */ .globl _init _init: bx lr - /* Macro to define default handlers. Default handler - * will be weak symbol and just dead loops. They can be - * overwritten by other handlers. */ - .macro def_irq_handler handler_name - .align 1 + /* + * The default handler for all IRQs just spins forwever. + * TODO(q3k): let epicardium know we've reached an infinite loop due to + * an exception and/or unhandled IRQ, perhaps by splitting + * DefaultHandler into multiple handlers that report different + * error conditions to epicardium (eg. unhandled IRQ, fault, ...) + */ .thumb_func - .weak \handler_name - .type \handler_name, %function -\handler_name : - b . - .size \handler_name, . - \handler_name + .type DefaultHandler, %function +DefaultHandler: + b . + + .macro def_irq_handler handler_name + .weakref \handler_name, DefaultHandler .endm /* @@ -191,11 +198,9 @@ _init: def_irq_handler SVC_Handler def_irq_handler DebugMon_Handler def_irq_handler PendSV_Handler - def_irq_handler Default_Handler def_irq_handler PF_IRQHandler def_irq_handler WDT0_IRQHandler - def_irq_handler USB_IRQHandler def_irq_handler RTC_IRQHandler def_irq_handler TRNG_IRQHandler def_irq_handler TMR0_IRQHandler @@ -203,11 +208,9 @@ _init: def_irq_handler TMR2_IRQHandler def_irq_handler TMR3_IRQHandler def_irq_handler TMR4_IRQHandler - def_irq_handler TMR5_IRQHandler def_irq_handler RSV11_IRQHandler def_irq_handler RSV12_IRQHandler def_irq_handler I2C0_IRQHandler - def_irq_handler UART0_IRQHandler def_irq_handler UART1_IRQHandler def_irq_handler SPI1_IRQHandler def_irq_handler SPI2_IRQHandler @@ -217,8 +220,6 @@ _init: def_irq_handler RSV21_IRQHandler def_irq_handler RSV22_IRQHandler def_irq_handler FLC0_IRQHandler - def_irq_handler GPIO0_IRQHandler - def_irq_handler GPIO1_IRQHandler def_irq_handler RSV26_IRQHandler def_irq_handler TPU_IRQHandler def_irq_handler DMA0_IRQHandler @@ -291,4 +292,4 @@ _init: .section .cinterp .asciz "card10-l0dable" - .byte + .byte diff --git a/l0dables/lib/hardware.c b/l0dables/lib/hardware.c index e9325a1c..33233843 100644 --- a/l0dables/lib/hardware.c +++ b/l0dables/lib/hardware.c @@ -18,7 +18,7 @@ #include "icc_regs.h" #include "pwrseq_regs.h" -uint32_t SystemCoreClock = HIRC_FREQ >> 1; +uint32_t SystemCoreClock = HIRC_FREQ >> 1; void SystemCoreClockUpdate(void) { @@ -79,10 +79,8 @@ __weak void SystemInit() { // newlib syscall to allow printf to work. long _write(int fd, const char *buf, size_t cnt) { - /* - * Only print one line at a time. Insert `\r` between lines so - * they are properly displayed on the serial console. - */ + // Only print one line at a time. Insert `\r` between lines so + // they are properly displayed on the serial console. size_t i, last = 0; for (i = 0; i < cnt; i++) { if (buf[i] == '\n') { @@ -91,9 +89,7 @@ long _write(int fd, const char *buf, size_t cnt) last = i; } } - if (last != i) { - epic_uart_write_str(&buf[last], cnt - last); - } + epic_uart_write_str(&buf[last], cnt - last); return cnt; } @@ -106,6 +102,24 @@ uint32_t _sbrk(int incr) brk = (char *)&__heap_start; } + // Ensure we don't overflow the heap by checking agsinst the current stack + // pointer (the heap grows towards the stack, and vice-versa). + // + // This is only a last-ditch attempt at saving ourselves from memory + // corruption. It doesn't prevent the stack from growing into the heap + // first. + + void *sp; + __asm__ __volatile__ ("mov %0, sp" : "=r"(sp)); + + // Require a 'safe margin' of 4k between the heap and stack. + uint32_t stack_bottom = (uint32_t)sp - 4096; + + if (((uint32_t)brk + incr) > stack_bottom) { + errno = ENOMEM; + return (uint32_t)-1; + } + char *prev_brk = brk; brk += incr; return (uint32_t)prev_brk; diff --git a/l0dables/lib/meson.build b/l0dables/lib/meson.build index 60d557d4..f2f16295 100644 --- a/l0dables/lib/meson.build +++ b/l0dables/lib/meson.build @@ -2,7 +2,7 @@ l0dable_startup_lib = static_library( 'l0dable-startup', 'crt.s', 'hardware.c', - dependencies: [periphdriver, api_caller], + dependencies: [api_caller], pic: true, ) -- GitLab