基础架构

  • 存储器映像空间(最大4GB)

img

  • MMIO映射区域(不是真实的存储器)
    • BOOT区
    • 总线仲裁器发现要访问BOOT区时,会通过总线仲裁(主FLASH、系统FLASH、SRAM三选一),然后转接到对应地址
    • 核外设备寄存器
    • 总线仲裁器发现要访问该区时,会转接到外设端口
    • 核内设备寄存器
    • 总线仲裁器发现要访问该区时,会转接到内设端口
    • Bit-Band区(位段/位带)与Bit-Band别名区
    • SRAM和FLASH中各有一个位带区,这个区域内可以支持对bit操作
    • 位带操作:访问位带别名区的对应byte==访问位带区的对应bit(注意不能直接对位带区操作)
    • 进行位带操作时,必须使用volatile:否则可能因为优化产生一个缓存,导致不能立即进行写入。
    • 位带与位带别名区的映射:$位带别名地址 = 位带别名基址 + (字节偏移 × 32) + (位编号 × 4)$
  • ROM:主FLASH、系统FLASH(SystemMemory)、选项字节FLASH
  • RAM:SRAM

  • 内存外存分类

  • 内存:片内RAM,片内FLASH(主FLASH、系统FLASH、选项字节FLASH),核内设备寄存器
  • 外存:FMC存储(片外RAM、片外FLASH),核外设备寄存器

  • 总线结构

  • ICode总线(ICache):FLASH
  • DCode总线(DCache):FLASH
  • System总线:总线仲裁器(master访问总线矩阵中连接的slave(直连的内设/外设总线))
    • AHB总线(高速外设):高速外设SDIO、RCC、APB总线
    • APB2总线(中速外设):ADC、GPIO、SPI、TIM、USART的高速端口
    • APB1总线(低速外设):ADC、GPIO、SPI、TIM、USART的低速端口
  • DMA总线:总线仲裁器

  • 主FLASH与SRAM构成

  • 主FLASH:初始化段、只读数据段(.rodata)、代码段
    • 初始化段:待初始化的.data和.bss段
    • 只读数据段:存放常量
    • 代码段
    • 读取FLASH的方式
    • 若读取bootloader代码,则只能使用XIP硬件移动(前提是代码段存在FLASH中,否则可以使用软件移动)
    • 若读取普通代码/数据,则可以:软件移动 / XIP硬件移动 至SRAM的data段再读写
  • SRAM:数据段(.data)、BSS段(.bss)、堆段、共享段、栈段
    • 系统栈段:存放进程上下文和局部变量
    • 共享段:存放多进程共享的库函数、用共享区域实现进程通信
    • 系统堆段:由malloc/free分配
    • BSS段:存放未初始化的全局变量和静态变量
    • 数据段:存放初始化的全局变量和静态变量
  • 选项字节FLASH
  • 用于配置读/写保护、硬件参数、用户自定义参数

系统上电过程

  • 流程:上电硬件复位->bootROM->(一级Bootloader)->二级Bootloader(SystemInit、__main)->用户程序
  • 一级Bootloader是可选的

  • 上电硬件复位

  • bootROM:硬件编程的启动代码,不在内存映像中
  • 用于初始化硬件
  • 最后通过BOOT区仲裁,跳转到一级bootloader/二级bootloader
  • 一级Bootloader==内置==:存在于系统FLASH中
  • 用于初始化CPU核心
  • 最后跳转至二级Bootloader
  • 二级Bootloader==用户reset_handler==:存在于主FLASH的SystemInit()中
  • 用于初始化SoC
  • 最后跳转至__main()
  • __main()用户reset_handler:存在于主FLASH的__main()中
  • 用于复制flash的.data段,移动flash的.bss段、堆栈初始化
  • 最后跳转至用户程序main()

分散加载文件(链接文件)

位运算

  • 置1:a |= 00000111([2:0]置为1)
  • 置0:a &= 11111001([2:1]置为0)
  • 取反:a ^= 00010000([4:4]取反)

配置部件的思路

  • 初始化:与Init、Config相关
  • 用结构体进行初始化的过程:先用StructInit将结构体赋默认值,然后将需要用的成员进行修改
  • 运行:与get/read、set/Generate/write、clear/reset相关
  • 注意事项
  • 对于会产生数据覆盖的场景:需要使用轮询机制/中断机制(手动中断、睡眠等)
  • 对于会产生死循环的场景:在循环中加入timeout倒计时,或者使用中断

1. 配置NVIC

  • 注:NVIC无需挂载到RCC树上
  • 初始化NVIC:优先级分组设置、写中断函数等 + 中断系统初始化
  • 运行NVIC:改变中断优先级、读写某个通道的中断位/中断挂起位

2. 配置EXTI

  • 注:EXTI无需挂载到RCC树上

  • 初始化EXTI:外部中断系统初始化

  • 运行EXTI:读写外部中断位(IT)/外部事件位(FLAG)

2. 配置GPIO

  • 注:将GPIO和AFIO看作GPIO系统中的两个模块,未用到AFIO时可以忽略AFIO

  • 总线时钟配置(将GPIO和AFIO挂载到RCC树)

  • 初始化GPIO:AFIO功能复用配置等 + 输入输出初始化
  • 配置EXTI(可选)
  • 配置NVIC(可选)
  • 运行GPIO:读写DR

3. 配置TIM

  • 总线时钟配置(将TIM挂载到RCC树)、计数时钟配置
  • 初始化TIM:模式配置等 + OC、IC、时基单元初始化
  • 配置NVIC(可选)
  • 运行TIM:运行控制、读写ARR和CCR、读写时钟中断位(IT)/时钟事件位(FLAG)

4. 配置DMA

  • 总线时钟配置(将DMA挂载到RCC树)
  • 初始化DMA:通道中断配置等 + DMA初始化
  • 配置NVIC(可选)
  • 运行DMA:运行控制、读写CNT、读写DMA中断位(IT)/DMA事件位(FLAG)

5. 配置USART

  • 总线时钟配置(将USART挂载到RCC树)
  • 初始化USART:USART传输模式配置等 + USART初始化
  • 配置NVIC(可选)
  • 配置GPIO(可选)
  • 运行USART:运行控制、读写DR、读写USART中断位(IT)/USART事件位(FLAG)

6. 配置硬件I2C

  • 总线时钟配置(将I2C挂载到RCC树)
  • 初始化I2C:I2C应答配置、校验配置等 + I2C初始化
  • 配置GPIO(可选)
  • 运行I2C:运行控制、读写ACK、读写DR、读写I2C中断位(IT)/I2C事件位(FLAG)

7. 配置硬件SPI

  • 总线时钟配置(将SPI挂载到RCC树)

8. 配置BKP

  • 总线时钟配置(将PWR和BKP挂载到RCC树)
  • 初始化BKP:侵入检测配置等 + BKP初始化(即在PWR处对BKP进行使能)
  • 运行BKP:运行控制、读写RTCR、读写BKPR、读写BKP中断位(IT)/BKP事件位(FLAG)

9. 配置RTC

  • 总线时钟配置(将PWR和BKP挂载到RCC树)、计数时钟配置
  • 初始化RTC:计数配置等 + RTC初始化(即在PWR处对BKP进行使能)
  • 运行RTC:读写CNT、读写ALARM、读写分频寄存器、等待同步操作、读写RTC中断位(IT)/RTC事件位(FLAG)