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.

OMAP L138 TSK_sleep() does not return after DMA enabled.

I am building an application for the OMAP-L138 with a C674x Fixed / Floating Point DSP (MityDSP) and using the C6000 build tools in CCS. I have a need to implement a heartbeat/watchdog functionality. What I am finding is that when I run this task, it runs find until the DMA channels are enabled and data transfers are handled.

I have the following CCS and BIOS versions.

  Code Composer Studio version 6.0.1.00040

  DSP/BIOS (IDE Client)    5.42.1.09   
  DSP/BIOS (Target Content)    5.42.1.09   

In the code snippets below I have observed that the debug output from Heartbeat_task() is constant to the console port until the DMA transfers start.

Keep in mind there are also DMA tasks in that handle data from the transfer complete interrupt, which are blocked on semaphores until signaled by transfer complete handler of DMA.

I am curious, is the Heartbeat_task() stopping because a higher priority task is blocking it, or if the timer that kicks PRD_tick() is disabled when the DMA channels are configured?


Thanks in advance for looking at this.

Regards,
Rob Peipert

===================================== Code Snippets below ==================================

Start the tasks:

  TSK_Attrs* lpAttrs1 = new TSK_Attrs;
  *lpAttrs1          = TSK_ATTRS;
  lpAttrs1->name      = "HighSpeed";
  lpAttrs1->stacksize = 8192*2;
  lpAttrs1->priority  = 7;
  TSK_create((Fxn)high_speed_task,lpAttrs1);  // This task waist forever on a semaphore.
    
  TSK_Attrs* lpAttrs2 = new TSK_Attrs;
  *lpAttrs2          = TSK_ATTRS;
  lpAttrs2->name      = "LowSpeed";
  lpAttrs2->stacksize = 8192*2;
  lpAttrs2->priority  = 6;
  TSK_create((Fxn)low_speed_task,lpAttrs2);  // This task waits forever on a semaphore

  TSK_Attrs* lpAttrs3 = new TSK_Attrs;
  *lpAttrs3          = TSK_ATTRS;
  lpAttrs3->name      = "LowSpeed";
  lpAttrs3->stacksize = 8192*2;
  lpAttrs3->priority  = 15;
  TSK_create((Fxn)heartbeat_task,lpAttrs3);

My Task code: (Heartbeat is static unsigned int)

void heartbeat_task()
{
  // Wait for init to complete.
  debugPrint("\n\nDSP Heartbeat: Task started!!!");

  Heartbeat = 0;

  while( 1 )
  {
      Heartbeat++;
      debugPrint("\nDSP Heartbeat: %d",Heartbeat);

      TSK_sleep(2);
  }
}

Snippet of code that starts the DMA

