STM32学习笔记

操作系统有两种,用MMU的和不用MMU的:

CPU有两种,带MMU的和不带MMU的:

意法半导体微控制器页面可以看到ST公司有很多种芯片,涉及各种用途。

出货量最多的STM32系列是STM32F1系列,这个系列不带MMU,所以STM32不能运行Linux,但是可以运行RTOS。

所以学习方向有两个:

关于STM32F1系列芯片

STM32F1系列芯片是一种单片微型计算机,芯片内部不光有CPU,很多外设也被封装到里面了。以下是芯片内的资源:

image

STM32F1C6的片内Flash/RAM大小为32k/10k,STM32F1C8的片内Flash/RAM大小为64k/20k。

STM32F103系列芯片采用Cortex-M3内核的CPU,而Cortex-M3内核是采用的ARMv7架构

ARMv7架构是指用的什么指令集、寄存器多少个、地址总线多少位、冯诺依曼结构还是哈佛结构。Cortex-M3内核是指用什么样的电路来实现ARMv7架构,几级流水线、有没有分支预测。

注:冯诺依曼结构程序和数据都放在内存中。哈佛结构的程序和数据分开放,拥有独立的指令总线和数据总线。x86的CPU都采用冯诺依曼结构。大多数嵌入式芯片都是哈佛结构的。

附一张ARMv7架构与ARMv8架构的比较图:

image

STM32的启动流程

编译命令可以查看GCC手册

STM32有三种启动方式,可由跳线帽设置:

image

我们一般从Flash启动,当设置从Flash启动后,存储器会将0x00000000开始的一小段地址映射到Flash。换句话说,从0x00000000获取到的内容和从0x08000000获取到的内容是一样的。

CPU上电后会做下面两件事:

因为0x00000000开始的一小段地址已经被映射到了0x08000000,这里正是我们程序烧写的地址。也就是说,只有我们正确设置程序开头几个字节的内容,就可以初始化STM32的栈寄存器和PC寄存器。

链接脚本:

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 5K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 32K
}


SECTIONS
{
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
  } >FLASH

  .text :
  {
    . = ALIGN(4);
    *(.text)
  } >FLASH

  .data : 
  {
    . = ALIGN(4);
    *(.data)
  } >RAM
  
  .bss :
  {
    . = ALIGN(4);
    *(.bss)
  } >RAM
}

在链接脚本里isr_vector段在最前面,也就是说isr_vector段的内容会被烧录到0x08000000。

看一下汇编文件:

.section .text
.type Reset_Handler, %function

Reset_Handler:
  bl main
  bx lr
  
Default_Handler:
  b Default_Handler

.section .isr_vector,"a"
.type vectors, %object

vectors:
  .word 0x20002800
  .word Reset_Handler

isr_vector段开始的是两个值,第一个值0x20002800会被作为栈寄存器的值,Reset_Handler会被作为PC寄存器的初始值。换句话说,CPU会从Reset_Handler开始执行。Reset_Handler里面是一条跳转指令,跳转到了C语言的main函数中了。

烧录

STM32支持JTAG和SWD两种烧录/调试协议,JTAG协议需要20根引脚,SWD协议只需要4根引脚。因为SWD引脚少,所以我们常用SWD协议。

PC需要一个USB转SWD的转换器(烧录器、调试器),常见的有JLink、ST-Link、uLink、OpenJTAG。

PC上还需要一个烧录/调试软件,很多IDE中集成了烧录/调试功能,命令行烧录软件有:

STM32Cube工具

这是ST官方提供了很多开发工具。

安装的时候会出现权限问题,以STM32CubeMX为例:

下载:stm32cubemx

解压后按照Readme.html中执行

sudo xattr -cr ./SetupSTM32CubeMX-6.4.0.app

双击执行文件,在系统偏好与设置->安全与隐私中会出现陌生java程序,点击运行。再次双击运行即可。

OpenOCD调试程序

我们经常用OpenOCD烧录程序,但它不仅仅是个烧录软件,而是一个调试软件。烧录程序(写flash)仅是调试命令之一。

OpenOCD后会监听4444端口,我们用telnet链接4444端口,就可以执行调试命令。

调试的原理也很简单,设置个断点,然后打印寄存器或者内存的值查找问题。

常用调试命令就这几条:

halt 停止运行
bp 0x8000a68 2 hw 设置硬件断点
reg sp 查看寄存器
mdb 0x200027d0 48 查看从0x200027d0开始的内存,大小48个字节
step 单步运行
reset 复位,重新运行

对了,OpenOCD只能在汇编层面调试,设置断点和单步运行都是指汇编指令。如果读者想在C语言层面调试,在C语言上打断点和单步,可以用gdb,OpenOCD也是支持gdb的。

伪指令

CPU只认识指令集里的指令,伪指令最终都会转化成指令集里的指令。这说明伪指令是编译器的行为,与CPU无关。编译器定义这些伪操作、伪指令只是为了方便编程而已。

不同的编译器有自己的伪指令,我们常用GNU的汇编器,文档Using as里面详细介绍了GNU的汇编器所支持的伪指令。

指令集

在st官网能找到各种处理器内核使用的架构:Arm Cortex-M4概述

我们常用的Cortex-M3和Cortex-M4内核是Armv7-M和Armv7E-M架构的,在ARM官网关于该架构的手册《Armv7-M Architecture Reference Manual》详细介绍了该架构的指令集。


posted @ 2021-12-01 12:33:29
评论加载中...
发表评论