cazure / small_modbus

modbus c library
Apache License 2.0
16 stars 6 forks source link

device->user_data在rt-thread驱动层被使用,导致hardfult #1

Open kylongmu opened 1 year ago

kylongmu commented 1 year ago

在官方rt-thread源bsp\wch\risc-v\ch32v307v-r1开发板工程下测试直接死机 msh > hardfult mepc:00013a5c mcause:00000004 mtval:50504251 跟踪后在small_modbus_port_rtthread.c文件中

` static int _modbus_rtdevice_open(small_modbus_t smb) { small_modbus_port_rtdevice_t smb_port_device = (small_modbus_port_rtdevice_t *)smb->port; if (smb_port_device->device) { //屏蔽下面一行可以执行无硬件报错,应该是这里引起问题 //smb_port_device->device->user_data = smb_port_device;

    rt_device_set_rx_indicate(smb_port_device->device, _modbus_rtdevice_rx_indicate);
    rt_device_open(smb_port_device->device, smb_port_device->oflag);

`


把smb_port_device->device->user_data = smb_port_device; 放到rt_device_open后执行,能通过,但是一旦接收到数据,接收数据引用user_data就直接hardfult。看来是user_data的赋值有问题,再引用它的指针时发生了内存越界错误。

进一步检查后发现user_data在Libraries\ch32_drivers\drv_usart.c中被使用了 ` static rt_err_t ch32_configure(struct rt_serial_device serial, struct serial_configure cfg) { struct ch32_uart *uart; GPIO_InitTypeDef GPIO_InitStructure={0};

RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);

uart = (struct ch32_uart *) serial->parent.user_data;//此处被驱动使用

` 这个变量已经被驱动层代码占用了,应用层再用当然指针出错了,device->user_data不能用。

kylongmu commented 1 year ago

在其他系列MCU的drv_usart.c中查看: ` static rt_err_t hpm_uart_configure(struct rt_serial_device serial, struct serial_configure cfg) {

RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);

uart_config_t uart_config;
struct hpm_uart *uart  = (struct hpm_uart *)serial->parent.user_data;

user_data也被使用了。 再看stm32的drv_usart.c static rt_err_t stm32_configure(struct rt_serial_device serial, struct serial_configure cfg) { struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL);

uart = rt_container_of(serial, struct stm32_uart, serial);

用了一个奇怪的方式,查到这个宏:

define rt_container_of(ptr, type, member) \

((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

` 晦涩难懂,但是没有占用user_data 所以这个user_data被其他系列MCU的驱动使用了,只能在stm32上面正确运行。

cazure commented 1 year ago

好吧,在写这个代码前我还研究过这个驱动user_data到底是给驱动做用户数据还是给应用做用户数据使用。 我误认为是给应用层做数据使用的。 所以这个地方得改一下。

kylongmu commented 1 year ago

好吧,在写这个代码前我还研究过这个驱动user_data到底是给驱动做用户数据还是给应用做用户数据使用。 我误认为是给应用层做数据使用的。 所以这个地方得改一下。

多谢修复该问题,另外串口驱动现在有了V2版本,还请考虑一下兼容性

cazure commented 1 year ago

这是我以前提问的帖子 https://club.rt-thread.org/ask/question/ead12ad1be79c8f0.html V2版本的串口驱动应该不需要改动吧,直接使用中断接收+轮询发送即可。如果是DMA之类的调整接收的帧超时或者字节超时应该也能适应的。