雄安网站建设,网站建站流程图,织梦网站怎样入侵,网站数据接口怎么做目录1.嵌入式系统编程入门微控制器是如何启动的嵌入式程序设计2.输入和输出3.开发流程4.C编程和汇编编程5.什么是程序映像6.C编程#xff1a;数据类型7.用C语言操作外设8.Cortex微控制器软件接口标准#xff08;CMSIS#xff09;简介标准化内容组织结构使用方法优势1.嵌入式…
目录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、系统控制块SCBSysTick的中断控制和初始化。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内核访问函数占用的存储器空间很小并且经过测试这有助于减少软件测试的时间。