Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析

遇到的问题如下:

1.boot0管脚拉高或拉低都不能从系统存储区(system flash)启动(即进入bootloader状态)。

2.新的Stm32g031芯片能够使用ISP烧写程序,但写完程序后就没法再次烧写了,芯片无法进入bootloader状态,只能进入main flash中,运行之前烧写的程序。

3.芯片第一次使用swd模式烧写完后设置了reset也无法进入程序区,即使按reset键也无法进入,必须得断电重启才能运行烧写的程序。

先解答问题1:因为Stm32g031芯片默认是从main flash区启动的,且默认boot0 pin 不起作用,所以不会进入bootloader状态。原因如下:

芯片的启动配置设置如下:

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第1张图片

如上表所致,芯片的启动配置由boot_lock bit、nboot1 bit、nboot0 pin、nboot_sel bit、nboot0 bit决定。

boot_lock bit是强制从main flash区启动的配置位,默认是0,即没有强制从main flash区启动。

于是启动方式由nboot1 bit、nboot0 pin、nboot_sel bit、nboot0 bit决定。当nboot_sel bit为0时启动方式由nboot1 bit、nboot0 pin决定,即此时用户可以通过boot0管脚进行启动方式的设置,可以使用ISP下载方式。

但是很不幸的是Stm32g031芯片默认nboot_sel bit为1,即下载方式由nboot1 bit、nboot0 bit决定的,而nboot1 bit、nboot0 bit的默认值都为1,从而导致Stm32g031芯片默认是从main flash区启动的,且默认boot0 pin 不起作用。

nboot1 bit、nboot_sel bit、nboot0 bit所在寄存器地址及初始值如下:

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第2张图片

问题1说明白了,下面解释问题2:

为何新的Stm32g031芯片可以使用ISP烧写,但也只能写一次,第二次不行了呢。原因如下:

芯片刚开始启动会检查main flash区有没有代码,要是0x08000000没有代码,就进入bootloader状态,要是有代码就从main flash区运行;

芯片使用手册原文如下:

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第3张图片

翻译:

内部空检查标志(FLASH访问控制寄存器的EMPTY位(FLASH ACT))的实现是为了允许引导加载程序轻松地对原始设备进行编程。当BOOT0引脚将主闪存定义为目标引导区时,使用此标志。 设置该标志后,该设备将被视为空设备,并且选择了系统内存(引导加载程序)而不是主闪存作为引导区域,以允许用户对闪存进行编程。

该标志仅在Option字节加载期间更新:当地址0x0800 0000的内容读取为0xFFFF FFFF时置1,否则将其清除。 这意味着在对原始设备进行编程以在系统复位后执行用户代码之后,需要进行电源复位或将FLASH_CR寄存器中的OBL_LAUNCH位置1以清除该标志。 EMPTY位也可以直接由软件写入。

如果是第一次对设备进行编程,但未重新加载选项字节,则在系统复位后,设备仍将选择系统内存作为引导区。

通过上面的翻译我们也就明白问题3的原因了:

因为芯片首次运行进行了空位检查,此时的empty 标志位(即OBL_LAUNCH)已经置位了1,当使用swd烧写完程序后,无论是软件reset还是芯片的reset管脚复位,都无法把empty标志为清0,芯片会在每次的reset后都进入bootloader状态,而不会进入main flash区。只有断电重启,empty flag才会变成0,此时芯片才会进入main flash区运行。

在首次断电重启后,后面的swd烧写就可随意reset了。

上面3个问题已经研究清楚了,那么如何更改芯片默认的启动方式呢,根据上面的分析,我们应该更改0x1fff 7800处寄存器的nboot_sel bit为0即可使用芯片的boot0管脚来决定芯片如何启动。更改方法如下:

方法1:使用STM32CubeProgrammer更改。

1:使用STM32CubeProgrammer成功连接芯片点击主界面read,如下图;

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第4张图片

2.读取成功后点击OB选项,然后选择User Configuration,会看的0x1fff 7800处所有bit的配置值;

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第5张图片

3 将nboot_sel后面的勾选去掉,点击apply,配置完成(此时可能会弹出读取失败啥的,就不用管了)。断电复位,此时芯片的启动方式就由boot0引脚决定了。要是想进bootloader模式就得上拉boot0了。

.Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第6张图片

方法2:在应用程序里改(理论上可以,但我改失败了,芯片成了砖!!!,至今不知道如何挽救) 

为何理论可以改呢?因为芯片手册里对0x1fff7800寄存器起名了,且为rw状态:

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第7张图片

St的hal库也提供了修改的库函数

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第8张图片

于是我就按照上面的代码改了,看似合理,但执行到HAL_FLASH_OB_Launch();后芯片就成砖了,至今不知道如何挽救,哪位高手有时间,有足够的芯片研究非常欢迎,希望能告知我一下
————————————————
版权声明:本文为CSDN博主「howareyou23」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/w942401053/article/details/109627440

