基于STM32从零写操作系统系列---bootloader

发布者:asa1670最新更新时间:2019-09-10 来源: eefocus关键字:STM32  操作系统系列-  bootloader 手机看文章 扫描二维码
随时随地手机看文章

本章主要使用汇编语言编写STM32F103(以下称为“该芯片”)的启动代码。具体结构如图:

启动模式

 该芯片可以通过设置BOOT0和BOOT1两个引脚,选择不同的启动方式,正常情况下BOOT0=0,BOOT1=0(0为低电平)。即,芯片将从Flash中加载代码启动。


当芯片上电/复位后,芯片首先从地址0x0000_0000处获取栈地址,然后将地址0x0000_0004处的值赋值给PC寄存器。按照PC寄存器的值,取第一条指令,执行......具体如图:

 地址0x0800_0205处的具体代码如图:


简单来说,地址0x0000_0004处存放的是复位处理函数的地址。当上电/复位时,芯片硬件会自动将地址0x0000_0000处的栈地址赋值给MSP寄存器;将地址0x0000_0004处的复位函数地址值赋值给PC寄存器;然后就从PC寄存器所指的地址开始执行代码。


为什么Flash的地址明明是从0x0800_0000开始,但芯片是从地址0x0000_0000处开始取数据呢?原因很简单,当我们设置BOOT0=0,BOOT1=0时,芯片会将flash的地址范围映射到0x0000_0000~0x0007_ffff的地址范围内,如图:


向量表

当发生了异常并且要响应它时,CM3 需要定位其处理例程的入口地址。这些入口地址存储在所谓的“(异常)向量表”中。缺省情况下,CM3 认为该表位于零地址处,且各向量占用 4 字节,因此每个表项占用 4 字节。如图:

 完整的向量表定义,请看源代码。


复位处理函数

用于上电/复位后,初始化芯片,让芯片能够以最好的状态运行。初始化完成后,跳转到_main函数继续执行。如图:

初始化SystemInit.s

主要是配置芯片的时钟,禁止所有中断,设置向量表位置。如图:


链接脚本

用于链接各个目标文件,定义各个代码段,数据段的位置。如图:

 这个链接脚本的作用,可以简单地理解为规划Flash。如图:

 所以,我们看到第一条指令是放在地址0x0800_0200处的。


Makefile

用于多文件编译管理。如图:


 

main.s 

在本章中,main.s只做死循环,下一章将点亮LED灯。如图:

实验步骤:

1.如下图,创建一个文件夹,在文件夹中新建如图中的文件,按照上面所分析的编辑代码。

 2.在命令行中,进入上一步创建的文件夹,输入make,编译项目。如图:


3.如无意外编译通过,然后按照前面章节讲述的步骤,将生成的.bin文件下载到芯片里。


4.简单对比.list文件与芯片flash中的数据,如图:


小结

本章到此结束,主要是简单介绍了该芯片的启动模式设置,启动流程。stm32F103的初始化没有什么复杂的设置,可以通过相关文档手册,了解向量表的内容;或参照STM32固件库v3.5的源代码。有关链接脚本,Makefile的知识,在本系列博客中不会讲解,网上有相关的资料文档。


关键字:STM32  操作系统系列-  bootloader 引用地址:基于STM32从零写操作系统系列---bootloader

上一篇:基于STM32从零写操作系统系列---基于寄存器写串口驱动
下一篇:基于STM32从零写操作系统系列---熟悉纯windows交叉编译环境

推荐阅读最新更新时间:2024-11-02 11:11

