STM32 HAL驱动程序 内部Flash

发布于:2025-05-13 ⋅ 阅读:(11) ⋅ 点赞:(0)

hal_flash.c

#include "hal_flash.h"


volatile uint32_t flashWriteOffset = SYS_APP_BAK_SAVE_ADDR_BASE;
volatile uint32_t flashReadOffset = SYS_APP_BAK_SAVE_ADDR_BASE;

/* MCU OTA */
/*擦除指定的Flash页*/
void flash_erase_page(uint8_t flashPage , uint32_t addr_base)
{

		HAL_FLASH_Unlock();

    FLASH_EraseInitTypeDef f;
    f.TypeErase = FLASH_TYPEERASE_PAGES;
    f.PageAddress = addr_base+flashPage*FLASH_PAGE_SIZE;
    f.NbPages = 1;
	
    uint32_t PageError = 0;
    HAL_FLASHEx_Erase(&f, &PageError);
		HAL_FLASH_Lock();
}
void flash_erase(uint32_t size , uint32_t addr_base)
{
    uint32_t flashPageSum;
		uint32_t i;
    /*如果小于1024做处理*/
    if(size < FLASH_PAGE_SIZE)
        size = FLASH_PAGE_SIZE;												//
    /* 计算需要擦写的Flash页 */
    if((size % FLASH_PAGE_SIZE) == 0)
    {
        flashPageSum = size / FLASH_PAGE_SIZE;				//小于一页擦除一页
    }
    else
    {
        flashPageSum = (size / FLASH_PAGE_SIZE) + 1;	//大于一页擦除n+1页
    }
    for(i = 0;i<flashPageSum;i++)
    {
			flash_erase_page(i,addr_base);								//基址累加擦除flash
    }
}

void writeFlash(uint16_t * buf_to_save , uint16_t len , uint32_t wFlashAddr)
{
    uint16_t count=0;
    if(wFlashAddr >= 0x08010000)
    {
#ifdef DEBUG
        printf("Waring:Flash Write Addr Error\r\n");
#endif
        flashWriteOffset = SYS_APP_BAK_SAVE_ADDR_BASE;
        return;
    }
	HAL_FLASH_Unlock();

		while(count < len)
		{
				HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,(wFlashAddr + count*2),buf_to_save[count]); //вflashһٶַ֘дɫѫؖè16λé	
				count ++;     
		}
		HAL_FLASH_Lock();
}

void readFlash(uint16_t * buf_to_get,uint16_t len , uint32_t readFlashAddr)
{
	uint16_t count=0;
	while(count<len)
	{
	 	buf_to_get[count]=*(uint16_t *)(readFlashAddr + count*2);
		count++;
	}
}
/*写Flash,控制写长度,Flash地址偏移*/
void wFlashData(uint8_t * buf_to_save , uint16_t len , uint32_t wFlashAddr)
{
    uint8_t WriteFlashTempBuf[PIECE_MAX_LEN];//写Flash临时缓冲区
    uint16_t WriteFlashTempLen = 0;//写Flash长度
    memset(WriteFlashTempBuf,0xEE,sizeof(WriteFlashTempBuf));//写Flash临时缓冲区首先全部填充0xEE
    memcpy(WriteFlashTempBuf,buf_to_save,len);//临时缓冲区
    WriteFlashTempLen = len;
    if(len%2 != 0)
        WriteFlashTempLen += 1;//因为Flash只能写半字
    writeFlash((uint16_t *)&WriteFlashTempBuf ,  WriteFlashTempLen/2 , wFlashAddr);
}
void rFlashData(uint8_t * buf_to_get , uint16_t len , uint32_t rFlashAddr)
{
    uint8_t ReadFlashTempBuf[PIECE_MAX_LEN];//读Flash临时缓冲区
    uint16_t ReadFlashTempLen = 0;//读Flash长度
    
    if(len%2 == 0)
    {
        ReadFlashTempLen = len;
        readFlash((uint16_t *)&ReadFlashTempBuf,ReadFlashTempLen/2 , rFlashAddr);
        memcpy(buf_to_get,ReadFlashTempBuf,len);
    }
    else
    {
        ReadFlashTempLen = len + 1;//因为Flash只能读半字
        readFlash((uint16_t *)&ReadFlashTempBuf,ReadFlashTempLen/2 , rFlashAddr);
        memcpy(buf_to_get,ReadFlashTempBuf,len);
    }
}
/****IAP*****/
typedef  void (*iapfun)(void);				//֨ӥһٶگ˽`эքӎ˽.
iapfun jump2app; 
u16 iapbuf[1024];   

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

//设置栈顶指针
__asm void MSR_MSP(u32 addr) 
{
    MSR MSP, r0 			//set Main Stack value
    BX r14
}
void iap_load_app(u32 appxaddr)
{
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//ݬөջַ֥֘ˇرۏר.
	{ 
		printf("Stack Success!\r\n");
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//ԃۧպëȸ֚׾ٶؖΪԌѲߪʼַ֘(شλַ֘)		
		MSR_MSP(*(vu32*)appxaddr);					//ԵʼۯAPPבջָ֫(ԃۧպëȸք֚һٶؖԃԚզ؅ջַ֥֘)
		jump2app();									//͸תսAPP.
	}
	else
	{
		printf("Stack Failed!\r\n");
	}
}

 hal_flash.h

#ifndef _FLASH_
#define _FLASH_


#include "stm32f1xx.h"

typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef __IO uint32_t  vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t  vu8;

//#include "stm32f10x.h"
/* BootLoader Flash首地址 */
#define SYS_Bootloader_SAVE_ADDR_BASE       0x08000000//Bootloader首地址
/* 升级参数存储 */
#define UPDATE_PARAM_SAVE_ADDR_BASE         0x08002C00
#define UPDATE_PARAM_MAX_SIZE               (1*1024)//支持参数大小1KB
/* APP Flash首地址 */
#define SYS_APP_SAVE_ADDR_BASE              0x08003000
#define APP_DATA_MAX_SIZE                   (26*1024)//支持APP大小26KB
/* APP BAK Flash首地址 */
#define SYS_APP_BAK_SAVE_ADDR_BASE          0x08009800
#define APP_BAK_DATA_MAX_SIZE               (26*1024)//支持APP_BAK大小26KB


/* FLASH页大小 */
//#define FLASH_PAGE_SIZE           0x400U   //1KB

#define NEED_UPDATA_PARAM 0xA5A5//10100101 10100101
#define DONT_UPDATA_PARAM 0x5A5A//01011010 01011010

void save_param_to_flash(uint16_t * buf_to_save,uint16_t len );
void read_param_from_flash(uint16_t * buf_to_get,uint16_t len);
void set_flash_flag_to_updata(uint16_t crc_code);
void flash_erase(uint32_t size , uint32_t addr_base);
void EraseFlash(uint32_t size);
void rFlashData(uint8_t * buf_to_get , uint16_t len , uint32_t rFlashAddr);
void wFlashData(uint8_t * buf_to_save , uint16_t len , uint32_t wFlashAddr);
void iap_load_app(u32 appxaddr);
#endif

 


网站公告

今日签到

点亮在社区的每一天
去签到