Keil一般使用ARMCC编译MCU工程代码。偶然听说Keil也是支持内嵌GCC编译器的。于是尝试了网上博客所述的一些方法,最终找到了一篇博客

http://blog.csdn.net/lan120576664/article/details/46806991

按照文中所述,发现仍存在一些其他错误,后来又查找了其他相关资料,在这作以总结

一、下载GCC编译器
https://launchpad.net/gcc-arm-embedded/

二、安装GCC
GCC解压到keil的安装目录下面。如下图

三、配置Keil
如下图所示进行相关设置:

Prefix:arm-none-eabi-
Folder:D:\keil_MDK\Keil_v5\ARM\GCC\ (注:这里是刚刚安装的GCC所在位置)

四、配置工程设置
1.配置CC编译规则
注意勾选一下选项,填写规则

Misc Controls : -mcpu=cortex-m3 -mthumb -fdata-sections -ffunction-sections
注:
1.这里我用的cortex-m3,如果你是m4内核就改成4)
2.-mthumb的意义是:使用这个编译选项生成的目标文件是Thumb的
3.-fdata-sections和-ffunction-sections和下文连接规则一起说

2.配置Assembler编译规则
类似前一项

Misc Controls : -mcpu=cortex-m3 -mthumb

3.配置Linker连接规则
这里要添加连接脚本,一般可以在官方提供的固件库包找到类似的

Misc Controls : -Wl,–gc-sections
注:
1.注意这个gc前面是两个短小的“–”,由于博客的问题直接复制会出错
2.-wl, 表示后面的参数 –gc-sections 传递给链接器
3.-fdata-sections和-ffunction-sections和–gc-sections的说明如下
-ffunction-sections和-fdata-sections会使编译器为每个function和data item分配独立的section。 –gc-sections会使连接器删除没有被使用的section。
连接操作以section作为最小的处理单元,只要一个section中有某个符号被引用,该section就会被放入output中。这些选项一起使用会从最终的输出文件中删除所有未被使用的function和data, 只包含用到的unction和data。

具体细节可以参考另一位博主的文章http://blog.csdn.net/pengfei240/article/details/55228228

4.stm32f10x_flash_extsram.ld内容
/*
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) }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
五、启动代码,使用GCC专用的.S文件
使用GCC编译器需要的启动代码不同与AMRCC,不过官方已经有提供了相关代码,如下图:

六、编译运行
1.core_cm3.c错误

出现两个错误,经过在搜索发现原来是官方提供的core_cm3.c有bug造成的
将其中
736行改为:

__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
1
753行改为:

__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
1
这样就不会有错误了。

2.标准的C 库函数错误

如上图所示出现两个错误,根据原文所述如果有使用标准的C 函数,如sprintf,则要包含syscall.c 这个文件。于是我查找了标准库文件发现没有提供,后来又查找了HAL库的文件,找到了syscall.c如下图

添加后只剩下一个错误

如下:

ld.exe: section .ARM.exidx loaded at [080053dc,080053e3] overlaps section .data loaded at [080053dc,08005d83]
1
这里发现.ARM.exidx与.data段重叠了,但是.ARM.exidx段究竟是什么?
在这篇文章中找到了答案http://www.cnblogs.com/tfanalysis/p/3652788.html
最终,我的解决办法是在stm32f10x_flash_extsram.ld连接脚本文件第75行添加以下代码

/* 添加.ARM.exidx段 */
.ARM.exidx : {
. = ALIGN(4);
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
. = ALIGN(4);
} >FLASH
1
2
3
4
5
6
修改后再次编译发现没有错误。
注:
1.连接脚本规则可以参考这篇博客http://blog.csdn.net/cat_lover/article/details/50727988
2.个人理解连接脚本类似用ARMCC,ARMLINK编译连接时写的.sct格式分散加载文件

七、编译成功

注:采用GCC编译器后无法使用“Go To Definition Of ”跳转到相应的函数这个功能。
附上工程:http://download.csdn.net/download/weixin_39871788/10166971
---------------------
作者:Quarder
来源:CSDN
原文:https://blog.csdn.net/weixin_39871788/article/details/78858791
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://www.cnblogs.com/wuhh123/p/10523960.html

