Understanding LDS File Creation for TAE32G5800

Understanding LDS File Creation for TAE32G5800

01

Application Function Introduction

VSCode uses the GCC cross-compilation tool, and the partition script syntax is different from that of Keil’s sct dispersed loading script, adopting the lds link script language. This article will analyze the various components and construction schemes of the lds file in detail.

02

Detailed Explanation of LDS Files

The main functions of LDS are:

  1. Partition information;

  2. Declare code entry;

  3. Section block construction;

The Flash space of TAE32G5800 is from 0x08000000 to 0x0803FFFF, and the SRAM space is from SRAMA to SRAMD, with a space of 0x20000000 to 0x2001FFFF.

Understanding LDS File Creation for TAE32G5800

Figure 2.1 TAE32G5800 Memory Space Division

Flash can work in single Bank mode and dual Bank mode, with the minimum unit of erase operation being Sector. In single Bank mode, each Sector size is 8KB (0x2000), and in dual Bank mode, each Sector size is 4KB (0x1000).

The 256KB of TAE32G5800 works in dual Bank mode with 64 Sectors; in single Bank mode, there are 32 Sectors.

2.1

Memory Partition Information

Memory partitions are used to divide Flash and RAM space. First, establish a partition table, declaring the starting address, length, and operation permissions.

The example is as follows.

__ROM_BASE = 0x08000000;__ROM_SIZE = 0x0001D000;__RAMA_BASE = 0x20000000;__RAMA_SIZE = 0x00010000;__RAMB_BASE = 0x20010000;__RAMB_SIZE = 0x0000E000;__IMP_BASE = 0X2001E000;__IMP_SIZE = 0X00002000;MEMORY{ FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE RAMA (rwx) : ORIGIN = __RAMA_BASE, LENGTH = __RAMA_SIZE RAMB (rwx) : ORIGIN = __RAMB_BASE, LENGTH = __RAMB_SIZE IMPCODE (rwx) : ORIGIN = __IMP_BASE, LENGTH = __IMP_SIZE}

In MEMORY{}, each partition’s information is declared, with the first field being the partition name, such as FLASH, FIXED_CODE, etc.; the parentheses contain operation attributes, such as r (read attribute), w (write attribute), x (executable attribute); ORIGIN specifies the starting address of the area; LENGTH specifies the size of the area.

For the ORIGIN and LENGTH of Flash space, they must be the minimum unit of Sector size, which is either 4K (0x1000) or 8K (0x2000). For the division of SRAM space, it is also recommended to use Sector size as the minimum unit for easy unified management.

2.2

Entry Declaration

The ENTRY keyword is used to define the entry point of the application. The ld link tool has several ways to set the code entry address:

  1. ld -e option specified;

  2. ENTRY(Symbol) declaration in the link script;

  3. start symbol defined in the link script;

  4. If there is a .text section, use the first address of the .text section as the entry;

  5. Use address 0 as the entry;

The priority of these five methods is from high to low, and once a high-priority condition is met, lower priority conditions are ignored. By default, it is recommended to use the ENTRY method for explicit declaration, as shown below.

ENTRY(Reset_Handler)

Using Reset_Handler as the program entry, which includes actions such as setting up the environment.

2.3

Basic Introduction of SECTIONS

SECTIONS{} wraps the entire code area content. It is necessary to understand the following points in advance:

  1. VMA (Virtual Memory Address) and LMA (Load Memory Address);

  2. Basic section concepts, including: code section (.text), data section (.data), heap area, stack area, BSS section (.bss);

  3. Variable relationships required for setting up the Cortex-M4 environment;

2..3.1

Basic Concept of Address

The concept of address is divided into two layers.

First, VMA is the running address, the address during code execution; LMA is the download address, the physical address stored in Flash, and VMA and LMA are classified as “code layer addresses”. Then, the other two concepts introduced by dual Bank are mapped address and actual physical address, where the mapped address refers to the LMA address seen in the code, while the actual physical address refers to the Flash address within the chip. Due to the introduction of the dual Bank mapping switch function, the actual physical address and the mapped address have a mapping relationship, and these two address concepts are classified as “space layer addresses”.

2.3.2

Basic Concept of Section

The basic sections include code section (.text), data section (.data), stack area, heap area, BSS section (.bss), etc., with the concepts shown below.

Table 2.1 Section Concept

Section

Does Flash save the entity

Description

.text

Yes

