嵌入式操作系统组成结构(软硬件之间的联系)--硬件如何执行第一行代码?

引言:

最近纠结了两周决定自己以后还是走爱好的嵌入式方向,细分就是操作系统相关,下一步的目标是从0到1编写  RT-Thread的内核,然后转战嵌入式linux软件驱动开发,

正好之前有做FreeRTOS,但都是偏上层的API函数的调用,这种仅会应用的层面给人带来一种不踏实的虚假感,因此为加强自己对整个系统的理解,一周内恶补了七、八本经典的书籍,针对各本书前几章对整个嵌入式操作系统的架构讲解,自己进行了汇总整理。

本文涉及到的知识有  汇编语言 计算机系统结构 操作系统等。


写者叙:

如果在学习讨论的过程中发现本文中提到自己暂时不了解的知识,可以阅后在文中附有的相关资料参考,也欢迎大家评论附上对相关内容解释较好的链接或者自己的理解进行交流~


提出两个问题:

1.C/C++ 程序代码如何被编译成目标文件程序在目标文件中如何存储?

    针对嵌入式操作系统即 C代码如何与硬件进行交流? 利用串口打印printf(“hello world\r\n”) 从开发环境编译加载到板子再到打印 这个过程中,到底发生了什么?(main函数之前发生了什么?)

2.为什么每次仿真开始的时候 PC指向一堆汇编代码?这是什么东西?

 

综上主要是分为两个问题:

第一个是程序编译相关问题,不是本文重点,详见(具体的编译、链接、装载的知识可以参考 《程序员的自我修养》俞甲子著),里面有清晰明确的答案

问题二是本文重点,针对C程序如何转化为板子能够运行的语言,并且对板子的启动过程——(main函数之前发生了什么?)进行理解总结


目录

引言:

写者叙:

提出两个问题:

一、硬件能够执行的指令——机器语言

二、启动文件(开发板启动流程)(重要)

2.1启动文件

2.2启动流程

1)创建异常向量表

2)初始化基本硬件(CPU、主存等)

3)初始化堆栈

4)加载应用程序运行环境

5)跳转到主程序

三、总结



一、硬件能够执行的指令——机器语言

机器语言是机器指令的集合。它是一列二进制数字,计算机将之转化为一列高低电平,使电子器件电路收到驱动,进行运算。

需要注意的是每一种微处理器,由于硬件设计和内部结构的不同,就需要用不同的机器指令(电平脉冲序列)来控制。所以每一种微处理器都有自己的机器指令集。

至于机器码如何执行以及它的含义我们暂时不需要理解,只需要知道编译环境会将我们写的C程序转化为我们选择的CPU所对应的指令集即可。(C程序如何转换为对应的汇编指令,以及CPU的结构及如何执行汇编指令,请参考清华王爽《汇编语言(第三版)》)

因此你在使用keil新建工程的时候,必定在某个地方选择了特定的CPU型号,(新建工程后的弹框F103选择Cotex-M3,F4选择Cotex-M4)

这个操作使编译器可以把你的C程序编译为对应CPU指令集的汇编语言→机器语言,因此你的硬件便能执行了。(具体的编译、链接、装载的知识可以参考 《程序员的自我修养》俞甲子著)

但是现在有一个问题是,CPU已经认识你的程序了,但是从哪里开始执行呢?是从main开始吗?(当然不是)

二、启动文件(开发板启动流程)(重要)

2.1启动文件

新建工程后,紧接着出现的弹框,就是选择启动文件。

启动文件的作用是是什么呢?

根据计算机组成原理的知识,一切指令与程序都只能够在主存上运行。而主存价格较为昂贵,并且开发人员的程序通常比较大,因此,开发人员的程序通常存储在外存中,而外存通常无法运行指令,因此系统上电后,怎样通过一些机制将应用程序从其他存储设备复制到主存上是相当重要的。

如果你CPU连你main函数存放的地址都不知道在哪里?还谈何执行呢?这是启动文件必先在main函数之前执行的一个原因,

此外,不同的系统硬件设备不同,开机后所需要的硬件设备的配置也不同。所以,系统上电后,对各硬件控制器的配置也不同(例如显存、扩展插槽上存储设备的地址等),这些都是需要在启动文件中进行设置的,也就是告诉CPU通过地址总线去哪些地址找东西、写东西。

启动文件的作用可以根据需求的增加而进行扩充,上述只是告诉CPU 启动系统运行的基本硬件的设置,实际上启动代码还可以包括实际开发板上各板级硬件和接口的驱动程序,这时的启动代码其实就具有了能够使应用程序使用开发板各资源的接口功能了,(例如RT-Thread的任务调度、切换就利用汇编代码利用了CPU异常处理的资源)

