Cortex-M0编程入门

news2024/12/24 0:20:27

目录

  • 1.嵌入式系统编程入门
    • 微控制器是如何启动的
    • 嵌入式程序设计
  • 2.输入和输出
  • 3.开发流程
  • 4.C编程和汇编编程
  • 5.什么是程序映像
  • 6.C编程:数据类型
  • 7.用C语言操作外设
  • 8.Cortex微控制器软件接口标准(CMSIS)
    • 简介
    • 标准化内容
    • 组织结构
    • 使用方法
    • 优势

1.嵌入式系统编程入门

微控制器是如何启动的

  • 为了保存编译好的程序代码,大多数的现代微控制器都会包含片上Flash存储器。程序代码在Flash存储器中是以二进制机器码的形式存放的,因此C代码必须经过编译,才能烧写到Flash中。有些微控制器会配备一个独立的启动ROM,里面有一个小的Boot loader程序。微控制器启动后,在执行Flash里的用户程序前,Boot loader会首先运行。
  • 程序代码烧写到Flash存储器(或者是其它类型的程序存储器)以后,处理器就可以访问程序了。复位以后,处理器将会运行复位流程。
    在这里插入图片描述
    在复位流程中,处理器会取出MSP的初始值和复位向量,然后开始执行复位处理。这些所需信息都放在一个叫做启动代码的程序文件中。启动代码中的复位处理可能还会履行系统初始化的职责,一般系统初始化是在C程序main()中开始的。
  • 执行完C启动代码后,应用程序就开始执行了。其通常包含:硬件初始化(如时钟、PLL和外设)、应用程序的处理部分、中断服务程序。
    应用程序可能会用C库函数,此时C编译器/链接器会将所需的库函数纳入编译好的程序映像中。
    硬件初始化可能会涉及到一系列的外设、系统控制寄存器和Cortex-M0里的中断控制寄存器。如果在复位处理时没有进行处理,系统时钟控制和PLL此时也需要进行初始化。外设初始化完成后,程序就可以继续执行应用程序处理部分了。

嵌入式程序设计

应用程序处理流程可以用三种方式来实现,下面是一些基本概念:

  • 轮询:轮询适用于简单的应用程序,而当应用程序变得复杂或对处理能力的要求更高时,轮询就不合适了。比如当一个进程占用时间过长,其他模块在这段时间内就不会收到处理器的任何服务。
    轮询方式示意图如下:
    在这里插入图片描述
  • 中断驱动:对于一些需要低功耗的应用,处理器可以在中断服务程序中执行处理,当没有任务需要处理时进入休眠模式。外部中断源或者芯片外设都可以触发中断,并唤醒处理器。此外,在中断程序的应用程序中,不同设备的中断可以被设置为不同的优先级。
    中断驱动应用程序方式如下:
    在这里插入图片描述
  • 轮询和中断驱动的组合使用:许多情况下,应用程序可以将中断驱动和轮询这两种方式组合使用,通过软件变量传递,中断处理程序和主处理流程间可以进行信息交换,如下图:
    在这里插入图片描述
    将一个处理任务分割为中断服务程序和主流程中的处理,可以减少中断服务的持续时间,以便低优先级的中断能有更多的机会获得服务。
  • 处理并发任务:当一个处理任务可能会占用大量时间时,上述的处理就不合适了。如果任务A的执行需要太长的时间,任务B和C可能就无法及时响应外设模块的请求。针对这种情况,一般的解决方案如下:
    1.将一个长时间的处理任务划分为一系列的状态,每次处理任务时,只执行一种状态。
    2.使用实时操作系统(RTOS)处理多任务。
    使用第1种方法,一个任务被划分为了几个部分,可以使用软件变量追踪任务的状态。每次执行任务时,状态信息就会得到更新,这样下次再执行这个任务时,就可以继续上次的处理了。如下:
    在这里插入图片描述

而对于更加复杂的应用程序,可以使用RTOS。RTOS将处理器时间划分为多个时间片,在有多个应用进程运行时,只有一个进程会获得时间片。使用RTOS,需要由定时器产生周期性的中断请求。当一个时间片的时间到时,RTOS的任务调度器会由定时器中断触发,并判断是否需要执行上下文切换。如果需要,任务调度会暂停正在执行的任务,并切换到下一个准备就绪的任务。如下:
在这里插入图片描述