Code section running in Flash

.data

Yes

Stores initialized global data section

.stack

No

The stack area is automatically allocated and released by the compiler, storing local variables, parameters, and return values

.heap

No

The heap area is allocated and released by the programmer, using malloc() and free()

.bss

No

Stores uninitialized global data section, only the starting address and length, does not occupy Flash space

.ram

Yes

Fast code running in RAM

The data area mainly stores variables with initialized values, thus occupying Flash space and needing to be copied from Flash to RAM during startup; the bss area mainly stores uninitialized variables, so it only needs to obtain the starting address of the area and the size, and clear this area during startup without occupying Flash space.

The stack area does not need to occupy Flash space, the stack area is mainly for push and pop operations of sub-functions and interrupts, storing temporary variables, and local variables. The heap area is mainly used for dynamic allocation with malloc() and free().

The ram area means that LMA is Flash address, VMA is SRAM address, and it needs to execute frequently.

2.3.3

Variable Relationships Required for Setting Up the Cortex-M4 Environment

During the startup phase, RAM space code needs to be set up, generally using the GCC cross-compilation tool to reference ARM’s official setup function, as shown in program listing 2.2.

Program Listing 2.2 GCC Calls ARM Setup Space Code

File path: cmsis_gcc.h

#ifndef __PROGRAM_START__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void){

extern void _start(void) __NO_RETURN; typedef struct { uint32_t const* src; uint32_t* dest; uint32_t wlen; } __copy_table_t; typedef struct { uint32_t* dest; uint32_t wlen; } __zero_table_t; extern const __copy_table_t __copy_table_start__; extern const __copy_table_t __copy_table_end__; extern const __zero_table_t __zero_table_start__; extern const __zero_table_t __zero_table_end__; for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { for(uint32_t i=0u; iwlen; ++i) { pTable->dest[i] = pTable->src[i]; } } for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { for(uint32_t i=0u; iwlen; ++i) { pTable->dest[i] = 0u; } } _start();}#define __PROGRAM_START __cmsis_start#endif

VSCode uses the gcc compilation toolchain, so it uses the cmsis_gcc.h file. The __PROGRAM_START macro is called by Reset_Handler(). First, declare the imported external variables __copy_table_start, __copy_table_end, __zero_table_start, and __zero_table_end, which are defined from the ld file. As shown below.

Program Listing 2.3 Copy Address Declaration of lds File

/* —< Copy&Zero table sections Config >— */.copy.table :

{ . = ALIGN(4); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) LONG ((__data_end__ – __data_start__) / 4) __copy_table_end__ = .;} > FLASH.zero.table :{ . = ALIGN(4); __zero_table_start__ = .; LONG (__bss_start__) LONG ((__bss_end__ – __bss_start__) / 4) __zero_table_end__ = .; } > FLASH

Program listings 2.2 and 2.3 mainly function to construct the content of RAM space during the startup phase.

2.4

SECTIONS Building Syntax

The SECTIONS keyword format is as follows.

SECTIONS { SECTION-COMMAND SECTION-COMMAND}

SECTION-COMMAND includes entry commands, symbol assignment statements, section descriptions, etc. The format is:

Section_name : {…}

2.4.1

Declare .text Section

The definition of .text is shown in program listing 2.4.

Program Listing 2.4 .text Section Definition

.text :{ KEEP(*(.vectors)) *(.text*) KEEP(*(.init)) …} > FLASH

The KEEP statement is used to declare that the block is positioned in the section and avoids being optimized by the compiler, with vectors being the interrupt vector table. The KEEP(*(.vectors)) statement indicates that the interrupt vector table is placed at the head of the .text section.

The *(.text*) statement includes all code sections.

The ending statement > FLASH indicates that this section belongs to the FLASH partition.

2.4.2

Declare .data Section and .bss Section

.data and .bss sections belong to the RAM partition, but .data needs to occupy Flash space, while .bss section does not.

Program Listing 2.5 Declare .data and .bss Sections

__etext = ALIGN (4);.data : AT (__etext) { __data_start__ = .; *(vtable) *(.data) *(.data.*)… __data_end__ = .; } > RAMA.bss :{ . = ALIGN(4); __bss_start__ = .; *(.bss) *(.bss.*) *(COMMON) . = ALIGN(4); __bss_end__ = .;} > RAMA AT > RAMA

