From 6dcbc3572d9de332adaef7c24c4754980098e3b2 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 12 May 2020 13:34:35 +0200 Subject: [PATCH] Psoc6: fixes for correct device bring-up --- .gdbinit | 1 + arch.mk | 1 + hal/psoc6.c | 30 +++- hal/psoc6.ld | 40 +++++ hal/psoc6_02_cm0plus.S | 378 +++++++++++++++++++++++++++++++++++++++++ src/boot_arm.c | 25 ++- 6 files changed, 461 insertions(+), 14 deletions(-) create mode 100644 hal/psoc6_02_cm0plus.S diff --git a/.gdbinit b/.gdbinit index 082ef20d..67391fbd 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,4 +1,5 @@ tar rem:3333 file wolfboot.elf foc c +mon psoc6 reset_halt diff --git a/arch.mk b/arch.mk index c804a88a..f14e6986 100644 --- a/arch.mk +++ b/arch.mk @@ -153,6 +153,7 @@ endif ifeq ($(TARGET),psoc6) CORTEX_M0=1 + OBJS+=hal/psoc6_02_cm0plus.o PKA_EXTRA_OBJS+= $(CYPRESS_PDL)/drivers/source/cy_flash.o \ $(CYPRESS_PDL)/drivers/source/cy_ipc_pipe.o \ $(CYPRESS_PDL)/drivers/source/cy_ipc_sema.o \ diff --git a/hal/psoc6.c b/hal/psoc6.c index bdd10dd0..4f688e3f 100644 --- a/hal/psoc6.c +++ b/hal/psoc6.c @@ -21,6 +21,7 @@ #include #include +#include #include "image.h" #include "cy_device_headers.h" @@ -31,9 +32,12 @@ #include "cy_syslib.h" #include "cy_ipc_drv.h" -#define ROW_SIZE (0x200) +#define ROW_SIZE (0x1000) +#define FLASH_BASE_ADDRESS (0x10000000) #define CPU_FREQ (100000000) +uint8_t psoc6_write_buffer[ROW_SIZE]; + #ifndef NVM_FLASH_WRITEONCE # error "wolfBoot psoc6 HAL: no WRITEONCE support detected. Please define NVM_FLASH_WRITEONCE" #endif @@ -67,10 +71,9 @@ static const cy_stc_pll_manual_config_t srss_0_clock_0_pll_0_pllConfig = .outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO, }; -void hal_init(void) +#define MPU_CTL *((volatile uint32_t *)(0xE000ED90)) +static void hal_set_pll(void) { - SystemInit(); -#if 0 /*Set clock path 1 source to IMO, this feeds PLL1*/ Cy_SysClk_ClkPathSetSource(1U, CY_SYSCLK_CLKPATH_IN_IMO); @@ -97,8 +100,15 @@ void hal_init(void) while(1) ; } -#endif +} + +void hal_init(void) +{ + MPU_CTL = 0; + //SystemInit(); + Cy_PDL_Init(CY_DEVICE_CFG); Cy_Flash_Init(); + //hal_set_pll(); } void hal_prepare_boot(void) @@ -114,10 +124,18 @@ void hal_prepare_boot(void) */ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { + const uint8_t *src = data; if (len < NVM_CACHE_SIZE) return -1; + if ((((uint32_t)data) & FLASH_BASE_ADDRESS) == FLASH_BASE_ADDRESS) { + if (len != ROW_SIZE) { + return -1; + } + memcpy(psoc6_write_buffer, data, len); + src = psoc6_write_buffer; + } while (len) { - Cy_Flash_WriteRow(address, (const uint32_t *) data); + Cy_Flash_ProgramRow(address, (const uint32_t *) src); len -= NVM_CACHE_SIZE; if ((len > 0) && (len < NVM_CACHE_SIZE)) return -1; diff --git a/hal/psoc6.ld b/hal/psoc6.ld index 98cabaa9..03ef304b 100644 --- a/hal/psoc6.ld +++ b/hal/psoc6.ld @@ -12,6 +12,7 @@ SECTIONS _start_text = .; __Vectors = .; KEEP(*(.isr_vector)) + KEEP(*(.vectors)) . = ALIGN(0x400); *(.text*) *(.rodata*) @@ -19,6 +20,7 @@ SECTIONS *(.fini*) . = ALIGN(4); _end_text = .; + __etext = .; } > FLASH .edidx : @@ -32,21 +34,55 @@ SECTIONS .data : AT (_stored_data) { _start_data = .; + __data_start__ = .; + KEEP(*(.data*)) . = ALIGN(4); + KEEP(*(.ramcode)) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + + KEEP(*(.cy_ramfunc*)) + . = ALIGN(4); + _end_data = .; + __data_end__ = .; + } > RAM .bss (NOLOAD) : { _start_bss = .; __bss_start__ = .; + __zero_table_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); _end_bss = .; __bss_end__ = .; + __zero_table_end__ = .; _end = .; + . = ALIGN(0x100); __ramVectors = .; } > RAM . = ALIGN(4); @@ -54,3 +90,7 @@ SECTIONS END_STACK = ORIGIN(RAM) + LENGTH(RAM); +__StackTop = ORIGIN(RAM) + LENGTH(RAM); +__StackLimit = __StackTop - 0x4000; +PROVIDE(__stack = __StackTop); + diff --git a/hal/psoc6_02_cm0plus.S b/hal/psoc6_02_cm0plus.S new file mode 100644 index 00000000..c49e209e --- /dev/null +++ b/hal/psoc6_02_cm0plus.S @@ -0,0 +1,378 @@ +/**************************************************************************//** + * @file startup_psoc6_02_cm0plus.S + * @brief CMSIS Core Device Startup File for + * ARMCM0plus Device Series + * @version V5.00 + * @date 02. March 2016 + ******************************************************************************/ +/* + * Copyright (c) 2009-2016 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /* Address of the NMI handler */ + #define CY_NMI_HANLDER_ADDR 0x0000000D + + /* The CPU VTOR register */ + #define CY_CPU_VTOR_ADDR 0xE000ED08 + + /* DONT / Copy flash vectors and data section to RAM */ + // DONT / #define __STARTUP_COPY_MULTIPLE + + // #define RAM_VECTORS + + #define __NO_SYSTEM_INIT + + /* Clear single BSS section */ + #define __STARTUP_CLEAR_BSS + + .syntax unified + .arch armv6-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0x00001000 +#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, 0x00000400 +#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 CY_NMI_HANLDER_ADDR /* 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 Description */ + .long NvicMux0_IRQHandler /* CPU User Interrupt #0 */ + .long NvicMux1_IRQHandler /* CPU User Interrupt #1 */ + .long NvicMux2_IRQHandler /* CPU User Interrupt #2 */ + .long NvicMux3_IRQHandler /* CPU User Interrupt #3 */ + .long NvicMux4_IRQHandler /* CPU User Interrupt #4 */ + .long NvicMux5_IRQHandler /* CPU User Interrupt #5 */ + .long NvicMux6_IRQHandler /* CPU User Interrupt #6 */ + .long NvicMux7_IRQHandler /* CPU User Interrupt #7 */ + .long Internal0_IRQHandler /* Internal SW Interrupt #0 */ + .long Internal1_IRQHandler /* Internal SW Interrupt #1 */ + .long Internal2_IRQHandler /* Internal SW Interrupt #2 */ + .long Internal3_IRQHandler /* Internal SW Interrupt #3 */ + .long Internal4_IRQHandler /* Internal SW Interrupt #4 */ + .long Internal5_IRQHandler /* Internal SW Interrupt #5 */ + .long Internal6_IRQHandler /* Internal SW Interrupt #6 */ + .long Internal7_IRQHandler /* Internal SW Interrupt #7 */ + + .size __Vectors, . - __Vectors + .equ __VectorsSize, . - __Vectors + + .section .ram_vectors + .align 2 + .globl __ramVectors +__ramVectors: + .space __VectorsSize + .size __ramVectors, . - __ramVectors + + + .text + .thumb + .thumb_func + .align 2 + + /* + * Device startup customization + * + * Note. The global resources are not yet initialized (for example global variables, peripherals, clocks) + * because this function is executed as the first instruction in the ResetHandler. + * The PDL is also not initialized to use the proper register offsets. + * The user of this function is responsible for initializing the PDL and resources before using them. + */ + .weak Cy_OnResetUser + .func Cy_OnResetUser, Cy_OnResetUser + .type Cy_OnResetUser, %function + +Cy_OnResetUser: + bx lr + .size Cy_OnResetUser, . - Cy_OnResetUser + .endfunc + + /* Reset handler */ + .weak Reset_Handler + .type Reset_Handler, %function + +Reset_Handler: + bl Cy_OnResetUser + cpsid i + +/* 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 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 + 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 */ + +#ifdef RAM_VECTORS + /* Update Vector Table Offset Register. */ + ldr r0, =__ramVectors + ldr r1, =CY_CPU_VTOR_ADDR + str r0, [r1] + dsb 0xF +#endif + +#ifndef __NO_SYSTEM_INIT + bl SystemInit +#endif + + bl main + + /* Should never get here */ + b . + + .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 + .weak Cy_SysLib_FaultHandler + .type Cy_SysLib_FaultHandler, %function + +Cy_SysLib_FaultHandler: + b . + .size Cy_SysLib_FaultHandler, . - Cy_SysLib_FaultHandler + .type Fault_Handler, %function + +Fault_Handler: + /* Storing LR content for Creator call stack trace */ + push {LR} + movs r0, #4 + mov r1, LR + tst r0, r1 + beq .L_MSP + mrs r0, PSP + b .L_API_call +.L_MSP: + mrs r0, MSP +.L_API_call: + /* Compensation of stack pointer address due to pushing 4 bytes of LR */ + adds r0, r0, #4 + bl Cy_SysLib_FaultHandler + b . + .size Fault_Handler, . - Fault_Handler + +.macro def_fault_Handler fault_handler_name + .weak \fault_handler_name + .set \fault_handler_name, Fault_Handler + .endm + +/* 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_fault_Handler HardFault_Handler + + def_irq_handler SVC_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + + def_irq_handler NvicMux0_IRQHandler /* CPU User Interrupt #0 */ + def_irq_handler NvicMux1_IRQHandler /* CPU User Interrupt #1 */ + def_irq_handler NvicMux2_IRQHandler /* CPU User Interrupt #2 */ + def_irq_handler NvicMux3_IRQHandler /* CPU User Interrupt #3 */ + def_irq_handler NvicMux4_IRQHandler /* CPU User Interrupt #4 */ + def_irq_handler NvicMux5_IRQHandler /* CPU User Interrupt #5 */ + def_irq_handler NvicMux6_IRQHandler /* CPU User Interrupt #6 */ + def_irq_handler NvicMux7_IRQHandler /* CPU User Interrupt #7 */ + def_irq_handler Internal0_IRQHandler /* Internal SW Interrupt #0 */ + def_irq_handler Internal1_IRQHandler /* Internal SW Interrupt #1 */ + def_irq_handler Internal2_IRQHandler /* Internal SW Interrupt #2 */ + def_irq_handler Internal3_IRQHandler /* Internal SW Interrupt #3 */ + def_irq_handler Internal4_IRQHandler /* Internal SW Interrupt #4 */ + def_irq_handler Internal5_IRQHandler /* Internal SW Interrupt #5 */ + def_irq_handler Internal6_IRQHandler /* Internal SW Interrupt #6 */ + def_irq_handler Internal7_IRQHandler /* Internal SW Interrupt #7 */ + + .end + + +/* [] END OF FILE */ diff --git a/src/boot_arm.c b/src/boot_arm.c index 227d8bb9..c203ed5a 100644 --- a/src/boot_arm.c +++ b/src/boot_arm.c @@ -35,6 +35,8 @@ extern uint32_t *END_STACK; extern void main(void); +#if !defined(PLATFORM_psoc6) + void isr_reset(void) { register unsigned int *src, *dst; #if defined(PLATFORM_kinetis) @@ -75,7 +77,8 @@ void isr_empty(void) /* Ignore unmapped event and continue */ } -#define VTOR (*(volatile uint32_t *)(0xE000ED08)) +#endif + /* This is the main loop for the bootloader. * @@ -87,6 +90,7 @@ void isr_empty(void) * - Call the application entry point * */ +#define VTOR (*(volatile uint32_t *)(0xE000ED08)) static void *app_entry; static uint32_t app_end_stack; @@ -97,12 +101,8 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset) #ifndef NO_VTOR /* Disable interrupts */ asm volatile("cpsid i"); - #ifdef PLATFORM_psoc6 - VTOR = (((uint32_t)(app_offset)) - ARCH_FLASH_OFFSET); - #else - /* Update IV */ - VTOR = ((uint32_t)app_offset); - #endif + /* Update IV */ + VTOR = ((uint32_t)app_offset); #endif /* Get stack pointer, entry point */ @@ -118,12 +118,20 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset) asm volatile("mov pc, %0" ::"r"(app_entry)); } +#ifdef PLATFORM_psoc6 +typedef void(*NMIHANDLER)(void); +# define isr_NMI (NMIHANDLER)(0x0000000D) +#else +# define isr_NMI isr_empty +#endif + +#ifndef PLATFORM_psoc6 __attribute__ ((section(".isr_vector"))) void (* const IV[])(void) = { (void (*)(void))(&END_STACK), isr_reset, // Reset - isr_fault, // NMI + isr_NMI, // NMI isr_fault, // HardFault isr_fault, // MemFault isr_fault, // BusFault @@ -180,6 +188,7 @@ void (* const IV[])(void) = isr_empty, isr_empty, }; +#endif /* ! TARGET_psoc6 */ #ifdef RAM_CODE