问题
RT1052 rtthread 报错"FPU active!" “UNALIGNED”
开发环境
RT-Thread: v4.0.2(master)
SOC: i.MX RT1050
Board: 野火 RT1052
问题背景
我创建了一个线程去解析UDP数据, 而数据形式是我定义好的一个结构体的形式, 我使用结构体指针去取对应的值, 取前面的值都可以, 但取到float类型的成员时, 程序崩溃, 报如下错误:
使用到的结构体
typedef struct
{
unsigned char protocol_flag;
unsigned char protocol_version;
unsigned char direction;
unsigned char cmd;
unsigned int len;
} UdpProtocolHead;
typedef struct
{
UdpProtocolHead head;
unsigned int data1;
unsigned int data2;
unsigned int data3;
unsigned int data4;
float data5;
float data6;
} UdpProtocolData;
问题代码
int8_t handle_data_tophalf(uint8_t* data, uint32_t len, struct sockaddr_in* client_addr){
UdpProtocolData* data = (UdpProtocolData*)data;
uint8_t* p = (uint8_t*)&data->data5;
printf("data5: %x %x %x %x\r\n", p[0], p[1], p[2], p[3]);
printf("data5: %f\r\n", data->data5);
p = (uint8_t*)&data->fy;
printf("data6: %x %x %x %x\r\n", p[0], p[1], p[2], p[3]);
printf("data6: %f\r\n", data->data6);
}
问题自测
我在main中编写了自测代码来模拟现场, 运行正常, 代码如下:
char data2[] = {0xff, 0x01, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x20, 0x2d, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x3f};
uint8_t* p2 = rt_malloc(sizeof(data2));
memcpy(p2, data2, sizeof(data2));
UdpProtocolData* pdata = (UdpProtocolData*)p2;
printf("head: %x %x %x %x %d\r\n", pdata->head.protocol_flag, pdata->head.protocol_version, pdata->head.direction, pdata->head.cmd, pdata->head.len);
printf("head: %x %x %x %x\r\n", pdata->data_type, pdata->data_index, pdata->timestamp_s, pdata->timestamp_ns);
printf("data: %f %f\r\n", pdata->fy, pdata->fx);
我首先将问题发布到了RT-Thread官方论坛上寻求大家的帮助, 等待了一会, 官方大牛给了回复
类型强转必然出错,还要留意对齐和填充问题。
data地址是多少?
data->data6 地址多少?
float 要求地址对齐到4字节。
这些给了我思路, 然后进行实验检测. 发现
全局变量定义的是 uint32_t 的数据类型, 而该数组地址非四字节对齐, 在使用中强转为结构体指针, 再引用float成员导致字节未对齐问题, 打印查看到 float成员地址也非四字节对齐. 同时又产生了新的疑问: int 类型为什么没有出错, 而float却出错了呢? 是float有什么特殊要求吗?
这里也给我提了一个醒, RT-Thread 报错"FPU active"或"UNALIGNED" 一般都是字节对齐问题.
同时, 我也有遇到过空地址引用成员, 导致"UNALIGNED"错误
原贴地址:
RT1052 rtthread 报错"FPU active!" “UNALIGNED” 原贴
相关文章地址:
单片机开发重点-字节对齐问题
补充"FPU active"代码跟踪
void rt_hw_hard_fault_exception(struct exception_info *exception_info)
{
...//省略
if (exception_info->exc_return & (1 << 2))
{
rt_kprintf("hard fault on thread: %s\r\n\r\n", rt_thread_self()->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
}
else
{
rt_kprintf("hard fault on handler\r\n\r\n");
}
if ( (exception_info->exc_return & 0x10) == 0)
{
rt_kprintf("FPU active!\r\n");
}
#ifdef RT_USING_FINSH
hard_fault_track();
#endif /* RT_USING_FINSH */
while (1);
}
HardFault_Handler PROC
MemManage_Handler
; get current context
TST lr, #0x04 ; if(!EXC_RETURN[2])
ITE EQ
MRSEQ r0, msp ; [2]=0 ==> Z=1, get fault context from handler.
MRSNE r0, psp ; [2]=1 ==> Z=0, get fault context from thread.
STMFD r0!, {r4 - r11} ; push r4 - r11 register
IF {FPU} != "SoftVFP"
STMFD r0!, {lr} ; push dummy for flag
ENDIF
STMFD r0!, {lr} ; push exec_return register
TST lr, #0x04 ; if(!EXC_RETURN[2])
ITE EQ
MSREQ msp, r0 ; [2]=0 ==> Z=1, update stack pointer to MSP.
MSRNE psp, r0 ; [2]=1 ==> Z=0, update stack pointer to PSP.
PUSH {lr}
BL rt_hw_hard_fault_exception