一、嵌入式相关资源汇总
1、OS
鸿蒙OS:一款面向全场景的开源分布式操作系统。
RT-Thread:一款小而美的物联网操作系统。
TencentOS tiny:一款面向物联网领域开发的实时操作系统。
freertos:一个轻量级的操作系统。
µC/OS :一个功能齐全的嵌入式操作系统。
mbed-os :ARM自己打造、主打IoT的一整套软件解决方案 。
BabyOS:专为MCU项目开发提速的代码框架 。
LuatOS :LuatOS是运行在嵌入式硬件的实时操作系统,只需要少量内存的flash空间就能运行,用户编写lua代码就可完成各种功能。
Contiki-OS:一个小型的,开源的,极易移植的多任务操作系统。
DJYOS:都江堰操作系统。
klite :简洁易用的嵌入式操作系统内核。
lmosem :一个完全从第一行引导代码开始编写,基于ARM平台,支持多进程、多CPU、内存管理、文件与设备管理的全32位操作系统内核。
freenos:FreeNOS微内核操作系统。
更多资源敬请期待......
2、实用库/框架
cJSON:一个基于C语言的轻量级的JSON解析库。
jsmn:一个小巧的基于C语言的JSON解析库。
MultiTimer :一个软件定时器扩展模块。
MultiButton:一个小巧简单易用的事件驱动型按键驱动模块。
SmartTimer :一个轻量级的基于STM32的定时器调度器 。
CmBacktrace :一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪库。
EasyLogger:一款超轻量级、高性能的 C/C++ 日志库。
EasyFlash:一款开源的轻量级嵌入式Flash存储器库 。
SFUD:一款开源的串行 SPI Flash 通用驱动库。
lw_oopc:轻量级的C语言面向对象编程框架。
PLOOC:受保护的低开销面向对象编程。
cmd-parser:一个非常简单好用的命令解析器。
mqttclient:一个省资源、高稳定的MQTT客户端。
NorthFrame :一个单片机极简图形化状态机框架 。
letter-shell:一个功能强大的嵌入式shell。
pigweed:谷歌开源的嵌入式目标库(模块)集合。
lwrb:一个轻量级通用环缓冲区管理器库。
cQueue :使用ANSI C 编写的消息队列功能函数。
Unity:一个轻量级的、适合嵌入式的测试框架。
Embedded Unit:是个纯标准c构建的单元测试框架。
CuTest :一款微小的C语言单元测试框, 全部代码加起来不到一千行。
cmockery:谷歌C单元测试框架。
googletest:谷歌C++测试框架。
znfat :振南fat,国产嵌入式文件系统方案 。
libu:一个C语言写的多平台工具库。
LWIP:一个小型开源的TCP/IP协议栈 。
SQLite :一个开源的嵌入式关系数据库。
OpenBLT:一种开源引导加载程序。
Linux Lab :Linux 内核实验室,基于 Docker/Qemu 的极速 Linux 内核学习、开发和测试环境。
airkissOpen :腾讯airkiss协议解析库 。
nr_micro_shell :shell for MCU,单片机命令行交互。
FlexibleButton:FlexibleButton 是一个基于标准 C 语言的小巧灵活的按键处理库。
mbedtls :一个开源、便携,易于使用,可读的和灵活的SSL库。
mosquitto或mosquitto(下载速度快):一个开源的MQTT代理。
inih:C 语言编写的 INI 文件解析器。
QP:QP实时嵌入式框架。
MS-RTOS:Micro Safe RTOS 。
protobuf-c:protobuf-c。
eepromfs:基于EEPROM的简易类文件的数据读写库 。
gear-lib :适用于IOT/嵌入式/网络服务开发的C库 。
mult_timer :一个Linux下的超级精简的多重定时器 。
EFSM :是一个基于事件驱动的有限状态机 。
EasyX:一个免费的图形库。
更多资源敬请期待......
3、GUI相关
GuiLite:大道至简 - 5千行/仅头文件/全平台GUI库 。
yoxios: 基于Linux开发的轻量级物联网系统和硬件平台。
ToughGFX:一个C++编写的GUI软件框架 。
emwin:一个老牌GUI库。
littlevGL :一个免费的开源图形库。
野牛 LittlevGL demo:基于野牛开发板的 LittlevGL demo 程序 。
MonoGUI :一个黑白图形用户接口系统 。
MiniGUI:一个快速、稳定、跨操作系统的GUI。
QT:跨平台的应用程序和用户界面框架。
QT_Creator:QT_Creator下载链接。
Gtk:一个用于创造图形用户接口的图形库。
AWTK:是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架 。
玲珑GUI:玲珑GUI教程页。
更多资源敬请期待......
4、物联网、智能家居
HomeAssistant :一款基于 Python 的智能家居开源系统。
Domoticz :一个开源的智能家居系统 。
Kaa IoT Platform:功能丰富的开放和高效的物联网云平台。
RT-Thread IoT SDK :基于RT-Thread IOT开发板的各类例程。
从零打造物联网:一份适合嵌入式开发人员学习的web开发教程。
更多资源敬请期待......
5、实例/项目/软硬结合
qt_2019_ncov:基于Qt/C++实现的新冠肺炎疫情监控平台。
H7-TOOL_STM32H7_App :H7-TOOL 多功能开发工具。
DAPLink/CMSIS DAP:一个调试器, 集成下载、调试和USB虚拟串口。
mcush:MCU shell。
DoST:Linux 下开发 STM32 。
Crazepony:Crazepony开源四轴飞行器。
MiniQ :一个迷你四轴飞行器。
LiPow-Firmware:基于STM32G0采用USB type-C供电的开源锂电池充电器。
Avem:一个轻量级无人机飞控。
SoftWareSerial:一个STM32 IO口模拟实现软件串口程序。
串口ISP程序:一个stm32串口ISP程序。
DSO_Nano :一个手持示波器。
DSView:一个跨平台的逻辑分析仪。
MCU-Development:基于51、430、STM32F10X、STM32F407X、T4MC123G平台的各常见硬件模块demo。
Arduino :开源电子原型平台。
EWAHBoolArray:bitmap算法。
更多资源敬请期待......
6、学习资料/资源/工具/网站
100ask download:百文网资料下载中心。
armfly:安富莱/硬汉嵌入式论坛。
fire download:野火资料下载中心。
openedv download:正点原子资料下载中心。
野火:野火电子论坛。
正点:正点原子论坛。
ST:ST中文社区。
讯为开发社区:北京讯为ARM开发社区。
讯为官网:讯为官网。
NXP社区:恩智浦论坛。
Linux:Linux内核官网。
Linux源码:可在线阅读Linux内核源码。
Buildroot:buildroot源码。
Debian:Debian官网。
Ubuntu:Ubuntu官网。
荔枝派:荔枝派指南。
清华镜像站:清华大学开源软件镜像站。
中科大镜像站:中国科技大学镜像站。
u-boot:u-boot源码下载页面。
bear-pi:小熊派demo。
宅学部落:一个Linux、编程语言、内核、驱动开发学习网站。
单片机教程网:单片机基础、设计实例、论坛。
GNU:GNU官网。
ChinaUnix:Linux/Unix相关。
PyQt5:PyQt5教程。
qter:QT开源社区。
git手册:git学习手册。
开源项目风格:Google 开源项目风格指南 (中文版)。
电子世家:一个电子类导航网站。
21ic:21IC中国电子网。
芯路恒电子:小梅哥博客、FPGA论坛。
嵌入式开发者社区:创龙论坛。
micropython:micropython中文网。
泰晓科技:Linux相关。
电堂科技:STM32相关。
源代码使用示例聚合器:从超过100万个开源项目搜索CPP代码示例。
KST-51 :《手把手教你学51单片机》 。
原子哥:专注电子技术教学。。
digoboy:地瓜派视频网。
c.biancheng:C语言中文网。
open-c-book :《C语言编程透视》。
PyQt5:PyQt5在线教程。
open-shell-book:《Shell 编程范例》 。
software_unit_test:《软件单元测试入门与实践》。
kerneltravel:Linux内核之旅。
蜗窝科技:慢下来,享受技术。
bookstack:书栈网。
wireshark:抓包工具下载链接。
MobaXterm:一个好用的终端软件。
Stduino:一款面向32位处理器快速入门学习的集成开发平台 。
easyicon:一个免费图标下载网站。
codingdict:一个类似于菜鸟教程的编程类教程网站。
codingdict开源软件:codingdict网站收集的各类开源软件集合。
二、STM32嵌入式面试知识点
#1、STM32F1和F4的区别?
解答:
参看:STM32开发 – STM32初识
内核不同:F1是Cortex-M3内核,F4是Cortex-M4内核;
主频不同:F1主频72MHz,F4主频168MHz;
浮点运算:F1无浮点运算单位,F4有;
功能性能:F4外设比F1丰富且功能更强大,比如GPIO翻转速率、上下拉电阻配置、ADC精度等;
内存大小:F1内部SRAM最大64K,F4有192K(112+64+16)。
#2、介绍以下STM32启动过程?
解答:
参看:STM32开发 – 启动流程
通过Boot引脚设定,寻找初始地址
初始化栈指针 __initial_sp
指向复位程序 Reset_Hander
设置异常中断 HardFault_Handler
设置系统时钟 SystemInit
调用C库函数 _main
#3、介绍以下GPIO?
解答:
参看:STM32开发 – GPIO详解
GPIO 8种工作模式(gpio_init.GPIO_Mode):
(1) GPIO_Mode_AIN 模拟输入
(2) GPIO_Mode_IN_FLOATING 浮空输入
(3) GPIO_Mode_IPD 下拉输入
(4) GPIO_Mode_IPU 上拉输入
(5) GPIO_Mode_Out_OD 开漏输出
(6) GPIO_Mode_Out_PP 推挽输出
(7) GPIO_Mode_AF_OD 复用开漏输出
(8) GPIO_Mode_AF_PP 复用推挽输出
APB2负责 AD,I/O,高级TIM,串口1。
APB1负责 DA,USB,SPI,I2C,CAN,串口2345,普通TIM,PWR
GPIO框图剖析:
#4、UART
-
问题一:串行通信方式介绍?
同步通信:I2C 半双工,SPI 全双工异步通信:RS485 半双工、RS232 全双工 -
问题二:串口配置?
串口设置的一般步骤可以总结为如下几个步骤:(1)串口时钟使能,GPIO时钟使能(2)串口复位(3)GPIO端口模式设置TX的GPIO工作模式为:GPIO_Mode_AF_PP;//复用推挽输出RX的GPIO工作模式为:GPIO_Mode_IN_FLOATING;//浮空输入(4)串口参数初始化主要包含:波特率设置(115200)、8个数据位、1个停止位、无奇偶校验位、无硬件数据流控制、收发模式。(5)开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)(6)使能串口(7)编写中断处理函数 -
问题三:USART主要特点?
(1)全双工操作(相互独立的接收数据和发送数据);(2)同步操作时,可主机时钟同步,也可从机时钟同步;(3)独立的高精度波特率发生器,不占用定时/计数器;(4)支持5、6、7、8和9位数据位,1或2位停止位的串行数据桢结构;(5)由硬件支持的奇偶校验位发生和检验;(6)数据溢出检测;(7)帧错误检测;(8)包括错误起始位的检测噪声滤波器和数字低通滤波器;(9)三个完全独立的中断,TX发送完成、TX发送数据寄存器空、RX接收完成;(10)支持多机通信模式;(11)支持倍速异步通信模式。
解答:
参看:STM32开发 – 串口详解
应用场景:GPS、蓝牙、4G模块
#5、I2C
-
问题一:I2C 总线在传送数据过程中共有三种类型信号?
(1)开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。(2)结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。(3)应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。 -
问题二:I2C配置主机模式端口该怎么配置?
硬件模式:复用开漏输出、既不上拉也不下拉。(快速模式:400 Kbit/s)软件模拟:推挽输出、配置上拉电阻。 -
问题三:I2C仲裁机制?
参看:S5PV210开发 – I2C 你知道多少?(三)
I2C 仲裁机制,理解了 线“与”(Wired-AND),就一目了然了。简单说,它遵循“低电平优先”的原则,即谁先发送低电平谁就会掌握对总线的控制权。
解答:
参看:STM32开发 – PMIC、I2C详解
硬件模式: 是有通信速率设置的
/* STM32 I2C 快速模式 */
#define I2C_Speed 400000
/* 通信速率 */
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
软件模拟: 没有设置通信速率,该怎么计算呢?
通过I2C总线位延迟函数 i2c_Delay:
static void i2c_Delay(void)
{
uint8_t i;
/*
下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。
CPU主频72MHz时,在内部Flash运行, MDK工程不优化
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
IAR工程编译效率高,不能设置为7
*/
for (i = 0; i < 10; i++);
}
应用场景:PMIC、加速度计、陀螺仪
#6、SPI
-
问题一:SPI需要几根线?
SPI 接口一般使用 4 条线通信:MISO 主设备数据输入,从设备数据输出。MOSI 主设备数据输出,从设备数据输入。SCLK 时钟信号,由主设备产生。CS 从设备片选信号,由主设备控制。 -
问题二:SPI通信的四种模式?
SPI 有四种工作模式,各个工作模式的不同在于 SCLK 不同, 具体工作由 CPOL,CPHA 决定。(1)CPOL: (Clock Polarity),时钟极性:
SPI的CPOL,表示当SCLK空闲idle的时候,其电平的值是低电平0还是高电平1:CPOL=0,时钟空闲idle时候的电平是低电平,所以当SCLK有效的时候,就是高电平,就是所谓的active-high;CPOL=1,时钟空闲idle时候的电平是高电平,所以当SCLK有效的时候,就是低电平,就是所谓的active-low;
(2)CPHA:(Clock Phase),时钟相位:
相位,对应着数据采样是在第几个边沿(edge),是第一个边沿还是第二个边沿,
0对应着第一个边沿,1对应着第二个边沿。对于:
CPHA=0,表示第一个边沿:
对于CPOL=0,idle时候的是低电平,第一个边沿就是从低变到高,所以是上升沿;
对于CPOL=1,idle时候的是高电平,第一个边沿就是从高变到低,所以是下降沿;
CPHA=1,表示第二个边沿:
对于CPOL=0,idle时候的是低电平,第二个边沿就是从高变到低,所以是下降沿;
对于CPOL=1,idle时候的是高电平,第一个边沿就是从低变到高,所以是上升沿;
-
问题三:该如何确定使用哪种模式?
(1)先确认从机需求的 SCLK 极性,不工作时是在低电位还是高电位,由此确认 CPOL 为 0 或 1。看原理图,我们设置串行同步时钟的空闲状态为高电平所以我们选择 SPI_CPOL_High。也就是CPOL为1
(2)再由slave芯片 datasheet 中的时序图确认 slave 芯片是在 SCLK 的下降沿采集数据,还是在SCLK的上升沿。翻译一下:W25Q32JV通过SPI兼容总线访问,包括四个信号:串行时钟(CLK),芯片选择(/CS),串行数据输入(DI)和串行数据输出(DO)。标准SPI指令使用DI输入引脚串行地将指令、地址或数据写入CLK上升沿上的设备。DO输出引脚用于从CLK下降沿上的设备读取数据或状态。支持模式0(0,0)和3(1,1)的SPI总线操作。模式0和模式3关注的是当SPI总线主端处于待机状态,数据没有被传输到串行Flash时CLK信号的正常状态。对于模式0,在下降和上升时,CLK信号通常是低的边缘/ CS。对于模式3,在/CS的下降和上升边缘上CLK信号通常是高的。既然串行同步时钟的空闲状态为高电平,这里我们选择第二个跳变沿,所以选择 SPI_CPHA_2Edge。也就是CPHA为1
即,我们选择的是模式3(1,1)。
解答:
参看:STM32开发 – W25Q32JV SPI FlASH详解
参看:详解SPI中的极性CPOL和相位CPHA
应用场景:SPI Flash,W25Q32 存储器容量 32Mb (4M x 8),即4M byte
#7、CAN
-
问题一:CAN总结介绍一下?
CAN控制器根据 CAN_L 和 CAN_H上 的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者比居其一。发送方通过使总线电平发生变化,将消息发送给接收方。 -
问题二:CAN初始化配置步骤?
(1)配置相关引脚的复用功能,使能CAN时钟(2)设置CAN工作模式及波特率等(CAN初始化环回模式,波特率500Kbps )(3)设置滤波器 -
问题三:CAN发送数据格式?
CanTxMsg TxMessage;TxMessage.StdId=0x12; // 标准标识符TxMessage.ExtId=0x12; // 设置扩展标示符TxMessage.IDE=CAN_Id_Standard; // 标准帧TxMessage.RTR=CAN_RTR_Data; // 数据帧TxMessage.DLC=len; // 要发送的数据长度 发送8个字节for(i=0;i<len;i++)TxMessage.Data[i]=msg[i]; //数据
解答:
参看:STM32开发 – CAN总线详解
#8、DMA
-
问题一:DMA介绍?
直接存储器存取(DMA) 用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。 -
问题一:DMA传输模式有几种?
DMA_Mode_Circular 循环模式DMA_Mode_Normal 正常缓存模式应用场景:GPS、蓝牙,都是用的循环采集,DMA_Mode_Circular模式。
解答:
一个比较重要的函数,获取当前剩余数据量大小,根据设置的接收buff大小减去当前剩余数据量 ,得到当前接收数据大小。
#9、中断
-
问题一:描述一下中断的处理流程?
(1)初始化中断,设置触发方式是上升沿/下降沿/双沿触发。(2)触发中断,进入中断服务函数 -
问题二:STM32的中断控制器支持多少个外部中断?
STM32的中断控制器支持19个外部中断/事件请求:
从图上来看,GPIO 的管脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0 ~ 15。另外四个EXTI线的连接方式如下:● EXTI线16连接到PVD输出● EXTI线17连接到RTC闹钟事件● EXTI线18连接到USB唤醒事件● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)中断服务函数列表:
IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。EXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI9_5_IRQHandlerEXTI15_10_IRQHandler
解答:
参看:STM32开发 – 外部中断详解
#10、STM32有几个时钟源?
STM32 有5个时钟源:HSI、HSE、LSI、LSE、PLL。①、HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。③、LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
解答:
参考:STM32的时钟系统
#11、RTOS的任务是怎么写的?如何切出这个任务?
解答:
一个任务,也称作一个线程。
UCOS有一个任务调度机制,根据任务的优先级进行调度。
一个是硬件中断, 那么系统会将当前任务有关变量入栈,然后执行中断服务程序,执行完成后出栈返回.
另一个是任务之间的切换,使用的方法就是任务调度,每一个任务有自己的栈,顺度也是一样的入栈,然后执行另一个程序,然后出线返回。
并非是每一任务按优先级顺序轮流执行的,而是高优先级的任务独占运行,除非其主动放弃执行,否则低优先级任务不能抢占,同时高优先级可以把放出去给低优先级任务使用的CPU占用权抢回来。所以ucos的任务间要注意插入等待延时,以便ucos切出去让低优先级任务执行。
#12、UCOSII中任务间的通信方式有哪几种?
解答:
在UCOSII中,是使用信号量、邮箱(消息邮箱)和消息队列这些被称作事件的中间环节来实现任务间的通信的,还有全局变量。
信号量:
参看:ucosII 信号量使用总结(举例讲解)
信号量用于:
1.控制共享资源的使用权(满足互斥条件)
2.标志某时间的发生
3.使2个任务的行为同步
应用实例:互斥信号量
作为互斥条件,信号量初始化为1。
实现目标:调用串口发送命令,必须等待返回“OK”字符过后,才能发送下一条命令。每个任务都有可能使用到此发送函数,不能出现冲突!
邮箱(消息邮箱):
消息队列:
概念:
(1)消息队列实际上就是邮箱阵列。
(2)任务和中断都可以将一则消息放入队列中,任务可以从消息队列中获取消息。
(3)先进入队列的消息先传给任务(FIFO)。
(4)每个消息队列有一张等待消息任务的等待列表,如果消息列中没有消息,则等待消息的任务就被挂起,直到消息到来。
应用场景:
串口接收程序中的接收缓冲区。
储存外部事件。
#13、项目使用了自定义协议,是什么结构?
解答:
了解过Modbus协议。
结构为:帧头(SDTC)+帧长度+指令+流水号+数据+CRC校验。
#14、uCOSII和Linux的差异?
解答:
μC/OS-II是专门为计算机的嵌入式应用设计的,μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。μC/OS-II 已经移植到了几乎所有知名的CPU 上。
linux 免费,安全,稳定,应用范围广,在嵌入式上,服务器上,家用机,都有广泛应用。
μC/OS-II Linux 都适合用在嵌入式上。但μC/OS-II 是专为嵌入式而设计,这样的结果是,运行效率更高,占用资源更少。
linux 都可以用作服务器上,使用率高。linux 虽然不是专门针对服务器而开发,但其源码公开,完全可以修改,使得两者差异不大,最主要的发行版redhat linux 就是在服务器上用得很多的系统。
#15、Git提交代码
问题:Git提交代码过程?
解答:
1、显示工作路径下已修改的文件:
$ git status
2、进入修改文件目录:
$cd -
3、显示与上次提交版本文件的不同:
$ git diff
4、把当前所有修改添加到下次提交中:
$ git add .
5、添加相关功能说明,(第一次提交使用这个)
$ git commit -s
其中还要注明:
Fuction: 修改代码的功能
Ticket: 对应Bug号
注意:每一个文件夹下都要重新提一次。
6、查看提交代码
$ tig .
7、请勿修改已发布的提交记录! (以后提交使用这个)
$git commit --amend
命令模式下:
:x ( 写入文件并退出)
8、推送到服务器
$ git push origin HEAD:refs/for/master
#16、ucosii和ucosiii和freeRTOS比较
-
问题一:三者比较?
解答:
ucosii和freeRTOS比较:
(1)freeRTOS只支持TCP/IP, uCOSii则有大量外延支持,比如FS, USB, GUI, CAN等的支持。(我们用于tbox要用到CAN,所以选择uCOSii)
(2)freeRTOS 是在商业上免费应用。uCOSii在商业上的应用是要付钱的。
(3)任务间通讯freeRTOS只支持队列, 信号量, 互斥量。uCOSii除这些外,还支持事件标志组,邮箱。
(4)理论上讲,freeRTOS 可以管理超过64个任务,而uCOSii只能管理64个。
ucosii和ucosiii比较:
那么从μC/OS-II到μC/OS-III有哪些不同的地方呢?增加了什么,我们看改动还是很大的。一个是原来只有0~63个优先级,而且优先级不能重复,现在允许几个任务使用同一个优先级,在同一个优先级里面,支持时间片调度法;第二个是允许用户在程序运行中动态配置实时操作系统内核资源,比如,任务、任务栈、信号量、事件标志组、消息队列、消息数、互斥型信号量、存储块划分和定时器,可以在程序运行中变更。这样,用户可以避免在程序编译过程中出现资源不够分配的问题。在资源复用上,也做了一些改进。μC/OS-II中,最多任务数有64个,到了版本2.82以后是256个,μC/OS-III中,用户可以由任意多的任务、任意多的信号量、互斥型信号量、事件标志、消息列表、定时器和任意分配的存储块容量,仅受限于用户CPU可以使用的RAM量。这个也是一个很大的扩展。(问:邵老师,它的这个数是启动时就固定的,还是启动后随便定?)它是配置的时候可以自由定义的,只有你的RAM足够大的话。第四点是增加了很多功能,功能总是越来越多的,大伙可以看一下的。原来这些功能在μC/OS-II里面是没有的。
#17、低功耗模式
-
问题一:低功耗模式有几种?唤醒方式是什么?
解答:
#18、物联网的架构
-
问题一:物联网的架构分为几层?每一层都负责哪些功能?
解答:
分三层,物联网从架构上面可以分为感知层、网络层和应用层,
(1)感知层: 负责信息采集和物物之间的信息传输,信息采集的技术包括传感器、条码和二维码、 RFID射频技术、音视频等多媒体信息,信息传输包括远近距离数据传输技术、自组织组网技术、协同信息处理技术、信息采集中间件技术等传感器网络。感知层是实现物联网全面感知的核心能力,是物联网中包括关键技术、标准化方面、产业化方面亟待突破的部分,关键在于具备更精确、更全面的感知能力,并解决低功耗、小型化和低成本的问题。
(2)网络层: 是利用无线和有线网络对采集的数据进行编码、认证和传输,广泛覆盖的移动通信网络是实现物联网的基础设施,是物联网三层中标准化程度昀高、产业化能力昀强、昀成熟的部分,关键在于为物联网应用特征进行优化和改进,形成协同感知的网络。
(3)应用层: 提供丰富的基于物联网的应用,是物联网发展的根本目标,将物联网技术与行业信息化需求相结合,实现广泛智能化应用的解决方案集,关键在于行业融合、信息资源的开发利用、低成本高质量的解决方案、信息安全的保障以及有效的商业模式的开发。
#19、内存管理
-
问题一:UCOS中内存管理的方法有哪些?
解答:
系统通过与内存分区相关联的内存控制块来对内存分区进行管理。
动态内存管理函数有:
创建动态内存分区函数OSMemCreate();
请求获得内存块函数OSMemGet();
释放内存块函数OSMemPut();
#20、Ucos中任务状态哪几种?任务状态之间的关系图?
解答:
有5种状态:
睡眠状态、就绪状态、运行状态、等待状态(等待某一事件发生)和中断服务状态。
UCOSII任务的5个状态转换关系:
#21、ADC
-
问题一:简述STM32的ADC系统的功能特性?
(1)12bit分辨率(2)自动校准(3)可编程数据对齐(转换结果支持左对齐或右对齐方式存储在16位数据寄存器)(4)单次和连续转换模式
解答:
参考:STM32中的ADC
#22、系统时钟
-
问题一:简述设置系统时钟的基本流程?
(1)打开HSE,等待就绪后,设置Flash等待操作。(2)设置AHB,APB1,APB2分频系数,确定他们各自和系统时钟的关系。(3)设置CFGR寄存器确定PLL的时钟来源和倍频系数(HSE外部8M*9倍=72MHz)。(4)使能PLL,将系统时钟源切换到PLL.
解答:
#23、HardFault_Handler处理
-
问题一:造成原因?
(1)数组越界操作;(2)内存溢出,访问越界;(3)堆栈溢出,程序跑飞;(4)中断处理错误; -
问题二:处理方式?
(1)在startup_stm32f10x_cl.s里找到HardFault_Handler的地址重映射,并重新编写,让其跳转到HardFaultHandle函数。
(2)打印查看R0、R1、R2、R3、R12、LR、PC、PSR寄存器。(3) 查看Fault状态寄存器组(SCB->CFSR和SCB->HFSR)
#24、TTS语音合成方法
-
问题一:sim7600 TTS语音使用什么方法?
解答:
(1)使用unicode编码合成声音
AT+CTTS=1,”
6B228FCE4F7F75288BED97F3540862107CFB7EDF”
内容是“欢迎使用语音合成系统”,模块收发中文短信就是unicode编码,所以很容易将短信朗读出来;
(2)直接输入文本,普通字符采用ASIIC码,汉字采用GBK编码。
AT+CTTS=2,”欢迎使用语音合成系统”
#25、定时器
-
问题一:已知STM32的系统时钟为72MHz,如何设置相关寄存器,实现20ms定时?
解答:
参考
通过SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))//1ms定时器
其中: SysTick系统定时器
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
#define SYSCLK_FREQ_72MHz 72000000
#define OS_TICKS_PER_SEC 1000 /* Set the number of ticks in one second
如果需要20ms则,可以通一设置一个全局变量,然后定初值得为20,这样,每个systick中断一次,这个全局变量减1,减到0,即systick中断20次,时间为:1ms*20=20ms。从而实现20ms的定时。
#26、优先级
-
问题一:如果是两个优先级相同的任务怎么运行?
解答:
使获得信号量任务的优先级在使用共享资源期间暂时提升到所有任务最高优先级的高一个级别上,以使该任务不被其他任务所打断,从而能尽快地使用完共享资源并释放信号量,然后在释放信号量之后,再恢复该任务原来的优先级别。
#27、状态机
-
问题一:使用的什么状态机?
解答:
参考:状态机
有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机。
假设状态机的状态转换由下表所示:
实现:(使用switch语句)
//横着写
void event0func(void)
{
switch(cur_state)
{
case State0:
action0;
cur_state = State1;
break;
case State1:
action1;
cur_state = State2;
break;
case State2:
action1;
cur_state = State0;
break;
default:break;
}
}
void event1func(void)
{
switch(cur_state)
{
case State0:
action4;
cur_state = State1;
break;
default:break;
}
}
void event2func(void)
{
switch(cur_state)
{
case State0:
action5;
cur_state = State2;
break;
case State1:
action6;
cur_state = State0;
break;
default:break;
}
}
#28、器件选型
-
问题一:STM32F407 VS STM32F103 主要功能及资源对比?
解答:
三、波形实测,采样率越高噪声越大
ADC采样率指的是模拟到数字转换器(ADC)对模拟信号进行采样的速率。在数字信号处理系统中,模拟信号首先通过ADC转换为数字形式,以便计算机或其他数字设备能够处理它们。
ADC采样率通常以每秒采样的次数来表示,单位为赫兹(Hz)。采样率决定了模拟信号在单位时间内被离散采样的次数。较高的采样率意味着更多的样本被记录下来,从而提供了更准确的信号再现。
上面有两个波形,都是采集的13Hz、10uVpp的正弦信号,哪个图的采样率是1kHz?哪个图的采样率是10kHz呢?
一般来说,采样率需要根据被采样信号中最高频率的两倍以上进行选择,以避免采样误差导致的信号失真。
例如,CD音频的标准采样率为44.1 kHz,这意味着每秒钟对模拟音频信号进行44100次采样。更高的采样率如96 kHz、192 kHz等在高保真音频或专业录音领域中使用,以捕捉更广范围的频率和细节。
采样率和噪声之间存在一定的关系。以下是几个与采样率和噪声相关的方面:
Aliasing噪声:当模拟信号的频率超过采样率的一半时,就会出现混叠现象,导致Aliasing噪声。Aliasing噪声是由于高频成分在离散采样时被错误地表示为低频成分而引起的。为了避免Aliasing噪声,采样率必须满足奈奎斯特(Nyquist)采样定理,即采样率应至少为被采样信号最高频率的两倍。
模拟滤波器抗混叠能力:为了避免Aliasing噪声,通常在采样之前要使用模拟滤波器来限制输入信号的频率范围。较高的采样率可以降低模拟滤波器的要求,因为更高的采样率意味着可以更好地保留输入信号的高频成分。
量化噪声:ADC将连续的模拟信号转换为离散的数字信号时,会引入量化误差,称为量化噪声。量化噪声的幅度与ADC的分辨率有关。
需要注意的是,采样率本身并不能消除或减少模拟信号中的噪声。它只是影响了采样过程和数字信号重构的质量。要降低噪声的影响,可能需要使用合适的模拟滤波器、适当的ADC分辨率以及其他信号处理技术。
那么上图中,哪个图是10kHz的采样率呢?看海说第二个图、噪声大的是采样率高的,这是为什么呢?
四、详解STM32启动文件
本文对STM32启动文件startup_stm32f10x_hd.s的代码进行讲解,此文件的代码在任何一个STM32F10x工程中都可以找到。
启动文件使用的ARM汇编指令汇总
Stack——栈
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=
Stack_Mem SPACE Stack_Size
__initial_sp
开辟栈的大小为 0X00000400(1KB),名字为 STACK, NOINIT 即不初始化,可读可写, 8(2^3)字节对齐。
栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小,如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬 fault 的时候,这时你就要考虑下是不是栈不够大,溢出了。
EQU:宏定义的伪指令,相当于等于,类似于C 中的 define。
AREA:告诉汇编器汇编一个新的代码段或者数据段。STACK 表示段名,这个可以任意命名;NOINIT 表示不初始化;READWRITE 表示可读可写, ALIGN=3,表示按照 2^3对齐,即 8 字节对齐。
SPACE:用于分配一定大小的内存空间,单位为字节。这里指定大小等于 Stack_Size。
标号__initial_sp 紧挨着 SPACE 语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。
Heap——堆
Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
heap_limit
开辟堆的大小为 0X00000200(512 字节),名字为 HEAP, NOINIT 即不初始化,可读可写, 8(2^3)字节对齐。__heap_base 表示对的起始地址, __heap_limit 表示堆的结束地址。堆是由低向高生长的,跟栈的生长方向相反。
堆主要用来动态内存的分配,像 malloc()函数申请的内存就在堆上面。这个在 STM32里面用的比较少。
PRESERVE8
THUMB
PRESERVE8:指定当前文件的堆栈按照 8 字节对齐。
THUMB:表示后面指令兼容 THUMB 指令。THUBM 是 ARM 以前的指令集, 16bit,现在 Cortex-M 系列的都使用 THUMB-2 指令集, THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超集。
向量表
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
定义一个数据段,名字为 RESET,可读。并声明 __Vectors、 __Vectors_End 和__Vectors_Size 这三个标号具有全局属性,可供外部的文件调用。
EXPORT:声明一个标号可被外部的文件使用,使标号具有全局属性。如果是 IAR 编译器,则使用的是 GLOBAL 这个指令。
当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定 ESR的入口地址, 内核使用了―向量表查表机制‖。这里使用一张向量表。向量表其实是一个WORD(32 位整数)数组,每个下标对应一种异常,该下标元素的值则是该 ESR 的入口地址。向量表在地址空间中的位置是可以设置的,通过 NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为 0。因此,在地址 0 (即 FLASH 地址 0) 处必须包含一张向量表,用于初始时的异常分配。要注意的是这里有个另类:0 号类型并不是什么入口地址,而是给出了复位后 MSP 的初值。下图是F103的向量表。
__Vectors DCD __initial_sp ;栈顶地址
DCD Reset_Handler ;复位程序地址
DCD NMI_Handler
DCD HardFault_Handler
DCD MemManage_Handler
DCD BusFault_Handler
DCD UsageFault_Handler
DCD 0 ; 0 表示保留
DCD 0
DCD 0
DCD 0
DCD SVC_Handler
DCD DebugMon_Handler
DCD 0
DCD PendSV_Handler
DCD SysTick_Handler
;外部中断开始
DCD WWDG_IRQHandler
DCD PVD_IRQHandler
DCD TAMPER_IRQHandler
;限于篇幅,中间代码省略
DCD DMA2_Channel2_IRQHandler
DCD DMA2_Channel3_IRQHandler
DCD DMA2_Channel4_5_IRQHandler
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
__Vectors 为向量表起始地址, __Vectors_End 为向量表结束地址,两个相减即可算出向量表大小。
向量表从 FLASH 的 0 地址开始放置,以 4 个字节为一个单位,地址 0 存放的是栈顶地址, 0X04 存放的是复位程序的地址,以此类推。从代码上看,向量表中存放的都是中断服务函数的函数名,可我们知道 C 语言中的函数名就是一个地址。
DCD:分配一个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中, DCD 分配了一堆内存,并且以 ESR 的入口地址初始化它们。
复位程序
AREA |.text|, CODE, READONLY
定义一个名称为.text 的代码段,可读。
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟,然后调用 C 库函数_mian,最终调用 main 函数去到 C 的世界。
WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以由用户在其他文件重新实现,这里并不是唯一的。
IMPORT:表示该标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似。这里表示 SystemInit 和__main 这两个函数均来自外部的文件。
SystemInit()是一个标准的库函数,在 system_stm32f10x.c 这个库文件中定义。主要作用是配置系统时钟,这里调用这个函数之后,单片机的系统时钟配被配置为 72M。__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,并在函数的最后调用main 函数去到 C 的世界。这就是为什么我们写的程序都有一个 main 函数的原因。
LDR、 BLX、 BX 是 CM4 内核的指令,可在《CM3 权威指南 CnR2》第四章-指令集里面查询到,具体作用见下表:
中断服务程序
在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一样的就是这些函数都是空的,真正的中断服务程序需要我们在外部的 C 文件里面重新实现,这里只是提前占了一个位置而已,相关推荐:STM32外部中断实例。
如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且在这个空函数中无线循环,即程序就死在这里。
NMI_Handler PROC ;系统异常
EXPORT NMI_Handler [WEAK]
B .
ENDP
;限于篇幅,中间代码省略
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC ;外部中断
EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMP_STAMP_IRQHandler [WEAK]
;限于篇幅,中间代码省略
LTDC_IRQHandler
LTDC_ER_IRQHandler
DMA2D_IRQHandler
B .
ENDP
B:跳转到一个标号。这里跳转到一个‘.’,即表示无线循环
用户堆栈初始化
ALIGN
ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示 4 字节对齐。
;用户栈和堆初始化,由 C 库函数_main 来完成
IF :DEF:__MICROLIB ;这个宏在 KEIL 里面开启
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory ; 这个函数由用户自己实现
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ALIGN
ENDIF
END
首先判断是否定义了__MICROLIB ,如果定义了这个宏则赋予标号__initial_sp(栈顶地址)、 __heap_base(堆起始地址)、 __heap_limit(堆结束地址)全局属性,可供外部文件调用。有关这个宏我们在 KEIL 里面配置,具体见图 15-2。然后堆栈的初始化就由 C 库函数_main 来完成。
如果没有定义__MICROLIB,则才用双段存储器模式,且声明标号__user_initial_stackheap 具有全局属性,让用户自己来初始化堆栈。
IF,ELSE,ENDIF:汇编的条件分支语句,跟 C 语言的 if ,else 类似
END:文件结束
五、眼图是什么
眼图,是由于示波器的余辉作用,将扫描所得的每一个码元波形重叠在一起,从而形成眼图。
本文将带领大家了解PCB上的眼图是什么,眼图是怎样形成的,眼图中包含有哪些信息,如何根据眼图情况分辨信号质量。
想看 懂示波器眼图需要掌握以下4点:
什么是眼图?
眼图是一系列数字信号在示波器上累积而显示的图形,它包含了丰富的信息,从眼图上可以观察出码间串扰和噪声的影响,体现了数字信号整体的特征,从而估计系统优劣程度,因而眼图分析是高速互连系统信号完整性分析的核心。
另外也可以用此图形对接收滤波器的特性加以调整,以减小码间串扰,改善系统的传输性能。
用一个示波器跨接在接收滤波器的输出端,然后调整示波器扫描周期,使示波器水平扫描周期与接收码元的周期同步,这时示波器屏幕上看到的图形就称为眼图。
示波器一般测量的信号是一些位或某一段时间的波形,更多的反映的是细节信息,而眼图则反映的是链路上传输的所有数字信号的整体特征。
观察眼图的方法是:用一个示波器跨接在接收滤波器的输出端,然后调整示波器扫描周期,使示波器水平扫描周期与接收码元的周期同步,这时示波器屏幕上看到的图形像人的眼睛,故称为“眼图”。
从“眼图”上可以观察出码间串扰和噪声的影响,从而估计系统优劣程度。另外也可以用此图形对接收滤波器的特性加以调整,以减小码间串扰和改善系统的传输性能。
眼图是怎么形成的?
对于数字信号,其高电平与低电平的变化可以有多种序列组合。以3个bit为例,可以有000-111共8中组合,在时域上将足够多的上述序列按某一个基准点对齐,然后将其波形叠加起来,就形成了眼图。
如下图。对于测试仪器而言,首先从待测信号中恢复出信号的时钟信号,然后按照时钟基准来叠加出眼图,最终予以显示。
眼图中包含的信息有哪些?
对于一幅真实的眼图,如下图,首先我们可以看出数字波形的平均上升时间(RiseTime)、下降时间(FallTime)、上冲(Overshoot)、下冲(Undershoot)、门限电平(Threshold/CrossingPercent)等基本的电平变换的参数。
上升时间(RiseTime):脉冲信号的上升时间是指脉冲瞬时值最初到达规定下限和规定上限的两瞬时之间的间隔。除另有规定之外,下限和上限分别定为脉冲峰值幅度的10%和90%。
下降时间(FallTime):脉冲信号的下降时间是指从脉冲峰值幅度的90%下降到10%所经历的时间间隔。
上冲(Overshoot):也叫过冲就是第一个峰值或谷值超过设定电压,主要表现为一个尖端脉冲,并且能导致电路元器件的失效。
下冲(Undershoot):是指下一个谷值或峰值。过分的过冲能够引起保护二极管工作,导致过早地失效。过分的下冲能够引起假的时钟或数据错误。
门限电平(Threshold/CrossingPercent):是指在系统传输特性劣于某一特定误码率的情况下,收信机所能达到的最低接收电平。
如何根据眼图情况分辨信号质量?
信号不可能每次高低电平的电压值都保持完全一致,也不能保证每次高低电平的上升沿、下降沿都在同一时刻。由于多次信号的叠加,眼图的信号线变粗,出现模糊(Blur)的现象。
所以眼图也反映了信号的噪声和抖动:在纵轴电压轴上,体现为电压的噪声(VoltageNoise);在横轴时间轴上,体现为时域的抖动(Jitter)。如下图示。
当存在噪声时,噪声将叠加在信号上,观察到的眼图的线迹会变得模糊不清。若同时存在码间串扰,“眼睛”将张开得更小。一般眼图的眼睛睁得越大,眼图眼高越高,代表信号质量越好。
做信号仿真可以获取眼图情况,然后根据眼图情况判断信号的质量,如果眼图情况不好,可以调整硬件设计或者PCB设计,使眼图眼高变高,保证生产出的产品信号质量。
六、whaosoftのMCU架构
处理器是任何计算机的大脑,它在不断发展以提高效率。一个处理器的设计决定了它能做多少条指令,以及它做这些指令的速度和效率。RISC、RISC-V 和 ARM 是处理器设计中使用的术语,表示一种使用特定类型的指令集架构(ISA)的处理器。
虽然在主流计算机中不常用,但这些处理器为智能手机、微控制器、单板计算机和各种物联网设备提供动力。让我们继续阅读,大眼仔带您了解更多关于它们和它们的区别。
解释指令集结构和 RISC 的含义
如果你不知道 CPU 是如何工作和执行代码的,就很难理解 RISC、RISC-V 和 ARM 之间的区别。因此,在我们开始比较这些术语之前,让我们先谈谈指令集架构,以及它与你的普通计算机处理器使用的指令集架构有何不同。
无论是微处理器、微型计算机,还是普通的台式计算机,它们的处理器都使用一个指令集架构(ISA)。ISA 是处理器的一部分,包含了一个处理器可以执行的所有基本指令。这些指令是计算机程序的构建块。它们通常不会比你的基本加减法更复杂。
一般来说,有两种类型的 ISA 在市场上流通。它们是 RISC 和 CISC 架构。RISC 代表精简指令集计算机,而 CISC 则代表复杂指令集计算机。这两种架构今天都很普遍,X86(英特尔和 AMD 处理器)是利用 CISC 的顶级处理器,ARM(高通和联发科处理器)是最流行的 RISC 架构。
基本上,RISC 是一种计算机架构,其设计和优化是为了使用比 CISC 同类产品更少的指令。这些较少的指令和 RISC 架构中使用的其他优化技术使这些类型的处理器使用更少的功率,使它们成为智能手机、相机、智能手表和各种物联网设备的理想选择。
什么是 ARM?
我们已经确定,ARM 处理器是市场上的一些顶级 RISC 架构。那么,究竟什么是 ARM,为什么它们是最受欢迎的 RISC 处理器?
在 RISC-V(我们很快就会谈到)之前,基于 ARM 的处理器是任何想使用自己的定制处理器来制造电子产品的人的唯一选择。
Arm(小写 “rm”)有限公司是一家为各种硬件制造商设计和授权芯片的公司,如苹果、联发科、高通,以及像 PINE64 这样的小公司。他们使用自己的闭源 ARM ISA 来设计高效的微处理器和片上系统(SoC)。Arm 公司的所有设计都被称为高级 RISC 机器处理器,或简单地称为 ARM(所有大写)处理器。
除了是最早销售和定制芯片设计的公司之一外,Arm 还设法成为占主导地位的 RISC 芯片设计公司,因为它在 ARM ISA 和 ARM 处理器设计方面不断创新。
与 AMD 的 APU(将 CPU 和 GPU 整合到一个芯片中)一样,ARM 处理器被称为将 CPU、GPU、内存、DSP 和各种调制解调器全部整合到一个芯片中,这被称为片上系统(SoC)。这种多个模块的紧密结合使 ARM 处理器的速度和效率得到了提高。
什么是 RISC-V?
RISC-V 是加州大学伯克利分校开发的一种开放标准的 ISA。这种 ISA 并没有在市场上引入任何新技术,然而许多人猜测它是基于 RISC 的处理器的未来。那么,为什么是它呢?
RISC-V 已经获得了亚马逊、谷歌、高通、英特尔、Rockchip、SiFive、索尼、中兴和西部数据等公司的关注。这是因为 RISC-V 是一个开放标准的 ISA。RISC-V 国际组织(RISC-V 的非营利性协会)允许任何人在他们的处理器上使用 RISC-V ISA,而无需支付费用。
RISC-V的伟大之处在于它能够根据你的芯片在特定产品中需要的任何过程来扩展指令集。RISC-V 只从 47 条指令的基础指令集开始。这些指令包括一个芯片工作和完成基本任务所需的所有基本功能。
然后,设计者可以自由选择哪些指令添加到基本指令集中,使芯片具有它所需要的所有功能,而没有任何额外的臃肿功能,它不会使用。
虽然 RISC-V 仍然是一个相对较新的 ISA,但它有可能为各种应用提供具有成本效益和高效率的专用芯片,这就是它成为一个特殊 ISA 的原因。
ARM 或 RISC V?哪个更好?
ARM 和 RISC-V 是遵循 RISC 设计理念的 ISA,那么哪一个更好呢?
为了进行比较,下面是 SiFive 的 P670 处理器与 Arm 的 Cortex-A78 处理器之间的性能比较。
SiFive’s P670 vs. Arm’s Cortex-A78
正如你在图中看到的,Cortex-A78 在峰值单线程性能方面略微领先于 P670。虽然 Cortex-A78 在原始性能上胜出,但 P670 的计算密度是 Cortex-A78 的两倍。这意味着 SiFive 的 P670 处理器提供了与 Cortex-A78 相当的峰值单线程性能,而后者的物理尺寸是 P670 的两倍。
在这种比较中,SiFive 的 P670 处理器在以一半的尺寸提供可比的单线程性能方面胜过 Arm 的 Cortex-A78。然而,你也应该注意到,Cortex-A78 是在 2020 年 12 月通过 Vivo X60 和 X60 Pro 发布的,而 P670 是在 2022 年 11 月 1 日刚刚宣布的。
这在研究和开发方面大约有两年的差异。Arm 的最新处理器现在运行在 ARMv9 ISA 上,大大改进了 Cortex-A78 使用的 ARMv8。从这个角度来看,最新的 ARMv9 处理器的性能提高了约 30%,能效提高了 50%。
因此,就原始性能而言,ARM 处理器仍然处于领先地位。但是,由于 SiFive 的 P670 比 Cortex-A78 提供了两倍的计算密度,在可穿戴技术方面,RISC-V 处理器似乎比 ARM 处理器更有优势,因为可穿戴技术大大受益于使用较小尺寸的处理器。
RISC、RISC-V 和 ARM 是不同的指令集架构
总之,RISC 是一种设计理念,它使用的指令比你在普通桌面处理器(如 x86)上看到的少。拥有更短和更少的指令使 RISC 处理器具有高度的功率效率。
ARM 是一种基于 RISC 的闭源 ISA,它被授权给公司用于其处理器和 SoC。ARM ISA 允许 Arm 设计高性能的 RISC 处理器,如苹果的 M1 芯片。另一方面,RISC-V 是一种基于 RISC 的开放标准 ISA,任何人都可以用它来设计自己的芯片,而无需支付许可费。它的开源性质允许 RISC-V ISA 被进一步修改和扩展,以便为特定的任务制作专门的芯片。
虽然它可能看起来不是那么重要,但 ARM 和 RISC-V 之间的这种持续竞争肯定会使所有消费者受益,特别是在涉及物联网设备、微控制器、单板计算机和手持设备(如智能手机和平板电脑)时。谁知道呢,有了苹果的 M1 芯片作为证明,基于 RISC 的处理器实际上可能比预期的更早与 x86 处理器竞争。
最后我们常用的STM32F1系列微控制器是一款基于ARM Cortex-M3内核的嵌入式芯片
ARM Cortex-M3内核:STM32F1系列微控制器采用了ARM Cortex-M3内核,该内核是一种高性能、低功耗的32位RISC处理器,具有较高的代码密度和执行效率,支持Thumb-2指令集,能够实现快速响应和高效处理。
七、STM32芯片的内部架构
STM32芯片主要由内核和片上外设组成,STM32F103采用的是Cortex-M3内核,内核由ARM公司设计。STM32的芯片生产厂商ST,负责在内核之外设计部件并生产整个芯片。这些内核之外的部件被称为核外外设或片上外设,如 GPIO、USART(串口)、I2C、SPI 等
芯片内部架构示意图
芯片内核与外设之间通过各种总线连接,其中驱动单元有 4 个,被动单元也有 4 个,具体如上图所示。可以把驱动单元理解成是内核部分,被动单元都理解成外设。
ICode 总线
ICode总线是专门用来取指令的,其中的I表示Instruction(指令),指令的意思。写好的程序编译之后都是一条条指令,存放在 FLASH中,内核通过ICode总线读取这些指令来执行程序。
DCode总线
DCode这条总线是用来取数的,其中的D表示Data(数据)。在写程序的时候,数据有常量和变量两种。常量就是固定不变的,用C语言中的const关键字修饰,放到内部FLASH当中。变量是可变的,不管是全局变量还是局部变量都放在内部的SRAM。
系统System总线
我们通常说的寄存器编程,即读写寄存器都是通过系统总线来完成的,系统总线主要是用来访问外设的寄存器。
DMA总线
DMA总线也主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在SRAM,可以在内部FLASH
因为数据可以被Dcode总线,也可以被DMA总线访问,为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。
内部的闪存存储器Flash
内部的闪存存储器即FLASH,编写好的程序就放在这个地方。内核通过ICode总线来取里面的指令。
内部的SRAM
内部的SRAM,是通常所说的内存,程序中的变量、堆栈等的开销都是基于内部SRAM,内核通过DCode总线来访问它。
FSMC
FSMC的英文全称是Flexible static memory controller(灵活的静态的存储器控制器)。通过FSMC可以扩展内存,如外部的SRAM、NAND-FLASH和NORFLASH,但FSMC只能扩展静态的内存,不能是动态的内存,比如就不能用来扩展SDRAM。
AHB
从AHB总线延伸出来的两条APB2和APB1总线是最常见的总线,GPIO、串口、I2C、SPI 这些外设就挂载在这两条总线上。这个是学习STM32的重点,要学会对这些外设编程,去驱动外部的各种设备。