抽象的理解第一条指令的执行过程:CPU复位上电后会由硬件电路使程序指针指向一个特定的地址,因此将要需要执行的第一条指令code_1(其实并不是main)放入这个地址,CPU便会转入code_1继续顺序执行指令。

2.2启动流程

本节参考《嵌入式实时操作系统的设计与开发》 廖勇,本节只概述启动文件中的初始化流程,对每个操作不进行细节解释,想距离了解的读者见参考书。

以S3C2440A为例芯片为例,此芯片通过硬件机制将NAND Flash(无法作为程序运行载体的一种外部存储器)中内容复制到S3C2440A芯片内部的4KB大小的SRAM,并且将它映射为自身内存的BANK0(不是很理解),将这4KB大小的内容映射到从0x00000000开始的地址(BANK0)上,为什么映射到0x00000000?见下文

(arm处理器bank与存储器的bank详解:

https://blog.csdn.net/dahailantian1/article/details/78584820?ops_request_misc=&request_id=&biz_id=102&utm_term=BANK%E5%9C%B0%E5%9D%80%E6%98%A0%E5%B0%84&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-4-78584820.first_rank_v2_pc_rank_v29_10

                             

1)创建异常向量表

当程序在芯片上运行发生复位异常时,程序指针PC会自动跳转到主存最开始的地址(0x00000000),这里就是异常向量表的起始地址,然后硬件机制会把异常向量表地址中存储的数据(异常服务函数地址)的值赋给指针。(√)

ARM处理器内核一共定义了7种异常:复位异常、未定义指令异常、软中断异常、预取址终止异常、数据终止异常、IRQ中断异常、IRQ快速中断异常。

所有跳转地址都是在CPU芯片生产时就确定且无法更改的(一般),产生异常时硬件跳转到规定的地址,再通过地址内存储的跳转指令跳转到异常处理程序的起始地址。

2)初始化基本硬件(CPU、主存等)

从NAND Flash启动,这里面的启动代码包含对CPU、主存的初始化:

①:关闭看门狗、屏蔽中断、

②:设置时钟与PLL、初始化BANK(由于BANL6,7挂载了内存,揣测:main函数的地址位于BANK6 ,其物理地址为0x30000000

3)初始化堆栈

ARM具有7种不同的模式,由于CPU寄存器是公用的,因此要保存每个模式下面的上下文信息,因此每个模式有其自己的堆栈指针需要初始化

4)加载应用程序运行环境

编译过程中会产生arm文件,这里面有应用程序中用户定义的RO ZI RW等类型的数据,需要加载入内存

5)跳转到主程序

   loop main   //  main.c 中 int main (void) 


三、总结

到此问题二的答案很清晰了, 板子执行main函数之前,上电后会触发复位异常,进行启动文件的环境初始化,进行一系列初始化之后,在最后跳入 main();

因水平有限,还在不断学习的过程中,文中有什么错误,或者解释不好的概念,恳请各位读者附上更好的链接或者批评指正,最后这也是写这么多日志以来第一次系统的总结,如果给你带来一点点启示或者理解,作为激励求一波赞啦~

 

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
嵌入式系统软硬件协同设计实战指南:基于Xilinx Zynq(第2版)陆佳》是一本关于嵌入式系统协同设计的实战指南。书中主要介绍了基于Xilinx Zynq芯片的软硬件协同设计技术和实践方法。 该书首先详细介绍了嵌入式系统的基本概念和发展历程,并深入解析了Zynq芯片的特性和架构,以及用于嵌入式系统设计的Xilinx Vivado开发工具。 接着,书中通过一系列实际案例,从硬件设计和软件开发两个方面,结合Zynq芯片的特性,详细讲解了软硬件协同设计的基本原理和方法。同时,书中还详细介绍了如何使用Vivado工具进行硬件开发,包括FPGA逻辑设计、时序约束、时钟分频等。在软件开发方面,书中详细介绍了如何使用Xilinx SDK进行裸机和Linux应用开发,并介绍了常用的外设驱动编程和Linux设备树的使用方法。 此外,书中还介绍了实时操作系统RTOS)的基本概念和嵌入式系统中的任务调度和通信机制,并详细介绍了使用FreeRTOS进行任务调度和消息传递的方法。 最后,书中还介绍了测试和调试嵌入式系统的方法和技巧,包括使用硬件仿真和调试技术、串口调试和JTAG调试等。 《嵌入式系统软硬件协同设计实战指南:基于Xilinx Zynq(第2版)陆佳》通过详细的实例和指导,帮助读者全面了解嵌入式系统软硬件协同设计的基本原理和方法,掌握使用Xilinx Zynq开发嵌入式系统的技术和工具。对于从事嵌入式系统开发和设计的工程师和学生来说,这是一本非常实用的参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值