unsigned int SetupTransfers( unsigned int *firstChannel, unsigned int *secondChannel, unsigned int *thirdChannel, unsigned int *resultIndex, EDMA3_RM_TccCallback Callback, unsigned int sourceAddress, struct _samples *destinationAddress, unsigned int numberOfSignals, unsigned int event, unsigned int eventQ )
{
  EDMA3_DRV_Result  result, result1;
  EDMA3_DRV_SyncType synctype;
  unsigned int tcc1, acnt, bcnt, ccnt, bcntreload, srcbidx, srccidx, desbidx, descidx, tcc2;
  unsigned int tcc3;

  result1 = 0;
  tcc1            = event;
  firstChannel[0] = event;

  result = EDMA3_DRV_requestChannel (hEdma, firstChannel, &tcc1, (EDMA3_RM_EventQueue) NULL, Callback, NULL);

  result = EDMA3_DRV_mapChToEvtQ (hEdma, firstChannel[0], eventQ );

  result = EDMA3_DRV_setSrcParams (hEdma, firstChannel[0], sourceAddress, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

result = EDMA3_DRV_setDestParams (hEdma, firstChannel[0], (unsigned int) (destinationAddress[0].buffer), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

  acnt = 2048;
  bcnt = numberOfSignals;
  ccnt = 1;
  bcntreload = 0;
  synctype = EDMA3_DRV_SYNC_AB;

  result = EDMA3_DRV_setTransferParams (hEdma, firstChannel[0], acnt, bcnt, ccnt, bcntreload, synctype);


  srcbidx = acnt;
  srccidx = acnt;

  result = EDMA3_DRV_setSrcIndex  (hEdma, firstChannel[0], srcbidx, srccidx);

  desbidx = sizeof(BufferRing.samples[0][0])*LENGTH_OF_BUFFER_RING;
  descidx = sizeof(BufferRing.samples[0][0])*LENGTH_OF_BUFFER_RING;

  result = EDMA3_DRV_setDestIndex (hEdma, firstChannel[0], desbidx, descidx);


  tcc2              = EDMA3_DRV_TCC_ANY;
  secondChannel[0]  = EDMA3_DRV_DMA_CHANNEL_ANY;

  result = EDMA3_DRV_requestChannel (hEdma, secondChannel, &tcc2, (EDMA3_RM_EventQueue) NULL, Callback, NULL);

  result = EDMA3_DRV_setSrcParams (hEdma, secondChannel[0], sourceAddress, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

 result = EDMA3_DRV_setDestParams (hEdma, secondChannel[0], (unsigned int) &destinationAddress[1].buffer, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

  result = EDMA3_DRV_setDestIndex (hEdma, secondChannel[0], desbidx, descidx);

  result = EDMA3_DRV_setTransferParams (hEdma, secondChannel[0], acnt, bcnt, ccnt, bcntreload, synctype);

  tcc3             = EDMA3_DRV_TCC_ANY;
  thirdChannel[0]  = EDMA3_DRV_DMA_CHANNEL_ANY;

  result = EDMA3_DRV_requestChannel (hEdma, thirdChannel, &tcc3, (EDMA3_RM_EventQueue) NULL, Callback, NULL);

  result = EDMA3_DRV_setSrcParams (hEdma, thirdChannel[0], sourceAddress, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

 result = EDMA3_DRV_setDestParams (hEdma, thirdChannel[0], (unsigned int) &destinationAddress[2].buffer, EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT);

 result = EDMA3_DRV_setSrcIndex  (hEdma, thirdChannel[0], srcbidx, srccidx);

  result = EDMA3_DRV_setDestIndex (hEdma, thirdChannel[0], desbidx, descidx);

  result = EDMA3_DRV_setTransferParams (hEdma, thirdChannel[0], acnt, bcnt, ccnt, bcntreload, synctype);

  result = EDMA3_DRV_linkChannel (hEdma, firstChannel[0], secondChannel[0]);

  result = EDMA3_DRV_linkChannel (hEdma, secondChannel[0], thirdChannel[0]);

  result = EDMA3_DRV_linkChannel (hEdma, thirdChannel[0], secondChannel[0]);

  result = EDMA3_DRV_setOptField (hEdma, firstChannel[0], EDMA3_DRV_OPT_FIELD_TCINTEN, 1);

 result = EDMA3_DRV_setOptField (hEdma, secondChannel[0], EDMA3_DRV_OPT_FIELD_TCINTEN, 1);

 result = EDMA3_DRV_setOptField (hEdma, thirdChannel[0], EDMA3_DRV_OPT_FIELD_TCINTEN, 1);

 result = EDMA3_DRV_clearErrorBits( hEdma, firstChannel[0] );

 result = EDMA3_DRV_enableTransfer(hEdma, firstChannel[0], EDMA3_DRV_TRIG_MODE_EVENT);

  return( result1 );
}

  • What does debugPrint do? How do you know the heartbeat task is getting delayed? Could it be running properly, but the moving of the debugPrint output be delayed?

    Todd
  • Todd,

    Thanks for the reply.  The debugPrint code is below, essentially we send a formatted string to the ARM console via an IPC/DSPLink message. It appears that what I was seeing is the result of IPC being taken over by another task?  In any event, the DSP taskt that increments the heartbeat appears to work as expected, removing the debugPrint.   I assumed it was benign until I looked under the hood.


    Thanks,

    Rob

    void debugPrint(char *format, ...)
    {
          char buffer[512];
          va_list args;

          va_start (args, format);
          vsprintf (buffer,format, args);
          va_end (args);

        if(true == allowDebugPrint)
            {
              dPrintf(buffer);
            }

    }
    tcCL_IPCOutbound*     gpDebug;

    gpDebug = new tcCL_IPCOutbound("debug");

    void dPrintf(char* pMsg)
    {
      // The length of the message to be sent
      //
      int len = strlen(pMsg);

      // Pointer to dsplink buffer where to write the message
      //
      char* pBuffer;

        
      // Make sure the debug IPC outbound object has been initialized
      //
      if (gpDebug == NULL)
        return;
        
      // Get a buffer for the message
      //
      pBuffer = (char *)gpDebug->GetBuffer(len+1);
        
      // Check that the buffer is valid
      //
      if (pBuffer)
      {
        // Copy the message to the buffer
        strcpy(pBuffer, pMsg);

        // Send the message
        gpDebug->SendMessage(pBuffer, strlen(pBuffer));
      }
    }

  • Thanks for the update. Can you mark this thread as answered?