Hello everyone, I am a ruffian balance, is a serious technical ruffian. Today ruffian balance to share with you is a strange Keil MDK variable link forced alignment error.

Ruanziheng has been participating in NXP SBL project recently (that is, a complete OTA scheme applicable to LPC and I. MXRT). This project will meet you in the near future. The project needs to support three development environments: GCC, IAR and MDK at the same time. But in MDK link alignment error problem, ruffian balance took the time to study to solve this problem, this problem is closely related to MDK tool itself, ruffian balance feel very interesting (in fact, mainly want to ridicule MDK), especially to share with you.

The problem may be related to the MDK version, before analyzing the problem, especially the version information:

L6244E error reporting problem

In the USB stack source file usb_device_EHci. c, there is the following definition of a BSS variable named qh_buffer. The actual length of this variable is 3KB. We require MDK links to be placed at 2KB aligned addresses.

#define USB_DEVICE_CONFIG_EHCI      (2)
#define USB_DEVICE_CONFIG_ENDPOINTS (8U)

__attribute__((aligned(2048)))
static uint8_t qh_buffer[(USB_DEVICE_CONFIG_EHCI - 1) * 2048 + USB_DEVICE_CONFIG_ENDPOINTS * 2 * sizeof(usb_device_ehci_qh_struct_t)];
Copy the code

The following is the MDK link file for the SBL project (MIMxRT1176XXXXX_CM7_FLEXspi_NOR.scf), and the engineering code is executed by XIP. This is a normal link file, except for the special placement of the i. mx header (FDCB, IVT, BootData), the rest are normal link statements, no special placement of other code or variables, basically let the linker (armlink) do what it wants.

#define m_flash_config_start 0x30000400 #define m_flash_config_size 0x00000C00 #define m_ivt_start 0x30001000 #define m_ivt_size 0x00001000 #define m_interrupts_start 0x30002000 #define m_interrupts_size 0x00000400 #define m_text_start 0x30002400 #define m_text_size 0x00FBDC00 #define m_data_start 0x20000000 #define m_data_size 0x00040000 #define Stack_Size 0x0400 #define Heap_Size 0x0400 LR_m_text m_flash_config_start m_text_start+m_text_size-m_flash_config_start {; Place FDCB (i.mx feature) RW_m_config_text M_flash_config_start FIXED M_flash_config_SIZE {* (.boot_hdr.conf, +FIRST)}; RW_m_ivt_text m_IVt_start FIXED M_IVt_size {* (.boot_hdr. IVT, +FIRST) * (.boot_hdr.boot_data) } ; VECTOR_ROM m_interrupts_start FIXED M_interrupts_size {* (.isr_vector,+FIRST)}; ER_m_text m_text_start FIXED m_text_size {* (InRoot$$Sections).any (+RO)}; Place the program variable RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size {.ANY (+RW +ZI) * (RamFunction) * (noncacheable.init) * (*NonCacheable) } ; ARM_LIB_HEAP +0 EMPTY Heap_Size {} ARM_LIB_STACK m_data_start+m_data_size empty-stack_size {}Copy the code

The compiler gets a strange link error as shown in the following image. The linker says the LR_m_text start address is not aligned with 2KB. The LR_m_text load area address range specified in the link file [m_flash_config_start, m_text_start+m_text_size-m_flash_config_start] is only a maximum RO storage range, Although m_flash_config_start is equal to 0x30000400, this start address is specified to place FDCB, and qh_buffer is a BSS variable (initialized to 0, no need to put initial value in flash). It does not occupy RO at all, only RW can be allocated. It’s hard to understand why the linker is so anxious about the start address of LR_m_text because of the alignment requirements of qh_buffer.

Try to solve the error reporting problem

2.1 Adjusting the LR_m_text Start ADDRESS

Since the linker is so anxious about the LR_m_text start address, let’s just set the start address to 0x30000000 (FlexSPI map start address), so the link file changes as follows. Note: since several segments of the I.mx start header are placed at fixed addresses, the change to the starting address does not affect them, nor does it affect the rest of the segments placed at unspecified addresses.

