建网站的公司叫什么,承德网站建设怎么做,销售网站的技巧,织梦网站如何上传STM32G030是F0系列的升级版#xff0c;其在性能上比F0要好很多#xff0c;具体G0参数如下#xff1a; 最开始做项目选用的单片机是STM32F030F4P6#xff0c;但是在后期使用中发现#xff0c;我的FLASH#xff08;16K#xff09;不够用了#xff0c;就选择了STM32G030F6…STM32G030是F0系列的升级版其在性能上比F0要好很多具体G0参数如下 最开始做项目选用的单片机是STM32F030F4P6但是在后期使用中发现我的FLASH16K不够用了就选择了STM32G030F6P6来进行项目使用主要是价格便宜资源够用。 在F030使用的flash拿到G030上来发现不可使用就进行了一些修改但是这个时候就出现了报错在进行flash擦除的时候报错 HAL_FLASHEx_Erase(EraseInitStruct,PageError); 通过发现擦除有问题我就去查看其底层函数。
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
{HAL_StatusTypeDef status;uint32_t index;/* Check the parameters */assert_param(IS_FLASH_TYPEERASE(pEraseInit-TypeErase));/* Process Locked */__HAL_LOCK(pFlash);/* Reset error code */pFlash.ErrorCode HAL_FLASH_ERROR_NONE;/* Wait for last operation to be completed */status FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);if (status HAL_OK){
#if !defined(FLASH_DBANK_SUPPORT)/* For single bank product force Banks to Bank 1 */pEraseInit-Banks FLASH_BANK_1;
#endif /* FLASH_DBANK_SUPPORT */if (pEraseInit-TypeErase FLASH_TYPEERASE_MASS){/* Proceed to Mass Erase */FLASH_MassErase(pEraseInit-Banks);/* Wait for last operation to be completed */status FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);}else{/*Initialization of PageError variable*/*PageError 0xFFFFFFFFU;for (index pEraseInit-Page; index (pEraseInit-Page pEraseInit-NbPages); index){/* Start erase page */FLASH_PageErase(pEraseInit-Banks, index);/* Wait for last operation to be completed */status FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);if (status ! HAL_OK){/* In case of error, stop erase procedure and return the faulty address */*PageError index;break;}}/* If operation is completed or interrupted, disable the Page Erase Bit */CLEAR_BIT(FLASH-CR, FLASH_CR_PER);}}/* Process Unlocked */__HAL_UNLOCK(pFlash);/* return status */return status;
} 其大致意思就是两种擦除方式片擦除以及全部擦除。然后发现其status是在 FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); 里面进行报错其函数实现如下:
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{uint32_t error;/* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.Even if the FLASH operation fails, the BUSY flag will be reset and an errorflag will be set */uint32_t timeout HAL_GetTick() Timeout;/* Wait if any operation is ongoing */
#if defined(FLASH_DBANK_SUPPORT)error (FLASH_SR_BSY1 | FLASH_SR_BSY2);
#elseerror FLASH_SR_BSY1;
#endif /* FLASH_DBANK_SUPPORT */while ((FLASH-SR error) ! 0x00U){if (HAL_GetTick() timeout){return HAL_TIMEOUT;}}/* check flash errors */error (FLASH-SR FLASH_SR_ERRORS);/* Clear SR register */FLASH-SR FLASH_SR_CLEAR;if (error ! 0x00U){/*Save the error code*/pFlash.ErrorCode error;return HAL_ERROR;}/* Wait for control register to be written */timeout HAL_GetTick() Timeout;while ((FLASH-SR FLASH_SR_CFGBSY) ! 0x00U){if (HAL_GetTick() timeout){return HAL_TIMEOUT;}}return HAL_OK;
}
发现其在这里进行报错然后从下面返回错误码上来。 返回我打印了这个error到底是多少发现其值为0x80发现报的错误是 FLASH_SR_PGSERR
然后查看数据手册以及使用手册发现这个是编程错误。然后继续查找问题发现G030的一个bank是2K修改之后发现还是报这个错误。 在详细查看数据手册后发现G030进行Flash读写是uint64_t进行读写的如下 在此情况下对读写函数进行修改将数据等改为uint64_t。在将这些修改过后发现问题没有在flash擦除那里进行报错而是在FLASH写入那里卡死。 HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST,addr,Data[i])!HAL_OK 上述函数错误的地方是 FLASH_TYPEPROGRAM_FAST 因为其意思是32位写 Fast program a 32 row double-word (64-bit) at a specified address 但是手册给出是64位写所以这里进行了报错然后将这里改成下面函数整个程序的读写就没有问题了在此问题就得到了解决。 HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,addr,Data[i])!HAL_OK 以下则是G030F6P6单片机的FLASH的程序
读
/*******************************************************************************
* Function Name : 读取Flash数据
* Description : Read packed message form flash
* Input : buff:point to first location of received buffer.length:Maxmum length of reception
* Output :
* Return : reception length
*******************************************************************************/
uint16_t Read_Flash( uint64_t *Data, uint16_t num, uint32_t addr)
{uint16_t i0;uint32_t add0;if(num 0){return 0;}add addr;i0;while((add FLASH_USER_END_ADDR1) (inum)){Data[i] *(__IO uint64_t *)add;add add8;}return i;
}
写
/*******************************************************************************
* Function Name : Flash写数据
* Description : Write a group of datas to flash.
* Input : buff:pointer of first data, length: write length
* Output :
* Return : true/false
*******************************************************************************/
uint16_t Write_Flash( uint64_t *Data , uint16_t num, uint32_t add)
{uint16_t i0;uint32_t addr0;FLASH_EraseInitTypeDef EraseInitStruct{0};uint32_t PageError0;//擦除错误地址EraseInitStruct.TypeErase FLASH_TYPEERASE_PAGES;//仅擦除页EraseInitStruct.Banks FLASH_BANK_1;EraseInitStruct.Page 15; //注该page为0-15页EraseInitStruct.NbPages 1; //擦除一页HAL_FLASH_Unlock();HAL_FLASHEx_Erase(EraseInitStruct,PageError);if(PageError ! 0xFFFFFFFF) {return 1;}addr add;i0;while((addr FLASH_USER_END_ADDR1) (inum)){if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,addr,Data[i])!HAL_OK){addr addr 8;}else{i;}}HAL_FLASH_Lock();return 0;
} 在这里使用的是uint64_t进行数据的读写但是如果用在其他程序就会出现error。因为单片机是32位的出现uint64_t参与的函数就报错。 在这里我写了一个简易的flash内存管理因为我们在写flash数据的时候往往很多数据并不是单一数据但是每写一次flash则需要进行flash擦除我这里采用一个数组进行使用如下 实现原理一次性读取一定数量的数据出来将自己需要的数据修改过后再讲修改后的数据全部写入在实际项目中还是比较实用的。
读
/*
*********************************************************************************************************
* 函 数 名uint8_t data_read(uint16_t *data,uint16_t datalen,uint16_t save_addr,uint32_t bank_addr)
* 功能说明数据读取
* 形 参data 数据 datalen 长度 save_addr数组中保存的地址 bank_addr 地址
* 返 回 值
*********************************************************************************************************
*/
uint8_t data_read(uint16_t *data,uint16_t datalen,uint16_t save_addr,uint32_t bank_addr)
{uint64_t buf[READ_NUM]{0}; //根据实际数据量进行设置if(datalen 0){return 1;}Read_Flash(buf,READ_NUM,bank_addr); //读数据for(int i0;idatalen;i) //数据更新{data[i] buf[save_addri];}return 0;
}
写
/*
*********************************************************************************************************
* 函 数 名uint8_t data_save(uint16_t *data,uint16_t datalen,uint16_t save_addr,uint32_t bank_addr)
* 功能说明数据保存
* 形 参data 数据 datalen 长度 save_addr数组中保存的地址 bank_addr 地址
* 返 回 值
*********************************************************************************************************
*/
uint8_t data_save(uint16_t *data,uint16_t datalen,uint16_t save_addr,uint32_t bank_addr)
{uint64_t buf[READ_NUM]{0}; //根据实际数据量进行设置if(datalen 0){return 1;}Read_Flash(buf,READ_NUM,bank_addr); //读数据if(buf[0]0xffffffff){for(int i0;iREAD_NUM;i){buf[i] 1;}Write_Flash(buf,READ_NUM,bank_addr); //写数据}for(int i0;idatalen;i) //数据更新{buf[save_addri] data[i];}Write_Flash(buf,READ_NUM,bank_addr); //写数据return 0;
}
其他宏定义相关代码
//数组大小
#define READ_NUM 30
//地址
#define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000000) //第一页
#define ADDR_FLASH_PAGE(n) (ADDR_FLASH_PAGE_0 (uint32_t)(n)*FLASH_PAGE_SIZE)#define FLASH_USER_PAGE_NUM 1
#define FLASH_USER_START_ADDR1 ADDR_FLASH_PAGE(16-1)
#define FLASH_USER_END_ADDR1 (FLASH_USER_START_ADDR1 FLASH_USER_PAGE_NUM*FLASH_PAGE_SIZE)
基本上可以实现功能主要的问题就是那个必须64位读写不然数据就有问题