此篇博客主要讲解STM32G0系列的Flash操作,没啥技术含量,老鸟直接发过就好了。
首先将Flash怎么操作,然后再讲标题中的问题及解决思路。
一、Flash操作
我建议大家先看编程手册的Flash这章,等有一个操作Flash的大概的流程概念(不需要
记住所有的操作步骤,因为有库),再去看库操作历程(这是我个人的习惯,只是给大家
提个建议)。
1、首先来看Flash基本知识
重点:
1)读写都是8个字节;
2)每页大小2K;
2、擦除步骤(除了页擦,还有多块擦除)
3、写入步骤(除了标准写,还有快速写入)
至于更具体的操作流程,我不在讲解了,大家到库和历程就好,所有的操作都是上面提到的。
我们来看看8字节的写入操作:
LL_StatusTypeDef LL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
传入的是uint64_t类型的变量,再看底层怎么操作:
/**
* @brief Program double-word (64-bit) at a specified address.
* @param Address specifies the address to be programmed.
* @param Data specifies the data to be programmed.
* @retval None
*/
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
{
/* Set PG bit */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Program the double word */
*(uint32_t *)Address = (uint32_t)Data;
*(uint32_t *)(Address + 4u) = (uint32_t)(Data >> 32u);
}
看到没有,分两次写入,那么读我们怎么操作?一样的:
for(i=0;i<(wSize);i+=8)
{
tData.wData1 = *((uint32_t*)(wAddr+i)); //ÒªÇó¶Ôflash²Ù×÷¶ÁÈ¡8¸ö×Ö½Ú
tData.wData2 = *((uint32_t*)(wAddr+i+4)); //ÏȶÁµÚÒ»¸ö×Ö£¬ÔÚ¶ÁµÚ¶þ¸ö×Ö
memcpy(pdwBuffer+i,tData.chBuffer,0x08);
}
至此,Flash操作,我们讲解完毕。
二、上电复位后PGSERR和PGAERR置位
首先来说现象,就是上电偶尔死机,操作Flash一定死机。首先查死机死到什么地方,通过
Log分析死在了HardFault_Handler()里面,查看手册,有下面这句话:
打印出Flash的SR寄存器=0x00A0:
想不通,看看度娘有没有答案:
1、https://bbs.21ic.com/icview-574918-1-1.html?ordertype=1
这个帖子说要加中断,我看了我的操作,有加。
2、http://www.stmcu.org.cn/module/forum/thread-524621-1-1.html
这个帖子说是MDK的一个BUG,换成IAR没有问题,我感觉不会。
3、http://www.openedv.com/posts/list/0/43988.htm
这个帖子说关中断,上电清零,然后开中断,试了,没用。
4、https://www.cnblogs.com/ramlife/p/12457096.html
这个帖子说是初始化时候操作了未初始化的指针,当时未在意。
我又把官方的库和操作手册对了一遍,然后尝试清零标志位,失败。就在我打算放弃时候,突然想到
了上面的第4条,难道是因为这个?因为我移植的SX1278的官方的Demo,里面有些东西,我没用。
从初始化开始看起:
SX1276Init->SX1276Reset->SX1276SetBoardTcxo->操作Gpio_t TcxoPower变量
但是这个变量,我并没有初始化,屏蔽掉,测试。
OK了,好吧,以后不用的变量一定记得屏蔽掉。