MDK编译过程、文件及_attribute__关键字

news/2024/12/23 7:12:34/
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="htmledit_views">

一.MDK编译过程及文件说明

1.MDK 的编译过程

c="https://i-blog.csdnimg.cn/direct/b597a7b35b56406c9eda61e804859c16.png" width="691" />

2.编译结果说明

c="https://i-blog.csdnimg.cn/direct/3e755de8ca9d424185f2706dae924e41.png" width="692" />

在工程的编译提示输出信息中有一个语句“Program Size:Code=xx RO-data=xx RW-data=xx ZIdata=xx”࿰c;它说明了程序各个域的大小࿰c;编译后࿰c;应用程序中所有具有同一性质的数据 (包括代码) 被归到一个域࿰c;程序在存储或运行的时候࿰c;不同的域会呈现不同的状态࿰c;这些域的意义如下:

Code:即代码域࿰c;它指的是编译器生成的机器指令࿰c;这些内容被存储到 ROM 区。

RO-data:Read Only data࿰c;即只读数据域࿰c;它指程序中用到的只读数据࿰c;这些数据被存储在ROM 区࿰c;因而程序不能修改其内容。例如 C 语言中 const 关键字定义的变量就是典型的RO-data。

RW-data:Read Write data࿰c;即可读写数据域࿰c;它指初始化为“非 0 值”的可读写数据࿰c;程序刚运行时࿰c;这些数据具有非 0 的初始值࿰c;且运行的时候它们会常驻在 RAM 区࿰c;因而应用程序可以修改其内容。例如 C 语言中使用定义的全局变量࿰c;且定义时赋予“非 0 值”给该变量进行初始化。

ZI-data:Zero Initialie data࿰c;即 0 初始化数据࿰c;它指初始化为“0 值”的可读写数据域࿰c;它与RW-data 的区别是程序刚运行时这些数据初始值全都为 0࿰c;而后续运行过程与 RW-data 的性质一样࿰c;它们也常驻在 RAM 区࿰c;因而应用程序可以更改其内容。例如 C 语言中使用定义的全局变量࿰c;且定义时赋予“0 值”给该变量进行初始化 (若定义该变量时没有赋予初始值࿰c;编译器会把它当 ZI-data 来对待࿰c;初始化为 0);

ZI-data 的栈空间 (Stack) 及堆空间 (Heap):在 C 语言中࿰c;函数内部定义的局部变量属于栈空间࿰c;进入函数的时候从向栈空间申请内存给局部变量࿰c;退出时释放局部变量࿰c;归还内存空间。而使用 malloc 动态分配的变量属于堆空间。在程序中的栈空间和堆空间都是属于ZI-data 区域的࿰c;这些空间都会被初始值化为 0 值。编译器给出的 ZI-data 占用的空间值中包含了堆栈的大小 (经实际测试࿰c;若程序中完全没有使用 malloc 动态申请堆空间࿰c;编译器会优化࿰c;不把堆空间计算在内)。

c="https://i-blog.csdnimg.cn/direct/1d47ed5998854207977ecadad5a20a0e.png" width="692" />

c="https://i-blog.csdnimg.cn/direct/c93611e65fc14bbaa6302742a709f72f.png" width="692" />

3.hex、bin 及 axf 文件的区别与联系

bin、hex 及 axf 文件都包含了指令代码࿰c;但它们的信息丰富程度是不一样的。

bin文件是最直接的代码映像࿰c;它记录的内容就是要存储到 FLASH 的二进制数据 (机器码本质上就是二进制数据)࿰c;在 FLASH 中是什么形式它就是什么形式࿰c;没有任何辅助信息࿰c;包括大小端格式也没有࿰c;因此下载器需要有针对芯片 FLASH 平台的辅助文件才能正常下载(一般下载器程序会有匹配的这些信息);

hex文件是一种使用十六进制符号表示的代码记录࿰c;记录了代码应该存储到 FLASH 的哪个地址࿰c;下载器可以根据这些信息辅助下载;

