DMA on M4 causing USB and Ethernet to Hang On Linux (A5)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA on M4 causing USB and Ethernet to Hang On Linux (A5)

980 Views
jseelbach
Contributor I

Hi everyone,

I am facing an issue where the M4 (Running MQX) is running a DMA operation that appears to stop the USB and Ethernet peripherals from working correctly in the Linux environment on the A5.  While this particular DMA is running, these devices seem to 'hang' and don't indicate to Linux that they have received data even through they have.

The DMA operation that appears to cause the issue is running on the M4.  The operation is sending a table of 512 values to a Port Toggle Output Register in order to toggle GPIO values over a period of time.  The DMA is set up using DMA1 channel 31.  The request source is selected as 24 (Flex Timer Module 0 Channel 0).  This timer is configured to 'pace' the DMA of these 512 bytes within a window of time that these GPIO signals should occur in.  Once the DMA is complete, it will be manually initiated again repeatedly (about 600-2000 times).

The DMA is set up using the following code:

...

static DMA_CHANNEL_HANDLE transferChannel;

...

void dmaInit(void){
   uint32_t ret;

   ret = dma_channel_claim(&transferChannel, 31);

   ret = dma_channel_setup(transferChannel, 1, 0);

   ret = dma_request_source(transferChannel, 24);

}

The DMA process is started using the following function:

...

static DMA_TCD transferDescriptor;

...

void startPrintingDMA(){
   transferDescriptor.DST_ADDR = (uint32_t) address_of_Port_Toggle_Output_Register;
   transferDescriptor.SRC_WIDTH = 1;
   transferDescriptor.SRC_MODULO = 0;
   transferDescriptor.SRC_OFFSET = 1;
   transferDescriptor.DST_MODULO = 0;
   transferDescriptor.DST_OFFSET = 0;
   transferDescriptor.DST_WIDTH = 1;
   transferDescriptor.LOOP_BYTES = 1;
   transferDescriptor.LOOP_COUNT = 512;
   transferDescriptor.LOOP_SRC_OFFSET = 0;
   transferDescriptor.LOOP_DST_OFFSET = 0;

   dma_transfer_submit(transferChannel, &transferDescriptor, NULL);

   dmaEnable();
}

Then it is repeated over and over by calling dmaEnable() repeatedly.

void dmaEnable(){
   DMA_SADDR_REG(DMA1_BASE_PTR, 31) = (uint32_t)((uint32_t *)address_of_source_table);
   DMA_DADDR_REG(DMA1_BASE_PTR, 31) = (uint32_t) address_of_Port_Toggle_Output_Register;
   DMA_SERQ_REG(DMA1_BASE_PTR) = 31;
}

The flexTimer module 0 channel 0 is configured to tick about every 0.50 ms or slower.

This DMA transfer is performed about 600-2000 times back to back.  

During this DMA on the M4, a hang issue is seen on Linux running on the A5.  The USB and Ethernet interfaces do not respond on a poll() system call event until the DMA completes (All of the DMA cycles since it is restarted about 600-2000 times as mentioned earlier).  Enabling debug messages for the gadget driver being used on the USB, this 'hang' time during the DMA is apparent at a driver level as well.

The M4 has another DMA operation (For the SPI using request source 15) that does not appear to cause this issue when run under similar circumstances.  This DMA is much faster since it is using "SPI1 Transmit" as the request source).  This DMA is executed about every 0.25 ms or slower and is intended to write data to the SPI interface.

Please let me know what further information I could provide that would help with this issue.

Thanks,

James

Labels (3)
0 Kudos
1 Reply

672 Views
jseelbach
Contributor I

To follow up on how this was resolved:

I found that the issue was not a hang on the USB or Ethernet interfaces but rather the debug messaging mechanism to measure when these events occurred.  The debug messages had a conflict with the M4 that would cause the messaging itself to hang while the M4 was performing the other DMA process (DMA conflict).  The real problem that I was trying to get visibility on was that the MCC (multi-core-communication) library would hang on the M4 side during this DMA and "stack up" messages within that time frame.  At a systemic level, this caused information that should've been sent on the USB and Ethernet interfaces to wait for the MCC communication to finish, which was waiting on the M4's DMA described above.  Adding debug messages would also hang on the M4's DMA process until DMA was disabled on the Linux side.

Thanks,

James

0 Kudos