#define m_flash_start 0x30000000 #define m_flash_size 0x00FC0000 #define m_flash_config_start 0x30000400 #define m_flash_config_size 0x00000C00 LR_m_text m_flash_start m_flash_size { ; Change here!! ; Place FDCB RW_m_config_text M_flash_config_start FIXED M_flash_config_SIZE {* (.boot_hdr.conf, +FIRST)}; Place IVT, BootData; Place interrupt direction meter; Place program code; Place program variables; Place program heap, stack}Copy the code

Recompiling MDK project after modifying the link file, no link errors this time, we opened the project map file (sbl.map) and found the qh_buffer content in it, we could see that qh_buffer was listed 0x20004800, this address was actually 2KB aligned, but this was the RW area, It has nothing to do with the LR_m_text load space we set/changed.

============================================================================== Image Symbol Table Local Symbols Symbol Name Value Ov Type Size Object(Section) qh_buffer 0x20004800 Data 3072 usb_device_ehci.o(.bss.qh_buffer) [Anonymous Symbol] 0x20004800 Section 0 usb_device_ehci.o(.bss.qh_buffer) ============================================================================== Memory Map of the image Image Entry point  : 0x30002401 Load Region LR_m_text (Base: 0x30000000, Size: 0x00011800, Max: 0x00fc0000, ABSOLUTE, COMPRESSED[0x00011518]) Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30010000, Size: 0x00005ed8, Max: 0x0003f800, ABSOLUTE, COMPRESSED[0x00000800]) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x20004800 - 0x00000c00 Zero RW 2164 .bss.qh_buffer usb_device_ehci.oCopy the code

2.2 Add — Legacyalign option to linker

The approach in the previous section solves the problem, but the solution is not convincing, just an alternative. For this reason, Ruffian Balance looked at the MDK official documentation and found the following documentation on link alignment:

  • –legacyalign –no_legacyalign
  • Section alignment with the linker: www.keil.com/support/man…

By default, the armLink linker assumes that the execution area and load area are 4-byte aligned, and inserts some padding space during link allocation to meet the special alignment requirements of the segment. The linker has two strategies for handling padding:

  • Strict policy — NO_LEGacyalign (default) : Instructs the linker to insert padding to enforce natural alignment at the head of an area, where natural alignment is the largest known alignment in the area. This option ensures strict ELF specification compliance.
  • Loose policy — Legacyalign: Instructs the linker to insert padding with minimal alignment.

The default is no_legacyalign. The linker should fill the LR_m_text header with the qH_buffer alignment, but the linker simply dropped the link and reported an error. Let’s not embarrass the linker and give it a loose policy:

With this change, there is no need to adjust the link file and the MDK project can compile the connection normally. Looking at the mapping files (SBL/Map), the Qh_buffer link addresses have changed from the previous scheme, moved from 0x20004800 to 0x20004000, but are still 2KB aligned.

============================================================================== Image Symbol Table Local Symbols Symbol Name Value Ov Type Size Object(Section) qh_buffer 0x20004000 Data 3072 usb_device_ehci.o(.bss.qh_buffer) [Anonymous Symbol] 0x20004000 Section 0 usb_device_ehci.o(.bss.qh_buffer) ============================================================================== Memory Map of the image Image Entry point  : 0x30002401 Load Region LR_m_text (Base: 0x30000400, Size: 0x00010944, Max: 0x00fbfc00, ABSOLUTE, COMPRESSED[0x00010408]) Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x3000f944, Size: 0x000056d8, Max: 0x0003f800, ABSOLUTE, COMPRESSED[0x000001ac]) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x20004000 - 0x00000c00 Zero RW 2164 .bss.qh_buffer usb_device_ehci.oCopy the code

One last MDK paradox, we added — Legacyalign and compiled a warning that says — Legacyalign is not recommended.

Armlink v6.14: legacyalign –legacyalign –legacyalign –legacyalign –legacyalign –legacyalign –legacyalign –legacyalign –legacyalign MDK ah, it is not easy to say I love you!

At this point, a strange Keil MDK variable link forced alignment error problem ruffian balance will be introduced to the end, where is the applause ~~~

Welcome to subscribe to

The article will be published on my blog park homepage, CSDN homepage, Zhihu homepage and wechat public account at the same time.

Wechat search “ruffian balance embedded” or scan the following two-dimensional code, you can see the first time on the phone oh.