A: Write_N_4Byte_flash(FLASH_APP1_ADDR,(uint32_t*)(valid_data+8),len);

   B:Write_N_4Byte_flash(FLASH_APP1_ADDR,(uint32_t*)(valid_data+6),len);

A语句存在写入flash时读取valid_data数据失败

B语句则可以正常的读写valid_data中数据的数据内容

不知道照成上述问题的原因,本人估计是内存对齐的问题

代码展示:

uint8_t __NeetErease(uint32_t start_addr ,uint32_t len)
{//该函数len必须是4的倍数 即 len%4==0volatile uint32_t i=0;for(;i<len;i++){if(Read_4Byte_flash(start_addr)!=0xffffffff){break;}start_addr+=4;}return i==len ? 0:1;
}
uint8_t _Erease_Flash(uint32_t base_addr)
{uint8_t flag=0;FLASH_EraseInitTypeDef hflash;//擦除页hflash.TypeErase=FLASH_TYPEERASE_PAGES; //擦除类型 hflash.Banks = FLASH_BANK_1;hflash.PageAddress = base_addr;//页基地址hflash.NbPages = 1;//需要擦除的页数uint32_t error=0;if(HAL_FLASHEx_Erase(&hflash,&error)==HAL_OK){flag=1;}return flag;
}uint8_t Write_One_Page_Data(volatile uint32_t base_addr,volatile uint32_t page_offst,volatile uint32_t *ppdata,volatile uint32_t erease_size)
{volatile uint8_t flag=0;volatile uint16_t i=0;volatile uint16_t cnt;volatile uint32_t cur_addr=0;//static uint8_t add=0;//add++;//HAL_FLASH_Unlock();if(__NeetErease(base_addr,erease_size)){memset((void*)flash_data,0,STM32_FLASH_PAGE_SIZE);for(i=0;i<page_offst ;i++){cur_addr = base_addr + i*4;flash_data[i]=Read_4Byte_flash(cur_addr);}_Erease_Flash(base_addr);//写入数据i=page_offst;cnt = erease_size+page_offst;for(;i<cnt;i++){flash_data[i]=*ppdata;//flash_data[i]=i+add;ppdata++;}for(i=0;i<erease_size+page_offst;i++){cur_addr = base_addr+i*4;if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE){HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,flash_data[i]);}}}else //不需要擦除就从偏移开始{for(i=page_offst;i<erease_size+page_offst;i++){cur_addr = base_addr+i*4;if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE){HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,*ppdata);ppdata++;}}}//HAL_FLASH_Lock();return 1;
}/*
本函数操作的整型数据 4个字节;flash是以一个字节为一个地址的
addr 起始地址
data 数据开始地址
surplus  整型数据长度1len=4Byte ;最大为     STM32_FLASH_PAGE_SIZE/4;
*/uint8_t Write_N_4Byte_flash(uint32_t addr,uint32_t *data,uint32_t len)
{volatile uint32_t start_page=0;    //起始页volatile uint32_t page_size=0;     //需要操作页的大小volatile uint32_t _offset=0;       //页操作页码的起始地址volatile uint32_t page_offset=0;   //页偏移volatile uint32_t erease_size=0;  //本次操作页可以使用的剩余大小volatile uint32_t base_addr=0;    //本次操作页的基地址      volatile uint32_t surplus=0;start_page=((uint32_t)addr-STM32_FLASH_BASE)/STM32_FLASH_PAGE_SIZE;_offset = (((uint32_t)addr-STM32_FLASH_BASE)%STM32_FLASH_PAGE_SIZE)/4;    if(PAGE_INT_SIZE-_offset>=len){page_size=1;surplus=0;}else{page_size=1;surplus = len-(PAGE_INT_SIZE-_offset);page_size +=surplus/PAGE_INT_SIZE + surplus%PAGE_INT_SIZE>0?1:0;}surplus=len;for(page_offset=0;page_offset<page_size;page_offset++){if(page_offset==0){erease_size =(PAGE_INT_SIZE-_offset)<surplus ? (PAGE_INT_SIZE-_offset):surplus;base_addr = STM32_FLASH_BASE + start_page*STM32_FLASH_PAGE_SIZE;surplus = len-erease_size;}else{_offset=0;erease_size =surplus>PAGE_INT_SIZE ? PAGE_INT_SIZE:surplus;base_addr = STM32_FLASH_BASE + (start_page+page_offset)*STM32_FLASH_PAGE_SIZE;surplus = surplus-erease_size;}Write_One_Page_Data(base_addr,_offset,data,erease_size);    data+=erease_size;//_offset=0;}return 1;
}

补充说明,问题产生原因:

