zoukankan      html  css  js  c++  java
  • Keil5配置GCC编译器编译STM32工程

    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_MDKKeil_v5ARMGCC (注:这里是刚刚安装的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
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    log4net(c#) 配置及使用
    【转】JMeter试用手记
    【转】性能测试工具JMeter的使用技巧
    【转】JMeter基础之——录制脚本
    【转】Jmeter基础之——jmeter基础概念
    【转】JMeter基础之——一个简单的性能测试
    【转】JMeter入门
    【转】Jmeter压力测试模拟并发
    【转】JMeter Tutorial的安装和具体操作
    【转】JMeter代理录制脚本
  • 原文地址:https://www.cnblogs.com/wuhh123/p/10523960.html
Copyright © 2011-2022 走看看