解决办法,另一入篇博客:STM32G0系列的启动配置与程序下载说明_stm32g0 boot_infinigo的博客-CSDN博客

STM32G0系列的启动配置与程序下载说明

目的
STM32G是意法半导体这两年新推出的系列芯片,相比原先的F系列的芯片有很多提升点,将来必将取代F系列芯片的地位。对于新芯片的应用来说能够正确下载与运行程序是比较重要的一点,这篇文章将对 STM32G0 系列芯片的启动配置与程序下载做个简单的说明。

启动配置
STM32G0系列芯片的启动配置相关内容在官方文档《AN5096:Getting started with STM32G0 Series hardware development》第三章中有详细的描述:

Stm32g031芯片无法进入bootloader的及首次烧写完程序reset无法运行原因分析_第9张图片

启动配置相关内容其实是不多的,下面将对这部分内容做个简单的说明。

STM32系列芯片程序启动方式分为下面三种:

Main Flash memory 从主闪存启动,想要运行我们自己的程序就要选择这种方式;
System memory 从系统存储区启动,想要通过串口下载程序就要选择这种方式;
Embbeded SRAM 从内存启动;
STM32G0系列芯片通过选项字节(option byte)中的 BOOT_LOCK、nBOOT1、nBOOT_SEL、nBOOT0这几位加上外部的 BOOT0 管脚的电平来确定启动方式。当 nBOOT_SEL 为 0 时, BOOT0 的值来源于外部的 BOOT0 管脚的电平,低电平为 0 ,高电平为 1 ;当 nBOOT_SEL 为 1 时, BOOT0 的值来源于 nBOOT0 的值。

芯片启动时会检查闪存地址0x080000000(即用户程序起始地址)处的数据,如果该数据为0xFFFFFFFF则表示用户程序为空,此时不管上面的那些设置程序会从 System memory 启动。

芯片在出厂后只要没有经过程序下载等操作启动时总是会从 System memory 启动。

程序下载
STM32系列系统程序下载通常通过串口进行,而使用串口下载程序重要的是要让芯片从 System memory 启动。

从上一章节内容可以知道芯片在初次烧写时就是从 System memory 启动的,你可以正常使用串口进行连接烧写,不需要关心外部 BOOT0 管脚的电平,如果连接不上就拉低下芯片 NRST 引脚复位下芯片试试。(如果还是连接不上就检查下芯片供电、线路连接、串口模块、串口驱动等试试。)

在初次连接芯片烧写程序前特别需要注意的一点是配置选项字节(option byte)。默认情况下 nBOOT_SEL 和 nBOOT0 均为 1 ,也就是当你在这种情况下下载程序后下次芯片上电时将从 Main Flash memory 启动(不管外部BOOT0引脚上的电平是多少)。如果你下载的程序中没有操作对 nBOOT_SEL 和 nBOOT0 进行操作的话你再也无法通过串口重新下载程序或是修改选项字节了。

补救办法有,那就是通过ST-LINK连接芯片进行程序擦写或是修改选项字节。(修改完成后可能需要芯片断电然后重新上电才能通过串口连接)

如果更严重点,程序中把ST-LINK连接需要的 SWDIO 和 SWCLK 引脚用作它用了,ST-LINK也连接不上怎么办?解决方法也有,断开这两个引脚上别的电路连接,然后将芯片的 NRST 引脚保持下拉,这时候 STM32CubeProgrammer 上选择ST-LINK点击Connect,然后断开 NRST 的下拉,芯片会在启动的一瞬间被ST-LINK连接上。

通过程序修改 nBOOT_SEL
使用HAL库进行开发的话可以使用下面程序判断nBOOT_SEL数值并进行修改,注意修改option byte并写入后会重启芯片:

void Flash_OB_Handle(void) {
    FLASH_OBProgramInitTypeDef optionsbytesstruct;
    bool UPDATE = false;    
    HAL_FLASHEx_OBGetConfig(&optionsbytesstruct);
    uint32_t userconfig = optionsbytesstruct.USERConfig;

    if((userconfig & FLASH_OPTR_nBOOT_SEL_Msk) != OB_BOOT0_FROM_PIN) {
            userconfig &= ~FLASH_OPTR_nBOOT_SEL_Msk;
            userconfig |= OB_BOOT0_FROM_PIN;
            UPDATE = true;
    }

    if(UPDATE) {
            optionsbytesstruct.USERConfig = userconfig;
            HAL_FLASH_Unlock();
            HAL_FLASH_OB_Unlock();
            HAL_FLASHEx_OBProgram(&optionsbytesstruct);
            HAL_FLASH_OB_Launch();
            HAL_FLASH_OB_Lock();
            HAL_FLASH_Lock();
    }

}

总结
了解上面内容后在STM32G0系列芯片上下载与运行程序应该就没什么问题了,配合STM32Cube等就可以愉快的使用新系列的芯片了。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)