.data:AT (…){}>RAMA statement indicates that data is stored in the AT specified LMA area and runs in RAMA area.

*(.data) statement is a self-defined RAM Code code area, which can specify its function to this code area in the code.

.bss : {…} > RAMA AT > RAMA statement indicates that the .bss area runs in the RAMA area.

Each area records the start and end, passing to copy_table and zero_table.

2.4.3

Declare .stack Area and .heap Area

The declaration of the stack area is shown in program listing 2.6.

Program Listing 2.6 .stack Area and .heap Area Declaration

.heap :{ . = ALIGN(8); __end__ = .; PROVIDE(end = .); . = . + __HEAP_SIZE; . = ALIGN(8); __HeapLimit = .;} > RAMA

.stack (ORIGIN(RAMA) + LENGTH(RAMA) – __STACK_SIZE) :{ . = ALIGN(8); __StackLimit = .; . = . + __STACK_SIZE; . = ALIGN(8); __StackTop = .;} > RAMAPROVIDE(__stack = __StackTop);

In this example, the stack area is assigned to the RAMA space.

2.4.4

Declare ram_code Area

Declare a code area that runs in RAM and is stored in Flash, as shown below.

Program Listing 2.7 Declaration of RAM_CODE Area

__eimp_code = ALIGN (4);.imp_code : AT (__eimp_code){ . = ALIGN(4); __eimp_code_start__ = .; *(.imp_code) *(.imp_code.*) . = ALIGN(4); __eimp_code_end__ = .;} > IMPCODE

First, define a __eimp_code variable, aligning with the current address by 4 bytes. Then record the starting and ending addresses of the area, passing to the startup function in program listing 2.2.

Program Listing 2.8 Copy Code for New RAM Space

.copy.table : { . = ALIGN(4); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) LONG ((__data_end__ – __data_start__) / 4) LONG (__eimp_code) LONG (__eimp_code_start__) LONG ((__eimp_code_end__ – __eimp_code_start__) / 4) __copy_table_end__ = .; } > FLASH

03

Usage Introduction

This chapter explains how to reference partition information in the code and specify operations for designated areas of the code.

3.1

Referencing Partition Information

Partition information includes VMA, LMA, and space size, as shown in the following example.

Program Listing 3.1 Declare Partition Information

PROVIDE(Load_IMP_CODE_Base = LOADADDR(.imp_code));PROVIDE(Image_IMP_CODE_Base = ADDR(.imp_code));PROVIDE(Image_IMP_CODE_Length = SIZEOF(.imp_code));

The PROVIDE() keyword is used to define a global symbol within the link script, which can then be referenced in C code. This function is mainly used in IAP upgrade and other firmware update schemes to specify firmware partition information.

The LOADADDR() function is used to obtain the LMA address of the section;

The ADDR() function is used to obtain the VMA address of the section;

The SIZEOF() function is used to obtain the size of the section;

In C code, use the following statements to obtain partition information.

Program Listing 3.2 Global Variables for Obtaining Partition Information in C Code

extern uint32_t Load_IMP_CODE_Base;extern uint32_t Image_IMP_CODE_Base;extern uint32_t Image_IMP_CODE_Length;

3.2

Specifying the Code’s Belonging Area

This chapter mainly specifies which module a piece of code belongs to, mainly using the __attribute__ encapsulated interface in C code.

Program Listing 3.3 Specify Partition Ownership

#define IMP_CODE __section(“.imp_code”)

Then, reference these macro definitions before the function to specify, as shown below.

IMP_CODE void User_UART_Example(void){

After compilation, check the MAP file.

Understanding LDS File Creation for TAE32G5800

Figure 3.1 Function Address in MAP File

About TAE

Zhu Hai TAE Electronics Co., Ltd. was established in 2019, focusing on the R&D of industrial-grade and automotive-grade core processor chips,committed to leading the innovation of the domestic semiconductor industry, continuously innovating in the fields of industrial control, new energy power conversion, power quality monitoring and management, high-end power supply, and servo, and continuously developing industrial-grade core processor chips to fully replace foreign products, striving to create better quality products and services for customers.

Understanding LDS File Creation for TAE32G5800

For more information, please follow us

Phone: 0756-3666670

Website: www.tai-action.com

WeChat Official Account: Tai-action

Bilibili Video Account: TAE Electronics

TaoBao Store: Search for “TAE Electronics”

Understanding LDS File Creation for TAE32G5800

Leave a Comment

×