This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: TI C/C++ Compiler
Hi,
During our integration testing, we are finding an issue on the TM4C USB side.
When the device is started, the communication is happening fine. After some couple of transaction the device is going to a hang state.
When we debug and checked the process is halting in USBHCDPipeWrite() function in usbhostenum.c. It is staying in the while(1) loop inside
there. We printed g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState which is always 7 and no condition check available for this state inside this
function.
Kindly help us in debugging this issue.
Thank you,
Deepanraj.A
Hi Charles,
But already the fix suggested in the provided link is fixed in version 2.1.4.178 version right.
Moreover in our case it does not enter this loop only.As we added debug print and checked bUseDMA is always true in our case.
Thank you,
Deepanraj.A
Hello Deepanraj,
If you are using DMA, I was told awhile back by a former expert of a couple other DMA impacting adjustments that were needed. One of which impacts USBHCDPipeWrite as well. Can you try to apply these? That includes additional fixes beyond what was suggested (plus a slightly cleaner fix for the prior E2E post).
They are on our list to update on TivaWare as well.
Replace the full functions in each file with the new ones.
File: usblib\host\usbhostenum.c
//***************************************************************************** // //! This function is used to write data to a USB HCD pipe. //! //! \param ui32Pipe is the USB pipe to put data into. //! \param pui8Data is a pointer to the data to send. //! \param ui32Size is the amount of data to send. //! //! This function will block until it has sent as much data as was //! requested using the USB pipe's FIFO. The caller should have registered a //! callback with the USBHCDPipeAlloc() call in order to be informed when the //! data has been transmitted. The value returned by this function can be less //! than the \e ui32Size requested if the USB pipe has less space available //! than this request is making. //! //! \return This function returns the number of bytes that were scheduled to //! be sent on the given USB pipe. // //***************************************************************************** uint32_t USBHCDPipeWrite(uint32_t ui32Pipe, uint8_t *pui8Data, uint32_t ui32Size) { uint32_t ui32Endpoint, ui32RemainingBytes, ui32ByteToSend, ui32PipeIdx; bool bUseDMA; // // Determine which endpoint interface that this pipe is using. // ui32Endpoint = IndexToUSBEP((EP_PIPE_IDX_M & ui32Pipe) + 1); // // Get index used for looking up pipe data // ui32PipeIdx = ui32Pipe & EP_PIPE_IDX_M; // // Set the total number of bytes to send out. // ui32RemainingBytes = ui32Size; // // Default to using DMA. // bUseDMA = false; // // Initialize the bytes to send to all of the remaining bytes. // ui32ByteToSend = ui32RemainingBytes; // // Send all of the requested data. // while(ui32RemainingBytes != 0) { // // If uDMA is not enabled for this pipe, or if the uDMA workaround // is applied, then don't use uDMA for this transfer. // if(ui32Pipe & EP_PIPE_USE_UDMA) { // // Disable the USB interrupt. // OS_INT_DISABLE(g_sUSBHCD.ui32IntNum); // // Start the DMA transfer. // if(USBLibDMATransfer(g_sUSBHCD.psDMAInstance, g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].ui8DMAChannel, pui8Data, ui32RemainingBytes) != 0) { if(ui32RemainingBytes < g_sUSBHCD.psDMAInstance->pui32MaxPacketSize[ui32PipeIdx]) { g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriteDMASend; } else if((ui32RemainingBytes % g_sUSBHCD.psDMAInstance->pui32MaxPacketSize[ui32PipeIdx]) == 0) { g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriteDMA; } else { g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriteDMASend; } bUseDMA = true; } // // Enable the USB interrupt. // OS_INT_ENABLE(g_sUSBHCD.ui32IntNum); } if(bUseDMA == false) { // // Only send 64 bytes at a time if not using DMA. // if(ui32ByteToSend > g_sUSBHCD.psDMAInstance->pui32MaxPacketSize[ui32PipeIdx]) { ui32ByteToSend = g_sUSBHCD.psDMAInstance->pui32MaxPacketSize[ui32PipeIdx]; } else { // // Send the requested number of bytes. // ui32ByteToSend = ui32RemainingBytes; } // // Start a write request. // g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeWriting; // // Disable uDMA on the USB endpoint // MAP_USBEndpointDMADisable(USB0_BASE, ui32Endpoint, USB_EP_HOST_OUT); // // Put the data in the buffer. // MAP_USBEndpointDataPut(USB0_BASE, ui32Endpoint, pui8Data, ui32ByteToSend); // // Schedule the data to be sent. // MAP_USBEndpointDataSend(USB0_BASE, ui32Endpoint, USB_TRANS_OUT); } // // Wait for a status change. // while(1) { // // If an error event occurs then exit out of the loop. // if(g_sUSBHCD.ui32IntEvents & (INT_EVENT_DISCONNECT | INT_EVENT_VBUS_ERR | INT_EVENT_POWER_FAULT)) { // // Set the pipe state to error. // g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeError; // // Needs to be set to exit out of large while loop. // ui32RemainingBytes = 0; break; } // // If the data was successfully sent then decrement the count and // continue. // else if(g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState == ePipeDataSent) { // // Decrement the remaining data and advance the pointer. // ui32RemainingBytes -= ui32ByteToSend; pui8Data += ui32ByteToSend; // // If there are less than 64 bytes to send then this is the // last of the data to go out. // if(ui32RemainingBytes < g_sUSBHCD.psDMAInstance->pui32MaxPacketSize[ui32PipeIdx]) { ui32ByteToSend = ui32RemainingBytes; } break; } else if(g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState == ePipeStalled) { // // Zero out the size so that the caller knows that no data was // written. // ui32Size = 0; // // Needs to be set to exit out of large while loop. // ui32RemainingBytes = 0; // // If DMA is being used, then disable the channel. // if(bUseDMA == true) { // // Disable the DMA channel. // USBLibDMAChannelDisable(g_sUSBHCD.psDMAInstance, g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].ui8DMAChannel); } // // This is the actual endpoint number. // USBHCDClearFeature( g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].psDevice->ui32Address, ui32Pipe, USB_FEATURE_EP_HALT); // // If there was a stall, then no more data is coming so break // out. // break; } else if(g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState == ePipeError) { // // An error occurred so stop this transaction and set the // number of bytes to zero. // ui32Size = 0; // // Needs to be set to exit out of large while loop. // ui32RemainingBytes = 0; break; } } } // // Go Idle once this state has been reached. // g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeIdle; return(ui32Size); }
File: usblib\usbdma.c
//***************************************************************************** // // USBLibDMATransfer() for USB controllers with an integrated DMA controller. // //***************************************************************************** static uint32_t iDMAUSBTransfer(tUSBDMAInstance *psUSBDMAInst, uint32_t ui32Channel, void *pvBuffer, uint32_t ui32Size) { uint32_t ui32PacketCount; if((uint32_t)pvBuffer & 0x3) { return(0); } // // Mark this channel as pending and not complete. // psUSBDMAInst->ui32Pending |= (1 << (ui32Channel - 1)); psUSBDMAInst->ui32Complete &= ~(1 << (ui32Channel - 1)); // // Save the pointer to the data and the byte count. // psUSBDMAInst->ppui32Data[ui32Channel - 1] = pvBuffer; psUSBDMAInst->pui32Count[ui32Channel - 1] = ui32Size; // // Set the address. // USBDMAChannelAddressSet(psUSBDMAInst->ui32Base, ui32Channel - 1, pvBuffer); // // Set the number of transfers. // USBDMAChannelCountSet(psUSBDMAInst->ui32Base, ui32Channel - 1, ui32Size); // // Set the mode based on the size of the transfer. More than one // packet requires mode 1. // if(ui32Size >= psUSBDMAInst->pui32MaxPacketSize[ui32Channel - 1]) { // // Calculate the number of packets required for this transfer. // ui32PacketCount = ui32Size / psUSBDMAInst->pui32MaxPacketSize[ui32Channel - 1]; if(ui32Size % psUSBDMAInst->pui32MaxPacketSize[ui32Channel - 1]) { ui32PacketCount += 1; } USBEndpointPacketCountSet(psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], ui32PacketCount); // // Configure the USB DMA controller for mode 1. // USBEndpointDMAConfigSet(psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], psUSBDMAInst->pui32EPDMAMode1[ui32Channel - 1]); USBDMAChannelConfigSet(psUSBDMAInst->ui32Base, ui32Channel - 1, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], psUSBDMAInst->pui32Config[ui32Channel - 1] | USB_DMA_CFG_MODE_1); // // Enable DMA on the endpoint. // if(psUSBDMAInst->pui32Config[ui32Channel - 1] & USB_DMA_CFG_DIR_TX) { // // Make sure that DMA is enabled on the endpoint. // MAP_USBEndpointDMAEnable( psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], USB_EP_HOST_OUT); } else { // // Make sure that DMA is enabled on the endpoint. // MAP_USBEndpointDMAEnable( psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], USB_EP_HOST_IN); } // // Enable the DMA channel. // USBDMAChannelEnable(psUSBDMAInst->ui32Base, ui32Channel - 1); } else { // // Configure the USB DMA controller for mode 0. // USBEndpointDMAConfigSet(psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], psUSBDMAInst->pui32EPDMAMode0[ui32Channel -1]); USBDMAChannelConfigSet(psUSBDMAInst->ui32Base, ui32Channel -1, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], psUSBDMAInst->pui32Config[ui32Channel - 1] | USB_DMA_CFG_MODE_0); // // In mode 0 only enable DMA transfer for mode 0. // if(psUSBDMAInst->pui32Config[ui32Channel - 1] & USB_DMA_CFG_DIR_TX) { // // Make sure that DMA is enabled on the endpoint. // MAP_USBEndpointDMAEnable( psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], USB_EP_HOST_OUT); // // Enable the DMA channel. // USBDMAChannelEnable(psUSBDMAInst->ui32Base, ui32Channel - 1); } else { // // Make sure that DMA is disabled on the endpoint, it will // be enabled when the endpoint interrupt occurs. // MAP_USBEndpointDMADisable( psUSBDMAInst->ui32Base, psUSBDMAInst->pui8Endpoint[ui32Channel - 1], USB_EP_HOST_IN); // // Returns 0 so that when DMA is not used, the bUseDMA flag in the calling function // is set to false. // return(0); } } return(ui32Size); }
Hello Deepanraj,
I see. We have not done Ethernet over USB applications with the TM4C, and we do not support that application. While I don't think this issue is purely related to that, I am in a tough position on trying to help with the PipeWrite issue given that:
1) I have not been able to replicate the issue at all
2) No other customer has come across an issue that our known fixes do not address
I suspect the core issue here is that the way Ethernet over USB works is using PipeWrite in a manner that brings this error up, but because it's not recreatable for me, and we do not support Ethernet over USB, there is not really anything else I can do to support this issue.
Given our lack of a support model for Ethernet over USB, you may need to consider other options for this application.
Hi Ralph,
Actually in our case we are using RNDIS host protocol in our application to establish internet connection.
When we continuously read from the USB the PipeWrite function is in a state that it continuously in the while loop.
and is there any constrain if a bluk data or if contiously the pipe is written it might go inside the loop and it wont get any interrupt from the USB for it exit from the loop.
Thank you,
Deepanraj