axf文件在前文已经解释࿰c;它不仅包含代码数据࿰c;还包含了工程的各种信息࿰c;因此它也是三个文件中最大的。

二.“__attribute__”关键字的说明

在程序中࿰c;当需要指定某个变量的内存地址时࿰c;MDK 提供了一个关键字“__attribute__”实现该功能࿰c;这种用法通常也是为了把变量指定到外部扩展的存储器。

使用示例:

 /* 定义一个要指定的地址 */

#define USER_ADDR ((uint32_t)0x20005000)

/* 使用 atribute 指定该变量存储到 USER_ADDR, 这种方式必须定义成全局变量 */

uint8_t testValue __attribute__((at(USER_ADDR)));

testValue = 0xDD;

这种方式使用“__attribute__((at()))”来指定变量的地址࿰c;代码中指定 testValue 存储到 USER_ADDR地址 0x20005000 中࿰c;若把该地址改为外部存储器 SRAM 的地址࿰c;变量就会被存储到外部 SRAM了࿰c;因而利用该关键字在一定程度上可以定制各种存储器的空间分配。要注意使用这种方法定义变量时࿰c;必须在函数外把它定义成全局变量࿰c;才可以存储到指定地址上。

class="blog-extension-box">

http://www.ppmy.cn/news/1524144.html

相关文章

揭开面纱--机器学习

一、人工智能三大概念 1.1 AI、ML、DL 1.1.1 什么是人工智能? AI:Artificial Intelligence 人工智能 AI is the field that studies the synthesis and analysis of computational agents that act intelligently AI is to use computers to analog and instead…

11. 建立你的第一个Web3项目

11. 建立你的第一个Web3项目 在这一部分,我们将带你一步步地建立一个简单的Web3项目,从环境搭建到智能合约的创建与部署,再到开发一个去中心化应用(dApp)并与智能合约交互。这是你迈向Web3开发的第一步。 1. 环境搭建…

Groovy -> Groovy 集合操作

List的增删改查 [1, 2, 3, 4] [1, 2, 3, 4, 5, 6] [2, 3, 4] [3, 4] [1, 2, 3, 4] [3, 4, 10] [3, 4, 20] Element: 3 Element: 4 Element: 20 contains 3// log [1, 2, 3, 4] [1, 2, 3, 4, 5, 6] [2, 3, 4] [3, 4] [1, 2, 3, 4] [3, 4, 10] [3, 4, 20] Element: 3 Element: 4…

浅谈C#之任务调度TaskScheduler

一、基本介绍 TaskScheduler 是一个抽象类,用于控制任务的执行方式,特别是它们如何被安排到线程池中的线程上执行。 TaskScheduler 负责将 Task 对象排队并决定何时、以何种方式执行这些任务。 二、TaskScheduler的作用 调度任务:将任务分配…

【网络安全】密码学概述

1. 密码学概述 1.1 定义与目的 密码学是一门研究信息加密和解密技术的科学,其核心目的是确保信息在传输和存储过程中的安全性。密码学通过加密算法将原始信息(明文)转换成难以解读的形式(密文),只有拥有正…

MQ-2烟雾传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 mq2.h文件 mq2.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 MQ-2气体传感器是一种常用的气体传感器,用于检测空气中的烟雾浓度。工作原理是基于半导…

设计模式-行为型模式-状态模式

1.状态模式的定义 允许一个对象在其内部状态改变时改变他的行为,用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题,状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活变化&…

计算987654321*123456789

#include <stdio.h>int main() {int a[9] {9,8,7,6,5,4,3,2,1};int b[9] {1,2,3,4,5,6,7,8,9};int c[20] {0};//定义第三个数组装乘积值int flag 0;//定义一个标志位int count 0;//定义一个进位//先进位再相加for(int i 0;i < 9;i)//遍历数组a的每一位{for(int …