Cortext-M3系列:M3的底层编程(7)

news2024/11/19 21:16:12

1、概览

        在CM3上编程,既可以使用C也可以使用汇编,keil也支持C++,但是大多数人还是会在C与汇编。C与汇编都“尺有所短,寸有所长”,不能互相取代。使用C能开发大型程序,而汇编则用于执行特种任务。

1.1 使用汇编

        如果工程比较小,使用纯汇编常常是可行的,而且能使我们随心所欲地优化和控制程序。不过,这么一来的开发周期会变长。尤其是当工程变大,需要处理比较复杂的数据结构,以及要管理函数库时,汇编那狰狞的真面目就会渐显出来:各种地址和间接引用千头万绪;bug劈头盖脸;甚至好几天都改不完,工作量激增,简直就是自虐。(汇编狗都不用,有时候,我们连狗都不如)

        不论如何,时间宝贵。我们应该以C来实现程序的大框架,而本着好钢用在刀刃上的原则来使用汇编,因为只有在不多的特殊场合是适合使用汇编,甚至是非使用汇编语言不可的,它们包括:

        无法用C写成的函数,如操作特殊功能寄存器,以及实施互斥访问。

        在危急关头执行处理的子程序(如,NMI服务例程)。 ​

        存储器极度受限,只有使用汇编才可能把程序或数据挤进去。 ​

        执行频率非常高的子程序,如操作系统的调度程序。 ​

        与处理器体系结构相关的子程序,如上下文切换。 ​

        对性能要求极高的应用,如防空炮的火控系统。

1.2 使用C

        用C写的程序可以移植,并且操作复杂数据结构时远远比汇编方便。但因为C是一种通用语言——至少是低等高级语言,它并不指定如何初始化具体的处理器(用于在main执行前准备好执行环境)。解决这个问题时,不同的工具链都有自己的一套方法。

        尽管在使用了C后,大大加速了开发,但是底层的系统控制往往还需要汇编代码。很多编译器都允许我们直接在C代码中插汇编,称为“内联汇编”;另外还允许我们写独立的汇编模块,与编译后的C模块一起连接。以往,使用内联汇编的作法比较多,但是在ARM编译器中,不支持对Thumb-2指令的内联汇编。取而代之的,是从RealView C编译器的3.0版开始,新增了所谓“嵌入式汇编”的功能,它支持Thumb-2指令。它让我们可以在C程序中插入使用汇编语言编写的函数,例如:

_asm  void SetFaultMask(unsigned int new_value)
{
		//在这里使用汇编代码实现本函数
		MSR FAULTMASK, new_value //把new_value写入FAULTMASK中BX LR //返回主程序(不可省略)
}

        RealView C编译器对嵌入式汇编的详细论述,在《RVCT 3.0 Compiler and LibraryGuide(Ref6)》中给出。在CM3中,嵌入式汇编还是比较需要的,因为常常会有访问特殊功能寄存器的时候。比如,在设置堆栈时,就要使用MRS/MSR指令。对于其它不能由编译器产生的指令,比如WFI/WFE、互斥访问、存储器隔离等指令,也必须用汇编显式给出。

        在以前的ARM处理器中,因为支持ARM/Thumb双重状态,往往需要所谓的“interworking”,且不同的源文件可能需要编译成不同状态下的代码。在CM3中不再有此需求,因为只使用了Thumb状态,从而工程管理方便多了。

        当使用C开发程序时,推荐开启CM3的双字对齐管理机制(在NVIC配置与控制寄存器中,把STKALIGN置位),这是用于确保系统能严格遵守AAPCS过程调用标准,代码形如:

#define	NVIC_CCR ((volatile unsigned long  *)(0xE000ED14))
*NVIC_CCR = *NVIC_CCR  |  0x200;     //设置STKALIGN位

