我有一个板、将 F28M35H52C1配置为 USB 主机、并连接4端口 USB 集线器、条形码扫描仪、USB 闪存驱动器和定制 USB 大容量器件。 该项目的 USB MSC 部分源自控制套件中的 USB MSC 示例。
该问题 与配置为使用 DMA 的端点有关。 如果端点配置为使用 DMA、并且该端点的管道索引>= 3、则数据传输失败。 USBHCDPipeRead 或 USBHCDipeWrite 将在无限循环中挂起、等待:while (g_sUSBHCD.USBINPipes[ulPipeIdx].estay == pipe_reading) -在管道中。
该问题从 USBHCDPipeAllocSize ()开始,适用于"输入"和"输出"管道。 该函数的相关代码如下所示:
if (ulEndpointType & EP_PIPE_USE_UDMA)
{
//
//前三个端点的某些通道是固定的
//部件使管道偏压以匹配这一点,因为最好是
//可能的。
//
if (lIdx < 3)
{
//
//检查固定通道是否可用于此目的
// USB 管道。
//
if (g_sUSBHCD.ucDMAChannels[lIdx * 2]==
USBHCD_DMA_unused)
{
//
//默认通道可用,因此请使用它。
//
g_sUSBHCD.ucDMAChannels[lIdx * 2]= lIdx;
g_sUSBHCD.USBINPipes [lIdx].ucDMAChannel = lIdx * 2;
}
方案
{
//
//如果固定的 USB 管道没有,则转到下一个 USB 管道
//可用。
//
继续;
}
}
方案
{
//
//固定通道不可用或
//管道索引大于前3个管道
///适用于所有器件。
//
for (lDMAIdx = 0;lDMAIdx < MAX_NUM_DMA_CHANNELS;
lDMAIdx += 2)
{
//
//找到任何可用的通道。
//
if (g_sUSBHCD.ucDMAChannels[lDMAIdx]==
USBHCD_DMA_unused)
{
//
//保存索引和 DMA 通道
//信息。
//
g_sUSBHCD.ucDMAChannels[lDMAIdx]= lIdx;
g_sUSBHCD.USBINPipes [lIdx].ucDMAChannel =
lDMAIdx;
}
}
}
当 lIdx >= 3时、否则分支会运行 for 循环以查找其他在较低索引中未使用的可用通道。 如果发现未使用的通道、则会进行相应的设置。 但是、对于每个可用通道、循环执行不会中断、循环会继续。
我在"输入"和"输出"管道设置中添加了一个断点、以防止这种情况发生。 但是、当我重新编译 usblib 并运行代码时、在管道读取和管道写入中仍然存在挂起的情况。
在 USBHCDPipeRead ()和 USBHCDipeWrite ()中,没有对 g_sUSBHCD.USBBINPipes[lIdx].ucDMAChannel,这是用于输入/输出管道传输的实际 DMA 通道。 该代码会假设管道索引小于3、并且可以使用 USB DMA 端点的默认索引。 例如、以下行:
uDMAChannelTransferSet (uDMA_channel_USBEP1RX +(ulPipeIdx * 2)、uDMA_MODE_AUTO、(void *) USBFIFOAddrGet (USB0_BASE、ulEndpoint)、pucData、 (ulBytesRead);
或
uDMAChannelEnable (uDMA_channel_USBEP1RX +(ulPipeIdx * 2));
(ulPipeIdx * 2)用于计算错误的偏移。 我认为代码应该参考 g_sUSBHCD.USBINPipes[ulPipeIdx].ucDMAChannel 以获取正确的 DMA 通道。
我意识到托管3个 USB 设备和集线器可能是 M3的一个极端用例、但我想指出这一点、以防其他人遇到这样的问题。 在我的例子中,作为一个短期的权变措施,我计划修改 USBHCDPipeAllocSize()以在索引大于等于3时禁用 DMA 的使用。 我可以控制正常产品使用中的 USB 端口、以强制 USB 闪存驱动器连接到第一个 USB 集线器端口。