你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【新手兴趣向 NO.2 】STM32进阶探究之应用启动(一)之嵌入式...

[复制链接]
酱哒哒 发布时间:2017-2-22 22:49
本帖最后由 酱哒哒 于 2017-2-25 00:05 编辑

声明:以下内容乃本人自我理解及部分学习资料综合而得,可能存在错误!敬请谅解,欢迎订正!
BY Kismet


1.序言

      首先,看了我写的这些东西,很可能对于各位嵌入式方面的项目开发,并没有太大的实质性作用。
但,我还是想要写出来,给新手大大们(包括自己这个菜鸟),看一看。
      因为,我个人觉得,这些东西对于理解嵌入式开发,有着至关重要的作用。虽然,这些东西,可能对于你的项目开发,例如我要做一个CAN通信、USB通信等等,用处不是很大。但是,在我看来,项目开发实施,主要就是在讲 how to do,我想要告诉新手大大(包括自己这个菜鸟)why to do。
      希望各位记住一点:软件不是魔法,程序开发是脱离不了物理介质的。任何程序运行,必然有对应的物理过程。如果你一直觉得,程序很神奇,很魔幻,那你完了。
      就如同,上一章我简单提到的各种变量的存储占用,其实就是想要说一个事实:程序脱离不了物理介质!

好了,又到了喜闻乐见的举例子时间:
利用for循环清零一个a[1024][1024]二维数组
TU1.JPG
结果:程序A消耗的时间比B消耗的时间短很多!!
分析:数组申请的空间,是沿着物理地址走的,CPU访问的时候,有远有近,程序A是按照顺序访问的,反观程序B,它每次跳着访问,存在走的路程有重复,所以消耗的时间自然就长!!(如果理解不了,你就画一个二维数组,按着程序清零的方式,试一下,我相信你们能理解的,嘿嘿)


2.STM32的startup
       现在基本上大部分的嵌入式开发,都使用的C语言编程,所以启动过程以C语言为例。
       而C语言有一个典型的特征,就是有且只有一个main函数!
       那么,你有没有想过单片机上电后,如何寻找main函数入口呢?
       不同开发者的程序,结构不同,变量函数等都不同,而C语言开发,变量/函数等地址是由编译器自行分配的,所以从硬件上来说main函数入口的地址不是一成不变的。这就导致,微控制器不能从硬件上直接锁定main的入口。
        所以,就需要一个“启动文件”起到中转衔接的作用,负责“复位”到“main函数”这之间的工作。(当然,这个文件并不止起这点作用。)
        这一步,ST已经替我们做了。(无论是MDK还是IAR等编译器,都必定有一个写好的启动文件,一般是汇编的形式。另外,如果你把编译器调试中runto main这个选项去掉,那么单步运行就能看到那个运行过程。)
       用官方一点的语言表述,启动代码(startupcode)的作用就是,在应用进入main函数(callthe main function)之前,初始化整个系统,包括硬件和软件。
       当然,在这儿我不会讲IDE工具中的启动文件的具体内容,这些东西,网上已经有很多讲解了,随便找一个读读,基本上都能理解的。


3.嵌入式应用
      作为嵌入式应用开发人员,自然关注的是嵌入式应用(EmbededApplication)本身的开发,一个嵌入式应用从生到灭,可以简单地分为三个大阶段。(当然,大部分的嵌入式应用都是无限循环,也就不存在灭)

图图.JPG

     本次,主要谈的就是这个初始化阶段(Initializationphase)。
     另外,为啥要用英文?因为可以加强英语学习啊,嘿嘿。
Ⅰ. 初始化阶段   Initializationphase
     初始化阶段就是系统复位到进入main函数之前,初始化阶段又可以简单地分为一下三部分:

      Ø硬件初始化:典型的就是系统启动文件中(XXXstartup.s)那样,当然也可以额外加入一些其他的。初始化一些硬件,例如CPU设置、复位一些硬件等。这部分就是为了软件C语言部分的初始化做准备。   
  Ø软件C/C++的初始化:进入main函数之前,正确初始化每一个全局或者静态链接的C/C++变量。
  Ø应用的初始化:这部分自然就主要是开发者操作了,例如初始化RTOS、中断、外设等。
      对于一个典型的ROM/Flash-based的系统,常量和函数总是放置在ROM中。RAM中所有的symbols在进入main函数之前,都将被初始化!然后,链接器(Linker)会把RAM划分好区域,供给变量、堆、栈使用。\


以典型的IAR集成开发工具为例,初始化过程主要就分为以下四步:
①.应用开始,系统级启动代码(xxxstartup.s)执行硬件初始化,堆栈指针指向堆栈底部(预先设置的)。【这儿重点注意】
②.ZI-data被初始化为0
③.从ROM中将RW-data拷贝到RAM对应区域
④.main函数启动


如下图所示
jump1.JPG
fig1.基于IAR的ROM+RAM初始化流程

注意:
       (1)①中,堆栈指针指向堆栈底部,这个只适用于IAR(前文提到过,IAR与GCC不同,它先分配stack和heap。MDK具体怎么的,我不清楚!)
       (2)ZI-data,在前文中我解释是,未初始化的变量(还包括初始化为0的变量,未初始化,编译器直接给0)
       (3)RW-data为何与ZI-data不同,还要占用Flash空间(ROM空间)?因为ZI-data是直接给0,而RW-data是含有具体数据的,所以编译器不可能无中生有,它不得不从Flash中拷贝到RAM中。并且,这也决定了,ZI-data在RAM中位于RW-data之上(先入)。

Ⅱ. 执行阶段
    嵌入式应用常常都是一个无限循环,通常采用中断或者轮询的方式实现外部交互或者内部事件。利用中断方式的应用,在main函数开始的时候,就该完成中断的初始化。
    假如应用对实时性的要求比较苛刻,并且还要求多任务机制,那么可以考虑引入RTOS。但是这也意味着,你必须在main函数开始的时候,完成各个任务的初始化。
Ⅲ.终止阶段
    大部分嵌入式应用,都没有结束!也就不存在终止的操作,但是如果需要终止,那么就必须准备好一个合适的结束动作。
    要以可控的方式终止程序,要么调用标准C语言函数exit,_Exit,abort,或者直接从main函数中return。如果使用return,exit函数就会执行,那么,所有的文件都会关闭。
    当然,如果系统逻辑存在问题,那么应用也可能终止——也就是跑飞了。


4.总结
一个完整的程序,由生到灭,就如同下图所示。
图图2.JPG

fig2.一个完整的程序(由生到灭)
PDF下载   STM32进阶探究之应用启动(一).pdf (214.66 KB, 下载次数: 20)

评分

参与人数 1 ST金币 +5 收起 理由
zero99 + 5 赞一个!

查看全部评分

收藏 2 评论2 发布时间:2017-2-22 22:49

举报

2个回答
feixiang20 回答时间:2017-6-28 15:10:26
赞的,新手对于启动是重点
子曰好人 回答时间:2017-6-29 12:45:27
分享学习的内容,给楼主点个赞

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版