2、汇编与C的接口

        在很多情况下,都需要让C程序模块与汇编程序模块互相交互,它们包括:

        在C代码中使用了嵌入式汇编(或者是在GNU工具下,使用了内联汇编)

        C程序呼叫了汇编程序,这些汇编程序是在独立的汇编源文件中实现的

        汇编程序调用了C程序

        在这些情况下,必须知晓参数是如何传递的,以及值是如何返回的,才能在主调函数与子程序之间协同工作。这些交互的机制在ARM中有明确的规定,由文档《ARM Architecture ProcedureCall Standard(AAPCS, Ref5)》给出。

                不过,在大多数场合下的情况都比较简单:当主调函数需要传递参数(实参)时,它们使用R0-R3。其中R0传递第一个,R1传递第2个……在返回时,把返回值写到R0中。在子程序中,可以随心所欲地使用R0-R3,以及R12。但若使用R4-R11,则必须在使用之前先PUSH它们,使用后POP回来。

        可见,汇编程序使用R0-R3, R12时会很舒服。但是如果换个立场——汇编要呼叫C函数,则考虑问题的方式就有所不同:必须意识到子程序可以随心所欲地改写R0-R3, R12,却决不会改变R4-R11。因此,如果在调用后还需要使用R0-R3,R12,则在调用之前,必须先PUSH,从C函数返回后再POP它们,对R4-R11则不用操心。

3、典型的开发流程

        在开发基于CM3的应用程序时,常常有多种源程序和库,有些是自己写的,有些是别人已经写好的(尤其是底层的软件)。上述这些开发工具生成代码的流程都差不离。对于最基本的应用,也至少需要C编译器,连接器以及二进制文件处理工具。如果使用的是ARM的工具,如RVDS或RealView编译器工具(RVCT),则它们的流程如图所示。其中的“分散加载脚本”是可选的,但是当存储器映射变得比较复杂时,则需要它。

4、使用互斥访问实现信号量操作

        专门用于信号量的操作中。最常见的用途,就是确保需要互斥使用的共享资源只被一个任务拥有。互斥锁本身的操作是原子访问的。

        在单处理机系统中,互斥访问主要用在ISR与主程序之间,用以保护它们共享的,并且需要互斥访问的资源(如,一块内存,一个外设)。此时,引起互斥写失败的唯一原因,就是在读写期间曾响应过中断。如果代码在特权级下运行,还可以通过设置PRIMASK,在“测试——置位”期间暂时把中断给掐了。 ​

         在多处理机系统中,情况会变得更复杂。此时,除了本机的中断,其它处理机对同一块内存的访问也可以使互斥写操作失败。为了检测到其它处理机对内存的访问,总线系统中必须加入一个“互斥访问监视”的硬件基础设施。它负责检测在互斥读写期间,总线上是否有其它主机访问了互斥锁及其临近的“高危地带”。事实上,在绝大多数低成本的CM3单片机中,都只包含了一个核,因此无需此监视器。 ​

         有了这个机制,我们就可以确信共享资源一定能互斥地使用,不会发生紊乱危象。如果一个共享资源在多次尝试时依然无法获取,则可能必须放弃对此资源的请求,有可能先前锁住该资源的任务已经崩溃了。

5、使用位带实现互斥锁操作

        如果存储器系统支持“锁定传送”(locked transfers),或者总线上只有一个主机,还可以使用CM3的位带功能来实现互斥锁的操作。通过使用位带,则可以在C程序中实现互斥锁,但是操作过程与互斥访问是不同的。在使用位带来做资源分配的控制机制时,需要使用位带存储区的内存单元(比如,一个字),该内存单元的每个位表示资源正被特定的任务使用。 ​

        在位带别名区的读写实质上是锁定的“读-改-写”(在传送期间总线不能被其它主机占有)。因此,只要每个任务都仅修改分配给它们自己的锁定位,其它任务锁定位的值就不会丢失,即使是两个任务同时写自己的锁定位也不怕。

        对于“测试并设置”这种互斥锁的简单操作,也可以使用“关中临界区”来保护——也就是在操作前关中断,操作后开中断。这种关中的时间是很短的,因为其它原因导致的关中通常都比这个长得多。只是有时为了无限追求实时性,有一丝希望也会尽最大的努力,就像这两种互斥锁操作那样。

