嵌入式驱动开发基础知识抄录—小白(我自己)版

总线

CPU有很多寄存器,其输入输出端往往都需要连接在一组传输线上,由于寄存器是由触发器组成,而触发器只有状态0和1,故一般每条信号传输线只能传递一个触发器信息。如果一条传输线技能与一个触发器接通断开,又能与另一个接通,那么一条信息传输线就可以分时传送多个触发器的信息,同理一组传输线就能传输多个寄存器中的信息。这样的一组传输线被称为“总线”。
总线一般按连接部件的不同分为三类:片内总线、系统总线和通信总线。
片内总线: 指芯片内部的总线,CPU芯片内部、寄存器与寄存器之间、寄存器与运算逻辑单元ALU之间。
系统总线: 指CPU、主存、I/O设备各大部件之间的信息传输线。这些部件通常都安放在主板或各个插件板(插卡)上,故又称板级总线或板间总线。从物理上看就是许多导线直接印制在电路板上,延伸到各个部件。按传输信息的不同可分为:数据总线、地址总线和控制总线。
通信总线: 用于计算机系统之间,或计算机系统与其它系统之间的通信,按传输方式分为:串行通信和并行通信。
总线结构:单总线结构和多总线结构。
单总线结构: 将CPU、主存、I/O设备都挂在一组总线上允许之间直接交换信息。
多总线结构: 将速度或类型不同的设备分开形成多条总线结构(比如主存总线和I/0总线)(主存总线、I/0总线和DMA总线)。

工程移植注意点

1. 移植的是协议,需注意协议栈的配置文件configurations,如freertos的FreeRTOSConfig文件
2. 移植的是工程软件,需注意,每个软件代码软本所在的工程可能同属于一种类型芯片的不同型号下,如TC397,TC375,同时每个工程底层开发工程师可能针对不同上层应用要求进行不同的底层配置,如英飞凌的ILLD库中Configurations文件夹下就有Ifx_Cfg_Ssw(芯片启动属性:电源自检,内存自检,PLL属性,SMU处理等),Ifx_Cfg_SswBmhd(启动bootrom配置),Ifx_Cfg(芯片工作配置:PLL频率SCU频率,软件中断开启宏,TRAP属性配置:其中TRAP6对应arm中pendsv可用来做系统内核切换功能)文件用来进行分别相关功能的配置
3. 当出现从同一种类型不同规格芯片的工程迁移一样的协议栈代码不能跑时,优先考虑底层工程的配置文件没有对齐。(比如从TC375迁移协议FreeRtos代码至另一个TC397工程中时发现一样的协议栈代码,TC375工程可以运行,然而TC397工程却会卡死在软件定时器初始化创建过程中,调试发现由于portYIELD_WITHIN_API无法切换出去,继续对比cortex发现由于对应pendsv的异常无法在此工程上实现,继续排查发现对于TRAP_SYSCALL即TRAP6内核切换未注册声明导致,此声明在TC375工程中是在Ifx_Cfg中进行定义的)

内核架构相关定义

