(A)通用寄存器 (B)链接寄存器 (C)程序计数器 (D)程序状态寄存器
(A)小端格式 (B)大端格式 (C)小端或大端格式 (D)没有正确答案
(A)小端格式 (B)大端格式 (C)小端或大端格式 (D)没有正确答案
13.所有的GPIO引脚有一个内部微弱的上拉和下拉,当它们被配置为( A )时可以是激活的或者非激活的
17.每个I/O端口位可以自由的编程,尽管I/O端口寄存器必须以( D )的方式访问
(A)结构更紧凑,减小芯片的尺寸
(B)连接更可靠,减小出错的概率
(C)减小延时,高效处理 最近发生的中断
(D)无所谓,没有特别的意思,远一点也没有关系
(A)只要响应优先级不一样就有可能发生中断嵌套
(B)只要抢占式优先级不一样就有可能发生中断嵌套
(C)只有抢占式优先级和响应优先级都不一才有可能发生中断嵌套
(A)所有中断和异常 (B)除了NMI外所有异常和中断
(C)除了NMI、异常所有其他中断 (D)部分中断
(A)STM32 ADC是一个12位连续近似模拟到数字的转换器
(B)STM32 ADC是一个8位连续近似模拟到数字的转换器
(C)STM32 ADC是一个12位连续近似数字到模拟的转换器
(D)STM32 ADC是一个8位连续近似数字到模拟的转换器
(A)采样—量化—编码(B)量化—采样—编码
(C)采样—编码—量化(D)编码—采样—量化
(C)按通道配置采样时间(D)数据对齐方式与内建数据一致
(C)性能线设备的转换时间:28MHz时为1us
(D)访问线设备的转换时间:56MHz时为1us
36.以下为STM32的GPIO端口配置寄存器的描述,在GPIO控制LED电路设计时,要使最大输出速度为10MHz,应该设置(
37.以下为GPIO端口配置寄存器的描述,在GPIO控制LED电路设计时,要使最大输出速度为2MHz,应该设置MODE[1:0]值为(
38.. 已知TIM1定时器的起始地址为0x,则定时器1的捕获/比较寄存器1的地址为(
39.已知TIM1定时器的起始地址为0x,则定时器1的捕获/比较寄存器2的地址为(
51.STM32中,1个DMA请求占用至少(B )个周期的CPU访问系统总线时间。
52.STM32的USART根据( A)寄存器M位的状态,来选择发送8位或者9位的数据字。
53.下面不属于STM32的bxCAN的主要工作模式为(C )。
A.初始化模式 B.正常模式
C.环回模式 D.睡眠模式
A、系统内核小 B、专用性强
C、可执行多任务 D、系统精简
55.嵌入式系统有硬件和软件部分构成,以下( C)不属于嵌入式系统软件。
58.在ADC的扫描模式中,如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到(
64.STM32的外部中断/事件控制器(EXTI)支持(C
)寄存器M位的状态,来选择发送8位或者9位的数据字。
66.DMA控制器可编程的数据传输数目最大为(A)。
67.每个DMA通道具有(A )个事件标志。
68.STM32中,1个DMA请求占用至少( B)个周期的CPU访问系统总线时间。
5.Contex-M3系列处理器内核采用了冯诺依曼结构的三级流水线。( 错 )
7.STM32处理器的LQPF100封装芯片的最小系统只需7个滤波电容作为外围器件。(dui )
8.Cortex-M3在待机状态时保持极低的电能消耗,典型的耗电值仅为2?A。( 错 )
12.高寄存器可以被所有的32位指令访问,也可以被16位指令访问。( 错 )
16.所谓不可屏蔽的中断就是优先级不可调整的中断。( 错)
17.向量中断控制器只负责优先级的分配与管理,中断的使能和禁止和它无关。( 错 )
18.Cortex-M3体系架构中,有了位带位操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。(对)
19.Cortex-M3体系架构中,有两个区中实现了位带:一个是 SRAM区的最低 1MB范围,第二个则是片内外设 区的最低 1MB范围。(对)
22.STM32的串口既可以工作在全双工模式下,也可工作在半双工模式下。( 对)
23.STM32的串口既可以工作在异步模式下,也可工作在同步模式下。(对)
24.每个I/O端口位可以自由的编程,尽管I/O端口寄存器必须以32位字的方式访问。(对)
25.所有的GPIO引脚有一个内部微弱的上拉和下拉,当它们被配置为输入时可以是激活的或者非激活的。( 对)
26.所有的GPIO引脚有一个内部微弱的上拉和下拉,当它们被配置为输出时可以是激活的或者非激活的。(错 )
27.端口输入数据寄存器的复位值为H。( 对)
28.端口输入数据寄存器位[15:0]是只读的,并且仅能按字访问,它们包含相关I/O端口的输入值。(对 )
29.端口输入数据寄存器位[7:0]是只读的,并且仅能按字访问,它们包含相关I/O端口的输入值。( 错)
30.固件包里的Library文件夹包括一个标准的模板工程,该工程编译所有的库文件和所有用于创建一个新工程所必须的用户可修改文件。( 错)
31.从是否可编程的角度 ,中断可分为固定优先级中断和可调整优先( 对 )
32.从某种意义上说,异常就是中断。(对 )
33.所谓不可屏蔽的中断就是优先级不可调整的中断。( 错)
34.向量中断控制器只负责优先级的分配与管理,中断的使能和禁止和它无关。(错)
35.中断的优先级和它在中断向量表里的位置没有关系。( 错)
36.当抢占式优先级不一样时,一定会发生抢占。( 错)
37.向量中断控制器允许有相同的优先级。( 对)
38.如果两个中断的抢占式优先级相同,则按先来后到的顺序处理。(对 )
39ADC主要完成模/数转换功能。( 对)
40.STM32 ADC是一个12位的连续近似模拟到数字的转换器。( 对)
41.ADC转换器在每次结束一次转换后触发一次DMA传输。(对)
42.由AD的有限分辨率而引起的误差称为量化误差。(对)
43.转换速率是指完成一次从模拟到数字的AD转换所需的时间。( 对)
45.如果规则转换已经在运行,为了注入转换后确保同步,所有的ADC的规则转换被停止,并在注入转换结束时同步恢复。( 对)
2.当STM32的I/O端口配置为输入时, 输出缓冲器 被禁止, 施密特触发输入被激活。根据输入配置(上拉,下拉或浮动)的不同,该引脚的 弱上拉和下拉电阻 被连接。出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器,对 输入数据寄存器的读访问可得到I/O状态。
来实现引脚的重新映射。
位所选的模式,转换的启动可以是ADC1主和ADC2从的交替触发或同时触发。
22.系统计时器(SysTick)提供了1个 24位,降序,的计数器,具有灵活的控制机制
位自动装载计数器构成。
只能在重复向下计数达到0的时候产生。这对于能产生PWM信号非常有用。
将被选为系统时钟。当时钟源被直接或通过PLL间接作为系统时钟时,它将不能被 停止 。只有当 目标时钟源准备就绪了(经过启动稳定阶段的延迟或PLL稳定),才可以从一个时钟源切换到另一个时钟源。在被选择时钟源没有就绪时,系统时钟的切换 不会发生。
个字节的用户应用程序数据。
39.在DMA处理时,一个事件发生后,外设发送一个请求信号到 DMA控制器 。DMA控制器根据通道的 优先权 处理请求。
40.DMA控制器的每个通道都可以在有固定地址的 外设寄存器和 存储器地址
1、什么是嵌入式系统?嵌入式系统一般由哪几部分构成? P1
2、ARM v7的体系结构可以分为哪几个子版本(款式),分别应用在什么领域?P12
3、Cortex-M3的处理器有那两种工作模式和状态?如何进行工作模式和状态的切换?P18
4、Cortex-M3的存储空间可以分为哪几个部分,每一部分的地址范围是怎样的?P26
5、什么是位绑定区、位绑定别名区?它们有怎样的关系?P30~31
6、基于CMSIS标准的软件架构分为那几层?其中的CMSIS层一般由哪几部分组成?P66
7、简述STM32固件库命名规则。
8、STM32共有那几种基本时钟信号?
9、简述设置系统时钟的基本流程。P86
10、STM32的GPIO的配置模式有那几种?如何进行配置模式的配置?P93
11、简述STM32的不同复用功能的重映射功能。
12、简述嵌套向量中断控制器(NVIC)的主要特性。P38
13、简述STM32的优先级划分与抢占的过程。P110
15、如何设置STM32的串口的波特率。P136
16、STM32高级定时器有哪些功能?
17、已知STM32的系统时钟为72MHz,如何设置相关寄存器,实现20ms定时?
18、简述DMA控制器的基本功能。
19、、请描述DMA通道的工作模式、工作原理。
20、简述STM32的ADC系统的功能特性。
1、在一个STM32点亮LED的程序中,部分代码如下:
解:设置引脚、设置速率、设置模式
(2)分析该程序,LED分别连接在哪些IO引脚上,当引脚输出高电平时,是点亮还是熄灭LED?
(3)分析循环点亮LED代码,补充相应的注释。
2、利用STM32的GPIO接口及其操作,实现4个LED按照LED1、LED2、LED3、LED4的顺序循环显示。硬件连接图如图所示。
3、已知系统时钟为72MHz,采用定时器TIM1产生周期为100ms的定时时间间隔并通过LED发光二极管指示定时过程。P156
如果要做嵌入式Linux,我们首先要在板子上烧写的往往不是kernel,而是u-boot,这时需要烧写工具帮忙。当u-boot烧写成功后,我们就可以用u-boot附带的网络功能来烧写kernel了。每当板子上电时,u-boot一般会被加载到内存的前半段,如果我们的kernel之前就已经被烧写到开发板了,那么u-boot会加载kernel到内存的后半段并跳转到kernel的起始地址处执行(或者直接跳转到kernel的起始地址处执行,如果kernel可以直接在flash上执行的话。)
如上图所示,绿色部分为u-boot,红色部分为kernel。
举个极端的例子:没有grub的话,我们就没办法做windows和linux双系统了。这就是最大的好处。
然而对于嵌入式,我倒是说不出什么上得了台面的理由,根据个人喜好,我倒是有3点理由:
1、不用再求助烧写工具了;
2、方便使用GNU交叉编译工具;
现在,我的笔记本就可以轻松一下了,只需单开fedora/ubuntu就能工作啦!
以下是源码和工程的下载链接:
接下来,我们将分为三部分叙述:
接下来我们将建立两个工程,一个是用来编译kernel,一个用来编译loader(姑且命名为“my-boot”)。首先,我们先把“my-boot”和kernel都编译好,并通过烧写工具把“my-boot”烧写进stm32的flash中。然后,我们就可以重启stm32,并使之运行“my-boot”。“my-boot”等待接收烧写kernel的起始命令,当我们通过串口向“my-boot”发送了烧写起始命令后,“my-boot”将把串口设置为DMA模式,并等待我们发送kernel的bin文件。接着,我们再通过串口传送kernel的bin文件。传送结束后,kernel也就被写入stm32的RAM中了,同时“my-boot”把串口切换回通常的窗口通信模式。此时,芯片的控制权依旧被掌控在“my-boot”手中,不过,如果我们再向串口发送一条启动kernel的指令,那么stm32将跳转到kernel代码处执行。至此,我们的目标达成。
我们的kernel很简单,只有一个源文件,其功能就是不停的闪led。程序参考了博客/sky1991/archive//2722640.html的“例子一”,并加以修改与简化,代码给出如下:
1 ;RCC寄存器地址映像 81 ENTRY ;指示程序从这里开始执行 83 CPSID I ;关中断 101 ;时钟系统设置 134 ;选择PLL时钟作为系统时钟 203 ALIGN ;通过用零或空指令NOP填充,来使当前位置与一个指定的边界对齐
该延时程序是“C51式”的延时,就是纯粹的让CPU空跑n个周期,这里是“DelayTime=“。“”是随便设的一个数,只是为了让眼睛和耐性都能接受,时钟频率变化之后,这个数字可以自行的、随性的去进行调整。
(3)LED翻转程序:
该LED翻转程序以“r5”寄存器为标志,“r5”为0或1时,分别使PA.8输出不同的电平(此处PA.8对应开发板上一个红色LED)。
一般MDK会生成hex文件,但不生成bin文件,所以我们还要给MDK加一些设置:
先找到fromelf.exe文件(一般在你的MDK安装目录里的bin目录里),然后如下图输入,
重新编译之后,于是我们就得到kernel的bin文件了,即kernel.bin,留着备用。
此处的kernel是可以独立运行的,所以不妨将该程序通过烧写工具烧写进开发板验证一下。
“my-boot”以中的代码为基础,并将之整理了一下,把各个源文件分类到了不同的目录。
如图,除了obj目录是存放编译时所用的中间文件和hex文件外,其余4个目录都存放源码。
(1)arch目录:其中的源码均是和CPU架构相关,如中断代码、串口初始化、启动代码等;
(2)include目录:所有的头文件都在这里;
(3)kernel目录:包含主函数、任务调度、延时相关的源码;
Task1:和kernel的功能一样,也是不断的闪led(最好是不同于kernel所使用的led),用来指示程序依旧正常运行,其功能很单纯;
TaskBH:接受串口发送过来的相关命令,并向串口打印信息以提示命令发送成功。特别是当收到“startos”指令后,会置位变量“GotoKernelFlag”,以致后续代码将跳转到kernel运行,该任务是三个任务中最复杂的一个;
其实以上三个任务的负担并不重,身上担子最重的时串口中断程序:
串口通信遵循一个自定义的协议,协议内容如下:
将以下串口中断程序与TaskBH结合着看,串口接受三种命令:
第一种:BURN命令:
协议信息16进制表示为
该命令就是在通知开发板:“我要发送kernel了呦,赶紧准备接驾。”
这时,串口中断程序会启动串口的DMA模式,并开启DMA中断。
关于命令中的地址“0x”,该值是设计为以后烧写flash做准备的,但现在我们只将kernel写入SRAM,所以现在还没有特别的作用,任意值都可以。
这个命令发送之后就要小心了,紧跟着必须向串口发送kernel的bin文件。发送结束后,DMA中断会被触发,并且会调用“LED1TURN()”去翻转另一个LED(不同于Task1的LED),用以指示kernel已经被写入RAM。
Note:看了以下代码后,其实对于"BURN”这个命令来说,校验和是形同虚设的,为了图方便就偷了个懒……
协议信息16进制表示为
开发板接收到该命令后,TaskBH会将变量“GotoKernelFlag”设为1。之后,当SysTick中断程序(如下)再次执行时,将会调用“ModifyPC()”(这里的“PC”不是指“Personal Computer”,而是指PC指令寄存器哦)。这个函数很难懂。如果能理解这个函数,那么loader加载kernel的原理也就等于理解了80%了。我们不妨来试着啃一啃这块硬骨头!
“ModifyPC()”是嵌入C语言式的汇编代码。其作用就是:
修改 PSP中存储的、“当前被SysTick中断的任务”的 PC指针,使之等于kernel代码的起始地址。当该任务再一次被调度时,由于PC被换成了kernel代码的起始地址,所以就进入了kernel。
于是,两个问题出现了:
(1)kernel的起始地址是什么?
(2)被SysTick中断的任务的PC又在哪?
或许有人会认为:“kernel在DMA传送时,被放进‘SRAM_Buffer’这个缓冲区了,那么kernel的起始地址不就是‘SRAM_Buffer’吗?”(一开始我也是这么想的……)
可惜,真正的“起始地址”要比SRAM_Buffer在靠后一点点。
不妨在MDK5下,在kernel工程里打开Debug,接着再用二进制编辑器打开kernel.bin,这样就能看出蹊跷了。
stm32烧写程序时,是将代码烧至起始地址为0x的flash中,并在开机运行时也是直接从flash启动。
看到没有,我们开机时的第一条命令是“CPSID I”,对应的指令地址为0x,机器码为“B672”。
再用二进制文件打开kernel.bin后,发现果然是“B672”(二进制文件为“小端法”表示,所以是“72 B6”)。
所以,我们的kernel代码的起始地址,确切来说是第一条命令“CPSID I”的地址为“SRAM_Buffer + 0x10”。
“既然代码烧写进地址为0x起始的地方,那么第一条指令为什么确实0x呢?”
第二个问题,“被SysTick中断的任务”的PC到底在哪儿呢?
首先我们要知道,任务使用的是PSP(可参考“PendSV_Handler”的汇编代码)。确认了这点之后,我们就可以继续往下讲了。
根据《Cortex-M3权威指南》--“chap09中断的具体行为”--“入栈”,当SysTick中断发生时,PSP会将发生如下图的变化。
也就是说,当SysTick中断发生时,CPU会自动将被中断任务的R0-R3,R12,LR,PC,xPSR这8个寄存器装载进PSP的后续存储空间,并且PSP最后将指向被中断任务R0寄存器的存储地址。
那么被中断任务的PC寄存器的存储地址就找到啦:PSP+24!如果该任务再次被调度执行,其第一条指令就是地址“PSP+24”存储的内容,如果我“偷偷的”把这个存储内容换成kernel代码的起始地址(确切来说,是第一条指令所在的地址),那么当该任务再次被调度时,原来的任务摇身一变,就成了kernel。
那么,ModifyPC()函数的代码就比较容易理解了。
协议信息16进制表示为
该命令将对TaskDMA_Print的行为产生影响(代码如下)。
不难看出,只有当“ReadDMAFlag不为0时,该任务才会打印缓冲区SRAM_Buffer的内容。而在TaskBH中,上述命令会使变量“ReadDMAFlag”在0,1之间翻转,所以该命令也就起到控制打印“SRAM_Buffer”内容的作用。
“284”?这个数字怎么这么莫名其妙?其实它表示的是kernel的大小(如下图),同时它也决定了缓冲区SRAM_Buffer的大小。
如果我编译了一个新的kernel,大小不再是284字节了怎么办?
实在对不住!“my-boot”中的这个宏也要改成相应的数字。当然,这确实是个不合理的地方,但现在为使代码尽可能简洁,所以就未做完善这方面的工作了,暂且辛苦一下。
为了使用stm32的函数库,且避免编译出错,故定义该宏。具体内容可查询“stm32f10x.h”第8296行附近的代码。
(3)库函数文件:
如果stm32的型号不是stm32f10x系列的,需要自备相应的函数库。
(2)向stm32开发板发送烧写命令:
命令发送之后,串口工具会打印信息“Addr: 8004000”。而且还有一个变化,那就是另一个LED灯亮了/灭了(如果存在第二个led的话)。
注意,是16进制发送。
这时我们会发现,刚刚亮了/灭了的LED现在又灭了/亮了(如果存在第二个led的话)。
(4)打印刚刚烧进SRAM中的kernel命令(可选):
该命令发送一次,就会打印一次“###ls###”,并且跟后会打印SRAM中的内容。如果该命令只发送一次,那么SRAM中的打印将每隔2秒打印一次,直到再一次发送该命令为止。
所以图中有2个“###ls###”,第二个就是终止打印的。
这时你将会看到开发板在运行kernel的程序啦!
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。