上图中给指针赋值就会出问题,程序就会跑到HardFault_Handler()里

0x20000a1和0x20000a0 都不是4的倍数

根据map文件的内容可以看见每个变量都是4的倍数的地址,STM32内存4字节对齐

STM32 存在字节对齐指针变量的地址都必须是4的倍数相关推荐

  1. 对指针变量取地址_C语言指针简介(amp;和*运算符)

    取地址符(&) 和  取值符(*) (1)& 运算符 :用于取一个对象的地址 例如:int *p;    p = &c;    将c的地址赋值给指针变量p,我们称p为 &quo ...

  2. STM32 终极字节对齐解析

    一.全局变量对齐问题: 基本上用户定义的变量是几个字节就是几字节对齐,这个比较好理解. uint8_t定义变量地址要1字节对齐. uint16_t定义变量地址要2字节对齐. uint32_t定义变量地 ...

  3. C语言中 指针变量 取地址符的用法 *指针变量名的用法

    文章目录 总结 Intro Code 图示 总结 众所周知,内存可以看成一个一个相邻的格子(类比Excel),而数据就存储于这些格子之中(size大的变量占用格子数多,size小就占用小).而每个格子 ...

  4. 对指针变量取地址意义

    先说结论 对一级指针取地址运算就是就相当于二级指针 #include<stdio.h> void func(int** a, int** b) {static int x = 100;st ...

  5. stm32中字节对齐问题(__align(n),__packed用法)

    http://www.openedv.com/thread-7415-1-1.html

  6. keil+mdk+c语言,keil mdk+stm32的ac5和 ac6两个编译器下的字节对齐操作方法

    最近在使用ac6.9的编译器,编译速度是真的很快,使用stm32的hal库编译速度也比ac5的编译器快很多. 本文试验stm32中字节对齐的代码测试,主要是结构体,因为结构体中实际项目中用到最多,同时 ...

  7. 一个指针变量占几个字节

    int main() {int a=2;char b = '2';int *p_a;char *p_b;p_a = &a;p_b = &b;printf("%d %d&quo ...

  8. C++字节对齐(地址对齐)

    1.什么是字节对齐 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是,在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型 ...

  9. 【C语言】结构体类型和结构体变量(字节对齐)

    目录 一.结构体类型定义 二.结构体变量的定义 ①先定义结构体类型,再定义结构体变量 ②在定义结构体类型的同时,定义结构体变量 ③直接定义结构体变量 三.结构体变量的内存分配 四.结构体变量的初始化 ...

最新文章

  1. 【财经】创业的10条定律 10大烦恼
  2. 4gl 上传文件_文件管理密码相册工具app下载-文件管理密码相册工具app安卓版下载v1.8...
  3. Python基础--Python3基础语法
  4. 转载——开阔自己的视野,勇敢的接触新知识
  5. linux centos命令语法,linux-centos7
  6. 写给准备学习Linux的人
  7. Python编程基础21:GUI编程
  8. 二分分类2.1 二分分类
  9. 整理了一个目录,督促自己写文章
  10. 吴恩达深度学习——提高算法运行效率
  11. 7-3 组个最小数 (20 分)
  12. AutoCAD2012从入门到精通中文视频教程 第46课 三维实体及创建实体命令1(个人收藏)
  13. python找重复元素_Python笔记(二)查找重复元素
  14. 自动(智能)驾驶 | 全网第一本激光雷达手册阅读指南(上)
  15. ie浏览器多开-----同时登陆多个账号
  16. 小学计算机教师业务笔记,2016-2017学年度小学教师业务学习笔记
  17. android逆向知乎,Android逆向之路---为什么从后台切换回app又显示广告了
  18. Java教程,Java视频,培训机构免费资源下载汇总帖,全网最有情怀,集合所以品牌机构(持续更新...)
  19. mysql中如何分页查询_MySQL_mysql分页原理和高效率的mysql分页查询语句,以前我在mysql中分页都是用的 l - phpStudy...
  20. Windows XP 故障恢复控制台的说明

热门文章

  1. efcore调用函数_EF Core 3.1 执行sql语句的几种方法
  2. java实现多表增加_java多表插入数据
  3. 看图识物_有声绘本故事《晚安,建筑工地》看图识物,嘘,晚安
  4. freertos 创建互斥量_freertos任务通信
  5. 微信小程序怎么弄成链接_自己怎么弄微信小程序?
  6. MySQL去重保留最大的那条记录(取最新的记录)
  7. 可用于wpf的图表控件:WPFTookit Chart
  8. 如何禁止chrome浏览器http自动转成https 【转】
  9. 分布式、集群的概念、区别
  10. 第九章 Servlet工作原理解析