Provides device startup, system configuration, and linker script files.
The system startup provides the followings features:
Configuration Considerations
Device Memory Definition
Allocation of different types of memory such as the flash, RAM etc., for the CPU is defined by the linker scripts.
- Note
- - The linker files provided with the PDL are generic and handle all common use cases. Your project may not use every section defined in the linker files. In that case you may see warnings during the build process. To eliminate build warnings in your project, you can simply comment out or remove the relevant code in the linker file.
-
- There is a common linker script for both CM7_0 and CM7_1 core. By default it links for CM7_0 core. But if the application is built for CM7_1, then a linker option _CORE_cm7_1 is provided in build system. For example, below piece of code is implemented in the build system.
ifeq ($(TOOLCHAIN),IAR)
LDFLAGS += --config_def _CORE_cm7_1_=1
else ifeq ($(TOOLCHAIN),GCC_ARM)
LDFLAGS += -Wl,'--defsym=_CORE_cm7_1_=1'
endif
ARM GCC
The flash and RAM sections for the CPU are defined in the linker files: 'xx_yy_zz.ld', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.ld', 'xmc7100d_x4160_cm7.ld', 'xmc7200d_x8384_cm0plus.ld' and 'xmc7100d_x4160_cm0plus.ld'.
- Note
- If the start of the Cortex-M7_0 or Cortex-M7_1 application image is changed, the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR should also be changed. The CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro should be used as the parameter for the Cy_SysEnableCM7() function call. By default,
- the COMPONENT_XMC7x_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual-core MCU device (CM0+, CM7_0).
- the COMPONENT_XMC7xDUAL_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual CM7-core MCU device (CM0+, CM7_0 and CM7_1).
Change the flash and RAM sizes by editing the macro values in the linker files for both CPUs:
- 'xx_yy_cm0plus.ld', where 'xx_yy' is the device group:
cm0_ram (rxw) : ORIGIN = _base_SRAM_CM0P, LENGTH = _size_SRAM_CM0P
cm0_flash (rx) : ORIGIN = _base_CODE_FLASH_CM0P,LENGTH = _size_CODE_FLASH_CM0P
- 'xx_yy_cm7.ld', where 'xx_yy' is the device group:
ram (rxw) : ORIGIN = _base_SRAM, LENGTH = _size_SRAM
flash_cm0p (rx) : ORIGIN = _base_CODE_FLASH_CM0P, LENGTH = _size_CODE_FLASH_CM0P
flash (rx) : ORIGIN = _base_CODE_FLASH, LENGTH = _size_CODE_FLASH
Change the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro to the ROM ORIGIN's value (0x10000000) + FLASH_CM0P_SIZE value (0x80000, the size of a flash image of the Cortex-M0+ application should be the same value as the flash LENGTH in 'xx_yy_cm0plus.ld') in the 'xx_yy_cm7.ld' file, where 'xx_yy' is the device group.
- Do this by editing the the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR value in the 'system_xx.h', where 'xx' is the device family:
#define CY_CORTEX_M7_0_APPL_ADDR BASE_CODE_FLASH_CM7_0
#define CY_CORTEX_M7_1_APPL_ADDR BASE_CODE_FLASH_CM7_1
'BASE_CODE_FLASH_CM7_0' and ''BASE_CODE_FLASH_CM7_1' macros are defined in the xmc7xxx_partition.h
ARM Compiler
The flash and RAM sections for the CPU are defined in the linker files: 'xx_yy_zz.sct', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example 'xmc7200d_x8384_cm7.sct', 'xmc7100d_x4160_cm7.sct', 'xmc7200d_x8384_cm0plus.sct' and 'xmc7100d_x4160_cm0plus.sct'.
- Note
- If the start of the Cortex-M7_0 or Cortex-M7_1 application image is changed, the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR should also be changed. The CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro should be used as the parameter for the Cy_SysEnableCM7() function call. By default,
- the COMPONENT_XMC7x_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual-core MCU device (CM0+, CM7_0).
- the COMPONENT_XMC7xDUAL_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual CM7-core MCU device (CM0+, CM7_0 and CM7_1).
-
The linker files provided with the PDL are generic and handle all common use cases. Your project may not use every section defined in the linker files. In that case you may see the warnings during the build process: L6314W (no section matches pattern) and/or L6329W (pattern only matches removed unused sections). In your project, you can suppress the warning by passing the "--diag_suppress=L6314W,L6329W" option to the linker. You can also comment out or remove the relevant code in the linker file.
Change the flash and RAM sizes by editing the macros value in the linker files for both CPUs:
- 'xx_yy_cm0plus.sct', where 'xx_yy' is the device group:
#define SRAM_BASE_ADDRESS 0x28000000
#define CM0PLUS_SRAM_RESERVE 0x00020000
#define CODE_FLASH_BASE_ADDRESS 0x10000000
#define CM0PLUS_CODE_FLASH_RESERVE 0x00080000
- 'xx_yy_cm7.sct', where 'xx_yy' is the device group:
#define SRAM_BASE_ADDRESS 0x28000000 //SRAM START
#define CM7_0_SRAM_RESERVE 0x00060000 //cm7_0 sram size
#define BASE_SRAM_CM7_0 SRAM_BASE_ADDRESS + CM0PLUS_SRAM_RESERVE
#define SIZE_SRAM_CM7_0 CM7_0_SRAM_RESERVE
#define SIZE_SRAM_CM7_1 SRAM_TOTAL_SIZE - CM0PLUS_SRAM_RESERVE - CM7_0_SRAM_RESERVE
#define BASE_SRAM_CM7_1 SRAM_BASE_ADDRESS + CM0PLUS_SRAM_RESERVE + CM7_0_SRAM_RESERVE
#define CODE_FLASH_BASE_ADDRESS 0x10000000 //FLASH START
#define CM7_0_CODE_FLASH_RESERVE 0x00200000 //cm7_0 flash size
#define BASE_CODE_FLASH_CM7_0 CODE_FLASH_BASE_ADDRESS + CM0PLUS_CODE_FLASH_RESERVE
#define SIZE_CODE_FLASH_CM7_0 CM7_0_CODE_FLASH_RESERVE
#define BASE_CODE_FLASH_CM7_1 CODE_FLASH_BASE_ADDRESS + CM0PLUS_CODE_FLASH_RESERVE + CM7_0_CODE_FLASH_RESERVE
#define SIZE_CODE_FLASH_CM7_1 CODE_FLASH_TOTAL_SIZE - CM0PLUS_CODE_FLASH_RESERVE - CM7_0_CODE_FLASH_RESERVE
Change the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro to the ROM ORIGIN's value (0x10000000) + FLASH_CM0P_SIZE value (0x80000, the size of a flash image of the Cortex-M0+ application should be the same value as the flash LENGTH in 'xx_yy_cm0plus.sct') in the 'xx_yy_cm7.sct' file, where 'xx_yy' is the device group.
- Do this by editing the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR value in the 'system_xx.h', where 'xx' is the device family:
#define CY_CORTEX_M7_0_APPL_ADDR BASE_CODE_FLASH_CM7_0
#define CY_CORTEX_M7_1_APPL_ADDR BASE_CODE_FLASH_CM7_1
'BASE_CODE_FLASH_CM7_0' and ''BASE_CODE_FLASH_CM7_1' macros are defined in the xmc7xxx_partition.h
IAR
The flash and RAM sections for the CPU are defined in the linker files: 'xx_yy_zz.icf', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.icf','xmc7100d_x4160_cm7.icf','xmc7200d_x8384_cm0plus.icf' and 'xmc7100d_x4160_cm0plus.icf'.
- Note
- If the start of the Cortex-M7_0 or Cortex-M7_1 application image is changed, the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR should also be changed. The CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro should be used as the parameter for the Cy_SysEnableCM7() function call. By default,
- the COMPONENT_XMC7x_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual-core MCU device (CM0+, CM7_0).
- the COMPONENT_XMC7xDUAL_CM0P_SLEEP prebuilt image is used for the CM0p core of the XMC dual CM7-core MCU device (CM0+, CM7_0 and CM7_1).
Change the flash and RAM sizes by editing the macros value in the linker files for both CPUs:
- 'xx_yy_cm0plus.icf', where 'xx_yy' is the device group:
define symbol sram_base_address = 0x28000000;
define symbol cm0plus_sram_reserve = 0x00020000;
define symbol code_flash_base_address = 0x10000000;
define symbol cm0plus_code_flash_reserve = 0x00080000;
- 'xx_yy_cm7.icf', where 'xx_yy' is the device group:
define symbol sram_base_address = 0x28000000;
define symbol cm7_0_sram_reserve = 0x00060000;
define symbol _base_SRAM_CM7_0 = sram_base_address + cm0plus_sram_reserve;
define symbol _size_SRAM_CM7_0 = cm7_0_sram_reserve;
define symbol _base_SRAM_CM7_1 = sram_base_address + cm0plus_sram_reserve + cm7_0_sram_reserve;
define symbol _size_SRAM_CM7_1 = sram_total_size - cm0plus_sram_reserve - cm7_0_sram_reserve;
define symbol code_flash_base_address = 0x10000000;
define symbol cm7_0_code_flash_reserve = 0x00200000;
define symbol _base_CODE_FLASH_CM7_0 = code_flash_base_address + cm0plus_code_flash_reserve;
define symbol _size_CODE_FLASH_CM7_0 = cm7_0_code_flash_reserve;
define symbol _base_CODE_FLASH_CM7_1 = code_flash_base_address + cm0plus_code_flash_reserve + cm7_0_code_flash_reserve;
define symbol _size_CODE_FLASH_CM7_1 = code_flash_total_size - cm0plus_code_flash_reserve - cm7_0_code_flash_reserve;
Change the value of the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR macro to the ROM ORIGIN's value (0x10000000) + FLASH_CM0P_SIZE value (0x80000, the size of a flash image of the Cortex-M0+ application should be the same value as the flash LENGTH in 'xx_yy_cm0plus.icf') in the 'xx_yy_cm7.icf' file, where 'xx_yy' is the device group.
- Do this by editing the CY_CORTEX_M7_0_APPL_ADDR or CY_CORTEX_M7_1_APPL_ADDR value in the 'system_xx.h', where 'xx' is the device family:
#define CY_CORTEX_M7_0_APPL_ADDR BASE_CODE_FLASH_CM7_0
#define CY_CORTEX_M7_1_APPL_ADDR BASE_CODE_FLASH_CM7_1
'BASE_CODE_FLASH_CM7_0' and ''BASE_CODE_FLASH_CM7_1' macros are defined in the xmc7xxx_partition.h
Device Initialization
After a power-on-reset (POR), the CM0+ starts boot-ROM directly from ROM and boot-ROM starts CM0+ startup. The CM0+ startup starts CM0+ user application. The CM0+ user application enables CM7 cores and starts CM7 startup. The startup code is the piece of code which is executed after every system reset. It initializes the system components like, memory, FPU, interrupts, clock, etc. and calls application's main() function. The startup code is always build as part of user application. There are two different startup codes for CM0+ and CM7 core.
The CM0+ startup code implements the following functions to run the CM0+ application:
- In the Reset Handler, it disables global interrupts
- Disables the SRAM ECC checking: CM0+ bus width is 32-bit, but SRAM is built with 64-bit based ECC on Facelift parts with CM7 core, sets CPUSS->RAMx_CTL0.ECC_CHECK_DIS bits to avoid causing unintentional ECC faults during startup while SRAM ECC has not been initialized yet.
- Calls SystemInit() function
- Initializes and enables the SRAM memory for ECC
- Copies the vector table from ROM to RAM and updates the VTOR (Vector Table Offset Register)
- Sets the CM0+ IRQ0 and IRQ1 handlers from SROM vector table, sets the CM0+ IRQ0 and IRQ1priority, then enables these interrupts: the SROM APIs are executed by CM0+ core in interrupt context using IRQ0 and IRQ1. So, proper interrupt handler addresses and priorities need to be configured for IRQ0 and IRQ1
- Unlocks and disable WDT (Watchdog timer)
- Calls the SystemCoreClockUpdate()
- Executes main() application
The CM7 startup code implement the following functions to run the CM7 user application:
- In the Reset handler, it disables global interrupts
- Allows write access to Vector Table Offset Register and ITCM/DTCM configuration register
- Enables CM7 core ITCM and DTCM
- Enables the FPU if it is used
- Copies the vector table from ROM to RAM and updates the VTOR (Vector Table Offset Register)
- Enables the CM7 core instruction and data cache
- Calls SystemInit() function
- Executes CM7 main() application
Heap and Stack Configuration
By default, the stack size is set to 0x00001000 and the Heap size is allocated dynamically to the whole available free memory up to stack memory. The Stack grows from higher to lower address. The Stack top or start is assigned to end of SRAM address. The Heap grows opposite of Stack. It grows from lower to higher address. The Heap top starts from end of used data section till Stack end.
ARM GCC
Editing source code files
The stack size is defined in the linker script files: 'xx_yy_zz.ld', 'xx_yy_zz.ld', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.ld', 'xmc7100d_x4160_cm7.ld', 'xmc7200d_x8384_cm0plus.ld' and 'xmc7100d_x4160_cm0plus.ld'. Change the stack size by modifying the following line:
- Note
- Correct operation of malloc and related functions depends on the working implementation of the 'sbrk' function. Newlib-nano (default C runtime library used by the GNU Arm Embedded toolchain) provides weak 'sbrk' implementation that doesn't check for heap and stack collisions during excessive memory allocations. To ensure the heap always remains within the range defined by __HeapBase and __HeapLimit linker symbols, provide a strong override for the 'sbrk' function:
void * _sbrk(uint32_t incr)
{
extern uint8_t __HeapBase, __HeapLimit;
static uint8_t *heapBrk = &__HeapBase;
uint8_t *prevBrk = heapBrk;
if (incr > (uint32_t)(&__HeapLimit - heapBrk))
{
errno = ENOMEM;
return (void *)-1;
}
heapBrk += incr;
return prevBrk;
}
For FreeRTOS-enabled multi-threaded applications, it is sufficient to include clib-support library that provides newlib-compatible implementations of 'sbrk', '__malloc_lock' and '__malloc_unlock':
https://github.com/Infineon/clib-support.
ARM Compiler
Editing source code files
The stack size is defined in the linker script files: 'xx_yy_zz.sct', 'xx_yy_zz.sct', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.sct', 'xmc7100d_x4160_cm7.sct', 'xmc7200d_x8384_cm0plus.sct' and 'xmc7100d_x4160_cm0plus.sct'. Change the stack size by modifying the following line:
#define STACK_SIZE 0x1000
IAR
Editing source code files
The heap and stack sizes are defined in the linker script files: 'xx_yy_zz.icf', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.icf','xmc7100d_x4160_cm7.icf','xmc7200d_x8384_cm0plus.icf' and 'xmc7100d_x4160_cm0plus.icf'. Change the heap and stack sizes by modifying the following lines:
define symbol cm7_stack_reserve = 0x00001000;
Default Interrupt Handlers Definition
The default interrupt handler functions are defined as weak functions to a dummy handler in the startup file. The naming convention for the interrupt handler names is <interrupt_name>_IRQHandler. A default interrupt handler can be overwritten in user code by defining the handler function using the same name. For example:
void scb_0_interrupt_IRQHandler(void)
{
...
}
Vectors Table Copy from Flash to RAM
This process uses memory sections defined in the linker script. The startup code actually defines the contents of the vector table and performs the copy.
ARM GCC
The linker script file is 'xx_yy_zz.ld', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.ld', 'xmc7100d_x4160_cm7.ld', 'xmc7200d_x8384_cm0plus.ld' and 'xmc7100d_x4160_cm0plus.ld'. It defines sections and locations in memory.
Copy interrupt vectors from flash to RAM:
From:
To:
LONG (__ram_vectors_start__)
Size:
The vector table address (and the vector table itself) are defined in the startup files (e.g. startup_cm0plus.S and startup_cm7.c). The code in these files copies the vector table from Flash to RAM.
ARM Compiler
The linker script file is 'xx_yy_zz.sct', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example 'xmc7200d_x8384_cm7.sct', 'xmc7100d_x4160_cm7.sct', 'xmc7200d_x8384_cm0plus.sct' and 'xmc7100d_x4160_cm0plus.sct'. The linker script specifies that the vector table (RESET_RAM) shall be first in the RAM section.
RESET_RAM represents the vector table. It is defined in the startup files (e.g. startup_cm0plus.S and startup_cm7.c). The code in these files copies the vector table from Flash to RAM.
IAR
The linker script file is 'xx_yy_zz.icf', where 'xx_ yy' is the device group, and 'zz' is the target CPU; for example, 'xmc7200d_x8384_cm7.icf','xmc7100d_x4160_cm7.icf','xmc7200d_x8384_cm0plus.icf' and ' 'xmc7100d_x4160_cm0plus.icf'.
The vector table address (and the vector table itself) are defined in the startup files (e.g. startup_cm0plus.S and startup_cm7.c). The code in these files copies the vector table from Flash to RAM.
Changelog
Version | Changes | Reason for Change |
1.0 | Initial version | |