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