SAME70 TCM code relocation does not work

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've followed this thread using agporsch's version to set up the use of TCM and slightly adapted the content for Atmel's latest linker script generated by START. My code compiles fine (except for a warning about 'pSrcEnd' not used) but when I set a break point in main.c, and look at the disassembled code, I don't see it relocated to 0x00200000. It's still at 0x00400000.

 

I am not familiar with linker scripts, so I don't know how to debug this. As far as I can tell, nothing has to be customized for my application. Can someone confirm?

 

I've tried compiling with and without optimization.

 

Here's the linker script same70q21b_flash.ld:

/**
 * Code found here: https://www.avrfreaks.net/forum/sams70-tcm-setup?skey=tcm
 *
 * \file
 *
 * \brief GCC linker script (flash) for ATSAME70Q21B
 *
 * Copyright (c) 2019 Microchip Technology Inc.
 *
 * \license_start
 *
 * \page License

 *
 * 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
 *
 *   http://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.
 *
 * \license_stop
 *
 */

/*----------------------------------------------------------------------------
 *      Linker script for running in internal FLASH on the ATSAME70Q21
 *----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
itcm_vectors (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000400 /* Vector table at beginning of ITCM */
itcm (rx)         : ORIGIN = 0x00000400, LENGTH = 0x0001FC00 /* Fast code in ITCM */
rom (rx)          : ORIGIN = 0x00400000, LENGTH = 0x00200000 /* rom, 2097152K */
dtcm (rw)         : ORIGIN = 0x20000000, LENGTH = 0x00020000 /* Fast data/bss in DTCM */
ram (rwx)         : ORIGIN = 0x20400000, LENGTH = 0x00060000 /* ram, 393216K */
}

/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE      = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
DTCM_STACK_SIZE = DEFINED(DTCM_STACK_SIZE) ? DTCM_STACK_SIZE : 0x2000;
__ram_end__     = ORIGIN(ram) + LENGTH(ram) - 4;

/* The heapsize used by the application. NOTE: you need to adjust according to your application. */
HEAP_SIZE       = DEFINED(HEAP_SIZE) ? HEAP_SIZE : DEFINED(__heap_size__) ? __heap_size__ : 0x0200;

