今天遇到一个有关FLASH写入数组存储内容的事情,在做OTA升级过程中,发现传出的协议内容与解密后的内容不一致,最后发现是FlASH写入出错了。
直接看代码
u8 Mem_Read_buffer[4096];
RamSource = (u32)Mem_Read_buffer;
//循环搬运flash数据
for(writeTime = 0; writeTime < (Read_Memorysize/4);writeTime++)
{
//Flash_Write(FlashDes,RamSource);//错误
Flash_Write(FlashDes,*(u32 *)RamSource);
FlashDes += 4;
RamSource += 4;
}
//另外void Flash_Write(uint32_t address, uint32_t data);
比较一下,
Flash_Write(FlashDes,RamSource);
Flash_Write(FlashDes,*(u32 *)RamSource);
这两句有什么不一样?
首先第一句的Flash_Write写入的是Mem_Read_buffer数组的首地址,与Mem_Read_buffer的内容并无关系。
第二句写入的是数组前4个元素,为什么是4个字节的内容,而不是一个字节的内容?
首先,强制类型转换
// 将 RamSource(u32 类型的地址值 0x1000)转换为 u32* 指针
u32* p = (u32*)RamSource; // p 指向地址 0x1000
然后,解引用指针
// 读取 p 指向的地址(0x1000)处的 4 字节数据
u32 value = *p;
因为*p是u32*数据类型,编译器会从0x1000开始连续读取4字节:0x11,0x22,0x33,0x044
这4字节会被合并为一个u32整数。小端模式为0x44332211,大端模式:0x11223344
那为什么是前4字节?
-
指针类型决定访问范围:
u32*
指针的解引用操作隐式约定“从指针指向的地址开始,读取 sizeof(u32) 字节”(即 4 字节)。这是由u32
的数据类型决定的,与指针原本的来源(u8
数组)无关。 -
物理内存视角:
无论指针原本指向什么类型,强制转换为u32*
后,编译器会“认为”它指向一个u32
类型的变量,因此必须读取 4 字节来构造这个变量。 -
对比直接使用
u8
数组 -
如果直接以
u8
类型访问数组:u8 byte1 = Mem_Read_buffer[0]; // 读取 0x11(1 字节) u8 byte2 = Mem_Read_buffer[1]; // 读取 0x22(1 字节)
而通过
u32*
指针解引用,一次性读取了 4 字节,这就是两者最本质的区别。