4,995
stars
+0+0+73
460
forks
88
watchers
–
prs
–
issues
0
releases
–
discussions
README
裸机编程指南 English | 中文 | Türkçe 本指南是为那些希望用GCC编译器和数据手册而无需其他任何东西就能开始为微控制器(单片机)编程的开发者而写的。本指南中的基础知识可以帮助你更好地理解像STM32Cube、Keil、Arduino和其他框架或IDE是怎么工作的。 本指南涵盖了以下话题: - 存储和寄存器 - 中断向量表 - 启动代码 - 链接脚本 - 使用make进行自动化构建 - GPIO外设和闪烁LED - SysTick定时器 - UART外设和调试输出 - printf重定向到UART - 用Segger Ozone进行调试 - 系统时钟配置 - 实现一个带设备仪表盘的web服务器 我们将使用Nucleo-F429ZI开发板(淘宝购买)贯穿整个指南的实践,每个章节都有一个相关的完整小项目可以实战。最后一个web服务器项目非常完整,可以作为你自己项目的框架,因此这个示例项目也提供了其他开发板的适配: - STM32 Nucleo-F429ZI - TI EK-TM4C1294XL - 树莓派 Pico-W 对其他板子的适配支持还在进行中,可以提交issue来建议适配你正在用的板子。 工具配置 为继续进行,需要以下工具: - ARM GCC, https://launchpad.net/gcc-arm-embedded - 编译和链接 - GNU make, http://www.gnu.org/software/make/ - 构建自动化 - ST link, https://github.com/stlink-org/stlink - 烧写固件 Mac安装 打开终端,执行: sh $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" $ brew install gcc-arm-embedded make stlink Linux(Ubuntu)安装 打开终端,执行: sh $ sudo apt -y install gcc-arm-none-eabi make stlink-tools Windows安装 - 下载并安装 gcc-arm-none-eabi-10.3-2021.10-win32.exe,安装过程注意勾选"Add path to environment variable"。 - 创建 C:\tools 文件夹 - 下载 stlink-1.7.0-x86_64-w64-mingw32.zip,解压 bin/st-flash.exe 到 C:\tools - 下载 make-4.4-without-guile-w32-bin.zip,解压 bin/make.exe 到 C:\tools - 添加 C:\tools 到 Path 环境变量 - 验证安装: - 下载这个仓库,解压到 C:\ - 打开命令行,执行: C:\Users\YOURNAME cd \ C:\ cd bare-metal-programming-guide-main\step-0-minimal C:\bare-metal-programming-guide-main\step-0-minimal make arm-none-eabi-gcc main.c -W -Wall -Wextra -Werror ... 需要的数据手册 - STM32F429 MCU datasheet - Nucleo-F429ZI board datasheet 微控制器介绍 微控制器(microcontroller,uC或MCU)是一个小计算机,典型地包含CPU、RAM、存储固件代码的Flash,以及一些引脚。其中一些引脚为MCU供电,通常被标记为VCC和GND。其他引脚通过高低电压来与MCU通信,最简单的通信方法之一就是把一个LED接在引脚上:LED一端接地,另一端串接一个限流电阻,然后接到MCU信号引脚。在固件代码中设置引脚电压的高低就可以使LED闪烁: 存储和寄存器 MCU的32位地址空间按区分割。例如,一些存储区被映射到特定的地址,这里是MCU的片内flash,固件代码指令在这些存储区读和执行。另一些区是RAM,也被映射到特定的地址,我们可以读或写任意值到RAM区。 从STM32F429数据手册的2.3.1节,我们可以了解到RAM区从地址0x20000000开始,共有192KB。从2.4节我们可以了解到flash被映射到0x08000000,共2MB,所以flash和RAM的位置像这样: 从数据手册中我们也可以看到还有很多其它存储区,它们的地址在2.3节"Memory Map"给出,例如:"GPIOA"区从地址0x40020000开始,长度为1KB。 这些存储区被关联到MCU芯片内部不同的外设电路上,以特殊的方式控制外设引脚的行为。一个外设存储区是一些32位寄存器的集合,每个寄存器有4字节的空间,在特定的地址,控制着外设的特定功能。通过向寄存器写入值,或者说向特定的地址写一个32位的值,我们就可以控制外设的行为。通过读寄存器的值,我们就可以得到外设的数据或配置。 MCU通常有许多不同的外设,其中比较简单的就是GPIO(General Purpose Input Output,通用输入输出),它允许用户将MCU引脚设为输出模式,然后置“高”或置“低”;或者设置为输入模式,然后读引脚电压的“高”或“低”。还有UART外设,可以使用串行协议通过两个引脚收发数据。还有许多其它外设。 在MCU中,一个相同外设通常会有多个“实例”,比如GPIOA、GPIOB等等,它们控制着MCU引脚的不同集合。类似地,也有UART1、UART2等等,可以实现多通道。在Nucleo-F429上,有多个GPIO和UART外设。 例如,GPIOA外设起始地址为0x40020000,我们可以从数据手册8.4节找到GPIO寄存器的描述,上面说 GPIOA_MODER 寄存器偏移为0,意味着它的地址是 0x40020000 + 0,寄存器地址格式如下: 数据手册显示MODER这个32位寄存器是由16个2位的值组成。因此,一个MODER寄存器控制16个物理引脚,0-1位控制引脚0,2-3位控制引脚1,以此类推。这个2位的值编码了引脚模式:'00'代表输入,'01'代表输出,'10'代表替代功能——在其它部分进行描述,'11'代表模拟引脚。因为这个外设命名为'GPIOA',所以对应引脚名为'A0'、'A1',等等。对于外设'GPIOB',引脚则对应叫'B0'、'B1',等等。 如果我们向MODER寄存器写入32位的值'0',就会把从A0到A15这16个引脚设为输入模式: c (volatile uint32_t ) (0x40020000 + 0) = 0; // Set A0-A15 to input mode 通过设置独立的位,我们就可以把