ARM 内核版本号
- 架构:如ARMv7,是ARM公司确定的,ARMv7是32位(见到的芯片多是该架构),ARMv8是64位但也支持32位。
- 该架构定义了处理器的基本指令集、体系结构以及支持的技术特性。
ARM SoC版本号
- 内核:如Cortex-A8,是ARM公司确定的
- 分割成了三条产品线,应对市场细分需要,Cortex-A(高性能),Cortex-R(高可靠性),Cortex-M(低功耗、低成本)
芯片型号
- 如 S5PV210,半导体公司确定
单片机开发和嵌入式开发的区别
- 单片机可以视为嵌入式系统的一个子集,是简化版的嵌入式系统,适用于轻量级和成本敏感的应用。
- 但一般单片机开发也被叫嵌入式开发。
- 单片机开发多为裸机,也跑一些RTOS,但程序规模较小,一般使用C语言和少量汇编。
- 外设多使用串口,I2C,ADC,SPI等简单外设。
- 学习路线短,职业平缓。
- 嵌入式一般使用嵌入式操作系统,如liunx和Android,一般使用C、C++、JAVA语言。
- 外设多使用网络、USB、音频解码等复杂外设。
- 学习路线长,职业生涯久。
嵌入式系统构成特点
- 专用、软硬件可裁剪可配置
- 低功耗、高可靠与稳定
- 代码可固化,实时性,弱交互
- 专业开发环境与人员
嵌入式系统组成
- 硬件:微处理器、存储器、I/O接口、输入输出
- 软件:嵌入式操作系统、BSP(板级支持包)、应用软件
嵌入式系统分层
- 硬件层(Hardware Layer):这是系统的物理基础,包括处理器、存储器、输入/输出接口等硬件组件。硬件层定义了系统的物理特性和限制。
- 板级支持包(Board Support Package, BSP)层:这一层可以视作硬件层与软件层之间的一个过渡层,负责初始化硬件、配置外设、提供硬件抽象,确保操作系统能正确识别和控制硬件。有时也被归并在驱动层讨论。
- 驱动层(Driver Layer):驱动程序直接控制硬件设备,为操作系统提供访问硬件的接口。这层包括各种设备驱动,如传感器、显示屏、网络接口等的驱动。
- 操作系统内核层(Kernel Layer):操作系统的核心部分,负责管理和调度硬件资源,如内存管理、进程管理、中断处理、线程调度等。它是硬件和应用程序之间的桥梁。
- 中间件层(Middleware Layer):这一层可选但重要,它提供了一系列服务和库,如网络协议栈、图形用户界面(GUI)库、数据库管理系统等,帮助应用程序开发者更高效地开发复杂功能。
- 应用层(Application Layer):顶层,包含用户直接交互的应用程序和服务。这一层实现了系统的最终功能,如数据采集、控制逻辑、用户界面等。
- 在某些描述中,BSP可能被整合到硬件层或驱动层中,而中间件层可能被视为操作系统层的一部分或单独作为一个层次。
嵌入式开发模式
- 非嵌入式开发:A类机器编写与编译得到可执行程序,发布给A类机器运行。电脑->电脑
- 嵌入式开发(交叉编译):A类机器编写与编译得到可执行程序,发布给B类机器运行。电脑->嵌入式
- B类处理器架构和资源限制(如存储空间小、处理能力有限)不适合直接在其上进行编译操作。
- 需要有一套针对目标平台的编译工具链(Cross Compiler),这套工具链能够生成对应于目标平台的机器代码。
- 工具链中包含了编译器、汇编器、链接器以及针对目标平台的库文件等,确保生成的代码能够在目标平台上正确执行。
- 无法使用纯软件进行调试,需要借助专用调试器
总线
-
CPU通过地址总线寻址,数据总线与外部设备交换信息。
-
总线速度决定CPU与外部设备交换信息的速度。
-
数据总线
- 数据总线位数决定CPU单词通信交换的信息数量,32位一般指的就是数据总线位数
- 实际运行中,32位单片机,8位16位32位数据效率相同,当数据不满32位会进行填充,但使用低字节会节省空间。
-
地址总线
- 地址总线位数决定CPU寻址范围,如32位最多支持4G内存
程序编译过程
- C语言通过编译器变为汇编语言,汇编语言通过汇编器变为elf二进制可执行程序,通过Objcopy工具转换为bin格式烧录文件
- CPU执行程序的过程:
- 程序计数器(PC)初始化:当单片机上电或复位时,程序计数器(Program Counter)会被初始化为某个特定的地址,这个地址通常是单片机固件中的起始位置,即程序存储区的首地址。
- 指令读取:CPU根据程序计数器(PC)中存放的地址,从程序存储器(通常是非易失性存储器如FLASH)中读取一条指令。在大多数单片机中,这是通过内部的地址总线和数据总线来实现的。
- 指令解码:读取的指令被送入指令寄存器,CPU对这条指令进行解码,以确定其操作码和操作数,从而理解该指令要执行的操作。
- 执行指令:根据指令解码的结果,CPU会执行相应的操作。这可能涉及到算术逻辑运算、数据传输、控制流改变(如跳转、调用子程序)等。在执行过程中,CPU可能会访问内部或外部的数据存储器(RAM)来读取或写入数据。
- 程序计数器更新:执行完当前指令后,程序计数器(PC)通常会自动递增,指向下一个指令的地址,准备读取并执行下一条指令。如果当前指令是跳转或分支指令,则PC会被更新为跳转目标的地址。
- 循环执行:上述过程不断重复,CPU依次读取、解码并执行程序中的每一条指令,直到遇到停止指令(如HALT)或者受到外部中断影响而暂停当前任务去处理中断服务程序。
指令集
- CISC指令集:复杂指令集,理念是用最少的指令完成任务。
- RISC指令集:精简指令集,通过简单的指令,组合成复杂指令。
IO与内存、外存
-
IO是输入输出接口,是CPU与其他外设通信的道路
- CPU访问外设类似于访问内存的方式,将外设寄存器当作内存地址读写,称为IO与内存统一编址方式
- 使用专用CPU的指令访问某种特定外设,称为IO与内存独立编址方式
-
内存是程序运行的场所,内存和CPU通过总线连接,通过地址访问具体内存单元。一般是RAM(DRAM SRAM等)
- SRAM是静态内存,单片机的RAM多为这种。容量小、价格高、但上电就能用
- DRAM是动态内存,容量大、价格低、但需要软件初始化后才能使用
-
外存是程序存储的场所,一般是ROM。常用外存由norflash、Nandflash、SD卡、硬盘等。一般是通过芯片的外存接口连接,不占用总线地址。但norflash例外。
架构
- 冯诺依曼结构:程序和数据都放在内存里,并不分离,如Intel的CPU
- 哈佛结构:程序和数据分开独立放在不同块,完全分离的结构,如大部分的单片机
- 结构分开,程序是只读的,避免程序错误导致程序损害
- 裸机程序链接麻烦,需要使用链接脚本告诉链接 器如何组织程序
- 程序部分:单片机存储在片内FLASH中,通过程序计数器的地址,CPU读取指令,并由译码器解析
- 数据部分:存储在RAM中
寄存器
-
通用寄存器:cpu组成部分,很多活动需要通用寄存器支持
-
特殊功能寄存器(SFR):不在CPU中,存在外设中,通过访问SFR控制外设
-
寄存器属于CPU外设的硬件组成部分,是硬件
-
可以像访问内存一样访问寄存器
-
由CPU硬件设计者制定(规定该寄存器是只读只写还是状态…),留作外设被编程控制的“活动开关”,设计者事先预留的能通过编程控制硬件的后台开关
-
寄存器是外设硬件的软件编程接口API,用软件编程控制某个硬件,其实就是读写该硬件的寄存器
-
Nandflash和Norflash的特点
- Norflash不需初始化可以总线直接访问,片内flash一般就是Norflash,一般用于启动。容量小价格高
- Nandflash不能总线访问,需要软件初始化后通过接口才能使用。容量大价格低
ARM的7种工作模式
-
工作模式
-
普通模式
- 用户模式(User):非特权模式,应用程序通常在此模式下运行,不能访问所有系统资源。
-
特权模式
-
快速中断模式(FIQ):用于需要快速响应的中断处理,、高优先级中断产生进入,拥有自己的寄存器组以加速处理过程。
-
中断模式(IRQ):用于一般的中断处理,低优先级中断产生进入。
-
管理模式(Supervisor,又称SVC):特权模式,复位或软中断指令执行时进入模式。
-
中止模式(Abort):当数据或指令预取发生错误(如访问权限违规或未对齐的访问)时进入此模式,用于处理存储器访问异常。
-
未定义指令模式(Undefined):尝试执行未定义指令时进入此模式,可以用于软件仿真硬件协处理器的指令。
-
系统模式(System,又称SYS):特权模式,与用户模式使用相同的寄存器集,但具有所有特权访问权限,通常用于运行具有特权级别的代码,如操作系统的某些部分或信任的系统服务,而不需要切换到SVC模式。
-
-
-
CPU只能存在一种模式,模式切换可以是代码主动切换(CPSR寄存器),也可以是CPU某些情况下自动切换
-
操作系统有安全级别要求,因此CPU设计多种模式是为了方便操作系统的多种角色安全等级需要
异常
- 异常会打断正在执行的工作,处理完成异常会重新恢复执行
- 中断是异常的一种
指令和伪指令
- 汇编指令:机器指令的助记符,编译后得到一串10组成的机器码,由CPU读取执行
- 汇编伪指令:本质上不是指令,但和指令一起写在代码中,为编译器提供指导编译过程,伪指令不生成机器码
协处理器
- Soc内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务
- ARM设计上支持多达16个协处理器,但一般SOC只实现CP15
- 协处理器一般与MMU、Cache、TLB等处理有关
- STM32通常不包含,但个别型号包含FPU
栈
- 空栈和满栈指的并不是空间存储的满不满,而是根据SP指针指向的位置,栈可以分为满栈和空栈
- 空栈:SP指针指向空的位置,每次是先存后移动,取出是先移动后取出。
- 满栈:SP指针指向最后一个数据的位置,每次是先移动后存,取出是可直接取出后再移动
- 升栈:随着数据的入栈,SP指针从低地址向高地址移动,称为升栈;
- 降栈:随着数据的入栈,SP指针从高地址向低地址移动,称为降栈;
Makefile
- 功能:用于管理工程。例如项目中有多个c和h文件,直接命令行编译每次输入是gcc a.c b.c d.c -o exe 很麻烦
- 使用:
- touch Makefile,创建文件
- 编写Makefile有三个部分:
- 目标(Target):想要生成的文件或执行的任务。顶格写,后面是:
- 依赖(Dependencies):生成目标所需要的文件或条件。
- 命令(Commands):生成目标要做的动作。命令前面一定是Tab,不能顶格,也不能是空格
- 使用:直接在当前路径输入make "目标"即可
GPIO
- 可以理解为就是芯片的引脚
- 可以被编程控制工作模式和输入输出
看门狗
- 现实中因为一些外部因素,电子设备经常会跑飞或者死机,希望设备能够自动复位
- 看门狗其实是SOC内部的一种 定时器,定好时间后,在时间到达之前需要重新置位,否则系统会被复位
C语言和栈
- C语言中的局部变量都是用栈实现,启动文件中的汇编会设置好合理合法的栈地址,没有合法的栈,局部变量 就会落空,程序死掉
volatile
- 让程序在编译时,编译器不对程序进行优化 。如果一个变量易变,不希望编译器优化,在定义时加volatile
cache
- Cache(是一种高速缓存存储器,位于CPU与RAM之间。目的是为了缓解CPU与RAM之间的速度不匹配问题。
- 当CPU需要数据时,它首先会检查Cache中是否有该数据的副本。如果存在(这种情况被称为“命中”),命中率是重要的指标
- 通常使用静态随机存取存储器(SRAM)技术构建
位置无关码和位置有关码
- 位置无关编码(PIC),在编译或汇编时生成的代码,它不依赖于特定的内存地址来执行。
- 位置有关编码,在编译或链接时被设定为预期在特定内存地址执行
链接地址和运行地址
-
链接地址:
- 链接地址是在编译和链接过程中为代码和数据分配的逻辑地址。它是程序链接时的位置参照点,由程序员或链接脚本设定。
- 对于位置无关的代码,链接地址可以视为一个相对参考点,因为实际执行时代码可以加载到内存的任意位置。
- 对于位置相关的代码,链接地址就是期望程序在最终执行时所在的物理地址或虚拟地址。
-
运行地址:
-
运行地址指的是程序在内存中实际执行时的地址,也就是程序加载到RAM后的起始地址。
-
在嵌入式系统中,如果程序直接在Flash(如NOR Flash)中执行,则运行地址和加载地址可能相同。
-
如果程序先加载到RAM中再执行,那么加载地址将是Flash或其他非易失性存储器中的地址,而运行地址则是RAM中的地址。
-
通过重定位机制,程序可以在加载时或启动时从链接地址调整到运行地址,特别是对于位置有关的代码来说,这是必要的步骤。
-
程序段
- 编译器内部定好
- 代码段:(.text),存放程序指令的部分,code和RO变量
- 数据段:(.data),存放显式初始化非0的全局变量,RW变量
- bss段:(.bss),又叫ZI段,零初始化段,对应初始化为0的全局变量,ZI变量
- 程序员自己指定
- 段名自己制定,属性和特征也是自己定义
- 在keil的map文件中,RO size为code+RO DATA,RW size(RAM占用空间)为RW DATA+ZI DATA,ROM size(ROM占用空间)为code+RO DATA+RW DATA
- 全局变量未显式初始化为0,本质是放到bss段,保证为0。局部变量是从栈中申请,栈反复使用导致值不确定。
- 全局变量显式初始化变量,在(.data)段,在执行main之前就被初始化,SCT文件中的*(InRoot$$Sections)
SOC时钟系统
- 最常见的配置,使用外部晶体振荡器(如石英晶体或陶瓷谐振器)产生的稳定频率作为参考,再通过内部电路PLL倍频后再分频所需的时钟信号。
- 为SoC内部的各种组件提供精确的时间基准,确保所有模块能够同步工作。
- 为了功耗,时钟系统可以对不活动的模块暂时关闭其时钟信号供应,直到需要时再恢复。关闭外设,一般是关闭其时钟信号。
通信
- 最重要的是信息表达方式,解析方法,信息的传输方法。通信双方的表达和解析方法需要一致,否则无法有效传递。
- 信号的传输时指经过编码后的信息再传输介质上传输的过程
- 同步和异步:同步通信要求发送端和接收端的时钟频率保持一致,以确保数据的正确接收。通信开始时,通常会发送同步字符来建立双方的时钟同步。异步通信不需要发送端和接收端的时钟完全同步。数据包或字符间可以有不固定的延迟,每个数据单元(如字符)传输前后有起始位和停止位来界定边界。
- 串行和并行:并行接口允许同时通过多条线路传输多个数据位;串行接口则是逐位顺序传输数据。
- 差分和电平:电平信号(也称单端信号)是指信号的表示依赖于信号线与一个固定参考电平(通常是地线GND)之间的电压差。差分信号是一种相对信号传输方式,它不依赖于固定的参考电位,而是通过两根信号线(称为差分对)之间的电压差来表示数据。
- 波特率是衡量单位时间内串行通信中信号状态变化次数的指标,直接影响数据传输速度,需通信双方匹配设置以确保数据正确传输。波特率9600指1s能传输9600个二进制位
- 单、半全双工通信:
- 单工通信是指数据只能在一个方向上传输,不能同时进行双向通信。
- 半双工通信是一种允许数据在两个方向上传输的通信方式,但与全双工通信不同的是,它不能同时进行双向传输。半双工就像是一个狭窄的道路,车辆可以双向行驶,但任何时候都只允许一方前进,另一方必须等待。
- 全双工通信则允许数据同时在两个方向上传输,即通信双方可以同时发送和接收信息,互不影响,就像两个人可以同时讲话和聆听对方,没有等待的时间。
- DB9接口:是一种常见的物理连接器,广泛应用于串行通信领域
- UART定义(电平信号),公头是2-RX,3-TX,5-GND,对应的母座就是2-TX,3-RX,5-GND
- RS485(差分信号),接口定义为,1-DATA-, 2-DATA+, 5-GND
- CAN接口(差分信号)的定义:信号引脚在2与7,7脚为CAN_H,2脚为CAN_L
FIFO
- 先进先出,fifo是一种数据结构。对于通信接受或者发送的fifo,其实是一个大缓冲区,这个缓冲区的工作方式类似于FIFO,先进先出。
- 数据管理:FIFO作为一种队列结构,保证了报文的接收顺序,即最先到达的报文会排在队列前面,等待处理器最先处理,随后到达的报文依序排队。
- 流量控制:由于CAN总线上的数据传输速率可能与微控制器(MCU)处理这些数据的速度不匹配,FIFO可以作为一个缓冲区,帮助平衡这种速率差异,避免数据丢失。
- 减少CPU负载:通过使用FIFO,微控制器不需要不断轮询总线状态,而是可以在FIFO中有数据可读时通过中断方式通知CPU,这样可以更加高效地利用CPU资源。
- 多报文处理:一些CAN控制器具备双FIFO(如FIFO0和FIFO1),可以配置为接收不同优先级或类型的报文,这样处理器可以根据报文的重要程度或处理逻辑分别处理,增强了系统的灵活性和响应速度。
- 简化软件设计:FIFO机制简化了软件层面的报文管理,开发者无需直接管理复杂的硬件读写时序,而只需关注FIFO的状态和报文处理逻辑。
- 例如,stm32的CAN接收,就有两个FIFO,每FIFO中有3个邮箱,一个邮箱可以缓存一帧报文。
DMA
- 使用DMA技术,外设可以直接与系统内存进行数据交换,而不需要CPU的干预。CPU只需初始化DMA传输过程,设定源地址、目标地址及传输量后,就可以去执行其他任务。DMA控制器负责数据的实际传输,并在传输完成后通过中断通知CPU。
- DMA的优势在于:
- 提高数据传输速度:因为CPU不必参与每次数据传输的读写操作。
- 减轻CPU负担:CPU可以同时处理其他计算任务,提高了系统整体效率。
- 适用于大批量数据传输:特别是对于高速I/O设备,DMA能显著提升系统性能。
定时器原理
- 定时器计时其实是通过计数来实现的。定时器内部有一个计数器,这个计数器根据一个时钟(这个时钟源来自于ARM的APB总线,然后经过时钟模块内部的分频器来分频得到)来工作。每隔一个时钟周期,计数器就计数一次,定时器的时间就是计数器计数值x时钟周期。
- 定时器内部有1个寄存器TCNT,计时开始时我们会把一个总的计数值(譬如说300)放入TCNT寄存器中,然后每隔一个时钟周期(假设为1ms)ICNT中的值会自动减1(硬件自动完成,不需要CPU软件去干预),直到TCNT中减为0的时候,ICNT就会触发定时器中断。
- 定时时间是由2个东西共同决定的:一个是TCNT中的计数值,一个是时钟周期。譬如上例中,定时周期就为300x1ms=300ms。
- PWM:定时器是实现PWM输出的基础硬件资源之一。
- 定时基础:PWM信号的核心是脉冲的占空比,即高电平时间与整个周期时间的比例。要生成这样的脉冲序列,就需要一个精确的时基,这正是定时器所提供的。定时器通过一个时钟源进行计数,可以设定计数周期(即PWM的周期)和比较值(决定PWM的高电平时间),从而控制输出脉冲的宽度。
- 占空比控制:通过比较模块,定时器可以监控计数器的当前值与预设的比较值(通常称为比较寄存器的值,如TCMPn)。当计数器的值等于比较值时,PWM输出会翻转其逻辑电平(从高变低或从低变高),这样就实现了对脉冲宽度的控制,进而调节了占空比。
- 频率与周期设定:定时器的时钟频率和重装载值决定了PWM信号的频率,即单位时间内脉冲重复的次数。而比较值(TCMPn)则决定了每个脉冲的高电平时间,从而间接设定了占空比。
- 硬件支持:许多微控制器,如STM32系列,其内部集成的定时器通常都具有专门的PWM模式,可以直接配置为输出PWM信号。在这些模式下,定时器可以自动管理PWM信号的生成,包括更新输出状态、调整占空比等,无需过多的软件干预。