魔术棒设置解析

Keil(MDK-ARM)系列教程(四)_工程目标选项配置(Ⅱ) (360doc.com)

99%开发者从未听说过的堆栈模型-电子发烧友网 (elecfans.com)

STM32(4):番外篇之stm32固件库工程搭建 - 知乎 (zhihu.com)

(22条消息) Keil(MDK-ARM)系列教程(三)_工程目标选项配置(Ⅰ)_strongerHuang的博客-CSDN博客

(18条消息) Keil(MDK-ARM)系列教程(四)_工程目标选项配置(Ⅱ)_plain char is signed_strongerHuang的博客-CSDN博客

九、魔术板设置解析

这个面板的设置影响十分多的东西

9.1 关于Use MicroLIB是否勾选问题

(22条消息) 关于Use MicroLIB是否勾选问题_The_General_Reader的博客-CSDN博客

MicroLib是一个微型的C库,提供了嵌入式常见的c的函数库,但是因为是对嵌入式函数的支持,所以相比于linux的gcclib很不完整;之所以需要勾选,是因为有的时候需要使用一些诸如在"stdio.h"来实现printf的时候,是需要c库支持的,这些底层c库的API接口以及实现stm32固件库是不提供的,注意stm提供是固件库,是直接操作(硬件)寄存器的,而c是操作系统层面的,属于软件层面的,所以有需要的时候勾选上;勾选上也会影响堆栈的初始化方式,也可能会与C库的区别

如果勾选上的话,并且主函数名为main的话启动文件一定要有__initial_sp,__heap_base,__heap_limit三个值,否则会报以下错误

.\Objects\led_c.axf: Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o).

可能需要用到的情况: 1、实际需要用到串口重定向到printf时可以勾选上。2、不使用这个,浮点数运算也会出问题。3、移植ucossiii ,不选微库,开了FPU 会死机

9.1.1 应用实例:串口

9.1.1.1 方法1–使用微库:

1、包含头文件:#include “stdio.h”

2、Printf重定向,修改fputc()函数的内容~

int fputc(int ch, FILE *f)
{
    USART_SendData(DEBUG_USART, (unsigned char) ch);
    while (!(DEBUG_USART->SR & USART_FLAG_TXE));
    return (ch);
}

这里的:

USART_SendData(DEBUG_USART, (unsigned char) ch);
while (!(DEBUG_USART->SR & USART_FLAG_TXE));

就是往串口发送一个字节的代码,修改相应的串口,初始化。这样就能使用printf了~可以一试。

9.1.1.2 方法2–不使用微库:

1、包含头文件#include “stdio.h”

2、重写fputc,但需要先加点东西:

(用这个方法,勾选上微库Use MicroLIB也没问题)

#pragma import(__use_no_semihosting)
_sys_exit(int x)
{
    x = x;
}
struct __FILE
{
    int handle;
};
FILE __stdout;
int fputc(int ch, FILE *f)
{
    USART_SendData(DEBUG_USART, (unsigned char) ch);
    while (!(DEBUG_USART->SR & USART_FLAG_TXE));
    return (ch);
}

9.1.1.3 总结

不使用微库

使用微库

9.2 C/C++界面

(22条消息) Keil(MDK-ARM)系列教程(三)_工程目标选项配置(Ⅰ)_strongerHuang的博客-CSDN博客

(18条消息) Keil(MDK-ARM)系列教程(四)_工程目标选项配置(Ⅱ)_plain char is signed_strongerHuang的博客-CSDN博客

9.2.1 Define

相当于添加宏定义,使工程根据Define进行编译在yiSTM32F103ZET6为例,

标准库常用 STM32F10X_HD,USE_STDPERIPH_DRIVER,两个都在stm32f10x.h用到,在此处宏定义后就无须在stm32f10x.h手动增加宏定义

Hal库常用 USE_HAL_DRIVER,STM32F103xE,前者在stm32f1xx.h,后者在system_stm32f1xx.c与stm32f1xx.h,stm32f1xx_hal.c,stm32f1xx_hal_rcc_ex.c,stm32f1xx_hal_rcc_ex.h,stm32f1xx_hal_flash_ex.h,stm32f1xx_hal_dac_ex.h, stm32f1xx_hal_dma_ex.h,stm32f1xx_hal_dma_ex.h等文件都有使用到

9.2.2 Language/Code Generation

Language/code Generation语言代码生成,可以理解成编译、链接到最后生成代码。这部分功能对于代码优化比较重要,初学者可以不用过多理解,对代码大小、运行速度等性能要求较高的人就需要深入理解

  • Execute only Code: 只生成执行代码 [设置编译器命令行: --execute only)

只生成执行代码防止编译器生成任何数据访问代码部分

  • Enum Container always int: 枚举总是int型

    很容易理解,我们枚举时成员变量类型为int型。

  • Optimize: 优化选择项,

有Level0 - Level3四个选项 设置编译器命令行: -Onum) 初学者、在线调试建议使用Level0,也就是不优化,这样执行的效果才和代码一 样。 如果配置成Leve13,在线调试可能有些地方优化而不能打断点

  • C99 Mode

    大大减小语法编译报错的概率;C99相比于默认的C89,不仅带来很多新特性,而且更加人性化,比如变量定义要在第一行可执行代码之前,否则编译报错:

9.2.3 Include Paths

包含路径是使用Keil(及类似)软件必须掌握的一项。包含路径就是指定我们工程中使用头文件所在的位置,让编译器找到相应的文件。是初学者、高级软件工程师都必须掌握的一项。

9.2.4 Misc Controls

多功能空间,可以用来忽略编译的警告或错误之类的,只需在Misc Control中添加“--diag_suppress=”就可以了, num就是Keil中的警告代码,把警告内容贴到百度搜索一下就可以知道警告代码是多少了,比如需要忽略warning: #61-D: integeroperation result is out of range这个警告,只需添加--diag_suppress=61

