内核相关部分
Cortex-M内核异常与中断
Cortex-M内核主要包括如下几种异常:
Reset:上电时复位或者热复位时调用,其被视为一种特殊形式的异常,永久启用、固定优先级-3
NMI:不可屏蔽中断,永久启用、固定优先级-2,不能被Reset以外的任何异常抢占,其可配置为软件触发或者外设信号触发,通常配置来用于处理严重的异常情况。当然,本人并没用过此异常
- NMI的应用场景由用户配置,如看门狗、
HardFault:优先级-1
- 在Cortex-M0内核中,只支持对齐访问,如果所编译的变量类型为非字节对齐(如int变量地址不能被4整除),可能会产生运行错误
MemManage:由于内存保护相关故障触发的异常,可配置触发方式/源,如非对齐内存访问、除零异常等
- 例:如果指针变量并非为四字节对齐,同时内核使能了非对齐内存方法异常,那么当程序访问该指针变量时,会触发MemManage异常。当然,在GCC编译中也有相应的编译选项–
-munaligned-access
,为非字节对齐变量生成特定的程序指令 - 如下代码所示,表示配置使能Cortex-M4内核的
USGFAULT, BUSFAULT, MEMFAULT
异常,启用DIV 0和未对齐异常内存访问1
2
3
4
5
6
7
8
9
10#define OS_NVIC_SHCSR 0xE000ED24
#define OS_NVIC_CCR 0xE000ED14
#define USGFAULT (1 << 18)
#define BUSFAULT (1 << 17)
#define MEMFAULT (1 << 16)
#define DIV0FAULT (1 << 4)
#define UNALIGNFAULT (1 << 3)
*(volatile UINT32 *)OS_NVIC_SHCSR |= (USGFAULT | BUSFAULT | MEMFAULT);
*(volatile UINT32 *)OS_NVIC_CCR |= (DIV0FAULT | UNALIGNFAULT);
BusFault:内存总线所检测的错误
UsageFault:与指令执行相关的故障异常,包括:未定义指令、指令执行状态无效、异常返回错误
如果在实际的函数指针强制转换调用中,传入参数与实际函数入参不一致,可能会导致未定义的行为错误
SVCall:由SVC指令触发的异常,操作系统环境中,程序可使用SVC指令主动挂起异常,访问内核和设备驱动
PendSV:实时操作系统可通过主动触发PendSV异常进行上下文切换
SysTick:系统滴答定时器归零时触发的异常,通常用作系统节拍
Interrupt(IRQ):中断
全局开关中断操作
1 | __disable_irq(); // 将 PRIMASK 寄存器的值设置为 1,禁止所有中断 |
MCU获取CPU使用率原理
- 理论来说,裸机程序不能获取CPU使用率
- 在RTOS下,可以通过计时器来测量CPU在空闲任务的运行时间,计算其占整体运行时间的比率即可得到CPU使用率
- CPU使用率 = (CPU总运行时间 - CPU空闲时间) / CPU总运行时间
- 通过使用计时器,可以计算上电运行以后的 CPU总使用率,也可以计算 一个时间周期内 CPU的使用率
系统相关部分
芯片时钟频率选择
选择芯片时钟频率,可以综合考虑芯片的性能需求、功耗需求、发热需求等
- 性能:如果运行任务复杂,如包括图形处理、视频处理、复杂数运算等,须选择高频率
- 功耗:如果产品对耗电有要求,可以考虑选用较低同时能够满足使用的频率,需要结合硬件综合评估
- 发热:高频率会增加芯片的发热量,产品设计空间密闭狭小情况下,需要考虑芯片可能过热工作
- 工艺:芯片制造工艺不够精湛,在高时钟频率下工作,可能会不稳定。 (当然,本人没遇到过相关情况)
外设接口相关部分
GPIO的输出速度
- 根据外部设备要求进行配置
- 常规的控制LED灯、按键等,采用2MHz即可
- GPIO模拟SPI、I2C等总线,可以配置为10MHz
- 控制DDR、USB等超高速接口,配置50MHZ
- GPIO的输出速度越高,其驱动电路的功耗就越高
内部与外部晶振
- 内部晶振精度较外部晶振低
- 一般情况下,使用内部晶振足以满足常用需求,包括spi、iic、uart的外设通信
- 如果要求时钟精度高,或应用于精密仪器等场景,或用到高速外设如usb、sdio的高精度时钟要求场景,考虑用外部晶振
- SDIO 接口要求时钟信号的精度为 2% 或以下
- 存储卡、扩展卡、无线模块
- 高速图像传感器、高速存储卡
- USB 接口要求时钟信号的精度为 5% 或以下
- 鼠标、键盘、打印机、网络摄像头、耳机
- 高速摄像头、高速打印机、高品质音频设备
- SDIO 接口要求时钟信号的精度为 2% 或以下
外设接口的通信频率
MCU常用外设的通信速率范围
接口类型 | 通信频率 | 精度 |
---|---|---|
SDIO | 25 MHz~50 MHz | 2% 以下 |
USB | 12 MHz~480 MHz | 5% 以下 |
I2C | 100 kHz~400 kHz | 1% 以下 |
SPI | 1 MHz~20 MHz | 1% 以下 |
UART | 1200 bps~921600 bps | 1% 以下 |
UART外设
- UART(通用异步收发传输器)是一种设备、通信的基础,规定了数据的格式和帧结构;RS232和RS485是基于UART的电气接口标准,其规定了电气特性和物理特性
- TTL电平的通信速率:MCU的UART外设理论最高速率取决于其外设的时钟源
- 可通过芯片手册查看时钟树,获取外设的时钟频率
- RS232为点对点通信,其标准传输速率须在20Kbps下,抗干扰能力差,传输最大距离不超过15m
- RS485的理论最高传输速率为10Mbps,可一对多通信,理论最大传输距离1500米(9600bps)
- 测试较高波特率场景要求时,可以通过示波器抓取uart外设波形,计算其误差是否满足,或者通过逻辑分析仪在收发两端分别测试验证
以下转述参考文章: UART波特率对时钟精度的要求有多高?
分频误差:波特率是根据系统时钟分频产生的,而系统时钟和波特率可能不是整数倍的关系,所以分频时也会产生误差。但是,当系统时钟较高,或者波特率较低时,这个误差影响很小。
时钟误差:波特率的主要误差还是取决于系统时钟的误差。串口通讯对时钟误差的要求有多高呢?
每一个字节都有一个起始位做同步,所以误差只会在一个字节内累计。在最后一个位采样时,误差最大,允许极限误差为0.5位。
按照每个字节10位计算,最大允许误差为±0.5/10=±0.05,即±5%。
考虑到串口通讯涉及收发两端,两端都可能存在误差,所以,每端的误差最好控制在±2.5%以内。当数据位、校验位等较多时,要求的时钟误差就更高一些。
考虑到上面所说的分频误差,一般来说,当时钟误差小于±2%时,串口通信是比较可靠的。
UART通信协议
- 空闲状态
- 起始位
- 数据位
- 奇偶检验位
- 停止位
空闲位和空闲中断
空闲位:在UART通信中两个字节或者两个帧之间的 一位高电平,用于表示线路的空闲状态;当接收端检测到线路从”1”跳转到”0”(起始位)时,可以知道下一字节开始传输
- 当一次发送多个字节时,每字节间会有个空闲位(可配置?看实际设计),用于区分字节
空闲中断:在接收到数据之后,如果在一个字节的时间内没有再接收到数据,就会产生空闲中断
- 其一般用于接收不定长数据,用于标识一个数据包/一帧数据
SPI外设
SPI 的 MOSI、MISO引脚在空闲状态下为低电平,SCK空闲电平可以指定
QSPI
IIS接口
IIS(Inter-IC Sound),又称集成电路内置音频总线,是飞利浦在1986年定义的数字音频传输标准,与IIC并无相关性。
相对其它协议,IIS接口协议相对简单,没有地址和片选机制。在总线上,只能同时存在一个主设备和发射设备:提供时钟的为主设备,主设备可以是发射设备、接收设备或者协调两者的其它控制设备皆可。
主要应用于处理器与音频编解码器之间的音频数据传输
IIS协议定义了三根信号线:时钟信号SCK、数据信号SD、左右声道选择信号WS
- SCK/BCLK 位时钟:等于通道数 * 位宽 * 采样率
- SDIN/DIN 数据线:串行数据,以二进制补码形式在数据线上传输,在WS变化后的第一个SCK脉冲先传输最高位
- WS/LRCLK 声道选择信号:用于区分左右声道的数据,0表示左声道,1表示右声道。也叫帧时钟,等于声音的采样频率
- MCLK 主时钟(可选):提供主时钟频率给接收端,确保采样率的准确性。 在高质量音频输出、使用外部音频解码器、多通道音频传输时,主时钟是必须的。
标准IIS模式
其它部分
bin文件合并大小
假如一个bin文件大小为6KB,烧录地址为0x8000000,另一个bin文件大小为60KB,烧录地址为0x8002800(偏移10KB),那么此两bin文件合并大小为70KB,而非66KB
为什么一个内存地址对应一个字节
一个内存地址,通常对应一个内存单元,在大部分计算机系统中,一个内存单元通常是一个字节,因为字节是计算机处理数据的基本单位。即一个地址表示的是一个8-bit大小的空间。
在某些特定硬件或者设计中,一个地址可能会对应不同的数据单位,STM32有特定设计把一片内存映射成位带,一个地址对应 1 位。或者在某些系统设计中,一个地址对应的是16-bit大小空间。
大端/小端存储
多字节数据存储的字节顺序问题:
- 大端存储(Big-endian)是指数据的高位字节存储在低地址,低位字节存储在高地址。
- 小端存储(Little-endian)是指数据的低位字节存储在低地址,高位字节存储在高地址。
例,32bit的16进制数 0x12345678 在内存中的存放方式:
大端内存地址 0x1000 0x1001 0x1002 0x1003
大端存放内容 0x12 0x34 0x56 0x78
小端内存地址 0x1000 0x1001 0x1002 0x1003
小端存放内容 0x78 0x56 0x34 0x12