Keil5配置GCC编译器编译STM32工程相关推荐

  1. Keil5.15使用GCC编译器编译STM32工程

    一.下载GCC编译器 GCC编译器下载地址  二.安装GCC 我们可以把GCC解压到keil的安装目录下面.如下图 1 2 三.配置Keil使用GCC编译器 1.配置CC编译规则,Misc Contr ...

  2. Keil中配置GCC编译器开发STM32

    一.下载编译链: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolc ...

  3. MinGW下载并配置gcc/g++编译环境

    本文将讲解如何下载MinGW并配置gcc\g++编译环境 #方案一:官网下载 ##一.下载MinGW 在MinGW官网中下载"mingw-get-setup.exe" 官网传送门: ...

  4. 深度剖析“GCC编译器编译过程”

    (这张图是本人画的并非网络图,如果有编译过程没有提到的可以提出来) 首先说说第一步 一.预编译 1.配置编译器环境  编译器在编译之前要运行配置文件通常叫configure的配置文件,一般这个配置文件 ...

  5. Windows G++ | VisualStudioCodeC语言环境配置(GCC编译器)

    VSCode GCC编译器 软件安装 VSCode(代码编辑器) MinGW(代码编译器) 配置环境变量 配置可执行文件环境变量 添加LIBRARY_PATH环境变量 配置C_INCLUDE_PATH ...

  6. windows 使用GCC编译器编译c++程序 开始学习c++最好的环境配置

    1.安装编译器gcc >下载 MinGW Installer  https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.e ...

  7. linux gcc编译c文件头文件,使用GCC编译器编译C语言

    GCC编译C源代码有四个步骤:预处理-->编译-->汇编-->链接. 可以利用GCC的参数来控制执行的过程,这样就可以更深入的了解编译C程序的过程. 下面将通过对一个程序的编译来演示 ...

  8. MinGW下载,配置gcc/g++编译环境

    方案一:官网下载 一.下载MinGW 在MinGW官网中下载"mingw-get-setup.exe" 官网传送门:http://www.mingw.org/ 二.安装MinGW ...

  9. gcc编译器 编译的4个步骤

    一.预处理 hello.c 经过预处理得到 hello.i gcc -E hello.c -o hello.i -E的含义:说明这是一个预处理操作 生成预处理文件(.i) -o的含义: 确定 输出文件 ...

最新文章

  1. 微软称电脑系统识别能力已经超越了人类
  2. c语言switch虚线,有以下程序:include<stdio.h>main(){int c;while((c=getchar())!='\n')switch(c-'2'){case 1:pu...
  3. fwrite视频写入帧率测试(不用测了。。)
  4. 关于 【通过代理访问】 的研究,【突破 IP ,“无限制”投票】
  5. redhat 添加ssh端口_RHEL 7修改ssh默认端口号
  6. Winform跨线程调用简洁办法
  7. java ee api_Java EE并发API教程
  8. 专访图灵奖得主:完全自动驾驶是计算机接近人类智能的一大步
  9. 三分钟让你掌握JavaScript中值传递和引用传递的区别
  10. 用@Scheduled完成定时任务
  11. 201903版的idea markdown无法预览的问题
  12. ng bind html br,使用PrimeNG开发angular web项目
  13. org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection
  14. 芝诺数解|「七」月是故乡明,月饼表浓情
  15. 阿里云 大数据DataWorks开发套件的相关操作
  16. 按摩店用的收银系统多少钱一套
  17. 微服务架构总结性介绍 (深度好文)
  18. xmind做会议记录的方法
  19. nginx在linux中查看日志信息,nginx查看日志
  20. 计算机网络安全面试问题,2016计算机信息安全工程师面试题及答案

热门文章

  1. LPC1758串口ISP下载程序
  2. 用jQuery插件实现“小图点击预览大图”功能1
  3. 《Java基础学习笔记》JAVA面向对象之封装
  4. ntext字段的替换处理示例--全表替换(作者:邹建)
  5. 爬取网易某只股票2017-01到2018-01的数据
  6. python 列表list相关知识
  7. 算法笔记_094:蓝桥杯练习 矩阵相乘(Java)
  8. ansible 简单使用
  9. 领域驱动设计之单元测试最佳实践(二)
  10. WebAPI Get