RTOS可以提高系统的反应能力,并且确保在一定时间内能够执行到所有任务。

2.输入和输出

在许多嵌入式系统中,可用的输入和输出有简单的电子接口,如数字和模拟输入/输出接口(I/O)、UART、I2C和SPI等,此外,还提供了USB、以太网、CAN图像LCD以及SD卡等接口,这些接口是由微控制器的外设控制的。

Cortex-M0的寄存器映射到了系统空间,并且它们还控制着外设。外设的典型初始化过程一般包括以下步骤:

  • 配置时钟控制回路,使能外设的时钟信号,并且有必要的话,初始化相应的引脚。
  • 配置I/O,大多数微控制器的引脚都是复用的,需要对I/O引脚的功能进行配置,以确保外设接口正常工作。
  • 配置外设,大多数接口外设都有多个可编程的控制寄存器,因此,为了确保外设工作正常,就需要对寄存器进行一系列的编程操作。
  • 配置中断,如果外设操作需要中断处理,就需要另外配置中断控制器。

3.开发流程

ARM微控制器可以使用的开发工具链有很多种,它们大多数都支持C和汇编语言。开发嵌入式工程时,可以使用C语言,也可以用汇编,或者两者混合编程。多数情况下,程序代码生成流程可以总结为如下所示的形式:
在这里插入图片描述

根据所使用开发工具的不同,链接器可能会使用命令行选项来指定内存分布。

生成可执行映像后,可以将其下载到微控制器的Flash存储器或内存中进行测试。开发工具与在线调试器配合使用时,可以分步进行以下工作:创建工程,编译应用程序,然后下载嵌入式应用程序到微控制器中,如下:
在这里插入图片描述
要想对Flash进行编程,可以使用开发组件中的调试器软件,或者从微控制器供应商网站下载的Flash编程工具。在微控制器上运行程序可以测试其正确性,而将调试器连接到微控制器上,则可以控制程序的运行并且观察其各种操作。这些功能都可以通过Cortex-M0处理器的调试接口实现,如下:
在这里插入图片描述

4.C编程和汇编编程

C语言和汇编语言的使用比较如下:
在这里插入图片描述

  • 大多数C编译器都允许在C程序代码中嵌入汇编代码。
  • 有些特殊指令没法用C代码生成,所以一些C编译器还提供了内在函数,其一般是与开发工具相关联的。
  • 可以在同一个工程里使用C和汇编代码混合编程,程序的大部分代码可以用C编写,无法用C实现的部分则使用汇编,这样做是为了保证输入参数和返回值的正确传递,两部分的函数接口必须保持一致。

5.什么是程序映像

Cortex-M0的程序映像一般包括以下几个部分:

  • 向量表:
    向量表可以用C语言或汇编语言实现。由于向量表的入口需要编译器和链接器生成的内容,所以向量表代码的实现细节是同开发工具链相关的。
    为了将向量表置于系统存储器映射的开头(地址为0x00000000),链接文件或命令行选项需要知道段的名字,以便链接器能够正确识别向量并将其地址映射。
    复位向量一般指向C启动代码的开头,不过,也可以自己定义复位处理,在跳转到C启动代码前执行附加的初始化操作。

  • C启动例程:
    C启动代码用于设置像全局变量之类的数据,也会清零加载时未被初始化的内存区域。初始化完成后,启动代码跳转到main()程序执行。
    C启动代码由编译器/链接器自动嵌入到程序中,并且是和开发工具链相关的,而只使用汇编代码编程则可能不存在C启动代码。对于ARM编译器,C启动代码被标识为"_mian",而是用GUN C编译器生成的代码则通常被标记为"_start"。

  • 程序代码(应用程序代码和数据):
    用户指定的任务是由应用程序生成的指令完成的,除了指令以外,还有以下各类数据:
    1.变量的初始值,函数或子程序中的局部变量需要初始化,这些初始值会在程序执行期间被赋给相应的变量。
    2.程序代码中的常量,应用程序中的常量数据有多种用法,如数据值、外设等寄存器的地址和常量字符串等,这些数据在程序映像中一般作为数据块放在一起,并被称作文字库。
    3.其他的常量,如查找表和图像数据。

  • C库代码(C库函数的程序代码,链接时插入):
    当使用特定的C/C++库函数时,它们的库代码就会由链接器嵌入到程序映像中。另外,由于有些数据处理任务需要浮点数或除法运算,在进行这些运算时,C库代码也会被包含进来。Cortex-M0中没有除法指令,需要借助C函数库中的除法函数来实现除法运算。
    除了向量表需要放在存储器映射的开头以外,程序映像中剩余部分的位置就没有限制了。