9.2.5 Compiler control string

设置编译器控制字符串,前面语言代码生成Language/code Generation语言代码生成的选择就会影响这边。

9.3 User界面

主要用于编写

1、编辑前运行的脚命令

2、编译前运行的命令

3、编译后运行的命令,基本上修改的是此处,生成bin文件或dis反汇编文件

4、Run "After Build" conditionally:执行条件;Beep When Complete:编译完成发出声音;Start Debugging:启动调试程序。

9.4 生成Bin文件或Dis文件

9.4.1 Bin,Hex,Axf,Dis文件的区别

Dis文件时反汇编文件,可以查看代码段与对应地址,可以直接拖入MDK打开

Bin文件是编译生成的二进制文件,是最纯粹的,烧录进单片机的就是这些数据,可以计算Program Size的 Code+ RO-data+ RW-data会发现等于bin文件的大小, 而axf文件时用于调试的(用调试器烧录使用的也是Hex,不是axf),Hex文件带有地址信息,都包括了一些其他数据,因此大小也会大于bin文件

9.4.2 如何使用Keil5生成

编辑 User的Afer Build/Rebuild脚本可以在编译后生成对应文件,实际上是调用MDK5安装路径下的fromelf.exe(MDK5\ARM\ARMCC\bin\fromelf.exe)

可以定位到所在文件夹后输入以下代码获取语法

.\fromelf.exe --help

下面是语法

fromelf [options] input_file  (命令的格式)

Options:
       --help         display this help screen (显示帮助信息)
       --vsn          display version information (显示版本信息)
       --output file  the output file. (defaults to stdout for -text format) (输出文件(默认的输出为文本格式))
       --nodebug      do not put debug areas in the output image (在生成的映象中不包含调试信息)
       --nolinkview   do not put sections in the output image (在生成的映象中不包含段的信息)

Binary Output Formats:
       --bin          Plain Binary (生成Plain Binary格式的文件)
       --m32          Motorola 32 bit Hex (生成Motorola 32位十六进制格式的文件)
       --i32          Intel 32 bit Hex (生成Intel 32位十六进制格式的文件)
       --vhx          Byte Oriented Hex format (面向字节的位十六进制格式的文件t)

       --base addr    Optionally set base address for m32,i32 (设置m32,i32格式文件的基地址)

Output Formats Requiring Debug Information (需要调试信息的格式)
       --fieldoffsets Assembly Language Description of Structures/Classes (结构/类的汇编语言描述)
       --expandarrays Arrays inside and outside structures are expanded (扩展数组内部和外部结构被扩展)

Other Output Formats:
       --elf         ELF
       --text        Text Information (显示文本信息)

                Flags for Text Information
                -v          verbose (打印详细信息)
                -a          print data addresses (For images built with debug) (打印数据地址(针对带调试信息的映象))
                -c          disassemble code (打印反汇编代码)
                -d          print contents of data section (打印数据段的内容)
                -e          print exception tables (打印表达式表)
                -g          print debug tables (打印调试表)
                -r          print relocation information (打印重定位信息)
                -s          print symbol table (打印字符表)
                -t          print string table (打印字符串表)
                -y          print dynamic segment contents (打印动态段的内容)
                -z          print code and data size information (打印代码和数据大小的信息)

下面提供一个生成bin的示例,放在RUN1 RUN2皆可

 fromelf.exe --bin --output ../OBJ/PWM.bin ../OBJ/PWM.axf

说明:

  • fromelf.exe声明了使用的exe如果找不到该文件可以尝试设置全局变量或是使用相对路径

    $K\ARM\ARMCC\bin\fromelf.exe
  • --bin 生成plain binary即纯二进制文件

  • --output 后面跟上输出文件

  • ../OBJ/PWM.bin 说明输出文件与路径 在项目文件PWM.uvprojx的上级文件夹下找到OBJ文件夹,在该文件夹下生成PWM.bin文件(PWM根据实际项目名修改,如不理解文件夹结构见下面的文件树,OBJ文件夹其实就是编译的输出文件夹,在魔术棒的 Output->Select Folder for Objects下设置)

  • ├─CORE
    ├─HALLIB
    │  └─STM32F1xx_HAL_Driver
    │      ├─Inc
    │      │  └─Legacy
    │      └─Src
    │          └─Legacy
    ├─HARDWARE
    │  ├─KEY
    │  ├─LED
    │  └─TIMER
    ├─OBJ
    ├─SYSTEM
    │  ├─delay
    │  ├─sys
    │  └─usart
    └─USER
        └─DebugConfig
  • ../OBJ/PWM.axf 说明使用的文件与路径 在项目文件PWM.uvprojx的上级文件夹下找到OBJ文件夹,在该文件夹下找到PWM.axf文件(PWM根据实际项目名修改)

    下面提供一个生成dis反汇编文件的实例,注意是--text -a -c

    fromelf  --text  -a -c  --output=../OBJ/PWM.dis  ../OBJ/PWM.axf

9.3 对函数使用F12 Go to Definition 不能跳转

勾选Output下的Browse information

9.4 为什么没有生成Map文件

勾选下面这个选项

9.4 为什么通过调试器烧录程序后,还需要复位才能运行

在Utilities界面下选择Seeting,勾选“Reset and Run”

9.5 新建工程后选择芯片后会在魔术棒界面增加什么设置

只会在Target标签设置频率,这个值主要用于仿真调试用,一般我们使用硬件调试可以不用管这个值,IROM1,IRAM1,不会在C/C++界面设置宏定义,会默认勾选上C99 Mode,GNU extensions ,默认优化等级0,会勾选上use memory layout from target

Last updated