当前位置: 首页 > news >正文

STM32 HAL驱动程序 内部Flash

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 DEBUGprintf("Waring:Flash Write Addr Error\r\n");
#endifflashWriteOffset = 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临时缓冲区首先全部填充0xEEmemcpy(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 valueBX 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 01011010void 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

 

http://www.xdnf.cn/news/417025.html

相关文章:

  • ansible进阶版01
  • FFmpeg在Android开发中的核心价值是什么?
  • RAG之大规模解析 PDF 文档全流程实战
  • 开源免费无广告专注PDF编辑、修复和管理工具 办公学术 救星工具
  • 服务器相关
  • Java Web 应用安全响应头配置全解析:从单体到微服务网关的实践
  • Vue 2 项目中配置 Tailwind CSS 和 Font Awesome 的最佳实践,加 daisyUI 安装
  • 存算一体芯片对传统GPU架构的挑战:在GNN训练中的颠覆性实验
  • w~大模型~合集30
  • 【后端】SpringBoot用CORS解决无法跨域访问的问题
  • Go 语言即时通讯系统开发日志-day1:从简单消息收发 Demo 起步
  • Vue使用scale方法实现响应式自适应大屏缩放通用组件详解(附完整代码)
  • cursor Too many报错 显示锁机器码怎么办?也就是Cursor的
  • 101alpha---第10
  • 各类型和字节数组互相转换
  • pyenv无法使用pip解决方案
  • Cyrus-Beck算法的计算方法
  • C++类的继承和派生
  • MYSQL事务原理分析(三)
  • 动作识别笔记
  • Linux 详解inode
  • 密码学--希尔密码
  • 电子电器架构 --- 借力第五代架构,驱动汽车产业创新引擎
  • Ansible内置模块之 group
  • vue3+vite 自动导入文件夹下所有路由
  • 【Python算法】最长递增子序列
  • python与nodejs哪个性能高
  • 1688平台开放接口实战:如何通过API获取店铺所有商品数据(Python示例)‌
  • 从PNG到矢量图:星云智控Logo的商用矢量转换全解析-优雅草卓伊凡
  • 三、transformers基础组件之Model