mirror of
https://github.com/dougg3/mac-rom-simm-programmer.git
synced 2024-12-01 19:50:18 +00:00
257d395cd2
Nuvoton's sample startup_M251.S file handles enough initialization for my purposes, so I can completely bypass _start and jump directly to main. Note that I also had to add a define to enable clearing of BSS.
395 lines
13 KiB
ArmAsm
395 lines
13 KiB
ArmAsm
/****************************************************************************//**
|
|
* @file startup_M251.S
|
|
* @version V1.00
|
|
* @brief CMSIS Cortex-M23 Core Device Startup File for M251
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
|
|
*****************************************************************************/
|
|
|
|
.syntax unified
|
|
.arch armv8-m.base
|
|
|
|
.section .stack
|
|
.align 3
|
|
#ifdef __STACK_SIZE
|
|
.equ Stack_Size, __STACK_SIZE
|
|
#else
|
|
.equ Stack_Size, 0x00000400
|
|
#endif
|
|
.globl __StackTop
|
|
.globl __StackLimit
|
|
__StackLimit:
|
|
.space Stack_Size
|
|
.size __StackLimit, . - __StackLimit
|
|
__StackTop:
|
|
.size __StackTop, . - __StackTop
|
|
|
|
.section .heap
|
|
.align 3
|
|
#ifdef __HEAP_SIZE
|
|
.equ Heap_Size, __HEAP_SIZE
|
|
#else
|
|
.equ Heap_Size, 0x00000100
|
|
#endif
|
|
.globl __HeapBase
|
|
.globl __HeapLimit
|
|
__HeapBase:
|
|
.if Heap_Size
|
|
.space Heap_Size
|
|
.endif
|
|
.size __HeapBase, . - __HeapBase
|
|
__HeapLimit:
|
|
.size __HeapLimit, . - __HeapLimit
|
|
|
|
.section .vectors
|
|
.align 2
|
|
.globl __Vectors
|
|
__Vectors:
|
|
.long __StackTop /* 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 /* 0: BOD */
|
|
.long IRCTRIM_IRQHandler /* 1: IRC */
|
|
.long PWRWU_IRQHandler /* 2: PWRWU */
|
|
.long Default_Handler /* 3: Reserved */
|
|
.long CLKFAIL_IRQHandler /* 4: CKFAIL */
|
|
.long Default_Handler /* 5: Reserved */
|
|
.long RTC_IRQHandler /* 6: RTC */
|
|
.long TAMPER_IRQHandler /* 7: TAMPER */
|
|
.long WDT_IRQHandler /* 8: WDT */
|
|
.long WWDT_IRQHandler /* 9: WWDT */
|
|
.long EINT0_IRQHandler /* 10: EINT0 */
|
|
.long EINT1_IRQHandler /* 11: EINT1 */
|
|
.long EINT2_IRQHandler /* 12: EINT2 */
|
|
.long EINT3_IRQHandler /* 13: EINT3 */
|
|
.long EINT4_IRQHandler /* 14: EINT4 */
|
|
.long EINT5_IRQHandler /* 15: EINT5 */
|
|
.long GPA_IRQHandler /* 16: GPA */
|
|
.long GPB_IRQHandler /* 17: GPB */
|
|
.long GPC_IRQHandler /* 18: GPC */
|
|
.long GPD_IRQHandler /* 19: GPD */
|
|
.long GPE_IRQHandler /* 20: GPE */
|
|
.long GPF_IRQHandler /* 21: GPF */
|
|
.long QSPI0_IRQHandler /* 22: QSPI0 */
|
|
.long SPI0_IRQHandler /* 23: SPI0 */
|
|
.long BRAKE0_IRQHandler /* 24: BRAKE0 */
|
|
.long PWM0_P0_IRQHandler /* 25: EPWM0P0 */
|
|
.long PWM0_P1_IRQHandler /* 26: EPWM0P1 */
|
|
.long PWM0_P2_IRQHandler /* 27: EPWM0P2 */
|
|
.long BRAKE1_IRQHandler /* 28: BRAKE1 */
|
|
.long PWM1_P0_IRQHandler /* 29: EPWM1P0 */
|
|
.long PWM1_P1_IRQHandler /* 30: EPWM1P1 */
|
|
.long PWM1_P2_IRQHandler /* 31: EPWM1P2 */
|
|
.long TMR0_IRQHandler /* 32: TIMER0 */
|
|
.long TMR1_IRQHandler /* 33: TIMER1 */
|
|
.long TMR2_IRQHandler /* 34: TIMER2 */
|
|
.long TMR3_IRQHandler /* 35: TIMER3 */
|
|
.long UART0_IRQHandler /* 36: UART0 */
|
|
.long UART1_IRQHandler /* 37: UART1 */
|
|
.long I2C0_IRQHandler /* 38: I2C0 */
|
|
.long I2C1_IRQHandler /* 39: I2C1 */
|
|
.long PDMA_IRQHandler /* 40: PDMA */
|
|
.long DAC_IRQHandler /* 41: DAC */
|
|
.long EADC_INT0_IRQHandler /* 42: EADC00 */
|
|
.long EADC_INT1_IRQHandler /* 43: EADC01 */
|
|
.long ACMP01_IRQHandler /* 44: ACMP */
|
|
.long BPWM0_IRQHandler /* 45: BPWM0 */
|
|
.long EADC_INT2_IRQHandler /* 46: EADC02 */
|
|
.long EADC_INT3_IRQHandler /* 47: EADC03 */
|
|
.long UART2_IRQHandler /* 48: UART2 */
|
|
.long Default_Handler /* 49: Reserved */
|
|
.long USCI0_IRQHandler /* 50: UCSI0 */
|
|
.long SPI1_IRQHandler /* 51: SPI1 */
|
|
.long USCI1_IRQHandler /* 52: USCI1 */
|
|
.long USBD_IRQHandler /* 53: USBD */
|
|
.long BPWM1_IRQHandler /* 54: BPWM1 */
|
|
.long PSIO_IRQHandler /* 55: PSIO */
|
|
.long Default_Handler /* 56: Reserved */
|
|
.long CRPT_IRQHandler /* 57: CRPT */
|
|
.long SC0_IRQHandler /* 58: SC0 */
|
|
.long Default_Handler /* 59: Reserved */
|
|
.long USCI2_IRQHandler /* 60: USCI2 */
|
|
.long LCD_IRQHandler /* 61: LCD */
|
|
.long OPA_IRQHandler /* 62: OPA */
|
|
.long TK_IRQHandler /* 63: TK */
|
|
|
|
.size __Vectors, . - __Vectors
|
|
|
|
.text
|
|
.thumb
|
|
.thumb_func
|
|
.align 2
|
|
.globl 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 */
|
|
|
|
#define __STARTUP_CLEAR_BSS
|
|
|
|
/* 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 define 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
|
|
str r0, [r1, r2]
|
|
bgt .L_loop2_0
|
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
/* Unlock Register */
|
|
ldr r0, =0x40000100
|
|
movw r1, 0x00000059
|
|
str r1, [r0]
|
|
movw r1, 0x00000016
|
|
str r1, [r0]
|
|
movw r1, 0x00000088
|
|
str r1, [r0]
|
|
|
|
|
|
#ifndef __NO_SYSTEM_INIT
|
|
bl SystemInit
|
|
#endif
|
|
|
|
/* Init POR */
|
|
#if 1
|
|
|
|
ldr r0, =0x40000024
|
|
movw r1, 0x00005AA5
|
|
str r1, [r0]
|
|
|
|
ldr r0, =0x400001EC
|
|
str r1, [r0]
|
|
#endif
|
|
|
|
/* Lock register */
|
|
ldr r0, =0x40000100
|
|
movw r1, 0x00000000
|
|
str r1, [r0]
|
|
|
|
#define __START main
|
|
#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 IRCTRIM_IRQHandler
|
|
def_irq_handler PWRWU_IRQHandler
|
|
def_irq_handler CLKFAIL_IRQHandler
|
|
def_irq_handler RTC_IRQHandler
|
|
def_irq_handler TAMPER_IRQHandler
|
|
def_irq_handler WDT_IRQHandler
|
|
def_irq_handler WWDT_IRQHandler
|
|
def_irq_handler EINT0_IRQHandler
|
|
def_irq_handler EINT1_IRQHandler
|
|
def_irq_handler EINT2_IRQHandler
|
|
def_irq_handler EINT3_IRQHandler
|
|
def_irq_handler EINT4_IRQHandler
|
|
def_irq_handler EINT5_IRQHandler
|
|
def_irq_handler GPA_IRQHandler
|
|
def_irq_handler GPB_IRQHandler
|
|
def_irq_handler GPC_IRQHandler
|
|
def_irq_handler GPD_IRQHandler
|
|
def_irq_handler GPE_IRQHandler
|
|
def_irq_handler GPF_IRQHandler
|
|
def_irq_handler QSPI0_IRQHandler
|
|
def_irq_handler SPI0_IRQHandler
|
|
def_irq_handler BRAKE0_IRQHandler
|
|
def_irq_handler PWM0_P0_IRQHandler
|
|
def_irq_handler PWM0_P1_IRQHandler
|
|
def_irq_handler PWM0_P2_IRQHandler
|
|
def_irq_handler BRAKE1_IRQHandler
|
|
def_irq_handler PWM1_P0_IRQHandler
|
|
def_irq_handler PWM1_P1_IRQHandler
|
|
def_irq_handler PWM1_P2_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 I2C0_IRQHandler
|
|
def_irq_handler I2C1_IRQHandler
|
|
def_irq_handler PDMA_IRQHandler
|
|
def_irq_handler DAC_IRQHandler
|
|
def_irq_handler EADC_INT0_IRQHandler
|
|
def_irq_handler EADC_INT1_IRQHandler
|
|
def_irq_handler ACMP01_IRQHandler
|
|
def_irq_handler BPWM0_IRQHandler
|
|
def_irq_handler EADC_INT2_IRQHandler
|
|
def_irq_handler EADC_INT3_IRQHandler
|
|
def_irq_handler UART2_IRQHandler
|
|
def_irq_handler USCI0_IRQHandler
|
|
def_irq_handler SPI1_IRQHandler
|
|
def_irq_handler USCI1_IRQHandler
|
|
def_irq_handler USBD_IRQHandler
|
|
def_irq_handler BPWM1_IRQHandler
|
|
def_irq_handler PSIO_IRQHandler
|
|
def_irq_handler CRPT_IRQHandler
|
|
def_irq_handler SC0_IRQHandler
|
|
def_irq_handler USCI2_IRQHandler
|
|
def_irq_handler LCD_IRQHandler
|
|
def_irq_handler OPA_IRQHandler
|
|
def_irq_handler TK_IRQHandler
|
|
|
|
|
|
.end
|