| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> IAR 8051 嵌入式开发概述 -> 正文阅读 |
|
[嵌入式]IAR 8051 嵌入式开发概述 |
节选自IAR C/C++ Compiler User Guide ,47 ~ 58 页 使用IAR 构建工具开发嵌入式软件通常,嵌入式软件是为特定的微处理器编写的。程序的主要流程被设计成一个无限循环,等待外部的事件发生,然后做出处理。程序位于单片机的ROM 区域(注:一般单片机都是哈佛架构,与PC 不同),在系统复位后开始执行。编写嵌入式软件时,必须综合考虑多种硬件和软件方面的因素。作为辅助,开发工具提供了编译器选项、扩展关键字、#pragma 预编译指令等。 存储映射和分区嵌入式系统一般包含多种不同类型的存储区,比如片内RAM、扩展DRAM 或SRAM、ROM、EEPROM,以及flash 存储区。 注:有些单片机是不带RAM 的。单片机使用的哈弗架构,执行程序的时候RAM 并不是必须的,程序内部的变量有些时候只用寄存器就足够了,比如AVR 这种通用寄存器比较多的类型。而PC 则需要先把程序代码和数据全部加载到RAM 之后才能执行。 作为嵌入式软件开发者,必须理解这些存储区的不同特性和功能。举例来说,片内RAM 一般比其他类型的存储要快,对于时序要求高的应用,把经常访问的变量放在片内RAM 里会更有效率。而一些配置信息可能使用不频繁,但是需要在掉电后保持它们的值,这时候就应该把它们放进EEPROM 或者flash 存储。 为了实现高效的存储分配,编译器提供了一些机制,用来指示应该把函数代码和数据放在什么地方,参见控制数据和函数的存储位置 @ 原文259 页。根据特定的链接器配置文件,链接器控制代码和数据区段的存储,参见安排代码和数据 - 链接器配置文件 @ 原文122 页。 与外设单元的通讯如果有外部器件连接到单片机上,可能就需要初始化并控制信号接口。比如,使用SPI 的CE 引脚,以及监听并处理外部中断信号。通常,这些工作都是在运行时完成的,通过使用单片机的特殊功能寄存器(SFR)实现。这些寄存器一般都位于特定的地址上,包含一些用于配置芯片功能的数据位。 这些寄存器和单片机标准外设的信息在每个器件特定的I/O 头文件中定义,扩展名是*.h*,参见器件支持 @ 原文43页,或者上一篇blog。关于使用的例子,参见访问特殊功能寄存器 @ 原文273 页。 事件处理在嵌入式系统中,中断 是一种实时处理内外事件的方式,比如检测一个按钮按下的事件,以及串口通信的事件。一般来说,当中断被启用后,一旦触发,单片机就会立即从正在执行的代码中跳出,开始执行中断处理的程序流程。 注:这说的是正在执行main 函数的时候发生了中断。在执行中断处理流程的过程中也可以继续发生中断,这时候要怎么处理就会复杂很多。此外,中断也可以在完全没有执行代码的时候发生,比如单片机休眠后中断唤醒。总之,基本上就是任何时候,而这种灵活性也相应的导致了复杂性。 编译器提供了一些语法,用来管理硬件和软件中断,以及编写自定义的中断处理程序(注:也就是中断服务程序,ISR,向中断服务的流程),参见中断原语、并行以及操作系统相关的编程 @ 原文97 页。 系统启动在所有的嵌入式系统中,系统启动代码都是用来在 嵌入式软件开发者必须保证启动代码位于特定的地址上,或者有向量表中的指针指向它(注:指复位中断)。这意味着启动代码以及向量表必须放在非易失性存储中,比如ROM、EEPROM、或者flash。 注:说什么废话……一般预定义的启动代码编译之后会自动加进程序里,基本上就几行汇编,哪怕项目里没有驱动代码的文件。大部分时候不用操心这个,也别想着一定要把功能性的初始化代码放进去,那些启动代码的作用是,没有它们,程序本身都跑不动。 C/C++ 应用程序进一步,还需要初始化所有全局变量,这些工作是由链接器和系统启动代码共同处理的。参见应用程序的执行 - 概述 @ 原文52 页,就在这篇后面。 实时操作系统(RTOS)很多情况下,由一个main 函数构成的嵌入式程序就是唯一在系统上跑的软件。然而,使用RTOS 会有一些好处。 注:RTOS 最基本的功能就是任务调度,类似于有几个灯要定时交替亮这种,大部分时候有这么个调度框架就够用了。 比如说,高优先级任务的执行时序不会被程序其他部分的低优先级任务影响。这通常可以让程序的行为更有确定性,并且可以更有效率的使用CPU、让CPU 在空闲时进入休眠模式,从而可能减少单片机的电量消耗。 使用RTOS 可以让程序更易读、易维护,很多时候还能减少代码体积(注:因为你可能会自己写一堆比较笨拙的代码来实现和RTOS 相似的功能。)。应用代码可以被干净的分离成几个任务,相互间可以相对独立。这可以让团队合作更容易实现,同时开发任务也可以简单的分离成多个任务,由多名开发者或团队同时推进。 最后,RTOS 可以给应用程序创造一个相对干净的开发接口,降低硬件依赖性,可以更容易的将代码移植到不同的硬件平台。 构建流程 - 概述这一节将介绍程序的构建流程,介绍相关的构建工具——编译器、汇编器(注:就是汇编代码的编译器)和链接器,以及它们的协作过程,从源代码开始,到生成可执行文件。为了更熟悉实践中的过程,你还应该实际运行一两个IAR 提供的示例项目。 注:这部分可以去看看其他描述编译、链接过程的资料,应该有本书名字就叫”程序员的基本修养“,看看也没坏处,如果有时间的话。 编译过程IDE 中有两个工具,也就是IAR C/C++ 编译器和IAR 汇编器,它们用于将源代码编译成目标文件,这是一种中间产物。两种工具生成的都是IAR UBROF 格式的可重定位目标文件。有需要的话,编译器也可以用来生成汇编源文件,你可以直接修改汇编文件,然后再用汇编器编译成目标文件。关于汇编器的更多信息,参见IAR Assembler User Guide for 8051。 编译过程的图示如下: 编译过后,你可以将任意数量的模块打包成一个库,每个模块就是一个目标文件。使用库的好处是,构成库的每个模块只会在被直接或间接使用时才会链接到应用程序中(注:静态链接)。或者,在创建库之后,也可以使用IAR XAR Library Builder 或IAR XLIB Librarian(注:大概是用来生成IAR 特别的两种库文件格式)。 注:一般很少有必要生成个静态库之后再用,尤其是嵌入式环境,以前的话顶多能省点编译时间吧。如果把代码编译成静态库再用,万一硬件配置改变了,可能还得重新把库编译一遍,灵活性太差了。像arduino 的生态里,基本上库都是按源代码分发,然后就地编译进程序里。 链接过程目标文件或库文件形式的可重定位模块,被IAR 编译器和汇编器生成后,是不能直接原样执行的。要变成一个可执行文件,首先要经过链接。 IAR 环境使用的链接器是IAR XLINK 链接器。通常,链接器需要以下信息作为输入:
IAR XLINK 链接器可以根据配置生成输出,可以根据需要选择不同的输出格式。你可能会想把输出加载到调试器,也就是说你需要输出调试信息。或者也可能像把输出送给编程器,这时调试信息就是不需要的。使用 链接过程的图示如下: 链接过程中,链接器可能会在 更多信息参见IAR Linker and Library Tools Reference Guide。 链接之后IAR XLINK 链接器会生成一个绝对地址目标文件,如果你没有选择别的格式。链接完成后,这个目标文件可以被用于:
输出文件的可能用法如下图: 应用程序的执行 - 概述这一部分介绍了嵌入式程序的执行过程,分为三个阶段:
初始化阶段初始化阶段在程序启动后,main 函数执行前,也就是CPU 复位后。简单起见,初始化阶段可被分为:
对于一个基于ROM 或者flash 的系统(注:也就是单片机的哈佛架构),所有的常量和函数代码直接放在ROM 中。而所有放在RAM 中的符号(注:只包括全局和静态的量)都必须在main 函数执行前被初始化。链接器在程序执行前已经把RAM 分割成多个区域,分别用于变量、栈、堆以及其他。 以下图示简要介绍了初始化阶段的流程,关于初始化流程各阶段的更多信息,参见系统启动和终止 @ 原文164 页。关于对数据的初始化,参见初始化和系统启动 @ 原文123 页。 1. 复位后首先系统启动代码执行硬件初始化,比如根据预先划分的栈区域,让栈指针指向正确的位置。 2. RAM 初始化将所有RAM 区域用0 填充。 3. 变量初始化执行所有全局和静态量的初始化,把它们的数据从ROM 复制到对应RAM 地址。 4. 调用main 函数执行阶段嵌入式软件主要流程的实现一般是一个循环,然后要么由中断驱动,要么用轮询,从而实现与外部的交互,以及处理内部事件。如果是一个中断驱动的程序,相关的中断配置一般会在main 函数的开头完成。 对于一个有实时性要求的系统,多任务操作系统提供的框架可能是必要的。这意味着你的程序软件应该作为一个实时操作系统的一部分。这种情况下,RTOS 本身以及要执行的各种任务必须要在main 函数中初始化并启动。 终止阶段通常,嵌入式应用一经启动,永远不会主动终止。如果需要的话,你必须让终止行为明确且合适。 要让一个应用受控的终止,要么调用标准库函数,比如 注:以前听说过,好像有什么单片机,它的main 函数外面默认包了一层无限循环,就是说从main 退出之后只会再次回到开头初始化的部分。 当然,如果程序逻辑有问题,程序也可能以不受控的形式终止,也就是一场系统崩溃。更多信息参见系统终止 @ 原文166 页。 注:为了保证哪怕在完全未知的情况也不至于因为失控而造成严重后果,可以使用看门狗自动复位,或者自动执行正确的终止流程。相关的高可靠设计方法的书估计起码能填满一个书架,算上讲反面案例的故事书的话就更多了。当然更简单的还是,有点b 数,别去掺和那些很可能搞出人命的事。 构建应用程序 - 概述在命令行环境下,要将源代码文件myfile.c 编译成目标文件myfile.r15,可以使用如下命令:
这条命令使用默认设置生成了目标文件,实际中你必须明确一些重要的参数,参见基本项目配置 @ 原文56 页,就在后面。 调用链接器可以使用如下命令:
这行示例给链接器输入了两个目标文件,即myfile.r51 和myfile2.r51,my_configfile.xcl 是链接器配置文件。 构建项目的时候,IDE 环境下会在Build 消息窗口输出大量的构建信息。这些信息可能会派上用场,比如,可以据此生成构建项目的命令行脚本。要启用这个功能,右键点击Build 消息窗口,在弹出菜单中选择All。 基本项目配置这一节将会简要介绍项目的基础配置,从而让编译器和链接器能够根据项目的目标器件生成最佳的程序。在IDE 或命令行环境下你都可以设置这些参数。 基本上,你可能需要设置以下方面的参数:
除了这些以外,还有很多其他选项,可以通过精细的调整让结果更佳。关于所有可用的选项的信息,参见编译器选项 以及IDE 项目管理和构建指引 章节。 处理器配置要让编译器能生成最优化的代码,你应该告诉它你使用的8051 处理器类型。 CPU 核心编译器支持经典的Intel 8051 微处理器核心、美信(Dallas)DS80C390 核心、Mentor Graphics M8051W/M8051EW 核心,以及相似的其他器件。 命令行环境可以使用参数 IDE 环境下,可以在Project > Options > General Options > Target 菜单下,从Core 选项的下拉菜单中选择正确的选项。与核心相关的其他默认配置随后会自动完成,用于链接器和调试器的器件配置文件也会自动选择。 数据模式8051 系列微处理器的一个特点就是在存储访问能力方面的取舍,可选择的范围从 编译器选项 数据存储 章节涵盖了这方面更多的细节,同时还包括了如何在代码中覆盖单个变量的默认设置。 代码模式编译器支持在文件或单个函数的层面上设置默认的函数位置,这同时隐含了函数调用约定的默认配置。代码模式的更多细节参见函数 章节。 调用约定用编译器选项 DPTR 配置一些器件可以使用最多8 个数据指针,使用它们可以提高执行一些库函数代码的效率。 使用编译器选项 对速度和体积的优化编译器可以对代码进行多种优化,包括:
编译器也可以对循环做优化,比如把循环展开并删除循环变量(注:就是把循环变成写死的一大串代码)。 你可以在多个优化等级中择其一,在最高优化等级时,你可选择三种不同的优化目标——体积、速度和平衡。大部分优化可以让程序跑的更快,同时体积更小,但是当这种最优结果无法实现时,编译器会根据优化目标来选择要执行的优化。 注:比如内联和循环展开优化,基本上肯定会导致体积膨胀。 优化等级和优化目标可以用在整个程序上,也可以在单个文件甚至单个函数的等级分别指定。此外,一些优化是可以单独被关闭的,比如函数内联。 更多关于编译器优化的以及高效率编码技巧的信息,参见高效嵌入式应用编码 章节。 |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 8:18:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |