关于使用STM32和RIOT操作系统示例编程现代微控制器的第一篇演讲的摘要。 讲座于周六从MIREA信息技术学院在D楼4层的礼堂举行,讲座时间为12时50分。课程本身为1.5个小时,三星大学物联网实验室的实际课程为3个小时,以讲座为主题。你好,Giktayms! 按照我们的承诺,我们将开始发布在MIREA IT研究所提供的讲义。 根据第一期介绍性演讲的结果,我们决定略微改变课程的结构-代替计划的两节5课,而不是计划的7课。 这样就可以轻松地解决一些支持性问题,并且摘要文章将在整个三月和四月的每周一次出现在GT上,而不是以前计划的一周之内。
但是,不可能在7个讲座中完全涵盖如此广泛的主题,因此该演讲将在某些地方成为论文的主题-尽管对此进行了补偿,但我们将尝试指出那些想要更深入地独立研究该问题的方向。
该课程是为熟悉C语言和电子与电气工程基本概念的二,三年级学生设计的。 不需要事先了解微控制器。
本课程的目的是开发技能,使您可以在现代水平上自由地使用ARM Cortex-M内核上的微控制器,并且如果有这样的愿望,则可以进一步加深您的知识。

今天的讲座是第一堂课,因此它将了解一般概念:什么是微控制器,为什么需要它,什么是固件以及如何获得它,为什么需要操作系统,最后是如何使用git。 本课程的结果是您自己的带有操作系统源代码的GitHub存储库,以及在本地计算机上成功配置的构建环境。
微控制器
简而言之,微控制器是“片上系统”的经典示例,它既包括处理器内核,又包括一组辅助和外围设备,这使得微控制器在许多情况下可以完全自给自足。

在典型的微处理器中,类似于任何PC或智能手机上的微处理器,几乎所有可归因于辅助模块的模块(电源,时钟,甚至基本外围设备)都移到了芯片本身之外,尽管微处理器在没有它们的情况下也可以工作不能。
相反,在微控制器中,在与内核相同的芯片上,不仅实现了其操作所需的子系统,而且还实现了各种实际任务中可能需要的大量外围设备。 而且,许多微控制器制造商彼此竞争的不是核心性能或存储容量,而是外围设备的丰富度和功能。
微控制器与微处理器并行开发已经有一段时间了-例如,工业产品中仍然发现的Intel 8051架构是1980年开发的。 在某些时候,它们的发展方向开始与微处理器相交-例如,较旧型号的微控制器具有用于外部RAM的接口,并且微处理器制造商将越来越多的外围设备集成到芯片上(足以回想起“个人计算机”诞生之初,甚至拨打了外部缓存)微电路)-但无论如何,它们仍然是两个明显不同的发展分支。
实际上,创建微控制器的目的是降低成本和使各种需要较小计算能力的设备小型化:与使用4-5个单独的芯片组相比,使用一块足以为其运行提供动力的芯片可以大大简化印刷电路板的设计和制造。 。
当然,微控制器有其自身的局限性-从技术上讲,不可能将一个大型PC占用一块相当大的板子封装在一块芯片中。
- 工作频率很少会超过200 MHz,并且更经常会在几十兆赫兹的范围内。
- RAM的数量在几兆字节以内,并且通常在几十千字节左右。
- 程序存储器的大小在几兆字节以内,并且通常在几十到几百千字节之间。
作为课程的一部分,我们将使用STM32L151CC微控制器,它们具有32 KB的RAM,256 KB的ROM和最大工作频率为32 MHz(Nucleo-L152RE板上的芯片稍稍重要-80 KB的RAM和512 KB的ROM)。
记忆
通常,微控制器内部可以有四种类型的存储器:
- 永久存储器 (闪存)用于存储用户程序,有时还用于存储微控制器本身的某些设置。 如果在指定微控制器的特性时,他们在不指定哪一个的情况下写入了内存量-通常,这与闪存有关。 停电后,闪存的内容不会重置,正常情况下,闪存中的信息存储时间通常至少为10年。
- RAM用于执行用户程序并存储“瞬时”数据。 重新启动或关闭电源时,RAM始终会重置,进入某些睡眠模式时也可能不会保存。 在微控制器中,程序存储器和数据存储器之间通常没有明确的分隔-因此,可以找到术语“从RAM执行”,这意味着RAM中不仅存在数据,而且还存在程序本身。 但是,这些都是非常特殊的情况。
- EEPROM 。 它也指只读存储器,但其特性与闪存显着不同。 闪存有两个很大的缺点,这使得从程序中保存一些当前数据非常不便-首先,闪存对同一单元的覆盖次数有限,其次,通常可能只在整页中使用闪存。大小为数百个字节,即使您只需要覆盖一个字节也是如此。 EEPROM没有这些缺点-使用寿命通常长十倍(从10万次重写到100万次重写),并且可以在每个字节中单独使用。 因此,EEPROM用于永久存储由程序本身生成的数据(测量档案,程序设置等),其典型体积为千字节单位,但并非在所有控制器中都使用。
- 系统内存 只读存储器区域,用户无法访问以进行记录,但记录在微控制器的生产中。 通常,它们包含引导加载程序可执行代码(如下所述),但是也可以存储一些校准常数,序列号甚至用于与外围设备一起使用的辅助库。
您可以在其数据表中查看特定控制器的内存组织。 例如,此处是
STM32L151CC上的
数据表 ,在此页上提供了该系列的存储卡。
可以很容易地注意到,我们所讨论的所有四种类型的存储器都只占卡的一小部分-并且在大多数图片中,列出了控制器中所有可用外围设备的列表。
寄存器
事实是,与微控制器的所有外围设备及其所有设置的所有通信(通常是所有通信)仅使用以下两种操作即可进行:
微控制器内部的所有内容都必须映射到某个地址。 这些地址称为
寄存器 (不要与处理器寄存器混淆-处理器的寄存器包含处理器在其上执行操作的数据;我们所讨论的寄存器包含一些特殊的数据,这些数据专门映射到微控制器的各种硬件单元的状态)。
因此,例如,如果我们希望“ 1”出现在微控制器的端口A的第三脚(PA2,从头开始编号),则需要在位于0x4002014的寄存器的第三位中写入“ 1”。 而且,如果将此支路配置为输入,并且相反,我们想找出其上的值,则需要读取地址0x40020010处寄存器的第三位。
是的,要向控制器指示该支路是输入还是输出-您需要将相应的值写入地址0x40020000的相应位。
这是理解微控制器操作的重要一点:处理器内核本身负责的绝对不是计算操作的所有事情都是通过写入或读取该寄存器或该寄存器来完成的。 无论哪种库都是从上面被欺骗到您的程序中的-最后,所有这些都归结为寄存器。
当然,使用数字地址非常不便,因此,对于Cortex-M内核上的每个微控制器,都有一个CMSIS库(Cortex微控制器软件接口标准),对于我们而言,最重要的组件是标头文件,该标头文件描述了特定控制器中可用的寄存器,并使它们相对易读。名称。
使用CMSIS,上面用PA脚描述的操作将如下所示:
int pin_num = 2; /* PA2*/
GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* PA2 */
GPIOA->MODER |= 0b01 << (pin_num*2); /* PA2 01 — */
GPIOA->ODR |= 1 << pin_num; /* PA2 1 */
GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* PA2, */
uint32_t pa2_value = GPIOA->IDR & (1 << pin_num); /* PA2 */
, —
Reference Manual (, , , RM0038, STM32L1). , 900 RM0038 — , 1500-2000 . -, , — .
, — . , , «» .
, , — , - ( 1 , , , 1 , , ), .
STM32 Standard Peripherals Library, StdPeriphLib, SPL. , ST LL, — ,
LibOpenCM3. , STM32 .
, SPL , , , GPIO_Init GPIO_Write.
, , SPL — .
, SPL «» , ,
STM32 CubeMX. (, , ) STM32.
, , « , - » — « , ». SPL, , , , SPL , — SPL , . , .
, , , - , , , STM32L1 ATSAMD21 , SPL, .
SPL — , , , SPL.
, SPL — «» . , :
- . , (RTC), — - , ( ) (, ), . -, .
- . , . Arduino loop() , . loop() , , . ( , ).
- . , , — , : -, , , . - — , , , , . , API.
— — .
, ( 5-20 ), , 70 % .

, , SPL.
RIOT OS, STM32 — SPL .
: , , , , SPL . , SPL , , STM32, , .
, :

, RIOT OS - (IDE) — , , IDE, (, , Arduino IDE — ; , , ).
, , , , « , , ».
, , Arduino IDE, IDE, — .

, RIOT OS , : HAL cpu ( , , AVR PIC32), — boards, — drivers, — core, — sys, — examples.
, — , ( ) , , , , . — , , .
https://github.com/unwireddevices/RIOT/tree/mirea — RIOT OS, Unwired Devices STM32L1, , , , .
Github, «Clone/Download» «Download ZIP», . GitHub, «Fork» — , .
GitHub Git — , .
, , - , «Hello world» :
#include <stdio.h>
int main(void)
{
puts("Hello World!");
printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
printf("This board features a(n) %s MCU.\n", RIOT_MCU);
return 0;
}
example/hello-world main.c ( ).
, , , . - .
1. Windows 8 . , MinGW, .
. , Git/GitHub
Git for Windows, MinGW. MinGW, MinGW .
, Windows 7 Windows 8, , .
2. Windows 10. Microsoft Store, Ubuntu . Ubuntu Windows, « Windows», « Windows Linux» .
Ubuntu, , MinGW.
(: 64- Linux!), Ubuntu, :
cd /opt
sudo tar xf /mnt/c/Users/vasya/Downloads/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:$PATH
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:$PATH
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:\$PATH" >> ~/.bashrc
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:\$PATH" >> ~/.bashrc
.bashrc, Ubuntu. $ >> — , ( ) .bashrc.
arm-none-eabi-gcc --version , , — 7.2.1 ( ).
Git ssh-keygen, ( Ubuntu Windows cat ~/.ssh/id_rsa.pub, Enter — ) GitHub. GitHub git.
NB: Linux, : , Tab ( cd /opt/gcc- cd /opt/gcc-arm-none-eabi-7-2017-q4-major). , — , . , Tab .
NB: Windows , , Windows, Documents/git/RIOT. - MinGW /c/Users/vasya/Documents/git/RIOT, - Ubuntu — /mnt/c/Users/vasya/Documents/git/RIOT. , , , Windows, Notepad++.
3. Linux. Windows 10, , Microsoft Store . gcc-arm-none-eabi — .
, RIOT examples/hello-world,
make.
, , unzip ( Windows 10 ), make . Windows 10 ( ):
sudo apt-get install unzip make
make — , «
make clean && make»: , . , - , — , .
NB: RIOT hello-world native, , , x86. unwd-range-l1-r3, stm32,
Building application "mirea" for "unwd-range-l1-r3" with MCU "stm32l1".
- , make — . mirea.elf ( - ).
- :

, , , , , .
, GPIO, — , , — , .
P.S. — 360- ( : « » , , - ):
