编译,并在线调试,发现并没有出现客户所描述的问题。如图3所示。
图3.测试代码1结果(位于SPI初始化之后)
可以看到,WRPERR的值并没有被置1,Flag1和Flag2的值也都是0。那么,为什么客户说他那边会有这个问题呢?
再回头仔细看一下客户的测试代码,发现客户的测试代码中并没有对SPI进行初始化,其_HAL_SPI_DISABLE()代码是放在其他外设初始化之后的。
好,那么再来修改一下测试代码,把客户这三句测试代码挪动到SPI初始化之前,如图4所示。
图4.测试代码2(位于SPI初始化之前)
编译,并在线调试,这时,会惊奇地发现客户所描述地问题来了。其结果如图5所示。
图5.测试代码2结果(位于SPI初始化之前)
可以看到,这时Flash的WRPERR标志位置1了,测试代码中,flag2的值也跟flag1不同了。
再做一个实验,将此处的HAL库写法,改成直接操作寄存器,来试一下。测试代码变成是图6这样的。
图6.测试代码3(位于SPI初始化之前,直接操作寄存器)
编译,在线调试,这次又惊喜地发现,问题不见了。结果如图7所示。
图7.测试代码3结果(位于SPI初始化之前,直接操作寄存器)
三种操作,为什么只有第二种方式有问题呢?而且为什么错的偏偏是Flash的写保护错误标志WRPERR呢?接下来可以分析一下它们的反汇编代码,看看到底是哪里出问题了。
2.3 反汇编分析
对于三种情况,把反汇编拉出来看最清楚其操作过程了。
先分析第一种情况——测试代码位于SPI初始化之后。其反汇编如图8所示。
图8.测试代码1的反汇编(位于SPI初始化之后)
从之前的Watch窗口,知道flag1的地址为 0x2000000c,flag2的地址为0x2000000d。
现在对三句C语言测试语句的反汇编语句进行解析,如下:
可以看到,这段汇编是一点问题都没有的。
接下来,先分析第三种情况——也就是测试代码放在SPI初始化之前,但是使用直接操作寄存器的方式。其反汇编如图9所示。
图9.测试代码3的反汇编(位于SPI初始化之前,直接操作寄存器)
从之前的Watch窗口,知道flag1的地址为0x2000000c,flag2的地址为0x2000000d。
现在对三句C语言测试语句的反汇编语句进行解析,如下:
可以看到,这段汇编也是一点问题都没有的。
最后,再来分析一下有问题的第二种情况,也就是测试代码放在SPI初始化之前,但是使用_HAL_SPI_DISABLE()关闭SPI的情况。其反汇编如图10所示。
图10.测试代码2的反汇编(位于SPI初始化之前)
|