我在MDK518环境下, 使用
STM32F072
芯片,在做结构体时,定义了两个变量saveblock,Storage。用指针访问saveblock成功,访问Storage时就跳转到硬件错误, 两个变量是同一个结构,进行的同样的操作,为什么先定义的那个就没事,后定义的那个旧不能正常访问。
typedef union
{
u8 Mem[6];
struct
{
u8 ID : 8;
u8 Year : 8;
u8 Month : 4;
u8 Day : 6;
u8 Hour : 6;
u8 Minute : 8;
u8 Second : 8;
}Date;
}Date_Union;
typedef struct {
u8 Machine_State[2];
Date_Union Date_Result;
}STORAGE;
STORAGE saveblock,Storage;
int main()
{
u16 *Tmp;
u16 TestValue;
saveblock.Date_Result.Date.ID=0x15;
Storage.Date_Result.Date.ID=0x16;
Tmp = (u16*)&saveblock;
Tmp+=2;
TestValue = *Tmp;
Tmp = (u16*)&Storage;
Tmp+=1;
TestValue = *Tmp; //调试的时候 在这里跳转到硬件错误 不能正常读取
while(1);
}
即使人眼看的不明显也得让编译器明白才行,你的tmp是u16的,但是强制转换的结构体并没有体现出来和它对应的值。
2.指针++后无论“跨度”怎么样确实会指向一个内存,但这个内存不一定是安全或可以用的。STM32永远不会把4GB的存储器地址全部用完且都可访问即使你只是读。
3.内核寄存器寻址和存储器寻址不是一个概念,对于STM32,对内核寄存器寻址只能使用R0~R15等方式(意思就是说你如果不用汇编则无法直接访问到),对存储器寻址可以直接引用其地址值(无论是外设寄存器或者是RAM存储器等)。
你说的“指针跳到STM32的寄存器当中”我对你的理解是对存储器的寻址,当你试图访问系统不允许的位置时自然会引起HardFault。由于你存在不“得体”的强制类型转换,使得内存位置访问变得不可靠,具体你可以调试到此处时打开汇编,看下具体的位置是否被允许访问。但指针错误引用不是导致HardFault的唯一原因,比如大小越位也会导致此类错误。
4.你说的其它MCU可行,那完全是巧合导致的。这中巧合可能由于编译器、芯片类型、存储器映射、代码大小等等各类因素制约,但它基于错误的指针运算,永远都不是安全的即使你看起来“行得通”。
{
u8 Mem[6];
struct
{
u8 ID : 8;
u8 Year : 8;
u8 Month : 4;
u8 Day : 6;
u8 Hour : 6;
u8 Minute : 8;
u8 Second : 8;
}Date;
}Date_Union;
typedef struct {
u8 Machine_State[2];
Date_Union Date_Result;
}STORAGE;
STORAGE saveblock,Storage;
u8 Errno;
void Test(void)
{
u16 *Tmp;
u16 TestValue;
saveblock.Date_Result.Date.ID=0x15;
Storage.Date_Result.Date.ID=0x16;
Tmp = (u16*)&saveblock;
Tmp+=1;
TestValue = *Tmp;
if(TestValue!=0x0015)
{
Errno=1;
}
Tmp = (u16*)&Storage;
Tmp+=1;
TestValue = *Tmp;
if(TestValue!=0x0016)
{
Errno=1;
}
}
你们试试这段代码看看能不能跑通
他们都是STORAGE类型的,即使可以通过强制类型转换你也得转换的“得体”才行。
对于:
Tmp = (u16*)&saveblock;
这种,显然有问题!即使你现在没有出现问题。
语法上看,你把Tmp+=1,相当于u16的指针往下跳u16,跟STORAGE内部完全匹配不上。
u8 *Tmp;
u16 TestValue;
saveblock.Date_Result.Date.ID=0x15;
Storage.Date_Result.Date.ID=0x16;
Tmp = (u8*)&saveblock;
Tmp+=2;
TestValue = *Tmp;
if(TestValue!=0x15)
{
Errno=1;
}
Tmp = (u8*)&Storage;
Tmp+=2;
TestValue = *Tmp;
if(TestValue!=0x16)
{
Errno=1;
}
测试了F76x运行下代码没有问题。楼主看下fault的时候Tmp的地址是不是有问题。
一周热门 更多>