RAM中的数据:
像程序ROM一样,微控制器的RAM也有多种用法。典型地,RAM的使用一般可以分为数据、栈和堆区域,如下所示:

在这里插入图片描述
数据、栈和堆区域存储内容如下:

数据:数据存储在内存的底部,包含全局变量和静态变量,为了节省内存,可以将局部变量分配在栈上,而且函数内未用的局部变量不占用存储器空间。
栈:栈空间用于临时数据存储(常见的PUSH和POP操作)、局部变量的存储空间、函数调用参数传递和异常处理的寄存器备份等。
堆:堆存储用于C函数自动分配存储器区域,以及其他使用这些函数的函数调用。为了确保这些函数能够正确地分配存储器空间,C启动代码需要初始化堆存储及其控制变量。

一般来说,栈位于存储器空间的顶部,而堆区域则位于底部,这样做使得内存使用具有最大的灵活性。在操作系统环境中,可能会有多个内存区域用作数据、栈和堆。

有些操作系统允许用户自定义任务的栈,这样也就需要更大的栈空间。有些操作系统则将内存分为若干个段,每个任务分配一个段,用于各自的数据、栈和堆区域,如下:
在这里插入图片描述

6.C编程:数据类型

Cortex-M0处理器支持的数据类型如下:
在这里插入图片描述
在这里插入图片描述

将应用程序从其他架构的处理器移植到ARM上时,如果两者的数据类型的宽度不同,那么可能就需要修改C代码,以确保程序运行正常。此外,在Cortex-M0上编程时,变量的存放地址为其数据宽度的倍数。

7.用C语言操作外设

  • 除了变量以外,微控制器的C应用程序通常需要操作外设。对于ARM Cortex-M0微控制器,外设寄存器被映射到系统存储器空间,它们可以通过指针进行访问。外设访问定义指针时,需要使用volatile关键字。
  • 大多数情况下,外设寄存器都被定义为32位宽度,这是因为连接外设的外部总线(APB)是按照32位处理数据传输的,有些外设可能会连接至处理器总线(AHB),这样,寄存器可以按照其他宽度的方式访问。

8.Cortex微控制器软件接口标准(CMSIS)

简介

随着嵌入式软件复杂性的增加,软件代码的兼容性和可重用性变得更加重要。为了使软件产品具有高度的兼容性和可移植性,ARM同一些微控制器供应商一起开发了一个通用的软件框架CMSIS,该框架适用于大多数的Cortex-M处理器以及Cortex-M微控制器产品,如下:
在这里插入图片描述
CMSIS一般是作为微控制器厂商提供的设备驱动库的一部分来使用的。为了使用诸如NVIC和系统控制功能等处理器特性,CMSIS提供了一种标准化的软件接口。

标准化内容

CMSIS为嵌入式软件提供了以下标准化的内容:

  • 标准化的操作函数,用于访问NVIC、系统控制块(SCB),SysTick的中断控制和初始化。
  • NVIC、SCB和SysTick寄存器的标准化定义。
  • 使用Cortex-M0微控制器指令的标准化函数。有些指令不能由普通的C代码生成,如果需要这些指令,就可以使用CMSIS提供的这类函数来实现。
  • 系统异常处理的标准化命名。
  • 系统初始化函数的标准化命名。
  • 为时钟频率信息建立标准化的变量。
  • 设备驱动库的通用平台。

组织结构

CMSIS可以分为以下 几层:

  • 核心外设访问层:命名定义,地址定义,以及访问核心寄存器和NVIC、SCB以及SysTick等核心外设的辅助功能。
  • 中间件访问层(正在进行中)
    1.典型嵌入式系统访问外设的通用方法。
    2.面向通信接口,包括UART、Ethernet和SPI等。
    3.嵌入式软件能够在任何支持特定通信接口的Cortex微控制器上使用。
  • 设备外设访问层(MCU相关):寄存器名称定义,地址定义,以及访问外设的设备驱动代码。
  • 外设的访问函数(MCU相关):可选的外设辅助函数。