1、栈区(stack): 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
2、堆区(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
3、全局区(静态区):(static)全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
4、文字常量区: 常量字符串就是放在这里的。
5、程序代码区: 存放函数体的二进制代码。
6、堆栈指针寄存器: 堆栈是内存的一部分,而栈指针寄存器SP用于指向当前堆栈的顶部。 当数据被推入堆栈时,SP寄存器的值会相应减少,指向新的堆栈顶部;当数据从堆栈弹出时,SP寄存器的值会增加,指向新的堆栈顶部。 在函数调用过程中,寄存器(如SP)和堆栈紧密协作,以确保函数的参数、局部变量和返回地址得到正确的管理。(以英飞凌为例)TriCore内核是有独立的中断栈寄存器ISP 当进入中断且IS位为0的时候,硬件会先将栈寄存器置为ISP的值,以使用中断的特有栈(当然,在此之前硬件会自动保存SP指针,中断返回后会自动加载回来,不用担心被覆盖),并将IS位置1 。
7、PC 代表程序计数器: ARM流水线使用三个阶段,因此指令分为三个阶段执行:
1.取指(从存储器装载一条指令);2.译码(识别将要被执行的指令);3.执行(处理 指令并将结果写回寄存器)。
R15(PC)总是指向“正在取指”的指令;ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(假设在ARM状态 下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。当突然发生中断的时候,保存的是PC的地址。如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq #4。
8、返回地址寄存器: 主要用于存储子程序调用的返回地址,具有多种用途,但其最主要的用途可以归纳为以下两种:
1、当一个函数调用(使用 BL 或 BLX 指令)时,处理器自动将当前指令的地址(即函数返回的地址)保存在 LR 寄存器中。这个返回地址是函数执行完毕后,需要跳回的地方。
2、当函数执行完毕并准备返回时,程序通过 MOV PC, LR 或 BX LR 指令,将 LR 寄存器的值(即返回地址)加载到 PC(Program Counter) 中,从而跳转回到调用函数的地方。
9、调用深度寄存器: TriCore内核是有调用深度检查的,每次调用计数器加1,最大6位计数器,也就是最多支持64层调用(每个Task或者中断具有独立的上下文,因此独立计数),当超过调用上限,会产生异常;将调用深度计数使能位置0,可暂时关闭调用计数,但是在下次Call指令执行时会自动再次打开。
10、系统控制寄存器: 以英飞凌为例SYSCON的主要功能是对所属核进行控制(该寄存器有外设32位地址,可进行跨核访问,比如主核通过控制从核的BHALT位设置启动)

上下文切换方法 (来源:https://zhuanlan.zhihu.com/p/683873069)

定义: 众所周知,计算机程序在编写过程中,需要使用模块化、封装、分层、抽象等设计理念,这就使得程序在运行中需要不断地在多个子程序中不断地调用、返回,形成一个程序执行树。在不同架构芯片进行操作系统移植时,除了基本硬件定时器等配置外,首要的就是将port文件中上下文切换函数与待移植芯片适配。
1、对于单任务系统来说, 在程序调用子程序之前,需要把当前的寄存器、系统状态等信息进行保存,并在子程序返回时,将这些信息加载回来。
2、对于多任务系统, 每个任务都有自己的上下文,在任务切换过程中需要将一个进程的执行环境切换到另一个进程的执行环境,这是多任务处理的基本机制。
3、另外在发生中断或异常时, 当前程序的运行环境和寄存器信息需要进行保存,称为保护现场。

void FuncA();
void FuncB();
void FuncC();
void FuncA()
{
   FuncB();}
void FuncB()
{
   FuncC();}
void FuncC()
{
   ...} 

保存内容: 上述代码为简单函数调用,当程序执行到FuncB,即将调用FuncC时,因为是FuncA调用FuncB,所以当前返回地址为FuncA中调用FuncB函数对应的CALL指令地址,并且稍后调用FuncC后,返回地址寄存器会被覆盖为FuncB中调用FuncC函数对应的CALL指令地址,因此在调用执行FuncC之前,程序需要先保存 返回地址寄存器 (一般存在栈中)。
另外此时通用寄存器用于FuncB中的一些数据计算,其中的数据在调用完FuncC之后还需要继续使用,而FuncC在执行过程中还需要使用这些寄存器,因此需先把 通用寄存器中的值 保存下来。此外,FuncC中可能还会声明局部变量,因此它会移动栈指针,这就需要把栈指针寄存器的值 也保存下来,FuncC执行完之后,释放占用的栈空吉间。
ARM: 常见的嵌入式内核比如ARM中,上下文的内容都是保存在栈中的,当程序进行调用时,将通用寄存器和链接寄存器等压入栈中,等到调用返回时,再从栈中弹出,形成一个上下文保存机制。
Tricore(英飞凌): 在TriCore内核的上下文切换机制中,上下文是保存在称为CSA的一片区域中的,虽然和栈一样都在RAM中,但是得益于和栈的区分式管理,以及CSA的硬件自动切换机制,能够有效地提高内存使用效率和实时性。

数据/指令屏障(ARM:DMB/DSB/ISB Tricore:__dsync/__isync )

内存屏障是一个通用术语,用于指代一条或多条指令,它们强制处理器在执行加载(load)或存储(store)指令时进行同步事件
一、数据内存屏障: 主要用于多核处理器系统中,不同的处理器可能同时执行数据内存传输指令。确保在DMB之前的所有显式数据内存传输指令都已经在内存中读取或写入完成,同时确保任何后续的数据内存传输指令都将在DMB执行之后开始执行,否则有些数据传输指令可能会提前执行。

二、数据同步屏障: 在计算机的体系结构中,处理器在执行指令时通常会利用指令流水线来提高性能。但也会产生一些问题,比如在多线程编程中,两个线程同时对共享的内存进行读写操作,由于读/写操作的重排序,就会导致数据的不一致。当执行DSB指令时,它确保在DSB之前的所有显式数据内存传输指令都已经在内存中读取或写入完成,同时确保任何后续的指令都将在DSB执行之后开始执行。

三、指令同步屏障: 指令的流水线允许处理器同时执行多条指令的不同阶段,然而这样并行执行可能会导致一些问题,特别是涉及到上下文切换的情况,如实时操作系统的任务切换。当上下文切换时,可能指令流水线中的指令还在执行,而此时上下文已经改变,导致指令执行的结果不正确。通过插入ISB指令,处理器会将流水线中的指令全部刷新,从而确保之前的指令不会影响后续指令的执行,并且后续指令将从正确的上下文开始重新获取。

链接文件在代码编译中的作用

编译过程
GCC编译过程为例:
1. 预处理(Preprocessing): 预处理器把.c文件生成.i文件,它会提前处理由"#"开头的预处理器指令,如#define,#include等。命令如下:

gcc -E *.c -o *.i

2. 编译(Compilation): 编译器将.i文件生成.s文件,它将程序转换为特定平台的汇编语言,命令如下:

gcc -S *.i -o *.s

3. 汇编(Assemble): 汇编过程将上一步的汇编代码转换成机器码,这一步产生的文件叫做目标文件,是二进制格式。编译的命令如下:

gcc -c *.s -o *.o

4. 链接(Linking): 链接器将所有目标文件与其他库文件、启动文件等链接起来生成可执行文件。命令格式如下:

gcc *.o -o *

在生成可执行文件之前,编译器根据链接文件中定义好的地址段,将该段包含的所有代码,变量信息链接到芯片的绝对逻辑地址。链接文件中定义的地址段包含字节对齐,运行地址,是否连续,读写属性等。(.hex .elf都是可执行文件,但是hex文件只包含可执行信息,elf文件除了可执行信息,还包含了调试信息)在这里插入图片描述
由左到右为一个简单的链接过程,它把不同文件的里的不同内容按类别重新组合,并放置到对应的存储空间中。

链接文件常见属性与功能(以英飞凌LSL文件为例)

属性(Attributes)
r = readable (readable sections)
w = writeable (writeable sections)
x = execuable (execuable sections)
i = initialized (initialized sections)
b = cleared (sections should be cleared at program startup)
s = scratch (scratch sections :not cleared and not initialized)
p = protected (protected sections)

其他比较有用的lsl关键字
— run_addr = address(运行时地址,address at run-time)
— load_addr = address (再复制到运行地址前,初始地址在ROM中(initial address))
— ordered (以group中单个地址范围内随意布局,但会占用一段连续的memory空间)
— contiguous (在group中某单个地址范围内随意布局,但会占用一段连续的memory空间)
— clustered (连续的排布(contiguous),但是当memory不足的时候会被分割开)
— fill (避免其他section填补 对其间隙(alignment maps))
— overlay (contiguous,将当前section覆盖到当前的run address上)
— copy (为sections 创建一份ROM拷贝,在启动时会将这部分sections从ROM复制到RAM中)
— reserved (保留这些section)

名词解释:
linear:4G,定义了32位地址全部寻址空间
abs24:每个segment前2MB,一般用于PC寻址
abs18:用于访问每个segment前16KB空间,可以通过18位绝对寻址方式进行访问(4位段地址+14位偏移地址),属于近程寻址
csa:core内部上下文存储区域

内存限定符:1.标记该数据为近程还是远程寻址 2.由编译器指定 3.a0/a1/a8/a9为全局地址寄存器,可专门用来寻址其指定基地址的前后32KB数据
__near: 寻址方式:18位绝对地址(4bits段地址+14bits偏移地址) 寻址范围:每个segment前16KB
__far: 寻址方式:基地址+偏移地址 寻址范围:全局
__a0: 寻址方式:A0+offset(符号扩展的16bits偏移地址) 寻址范围:64KB(A0前后32KB)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值