Click below to【Learn Embedded Together】follow, learn together, and grow together
Introduction
Keil MDK-ARM can be used with the GNU Compiler Collection (GCC). GCC is an open-source development tool with many contributors, widely available and supports many devices.
Keil defaults to using ARMCC to compile MCU project code. Therefore, the following configurations are required to set it to compile with GCC.
Download Steps
ARM GCC compiler download link (copy the link to your browser):
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads

Operation Steps
To enable MDK-ARM to use GCC:
1. Open the Components, Environment, and Books dialog in Project > Manage > Components, Environment, Books…
μVision GNU Tool Selection
2. Select the Folder/Extensions tab;
3. Check to use the GNU compiler.

1. Configure GCC Compilation Rules
Make sure to check the following options and fill in the rules:
Misc Controls : -mcpu=cortex-m3 -mthumb -fdata-sections -ffunction-sections
Note:
(1.) I used cortex-m3 here, if you are using m4 core, change it to 4;
(2.) The meaning of -mthumb is: the target file generated with this compile option is Thumb;
(3.) -fdata-sections and -ffunction-sections are discussed together with the following connection rules;

2. Configure Assembler Compilation Rules
Similar to the previous one, Misc Controls : -mcpu=cortex-m3 -mthumb
3. Configure Linker Connection Rules
Here you need to add a connection script, which can generally be found in the official firmware library package.
Misc Controls : -Wl,–gc-sections
Note: 1. Note that there are two short “–” before gc, copying directly may cause errors due to the blog issue; 2. -wl, indicates that the following parameter –gc-sections is passed to the linker; 3. The explanations for -fdata-sections and -ffunction-sections and –gc-sections are as follows.

4. stm32f10x_flash_extsram.ld Content
/*
Default linker script for STM32F10x_1024K_1024K
Copyright RAISONANCE S.A.S. 2008
*/
/* include the common STM32F10x sub-script */
/* Common part of the linker scripts for STM32 devices*/
/* default stack sizes.
These are used by the startup in order to allocate stacks for the different modes.
*/
__Stack_Size = 1024 ;
PROVIDE ( _Stack_Size = __Stack_Size ) ;
__Stack_Init = _estack - __Stack_Size ;
/*"PROVIDE" allows to easily override these values from an object file or the commmand line.*/
PROVIDE ( _Stack_Init = __Stack_Init ) ;
/*
There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 0x100 ;
/* include the memory spaces definitions sub-script */
/*
Linker subscript for STM32F10x definitions with 1024K Flash and 1024K External SRAM */
/* Memory Spaces Definitions */
MEMORY
{
RAM (xrw) : ORIGIN = 0x68000000, LENGTH = 1024K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
}
/* higher address of the user mode stack */
_estack = 0x68100000;
/* include the sections management sub-script for FLASH mode */
/* Sections Definitions */
SECTIONS
{
/* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* for some STRx devices, the beginning of the startup code is stored in the .flashtext section, which goes to FLASH */
.flashtext :
{
. = ALIGN(4);
*(.flashtext) /* Startup code */
. = ALIGN(4);
} >FLASH
/* the program code is stored in the .text section, which goes to Flash */
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data secion */
_sidata = _etext;
} >FLASH
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM. */
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_sdata = . ;
*(.data)
*(.data.*)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_edata = . ;
} >RAM
/* This is the uninitialized data section */
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .;
*(.bss)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_ebss = . ;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
/* This is the user stack section
This is just to check that there is enough RAM left for the User mode stack
It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >RAM
/* this is the FLASH Bank1 */
/* the C or assembly source must explicitly place the code or data there
using the "section" attribute */
.b1text :
{
*(.b1text) /* remaining code */
*(.b1rodata) /* read-only data (constants) */
*(.b1rodata*)
} >FLASHB1
/* this is the EXTMEM */
/* the C or assembly source must explicitly place the code or data there
using the "section" attribute */
/* EXTMEM Bank0 */
.eb0text :
{
*(.eb0text) /* remaining code */
*(.eb0rodata) /* read-only data (constants) */
*(.eb0rodata*)
} >EXTMEMB0
/* EXTMEM Bank1 */
.eb1text :
{
*(.eb1text) /* remaining code */
*(.eb1rodata) /* read-only data (constants) */
*(.eb1rodata*)
} >EXTMEMB1
/* EXTMEM Bank2 */
.eb2text :
{
*(.eb2text) /* remaining code */
*(.eb2rodata) /* read-only data (constants) */
*(.eb2rodata*)
} >EXTMEMB2
/* EXTMEM Bank0 */
.eb3text :
{
*(.eb3text) /* remaining code */
*(.eb3rodata) /* read-only data (constants) */
*(.eb3rodata*)
} >EXTMEMB3
/* after that it's only debugging information. */
/* remove the debugging information from the standard libraries */
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
5. Startup Code, Using GCC-Specific .S Files
The startup code required for the GCC compiler is different from ARMCC, but the official has provided related code, as shown in the figure below:

6. Compile and Run
1. core_cm3.c Error

Two errors appeared, and after searching, it was found that the official provided core_cm3.c has a bug causing it. Change line 736 to:
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
Change line 753 to:
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
Knowledge Supplement
–gnu
Enables GNU Compiler extensions supported by the ARM compiler. Compatible GCC versions can be checked by examining the predefined macros __GNUC__ and __GNUC_MINOR__. Additionally, in GNU mode, the ARMCC compiler simulates GCC to comply with C/C++ standards, regardless of their strictness.
This option can also be combined with other source language command line options. For example, armcc –c90 –gnu.
–C99 and –gnu
Many compilation standards in SOEM code seem to be GNU standards, such as anonymous UNION, and array size cannot be zero, etc. Therefore, it is necessary to add to the Misc Controls in Keil c/c++--gnu
Referring to other bloggers, it may cause problems with printf, therefore, the following content needs to be added to the code:
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
//#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
//comment_20190422: soem needs --gnu compile option,
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
Original text:https://blog.csdn.net/qq_32348883/article/details/123894312
Source from the internet, copyright belongs to the original author, if there is any infringement, please contact to delete.

Follow me【Learn Embedded Together】, learn together and grow together.
If you think this article is good, click “Share”, “Like”, “View”!