在移植一个某个程序时,以前平台(arm Cortex-M3)运行得很好的程序,突然到新的平台(arm Cortex-M7)突然出现hard fault 了
FPU ac
tive!
usage fault:
SCB_CFSR_UFSR:0x100 UNALIGNED
这种错误,我通过cpu pc寄存器值和map文件定位到了在 memcpy 函数中,猜测应该是复制数据时地址未对齐引起的。 我开始以为 memcpy 就是 rt_memcpy ,所以把 rt_memcpy 函数的4字节对齐复制变成单字节复制,发现问题依然存在。
然后我通过搜索map文件发现,很多软件包并没有使用rt_memcpy ,而是使用编译器提供的 memcpy 。即使 我通过下面这样的代码,想把memcpy重定向到 rt_memcpy依然没有丝毫效果。
void *memset(void *src, int c, size_t n)
{
return rt_memset(src, c, n);
}
void *memcpy(void *dest, const void *src, size_t n)
{
return rt_memcpy(dest, src, n);
}
然后我在map文件中发现一些函数,部分map文件内容
ntp.o(i.ntp_get_time) refers to rt_memcpy_w.o(.text) for __aeabi_memcpy4
ntp.o(i.ntp_get_time) refers to rt_memclr_w.o(.text) for __aeabi_memclr4
rt_memcpy_v6.o(.text) refers to rt_memcpy_w.o(.text) for __aeabi_memcpy4
rt_memmove_v6.o(.text) refers to rt_memcpy_v6.o(.text) for __aeabi_memcpy
rt_memmove_v6.o(.text) refers to rt_memmove_w.o(.text) for __memmove_aligned
aeabi_memset.o(.text) refers to rt_memclr.o(.text) for _memset
rt_memclr.o(.text) refers to rt_memclr_w.o(.text) for _memset_w
strncpy.o(.text) refers to rt_memclr.o(.text) for __aeabi_memclr
我才发现原来memcpy并不是直接使用调用的,编译器还分了单字节复制和4字节复制的方式 rt_memcpy_v6 rt_memcpy_w aeabi_memcpy aeabi_memcpy4 然后我再次重新定义
void __aeabi_memcpy(void *dest, const void *src, size_t n)
{
rt_memcpy(dest, src, n);
}
void __aeabi_memcpy4(void *dest, const void *src, size_t n)
{
rt_memcpy(dest, src, n);
}
再一编译发现问题消失了。
也有查找网上资料说 使用 #pragma pack(1) 将变量设置成单字节对齐,这样使用memcpy时就会调用__aeabi_memcpy4而是使用 __aeabi_memcpy函数
不知道大家有没有更好的办法,能使memcpy完全使用rt_memcpy