STM32学习笔记(3):系统时钟和SysTick定时器
1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独立看门狗IWDG使用,另
[单片机]
STM32查看系统时钟
调用库函数RCC_GetClocksFreq,该函数可以返回片上的各种时钟的频率 函数原形 void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) RCC_ClocksTypeDef定义于文件 stm32f10x_rcc.h : typedef struct { uint32_t SYSCLK_Frequency; /*! SYSCLK clock frequency expressed in Hz */ uint32_t HCLK_Frequency; /*! HCLK clock frequency expressed in Hz */ uint32_t PC
[单片机]
可以快速用STM32实现什么?
一、前言 假如你会使用8051,会写C语言,那么STM32本身并不需要刻意地学习。 我们要考虑的是, 我可以快速用STM32实现什么?为什么使用STM32而不是8051? 是因为51的频率太低,无法满足计算需求? 是51的管脚太少,无法满足众多外设的IO? 是51的功耗太大,电池挺不住? 是51的功能太弱,而你要使用SPI、I2C、ADC、DMA? 是51的内存太小而你要存储的东西太多? 当你需要使用STM32某些功能,而51实现不了的时候, 那STM32自然不需要学习,你会直接去寻找STM32某方面的使用方法。 比如要用spi协议的网卡、要使用串口通信、要使用rtos等等... 快速上手的学习步骤 我们假定大家已经对STM32的
[单片机]
STM32中FLASH_Status的5个状态各表示的含义详解
获取状态:FLASH_Status FLASH_GetStatus(void); 返回值是通过枚举类型定义的。 typedef enum { FLASH_BUSY = 1, //忙 FLASH_ERROR_PG, //编程错误 FLASH_ERROR_WRP, //写保护错误 FLASH_COMPLETE, //操作完成 FLASH_TIMEOUT //操作超时 }FLASH_Status;
[单片机]
STM32之外部中断控制
一、STM32外部中断 1、STM32外部中断结构图   如上图所示:主要包括四个环节,GPIO、AFIO、EXTI、NVIC。以STM32F103VE(100脚)为例说明硬件模块的数量: GPIO:       80个 AFIO选择通道:   16个 外部中断线EXTI:  16 + 3 = 19个 NVIC     :  1个  2、EXTI控制器结构图 ① 功能 中断   申请中断 事件   当事件发生的时候,将产生事件脉冲,可以用来唤醒内核 ② 功能详细说明     如果要产生中断,必须事先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写 1 允许
[单片机]
<font color='red'>STM32</font>之外部中断控制
STM32 DMA使用详解
DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧。下面用问答的形式表达我的思路。 DMA有什么用? 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。 有多少个DMA资源? 有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。 数据从什么地方送到什么地方? 外设到SRAM(I2C/UART等获取数据并送入SRAM); SRAM的两个区域之间; 外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比); SRAM到外设(SR
[单片机]
<font color='red'>STM32</font> DMA使用详解
stm32成长记之中断介绍
嵌套向量中断控制器 特性 ●68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线); ● 16个可编程的优先等级(使用了4位中断优先级); 外部中断/事件控制器框图 外部中断程序设计思路: 中断初始化,主要是完善三个结构体: ①GPIO_InitTypeDef (功能:IO配置) ②EXTI_InitTypeDef (功能:中断配置) ③NVIC_InitTypeDef (功能:中断优先级配置) 抢占优先级高的可以抢占优先级低的,即发生中断嵌套;响应优先级高的中断先进行,但不会抢占响应优先级低的中断,即不能发生中断嵌套; void exti_init() { GPIO
[单片机]
<font color='red'>stm32</font>成长记之中断介绍
一例使用STM32外设库设置串口速度与实际不一样的解决
最近手上有了块金牛的stm32实验板,兴致勃勃的测试各种功能,但是碰到一个问题,用stm32 的外设库写串口程序,发现串口速度与实际不一样。一度怀疑是外设库的问题,但是用mdk的外设监控查看后,发现实际的串口速度为自定义的3倍,如图 很疑惑,本人有一种钻牛角尖的精神,因此一度debug下去,发现这个设置是在如下关键语句 (位于 外设库 中的 USART_Init定义语句,在stm32f10x_usart.c中) USART_Init初始化函数 RCC_GetClocksFreq(&RCC_ClocksStatus); if (usartxbase == USART1_BASE) { apbclock = RCC_ClocksSt
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved