STM32WB55xx 任意长度和任意地址写入的 Flash 驱动

wb这颗完蛋芯片的flash,即使整个page都是0xff也写不了必须擦除了才能写。
先在APP_BLE_Init() 中 添加两行

// 这一行防止flash操作导致断开链接
SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
void APP_BLE_Init( void )
{
    
    
...
/* Select which mechanism is used by CPU2 to protect its timing versus flash operation */
  SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7);
  /**
   * The error flag shall be cleared before moving forward
   */
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
  /**
	* Initialize P2P Server Application
	*/
	P2PS_APP_Init();
	....
}
/**
 ******************************************************************************
 * File Name          : McuFlash.c
 * Description        : Flash driver for STM32WB55xx
 * @author            : zxk
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "app_common.h"

#include "flash_driver.h"
#include "shci.h"
#include "hw_conf.h"
#include "utilities_conf.h"

#include <stdio.h>
#include "cmsis_os.h"
#include "dbg_trace.h"
#include "McuFlash.h"
#include "main.h"

/* Private typedef -----------------------------------------------------------*/

/* Private defines -----------------------------------------------------------*/
#define FLASH_DBG			APP_DBG_MSG//PRINT_NO_MESG//

#define Rd64Bit(addr)       (*(uint64_t *)(addr))
#define USR_DATA_START		(ADDR_FLASH_PAGE_24)
#define USR_DATA_SIZE       (FLASH_PAGE_SIZE * 15)
#define USR_DATA_END		(USR_DATA_START + USR_DATA_SIZE - 1)
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t pageBuff[FLASH_PAGE_SIZE];
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

inline uint32_t GetPage(uint32_t Addr)
{
    
    
  return (Addr - FLASH_BASE) >> 12;
}

FlashWrRet McuFlashErase(uint32_t FirstPage, uint32_t NbOfPages)
{
    
    
	FLASH_EraseInitTypeDef EraseInitStruct;
	uint32_t PageError = 0;
	
	/* Fill EraseInit structure*/
	EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
	EraseInitStruct.Page        = FirstPage;
	EraseInitStruct.NbPages     = NbOfPages;
	/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
		you have to make sure that these data are rewritten before they are accessed during code
		execution. If this cannot be done safely, it is recommended to flush the caches by setting the
		DCRST and ICRST bits in the FLASH_CR register. */
	if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
	{
    
    
		FLASH_DBG("<0x%x>Erase once fail!\r\n",PageError);
		/* Try again. */
		if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
		{
    
    
			FLASH_DBG("<0x%x>Erase twice Error!\r\n",PageError);
			return 1;
		}
		/*Error occurred while  erase.user can call function 'HAL_FLASH_GetError()'*/
	}
	return 0;
}

FlashWrRet McuWriteNoChk(uint32_t addr, uint8_t * data, uint16_t len)
{
    
    
	Data64   tempData = {
    
    .buff = {
    
    0}};
	uint32_t tempAddr = 0;
	uint16_t tempLen  = 0;
	/* step.1 write head */
	if(addr & 0x07)
	{
    
    
		tempLen  = 8 - (addr & 0x07);
		tempLen  = (tempLen > len) ? len : tempLen;
		tempAddr = addr - (addr&0x07);
		memcpy(tempData.buff, (uint8_t *)tempAddr, 8);
		memcpy(&tempData.buff[addr & 0x07], data, tempLen);
		
		if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, tempAddr, tempData.num) != HAL_OK)
		{
    
    
			return 0x01;
		}
		len  -= tempLen;
		addr += tempLen;
		data += tempLen;
	}
	/* step.2 write body */
	while(len >= 8)
	{
    
    
		memcpy(tempData.buff, data, 8);
		if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, tempData.num) != HAL_OK)
		{
    
    
			return 0x02;
		}
		len  -= 8;
		addr += 8;
		data += 8;
	}
	/* step.3 write tail */
	if(len)
	{
    
    
		memcpy(tempData.buff, (uint8_t *)addr, 8);
		memcpy(tempData.buff, data, len);
		
		if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, tempData.num) != HAL_OK)
		{
    
    
			return 0x03;
		}
	}
	return 0;
}

FlashWrRet McuFlashWrie(uint32_t addr, uint8_t * data, uint16_t lenToWr)
{
    
    
	uint16_t pageOff    		= addr & 0x0FFF;
	uint16_t pageRemain 		= FLASH_PAGE_SIZE - pageOff;
	uint32_t pageAddr			= addr - pageOff;
	
	/* Check the input parameter.*/
	if((addr < USR_DATA_START) 	  || \
		(NULL == data)			  || \
		(lenToWr > USR_DATA_SIZE) || (0 == lenToWr))
		return 0x01;
	
	/* Unlock the Flash to enable the flash control register access *************/
	HAL_FLASH_Unlock();
	do{
    
    
		/* Updata the number of data to be written in this page. */
		pageRemain = (pageRemain > lenToWr) ? lenToWr : pageRemain;
		/* Copy the old data of this page before erase it. */
		memcpy(pageBuff, (uint8_t *)pageAddr, FLASH_PAGE_SIZE);
		/* Refresh the buff of this page. */
		memcpy(pageBuff+pageOff, data, pageRemain);
		/* Refresh flash data. */
		if(0 != McuFlashErase(GetPage(pageAddr), 1))
		{
    
    
			HAL_FLASH_Lock();
			FLASH_DBG("-<Err> McuFlashErase... 0x02.\n");
			return 0x02;
		}
		if(0 != McuWriteNoChk(pageAddr, pageBuff, FLASH_PAGE_SIZE))
		{
    
    
			HAL_FLASH_Lock();
			FLASH_DBG("-<Err> McuWriteNoChk... 0x03.\n");
			return 0x03;
		}
		/* Updata addr and length. */
		data 		+= pageRemain;
		lenToWr 	-= pageRemain;
		pageAddr 	+= FLASH_PAGE_SIZE;
		pageOff 	= 0;
		pageRemain 	= FLASH_PAGE_SIZE;		
	}while(lenToWr);
	/* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
	HAL_FLASH_Lock();
	
	return 0;
}

验证待写入的page全为0xff也不能直接写,这一页最近一个flash动作必须是被擦除。

static void DbgFlash(const char * str,uint32_t addr, short len)
{
    
    
	if(str != NULL)
	{
    
    
		MAIN_DBG("%s addr[0x%x]-%d\r\n",str,addr,uwTick);osDelay(1);
	}
	while(len--)
	{
    
    
		MAIN_DBG("0x%02x, ",*(uint8_t *)addr);
		addr++;
	}//osDelay(4);
	MAIN_DBG("\n\n\n"); osDelay(1);
}
void test_flash(void)
{
    
    
	uint32_t addr = FLASH_USER_START_ADDR;
	
	osDelay(64);
	
	DbgFlash("Before test operation:", addr, 16);

	HAL_FLASH_Unlock();
	
	McuFlashErase(GetPage(addr), 1);
	DbgFlash("-1-erase.", addr, 16);
	
	if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, 0xFFFFFFFFFFFFffFF) != HAL_OK)
	{
    
    
		MAIN_DBG("--<Err> ... HAL_FLASH_Program 0xff.\n");osDelay(2);
	}
	DbgFlash("after write 0xff.", addr, 16);
	
	if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, 0xFFFFFFFFFFFF07FF) != HAL_OK)
	{
    
    
		MAIN_DBG("--<Err> ... HAL_FLASH_Program 0x07.\n");osDelay(2);
	}
	DbgFlash("after write 0x07.", addr, 16);
	HAL_FLASH_Lock();
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_28851611/article/details/107653844