/* Section Definitions */
SECTIONS
{
    .fast_vectors (NOLOAD) :
    {
        . = ALIGN(4);
        _srelocate_vectors = .;
    } > itcm_vectors

    .fast_code : AT (_etext)
    {
        . = ALIGN(4);
        _s_fast_code = .;
        _s_fast_code_from = LOADADDR(.fast_code);
        *(.itcm_functions);
        _e_fast_code = .;
        _e_fast_code_from = LOADADDR(.fast_code) + SIZEOF(.fast_code);
    } > itcm

    .text :
    {
        . = ALIGN(4);
        _sfixed = .;
        KEEP(*(.vectors .vectors.*))
        *(.text .text.* .gnu.linkonce.t.*)
        *(.glue_7t) *(.glue_7)
        *(.rodata .rodata* .gnu.linkonce.r.*)
        *(.ARM.extab* .gnu.linkonce.armextab.*)
        /* Support C constructors, and C destructors in both user code
           and the C library. This also provides support for C++ code. */
        . = ALIGN(4);
        KEEP(*(.init))
        . = ALIGN(4);
        __preinit_array_start = .;
        KEEP (*(.preinit_array))
        __preinit_array_end = .;
        . = ALIGN(4);
        __init_array_start = .;
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        __init_array_end = .;
        . = ALIGN(4);
        KEEP (*crtbegin.o(.ctors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
        KEEP (*(SORT(.ctors.*)))
        KEEP (*crtend.o(.ctors))
        . = ALIGN(4);
        KEEP(*(.fini))
        . = ALIGN(4);
        __fini_array_start = .;
        KEEP (*(.fini_array))
        KEEP (*(SORT(.fini_array.*)))
        __fini_array_end = .;
        KEEP (*crtbegin.o(.dtors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
        KEEP (*(SORT(.dtors.*)))
        KEEP (*crtend.o(.dtors))
        . = ALIGN(4);
        _efixed = .;            /* End of text section */
    } > rom

    /* .ARM.exidx is sorted, so has to go in its own output section.  */
    PROVIDE_HIDDEN (__exidx_start = .);
    .ARM.exidx :
    {
      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > rom
    PROVIDE_HIDDEN (__exidx_end = .);
    . = ALIGN(4);
    _etext = .;

    /* Slow data segment listed first */
    /* Only a few modules are listed here */
    /* Uses system memory */
    .data : AT (_etext + SIZEOF(.fast_code))
    {
        . = ALIGN(4);
        _sdata = .;
        _sdata_from = LOADADDR(.data);
        . = ALIGN(4);
        _edata = .;
        _edata_from = LOADADDR(.data) + SIZEOF(.data);
    } > ram

    /* Slow BSS segment listed first */
    /* Only a few modules are listed here */
    /* Uses system memory */
    .bss (NOLOAD) :
    {
        . = ALIGN(4);
        _sbss = . ;
        _szero = .;
        . = ALIGN(4);
        _ebss = . ;
        _ezero = .;
    } > dtcm

    /* Fast data segment takes all remaining */
    /* modules, uses the TCM */
    .fast_data : AT (_etext + SIZEOF(.fast_code) + SIZEOF(.data))
    {
        . = ALIGN(4);
        _s_fast_data = .;
        _s_fast_data_from = LOADADDR(.fast_data);
        *(.data .data.*);
        . = ALIGN(4);
        _e_fast_data = .;
        _e_fast_data_from = LOADADDR(.fast_data) + SIZEOF(.fast_data);
    } > dtcm

    /* Fast BSS segment takes all remaining */
    /* modules, uses the TCM */
    .fast_bss (NOLOAD) :
    {
        . = ALIGN(4);
        _s_fast_bss = . ;
        _s_fast_zero = .;
        *(.bss .bss.*)
        *(COMMON)
        . = ALIGN(4);
        _e_fast_bss = . ;
        _e_fast_zero = .;
    } > dtcm

    /* heap section - needs to be listed before stack since heap grows up in address space */
    .heap (NOLOAD):
    {
        . = ALIGN(8);
        _sheap = .;
        . = . + HEAP_SIZE;
        . = ALIGN(8);
        _eheap = .;
    } > dtcm

    /* startup stack section. Stack needed just for reset_handler, just to get us through operation where we check TCM bits in GPNVM */
    .stack (NOLOAD):
    {
        . = ALIGN(8);
        _sstack = .;
        . = . + STACK_SIZE;
        . = ALIGN(8);
        _estack = .;
    } > ram

    .runtime_stack (NOLOAD):
    {
        . = ALIGN(8);
        _s_runtime_stack = .;
        . = . + DTCM_STACK_SIZE;
        . = ALIGN(8);
        _e_runtime_stack = .;
    } > dtcm

    . = ALIGN(4);
    _end = . ;
    _ram_end_ = ORIGIN(ram) + LENGTH(ram) - 1 ;
}

 

And here's the content of startup_same70q21b.c:

/**
 * \file
 *
 * \brief GCC startup file for ATSAME70Q21B
 *
 * Copyright (c) 2019 Microchip Technology Inc.
 *
 * \license_start
 *
 * \page License
 *
 * 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
 *
 *   http://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.
 *
 * \license_stop
 *
 */

#include "same70q21b.h"

extern uint32_t _s_fast_code_from;
extern uint32_t _e_fast_code_from;
extern uint32_t _s_fast_code;
extern uint32_t _e_fast_code;

extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sdata_from;
extern uint32_t _edata_from;

extern uint32_t _s_fast_data;
extern uint32_t _e_fast_data;
extern uint32_t _s_fast_data_from;
extern uint32_t _e_fast_data_from;

extern uint32_t _sbss;
extern uint32_t _ebss;

extern uint32_t _s_fast_bss;
extern uint32_t _e_fast_bss;

extern uint32_t _sstack;
extern uint32_t _estack;

extern uint32_t _e_runtime_stack;

/** \cond DOXYGEN_SHOULD_SKIP_THIS */
int main(void);
/** \endcond */

void __libc_init_array(void);

/* Default empty handler */
void Dummy_Handler(void);

/* Cortex-M7 core handlers */
void NonMaskableInt_Handler   ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HardFault_Handler        ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MemoryManagement_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void BusFault_Handler         ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UsageFault_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SVCall_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DebugMonitor_Handler     ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PendSV_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SysTick_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

/* Peripherals handlers */
void SUPC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RSTC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTT_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void WDT_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PMC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EFC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOA_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOB_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOD_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOE_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HSMCI_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SPI0_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SSC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC4_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC5_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AFEC0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DACC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PWM0_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ICM_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ACC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USBHS_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN0_INT0_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN0_INT1_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN1_INT0_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN1_INT1_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AFEC1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SPI1_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void QSPI_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART2_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART3_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART4_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC6_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC7_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC8_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC9_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC10_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC11_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AES_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TRNG_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void XDMAC_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ISI_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PWM1_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void FPU_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SDRAMC_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RSWDT_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CCW_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CCF_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q1_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q2_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void IXC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void I2SC0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void I2SC1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q3_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q4_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q5_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {

    /* Configure Initial Stack Pointer, using linker-generated symbols */
    .pvStack = (void*) (&_estack),

    .pfnReset_Handler              = (void*) Reset_Handler,
    .pfnNonMaskableInt_Handler     = (void*) NonMaskableInt_Handler,
    .pfnHardFault_Handler          = (void*) HardFault_Handler,
    .pfnMemoryManagement_Handler   = (void*) MemoryManagement_Handler,
    .pfnBusFault_Handler           = (void*) BusFault_Handler,
    .pfnUsageFault_Handler         = (void*) UsageFault_Handler,
    .pvReservedC9                  = (void*) (0UL), /* Reserved */
    .pvReservedC8                  = (void*) (0UL), /* Reserved */
    .pvReservedC7                  = (void*) (0UL), /* Reserved */
    .pvReservedC6                  = (void*) (0UL), /* Reserved */
    .pfnSVCall_Handler             = (void*) SVCall_Handler,
    .pfnDebugMonitor_Handler       = (void*) DebugMonitor_Handler,
    .pvReservedC3                  = (void*) (0UL), /* Reserved */
    .pfnPendSV_Handler             = (void*) PendSV_Handler,
    .pfnSysTick_Handler            = (void*) SysTick_Handler,

    /* Configurable interrupts */
    .pfnSUPC_Handler               = (void*) SUPC_Handler,   /* 0  Supply Controller */
    .pfnRSTC_Handler               = (void*) RSTC_Handler,   /* 1  Reset Controller */
    .pfnRTC_Handler                = (void*) RTC_Handler,    /* 2  Real-time Clock */
    .pfnRTT_Handler                = (void*) RTT_Handler,    /* 3  Real-time Timer */
    .pfnWDT_Handler                = (void*) WDT_Handler,    /* 4  Watchdog Timer */
    .pfnPMC_Handler                = (void*) PMC_Handler,    /* 5  Power Management Controller */
    .pfnEFC_Handler                = (void*) EFC_Handler,    /* 6  Embedded Flash Controller */
    .pfnUART0_Handler              = (void*) UART0_Handler,  /* 7  Universal Asynchronous Receiver Transmitter */
    .pfnUART1_Handler              = (void*) UART1_Handler,  /* 8  Universal Asynchronous Receiver Transmitter */
    .pvReserved9                   = (void*) (0UL),          /* 9  Reserved */
    .pfnPIOA_Handler               = (void*) PIOA_Handler,   /* 10 Parallel Input/Output Controller */
    .pfnPIOB_Handler               = (void*) PIOB_Handler,   /* 11 Parallel Input/Output Controller */
    .pfnPIOC_Handler               = (void*) PIOC_Handler,   /* 12 Parallel Input/Output Controller */
    .pfnUSART0_Handler             = (void*) USART0_Handler, /* 13 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnUSART1_Handler             = (void*) USART1_Handler, /* 14 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnUSART2_Handler             = (void*) USART2_Handler, /* 15 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnPIOD_Handler               = (void*) PIOD_Handler,   /* 16 Parallel Input/Output Controller */
    .pfnPIOE_Handler               = (void*) PIOE_Handler,   /* 17 Parallel Input/Output Controller */
    .pfnHSMCI_Handler              = (void*) HSMCI_Handler,  /* 18 High Speed MultiMedia Card Interface */
    .pfnTWIHS0_Handler             = (void*) TWIHS0_Handler, /* 19 Two-wire Interface High Speed */
    .pfnTWIHS1_Handler             = (void*) TWIHS1_Handler, /* 20 Two-wire Interface High Speed */
    .pfnSPI0_Handler               = (void*) SPI0_Handler,   /* 21 Serial Peripheral Interface */
    .pfnSSC_Handler                = (void*) SSC_Handler,    /* 22 Synchronous Serial Controller */
    .pfnTC0_Handler                = (void*) TC0_Handler,    /* 23 Timer Counter */
    .pfnTC1_Handler                = (void*) TC1_Handler,    /* 24 Timer Counter */
    .pfnTC2_Handler                = (void*) TC2_Handler,    /* 25 Timer Counter */
    .pfnTC3_Handler                = (void*) TC3_Handler,    /* 26 Timer Counter */
    .pfnTC4_Handler                = (void*) TC4_Handler,    /* 27 Timer Counter */
    .pfnTC5_Handler                = (void*) TC5_Handler,    /* 28 Timer Counter */
    .pfnAFEC0_Handler              = (void*) AFEC0_Handler,  /* 29 Analog Front-End Controller */
    .pfnDACC_Handler               = (void*) DACC_Handler,   /* 30 Digital-to-Analog Converter Controller */
    .pfnPWM0_Handler               = (void*) PWM0_Handler,   /* 31 Pulse Width Modulation Controller */
    .pfnICM_Handler                = (void*) ICM_Handler,    /* 32 Integrity Check Monitor */
    .pfnACC_Handler                = (void*) ACC_Handler,    /* 33 Analog Comparator Controller */
    .pfnUSBHS_Handler              = (void*) USBHS_Handler,  /* 34 USB High-Speed Interface */
    .pfnMCAN0_INT0_Handler         = (void*) MCAN0_INT0_Handler, /* 35 Controller Area Network */
    .pfnMCAN0_INT1_Handler         = (void*) MCAN0_INT1_Handler, /* 36 Controller Area Network */
    .pfnMCAN1_INT0_Handler         = (void*) MCAN1_INT0_Handler, /* 37 Controller Area Network */
    .pfnMCAN1_INT1_Handler         = (void*) MCAN1_INT1_Handler, /* 38 Controller Area Network */
    .pfnGMAC_Handler               = (void*) GMAC_Handler,   /* 39 Gigabit Ethernet MAC */
    .pfnAFEC1_Handler              = (void*) AFEC1_Handler,  /* 40 Analog Front-End Controller */
    .pfnTWIHS2_Handler             = (void*) TWIHS2_Handler, /* 41 Two-wire Interface High Speed */
    .pfnSPI1_Handler               = (void*) SPI1_Handler,   /* 42 Serial Peripheral Interface */
    .pfnQSPI_Handler               = (void*) QSPI_Handler,   /* 43 Quad Serial Peripheral Interface */
    .pfnUART2_Handler              = (void*) UART2_Handler,  /* 44 Universal Asynchronous Receiver Transmitter */
    .pfnUART3_Handler              = (void*) UART3_Handler,  /* 45 Universal Asynchronous Receiver Transmitter */
    .pfnUART4_Handler              = (void*) UART4_Handler,  /* 46 Universal Asynchronous Receiver Transmitter */
    .pfnTC6_Handler                = (void*) TC6_Handler,    /* 47 Timer Counter */
    .pfnTC7_Handler                = (void*) TC7_Handler,    /* 48 Timer Counter */
    .pfnTC8_Handler                = (void*) TC8_Handler,    /* 49 Timer Counter */
    .pfnTC9_Handler                = (void*) TC9_Handler,    /* 50 Timer Counter */
    .pfnTC10_Handler               = (void*) TC10_Handler,   /* 51 Timer Counter */
    .pfnTC11_Handler               = (void*) TC11_Handler,   /* 52 Timer Counter */
    .pvReserved53                  = (void*) (0UL),          /* 53 Reserved */
    .pvReserved54                  = (void*) (0UL),          /* 54 Reserved */
    .pvReserved55                  = (void*) (0UL),          /* 55 Reserved */
    .pfnAES_Handler                = (void*) AES_Handler,    /* 56 Advanced Encryption Standard */
    .pfnTRNG_Handler               = (void*) TRNG_Handler,   /* 57 True Random Number Generator */
    .pfnXDMAC_Handler              = (void*) XDMAC_Handler,  /* 58 Extensible DMA Controller */
    .pfnISI_Handler                = (void*) ISI_Handler,    /* 59 Image Sensor Interface */
    .pfnPWM1_Handler               = (void*) PWM1_Handler,   /* 60 Pulse Width Modulation Controller */
    .pfnFPU_Handler                = (void*) FPU_Handler,    /* 61 Floating Point Unit */
    .pfnSDRAMC_Handler             = (void*) SDRAMC_Handler, /* 62 SDRAM Controller */
    .pfnRSWDT_Handler              = (void*) RSWDT_Handler,  /* 63 Reinforced Safety Watchdog Timer */
    .pfnCCW_Handler                = (void*) CCW_Handler,    /* 64 System Control Block */
    .pfnCCF_Handler                = (void*) CCF_Handler,    /* 65 System Control Block */
    .pfnGMAC_Q1_Handler            = (void*) GMAC_Q1_Handler, /* 66 Gigabit Ethernet MAC */
    .pfnGMAC_Q2_Handler            = (void*) GMAC_Q2_Handler, /* 67 Gigabit Ethernet MAC */
    .pfnIXC_Handler                = (void*) IXC_Handler,    /* 68 Floating Point Unit */
    .pfnI2SC0_Handler              = (void*) I2SC0_Handler,  /* 69 Inter-IC Sound Controller */
    .pfnI2SC1_Handler              = (void*) I2SC1_Handler,  /* 70 Inter-IC Sound Controller */
    .pfnGMAC_Q3_Handler            = (void*) GMAC_Q3_Handler, /* 71 Gigabit Ethernet MAC */
    .pfnGMAC_Q4_Handler            = (void*) GMAC_Q4_Handler, /* 72 Gigabit Ethernet MAC */
    .pfnGMAC_Q5_Handler            = (void*) GMAC_Q5_Handler  /* 73 Gigabit Ethernet MAC */
};

/**
 * \brief This is the code that gets called on processor reset.
 * To initialize the device, and call the main() routine.
 *
 * With the compiler optimization set to O3, this Reset_Handler
 * function would hang when it gets to the section of code where it copies the vector
 * table to beginning of ITCM (Address 0)
 */
 __attribute__ ((optimize("O0")))

void Reset_Handler(void) {
    uint32_t *pSrc;
    uint32_t *pSrcEnd;
    uint32_t *pDest;
    uint32_t *pDestEnd;
    uint32_t ulEEFC_bits;
    uint32_t dtcm_stack_pointer_addr;

    // Configure TCM with maximum size
    // 128 KByte Data
    // 128 KByte Program

    __DSB(); __ISB();
    EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_GGPB);
    __DSB(); __ISB();

    while (!(EFC->EEFC_FSR & EEFC_FSR_FRDY));      //Wait until the status falls to 0 (EFFC command is complete)

    ulEEFC_bits = EFC->EEFC_FRR;

    if ((ulEEFC_bits & 0x180) != 0x180) {
        __DSB(); __ISB();
        EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(7));  //issue command to clear bit 7
        __DSB(); __ISB();
        while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));     //Wait until the status falls to 0 (EFFC command is complete)

        __DSB(); __ISB();
        EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(8));  //issue command to clear bit 8
        __DSB(); __ISB();
        while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));     //Wait until the status falls to 0 (EFFC command is complete)

        __DSB(); __ISB();
        RSTC->RSTC_CR = RSTC_CR_KEY_PASSWD | RSTC_CR_PROCRST;  //Trigger Reset
        __DSB(); __ISB();
    }

    // Enable DTCM and ITCM
    __DSB(); __ISB();
    SCB->ITCMCR = (SCB_DTCMCR_EN_Msk | SCB_DTCMCR_RMW_Msk | SCB_DTCMCR_RETEN_Msk);
    SCB->DTCMCR = (SCB_DTCMCR_EN_Msk | SCB_DTCMCR_RMW_Msk | SCB_DTCMCR_RETEN_Msk);
    __DSB(); __ISB();

    // Copy Vector Table to beginning of ITCM (Address 0)
    pSrc     = (uint32_t*) &exception_table;
    pDest    = (uint32_t*) 0;
    pDestEnd = (uint32_t*) sizeof (DeviceVectors);

    while (pDest < pDestEnd) *pDest++ = *pSrc++;

    // Copy fast Code from Flash into ITCM
    pSrc     = &_s_fast_code_from;
    pSrcEnd  = &_e_fast_code_from;
    pDest    = &_s_fast_code;
    pDestEnd = &_e_fast_code;

    while (pDest < pDestEnd) *pDest++ = *pSrc++;

    // Copy data segments into DTCM and System RAM
    pSrc     = &_sdata_from;
    pSrcEnd  = &_edata_from;
    pDest    = &_sdata;
    pDestEnd = &_edata;

    while (pDest < pDestEnd) *pDest++ = *pSrc++;

    pSrc     = &_s_fast_data_from;
    pSrcEnd  = &_e_fast_data_from;
    pDest    = &_s_fast_data;
    pDestEnd = &_e_fast_data;

    while (pDest < pDestEnd) *pDest++ = *pSrc++;

    // Clear the zero segments in DTCM and System RAM
    pDest    = &_sbss;
    pDestEnd = &_ebss;
    while (pDest < pDestEnd) *pDest++ = 0;

    pDest    = &_s_fast_bss;
    pDestEnd = &_e_fast_bss;
    while (pDest < pDestEnd) *pDest++ = 0;

    // Set the vector table base address
    // to the copied table in ITCM (Address 0)
    pSrc = (uint32_t *) 0;

    SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

    //Now that we're at the point in this routine where we don't need any stack variables,
    //update our stack pointer to the runtime stack pointer that lives in DTCM
    dtcm_stack_pointer_addr = (uint32_t) &_e_runtime_stack;

    //asm(code : output operand list : input operand list : clobber list);
    //write r1 with the address of DTCM where the beginning of the stack lives (per the linker)
    __ASM volatile ("mov.w r1, %0"::"r" (dtcm_stack_pointer_addr):"r1");
    //update the stack pointer with the stack address that lives in r1
    __ASM volatile("mov sp, r1");                                         

    __DSB(); __ISB();

    /* Initialize the C library */
    __libc_init_array();

    /* Branch to main function */
    main();

    /* Infinite loop */
    while (1) {}
}

