Skip to content

Instantly share code, notes, and snippets.

@elfmimi
Last active December 26, 2022 14:15
Show Gist options
  • Select an option

  • Save elfmimi/e28761a42e14940b0c5f29656316e734 to your computer and use it in GitHub Desktop.

Select an option

Save elfmimi/e28761a42e14940b0c5f29656316e734 to your computer and use it in GitHub Desktop.

Revisions

  1. elfmimi revised this gist Dec 26, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ $(OBJDIR)/%.o: %.c

    $(TARGET).elf: $(addprefix $(OBJDIR)/,$(OBJS))
    clang -fuse-ld=lld $(CFLAGS) $^ -l:crt0-minimal.o -T picolibc.ld -Wl,--defsym=__flash=0,--defsym=__ram_size=0x3000,--lto-partitions=1,--lto-whole-program-visibility -o $@
    # ld.lld $^ $(CLANG_RUNTIME)/lib/crt0-minimal.o $(CLANG_RUNTIME)/lib/libc.a $(CLANG_RUNTIME)/lib/libclang_rt.builtins-armv6m.a $(FLAGS) -T picolibc.ld --defsym=__flash=0 --defsym=__ram_size=0x3000 --lto-partitions=1 --lto-whole-program-visibility -o $@
    # ld.lld $^ $(CLANG_RUNTIME)/lib/crt0-minimal.o $(CLANG_RUNTIME)/lib/libc.a $(CLANG_RUNTIME)/lib/libclang_rt.builtins-armv6m.a $(FLAGS) -T picolibc.ld --defsym=__flash=0 --defsym=__ram_size=0x3000 --lto-partitions=1 --lto-whole-program-visibility -o $@

    .PRECIOUS: %.hex
    %.hex: %.elf
  2. elfmimi revised this gist Dec 26, 2022. 2 changed files with 8 additions and 247 deletions.
    14 changes: 8 additions & 6 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -13,9 +13,6 @@ INCS+= -I$(DEVICEDIR)/Include
    INCS+= -I$(DRIVERDIR)/inc

    CFLAGS=--target=armv6m-none-eabi -march=armv6m -mcpu=cortex-m0 -mfloat-abi=soft
    # CFLAGS=--target=armv6m-none-eabi -march=armv6m -mcpu=cortex-m0 -mfpu=none -mfloat-abi=soft
    # CFLAGS=--target=armv8m.base-none-eabi -march=armv8-m.base -mfloat-abi=soft -mcpu=cortex-m23
    # CFLAGS=--target=arm-unknown-unknown-eabi -mcpu=cortex-m23 -mfloat-abi=soft
    CFLAGS+=-Oz -flto

    SRCDIRS=. $(DEVICEDIR)/Source $(DEVICEDIR)/Source/GCC $(DRIVERDIR)/src $(SAMPLEDIR)
    @@ -27,7 +24,8 @@ OBJS=$(notdir $(filter %.o,$(SRCS:.S=.o) $(SRCS:.s=.o) $(SRCS:.c=.o) $(SRCS:.cpp
    OBJDIR=obj

    CLANG_RUNTIME=../../../../../../../PROGRAMS/LLVMEmbeddedToolchainForArm-15.0.2/lib/clang-runtimes/armv6m_soft_nofp
    INCS+= -I$(CLANG_RUNTIME)/include
    # INCS+= -I$(CLANG_RUNTIME)/include
    CFLAGS+=--sysroot $(CLANG_RUNTIME)

    LDSPECS=

    @@ -40,19 +38,23 @@ bin: $(TARGET).bin
    vpath %.S $(SRCDIRS)
    $(OBJDIR)/%.o: %.S
    @mkdir -p $(@D)
    clang -x assembler-with-cpp -D__data_start__=__data_start -D__data_end__=__data_end -D__Vectors=__interrupt_vector -Dvectors=data.init.enter $(CFLAGS) $(FLAGS) $(DEFS) $(INCS) -c -o $@ $<
    clang -x assembler-with-cpp -D__etext=__data_source -D__data_start__=__data_start -D__data_end__=__data_end -D__Vectors=__interrupt_vector -Dvectors=data.init.enter $(CFLAGS) $(FLAGS) $(DEFS) $(INCS) -c -o $@ $<

    vpath %.c $(SRCDIRS)
    $(OBJDIR)/%.o: %.c
    @mkdir -p $(@D)
    clang $(CFLAGS) $(FLAGS) $(DEFS) $(INCS) -D__Vectors=__interrupt_vector -D__align=_Alignas -c -o $@ $<

    $(TARGET).elf: $(addprefix $(OBJDIR)/,$(OBJS))
    ld.lld $^ $(CLANG_RUNTIME)/lib/crt0-minimal.o $(CLANG_RUNTIME)/lib/libc.a $(CLANG_RUNTIME)/lib/libclang_rt.builtins-armv6m.a $(FLAGS) -T picolibc.ld --defsym=__flash=0 --defsym=__ram_size=0x5000 --lto-partitions=1 --lto-whole-program-visibility -o $@
    clang -fuse-ld=lld $(CFLAGS) $^ -l:crt0-minimal.o -T picolibc.ld -Wl,--defsym=__flash=0,--defsym=__ram_size=0x3000,--lto-partitions=1,--lto-whole-program-visibility -o $@
    # ld.lld $^ $(CLANG_RUNTIME)/lib/crt0-minimal.o $(CLANG_RUNTIME)/lib/libc.a $(CLANG_RUNTIME)/lib/libclang_rt.builtins-armv6m.a $(FLAGS) -T picolibc.ld --defsym=__flash=0 --defsym=__ram_size=0x3000 --lto-partitions=1 --lto-whole-program-visibility -o $@

    .PRECIOUS: %.hex
    %.hex: %.elf
    llvm-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@

    %.bin: %.hex
    llvm-objcopy -I ihex -O binary $< $@

    clean:
    rm -rf obj $(TARGET).elf $(TARGET).hex $(TARGET).bin
    241 changes: 0 additions & 241 deletions picolibc.ld
    Original file line number Diff line number Diff line change
    @@ -1,241 +0,0 @@
    /*
    * SPDX-License-Identifier: BSD-3-Clause
    *
    * Copyright © 2019 Keith Packard
    *
    * 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 the copyright holder 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.
    */

    ENTRY(_start)

    /*
    * These values should be provided by the application. We'll include
    * some phony values here to make things link for testing
    */

    MEMORY
    {
    flash (rx) : ORIGIN = DEFINED(__flash) ? __flash : 0x10000000, LENGTH = DEFINED(__flash_size) ? __flash_size : 0x10000
    ram (rwx) : ORIGIN = DEFINED(__ram ) ? __ram : 0x20000000, LENGTH = DEFINED(__ram_size ) ? __ram_size : 0x08000
    }

    PHDRS
    {
    text PT_LOAD;
    ram PT_LOAD;
    ram_init PT_LOAD;
    tls PT_TLS;
    }

    SECTIONS
    {
    PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram));

    .init : {
    KEEP (*(.text.init.enter))
    KEEP (*(.data.init.enter))
    KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*)))
    } >flash AT>flash :text

    .text : {

    /* code */
    *(.text.unlikely .text.unlikely.*)
    *(.text.startup .text.startup.*)
    *(.text .text.*)
    *(.gnu.linkonce.t.*)
    KEEP (*(.fini .fini.*))
    . = ALIGN(8);
    __text_end = .;

    PROVIDE (__etext = __text_end);
    PROVIDE (_etext = __text_end);
    PROVIDE (etext = __text_end);

    /* read-only data */
    *(.rdata)
    *(.rodata .rodata.*)
    *(.gnu.linkonce.r.*)

    *(.srodata.cst16)
    *(.srodata.cst8)
    *(.srodata.cst4)
    *(.srodata.cst2)
    *(.srodata .srodata.*)
    *(.data.rel.ro .data.rel.ro.*)
    *(.got .got.*)

    /* Need to pre-align so that the symbols come after padding */
    . = ALIGN(8);

    /* lists of constructors and destructors */
    PROVIDE_HIDDEN ( __preinit_array_start = . );
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN ( __preinit_array_end = . );

    PROVIDE_HIDDEN ( __init_array_start = . );
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
    KEEP (*(.init_array .ctors))
    PROVIDE_HIDDEN ( __init_array_end = . );

    PROVIDE_HIDDEN ( __fini_array_start = . );
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
    KEEP (*(.fini_array .dtors))
    PROVIDE_HIDDEN ( __fini_array_end = . );
    } >flash AT>flash :text

    /* additional sections when compiling with C++ exception support */
    /*
    .except_ordered : {
    *(.gcc_except_table *.gcc_except_table.*)
    KEEP (*(.eh_frame .eh_frame.*))
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    } >flash AT>flash :text
    .except_unordered : {
    . = ALIGN(8);
    PROVIDE(__exidx_start = .);
    *(.ARM.exidx*)
    PROVIDE(__exidx_end = .);
    } >flash AT>flash :text
    */

    /*
    * Data values which are preserved across reset
    */
    .preserve (NOLOAD) : {
    PROVIDE(__preserve_start__ = .);
    KEEP(*(SORT_BY_NAME(.preserve.*)))
    KEEP(*(.preserve))
    PROVIDE(__preserve_end__ = .);
    } >ram AT>ram :ram

    .data : {
    *(.data .data.*)
    *(.gnu.linkonce.d.*)

    /* Need to pre-align so that the symbols come after padding */
    . = ALIGN(8);

    PROVIDE( __global_pointer$ = . + 0x800 );
    *(.sdata .sdata.* .sdata2.*)
    *(.gnu.linkonce.s.*)
    } >ram AT>flash :ram_init
    PROVIDE(__data_start = ADDR(.data));
    PROVIDE(__data_source = LOADADDR(.data));

    /* Thread local initialized data. This gets
    * space allocated as it is expected to be placed
    * in ram to be used as a template for TLS data blocks
    * allocated at runtime. We're slightly abusing that
    * by placing the data in flash where it will be copied
    * into the allocate ram addresses by the existing
    * data initialization code in crt0
    */
    .tdata : {
    *(.tdata .tdata.* .gnu.linkonce.td.*)
    PROVIDE(__data_end = .);
    PROVIDE(__tdata_end = .);
    } >ram AT>flash :tls :ram_init
    PROVIDE( __tls_base = ADDR(.tdata));
    PROVIDE( __tdata_start = ADDR(.tdata));
    PROVIDE( __tdata_source = LOADADDR(.tdata) );
    PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) );
    PROVIDE( __tdata_size = SIZEOF(.tdata) );

    PROVIDE( __edata = __data_end );
    PROVIDE( _edata = __data_end );
    PROVIDE( edata = __data_end );
    PROVIDE( __data_size = __data_end - __data_start );

    .tbss (NOLOAD) : {
    *(.tbss .tbss.* .gnu.linkonce.tb.*)
    *(.tcommon)
    PROVIDE( __tls_end = . );
    PROVIDE( __tbss_end = . );
    } >ram AT>ram :tls :ram
    PROVIDE( __bss_start = ADDR(.tbss));
    PROVIDE( __tbss_start = ADDR(.tbss));
    PROVIDE( __tbss_size = SIZEOF(.tbss) );
    PROVIDE( __tls_size = __tls_end - __tls_base );

    /*
    * The linker special cases .tbss segments which are
    * identified as segments which are not loaded and are
    * thread_local.
    *
    * For these segments, the linker does not advance 'dot'
    * across them. We actually need memory allocated for tbss,
    * so we create a special segment here just to make room
    */
    .tbss_space (NOLOAD) : {
    . = . + SIZEOF(.tbss);
    } >ram AT>ram :ram

    .bss (NOLOAD) : {
    *(.sbss*)
    *(.gnu.linkonce.sb.*)
    *(.bss .bss.*)
    *(.gnu.linkonce.b.*)
    *(COMMON)

    /* Align the heap */
    . = ALIGN(8);
    __bss_end = .;
    } >ram AT>ram :ram
    PROVIDE( __end = __bss_end );
    PROVIDE( _end = __bss_end );
    PROVIDE( end = __bss_end );
    PROVIDE( __bss_size = __bss_end - __bss_start );

    /* Make the rest of memory available for heap storage */
    PROVIDE (__heap_start = __end);
    PROVIDE (__heap_end = __stack - (DEFINED(__stack_size) ? __stack_size : 0x800));
    PROVIDE (__heap_size = __heap_end - __heap_start);

    /* Define a stack region to make sure it fits in memory */
    .stack (NOLOAD) : {
    . += (DEFINED(__stack_size) ? __stack_size : 0x800);
    } >ram :ram

    /* Throw away C++ exception handling information */



    /DISCARD/ : {
    *(.note .note.*)
    *(.eh_frame .eh_frame.*)
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    *(.ARM.exidx*)
    }


    }
  3. elfmimi revised this gist Dec 25, 2022. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    Makefile for NUC123BSP ISP_HID sample

    This shows how to use LLVM/clang to compile the sample code in Nuvoton's BSP.
    This shows how to use LLVM/clang to compile the sample code in Nuvoton's BSP.\
    https://github.com/OpenNuvoton/NUC123BSP/tree/master/SampleCode/ISP/ISP_HID

    You can get LLVM/clang from here.\
    https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/tag/release-15.0.2
  4. elfmimi revised this gist Dec 25, 2022. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -3,4 +3,7 @@ Makefile for NUC123BSP ISP_HID sample
    This shows how to use LLVM/clang to compile the sample code in Nuvoton's BSP.

    You can get LLVM/clang from here.\
    https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/tag/release-15.0.2
    https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/tag/release-15.0.2

    For convenience, here is a zip file. It also include pre-built binary.\
    https://1drv.ms/u/s!AqNXcMx4fMGyrC2YtDAPPrgzTqbs
  5. elfmimi created this gist Dec 25, 2022.
    58 changes: 58 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    TARGET=ISP_HID


    NUC123BSP=../../../../../GitHub/Nuvoton-NUC123BSP
    CMSISDIR=$(NUC123BSP)/Library/CMSIS
    DEVICEDIR=$(NUC123BSP)/Library/Device/Nuvoton/NUC123
    DRIVERDIR=$(NUC123BSP)/Library/StdDriver
    SAMPLEDIR=$(NUC123BSP)/SampleCode/ISP/ISP_HID
    INCS=-I.
    INCS+= -I$(SAMPLEDIR)
    INCS+= -I$(CMSISDIR)/Include
    INCS+= -I$(DEVICEDIR)/Include
    INCS+= -I$(DRIVERDIR)/inc

    CFLAGS=--target=armv6m-none-eabi -march=armv6m -mcpu=cortex-m0 -mfloat-abi=soft
    # CFLAGS=--target=armv6m-none-eabi -march=armv6m -mcpu=cortex-m0 -mfpu=none -mfloat-abi=soft
    # CFLAGS=--target=armv8m.base-none-eabi -march=armv8-m.base -mfloat-abi=soft -mcpu=cortex-m23
    # CFLAGS=--target=arm-unknown-unknown-eabi -mcpu=cortex-m23 -mfloat-abi=soft
    CFLAGS+=-Oz -flto

    SRCDIRS=. $(DEVICEDIR)/Source $(DEVICEDIR)/Source/GCC $(DRIVERDIR)/src $(SAMPLEDIR)
    SRCS=startup_NUC123.S system_NUC123.c
    SRCS+=sys.c
    SRCS+=usbd_user.c descriptors.c hid_transfer.c isp_user.c fmc_user.c targetdev.c
    SRCS+=main.c
    OBJS=$(notdir $(filter %.o,$(SRCS:.S=.o) $(SRCS:.s=.o) $(SRCS:.c=.o) $(SRCS:.cpp=.o)))
    OBJDIR=obj

    CLANG_RUNTIME=../../../../../../../PROGRAMS/LLVMEmbeddedToolchainForArm-15.0.2/lib/clang-runtimes/armv6m_soft_nofp
    INCS+= -I$(CLANG_RUNTIME)/include

    LDSPECS=

    default:
    objs: $(addprefix $(OBJDIR)/,$(OBJS))
    elf: $(TARGET).elf
    hex: $(TARGET).hex
    bin: $(TARGET).bin

    vpath %.S $(SRCDIRS)
    $(OBJDIR)/%.o: %.S
    @mkdir -p $(@D)
    clang -x assembler-with-cpp -D__data_start__=__data_start -D__data_end__=__data_end -D__Vectors=__interrupt_vector -Dvectors=data.init.enter $(CFLAGS) $(FLAGS) $(DEFS) $(INCS) -c -o $@ $<

    vpath %.c $(SRCDIRS)
    $(OBJDIR)/%.o: %.c
    @mkdir -p $(@D)
    clang $(CFLAGS) $(FLAGS) $(DEFS) $(INCS) -D__Vectors=__interrupt_vector -D__align=_Alignas -c -o $@ $<

    $(TARGET).elf: $(addprefix $(OBJDIR)/,$(OBJS))
    ld.lld $^ $(CLANG_RUNTIME)/lib/crt0-minimal.o $(CLANG_RUNTIME)/lib/libc.a $(CLANG_RUNTIME)/lib/libclang_rt.builtins-armv6m.a $(FLAGS) -T picolibc.ld --defsym=__flash=0 --defsym=__ram_size=0x5000 --lto-partitions=1 --lto-whole-program-visibility -o $@

    .PRECIOUS: %.hex
    %.hex: %.elf
    llvm-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@

    %.bin: %.hex
    llvm-objcopy -I ihex -O binary $< $@
    6 changes: 6 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    Makefile for NUC123BSP ISP_HID sample

    This shows how to use LLVM/clang to compile the sample code in Nuvoton's BSP.

    You can get LLVM/clang from here.\
    https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/tag/release-15.0.2
    241 changes: 241 additions & 0 deletions picolibc.ld
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,241 @@
    /*
    * SPDX-License-Identifier: BSD-3-Clause
    *
    * Copyright © 2019 Keith Packard
    *
    * 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 the copyright holder 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.
    */

    ENTRY(_start)

    /*
    * These values should be provided by the application. We'll include
    * some phony values here to make things link for testing
    */

    MEMORY
    {
    flash (rx) : ORIGIN = DEFINED(__flash) ? __flash : 0x10000000, LENGTH = DEFINED(__flash_size) ? __flash_size : 0x10000
    ram (rwx) : ORIGIN = DEFINED(__ram ) ? __ram : 0x20000000, LENGTH = DEFINED(__ram_size ) ? __ram_size : 0x08000
    }

    PHDRS
    {
    text PT_LOAD;
    ram PT_LOAD;
    ram_init PT_LOAD;
    tls PT_TLS;
    }

    SECTIONS
    {
    PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram));

    .init : {
    KEEP (*(.text.init.enter))
    KEEP (*(.data.init.enter))
    KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*)))
    } >flash AT>flash :text

    .text : {

    /* code */
    *(.text.unlikely .text.unlikely.*)
    *(.text.startup .text.startup.*)
    *(.text .text.*)
    *(.gnu.linkonce.t.*)
    KEEP (*(.fini .fini.*))
    . = ALIGN(8);
    __text_end = .;

    PROVIDE (__etext = __text_end);
    PROVIDE (_etext = __text_end);
    PROVIDE (etext = __text_end);

    /* read-only data */
    *(.rdata)
    *(.rodata .rodata.*)
    *(.gnu.linkonce.r.*)

    *(.srodata.cst16)
    *(.srodata.cst8)
    *(.srodata.cst4)
    *(.srodata.cst2)
    *(.srodata .srodata.*)
    *(.data.rel.ro .data.rel.ro.*)
    *(.got .got.*)

    /* Need to pre-align so that the symbols come after padding */
    . = ALIGN(8);

    /* lists of constructors and destructors */
    PROVIDE_HIDDEN ( __preinit_array_start = . );
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN ( __preinit_array_end = . );

    PROVIDE_HIDDEN ( __init_array_start = . );
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
    KEEP (*(.init_array .ctors))
    PROVIDE_HIDDEN ( __init_array_end = . );

    PROVIDE_HIDDEN ( __fini_array_start = . );
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
    KEEP (*(.fini_array .dtors))
    PROVIDE_HIDDEN ( __fini_array_end = . );
    } >flash AT>flash :text

    /* additional sections when compiling with C++ exception support */
    /*
    .except_ordered : {
    *(.gcc_except_table *.gcc_except_table.*)
    KEEP (*(.eh_frame .eh_frame.*))
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    } >flash AT>flash :text
    .except_unordered : {
    . = ALIGN(8);
    PROVIDE(__exidx_start = .);
    *(.ARM.exidx*)
    PROVIDE(__exidx_end = .);
    } >flash AT>flash :text
    */

    /*
    * Data values which are preserved across reset
    */
    .preserve (NOLOAD) : {
    PROVIDE(__preserve_start__ = .);
    KEEP(*(SORT_BY_NAME(.preserve.*)))
    KEEP(*(.preserve))
    PROVIDE(__preserve_end__ = .);
    } >ram AT>ram :ram

    .data : {
    *(.data .data.*)
    *(.gnu.linkonce.d.*)

    /* Need to pre-align so that the symbols come after padding */
    . = ALIGN(8);

    PROVIDE( __global_pointer$ = . + 0x800 );
    *(.sdata .sdata.* .sdata2.*)
    *(.gnu.linkonce.s.*)
    } >ram AT>flash :ram_init
    PROVIDE(__data_start = ADDR(.data));
    PROVIDE(__data_source = LOADADDR(.data));

    /* Thread local initialized data. This gets
    * space allocated as it is expected to be placed
    * in ram to be used as a template for TLS data blocks
    * allocated at runtime. We're slightly abusing that
    * by placing the data in flash where it will be copied
    * into the allocate ram addresses by the existing
    * data initialization code in crt0
    */
    .tdata : {
    *(.tdata .tdata.* .gnu.linkonce.td.*)
    PROVIDE(__data_end = .);
    PROVIDE(__tdata_end = .);
    } >ram AT>flash :tls :ram_init
    PROVIDE( __tls_base = ADDR(.tdata));
    PROVIDE( __tdata_start = ADDR(.tdata));
    PROVIDE( __tdata_source = LOADADDR(.tdata) );
    PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) );
    PROVIDE( __tdata_size = SIZEOF(.tdata) );

    PROVIDE( __edata = __data_end );
    PROVIDE( _edata = __data_end );
    PROVIDE( edata = __data_end );
    PROVIDE( __data_size = __data_end - __data_start );

    .tbss (NOLOAD) : {
    *(.tbss .tbss.* .gnu.linkonce.tb.*)
    *(.tcommon)
    PROVIDE( __tls_end = . );
    PROVIDE( __tbss_end = . );
    } >ram AT>ram :tls :ram
    PROVIDE( __bss_start = ADDR(.tbss));
    PROVIDE( __tbss_start = ADDR(.tbss));
    PROVIDE( __tbss_size = SIZEOF(.tbss) );
    PROVIDE( __tls_size = __tls_end - __tls_base );

    /*
    * The linker special cases .tbss segments which are
    * identified as segments which are not loaded and are
    * thread_local.
    *
    * For these segments, the linker does not advance 'dot'
    * across them. We actually need memory allocated for tbss,
    * so we create a special segment here just to make room
    */
    .tbss_space (NOLOAD) : {
    . = . + SIZEOF(.tbss);
    } >ram AT>ram :ram

    .bss (NOLOAD) : {
    *(.sbss*)
    *(.gnu.linkonce.sb.*)
    *(.bss .bss.*)
    *(.gnu.linkonce.b.*)
    *(COMMON)

    /* Align the heap */
    . = ALIGN(8);
    __bss_end = .;
    } >ram AT>ram :ram
    PROVIDE( __end = __bss_end );
    PROVIDE( _end = __bss_end );
    PROVIDE( end = __bss_end );
    PROVIDE( __bss_size = __bss_end - __bss_start );

    /* Make the rest of memory available for heap storage */
    PROVIDE (__heap_start = __end);
    PROVIDE (__heap_end = __stack - (DEFINED(__stack_size) ? __stack_size : 0x800));
    PROVIDE (__heap_size = __heap_end - __heap_start);

    /* Define a stack region to make sure it fits in memory */
    .stack (NOLOAD) : {
    . += (DEFINED(__stack_size) ? __stack_size : 0x800);
    } >ram :ram

    /* Throw away C++ exception handling information */



    /DISCARD/ : {
    *(.note .note.*)
    *(.eh_frame .eh_frame.*)
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    *(.ARM.exidx*)
    }


    }
    332 changes: 332 additions & 0 deletions startup_NUC123.S
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,332 @@
    /****************************************************************************//**
    * @file startup_NUC123.S
    * @version V1.00
    * @brief CMSIS Device Startup File
    *
    * SPDX-License-Identifier: Apache-2.0
    * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
    *****************************************************************************/



    .syntax unified
    .arch armv6
    .section .stack
    .align 3
    #ifndef Stack_Size
    .equ Stack_Size, 0x00000400
    #endif
    .global __StackTop
    .global __StackLimit
    __StackLimit:
    .space Stack_Size
    .size __StackLimit, . - __StackLimit
    __StackTop:
    .size __StackTop, . - __StackTop
    .section .heap
    .align 3
    #ifndef Heap_Size
    .equ Heap_Size, 0x00000100
    #endif
    .global __HeapBase
    .global __HeapLimit
    __HeapBase:
    .if Heap_Size
    .space Heap_Size
    .endif
    .size __HeapBase, . - __HeapBase
    __HeapLimit:
    .size __HeapLimit, . - __HeapLimit
    .section .vectors
    .align 2
    .global __Vectors
    __Vectors:
    .long __stack /* Top of Stack */
    .long Reset_Handler /* Reset Handler */
    .long NMI_Handler /* NMI Handler */
    .long HardFault_Handler /* Hard Fault Handler */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long SVC_Handler /* SVCall Handler */
    .long 0 /* Reserved */
    .long 0 /* Reserved */
    .long PendSV_Handler /* PendSV Handler */
    .long SysTick_Handler /* SysTick Handler */
    /* External interrupts */
    .long BOD_IRQHandler
    .long WDT_IRQHandler
    .long EINT0_IRQHandler
    .long EINT1_IRQHandler
    .long GPAB_IRQHandler
    .long GPCDF_IRQHandler
    .long PWMA_IRQHandler
    .long Default_Handler
    .long TMR0_IRQHandler
    .long TMR1_IRQHandler
    .long TMR2_IRQHandler
    .long TMR3_IRQHandler
    .long UART0_IRQHandler
    .long UART1_IRQHandler
    .long SPI0_IRQHandler
    .long SPI1_IRQHandler
    .long SPI2_IRQHandler
    .long SPI3_IRQHandler
    .long I2C0_IRQHandler
    .long I2C1_IRQHandler
    .long CAN0_IRQHandler
    .long CAN1_IRQHandler
    .long SC012_IRQHandler
    .long USBD_IRQHandler
    .long PS2_IRQHandler
    .long ACMP_IRQHandler
    .long PDMA_IRQHandler
    .long I2S_IRQHandler
    .long PWRWU_IRQHandler
    .long ADC_IRQHandler
    .long Default_Handler
    .long RTC_IRQHandler
    .size __Vectors, . - __Vectors
    .text
    .thumb
    .thumb_func
    .align 2
    .global Reset_Handler
    .type Reset_Handler, % function
    Reset_Handler:
    /* Firstly it copies data from read only memory to RAM. There are two schemes
    * to copy. One can copy more than one sections. Another can only copy
    * one section. The former scheme needs more instructions and read-only
    * data to implement than the latter.
    * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
    #ifdef __STARTUP_COPY_MULTIPLE
    /* Multiple sections scheme.
    *
    * Between symbol address __copy_table_start__ and __copy_table_end__,
    * there are array of triplets, each of which specify:
    * offset 0: LMA of start of a section to copy from
    * offset 4: VMA of start of a section to copy to
    * offset 8: size of the section to copy. Must be multiply of 4
    *
    * All addresses must be aligned to 4 bytes boundary.
    */
    ldr r4, = __copy_table_start__
    ldr r5, = __copy_table_end__
    .L_loop0:
    cmp r4, r5
    bge .L_loop0_done
    ldr r1, [r4]
    ldr r2, [r4, #4]
    ldr r3, [r4, #8]
    .L_loop0_0:
    subs r3, #4
    blt .L_loop0_0_done
    ldr r0, [r1, r3]
    str r0, [r2, r3]
    b .L_loop0_0
    .L_loop0_0_done:
    adds r4, #12
    b .L_loop0
    .L_loop0_done:
    #else
    /* Single section scheme.
    *
    * The ranges of copy from/to are specified by following symbols
    * __etext: LMA of start of the section to copy from. Usually end of text
    * __data_start__: VMA of start of the section to copy to
    * __data_end__: VMA of end of the section to copy to
    *
    * All addresses must be aligned to 4 bytes boundary.
    */
    ldr r1, = __etext
    ldr r2, = __data_start__
    ldr r3, = __data_end__
    subs r3, r2
    ble .L_loop1_done
    .L_loop1:
    subs r3, #4
    ldr r0, [r1, r3]
    str r0, [r2, r3]
    bgt .L_loop1
    .L_loop1_done:
    #endif /*__STARTUP_COPY_MULTIPLE */
    /* This part of work usually is done in C library startup code. Otherwise,
    * define this macro to enable it in this startup.
    *
    * There are two schemes too. One can clear multiple BSS sections. Another
    * can only clear one section. The former is more size expensive than the
    * latter.
    *
    * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
    * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
    */
    #ifdef __STARTUP_CLEAR_BSS_MULTIPLE
    /* Multiple sections scheme.
    *
    * Between symbol address __copy_table_start__ and __copy_table_end__,
    * there are array of tuples specifying:
    * offset 0: Start of a BSS section
    * offset 4: Size of this BSS section. Must be multiply of 4
    */
    ldr r3, = __zero_table_start__
    ldr r4, = __zero_table_end__
    .L_loop2:
    cmp r3, r4
    bge .L_loop2_done
    ldr r1, [r3]
    ldr r2, [r3, #4]
    movs r0, 0
    .L_loop2_0:
    subs r2, #4
    blt .L_loop2_0_done
    str r0, [r1, r2]
    b .L_loop2_0
    .L_loop2_0_done:
    adds r3, #8
    b .L_loop2
    .L_loop2_done:

    #elif defined (__STARTUP_CLEAR_BSS)
    /* Single BSS section scheme.
    *
    * The BSS section is specified by following symbols
    * __bss_start__: start of the BSS section.
    * __bss_end__: end of the BSS section.
    *
    * Both addresses must be aligned to 4 bytes boundary.
    */
    ldr r1, = __bss_start__
    ldr r2, = __bss_end__

    movs r0, 0

    subs r2, r1
    ble .L_loop3_done

    .L_loop3:
    subs r2, #4
    str r0, [r1, r2]
    bgt .L_loop3
    .L_loop3_done:
    #endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
    #ifndef __NO_SYSTEM_INIT
    bl SystemInit
    #endif
    #ifndef __START
    #define __START _start
    #endif
    bl __START
    .pool
    .size Reset_Handler, . - Reset_Handler
    .align 1
    .thumb_func
    .weak Default_Handler
    .type Default_Handler, % function
    Default_Handler:
    b .
    .size Default_Handler, . - Default_Handler
    /* 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
    .weak \handler_name
    .set \handler_name, Default_Handler
    .endm
    def_irq_handler NMI_Handler
    def_irq_handler HardFault_Handler
    def_irq_handler SVC_Handler
    def_irq_handler PendSV_Handler
    def_irq_handler SysTick_Handler


    def_irq_handler BOD_IRQHandler
    def_irq_handler WDT_IRQHandler
    def_irq_handler EINT0_IRQHandler
    def_irq_handler EINT1_IRQHandler
    def_irq_handler GPAB_IRQHandler
    def_irq_handler GPCDF_IRQHandler
    def_irq_handler PWMA_IRQHandler
    def_irq_handler TMR0_IRQHandler
    def_irq_handler TMR1_IRQHandler
    def_irq_handler TMR2_IRQHandler
    def_irq_handler TMR3_IRQHandler
    def_irq_handler UART0_IRQHandler
    def_irq_handler UART1_IRQHandler
    def_irq_handler SPI0_IRQHandler
    def_irq_handler SPI1_IRQHandler
    def_irq_handler SPI2_IRQHandler
    def_irq_handler SPI3_IRQHandler
    def_irq_handler I2C0_IRQHandler
    def_irq_handler I2C1_IRQHandler
    def_irq_handler CAN0_IRQHandler
    def_irq_handler CAN1_IRQHandler
    def_irq_handler SC012_IRQHandler
    def_irq_handler USBD_IRQHandler
    def_irq_handler PS2_IRQHandler
    def_irq_handler ACMP_IRQHandler
    def_irq_handler PDMA_IRQHandler
    def_irq_handler I2S_IRQHandler
    def_irq_handler PWRWU_IRQHandler
    def_irq_handler ADC_IRQHandler
    def_irq_handler RTC_IRQHandler
    /* ;int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0) */
    .align 2
    .thumb_func
    .type SH_DoCommand, % function
    SH_DoCommand:
    BKPT 0xAB /* ; Wait ICE or HardFault */
    //LDR R3, = SH_Return
    MOV R4, lr
    BLX R3 /* ; Call SH_Return. The return value is in R0 */
    BX R4 /* ; Return value = R0 */
    .size SH_DoCommand, . - SH_DoCommand
    .align 2
    .thumb_func
    .global __PC
    .type __PC, % function
    .end