6、使用位段提取与查表跳转

        位段提取指令(UBFX)和查表跳转指令(TBB/TBH)。这两条指令可以配合工作,以构建一个非常强大的“跳转树”。这对于电表及数据通信应用程序非常有意义,常使这类程序得到戏剧般地优化。这类程序在工作时,经常要判断各种各样的情况,并且“分类讨论”。有时,还需要进一步细化,作二级甚至多级的比较判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/669724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

去中心化金融(DeFi)的发展历史

随着Web3.0的兴起,去中心化金融(Decentralized Finance,DeFi)正逐渐成为金融领域的热门话题。DeFi旨在通过区块链技术和智能合约,实现无需信任的金融交易和服务,摆脱传统金融中心化的限制。然而&#xff0c…

C# Winform Label 控件

目录 一、概述 二、基本用法 1.控件内容显示 2.控件的外观 3.自定义控件的大小 4.控件的内边距 5.设置文本的固定位置 6.控件的事件 结束 一、概述 Label 控件是 winform 开发中最常用的一个控件,一般用做显示文本,也有时用做打开链接等操作。…

如何解决无法直接启动带有“类库输出类型”的项目

输出类型为类库的项目是编译为 dll 文件的项目,该文件旨在供其他项目使用。它无法直接启动,因为它没有 exe 文件。若要调试此项目,请在此解决方案中添加一个引用库项目的可执行项目。将这个可执行项目设置为启动项目,如下&#xf…

msp430fr2155 在线升级(一)

前言:由于单片机如果不支持USB等方式在线升级,每次升级会设计拆机升级单片机,这对于一个成熟的产品是很鸡肋的。所以记录一下本次研发升级功能的过程以及所需要的问题。 一、升级程序设计 二、内存重新分配 1.芯片原有内存分配 原有内存分…

做电商服务软件(电商ERP),怎么实现与电商平台的数据交互?

电商领域是目前互联网最热门、最活跃的行业之一,随着消费需求的增长和普及化,用户对于商品种类和购物体验的要求也越来越高,精准、高效、快速成为谋求更大商品销量的共同目标。因此,电商服务软件的市场需求正不断增强。 想要开发一…

C++---虚函数(8)

多态 虚函数 虚函数就是在类的成员函数声明前加virtual,该成员函数就变成了虚函数。一旦一个类中有虚函数,编译器就会为该类生成虚函数表。 虚函数表中一个元素记录一个虚函数的地址,使用该类构造对象时,对象前4(8)个字节记录虚…

团队知识库的使用场景有哪些?如何搭建团队知识库?

团队知识库是一种用于共享和管理团队知识和信息的工具。它可以帮助团队成员更好地组织、存储、查找和分享信息,提高工作效率和准确性。以下是团队知识库的使用场景和搭建方法的详细介绍。 一、团队知识库的使用场景 项目管理 团队知识库可以帮助团队成员更好地管…

封神之后,又来超神?南卡OE骨传导开放式耳机有啥新本领

终于到了适合夜跑的温度,我的新跑鞋和专用陪跑运动耳机也都收到了,万事俱备却意外中招“二阳”了。虽然身体情况,短期是不能支持去跑步运动了,但每天戴着新耳机打打王者也还是一样很欢乐的。 反正现在时间很多很闲,我…

pyqt6安装与配置(基于vscode环境)

