Keil使用命令行附加预定义宏编译

2023-05-16

1. 前言

很多时候,一份Keil工程代码可能需要满足多个不同的应用场景。可以通过逻辑判断,将多个不同的点集成在一份代码之中,但是嵌入式往往特别关注RAM空间,集成过多的逻辑判断,RAM空间可能就不够用了。针对这种情况Keil提供了配置Target,通过宏定义来分隔不同的功能,编译生成不同的bin文件。
在这里插入图片描述

但是有时,一个Target项目中,另外又有几个子场景,子场景也需要用预定义宏来区分开。但是Keil并没有提供这样的功能。
另外,Keil工程有非常多的Target,一次修改,必须不停选择不同Target来进行编译,这种编译方式非常不方便。

2. 方法

Keil提供了命令行,可以编译工程。另外,Keil使用的ArmCC和Armlink来编译和链接,这样的话,便可以使用makefile来编译Keil工程代码。

2.1. 命令行

2.1.1 用法

UV4 [command] [projectfile]

2.1.1.1. command

command可以是下述列表之一。如果command没有指定,则只是打开Keil工程。

  • -b, 编译指定的Keil工程默认的Target。

UV4 -b PROJECT1.uvprojx

  • -c, 清除Keil工程中所有Target的临时文件。

UV4 -c PROJECT1.uvprojx

  • -cr, 清除所有Target,然后重新编译所有Target。

UV4 -cr PROJECT1.uvprojx

  • -d, 启动Keil的调试模式。

UV4 -d PROJECT1.uvprojx

  • -f, 下载程序到flash上,下载完成之后退出。

UV4 -f PROJECT1.uvprojx -t"MCB2100 Board"

  • -r, 重新编译Keil工程的默认Target,或用-t指定Target。

UV4 -r PROJECT1.uvprojx
UV4 -r PROJECT1.uvprojx -t"Simulator"

  • -5, 转换Keil4工程为Keil5工程。

UV4 -5 myoldproject.uvproj -l log.txt

  • -et, 导出工程的Target的配置。
  • -ep, 导出工程所有Target配置。
  • -X, 生成预处理符号文件。
  • -X1, 为所有Target生成预处理符号文件。

2.1.3. Option

下面的选项是可选项。

  • -j0, 隐藏Keil的UI。
  • -i, 创建一个新的工程,或通过XML文件更新存在的工程。
  • -l logfile,保存命令生成的输出到logfile中。
  • -n device_name, 创建一个指定device_name的工程。

UV4 MyProject.uvprojx -n Device123

  • -np device_name, 如果工程不存在,则指定device_name创建工程。如果工程存在,则更新所有target的device_name。
  • -o outputfile, 指定输出的Log文件。

UV4 -r PROJECT1.uvprojx -o"output.log"

  • -q, 重新编译多工程指定的Target。
  • -t, 指定工程的target。

UV4 -r PROJECT1.uvprojx -t"MCB2100 Board"

  • -x, 配合Debug模式命令-d使用,返回完整的命令输出。
  • -y, 配合Debug模式命令-d使用,返回通用的配置。
  • -z, 重新编译工程的所有Target。

UV4 -b PROJECT1.uvproj -z

2.1.4. ERRORLEVEL

Kiel编译完成后的错误码

ERRORLEVEL描述
0无错误无敬告
1仅有敬告
2错误
3重大错误
11不能打开工程
12给定的设备不存在
13写工程文件出错
15读XML文件出错
20转换工程出错

2.1.5. 指定多预定义宏

为一个target指定多个预定义宏,此处使用shell脚本编写,需要git-bash或cygwin来编译。
添加一个define.h宏,Keil工程引用此宏达到控制一个Target中有不同的预编译宏。

# Obtain Keil project
prj_name=$(find *.uvproj)

# Obtain all target name of uvproj
mapfile -t target_array < <(cat "${prj_name}" | grep "TargetName" | awk -F '>' '{print $2}' | awk -F '<' '{print $1}')

# Macro
L85C_define=(__L85C1_ __L85C2__)

# Build all target
for name in "${target_array[@]}"; do
	if [[ "$name" == "L85C" ]]; then
		for define in "${L85C_define[@]}"; do
			echo "#define" $define>define.h
			# Code中include "define.h"
			"C:\Keil\UV4\UV4.exe" -r 5081Scan.uvproj -t"$name" -o "$name""$define""Build.txt" -j0
		done
	else
		"C:\Keil\UV4\UV4.exe" -r 5081Scan.uvproj -t"$name" -o "$name""Build.txt" -j0
	fi
	
	# If build error, stop build.
	if (( $? > 0 )); then
		echo Build error.
		break
	fi
done

2.2. makefile

2.2.1. Keil编译过程

Keil使用ArmCC编译源文件,使用Armlink链接目录文件生成efl文件,然后调用fromelf转换为bin文件。
那么ArmCC和Armlink如何使用呢?Keil提供一种方法来展示如何使用ArmCC和Armlink。如下图,勾选Create Batch File,会将ArmCC和Armlink编译链接的过程输出到相应的文件中。
![在这里插入图片描述](https://img-blog.csdnimg.cn/6b91db62eb83428895d169c13d3bfb9c.png
编译当前工程指定的Test,编译连接的命令过程生成在test.bat文件中,如下图:
在这里插入图片描述

  • startup_mo_ia文件主要是编译汇编文件,内容为:
    在这里插入图片描述
    实际的调用命令为:

ArmAsm --cpu Cortex-M0 -g --apcs=interwork --pd “__MICROLIB SETA 1” -I C:\Keil\ARM\RV31\INC
-I C:\Keil\ARM\CMSIS\Include --list .\list\startup_m0.lst --xref -o .\obj\startup_m0.o --depend .\obj\startup_m0.d “startup_M0.s”

  • main._ip,这个主要是生成汇编文件,一般情况可以不使用。
  • main._i文件主要是编译.c文件,内容为:
    在这里插入图片描述
    实际调用的过程为:

ArmCC -c --cpu Cortex-M0 -D__MICROLIB -g -O2 -Otime --apcs=interwork -I C:\Keil\ARM\RV31\INC -I C:\Keil\ARM\CMSIS\Include -o .\obj\main.o --omf_browse .\obj\main.crf --depend .\obj\main.d “Src\main.c”

  • scan.lnp,主要是描述连接的过程。
    在这里插入图片描述
    实际的连接过程为:

ArmLink --cpu Cortex-M0".\obj\startup_m0.o" “.\obj\scan.o” “.\obj\main.o” --library_type=microlib --strict --scatter “.\Obj\scan.sct” --summary_stderr --info summarysizes --map --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers --list “.\List\scan.map” -o .\Obj\scan.axf

2.2.2. makefile内容

APP ?= .\output\scan.afx
MACRO ?=invlid_macro

OUTPUTCHAN ?= SEMIHOSTED

SHELL=$(windir)\system32\cmd.exe
RM_FILES = $(foreach file,$(1),if exist $(file) del /q $(file))
RM_DIRS = $(foreach dir,$(1),if exist $(dir) rmdir /s /q $(dir)$(EOL))

ifeq ($(QUIET),@)
PROGRESS = @echo Compiling $<...
endif

SRC_DIR = Src
ASM_DIR = .
INC_DIR = include
OBJ_DIR = obj
LINK = armlink
OUTPUT_DIR=output

INCLUDES := -I$(INC_DIR)
INCLUDES += -I C:\Keil\ARM\RV31\INC
INCLUDES += -I C:\Keil\ARM\CMSIS\Include

ARCH               := Cortex-M0
CPU                := ARM
LINK_GCC            := link.ld
GCC_LINKER_FILE       := -T link/$(LINK_GCC)

GCC_TOOLCHAIN   := C:\Keil\ARM\ARMCC\bin
ASM         := $(GCC_TOOLCHAIN)\ArmAsm
CC        := $(GCC_TOOLCHAIN)\ArmCC
LINKER_CSRC := $(GCC_TOOLCHAIN)\armlink
FROMELF := $(GCC_TOOLCHAIN)\fromelf

# GCC options
ASM_OPTS          := --cpu Cortex-M0 -g --apcs=interwork --pd "__MICROLIB SETA 1"
CC_OPTS           := --cpu Cortex-M0 -D__MICROLIB -g -O2 -Otime --apcs=interwork -D$(MACRO)
LINKER_FILE		  := --cpu Cortex-M0 --library_type=microlib --strict --scatter ".\scan.sct"  --info summarysizes 


APP_C_SRC := $(wildcard $(SRC_DIR)/*.c)
APP_S_SRC := $(wildcard $(ASM_DIR)/*.s)
OBJ_FILES := $(APP_C_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 
OBJ_FILES += $(APP_S_SRC:$(ASM_DIR)/%.s=$(OBJ_DIR)/%.o)
DIRS= $(OUTPUT_DIR) $(OBJ_DIR) 

.phony: all clean

all: FORCE $(APP)

FORCE:
	@echo being

$(APP): $(DIRS) $(OBJ_FILES) 
	@echo Linking $@
	$(LINKER_CSRC) $(LINKER_FILE) $(OBJ_FILES) -o $@
	$(FROMELF) $@ --i32combined --output ".\output\scan.hex"
	$(FROMELF) $@  --bin --output ".\output\scan.bin"
	@echo Done.

clean:
	$(call RM_DIRS,$(OBJ_DIR))
	$(call RM_DIRS,$(OUTPUT_DIR))
	$(call RM_FILES,$(APP))


$(DIRS):
	mkdir $@
	@echo $(OBJ_FILES)

$(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
	@echo begin to comple c source
	$(CC) -c $(CC_OPTS) -o $@ $<

$(OBJ_DIR)/%.o : $(ASM_DIR)/%.s
	@echo begin to comple asm
	$(ASM) -c $(ASM_OPTS)  -o $@ $<

# Make sure everything is rebuilt if this makefile is changed
$(OBJ_FILES) $(APP): makefile

2.2.3. 多预编译宏

利用批处理,添加MACRO参数控制预编译宏。

echo off
set list=__AAA_ __BBB__  __CCCC__ __DDDD__

for %%n in (%list%) do (
	make clean
	make MACRO=%%n ) 

3. 其他

3.1. 总结

命令行的方式使用简单,但是灵活度不够,例如一个Target不能指定宏。Makefile比较灵活,但是前期构建工程会比较复杂,但是如果makefile构建完成之后,使用也非常方便。

3.2. 参考

  1. https://developer.arm.com/documentation/101407/0537/Command-Line
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Keil使用命令行附加预定义宏编译 的相关文章

  • Keil MDK C (error: #29: expected an expression) 错误的解决

    今天 xff0c 自己建了一个EFM32工程模版 xff0c 调试代码时显示 App Panel main c 119 error 29 expected an expression 仔细的检查了半个小时 xff0c 最后解决了 xff01
  • Keil使用命令行附加预定义宏编译

    1 前言 很多时候 xff0c 一份Keil工程代码可能需要满足多个不同的应用场景 可以通过逻辑判断 xff0c 将多个不同的点集成在一份代码之中 xff0c 但是嵌入式往往特别关注RAM空间 xff0c 集成过多的逻辑判断 xff0c R
  • keil 修改RAM、ROM

  • 基于stm32cubemx和keil的stm32(以stm32F407ZGTx为例)单片机的开发----实现printf函数将信息打印至串口

    一 printf打印函数实验 二 实验步骤 1 在cube里设置引脚 串口 串口5设置成异步 2 生成代码打开工程 别忘了先调试JLink 在main c文件开头添加头文件 在主函数外的用户区书写读取文件流函数 这样就可以使用printf函
  • STM32CubeIDE设置Flash烧录地址和大小(告别Keil魔术棒)

    STM32CubeIDE中设置Flash烧写地址和范围 在由Keil平台转到STM32CubeIDE平台过程中 我们熟悉的点开魔术棒进行相关烧录配置的方式已经不适用了 在STM32CubeIDE平台中我们需要通过修改文件的方式来实现 稍显麻
  • Keil编辑和STM32cubemx配置STM32控制步进电机

    使用Keil ARM V5 IDE编程和STM32CUBEMX代码配置实现STM32F103和步进电机驱动器模块A4988控制步进电机 Keil和Stm32cubemx 安装 安装Keil IDE非常简单 下载包含Keil IDE的MDK
  • keil的错误: Error: Encountered an improper argument 的2019.6.22最新解决方法

    keil的错误 Error Encountered an improper argument 的解决方法 什么都不要改动 最正确的办法是重新破解
  • keil5烧录或下载程序出现停止工作的问题

    本人在使用keil5烧录或下载程序出现停止工作的问题 开始认为是keil版本的原因 后来使用了keil4发现问题依然存在 发现因为本人使用了盗版JLINK被驱动检测出来了 由于安装的驱动版本为V6 14 新版的驱动检测到盗版JLINK 一旦
  • keil5 编辑栏一直是灰色

    无语了 气炸了 愤怒啊 查了一下 有很多 arm 和 c51 并存 不管他了 之前装了用完51 又装了arm 现在反而什么都用不了 打开license 发现过期了 重新破解 即可 注意音乐 大半夜吓死人 你以为这样就可以了 你就太天真了 网
  • KEIL编译出现错误“source file is not valid utf-8”

    KEIL编译出现错误 source file is not valid utf 8 在外面复制了一段代码 c文件一直报错source file is not valid utf 8的错误 经查找原因就是 文件中出现中文符号导致的 特别是中文
  • STM32F4 DWT功能 实现程序运行时间精确测试

    时间戳相关寄存器定义 在Cortex M里面有一个外设叫DWT Data Watchpoint and Trace 该外设有一个32位的寄存器叫CYCCNT 它是一个向上的计数器 记录的是内核时钟运行的个数 最长能记录的时间为 10 74s
  • L6050U compile erro

    L6050U The code size of this image exceeds the maximum allowed for this version of the linker 原因 是 用的 是 EVb版本 需要 正版 才没有
  • Keil不能正确生成.bin文件的解决办法

    1 打开keil IDE 然后打开help gt uVison Help 搜索fromelf关键字如下图1 然后再进入到右下角的索引找到fromelf命令行的语法和选项 找到 bin的说明如下 如红色标注所说 正是症结所在 即如果链接文件中
  • STM32如何使用超声波传感器(HC-SR04)。(HAL库版本)

    目录 作用 引脚作用以及接线 原理讲解 项目配置stm32cubmx 代码是实现 作用 首先我们先了解超声波传感器是用来干嘛的 目前我自认为这个传感器就是用来测量距离的 引脚作用以及接线 其次我们先来了解超声波传感器的4个引脚的作用 VCC
  • keil5 Device Database 灰色问题

    使用 keil5 安装 GD 软件包后打开工程依然无法搜索到对应的芯片型号 GD32F450 The Project references device files or libraries that are not installed D
  • Keil转STM32CubeIDE工程移植问题记录

    Keil转STM32CubeIDE工程移植问题记录 1 编译报错问题处理 2 工程相关配置问题 3 调试器配置 从Keil软件转战STM32CubeIDE 转换的过程中遇到了不少问题 在此记录一下 防止以后再踩坑 也给同样有转软件需求的朋友
  • keil mdk代码提示与代码补全设置

    主要参考https blog csdn net w5862338 article details 50520423 结合自己的实际问题 一旦习惯了一些实用的功能 当进入到类似的环境中而没有熟悉的功能 会觉得很不方便 代码提示与补全就是这样实
  • 如何确定嵌入式系统中的最大堆栈使用率?

    当我给Keil编译器 callgraph 选项时 它为我静态计算准确的 最大堆栈使用量 唉 今天它给了我一条 最大堆栈使用量 284 字节 未知 没有堆栈大小的函数 消息 以及 没有堆栈信息的函数 列表 Nigel Jones 表示递归在嵌
  • C 易失性位域结构的复制构造函数

    Good day 我正在尝试在 C 11 项目中使用 C SD 驱动程序 文件系统库 Keil MDK 它是由 Keil MDK 5 23 中的 Pack 管理器添加的 我正在使用 ARMCC 5 06u4 进行编译 我收到警告class
  • 在 Eclipse IDE 中使用 GCC 编译器编译 RTX 内核文件

    我们在KEIL IDE中有一个LPC2148的项目 里面有RTX内核程序以及其他程序 它是由ARM CC编译的 现在我们需要将IDE从KEIL ARM CC 更改为Eclipse GCC 当我们尝试在 Eclipse GCC 编译器中编译它

随机推荐

  • VScode单步调试

    VScode配置 0 快捷键1 安装clang2 VScodeDebug3 Cmake支持gdb调试的方法 0 快捷键 稍大工程在vscode下的调试参考该博客 Ctrl 43 打开默认终端 Ctrl 43 Shift 43 新建新的终端
  • 串口通信简介

    串口通信 串口通信是一种串行异步通信 xff0c 通信双方以字符帧作为数据传输单位 xff0c 字符帧按位依次传输 xff0c 每个位占固定的时间长度 两个字符帧之间的传输时间间隔可以是任意的 xff0c 即传输完一个字符帧之后 xff0c
  • ubuntu16.0 ROS(介绍EAI的YDLIDAR-X4激光雷达在ROS下使用方法)

    YDLIDAR X4激光雷达介绍 YDLIDAR X4激光雷达是深圳越登智能科技有限公司 xff08 YDLIDAR xff0c 这家公司属于EAI xff09 研发的一款 360 度二维测距产品 xff0c 本产品基于三角测距原理 xff
  • php使用http_build_query,parse_url,parse_str创建与解析url

    1 http build query http build query 可以创建urlencode之后的请求字符串 span class hljs keyword string span http build query mixed spa
  • 无人驾驶小车调试笔记(六)-- 车轮校准

    简介 xff1a 小车的动力完全来自于两个电机带动的车轮 xff0c 在理想状态下 xff0c 给两个电机同样的驱动参数 xff0c 两个车轮会以同样的转速带动小车直线行驶 xff0c 而实际情况是每个电机可能都会有个体差异 xff0c 也
  • Nginx HTTP详解

    正文 1 Nginx启动流程 2 HTTP 初始化 新连接建立时的行为 在上次博客的最后可以看到 xff0c 在ngx event accept方法建立连接的最后一步 xff0c 将会调用ngx listening t监听结构体的handl
  • 时钟周期,机器周期,指令周期的相互关系

    1 时钟周期 61 振荡周期 xff0c 名称不同而已 xff0c 都是等于单片机晶振频率的倒数 xff0c 如常见的外接12M晶振 xff0c 那它的时钟周期 61 1 12M 2 机器周期 xff1a 8051系列单片机的机器周期 61
  • 单片机的分频是什么意思?

    分频就是单片机的时钟频率 xff08 也就是晶振的震荡频率 xff09 F经过12分频 xff0c 变换成F 12的频率 简单的来说就是以整数倍降低频率 2分频就是分频前的频率除以2 xff1b 4分频就是分频前的频率除以4 比如 xff1
  • NMOS和PMOS管

    这里我先说一下我自己分辨MOS管的方法 对于NMOS我们看下图中的箭头 xff0c 都是远离源头 对于PMOS我们看箭头 xff0c 都是指向源头 P xff1a POSITIVE积极的寻找自己的起源 N xff1a NEGTIVE消极的远
  • 基本运算放大电路

    我先说明 下面的内容应该很多人都看到过 xff0c 但是我建议还是细看 xff0c 最好自己推一下 我就是这么做的 运算放大器工作原理综述 xff1a 运算放大器组成的电路五花八门 xff0c 令人眼花瞭乱 xff0c 在分析运算放大器工作
  • PCB板框的绘制——AD19

    pcb板框的绘制当然首先要切换到keep out 层才行 找到设置 xff0c 找到keep out 假如我们要绘制一个矩形的板框 xff0c 我们选择线径就可以 手动绘制一个矩形的板框 我们需要让我们的板子边框按照我们所绘制的走线来定义
  • 零基础自学STM32-野火——GPIO复习篇——使用绝对地址操作GPIO

    今天主要是复习一下 结合野火的 零基础开发指南 名字没记住大概是这个 先放一张结构图 存储器映射 xff08 初学重点 xff09 xff1a 我们的片内外设比如 xff1a Flash Sram Fsmc 以及挂在AHB 总线上的外设 x
  • Lcd1602——斌哥51

    最新修改时间2022 7 22 LCD1602 16代表显示16个字符 xff0c 2代表总共显示两行 芯片的工作电压是4 5 5 5v 工作电流2 0ma xff08 5V xff09 模块最佳工作电压5 0v 字符尺寸 xff1a 2
  • 无人驾驶小车调试笔记(七)-- 相机校准

    简介 xff1a 在第五节的内容中 xff0c 我们学习了使用rqt工具集观看摄像头视频流的方法 xff0c 细心的同学应该会发现camera node发布的视频数据中的图像有变形现象 xff0c 图像变形会导致直线不直 xff0c 部分区
  • Python实现MySql、SqlServer增删改查操作

    span class token keyword import span pymssql span class token keyword def span span class token function connection sql
  • ds1302——斌哥51

    以下内容分别借鉴了 清翔 51 xff0c 斌哥51 xff0c 以及CSDN 普通的不普通少年 内部结构 xff1a DS1302 包括时钟 日历寄存器和 31 字节 xff08 8 位 xff09 的数据暂存寄存器 xff0c 数据通信
  • AD添加LOGO

    先上原文链接 xff1a http www allchiphome com circuit pcb logo creator http www allchiphome com circuit pcb logo creator http ww
  • 视频播放组件实战【LivePlayer H5播放器】

    在公司项目开发中 xff0c 有一个项目里面需要做一个视频播放的功能 xff0c 播放方式是调用海康平台提供的接口获取流地址来进行视频的播放并且最重要的是需要支持flash 由于前端用的Vue xff0c 对比了几个 xff0c 最后选择了
  • 如何用示波器测量串口

    如何确定时基 假如要测量的波特率为9600 则每一比特位的时间为 xff1a 1 9600 104 s xff0c 一般示波器横向上每个大格子里5个小格子 xff0c 要想看清一比特位一般需要一个小格子就够了 xff0c 则时基为 xff1
  • Keil使用命令行附加预定义宏编译

    1 前言 很多时候 xff0c 一份Keil工程代码可能需要满足多个不同的应用场景 可以通过逻辑判断 xff0c 将多个不同的点集成在一份代码之中 xff0c 但是嵌入式往往特别关注RAM空间 xff0c 集成过多的逻辑判断 xff0c R