/**
 * \brief Default interrupt handler for unused IRQs.
 */
void Dummy_Handler(void) {
    while (1) {}
}

 

This topic has a solution.
Last Edited: Sat. Apr 18, 2020 - 08:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like a section 

.fast_code 

is available but have you actually assigned any code there? Looks like there is an example of that in the linked thread, look for __attribute__((__section__...

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars, thanks a lot for pointing me in the right direction. I put __attribute__((__section__(".fast_code"))) just before main(). So I get something like this:

__attribute__((__section__(".fast_code")))
int main(void)
{
	atmel_start_init();

        ....
	
	while(1) {}
}

When I set the breakpoint at atmel_start_init() and run the debugger, I can see the PC near 0x00000000 but there's not the same code that used to be at 0x00400000, so the MCU jumps right to the Dummy_Handler(). I am not sure where to continue investigating. Maybe the code copy in the Reset_Handler() didn't do its job?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I figured out what the problem was. I used the original code from agporsch which, I believe, may have been for an older version of the linker. During debugging, I noticed that pDest and pDestEnd in the Reset_Handler() are always identical. I assume this is a bug in the latest version of the linker as it doesn't seem to provide the right values for the external values for the end variables. Here are the two working files that I beautified a bit:

 

sam70q21b_flash.ld:

/**
 * Code found here: https://www.avrfreaks.net/forum/sams70-tcm-setup?skey=tcm
 *
 * \file
 *
 * \brief GCC linker script (flash) for ATSAME70Q21B
 *
 * Copyright (c) 2019 Microchip Technology Inc.
 *
 * \license_start
 *
 * \page License

 *
 * 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
 *
 *   http://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.
 *
 * \license_stop
 *
 */

/*----------------------------------------------------------------------------
 *      Linker script for running in internal FLASH on the ATSAME70Q21
 *----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)

/* Memory Spaces Definitions */
MEMORY
{
itcm_vectors (rx) : ORIGIN = 0x00000000, LENGTH = 0x00000400 /* Vector table at beginning of ITCM */
itcm (rx)         : ORIGIN = 0x00000400, LENGTH = 0x0001FC00 /* Fast code in ITCM */
rom (rx)          : ORIGIN = 0x00400000, LENGTH = 0x00200000 /* rom, 2097152K */
dtcm (rw)         : ORIGIN = 0x20000000, LENGTH = 0x00020000 /* Fast data/bss in DTCM */
ram (rwx)         : ORIGIN = 0x20400000, LENGTH = 0x00060000 /* ram, 393216K */
}

/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE      = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
DTCM_STACK_SIZE = DEFINED(DTCM_STACK_SIZE) ? DTCM_STACK_SIZE : 0x2000;
__ram_end__     = ORIGIN(ram) + LENGTH(ram) - 4;

/* The heapsize used by the application. NOTE: you need to adjust according to your application. */
HEAP_SIZE       = DEFINED(HEAP_SIZE) ? HEAP_SIZE : DEFINED(__heap_size__) ? __heap_size__ : 0x0200;

/* Section Definitions */
SECTIONS
{
	.fast_vectors (NOLOAD) :
	{
		. = ALIGN(4);
		_srelocate_vectors = .;
	} > itcm_vectors

	.fast_code : AT (_etext)
	{
		. = ALIGN(4);
		_s_fast_code = .;
		_s_fast_code_from = LOADADDR(.fast_code);
		*(.itcm_functions);
		_e_fast_code = .;
		_e_fast_code_from = LOADADDR(.fast_code) + SIZEOF(.fast_code);
	} > itcm

    .text :
    {
        . = ALIGN(4);
        _sfixed = .;
        KEEP(*(.vectors .vectors.*))
        *(.text .text.* .gnu.linkonce.t.*)
        *(.glue_7t) *(.glue_7)
        *(.rodata .rodata* .gnu.linkonce.r.*)
        *(.ARM.extab* .gnu.linkonce.armextab.*)
        /* Support C constructors, and C destructors in both user code
           and the C library. This also provides support for C++ code. */
        . = ALIGN(4);
        KEEP(*(.init))
        . = ALIGN(4);
        __preinit_array_start = .;
        KEEP (*(.preinit_array))
        __preinit_array_end = .;
        . = ALIGN(4);
        __init_array_start = .;
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        __init_array_end = .;
        . = ALIGN(4);
        KEEP (*crtbegin.o(.ctors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
        KEEP (*(SORT(.ctors.*)))
        KEEP (*crtend.o(.ctors))
        . = ALIGN(4);
        KEEP(*(.fini))
        . = ALIGN(4);
        __fini_array_start = .;
        KEEP (*(.fini_array))
        KEEP (*(SORT(.fini_array.*)))
        __fini_array_end = .;
        KEEP (*crtbegin.o(.dtors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
        KEEP (*(SORT(.dtors.*)))
        KEEP (*crtend.o(.dtors))
        . = ALIGN(4);
        _efixed = .;            /* End of text section */
    } > rom

    /* .ARM.exidx is sorted, so has to go in its own output section.  */
    PROVIDE_HIDDEN (__exidx_start = .);
    .ARM.exidx :
    {
      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > rom
    PROVIDE_HIDDEN (__exidx_end = .);
    . = ALIGN(4);
    _etext = .;

    /* Slow data segment listed first */
    /* Only a few modules are listed here */
    /* Uses system memory */
    .data : AT (_etext + SIZEOF(.fast_code))
    {
        . = ALIGN(4);
        _sdata = .;
        _sdata_from = LOADADDR(.data);
        . = ALIGN(4);
        _edata = .;
        _edata_from = LOADADDR(.data) + SIZEOF(.data);
    } > ram

    /* Slow BSS segment listed first */
    /* Only a few modules are listed here */
    /* Uses system memory */
    .bss (NOLOAD) :
    {
        . = ALIGN(4);
        _sbss = . ;
        _szero = .;
        . = ALIGN(4);
        _ebss = . ;
        _ezero = .;
    } > dtcm

    /* Fast data segment takes all remaining */
    /* modules, uses the TCM */
    .fast_data : AT (_etext + SIZEOF(.fast_code) + SIZEOF(.data))
    {
        . = ALIGN(4);
        _s_fast_data = .;
        _s_fast_data_from = LOADADDR(.fast_data);
        *(.data .data.*);
        . = ALIGN(4);
        _e_fast_data = .;
        _e_fast_data_from = LOADADDR(.fast_data) + SIZEOF(.fast_data);
    } > dtcm

    /* Fast BSS segment takes all remaining */
    /* modules, uses the TCM */
    .fast_bss (NOLOAD) :
    {
        . = ALIGN(4);
        _s_fast_bss = . ;
        _s_fast_zero = .;
        *(.bss .bss.*)
        *(COMMON)
        . = ALIGN(4);
        _e_fast_bss = . ;
        _e_fast_zero = .;
    } > dtcm

    /* heap section - needs to be listed before stack since heap grows up in address space */
    .heap (NOLOAD):
    {
        . = ALIGN(8);
        _sheap = .;
        . = . + HEAP_SIZE;
        . = ALIGN(8);
        _eheap = .;
    } > dtcm

    /* startup stack section. Stack needed just for reset_handler, just to get us through operation where we check TCM bits in GPNVM */
    .stack (NOLOAD):
    {
        . = ALIGN(8);
        _sstack = .;
        . = . + STACK_SIZE;
        . = ALIGN(8);
        _estack = .;
    } > ram

    .runtime_stack (NOLOAD):
    {
        . = ALIGN(8);
        _s_runtime_stack = .;
        . = . + DTCM_STACK_SIZE;
        . = ALIGN(8);
        _e_runtime_stack = .;
    } > dtcm

    . = ALIGN(4);
    _end = . ;
    _ram_end_ = ORIGIN(ram) + LENGTH(ram) - 1 ;
}

 

startup_same70q21b.c:

/**
 * \file
 *
 * \brief GCC startup file for ATSAME70Q21B
 *
 * Copyright (c) 2019 Microchip Technology Inc.
 *
 * \license_start
 *
 * \page License
 *
 * 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
 *
 *   http://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.
 *
 * \license_stop
 *
 */

#include "same70q21b.h"

extern uint32_t _s_fast_code_from;
extern uint32_t _e_fast_code_from;
extern uint32_t _s_fast_code;
extern uint32_t _e_fast_code;

extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sdata_from;
extern uint32_t _edata_from;

extern uint32_t _s_fast_data;
extern uint32_t _e_fast_data;
extern uint32_t _s_fast_data_from;
extern uint32_t _e_fast_data_from;

extern uint32_t _sbss;
extern uint32_t _ebss;

extern uint32_t _s_fast_bss;
extern uint32_t _e_fast_bss;

extern uint32_t _sstack;
extern uint32_t _estack;

extern uint32_t _e_runtime_stack;

/** \cond DOXYGEN_SHOULD_SKIP_THIS */
int main(void);
/** \endcond */

void __libc_init_array(void);

/* Default empty handler */
void Dummy_Handler(void);

/* Cortex-M7 core handlers */
void NonMaskableInt_Handler   ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HardFault_Handler        ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MemoryManagement_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void BusFault_Handler         ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UsageFault_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SVCall_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DebugMonitor_Handler     ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PendSV_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SysTick_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

/* Peripherals handlers */
void SUPC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RSTC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTT_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void WDT_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PMC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EFC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOA_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOB_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USART2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOD_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PIOE_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HSMCI_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SPI0_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SSC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC4_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC5_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AFEC0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DACC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PWM0_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ICM_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ACC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USBHS_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN0_INT0_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN0_INT1_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN1_INT0_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCAN1_INT1_Handler       ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AFEC1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TWIHS2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SPI1_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void QSPI_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART2_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART3_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UART4_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC6_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC7_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC8_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC9_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC10_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC11_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AES_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TRNG_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void XDMAC_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void ISI_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PWM1_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void FPU_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SDRAMC_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RSWDT_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CCW_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CCF_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q1_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q2_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void IXC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void I2SC0_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void I2SC1_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q3_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q4_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void GMAC_Q5_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {

    /* Configure Initial Stack Pointer, using linker-generated symbols */
    .pvStack = (void*) (&_estack),

    .pfnReset_Handler              = (void*) Reset_Handler,
    .pfnNonMaskableInt_Handler     = (void*) NonMaskableInt_Handler,
    .pfnHardFault_Handler          = (void*) HardFault_Handler,
    .pfnMemoryManagement_Handler   = (void*) MemoryManagement_Handler,
    .pfnBusFault_Handler           = (void*) BusFault_Handler,
    .pfnUsageFault_Handler         = (void*) UsageFault_Handler,
    .pvReservedC9                  = (void*) (0UL), /* Reserved */
    .pvReservedC8                  = (void*) (0UL), /* Reserved */
    .pvReservedC7                  = (void*) (0UL), /* Reserved */
    .pvReservedC6                  = (void*) (0UL), /* Reserved */
    .pfnSVCall_Handler             = (void*) SVCall_Handler,
    .pfnDebugMonitor_Handler       = (void*) DebugMonitor_Handler,
    .pvReservedC3                  = (void*) (0UL), /* Reserved */
    .pfnPendSV_Handler             = (void*) PendSV_Handler,
    .pfnSysTick_Handler            = (void*) SysTick_Handler,

    /* Configurable interrupts */
    .pfnSUPC_Handler               = (void*) SUPC_Handler,       /* 0  Supply Controller */
    .pfnRSTC_Handler               = (void*) RSTC_Handler,       /* 1  Reset Controller */
    .pfnRTC_Handler                = (void*) RTC_Handler,        /* 2  Real-time Clock */
    .pfnRTT_Handler                = (void*) RTT_Handler,        /* 3  Real-time Timer */
    .pfnWDT_Handler                = (void*) WDT_Handler,        /* 4  Watchdog Timer */
    .pfnPMC_Handler                = (void*) PMC_Handler,        /* 5  Power Management Controller */
    .pfnEFC_Handler                = (void*) EFC_Handler,        /* 6  Embedded Flash Controller */
    .pfnUART0_Handler              = (void*) UART0_Handler,      /* 7  Universal Asynchronous Receiver Transmitter */
    .pfnUART1_Handler              = (void*) UART1_Handler,      /* 8  Universal Asynchronous Receiver Transmitter */
    .pvReserved9                   = (void*) (0UL),              /* 9  Reserved */
    .pfnPIOA_Handler               = (void*) PIOA_Handler,       /* 10 Parallel Input/Output Controller */
    .pfnPIOB_Handler               = (void*) PIOB_Handler,       /* 11 Parallel Input/Output Controller */
    .pfnPIOC_Handler               = (void*) PIOC_Handler,       /* 12 Parallel Input/Output Controller */
    .pfnUSART0_Handler             = (void*) USART0_Handler,     /* 13 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnUSART1_Handler             = (void*) USART1_Handler,     /* 14 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnUSART2_Handler             = (void*) USART2_Handler,     /* 15 Universal Synchronous Asynchronous Receiver Transmitter */
    .pfnPIOD_Handler               = (void*) PIOD_Handler,       /* 16 Parallel Input/Output Controller */
    .pfnPIOE_Handler               = (void*) PIOE_Handler,       /* 17 Parallel Input/Output Controller */
    .pfnHSMCI_Handler              = (void*) HSMCI_Handler,      /* 18 High Speed MultiMedia Card Interface */
    .pfnTWIHS0_Handler             = (void*) TWIHS0_Handler,     /* 19 Two-wire Interface High Speed */
    .pfnTWIHS1_Handler             = (void*) TWIHS1_Handler,     /* 20 Two-wire Interface High Speed */
    .pfnSPI0_Handler               = (void*) SPI0_Handler,       /* 21 Serial Peripheral Interface */
    .pfnSSC_Handler                = (void*) SSC_Handler,        /* 22 Synchronous Serial Controller */
    .pfnTC0_Handler                = (void*) TC0_Handler,        /* 23 Timer Counter */
    .pfnTC1_Handler                = (void*) TC1_Handler,        /* 24 Timer Counter */
    .pfnTC2_Handler                = (void*) TC2_Handler,        /* 25 Timer Counter */
    .pfnTC3_Handler                = (void*) TC3_Handler,        /* 26 Timer Counter */
    .pfnTC4_Handler                = (void*) TC4_Handler,        /* 27 Timer Counter */
    .pfnTC5_Handler                = (void*) TC5_Handler,        /* 28 Timer Counter */
    .pfnAFEC0_Handler              = (void*) AFEC0_Handler,      /* 29 Analog Front-End Controller */
    .pfnDACC_Handler               = (void*) DACC_Handler,       /* 30 Digital-to-Analog Converter Controller */
    .pfnPWM0_Handler               = (void*) PWM0_Handler,       /* 31 Pulse Width Modulation Controller */
    .pfnICM_Handler                = (void*) ICM_Handler,        /* 32 Integrity Check Monitor */
    .pfnACC_Handler                = (void*) ACC_Handler,        /* 33 Analog Comparator Controller */
    .pfnUSBHS_Handler              = (void*) USBHS_Handler,      /* 34 USB High-Speed Interface */
    .pfnMCAN0_INT0_Handler         = (void*) MCAN0_INT0_Handler, /* 35 Controller Area Network */
    .pfnMCAN0_INT1_Handler         = (void*) MCAN0_INT1_Handler, /* 36 Controller Area Network */
    .pfnMCAN1_INT0_Handler         = (void*) MCAN1_INT0_Handler, /* 37 Controller Area Network */
    .pfnMCAN1_INT1_Handler         = (void*) MCAN1_INT1_Handler, /* 38 Controller Area Network */
    .pfnGMAC_Handler               = (void*) GMAC_Handler,       /* 39 Gigabit Ethernet MAC */
    .pfnAFEC1_Handler              = (void*) AFEC1_Handler,      /* 40 Analog Front-End Controller */
    .pfnTWIHS2_Handler             = (void*) TWIHS2_Handler,     /* 41 Two-wire Interface High Speed */
    .pfnSPI1_Handler               = (void*) SPI1_Handler,       /* 42 Serial Peripheral Interface */
    .pfnQSPI_Handler               = (void*) QSPI_Handler,       /* 43 Quad Serial Peripheral Interface */
    .pfnUART2_Handler              = (void*) UART2_Handler,      /* 44 Universal Asynchronous Receiver Transmitter */
    .pfnUART3_Handler              = (void*) UART3_Handler,      /* 45 Universal Asynchronous Receiver Transmitter */
    .pfnUART4_Handler              = (void*) UART4_Handler,      /* 46 Universal Asynchronous Receiver Transmitter */
    .pfnTC6_Handler                = (void*) TC6_Handler,        /* 47 Timer Counter */
    .pfnTC7_Handler                = (void*) TC7_Handler,        /* 48 Timer Counter */
    .pfnTC8_Handler                = (void*) TC8_Handler,        /* 49 Timer Counter */
    .pfnTC9_Handler                = (void*) TC9_Handler,        /* 50 Timer Counter */
    .pfnTC10_Handler               = (void*) TC10_Handler,       /* 51 Timer Counter */
    .pfnTC11_Handler               = (void*) TC11_Handler,       /* 52 Timer Counter */
    .pvReserved53                  = (void*) (0UL),              /* 53 Reserved */
    .pvReserved54                  = (void*) (0UL),              /* 54 Reserved */
    .pvReserved55                  = (void*) (0UL),              /* 55 Reserved */
    .pfnAES_Handler                = (void*) AES_Handler,        /* 56 Advanced Encryption Standard */
    .pfnTRNG_Handler               = (void*) TRNG_Handler,       /* 57 True Random Number Generator */
    .pfnXDMAC_Handler              = (void*) XDMAC_Handler,      /* 58 Extensible DMA Controller */
    .pfnISI_Handler                = (void*) ISI_Handler,        /* 59 Image Sensor Interface */
    .pfnPWM1_Handler               = (void*) PWM1_Handler,       /* 60 Pulse Width Modulation Controller */
    .pfnFPU_Handler                = (void*) FPU_Handler,        /* 61 Floating Point Unit */
    .pfnSDRAMC_Handler             = (void*) SDRAMC_Handler,     /* 62 SDRAM Controller */
    .pfnRSWDT_Handler              = (void*) RSWDT_Handler,      /* 63 Reinforced Safety Watchdog Timer */
    .pfnCCW_Handler                = (void*) CCW_Handler,        /* 64 System Control Block */
    .pfnCCF_Handler                = (void*) CCF_Handler,        /* 65 System Control Block */
    .pfnGMAC_Q1_Handler            = (void*) GMAC_Q1_Handler,    /* 66 Gigabit Ethernet MAC */
    .pfnGMAC_Q2_Handler            = (void*) GMAC_Q2_Handler,    /* 67 Gigabit Ethernet MAC */
    .pfnIXC_Handler                = (void*) IXC_Handler,        /* 68 Floating Point Unit */
    .pfnI2SC0_Handler              = (void*) I2SC0_Handler,      /* 69 Inter-IC Sound Controller */
    .pfnI2SC1_Handler              = (void*) I2SC1_Handler,      /* 70 Inter-IC Sound Controller */
    .pfnGMAC_Q3_Handler            = (void*) GMAC_Q3_Handler,    /* 71 Gigabit Ethernet MAC */
    .pfnGMAC_Q4_Handler            = (void*) GMAC_Q4_Handler,    /* 72 Gigabit Ethernet MAC */
    .pfnGMAC_Q5_Handler            = (void*) GMAC_Q5_Handler     /* 73 Gigabit Ethernet MAC */
};

/**
 * \brief This is the code that gets called on processor reset.
 * To initialize the device, and call the main() routine.
 *
 * With the compiler optimization set to O3, this Reset_Handler
 * function would hang when it gets to the section of code where it copies the vector
 * table to beginning of ITCM (Address 0)
 */
 __attribute__ ((optimize("O0")))

void Reset_Handler(void) {
	uint32_t *pSrc;
	uint32_t *pSrcEnd;
	uint32_t *pDest;
	uint32_t *pDestEnd;
	uint32_t ulEEFC_bits;
	uint32_t dtcm_stack_pointer_addr;

	// Configure TCM with maximum size
	// 128 KByte Data
	// 128 KByte Program

	__DSB(); __ISB();
	EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_GGPB);
	__DSB(); __ISB();

	while (!(EFC->EEFC_FSR & EEFC_FSR_FRDY));        // Wait until the status falls to 0 (EFFC command is complete)

	ulEEFC_bits = EFC->EEFC_FRR;

	if ((ulEEFC_bits & 0x180) != 0x180) {
		__DSB(); __ISB();
		EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(7));  // Issue command to clear bit 7
		__DSB(); __ISB();
		while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));     // Wait until the status falls to 0 (EFFC command is complete)

		__DSB(); __ISB();
		EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(8));  // Issue command to clear bit 8
		__DSB(); __ISB();
		while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));     // Wait until the status falls to 0 (EFFC command is complete)

		__DSB(); __ISB();
		RSTC->RSTC_CR = RSTC_CR_KEY_PASSWD | RSTC_CR_PROCRST;  // Trigger an MCU reset
		__DSB(); __ISB();
	}

	// Enable DTCM and ITCM
	__DSB(); __ISB();
	SCB->ITCMCR = (SCB_DTCMCR_EN_Msk | SCB_DTCMCR_RMW_Msk | SCB_DTCMCR_RETEN_Msk);
	SCB->DTCMCR = (SCB_DTCMCR_EN_Msk | SCB_DTCMCR_RMW_Msk | SCB_DTCMCR_RETEN_Msk);
	__DSB(); __ISB();

	// Copy Vector Table to beginning of ITCM (Address 0)
	pSrc     = (uint32_t*) &exception_table;
	pDest    = (uint32_t*) 0;
	pDestEnd = (uint32_t*) sizeof (DeviceVectors);

	while (pDest < pDestEnd) *pDest++ = *pSrc++;

	// Copy fast Code from Flash into ITCM
	pSrc     = &_s_fast_code_from;
	pSrcEnd  = &_e_fast_code_from;
	pDest    = &_s_fast_code;
	pDestEnd = &_e_fast_code;

	while (pSrc < pSrcEnd) *pDest++ = *pSrc++;

	// Copy data segments into DTCM and System RAM
	pSrc     = &_sdata_from;
	pSrcEnd  = &_edata_from;
	pDest    = &_sdata;
	pDestEnd = &_edata;

	while (pSrc < pSrcEnd) *pDest++ = *pSrc++;

	pSrc     = &_s_fast_data_from;
	pSrcEnd  = &_e_fast_data_from;
	pDest    = &_s_fast_data;
	pDestEnd = &_e_fast_data;

	while (pSrc < pSrcEnd) *pDest++ = *pSrc++;

	// Clear the zero segments in DTCM and System RAM
	pDest    = &_sbss;
	pDestEnd = &_ebss;
	while (pDest < pDestEnd) *pDest++ = 0;

	pDest    = &_s_fast_bss;
	pDestEnd = &_e_fast_bss;
	while (pDest < pDestEnd) *pDest++ = 0;

	// Set the vector table base address
	// to the copied table in ITCM (Address 0)
	pSrc = (uint32_t *) 0;

	SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

	//Now that we're at the point in this routine where we don't need any stack variables,
	//update our stack pointer to the runtime stack pointer that lives in DTCM
	dtcm_stack_pointer_addr = (uint32_t) &_e_runtime_stack;

	//asm(code : output operand list : input operand list : clobber list);
	//write r1 with the address of DTCM where the beginning of the stack lives (per the linker)
	__ASM volatile ("mov.w r1, %0"::"r" (dtcm_stack_pointer_addr):"r1");
	//update the stack pointer with the stack address that lives in r1
	__ASM volatile("mov sp, r1");

	__DSB(); __ISB();

	/* Initialize the C library */
	__libc_init_array(); 

	/* Branch to main function */
	main();

	/* Infinite loop */
	while (1) {}
}

/**
 * \brief Default interrupt handler for unused IRQs.
 */
void Dummy_Handler(void) {
    while (1) {}
}

 

Last Edited: Sat. Apr 18, 2020 - 08:08 AM