D_RT-Thread STM32 Notes
STM32中文参考手册
9.1 DMA简介
9.2 DMA主要特性
9.3 功能描述
STM32F10xxx参考手册
75
75 75 76 76 77 77 77
78
78 78 79 79 80 80 81 82 82
83
83 83 86 86 87 87
88
89
89
89 89
91
91 92 92 92 94
108
9.4.3 DMA通道x配置寄存器(DMA_CCRx)(x = 1…7)
108
9.4.4 DMA通道x传输数量寄存器(DMA_CNDTRx)(x = 1…7)
110
9.4.5 DMA通道x外设地址寄存器(DMA_CPARx)(x = 1…7)
110
9.4.6 DMA通道x存储器地址寄存器(DMA_CPARx)(x = 1…7)
16
1.3 可用的外设
16
2 存储器和总线构架
17
2.1 系统构架
17
2.2 存储器组织
18
2.3 存储器映像
19
2.3.1 嵌入式SRAM
20
2.3.2 位段
20
2.3.3 嵌入式闪存
21
2.4 启动配置
23
3 CRC计算单元(CRC)
25
3.1 CRC简介
25
3.2 CRC主要特性
25
3.3 CRC功能描述
STM32F10xxx参考手册
38
38 39
39
39 39 40 40 42
45
45
45 45 46
46
48 48 49 49 49 50 50 50 50 50
STM32学习笔记及勘误手册
/******************************************************************* 文件名:书写程序中一些特别需要留意的地方文件编辑人:张恒编辑日期:15/11/23功能:快速查阅巩固知识点*******************************************************************/ 版本说明:v1.0版本:1.开始编辑书写整个文档,开始用的为TXT文档的形式,整理了部分学习到的东西和一些在书写常用程序中容易出错的地方,以及经常忽视细节而导致程序运行失败,是巩固知识点,提醒值得注意地方的工具文档。
2.添加的功能上基本涵盖了所有的模块,除了串口通信中的SPI和I2C、I2S等,应用是比较简单后续可能会添加。
3.对一些特定的功能综合应用并未加入进去,这是一个不好的地方,后续应该会随着学习总结更新,每次更新记录为一个版本。
// 2015/11/24;v1.1版本:1.将所有的TXT版本的文档全部转换为DOC模式,并且更新的加入了目录显示,显示为1级目录,方便查阅相关内容。
2.更新了SysTick书写中值得注意的地方3.更新了FSMC的一些细微操作,后续继续追捕更新书写细节。
V1.2版本:1.更新了FSMC部分功能显示,详细了FSMC的使用注意事项2.添加了RTC实时时钟的一些注意事项。
//2015/12/1;V1.3版本:1.更新RTC部分注意事项。
//2015/12/11V1.4版本:1.更新ADC校准标志部分注意事项。
2.更新了TIM1和TIM8的高级定时器特殊功能说明。
//2015/12/13V1.5版本:1.优化了部分注意事项,SysTick的写法上重新的定制写法。
2.优化了ADC在使用过程的一些细节注意地方。
3.面对最近出现的浮点数运算错误,配合AD数据进行总结。
4.RTC细节的把握-配置正确顺序的错误。
stm32跑RT-thread之串口操作简介
UART 设备 UART 简介UART( Uni versal Asynchronous Receiver/Tra nsmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符 一位接一位地传输。
是在应用程序开发过程中使用频率最高的数据总线。
UART 串口的特点是将数据一位一位地顺序传送,只要 实现双向通信,一根线发送数据的同时用另一根线接收数据。
几个重要的参数,分别是波特率、起始位、数据位、停止位和奇偶检验位,对 于两个使用UART 串口通信的端口,这些参数必须匹配,否则通信将无法正常 完成。
UART 串口传输的数据格式如下图所示:2根传输线就可以UART 串口通信有? 起始位:表示数据传输的开始,电平逻辑为 “0 。
?数据位:可能值有5、6、7、8、9,表示传输这几个bit 取值为8,因为一个ASCII 字符值为8位。
?奇偶校验位:用于接收方对接收到的数据进行校验,校验 为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性, 要此位也可以。
? 停止位:表示一帧数据的结束。
电平逻辑为“ 1”。
?波特率:串口通信时的速率,它用单位时间内传输的二进制代码的有效位(bit)数来表示,其单位为每秒比特数 bit/s(bps)4800、9600、14400、38400、115200 等, 115200表示每秒钟传输115200位数据。
访问串口设备应用程序通过RT-Thread 提供的I 关接口如下所示:I/O 位数据。
一般 “ 1 ”的位数使用时不需。
常见的波特率值有 数值越大数据传输的越快,波特率为设备管理接口来访问串口硬件,相查找串口设备应用程序根据串口设备名称获取设备句柄,进而可以操作串口设备,查找 设备函数如下所示,rt_device_t rt_device_find( const char* name);描述返回©找到对应设备将返回相应的S 备句柄/*接收模式参数*/narrc设备名称IRT NULL没有找到拾应的设笛对觀一般情况下,注册到系统的串口设备名称为 uart0 如下所示: ,uartl 等,使用示例#defi ne SAMP LE_UART_NAME "uart2"/*串口设备名称*/static rt device t serial; /*串口设备句柄*//*查找串口设备*/serial = rt_device_fi nd(SA MP LE_UART_NAME);打开串口设备通过设备句柄,应用程序可以打开和关闭设备,打开设备时,会检测设备 是否已经初始化,没有初始化则会默认调用初始化接口初始化设备。
stm32自学笔记共20页
•
LED0=1;
•
LED1=0;
•
delay_ms(300);
•
}
•}
第二章 跑马灯实验
• Led.c函数
• void LED_Init(void)
•{
•
RCC->APB2ENR|=1<<2; //使能PORTA时钟
•
GPIOA->CRH|=0XFFFFFFFF3;//PA8 推挽输出
•
GPIOA->ODR|=1<<8; //PA8 输出高
• JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD,在原理图上可以看 到PA13和PA15为键盘和JTAG与SWD所共用,而这两种方针接口,他们 和普通的IO口公用,当想使用普通IO口时,必须先把他们关闭。在这 个函数里面设置参数,如果为二进制数00,则代表全部使能,如果是 二进制数01,则是能SWD,如果是10,则表示全部关闭。JTAG是一种 国际标准测试协议,主要用于芯片内部的测试。
• }要想实现一个点亮led小灯的功能,最少只需对3个寄存器进行设 置,第一步是设置外设时钟使能先把PORTA时钟使能,接下来把IO
口设置为输出,在接下来设置输出为高电平还是低电平,这里使用 推挽输出(3.3v),推挽输出主要是增强驱动能力,为外部提供大电 流。
第二章 跑马灯实验
• #ifndef __LED_H • #define __LED_H • #include "sys.h" • #define LED0 PAout(8)// PA8 • #define LED1 PDout(2)// PD2 • void LED_Init(void);//初始化
STM32学习笔记-STM32F103ZET6
STM32F103 系列芯片的系统架构:系统结构:在每一次复位以后,所有除SRAM 和FLITF 以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR 来打开该外设的时钟。
GPIO 输入输出,外部中断,定时器,串口。
理解了这四个外设,基本就入门了一款MCU。
时钟控制RCC:-4~16M 的外部高速晶振-内部8MHz 的高速RC 振荡器-内部40KHz低速RC 振荡器,看门狗时钟-内部锁相环(PLL,倍频),一般系统时钟都是外部或者内部高速时钟经过PLL 倍频后得到- 外部低速32.768K 的晶振,主要做RTC 时钟源ARM存储器映像:数据字节以小端格式存放在存储器中。
一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。
存储器映像与寄存器映射:ARM 存储器映像4GB0X0000 00000X1FFF FFFF0X2000 00000X3FFF FFFF0X4000 00000X5FFF FFFF寄存器名称相对外设基地址的偏移值编号位表读写权限寄存器位功能说明使用C语言封装寄存器:1、总线和外设基地址封装利用地址偏移(1)定义外设基地址(Block2 首地址)(2)定义APB2总线基地址(相对外设基地址偏移固定)(3)定义GPIOX外设基地址(相对APB2总线基地址偏移固定)(4)定义GPIOX寄存器地址(相对GPIOX外设基地址偏移固定)(5)使用 C 语言指针操作寄存器进行读/写//定义外设基地址#define PERIPH_BASE ((unsigned int)0x40000000) 1)//定义APB2 总线基地址#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2)//定义GPIOC 外设基地址#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3)//定义寄存器基地址这里以GPIOC 为例#define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4)#define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04)#define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08)#define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C)#define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10)#define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14)#define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18)//控制GPIOC 第0 管脚输出一个低电平5)GPIOC_BSRR = (0x01<<(16+0));//控制GPIOC 第0 管脚输出一个高电平GPIOC_BSRR = (0x01<<0);2、寄存器封装利用结构体、外设基地址和寄存器地址偏移typedef unsigned int uint32_t; /*无符号32 位变量*/typedef unsigned short int uint16_t; /*无符号16 位变量*//* GPIO 寄存器列表*/typedef struct{uint32_t CRL; /*GPIO 端口配置低寄存器地址偏移: 0x00 */uint32_t CRH; /*GPIO 端口配置高寄存器地址偏移: 0x04 */uint32_t IDR; /*GPIO 数据输入寄存器地址偏移: 0x08 */uint32_t ODR; /*GPIO 数据输出寄存器地址偏移: 0x0C */uint32_t BSRR; /*GPIO 位设置/清除寄存器地址偏移: 0x10 */uint32_t BRR; /*GPIO 端口位清除寄存器地址偏移: 0x14 */uint16_t LCKR; /*GPIO 端口配置锁定寄存器地址偏移: 0x18 */}GPIO_TypeDef;只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。
STM32_参考手册-中文
23 串行外设接口(SPI)小容量产品是指闪存存储器容量在16K 至32K 字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx 和STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。
互联型产品是指STM32F105xx和STM32F107xx微控制器。
除非特别说明,本章描述的模块适用于整个STM32F10xxx微控制器系列。
23.1 SPI简介在大容量产品和互联型产品上,SPI接口可以配置为支持SPI协议或者支持I2S音频协议。
SPI接口默认工作在SPI方式,可以通过软件把功能从SPI模式切换到I2S模式。
在小容量和中容量产品上,不支持I2S音频协议。
串行外设接口(SPI)允许芯片与外部设备以半/全双工、同步、串行方式通信。
此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。
接口还能以多主配置方式工作。
它可用于多种用途,包括使用一条双向数据线的双线单工同步传输,还可使用CRC校验的可靠通信。
I2S也是一种3引脚的同步串行接口通讯协议。
它支持四种音频标准,包括飞利浦I2S标准,MSB 和LSB对齐标准,以及PCM标准。
它在半双工通讯中,可以工作在主和从2种模式下。
当它作为主设备时,通过接口向外部的从设备提供时钟信号。
警告:由于SPI3/I2S3 的部分引脚与JTAG 引脚共享(SPI3_NSS/I2S3_WS 与JTDI ,SPI3_SCK/I2S3_CK与JTDO),因此这些引脚不受IO控制器控制,他们(在每次复位后) 被默认保留为JTAG用途。
如果用户想把引脚配置给SPI3/I2S3,必须(在调试时)关闭JTAG并切换至SWD接口,或者(在标准应用时)同时关闭JTAG和SWD接口。
RT-Thread操作系统及STM32F4xx体系结构详解
RT-Thread操作系统及STM32F4xx体系结构详解STM32F4xx包含16个32位核心(整数)寄存器。
它们被标记为R0-R15。
寄存器名可以在汇编语言中以大写或小写形式出现。
当寄存器在过程调用标准中具有固定角色时,使用大写。
STM32F4xx支持的核心寄存器如下图:程序计数器(PC)是寄存器R15。
它包含当前程序地址。
处理器复位时,处理器用复位向量的值加载PC,该值位于0x00000004。
编写汇编时需要遵循ABI规范,该规范规定了寄存器的相关用法,函数调用规范如下:前四个寄存器r0-r3(a1-a4)用于将参数值传递给子程序,并从函数返回结果值。
它们还可用于在例程中保存中间值(但通常仅在子例程调用之间)。
在一些变体中,r11(FP)可以用作帧指针。
通常寄存器r4-r8、r10和r11(v1-v5、v7和v8)用于保存例程局部变量的值。
向量表包含复位时堆栈指针的值、复位起始地址以及所有异常处理程序入口地址。
在系统复位时,向量表固定在地址0x00000000。
特权软件可以写入VTOR寄存器以将矢量表的起始地址重新定位到不同的内存位置,在范围0x00000080到0x3FFFFF80。
通过上述的链接脚本指isr_vector段即定向量表的地址位于代码起始处,其libraries\STM32F4xx_HAL\CMSIS\Device\ST\STM32F4xx\Source\ Templates\gcc\startup_stm32f407xx.s启动代码中的下图代码表明向量表的布局,与向量表图吻合,其处理器的执行的第一条指令为Reset_Handler函数的第一条指令。
Reset_Handler函数主要负责把数据段搬移到SRAM和BSS段清零操作,然后跳转到SystemInit函数设置微控制器系统,初始化FPU 设置、矢量表位置和外部存储器配置,最后调用entry函数进入RT-Thread内核初始化。
stm32跑RT-thread之串口操作简介
#define SAMPLE_UART_NAME
"uart2" /* 串口设备名称 */
static rt_device_t serial;
/* 串口设备句柄 */
/* 查找串口设备 */
serial = rt_device_find(SAMPLE_UART_NAME);
/* 以 DMA 接收及轮询发送模式打开串口设备 */
460800
#define BAUD_RATE_921600
921600
#define BAUD_RATE_2000000
2000000
#define BAUD_RATE_3000000 /* 数据位可取值 */
3000000
#define DATA_BITS_5
5
#define DATA_BITS_6
要此位也可以。
•
停止位: 表示一帧数据的结束。电平逻辑为 “1”。
•
波特率:串口通信时的速率,它用单位时间内传输的二进制代码的有效
位(bit)数来表示,其单位为每秒比特数 bit/s(bps)。常见的波特率值有
4800、9600、14400、38400、115200 等,数值越大数据传输的越快,波特率为
#define RT_DEVICE_FLAG_STREAM
0x040 /* 流模式
*/
/* 接收模式参数 */
#define RT_DEVICE_FLAG_INT_RX
0x100 /* 中断接收模式 */
#define RT_DEVICE_FLAG_DMA_RX /* 发送模式参数 */ #define RT_DEVICE_FLAG_INT_TX
UART 设备 UART 简介
STM32-深入浅出(新手必看)
STM32-深⼊浅出(新⼿必看)STM32学前班教程之⼀:为什么是它经过⼏天的学习,基本掌握了STM32的调试环境和⼀些基本知识。
想拿出来与⼤家共享,笨教程本着最⼤限度简化删减STM32⼊门的过程的思想,会把我的整个⼊门前的⼯作推荐给⼤家。
就算是给⽹上的众多教程、笔记的⼀种补充吧,所以叫学前班教程。
其中涉及产品⼀律隐去来源和品牌,以防⼴告之嫌。
全部汉字内容为个⼈笔记。
所有相关参考资料也全部列出。
:lol教程会分⼏篇,因为太长啦。
今天先来说说为什么是它——我选择STM32的原因。
我对未来的规划是以功能性为主的,在功能和⾯积之间做以平衡是我的⾸要选择,⽽把运算放在第⼆位,这根我的专业有关系。
⾥⾯的运算其实并不复杂,在⼊门阶段想尽量减少所接触的东西。
不过说实话,对DSP的外设并和开发环境不满意,这是为什么STM32⼀出就转向的原因。
下⾯是我⾃⼰做过的两块DSP28的全功能最⼩系统板,在做这两块板⼦的过程中发现要想尽⼒缩⼩DSP的⾯积实在不容易(⽬前只能达到50mm×45mm,这还是没有其他器件的情况下),尤其是双电源的供电⽅式和1.9V的电源让⼈很头疼。
后来因为⼀个项⽬,接触了LPC2148并做了⼀块板⼦,发现⼩型的ARM7在外设够⽤的情况下其实很不错,于是开始搜集相关芯⽚资料,也同时对⼩⾯积的A VR和51都进⾏了⼤致的⽐较,这个时候发现了CortexM3的STM32,⽐2148拥有更丰富和灵活的外设,性能⼏乎是2148两倍(按照MIPS值计算)。
正好2148我还没上⼿,就直接转了这款STM32F103。
与2811相⽐较(核⼼1.8V供电情况下),135MHz×1MIPS。
现在⽤STM32F103,72MHz×1.25MIPS,性能是DSP的66%,STM32F103R型(64管脚)芯⽚⾯积只有2811的51%,STM32F103C型(48管脚)⾯积是2811的25%,最⼤功耗是DSP的20%,单⽚价格是DSP 的30%。
RT—Thread操作系统在STM32中移植的研究
RT—Thread操作系统在STM32中移植的研究作者:朱志国来源:《计算机光盘软件与应用》2012年第22期摘要:介绍了RT-Thread操作系统在STM32F107VC上的移植,简要说明了具体的移植过程和使用的方法,并分析了RT-Thread操作系统内核代码的各个功能,给出了移植环境的如何搭建,及编写应用程序如何修改代码的方法。
最后通过一个实例成功实现RT-Thread在STM32F107VC上的移植,证明了移植是可行的。
关键词:RT-Thread;STM32;嵌入式操作系统;Keil中图分类号:TP311.52 文献标识码:A 文章编号:1007-9599 (2012) 22-0000-02RT-Thread属于第二代微内核操作系统,最突出的优势就是其支持处理器平台广泛,最低要求8k ROM,4k RAM空间就可以了。
STM32是基于Cortex-M3内核的处理器,也是一款性能优越的32位单片机,在工业控制方面的应用大有取代传统16位单片机之势。
1 RT-Thread操作系统介绍RT-Thread主要优点是:实时、小型、可裁剪。
它不仅仅是一个实时内核,也是一个功能丰富的软件平台,可以搭建POSIX环境,运行独立的应用程序,这是传统的实时操作系统所不具备的。
RT-Thread具有32~256可选优先级抢占式调度,线程度不限,相同优先级线程时间片轮转调度,支持动态创建、销毁线程,任务等待可按优先级进行排队。
RT-Thread内核大致可分为对象管理、实时调度器、线程管理、线程间通信、时钟管理、设备驱动6个部分。
(1)对象管理(object.c):定义了对象容器的种类,包括线程、信号量、互斥量、事件、邮箱、消息队列、内存池、设备、定时器、组件。
此部分主要完成各模块的创建,系统对象的初始化。
(2)实时调度器(schedule.c):定义了优先级。
该部分完成优先级的创建及调度算法的定义,对线程的初始化、创建、插入、移动进行了描述。
RT-Thread STM32 说明
; void rt_hw_interrupt_enable(rt_base_t level); ; 恢复中断 rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable MSR PRIMASK, r0 ; 恢复R0寄存器的值到PRIMASK中
RT-Thread 网站:
Cortex M3 微处理器是 ARM 公司于 2004 年推出的基于 ARMv7 架构的新一代微处理器,它 的速度比目前广泛使用的 ARM7 快三分之一,功耗则低四分之三,并且能实现更小芯片面 积,利于将更多功能整合在更小的芯片尺寸中。 Cortex-M3 微处理器包含了一个 ARM core,内置了嵌套向量中断控制器、存储器保护等系 统外设。ARM core 内核基于哈佛架构,3 级流水线,指令和数据分别使用一条总线,由于 指令和数据可以从存储器中同时读取,所以 Cortex-M3 处理器对多个操作并行执行,加快 了应用程序的执行速度。
swtich_to_thread LDR r1, =rt_interrupt_to_thread LDR r1, [r1] LDR r1, [r1] ; 载入切换到线程的栈指针到R1寄存器 LDMFD MSR ORR BX ENDP r1!, {r4 - r11} psp, r1 lr, lr, #0x04 lr ; 恢复R4 – R11寄存器 ; 更新程序栈指针寄存器 ; 构造LR以返回到Thread模式 ; 从PendSV异常中返回
Handler 模式 R4 ... R11 图 D - 1 正常模式下的线程上下文切换 当要进行切换时 (假设从 Thread [from] 切换到 Thread [to]) , 通过 rt_hw_context_switch 函数触发一个 PenSV 异常。异常产生时,Cortex M3 会把 PSR,PC,LR,R0 – R3,R12 压入当前线程的栈中,然后切换到 PenSV 异常。到 PenSV 异常后,Cortex M3 工作模式 切换到 Handler 模式,由函数 rt_hw_pend_sv 进行处理。rt_hw_pend_sv 函数会载 入切换出线程和切换到线程的栈指针,如果切换出线程的栈指针是 0 那么表示这是第一次 线程上下文切换,不需要对切换出线程做压栈动作。如果切换出线程栈指针非零,则把剩余 未压栈的 R4 – R11 寄存器依次压栈;然后从切换到线程栈中恢复 R4 – R11 寄存器。当 从 PendSV 异常返回时,PSR,PC,LR,R0 – R3,R12 等寄存器由 Cortex M3 自动恢 复。 因为中断而导致的线程切换可用图 D - 2 中断中线程上下文切换表示。 R4 ... R11
嵌入式系统原理及应用—基于STM32和RT-Thread 第2章 STM32软硬件基础
本章总结
课后作业
2.2.2 最小系统示例
5. 启动
具有BOOT0和BOOT1引脚的MCU启动模式配置
启动模式选择引脚
BOOT1
BOOT0
启动模式
说明
X
0
从Flash启动
Flash被选为启动区域
0
1
从系统存储器启动 系统存储器被选为启动区域
1
1
从SRAM启动
SRAM被选为启动区域
22
嵌入式系统基本 概念
1 0 1 1 0 1 0
Flash 空
0 X 1 X X X X
启动模式
从Flash启动 从Flash启动 从系统存储器启动 从系统存储器启动 从系统存储器启动
从SRAM 从SRAM
23
本节小结
嵌入式系统基本 概念
最小系统搭建
开发环境搭建
本章总结
课后作业
1. 掌握STM32最小系统概念; 2. 熟练设计STM32最小系统。
24
2.3 开发环境搭建
裸机开发环境 RT-Thread开发环境 本节小结
STM32概述 最小系统设计 开发环境搭建
本章总结 课后作业
2.3.1 裸机开发环境
1. 软件下载 2. 软件安装
3. 软件测试
报错——安装程序所在路径包含 中文
26
STM32概述 最小系统设计 开发环境搭建
本章总结 课后作业
最小系统搭建
开发环境搭建
本章总结
课后作业
2.2.2 最小系统示例
5. 启动
具有BOOT0,无BOOT1引脚的MCU启动模式配置
BOOT0
0 X 0 1 X 1 X
RT-Thread用户手册
6.7
线程相关接口 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 5 5 5 6 9 9 14 18 20 21 22 27 28 29 29 29 29 31 31 34 43 43 43 44 46 47 47 i
5 内核对象模型 5.1 C语言的对象化模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 内核对象模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 线程调度与管理 6.1 实时系统的需求 6.2 线程调度器 . . . 6.3 线程控制块 . . . 6.4 线程状态 . . . . 6.5 空闲线程 . . . . 6.6 调度器相关接口 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
RT-Thread4.0+STM32F407学习笔记1
RT-Thread4.0+STM32F407学习笔记1RT Thread 4.0提供了新的BSP框架新 BSP 框架的主要特性如下:提供多系列 BSP 模板,⼤⼤降低新 BSP 的添加难度;每个 BSP 都配有齐全的驱动⽂件,开发者可以⽅便地使⽤所有驱动;开发者可以使⽤ CubeMX ⼯具对 BSP 进⾏图形化配置;由于Hal库是以后主流,在使⽤STD库对STM32很熟悉后,建议转到Hal库本⽂参考官⽅《STM32系列BSP制作教程》,由于官⽅提供的CubeMX与Hal库版本固定,不⼀定适⽤所有初步使⽤的⼈,本⽂使⽤⾃⼰的CubeMX制作BSP并强调注意事项。
其中⼀些解释如内容说明、Scons、Env等,详细参见《STM32系列BSP制作教程》1. BSP 制作⽅法BSP 的制作过程分为如下五个步骤:1. 复制通⽤模板2. 使⽤ CubeMX ⼯具配置⼯程3. 修改 BSP 中的 Kconfig ⽂件4. 修改构建⼯程相关⽂件5. 重新⽣成⼯程1.1 复制通⽤模板复制 rt-thread-4.0.0\bsp\stm32\libraries\templates\stm32f4xx重命名为 rt-thread-4.0.0\bsp\stm32\stm32f407-pz6808l1.2 使⽤CubeMX配置⼯程本⽂使⽤的是CubeMX 5.2版本配置RCC使能外部晶振使能调试使能UART时钟配置⼯程管理,⽣成到BSP框架⾥的⽂件夹下⽣成⼯程如下1.3 HAL库替换删除MDK-ARM⽂件夹复制Drivers到 rt-thread-4.0.0\bsp\stm32\libraries ⽂件下并重命名为 STM32F4xx_HAL_502从模板中复制SConscript⽂件1.4⽂件修改rt-thread-4.0.0\bsp\stm32\stm32f407-pz6808l\board\board.c⽤⽣成的main.c中的 SystemClock_Config 进⾏替换修改board/Kconfig⽂件修改链接脚本填写对应芯⽚的Flah和RAM⼤⼩,主要有些芯⽚有⾮连续RAM,填写RAM1⼤⼩即可修改主⼯程⽬录下的修改 SConstruct 链接⾃⼰的HAL库修改 board ⽬录下的 SConscript修改为需要制作BSP的芯⽚型号对应内容注意 stm32f4xx_hal_msp.c ⽂件查看是否包含有串⼝初始化 HAL_UART_MspInit ,没有则⽤MX重新⽣成,否则程序运⾏会出错(串⼝异常)1.5 使⽤Env⼯具⽣成⼯程打开模板 template.uvprojx ,对⼯程进⾏相关设置,这样以后每次⽂件的改动需要重新⽣成⼯程时,⼯程就不⽤再设置了;在 env 界⾯输⼊命令 menuconfig 对⼯程进⾏配置,并⽣成新的 rtconfig.h ⽂件。
STM32单片机应用与全案例实践stm32自学笔记第二版pdf
STM32单⽚机应⽤与全案例实践stm32⾃学笔记第⼆版pdf STM32单⽚机应⽤与全案例实践pdfhttps:///s/16WrivuLcHvLTwS__Zcwl6Q4rj3stm32⾃学笔记第⼆版 pdfhttps:///share/init?surl=hsjGIXm6k5ustm32⾃学笔记第⼀版pdf/down1/stm32zxbj_downcc.zip/soft/317742.html第1章如何学习STM32 (1)1.1 学习STM32必须具备的知识基础(1)1.2 STM32的基本架构和基本原理(2)1.2.1 什么是ARM (2)1.2.2 什么是STM32 (3)1.2.3 STM32的内部结构(3)1.2.4 典型型号—STM32F103ZET6 (5)1.2.5 STM32的时钟树(5)1.3 学习STM32的最好⽅法是什么(9)1.4 学习STM32需要哪些⼯具或平台(9)1.4.1 硬件平台(10)1.4.2 软件平台(11)1.5 STM32程序开发的模式(12)1.5.1 基于寄存器的开发模式(13)1.5.2 基于ST固件库的开发模式(20)1.5.3 基于操作系统的开发模式(26)1.5.4 三种编程模式的选⽤建议(27)思考题(27)第2章如何调试STM32 (28)2.1 STM32单⽚机的最⼩系统(28)2.2 STM32⼯程模板的建⽴(30)2.2.1 STM32的固件库(Standard Peripherals Library)(30)2.2.2 新建⼯程模板第⼀步—拷贝固件库⽂件(34)2.2.3 新建⼯程模板第⼆步—新建⼀个KEIL⼯程(35)2.2.4 关于创建⼯程模板的简单⼩结(41)2.3 程序的烧写(42)2.3.1 基于串⼝的程序下载(烧写)⽅式(42)2.3.2 基于JTAG(SWD)的程序下载(烧写)⽅式(44)2.4 程序的调试(46)2.5 模板的使⽤(48)2.6 三个GPIO输出的范例—STM32中实现延时的三种常⽤⽅法(48)2.6.1 我的第⼀个LED⼯程—基于延时函数的延时(48)2.6.2 我的第⼆个LED⼯程—SysTick中断延时(50)2.6.3 我的第3个⼯程—定时器中断延时(52)2.7 GPIO⼝的各种输出⽅式及其应⽤(55)2.7.1 功能要求(55)2.7.2 程序实现(56)2.8 本章⼩结(58)思考题(59)第3章 GPIO及其应⽤—输⼊(60)3.1 单功能按键输⼊(60)3.1.1 实现思想(60)3.1.2 具体程序(61)3.2 复⽤功能按键输⼊(64)3.2.1 按键复⽤的基本概念(64)3.2.2 程序实现举例(64)3.3 ⾮按键类开关信号输⼊及其实现(67)3.3.1 GPIO的输⼊⽅式及其特点(67)3.3.2 程序实现(68)3.4 GPIO输⼊输出⼩结(69)思考题(70)第4章 TIMER与PWM (71)4.1 关于STM32的定时器概述(71)4.2 STM32定时器的简单应⽤(72)4.2.1 按周期输出⽅波的例⼦(72)4.2.2 实现原理(72)4.2.3 具体程序(72)4.3 STM32定时器的复杂应⽤—检测输⼊⽅波的频率(77)4.3.1 STM32定时器的其他特性(77)4.3.2 本例设计要求(78)4.3.3 硬件接⼝设计与测量原理(79)4.3.4 具体程序(79)4.4 PWM原理及其应⽤⼀—⼀个LED呼吸灯的实现(84)4.4.1 PWM的基本概念及其基本应⽤(84)4.4.2 STM32的PWM的实现原理(84)4.4.3 基于PWM的LED呼吸灯的实现思路(88)4.4.4 呼吸灯的实现程序(89)4.5 PWM原理及其应⽤⼆—通过L298N控制电机转速(96)4.5.1 硬件设计(96)4.5.2 直流电机调速与调向的原理(97)4.5.3 程序实现(97)思考题(104)第5章 USART及其应⽤(105)5.1 串⾏通信模块USART的基本应⽤要点(105)5.1.1 STM32的USART及其基本特性(105)5.1.2 STM32的USART应⽤的基本要领(106)5.2 ⼀个USART的通信实现(STM32与PC)—查询法(107)5.2.1 功能要求(107)5.2.2 实现难点(108)5.2.3 程序实现(108)5.2.4 USART应⽤的有关事项(114)5.3 ⼀个USART的通信实现(STM32与PC)—中断法(115)5.3.1 功能要求及通信协议设计(115)5.3.2 程序算法(115)5.3.3 本例的源程序(116)5.4 两个USART的通信实现(124)5.4.1 功能要求与通信协议(124)5.4.2 接⼝设计(124)5.4.3 程序实现(125)5.5 USART应⽤⼩结(139)思考题(141)第6章⼈机界⾯—按键输⼊与液晶显⽰(142)6.1 STM32与液晶模块12864的接⼝实现(142)6.1.1 STM32与液晶模块12864的接⼝实现—延时法(142)6.1.2 STM32与液晶模块12864的接⼝实现—查询“忙”状态(153)6.2 基于液晶模块12864的菜单实现(173)6.2.1 程序中菜单的种类与菜单化程序的优势(173)6.2.2 基于液晶模块12864的菜单实现实例(173)6.3 矩阵键盘的接⼝实现(186)6.3.1 矩阵键盘的应⽤与程序设计思想(186)6.3.2 4×4矩阵键盘的硬件设计(186)6.3.3 演⽰程序(187)6.4 本章⼩结(198)思考题(199)第7章同步串⾏接⼝总线SPI与I2C (200)7.1 STM32的SPI (200)7.1.1 SPI概述(200)7.1.2 STM32之SPI总线的应⽤要点(201)7.2 SPI的接⼝应⽤及其实现(202)7.2.1 STM32与OLED12864液晶模块的SPI接⼝(202)7.2.2 STM32的SPI1与OLED12864的接⼝程序(203)7.3 STM32的I2C总线(223)7.3.1 I2C总线的基本概念(223)7.3.2 STM32的I2C总线应⽤要领(226)7.4 STM32的I2C总线的应⽤举例(227)7.4.1 具有I2C接⼝的DS3231时钟模块(227)7.4.2 STM32与DS3231时钟模块的硬件接⼝(229)7.4.3 STM32与DS3231的软件接⼝及其演⽰实例(229)7.5 I2C总线稳健性设计(247)思考题(247)第8章 ADC、DAC与DMA及其应⽤(248)8.1 STM32的DMA (248)8.1.1 STM32的DMA及其基本特性(248)8.1.2 STM32的DMA原理及其配置要点(249)8.2 STM32的ADC (251)8.2.1 STM32的ADC的基本特性(251)8.2.2 STM32的ADC的程序流程与编程要点(253)8.3 ⼀个三通道A/D转换的范例(254)8.3.1 功能要求与⽅案设计(254)8.3.2 实现程序(256)8.3.3 本例的中断法实现(263)8.4 STM32的DAC (266)8.4.1 DAC概述(266)8.4.2 DAC的配置要领(266)8.4.3 DAC应⽤实例(268)思考题(277)第9章⼯程实例—基于线性CCD的⼩车循迹系统(278)9.1 系统要求(278)9.2 线性CCD的原理及其使⽤(278)9.2.1 线性CCD传感器原理(279)9.2.2 线性CCD传感器应⽤(280)9.2.3 硬件接⼝(281)9.3 ⾃适应曝光的算法设计(281)9.3.1 ⾃适应曝光算法(281)9.3.2 模块化架构(283)9.4 具体程序(285)9.4.1 ⼯程⽂件视图—⽂件结构(285)9.4.2 程序源代码(286)9.5 系统性能实测(315)9.5.1 系统实物与测试环境(315)9.5.2 系统实测结果(316)思考题(318)参考⽂献(319)。
RT-Thread STM32系列BSP制作教程
项目文件夹说明通用库stm32/libraries 用于存放HAL 库以及基于 HAL 库的多系列通用外设驱动文件F1 系列 BSP 工程模板stm32/libraries/templates/stm32f10xF1系列 BSP 模板,可以通过修改该模板制作更多 F1系列 BSP特定开发板BSP stm32/stm32f103-atk-nano在 BSP 模板的基础上修改而成STM32 系列 BSP 制作教程为了让广大开发者更好、更方便地使用 BSP 进行开发,RT-Thread 开发团队重新整理了现有的 STM32系列的 BSP,推出了新的 BSP 框架。
新的 BSP 框架在易用性、移植便利性、驱动完整性、代码规范性等方面都有较大提升,在新的 BSP 框架下进行开发,可以大大提高应用的开发效率。
和 RT-Thread 以往提供的 BSP 不同,在新的 BSP 文件夹中将不会包含固件库、外设驱动等可以被多个BSP 引用的代码文件。
而是将这些通用的文件统一存放在 Library 文件夹中,通过在特定 BSP 中引用这些文件的方式,来包含 BSP 中所需的库文件或者驱动文件。
这种方式不仅大大提高了代码复用率,降低了 BSP 的维护成本,而且可以更方便地给开发者提供更丰富的驱动文件,让开发者可以更容易地找到自己需要的资源。
新的 BSP 框架还引入了 CubeMX 工具,可以使用该工具来对 BSP 中使用的外设引脚进行配置。
CubeMX 工具提供了图形化的配置界面,这种图形化的配置方式对开发者来说更加直观,不仅可以让开发者灵活地配置 BSP 中使用的资源,并且可以让开发者对资源的使用情况一目了然。
新 BSP 框架的主要特性如下:提供多系列 BSP 模板,大大降低新 BSP 的添加难度;每个 BSP 都配有齐全的驱动文件,开发者可以方便地使用所有驱动;开发者可以使用 CubeMX 工具对 BSP 进行图形化配置;1. BSP 框架介绍BSP 框架结构如下图所示:每一个 STM32 系列的 BSP 由三部分组成,分别是通用库、BSP 模板和特定开发板 BSP,下面的表格以F1 系列 BSP 为例介绍这三个部分:本次制作的 BSP 为 F1 系列,因此拷贝模板文件夹下的stm32f10x文件夹,并将该文件夹的名称改为stm32f103-atk-nano,如下图所示:在接下来的 BSP 的制作过程中,将会修改 board 文件夹内的配置文件,将 F1 系列的 BSP 模板变成一在 CubeMX 工程中将芯片型号为修改芯片型号为 STM32F103RBTx 。
STM32知识
STM32知识1、 SYSCLK时钟源有三个来源:HSI RC、HSE OSC、PLL2、 MCO[2:0]可以提供4源不同的时钟同步信号,PA83、 GPIO口有两个反向串联的二极管用作钳位二极管。
4、 ICode总线,DCode总线、系统总线、DMA总线、总线矩阵、AHB/APB桥5、在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟6、 STM32复位有三种:系统复位、上电复位、备份区域复位。
其中系统复位除了RCC_CSR中的复位标志和BKP中的数值不复位之外,其他的所有寄存器全部复位。
触发方式例如外部复位、看门狗复位、软件复位等;电源复位由于外部电源的上电/掉电复位或者待机模式返回。
复位除了BKP中的寄存器值不动,其他全部复位;备份区域复位的触发源为软件复位或者VDD和VBAT全部掉电时。
7、 (NestedVectored Interrupt Controller)NVIC嵌套向量中断控制器,分为两种:抢先式优先级(可嵌套)和中断优先级(副优先级,不能嵌套)。
两种优先级由4位二进制位决定。
分配下来有十六种情况:8、自动装载寄存器和影子寄存器:前者相当于51当中的溢出设定数值。
而影子寄存器顾名思义是影子,就是寄存器的另一分copy。
实际起作用的是影子寄存器,而程序员操纵的则是自动装载寄存器。
如果APPE位使能,表明自动装载寄存器的值在下一次更新事件发生后才写入新值。
否则,写入自动装载寄存器的值会被立即更新到影子寄存器。
9、计数器的数值与输出比较器相等时,翻转输出信号10、ARM公司只生产内核标准,不生产芯片。
ST、TI这样的公司从ARM公司那里购买内核,然后外加自己的总线结构、外设、存储器、时钟和复位、I/O后就组成了自己的芯片。
中,TPAD可以用一块覆铜区域来替代,通过电容的充放电常数来确定是否按下。
屏幕的对应表PAGE2单独列出来:13、USART可以操纵SPI设备。
STM32课件
STM32F103Rx 64 KB RAM
STM32F103Vx 64 KB RAM
STM32F103Z x
64 KB RAM
STM32F103Z x
64 KB RAM
5xUSART 5x16-bit timer 2xSPI, 2XI2C USB, CAN, PWM 2xADC, 2xDAC, I2S EMI (144 pins only)
32b 32b 32b 64b
Cycles
1 1 1 3-7*
▪ 硬件除法
– UDIV&SDIV – 指令执行需要2到12周期,取决与被除数与除数 – 两者越相近指令完成越快 – 指令可以被中断(丢弃/重启)
Cortex-M3 VS ARM7: 主要参数比较
体系结构 指令集 DMIPS/MHz 流水线 中断
STM32F10x的两条产品线
STM32F103 “增强型”系列
•在32位的FLASH MCU中性能最强 •整体信号处理方面一定程度上胜过DSP解决方案 •出众的控制和连通性 •非常适合低电压/低功耗的应用场合
STM32F101 “基本型”系列
•16位处理器的价格却拥有32位的性能 •STM32系列中的入门级产品 •非常适合低电压/低功耗的应用场合
**只有在Flash大于256KB(包含)的芯片上才包括DAC, EMI (144 pins), I2S, SDIO,图象传感器
STM32F103 “增强型”系列
Flash Size (bytes)
512 K
256 K
STM32F103Rx 64 KB RAM
STM32F103Vx 64 KB RAM
•相比于ARM7TDMI,Cortex-M3内核要快35%且减少了45%的代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
RT-Thread/STM32 说明本文是RT-Thread的STM32移植的说明。
STM32是一款ARM Cortex M3芯片,本文也对RT-Thread关于ARM Cortex M3体系结构移植情况进行详细说明。
D.1 ARM Cortex M3概况Cortex M3微处理器是ARM公司于2004年推出的基于ARMv7架构的新一代微处理器,它的速度比目前广泛使用的ARM7快三分之一,功耗则低四分之三,并且能实现更小芯片面积,利于将更多功能整合在更小的芯片尺寸中。
Cortex-M3微处理器包含了一个ARM core,内置了嵌套向量中断控制器、存储器保护等系统外设。
ARM core内核基于哈佛架构,3级流水线,指令和数据分别使用一条总线,由于指令和数据可以从存储器中同时读取,所以Cortex-M3 处理器对多个操作并行执行,加快了应用程序的执行速度。
Cortex-M3 微处理器是一个32 位处理器,包括13 个通用寄存器,两个堆栈指针,一个链接寄存器,一个程序计数器和一系列包含编程状态寄存器的特殊寄存器。
Cortex-M3微处理器的指令集则是Thumb-2指令,是16位Thumb指令的扩展集,可使用于多种场合。
BFI 和BFC 指令为位字段指令,在网络信息包处理等应用中可大派用场;SBFX 和UBFX 指令改进了从寄存器插入或提取多个位的能力,这一能力在汽车应用中的表现相当出色;RBIT 指令的作用是将一个字中的位反转,在DFT 等DSP 运算法则的应用中非常有用;表分支指令TBB 和TBH用于平衡高性能和代码的紧凑性;Thumb-2指令集还引入了一个新的If-Then结构,意味着可以有多达4个后续指令进行条件执行。
Cortex-M3 微处理器支持两种工作模式(线程模式(Thread)和处理模式(Handler))和两个等级的访问形式(有特权或无特权),在不牺牲应用程序安全的前提下实现了对复杂的开放式系统的执行。
无特权代码的执行限制或拒绝对某些资源的访问,如某个指令或指定的存储器位置。
Thread 是常用的工作模式,它同时支持享有特权的代码以及没有特权的代码。
当异常发生时,进入Handler模式,在该模式中所有代码都享有特权。
这两种模式中分别使用不同的两个堆栈指针寄存器。
Cortex-M3微处理器的异常模型是基于堆栈方式的。
当异常发生时,程序计数器、程序状态寄存器、链接寄存器和R0 - R3、R12四个通用寄存器将被压进堆栈。
在数据总线对寄存器压栈的同时,指令总线从向量表中识别出异常向量,并获取异常代码的第一条指令。
一旦压栈和取指完成,中断服务程序或故障处理程序就开始执行。
当处理完毕后,前面压栈的寄存器自动恢复,中断了的程序也因此恢复正常的执行。
由于可以在硬件中处理堆栈操作,Cortex-M3 处理器免去了在传统的C语言中断服务程序中为了完成堆栈处理所要编写的汇编代码。
Cortex-M3微处理器内置的中断控制器支持中断嵌套(压栈),允许通过提高中断的优先级对中断进行优先处理。
正在处理的中断会防止被进一步激活,直到中断服务程序完成。
而中断处理过程中,它使用了tail-chaining技术来防止当前中断和和未决中断处理之间的压出栈。
要点D.2 ARM Cortex M3移植移植要点ARM Cortex M3微处理器可以说是和ARM7TDMI微处理器完全不同的体系结构,在进行RT-Thread移植时首先需要把线程的上下文切换移植好。
通常的ARM移植,RT-Thread需要手动的保存当前模式下几乎所有寄存器,R0 – R13,LR,PC,CPSR,SPSR等。
在Cortex M3微处理器中,代码D - 1 线程切换代码; rt_base_t rt_hw_interrupt_disable();; 关闭中断rt_hw_interrupt_disable PROCEXPORT rt_hw_interrupt_disableMRS r0, PRIMASK ; 读出PRIMASK值,即返回值CPSID I ; 关闭中断BX LRENDP; void rt_hw_interrupt_enable(rt_base_t level);; 恢复中断rt_hw_interrupt_enable PROCEXPORT rt_hw_interrupt_enableMSR PRIMASK, r0 ; 恢复R0寄存器的值到PRIMASK中BX LRENDP; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);; r0 --> from; r1 --> to; 上下文切换函数;在Cortex M3中,由于采用的上下文切换方式都是在Handler模式中处理,; 上下文切换统一使用原来RT-Thread中断中切换的方式来处理rt_ hw_context_switch PROCEXPORT rt_hw_context_switchLDR r2, =rt_interrupt_from_thread ; 保存切换出线程栈指针STR r0, [r2] ; (切换过程中需要更新到当前位置)LDR r2, =rt_interrupt_to_thread ; 保存切换到线程栈指针STR r1, [r2]LDR r0, =NVIC_INT_CTRLLDR r1, =NVIC_PENDSVSETSTR r1, [r0] ; 触发PendSV异常CPSIE I ; 使能中断以使PendSV能够正常处理BX LRENDP; void rt_hw_context_switch_to(rt_uint32 to);; r0 --> to; 切换到函数,仅在第一次调度时调用rt_hw_context_switch_to PROCEXPORT rt_hw_context_switch_toLDR r1, =rt_interrupt_to_thread ; 设置切换到线程STR r0, [r1]LDR r1, =rt_interrupt_from_thread ; 设置切换出线程栈为0MOV r0, #0x0STR r0, [r1]LDR r0, =NVIC_SYSPRI2 ; 设置优先级LDR r1, =NVIC_PENDSV_PRISTR r1, [r0]LDR r0, =NVIC_INT_CTRLLDR r1, =NVIC_PENDSVSETSTR r1, [r0] ; 触发PendSV异常CPSIE I ; 使能中断以使PendSV能够正常处理ENDP; 在异常处理过程中发生线程切换时的上下文处理函数rt_hw_context_switch_interrupt PROCEXPORT rt_hw_context_switch_interruptLDR r2, =rt_thread_switch_interrput_flagLDR r3, [r2]CMP r3, #1BEQ _reswitch ; 中断中切换标识已置位,则跳到_reswitch MOV r3, #1 ; 设置中断中切换标识STR r3, [r2]LDR r2, =rt_interrupt_from_thread ; 设置切换出线程栈指针STR r0, [r2]_reswitchLDR r2, =rt_interrupt_to_thread ; 设置切换到线程栈指针STR r1, [r2]BX lrENDP; 中断结束后是否进行线程上下文切换函数rt_hw_interrupt_thread_switch PROCEXPORT rt_hw_interrupt_thread_switchLDR r0, =rt_thread_switch_interrput_flagLDR r1, [r0]CBZ r1, _no_switch ; 如果中断中切换标志未置位,直接返回MOV r1, #0x00 ; 清楚中断中切换标志STR r1, [r0]; 触发PendSV异常进行上下文切换LDR r0, =NVIC_INT_CTRLLDR r1, =NVIC_PENDSVSETSTR r1, [r0]_no_switchBX lr; PendSV异常处理; r0 --> swith from thread stack; r1 --> swith to thread stack; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from thread] stack rt_hw_pend_sv PROCEXPORT rt_hw_pend_svLDR r0, =rt_interrupt_from_threadLDR r1, [r0]CBZ r1, swtich_to_thread ; 如果切换出线程栈为零,直接切换到切换到线程MRS r1, psp ; 获得切换出线程栈指针STMFD r1!, {r4 - r11} ; 对剩余的R4 – R11寄存器压栈LDR r0, [r0]STR r1, [r0] ; 更新切换出线程栈指针swtich_to_threadLDR r1, =rt_interrupt_to_threadLDR r1, [r1]LDR r1, [r1] ; 载入切换到线程的栈指针到R1寄存器LDMFD r1!, {r4 - r11} ; 恢复R4 – R11寄存器MSR psp, r1 ; 更新程序栈指针寄存器ORR lr, lr, #0x04 ; 构造LR以返回到Thread模式BX lr ; 从PendSV异常中返回ENDP线程切换的过程可以用来图D - 1 正常模式下的线程上下文切换表示。
图D - 1 正常模式下的线程上下文切换当要进行切换时(假设从Thread [from] 切换到Thread [to]),通过rt_hw_context_switch 函数触发一个PenSV异常。
异常产生时,Cortex M3会把PSR,PC,LR,R0 – R3,R12压入当前线程的栈中,然后切换到PenSV异常。
到PenSV异常后,Cortex M3工作模式切换到Handler模式,由函数rt_hw_pend_sv进行处理。
rt_hw_pend_sv函数会载入切换出线程和切换到线程的栈指针,如果切换出线程的栈指针是0那么表示这是第一次线程上下文切换,不需要对切换出线程做压栈动作。
如果切换出线程栈指针非零,则把剩余未压栈的R4 – R11寄存器依次压栈;然后从切换到线程栈中恢复R4 – R11寄存器。
当从PendSV异常返回时,PSR,PC,LR,R0 – R3,R12等寄存器由Cortex M3自动恢复。