首先仅写入:
发现可以进入debug,而且可以看到内存中确实已经写进去了
运行写入,然后擦除,发现无法进入debug,提示cannot halt the core
但是可以看到已经成功烧录了
这里验证一下写入之后,不写擦除函数,烧录过程是否会擦除数据。
首先打开写入,关闭擦除。
然后关闭写入,关闭擦除
可以看到,内存中依然有数据。所以烧录动作不会擦除所要操作的扇区。
把写入和擦除都关掉看看flash中现在是什么数据
此时可以进入debug
可以发现内存中什么数据也没有。
由于此时的烧录配置是仅擦除扇区,所以猜测应当是刚刚烧录进去的程序已经成功运行了,所以先写入数据之后,又将数据擦除了。下面可以做一个验证。
验证过程:
a、首先仅写入数据
这时进入debug后确认flash中已经成功写入了数据。
b、然后关闭写入,打开擦除
这里由于之前发现不能进debug,所以直接进行烧录
c、最后关闭写入且关闭擦除,进debug看数据是否已经擦除
可以看到此时flash的该扇区中已经没有数据了。
由此我们可以得出结论,虽然适用擦除函数后无法进入debug模式,但是可以烧录,并且烧录后确实已经成功执行了擦除动作。由此可以看到影响进入debug模式的,确实是擦除函数。
为了进一步探究并解决该问题,将库函数搬运到测试程序中执行
首先注释掉后面的程序,发现可以进入debug
这里就发现了,是后面的执行语句导致了这个问题。按照这个思路,我们定位到了这一条语句:
注意到这里有两条语句都是操作了CR寄存器
于是分别注释掉试试看。发现仅运行第一条语句可以进debug,但是仅运行第二条语句时无法进入debug,并且芯片无法再烧录,同样提示cannot halt the core。(解决办法:按住reset按钮,松开瞬间点击烧录)
下面就要查一下文档,看看这几条语句到底是什么
CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
复位编程大小
FLASH->CR |= tmp_psize;
定义编程大小
CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
复位扇区号
FLASH->CR |= FLASH_CR_SER | (FLASH_SECTOR_7 << FLASH_CR_SNB_Pos);
指定擦除扇区号,擦除方式为扇擦除
下面到了关键的一句
FLASH->CR |= FLASH_CR_STRT;
可以看到FLASH_CR_STRT的定义:
也就是这条语句启动了擦除动作
对于该位的说明如下:
也就是说由软件启动,当BSY清零的时候,该位也清零。
查询得知,BSY位在FLASH状态寄存器FLASH_SR中:
由于进debug时报的是cannot halt the core,也就是无法停止。那么我怀疑这里就是BSY一直处于置1的状态,而没有置0。
为什么FLASH操作一直处于忙的状态而导致BSY没有复位呢?
再看一眼程序:
我忽然想到,flash擦除是需要一定时间的,会不会是还没有擦完的时候,就执行了HAL_FLASH_Lock()语句,锁住了flash操作,从而导致bsy一直没有复位。
查询flash操作时间:
可以看到128k的扇区进行擦除的时候,根据擦除方式的不同需要的时间也不同。
在程序中增加一段延时
这里增加5s的时间。
结果:失败!
依然不能进入debug。
改成获取BSY状态
结果:失败!
依然不能进入debug状态。
然后忽然想到之前用的是另一条语句,里面有检测BSY状态的,为什么依然不行呢?程序如下:
这里面用到的擦除语句是HAL库推荐适用的,其中的标志位检测、超时检测都有,但是也不能够进入debug。
。。。。。。
事情似乎陷入了僵局。。。。
解决问题:
事情到了这个阶段,我就要考虑一些其他问题了。
因为我用的软件版本是KEIL MDK 15.6 盗版的,然后下载器也是用的盗版的。通常盗版的会出现一些莫名奇妙的事情。
首先我用的下载器长下面这样:
当然,也有长这样的,做成跟官方外观一样:
但是其实本质上没啥区别。
更换软件环境比较麻烦,先换个烧录器吧。手里面有两种ST-LINK V2(盗版的),U-link 2 (正版的),J-Link V8(盗版的)。
先换个J-link试一试:
斯巴达!!
斯巴达!!!
竟然进去了……
运行了一下,也没啥问题……
好吧,烧录器的锅~~~~~