这些层的作用在下图中做了总结:
在这里插入图片描述

使用方法

CMSIS被集成在微控制器供应商提供的设备驱动包中,如果使用设备驱动库进行软件开发,那么就已经在使用CMSIS了。

对于C程序代码,通常只需要包含微控制器供应商提供的设备驱动库里的头文件。这个头文件又包含了其他所有需要的文件,包括CMSIS特性和外设驱动等。

下图是包含了一个使用CMSIS包建立的简单工程,有些文件的名字由实际的微控制器设备决定(在图中标识为< device >)。

在这里插入图片描述
下图是一个使用CMSIS的简单例子:
在这里插入图片描述

优势

  • 不同的Cortex-M微控制器之间的程序移植变得容易。

  • 提高了兼容性,这是因为由于CMSIS文件的使用,中间件和嵌入式操作系统就会基于相同的内核外设寄存器定义以及内核访问函数。
    这同时也减小了代码冲突的概率,因为不同软件组件都分别使用自己的内核访问函数和寄存器定义时,就可能会发生冲突。没有CMSIS,可能会发现不同的第三方软件组件都包含了自己特有的驱动函数,这就可能会带来诸多问题,包括寄存器命名冲突、多个函数拥有类似命名引起的混乱以及重复函数带来的空间浪费,如下:
    在这里插入图片描述

  • CMSIS内核访问函数占用的存储器空间很小,并且经过测试,这有助于减少软件测试的时间。

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

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

相关文章

综合项目 旅游网 【4.旅游线路名称查询-参数传递】

目录 查询参数的传递 route_list.html4.0代码 header.html2.0代码 修改后台代码 RouteServlet之前 RouteDaoImpl1.0 改进后的RouteDaoImpl2.0 改进后的RouteServlet2.0 ​编辑修改前台代码 route_list.html RouteServlet3.0 旅游线路的详情展示 分析 整体过程 代码实现…

【遇见青山】项目难点:缓存穿透的解决方案

【遇见青山】项目难点&#xff1a;缓存穿透的解决方案1.缓存穿透现象缓存空对象布隆过滤其他方案2.解决方案&#xff0c;缓存空数据1.缓存穿透现象 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据…

常见的内存操作函数

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;C语言航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&a…

Java的异常处理

异常 异常就是程序非正常运行时的报错&#xff0c;不正常就是异常。 异常分类 通常分为两类&#xff1a; Error&#xff1a;错误。通常是Java虚拟机无法解决的严重问题。如&#xff1a;JVM系统内部错误、资源耗尽等严重情况。比如&#xff1a;StackOverflowError和OOM-->…

canvas根据坐标点位画图形-canvas拖拽编辑单个图形形状

首先在选中图形的时候需要用鼠标右击来弹出选择框&#xff0c;实现第一个编辑节点功能 在components文件夹下新建右键菜单 RightMenu文件&#xff1a; <template><div v-show"show" class"right-menu" :style"top:this.ypx;left:this.xpx…

PCB设计中的数据单位,层作用,工艺要求,制作过程等简介

PCB中常识 物理结构常识 几乎每层板子都是由两个金属层夹着一个绝缘层&#xff0c;像一个三明治结构。多层板是这种双层板叠加压合的。 常见的层的作用 参考&#xff1a;https://www.21ic.com/article/854059.html PCB电路板一般而言会分成六层&#xff0c;具体为&#x…

第二十四章 java并发常见知识内容(AQS)

JAVA重要知识点AQS介绍AQS的核心思想AQS资源共享方式自定义同步器常见同步工具类Semaphore(信号量)CountDownLatch(倒计时器)CyclicBarrier(循环栅栏)AQS 介绍 AQS 的全称为 AbstractQueuedSynchronizer &#xff0c;翻译过来的意思就是抽象队列同步器。这个类在 java.util.c…

图解 git 常用命令

本文图解 Git 中的最常用命令&#xff0c;如果你稍微理解 Git 的工作原理&#xff0c;这篇文章能够让你理解的更透彻。 基本用法 上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。 git add files 把当前文件放入暂存区域。 git commit 给暂存区域生成快照…

java集合:Collection:Set+List+Dueue

