From 694fb17d9f1e89bfb9a5fe7e28437b536369df07 Mon Sep 17 00:00:00 2001 From: Devan Lai Date: Sun, 28 Aug 2016 11:07:07 -0700 Subject: [PATCH 1/3] Implement experimental high-memory bootloader The bootloader now lives at the high end of flash, allowing an non- bootloader-aware application to run without modifications. The bootloader modifies the application's vector table to point to the bootloader's reset stub. The actual reset vector is stored in unused entries in the application's vector table. Based on ideas from: http://stm32duino.com/viewtopic.php?t=687 This is based on code from commit cf21dc3212cfedb6daca78ba3a23078f88dda8aa fixing DFU upload and rebasing on current master branch. Co-authored-by: Daniel Serpell --- src/dapboot.c | 14 ++--- src/dfu.c | 36 +++++++++++- src/stm32f103/bluepill/config.h | 2 +- src/stm32f103/generic/config.h | 2 +- src/stm32f103/maplemini/config.h | 2 +- src/stm32f103/stlink/config.h | 2 +- src/stm32f103/stm32f103x8.ld | 99 ++++++++++++++++++++++++++++++-- 7 files changed, 139 insertions(+), 18 deletions(-) diff --git a/src/dapboot.c b/src/dapboot.c index a43a524..cc894b8 100644 --- a/src/dapboot.c +++ b/src/dapboot.c @@ -31,8 +31,10 @@ static inline void __set_MSP(uint32_t topOfMainStack) { asm("msr msp, %0" : : "r" (topOfMainStack)); } +extern volatile const vector_table_t vector_table; + bool validate_application(void) { - if ((*(volatile uint32_t *)APP_BASE_ADDRESS & 0x2FFE0000) == 0x20000000) { + if (((uint32_t)(vector_table.reserved_x001c[0]) & 0x2FFE0000) == 0x20000000) { return true; } return false; @@ -41,20 +43,16 @@ bool validate_application(void) { static void jump_to_application(void) __attribute__ ((noreturn)); static void jump_to_application(void) { - vector_table_t* app_vector_table = (vector_table_t*)APP_BASE_ADDRESS; - - /* Use the application's vector table */ - target_relocate_vector_table(); /* Do any necessary early setup for the application */ target_pre_main(); /* Initialize the application's stack pointer */ - __set_MSP((uint32_t)(app_vector_table->initial_sp_value)); + __set_MSP((uint32_t)(vector_table.reserved_x001c[0])); /* Jump to the application entry point */ - app_vector_table->reset(); - + vector_table.reserved_x001c[1](); + while (1); } diff --git a/src/dfu.c b/src/dfu.c index 7351eb6..c96ed03 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -21,6 +21,7 @@ #include #include +#include #include "dfu.h" #include "usb_conf.h" @@ -94,6 +95,23 @@ static void dfu_on_download_request(usbd_device* usbd_dev, struct usb_setup_data (void)usbd_dev; (void)req; + if (current_dfu_offset == 0) { + if (dfu_download_size < offsetof(vector_table_t, reserved_x001c[1])) { + /* Can't handle splitting the vector table right now */ + dfu_set_status(DFU_STATUS_ERR_VENDOR); + } else { + vector_table_t* app_vector_table = (vector_table_t*)dfu_download_buffer; + /* Stash the application's initial stack value and reset + pointer in unused vector table entries */ + app_vector_table->reserved_x001c[0] = (vector_table_entry_t)(app_vector_table->initial_sp_value); + app_vector_table->reserved_x001c[1] = app_vector_table->reset; + /* Overwrite the stack and reset pointer to run the + bootloader instead */ + app_vector_table->initial_sp_value = &_stack; + app_vector_table->reset = reset_handler; + } + } + const uint16_t* data = (uint16_t*)dfu_download_buffer; uint16_t* dest = (uint16_t*)(APP_BASE_ADDRESS + current_dfu_offset); @@ -234,7 +252,6 @@ static int dfu_control_class_request(usbd_device *usbd_dev, __attribute__ ((fallthrough)); } case STATE_DFU_UPLOAD_IDLE: { - *buf = (uint8_t*)(APP_BASE_ADDRESS + current_dfu_offset); uint16_t len_to_copy = req->wLength; size_t max_firmware_size = target_get_max_firmware_size(); if (current_dfu_offset + req->wLength > max_firmware_size) { @@ -244,6 +261,23 @@ static int dfu_control_class_request(usbd_device *usbd_dev, dfu_set_state(STATE_DFU_UPLOAD_IDLE); } *len = len_to_copy; + if (current_dfu_offset < sizeof(vector_table_t)) { + /* Copy the flash memory to the download buffer, to + undo the vector modifications. */ + memcpy(dfu_download_buffer, (const void*)(APP_BASE_ADDRESS), + sizeof(dfu_download_buffer)); + vector_table_t* app_vector_table = (vector_table_t*)dfu_download_buffer; + /* Put the original stack pointer and reset vectors + back */ + app_vector_table->initial_sp_value = (unsigned int*)(app_vector_table->reserved_x001c[0]); + app_vector_table->reset = app_vector_table->reserved_x001c[1]; + app_vector_table->reserved_x001c[0] = 0; + app_vector_table->reserved_x001c[1] = 0; + /* Return the correct pointer */ + *buf = dfu_download_buffer + current_dfu_offset; + } else { + *buf = (uint8_t*)(APP_BASE_ADDRESS + current_dfu_offset); + } current_dfu_offset += len_to_copy; break; } diff --git a/src/stm32f103/bluepill/config.h b/src/stm32f103/bluepill/config.h index c0df9e0..add4a57 100644 --- a/src/stm32f103/bluepill/config.h +++ b/src/stm32f103/bluepill/config.h @@ -20,7 +20,7 @@ #define CONFIG_H_INCLUDED #ifndef APP_BASE_ADDRESS -#define APP_BASE_ADDRESS 0x08002000 +#define APP_BASE_ADDRESS 0x08000000 #endif #ifndef FLASH_SIZE_OVERRIDE #define FLASH_SIZE_OVERRIDE 0x20000 diff --git a/src/stm32f103/generic/config.h b/src/stm32f103/generic/config.h index 8bfe845..c5902c8 100644 --- a/src/stm32f103/generic/config.h +++ b/src/stm32f103/generic/config.h @@ -20,7 +20,7 @@ #define CONFIG_H_INCLUDED #ifndef APP_BASE_ADDRESS -#define APP_BASE_ADDRESS 0x08002000 +#define APP_BASE_ADDRESS 0x08000000 #endif #ifndef FLASH_SIZE_OVERRIDE #define FLASH_SIZE_OVERRIDE 0x20000 diff --git a/src/stm32f103/maplemini/config.h b/src/stm32f103/maplemini/config.h index f44ebc2..64f76ad 100644 --- a/src/stm32f103/maplemini/config.h +++ b/src/stm32f103/maplemini/config.h @@ -20,7 +20,7 @@ #define CONFIG_H_INCLUDED #ifndef APP_BASE_ADDRESS -#define APP_BASE_ADDRESS 0x08002000 +#define APP_BASE_ADDRESS 0x08000000 #endif #ifndef FLASH_PAGE_SIZE #define FLASH_PAGE_SIZE 1024 diff --git a/src/stm32f103/stlink/config.h b/src/stm32f103/stlink/config.h index b0127b4..c152692 100644 --- a/src/stm32f103/stlink/config.h +++ b/src/stm32f103/stlink/config.h @@ -20,7 +20,7 @@ #define CONFIG_H_INCLUDED #ifndef APP_BASE_ADDRESS -#define APP_BASE_ADDRESS 0x08002000 +#define APP_BASE_ADDRESS 0x08000000 #endif #ifndef FLASH_SIZE_OVERRIDE #define FLASH_SIZE_OVERRIDE 0x20000 diff --git a/src/stm32f103/stm32f103x8.ld b/src/stm32f103/stm32f103x8.ld index 68645d8..6f8e4bc 100644 --- a/src/stm32f103/stm32f103x8.ld +++ b/src/stm32f103/stm32f103x8.ld @@ -1,7 +1,9 @@ /* - * This file is part of the libopencm3 project. + * This file is part of the dapboot project. * + * Copyright (C) 2016 Devan Lai * Copyright (C) 2015 Karl Palsson + * Copyright (C) 2009 Uwe Hermann * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -20,12 +22,99 @@ /* Linker script for STM32F103x8, 64k flash, 20k RAM. */ /* Define memory regions. */ -/* 8k for the bootloader */ +/* 8k for the bootloader at the end, with a copy of the vector table at + * the beginning to bootstrap the bootloader + */ MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K + bootstrap (rx) : ORIGIN = 0x08000000, LENGTH = 1K + rom (rx) : ORIGIN = 0x0800e400, LENGTH = 0x1C00 ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } -/* Include the common ld script. */ -INCLUDE libopencm3_stm32f1.ld +/* Enforce emission of the vector table. */ +EXTERN (vector_table) + +/* Define the entry point of the output file. */ +ENTRY(reset_handler) + +/* Define sections. */ +SECTIONS +{ + /* Vector table for the initial upload */ + .vectors : { + *(.vectors) + } >bootstrap + + .text : { + *(.text*) /* Program code */ + . = ALIGN(4); + *(.rodata*) /* Read-only data */ + . = ALIGN(4); + } >rom + + /* C++ Static constructors/destructors, also used for __attribute__ + * ((constructor)) and the likes */ + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >rom + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >rom + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >rom + + /* + * Another section used by C++ stuff, appears when using newlib with + * 64bit (long long) printf support + */ + .ARM.extab : { + *(.ARM.extab*) + } >rom + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >rom + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) /* Read-write initialized data */ + . = ALIGN(4); + _edata = .; + } >ram AT >rom + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) /* Read-write zero initialized data */ + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >ram + + /* + * The .eh_frame section appears to be used for C++ exception handling. + * You may need to fix this if you're using C++. + */ + /DISCARD/ : { *(.eh_frame) } + + . = ALIGN(4); + end = .; +} + +PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); From a49485704022dacba897f5cd951d14479cff8806 Mon Sep 17 00:00:00 2001 From: Daniel Serpell Date: Fri, 17 Apr 2020 14:04:07 -0400 Subject: [PATCH 2/3] Compile bootloader variants for 64K and 128K boards. --- release.Makefile | 23 +++++++- src/stm32f103/common.ld | 109 +++++++++++++++++++++++++++++++++++ src/stm32f103/stm32f103x8.ld | 89 +--------------------------- src/stm32f103/stm32f103xB.ld | 35 +++++++++++ src/targets.mk | 18 ++++++ 5 files changed, 186 insertions(+), 88 deletions(-) create mode 100644 src/stm32f103/common.ld create mode 100644 src/stm32f103/stm32f103xB.ld diff --git a/release.Makefile b/release.Makefile index 8bc500f..857aeb7 100644 --- a/release.Makefile +++ b/release.Makefile @@ -31,7 +31,10 @@ BUILD_DIR ?= ./build all: dapboot-bluepill.bin \ dapboot-maplemini.bin \ - dapboot-stlink.bin + dapboot-stlink.bin \ + dapboot-bluepill-128.bin \ + dapboot-maplemini-128.bin \ + dapboot-stlink-128.bin clean: $(Q)$(RM) $(BUILD_DIR)/*.bin @@ -59,3 +62,21 @@ dapboot-maplemini.bin: | $(BUILD_DIR) $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ clean $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) + +dapboot-bluepill-128.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=BLUEPILL_128 -C src/ clean + $(Q)$(MAKE) TARGET=BLUEPILL_128 -C src/ + $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) + +dapboot-stlink-128.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=STLINK_128 -C src/ clean + $(Q)$(MAKE) TARGET=STLINK_128 -C src/ + $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) + +dapboot-maplemini-128.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=MAPLEMINI_128 -C src/ clean + $(Q)$(MAKE) TARGET=MAPLEMINI_128 -C src/ + $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) diff --git a/src/stm32f103/common.ld b/src/stm32f103/common.ld new file mode 100644 index 0000000..e3db3ae --- /dev/null +++ b/src/stm32f103/common.ld @@ -0,0 +1,109 @@ +/* + * This file is part of the dapboot project. + * + * Copyright (C) 2016 Devan Lai + * Copyright (C) 2015 Karl Palsson + * Copyright (C) 2009 Uwe Hermann + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* Common linker script */ + +/* Enforce emission of the vector table. */ +EXTERN (vector_table) + +/* Define the entry point of the output file. */ +ENTRY(reset_handler) + +/* Define sections. */ +SECTIONS +{ + /* Vector table for the initial upload */ + .vectors : { + *(.vectors) + } >bootstrap + + .text : { + *(.text*) /* Program code */ + . = ALIGN(4); + *(.rodata*) /* Read-only data */ + . = ALIGN(4); + } >rom + + /* C++ Static constructors/destructors, also used for __attribute__ + * ((constructor)) and the likes */ + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >rom + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >rom + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >rom + + /* + * Another section used by C++ stuff, appears when using newlib with + * 64bit (long long) printf support + */ + .ARM.extab : { + *(.ARM.extab*) + } >rom + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >rom + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) /* Read-write initialized data */ + . = ALIGN(4); + _edata = .; + } >ram AT >rom + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) /* Read-write zero initialized data */ + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >ram + + /* + * The .eh_frame section appears to be used for C++ exception handling. + * You may need to fix this if you're using C++. + */ + /DISCARD/ : { *(.eh_frame) } + + . = ALIGN(4); + end = .; +} + +PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/src/stm32f103/stm32f103x8.ld b/src/stm32f103/stm32f103x8.ld index 6f8e4bc..bbc24cb 100644 --- a/src/stm32f103/stm32f103x8.ld +++ b/src/stm32f103/stm32f103x8.ld @@ -22,7 +22,7 @@ /* Linker script for STM32F103x8, 64k flash, 20k RAM. */ /* Define memory regions. */ -/* 8k for the bootloader at the end, with a copy of the vector table at +/* 6.75k for the bootloader at the end, with a copy of the vector table at * the beginning to bootstrap the bootloader */ MEMORY @@ -32,89 +32,4 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } -/* Enforce emission of the vector table. */ -EXTERN (vector_table) - -/* Define the entry point of the output file. */ -ENTRY(reset_handler) - -/* Define sections. */ -SECTIONS -{ - /* Vector table for the initial upload */ - .vectors : { - *(.vectors) - } >bootstrap - - .text : { - *(.text*) /* Program code */ - . = ALIGN(4); - *(.rodata*) /* Read-only data */ - . = ALIGN(4); - } >rom - - /* C++ Static constructors/destructors, also used for __attribute__ - * ((constructor)) and the likes */ - .preinit_array : { - . = ALIGN(4); - __preinit_array_start = .; - KEEP (*(.preinit_array)) - __preinit_array_end = .; - } >rom - .init_array : { - . = ALIGN(4); - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - } >rom - .fini_array : { - . = ALIGN(4); - __fini_array_start = .; - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - __fini_array_end = .; - } >rom - - /* - * Another section used by C++ stuff, appears when using newlib with - * 64bit (long long) printf support - */ - .ARM.extab : { - *(.ARM.extab*) - } >rom - .ARM.exidx : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >rom - - . = ALIGN(4); - _etext = .; - - .data : { - _data = .; - *(.data*) /* Read-write initialized data */ - . = ALIGN(4); - _edata = .; - } >ram AT >rom - _data_loadaddr = LOADADDR(.data); - - .bss : { - *(.bss*) /* Read-write zero initialized data */ - *(COMMON) - . = ALIGN(4); - _ebss = .; - } >ram - - /* - * The .eh_frame section appears to be used for C++ exception handling. - * You may need to fix this if you're using C++. - */ - /DISCARD/ : { *(.eh_frame) } - - . = ALIGN(4); - end = .; -} - -PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); +INCLUDE stm32f103/common.ld diff --git a/src/stm32f103/stm32f103xB.ld b/src/stm32f103/stm32f103xB.ld new file mode 100644 index 0000000..4ff5f12 --- /dev/null +++ b/src/stm32f103/stm32f103xB.ld @@ -0,0 +1,35 @@ +/* + * This file is part of the dapboot project. + * + * Copyright (C) 2016 Devan Lai + * Copyright (C) 2015 Karl Palsson + * Copyright (C) 2009 Uwe Hermann + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* Linker script for STM32F103xB, 128k flash, 20k RAM. */ + +/* Define memory regions. */ +/* 6.75k for the bootloader at the end, with a copy of the vector table at + * the beginning to bootstrap the bootloader + */ +MEMORY +{ + bootstrap (rx) : ORIGIN = 0x08000000, LENGTH = 1K + rom (rx) : ORIGIN = 0x0801e400, LENGTH = 0x1C00 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +INCLUDE stm32f103/common.ld diff --git a/src/targets.mk b/src/targets.mk index d93a11a..59e955b 100644 --- a/src/targets.mk +++ b/src/targets.mk @@ -26,18 +26,36 @@ ifeq ($(TARGET),BLUEPILL) LDSCRIPT := ./stm32f103/stm32f103x8.ld ARCH = STM32F1 endif +ifeq ($(TARGET),BLUEPILL_128) + TARGET_COMMON_DIR := ./stm32f103 + TARGET_SPEC_DIR := ./stm32f103/bluepill + LDSCRIPT := ./stm32f103/stm32f103xB.ld + ARCH = STM32F1 +endif ifeq ($(TARGET),MAPLEMINI) TARGET_COMMON_DIR := ./stm32f103 TARGET_SPEC_DIR := ./stm32f103/maplemini LDSCRIPT := ./stm32f103/stm32f103x8.ld ARCH = STM32F1 endif +ifeq ($(TARGET),MAPLEMINI_128) + TARGET_COMMON_DIR := ./stm32f103 + TARGET_SPEC_DIR := ./stm32f103/maplemini + LDSCRIPT := ./stm32f103/stm32f103xB.ld + ARCH = STM32F1 +endif ifeq ($(TARGET),STLINK) TARGET_COMMON_DIR := ./stm32f103 TARGET_SPEC_DIR := ./stm32f103/stlink LDSCRIPT := ./stm32f103/stm32f103x8.ld ARCH = STM32F1 endif +ifeq ($(TARGET),STLINK_128) + TARGET_COMMON_DIR := ./stm32f103 + TARGET_SPEC_DIR := ./stm32f103/stlink + LDSCRIPT := ./stm32f103/stm32f103xB.ld + ARCH = STM32F1 +endif ifndef ARCH $(error Unknown target $(TARGET)) From 5f160ecae0dc779b79639f1ca46160a177e25623 Mon Sep 17 00:00:00 2001 From: Daniel Serpell Date: Sat, 18 Apr 2020 16:48:36 -0400 Subject: [PATCH 3/3] Use small versions of libc functions, almost 512 bytes smaller. --- src/Makefile | 1 + src/libc/memcpy.c | 19 +++++++++++++++++++ src/libc/strlen.c | 15 +++++++++++++++ src/libc/strncpy.c | 15 +++++++++++++++ src/stm32f103/stm32f103x8.ld | 6 +++--- src/stm32f103/stm32f103xB.ld | 4 ++-- 6 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 src/libc/memcpy.c create mode 100644 src/libc/strlen.c create mode 100644 src/libc/strncpy.c diff --git a/src/Makefile b/src/Makefile index bb68e9b..e3ce053 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,7 @@ include targets.mk SRCS := $(wildcard *.c) SRCS += $(wildcard $(TARGET_COMMON_DIR)/*.c) SRCS += $(wildcard $(TARGET_SPEC_DIR)/*.c) +SRCS += $(wildcard ./libc/*.c) OBJS += $(SRCS:.c=.o) DEPS = $(SRCS:.c=.d) diff --git a/src/libc/memcpy.c b/src/libc/memcpy.c new file mode 100644 index 0000000..9beacb6 --- /dev/null +++ b/src/libc/memcpy.c @@ -0,0 +1,19 @@ +/* + * memcpy.c: Smaller memcpy implementation. + */ + +#include + +// This makes GCC avoid replacing this with a call to builtin_memcpy +#pragma GCC optimize "Os" + +void *memcpy(void *dst, const void *src, size_t len) +{ + char *d = (char *)dst; + const char *s = (const char *)src; + + while(len--) + *d++ = *s++; + + return dst; +} diff --git a/src/libc/strlen.c b/src/libc/strlen.c new file mode 100644 index 0000000..46f79a7 --- /dev/null +++ b/src/libc/strlen.c @@ -0,0 +1,15 @@ +/* + * strlen.c: Smaller strlen implementation. + */ + +#include + +// This makes GCC avoid replacing this with a call to builtin_strlen +#pragma GCC optimize "Os" + +size_t strlen(const char *str) +{ + const char *start = str + 1; + while(*str++); + return str - start; +} diff --git a/src/libc/strncpy.c b/src/libc/strncpy.c new file mode 100644 index 0000000..dbfe893 --- /dev/null +++ b/src/libc/strncpy.c @@ -0,0 +1,15 @@ +/* + * strncpy.c: Smaller strncpy implementation. + */ + +#include + +// This makes GCC avoid replacing this with a call to builtin_strncpy +#pragma GCC optimize "Os" + +char *strncpy(char *dst, const char *src, size_t len) +{ + char *d = dst; + while( len-- && '\0' != (*d++ = *src++) ); + return dst; +} diff --git a/src/stm32f103/stm32f103x8.ld b/src/stm32f103/stm32f103x8.ld index bbc24cb..6af3bfa 100644 --- a/src/stm32f103/stm32f103x8.ld +++ b/src/stm32f103/stm32f103x8.ld @@ -22,13 +22,13 @@ /* Linker script for STM32F103x8, 64k flash, 20k RAM. */ /* Define memory regions. */ -/* 6.75k for the bootloader at the end, with a copy of the vector table at - * the beginning to bootstrap the bootloader +/* 6.5k for the bootloader at the end, with a copy of the vector table at the + * beginning to bootstrap the bootloader */ MEMORY { bootstrap (rx) : ORIGIN = 0x08000000, LENGTH = 1K - rom (rx) : ORIGIN = 0x0800e400, LENGTH = 0x1C00 + rom (rx) : ORIGIN = 0x0800e600, LENGTH = 0x1A00 ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } diff --git a/src/stm32f103/stm32f103xB.ld b/src/stm32f103/stm32f103xB.ld index 4ff5f12..7e03308 100644 --- a/src/stm32f103/stm32f103xB.ld +++ b/src/stm32f103/stm32f103xB.ld @@ -22,13 +22,13 @@ /* Linker script for STM32F103xB, 128k flash, 20k RAM. */ /* Define memory regions. */ -/* 6.75k for the bootloader at the end, with a copy of the vector table at +/* 6.5k for the bootloader at the end, with a copy of the vector table at * the beginning to bootstrap the bootloader */ MEMORY { bootstrap (rx) : ORIGIN = 0x08000000, LENGTH = 1K - rom (rx) : ORIGIN = 0x0801e400, LENGTH = 0x1C00 + rom (rx) : ORIGIN = 0x0801e600, LENGTH = 0x1A00 ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K }