CH32V307 指针强转问题

*(uint16_t *)(&cmd.D_len+1+cmd.D_len)=activeParams.ES_Num.Val++;
cmd是一个结构体,定义时用到过 __attribute__ ((packed)),比较复杂,我就不贴出来了。上边那行代码在stm32  cubeIDE中编译后下载到stm32单片机中没有问题。CH32V307中编译无问题,下载到单片机后,运行就进 HardFault_Handler。

把代码改成:   

    uint8_t *p=&cmd.D_len+1+cmd.D_len;

    p[0]=activeParams.ES_Num.byte.LB;

    p[1]=activeParams.ES_Num.byte.HB;

运行就没有问题了。看样子是指针寻址的对齐问题。后来又做测试,发现 1 如果是1,3,5,都不行,如果是2,4,6,程序可以正常运行。

请问:这是两种内核的区别么?如果我还是想用最开始那种代码写,有啥办法能解决吗?谢谢!


您好,RISC-V内核是不支持非对齐访问的,你之前那种写法可能需要改一下。


能具体解释一下什么情况下算是非对齐访问吗?


struct  __attribute__ ((packed))

{

   uint8_t a;

   uint16_t b;

   uint16_t c;

}t;

t.b=30;这算是非对齐访问吗?谢谢!


您好,关于非对齐访问:如果被访问的内存地址不按照被访问的数据类型的位宽对齐,称为非对齐访问。比如int型占4个字节,则访问int型数据的内存地址需要按照4字节对齐。在进行指针转换或使用packed属性或者编译选项时容易发生非对齐访问,从而导致alignment fault。你一开始的问题应该就是由于上面所说原因导致的。你3楼回复上面的访问也是非对齐访问,但若按照对应的大小访问,不用指针,编译器会进行优化,因此不会报错。


CH32V303,程序无规律进入?HardFault_Handler ,IDE左侧的Debug窗口,只有一个HardFault_Handler?函数显示,并没有像用程序暂停后,可以看到程序运行的上下文,无法分析是什么引起。在网上找资料使用__get_MCAUSE(),查看,都集中在下图的异常。上面的贴子说是RISV不支持非对齐问,然后编译还无错误,在我看来,这能不能算是编译器自己有bug?我是用高级语言写程序,对于内核确实不了解,这些关于对齐的内核的特性编译器自己不能解决么?还需要我自己在写程序时保证?如果必须要由我来保证,那我到底要如何写程序来保证呢? 请沁恒技术给些建议吧!谢谢!

image.png



如果实在解决不了,可否用下图所述的解决方式?目前问题是我不知道引起异常的指令是几个字节长的,mepc加几要如何确定呢?可有这方面的demo代码参考吗?


image.pngimage.png


另外,如果我把单片机换成沁恒的ARM核的,是不是就不会存在这种问题了?


您好,HardFault_Handler的排查思路可参考该贴:https://www.cnblogs.com/wchmcu/p/17545931.html



目前项目上遇到困难,迫切希望厂家能提供一些有价值的支持。我的程序里大量用到强制类型转换,肯请厂家技术能给我一个准确的判断,如果你们的RISC_V核的单片机及其编译器,只要是我用的强制类型转换,就不能保证不进入HardFault_Handler,并也无其它解决方法,那我就不费劲了,我还是改用arm核的单片机了,省得在这里互相浪费时间 。


你好,RISCV的汇编指令有如下特点

*(u8*)(addr)=value;        对应sb 地址可以是11结尾

*(u16*)(addr)=value;      对应sh 地址不能是11结尾,可以是10或00,即必须是2字节对齐

*(u32*)(addr)=value;      对应sw 地址必须是00结尾,即必须是4字节对齐

如果用*(u16*)无法确定后面的地址是否为2字节对齐,可以先判断一下,是2字节就直接用u16写,不是2字节对齐就拆成2次,用u8去写,判断条件if((u32)addr%2==0)。

简单点就直接用u8写2次。



首先需要强调一点您的代码在ARM上跑不会出问题,是因为ARM支持非对齐访问,而RISCV不支持非对齐访问,其次并不是说在RISCV开发过程中不能用强转,而是需要注意如果是按*(uint16*)两字节访问,那么地址的增量也必须是两字节,也就是*(uint16_t *)(&cmd.D_len+2+cmd.D_len)=activeParams.ES_Num.Val++;您所说的代码中的大量强转也需要注意这一点。


只有登录才能回复,可以选择微信账号登录