目录 Collection集合 1.常用方法 2.使用Iterator接口遍历集合元素 3.使用foreach循环遍历集合元素 4.Set集合 4.1 HashSet类 4.2 LinkedHashSet类 4.3 TreeSet类 4.4 EnumSet类 5. List接口 5.1 ListIteractor接口 5.2 Stack类 5.3 Arrays.ArrayList 5.4 Linke…

ChatGPT体验失败的经历

ChatGPT的介绍 最近有一个很热门的话题&#xff0c;而且这个话题内容已经覆盖了多个领域。ChatGPT这个词&#xff0c;最近不断的出现在微博的热搜或者公众号的文章里。那我们先大概了解一下ChatGPT。 ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序&#xff0c;于2022年11…

在Allegro设计界面中如何修改封装焊盘

在Allegro PCB设计界面中修改封装焊盘的方法1、选择菜单Tools→Padstack→Modify Design Padstack...2、然后点击封装上要修改的焊盘&#xff0c;右击选择Edit或者点击Options选项卡下要修改的焊盘&#xff0c;然后点击Edit修改3、修改完焊盘后&#xff0c;选择File→Update to…

PyTorch学习笔记:nn.PReLU——PReLU激活函数

PyTorch学习笔记&#xff1a;nn.PReLU——PReLU激活函数 torch.nn.PReLU(num_parameters1, init0.25, deviceNone, dtypeNone)功能&#xff1a;逐元素对数据应用如下函数公式进行激活 PReLU(x)max⁡(0,x)a∗min⁡(0,x)\text{PReLU}(x)\max(0,x)a*\min(0,x) PReLU(x)max(0,x)a∗…

JS document.write()换行

换行效果&#xff1a; 通过传递多个参数&#xff0c;即可实现换行效果&#xff1a; document.write("<br>",ar) 效果&#xff1a; 示例源码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

Vue3 中 导航守卫 的使用

目录前言&#xff1a;一、什么是导航守卫&#xff1f;二、导航守卫有哪几种&#xff1f;1、全局守卫&#xff08;3个&#xff09;全局前置守卫全局解析守卫全局后置钩子2、路由独享守卫&#xff08;1个&#xff09;3、组件内守卫&#xff08;3个&#xff09;beforeRouteEnter(t…

大数据Kylin(二):Kylin安装使用

文章目录 Kylin安装使用 一、Kylin安装要求 二、Kylin安装 1、Kylin安装前环境准备

SpringCloud-Netflix学习笔记12——Hystrix-Dashboard实现服务监控

一、服务监控 hystrixDashboard 除了隔离依赖服务的调用以外&#xff0c;Hystrix还提供了准实时的调用监控&#xff08;Hystrix Dashboard&#xff09;&#xff0c;Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息&#xff0c;并以统计报表和图形的形式展示给用户&…

MikTex+Texmaker环境LaTeX使用bib文件引用参考文献步骤

一、MikTexTexmaker环境 MikTexTexmaker环境是一个LaTeX编辑与编译&#xff0c;以及PDF预览环境。如果还没装好的话&#xff0c;推荐浏览【MiKTeXTexmaker安装】这篇博客去安装此环境。 二、准备bib文件 文件名命名为ref.bib&#xff0c;添加如下内容(作为demo) article{kaelb…

微信小程序nodejs+java+python美食制作教程系统

食谱大全所要实现的功能分析,对于现在网络方便,食谱大全要实现管理员、用户可以直接在平台上进行查看自己所需数据信息,这样既能节省管理的时间,不用再像传统的方式,如果用户想要进行交流信息,必须双方见面进行沟通交流所需的信息,由于很多用户时间的原因,没有办法进行见面沟通…

MySQL_InnoDB引擎

InnoDB引擎 逻辑存储结构 表空间&#xff08;ibd文件&#xff09;&#xff0c;一个mysql实例可以对应多个表空间&#xff0c;用于存储记录、索引等数据。 段&#xff0c;分为数据段&#xff08;Leaf node segment&#xff09;、索引段(Non-leaf node segment)、回滚段(Rollba…

【LeetCode】每日一题(1)

目录 题目&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 写在最后&#xff1a; 题目&#xff1a; 这是他给出的接口&#xff1a; class Solution { public:int fillCups(vector<int>& amount) {} }; 作为一个数学学渣&#xff0c;我想不出厉害的数学算法…