一、安装pyqt6和pyqt6-tools包 注意:pyqt6-tools目前仅支持python3.9版本,3.9版本后的安装部成功。(截止2022.11.20) 1.1 安装pyqt6和pyqt6-tools 安装pyqt和pyqt6-tools可以使用conda和pip进行安装 (1&#xff09…

基于高通camera-帧率-曝光

前人种树,后人乘凉;创造不易,请勿迁移~ daisy.skye的博客_CSDN博客-嵌入式,Qt,Linux领域博主 daisy.skye擅长嵌入式,Qt,Linux,等方面的知识 https://blog.csdn.net/qq_40715266?typelately ———————————————— 版权声明&…

计算机网络(谢希仁-第八版)第四章习题全解

4-01 网络层向上提供的服务有哪两种?试比较其优缺点? 虚电路服务和数据报服务。 虚电路 优点: 1.可以提供可靠的通信服务 2.因为数据是沿着建立的虚电路进行传输的,因此分组的首部不需要携带完整的目的主机 的地址&…

redis 的基本介绍以及 五种 数据类型

一、redis是什么? 一句话:redis 是一个开源的、使用C语言编写的、支持网络交互,基于内存也可持久化的 key-value (非关系型)数据库 redis作者博客,有兴趣的小伙伴可以去逛一逛:http://github.…

后台登录功能开发 -- 手把手教你做ssm+springboot入门后端项目黑马程序员瑞吉外卖(二)

文章目录 前言三、后台登录功能开发1. 需求分析2. 代码开发3. 功能测试(简略) 四、后台退出功能开发1. 需求分析2. 代码开发3. 功能测试(简略) 总结 前言 为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客…

Servlet规范maven创建webapp项目

main目录下新建webapp pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.…

C++完成淄博烧烤节管理系统

背景&#xff1a; 这次我们结合今年淄博烧烤做一个餐厅管理系统&#xff0c;具体需求如下&#xff0c;我们选择的是餐饮商家信息管理 问题描述&#xff1a; 淄博烧烤今年大火&#xff0c;“进淄赶烤”是大家最想干的事情&#xff0c;淄博烧烤大火特火的原因&#xff0c;火的…

SSM海南省陵水县旅游网站-计算机毕设 附源码87145

SSM海南省陵水县旅游网站 摘 要 本系统的前端界面主要实现页面的美观和动态效果使之符合广大群众的审美观&#xff0c;后台主要使用的技术主要有Java编程语言&#xff0c;SSM框架&#xff0c;JSP技术、Ajax技术进行开发系统。海南省陵水县旅游网站解决了传统旅游方式中数据分析…

开发者聚焦 | 不容错过的开发者新专栏就要来啦!

掌握前沿技术动态、获得新产品与新应用的使用技巧、在开放专业的社区中与志同道合的朋友交流互动&#xff0c;这些对于开发者来说&#xff0c;都是提高工作效率与自我技能的利器。 为了与开发者互动&#xff0c;并在社区与开发者建立连接和影响&#xff0c;让亚马逊云科技更好…

Toyota Programming Contest 2023#3(AtCoder Beginner Contest 306) 6月17日比赛 第四题

题目地址&#xff1a;D - Poisonous Full-Course 题目大意 时间限制&#xff1a;2秒&#xff0c;空间限制&#xff1a;1024MB&#xff0c;分值&#xff1a;400分 问题描述 小明来到了一家餐厅&#xff0c;一共有道菜&#xff0c;第道菜具有以下属性&#xff1a; 若&#xf…

web前端框架JS学习之JavaScript类型转换

vascript有多种数据类型&#xff0c;如字符串、数字、布尔等&#xff0c;可以通过typeof语句来查看变量的数据类型。数据类型转换就是数据类型之间相互转换&#xff0c;比如把数字转成字符串、把布尔值转成字符串、把字符串转成数字等&#xff0c;这在工作也是经常碰到的。 本…

C++----继承,多重继承(7)

面向对象的三大特征 封装 继承 多态 封装 该隐藏的数据私有化&#xff0c;该公开的数据设计为公有的接口 private public 目的为了更好地分工合作&#xff0c;有助于数据的安全性和使用的方便性&#xff0c;也防止不必要的扩展。 继承(inherite) 作用 实现了代码的复用&a…