Closed chengshuihang closed 2 years ago
Hi @chengshuihang 谢谢你的提问,NX_PHYSICAL_HEADER定义成16是为了保证TCP/IP 头四字节对齐,可以参考这个issue106看是否能够解决问题。
我看了https://github.com/azure-rtos/netxduo/issues/106,我与他的目的的一致的。但是在解答中没有提供 零拷贝 DMA的解决方案。看来只能放弃了,这个后续不考虑,添加下吗?毕竟DMA偏移功能不是都有的
保证4字节对齐是为了提高效率,不需要1字节1字节的进行解析和处理,这是NetXDuo的处理方法。遇到DMA没有偏移功能的,可能需要准备一个buffer复制数据,然后再传输给NetX。
About USB DMA that is based on STM32 HCD, it seems there is no zero-copy solution the rough code attempt to create copy of aligned buffer could be: In ux_hcd_stm32_request_bulk_transfer.c, change code to allocate aligned cache safe buffer for DMA, and copy data:
#if 1 /* Auto align buffer - allocate and copy if buffer is unaligned. */
/* In case DMA enabled, check data buffer alignment. */
ed -> ux_stm32_ed_data = transfer_request->ux_transfer_request_data_pointer;
if (hcd_stm32 -> hcd_handle -> Init.dma_enable &&
length > 0 &&
((ULONG)ed -> ux_stm32_ed_data & (~0x3ul)) != 0)
{
/* Allocate new aligned cache safe memory. */
ed -> ux_stm32_ed_data = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, length);
if (ed -> ux_stm32_ed_data == UX_NULL)
return(UX_MEMORY_INSUFFICIENT);
/* Copy data if it's OUT. */
if (direction == 0)
_ux_utility_memory_copy(ed -> ux_stm32_ed_data, transfer_request->ux_transfer_request_data_pointer, length);
}
/* Submit the transfer request. */
HAL_HCD_HC_SubmitRequest(hcd_stm32 -> hcd_handle, ed -> ux_stm32_ed_channel,
direction,
EP_TYPE_BULK, USBH_PID_DATA,
ed -> ux_stm32_ed_data,
length, 0);
#else
/* Submit the transfer request. */
HAL_HCD_HC_SubmitRequest(hcd_stm32 -> hcd_handle, ed -> ux_stm32_ed_channel,
direction,
EP_TYPE_BULK, USBH_PID_DATA,
transfer_request->ux_transfer_request_data_pointer,
length, 0);
#endif
In ux_hcd_stm32_callback.c::HAL_HCD_HC_NotifyURBChange_Callback, change code to use allocated buffer and free it after transfer done:
#if 1 /* Auto align buffer - request again. */
/* Submit the transmit request. */
HAL_HCD_HC_SubmitRequest(hcd_stm32 -> hcd_handle, ed -> ux_stm32_ed_channel,
0, ed -> ux_stm32_ed_type, USBH_PID_DATA,
ed -> ux_stm32_ed_data +
transfer_request -> ux_transfer_request_actual_length,
ed -> ux_stm32_ed_packet_length, 0);
#else
/* Submit the transmit request. */
HAL_HCD_HC_SubmitRequest(hcd_stm32 -> hcd_handle, ed -> ux_stm32_ed_channel,
0, ed -> ux_stm32_ed_type, USBH_PID_DATA,
transfer_request->ux_transfer_request_data_pointer +
transfer_request -> ux_transfer_request_actual_length,
ed -> ux_stm32_ed_packet_length, 0);
#endif
#if 1 /* Auto align buffer - copy and free buffer (if allocated). */
if (ed -> ux_stm32_ed_data != transfer_request -> ux_transfer_request_data_pointer)
{
if (ed -> ux_stm32_ed_dir)
{
_ux_utility_memory_copy(transfer_request -> ux_transfer_request_data_pointer,
ed -> ux_stm32_ed_data,
transfer_request -> ux_transfer_request_actual_length);
}
_ux_utility_memory_free(ed -> ux_stm32_ed_data);
ed -> ux_stm32_ed_data = UX_NULL;
}
#endif
/* Invoke callback function. */
if (transfer_request -> ux_transfer_request_completion_function)
transfer_request -> ux_transfer_request_completion_function(transfer_request);
In ux_hcd_stm32_endpoint_destroy.c and ux_hcd_stm32_endpoint_reset.c, add code to free allocated buffer on abnormal stops:
#if 1 /* Auto align buffer - free buffer (if allocated). */
if (ed -> ux_stm32_ed_data &&
ed -> ux_stm32_ed_data != endpoint -> ux_endpoint_transfer_request -> ux_transfer_request_data_pointer)
_ux_utility_memory_free(ed -> ux_stm32_ed_data);
#endif
谢谢!
Closing
@xiaocq2001 您好!我按照您的方案进行了一些修改,使用的STM32H743,打开了高速缓存,现在USB它可以完成枚举,但是无法完成DHCP,我无法确认我bulk是否正确,您能帮我确认下吗?截图是修改的位置,附件中是修改后的文件。
ux_hcd_stm32_request_bulk_transfer.c修改内容:
ux_hcd_stm32_periodic_schedule.c修改内容:
ux_hcd_stm32_request_control_transfer.c修改内容:
ux_hcd_stm32_callback.c修改内容:
ux_hcd_stm32.h修改内容:
usb_dma.zip
The use of transfer_request -> ux_transfer_request_packet_length
is not safe, since in upper layer it's used as a base to check if short packet is expected, please use some driver local field to replace it, e.g., UX_HCD_STM32_ED::ux_stm32_ed_packet_length
. Leave it unchanged in HCD.
我不确定是不是transfer_request -> ux_transfer_request_packet_length原因,我运行一段时间后,系统中会发生死锁,死锁位置是_ux_utility_memory_allocate,非常无奈,我将_ux_utility_memory_free移回各个_ux_utility_memory_allocate的函数里面,保证了数据同步,这样系统不会再发生死锁了,然后我发现软件中会出现数据翻转的错误,我正在排查问题。截图如下:
这是端点信息
transfer_request -> ux_transfer_request_packet_length
is used in upper layer as max packet size for zero length packet appending check. E.g., in CDC-ECM if OUT total length is multiple of this packet length, a ZLP is appended to terminate the transfer. That's why you can see a 0 byte OUT follows 42 bytes OUT in your tracing figure.
是的,这个空包是正常的,但是两次数据包都是DATA1,却让我无法理解
现在驱动发送0长度数据包,DATA0/DATA1不会切换,关闭dma是正常的,我需要找下问题。
驱动这里,当长度为0时,dma打开之后数据包不会翻转,不开dma会翻转,同理这个问题在in中也存在如下图
我明天尝试修改这里,看看能不能正常工作
Yes. It's a bug in HAL, hhcd->hc[ch_num].xfer_count
should be used instead of hhcd->hc[ch_num].XferSize
A fix is underway from ST and will release soon.
@liydu 非常感谢,另外这个最新USB驱动库好像还是有点问题。如果不使用dma的话,数据发送了一段时间后会停止发送。我添加了一些输出代码,用于输出信息吗,观测现象
Thanks for sharing the debugging information. Not sure which version of STM HAL you are using, but I'll share it with ST.
IDE是STM32CubeIDE 1.12.0,软件包是HAL版本是H7的1.11.0,使用ECM做主机,用中断进行通信。上面的修改在移除测试代码test_can_send后,还是不能正常工作。我之后修改了如下的代码,已经运行了一个晚上了,目前运行状态良好。
您好,我的以太网驱动是USB ECM,为了使能USB DMA功能我需要4字节对齐,当NX_PHYSICAL_HEADER为16时,在USB需要设置以太网帧包头(14字节),这将导致数据包地址不是4字节对齐的,因此我需要将NX_PHYSICAL_HEADER修改为14.设置完成后,我发现DHCP计算的IP Checksum与NX_PHYSICAL_HEADER为16的IP Checksum不一致,且NX_PHYSICAL_HEADER为14时,DHCP服务器不会响应。 下面截图是两次DHCP报文
我该怎么样,才能达成目的?