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.

Scheduling 4 Writer ADC Tasks and One Reader Task

Other Parts Discussed in Thread: CC3200

Hi,

I am using TI-RTOS on CC3200 LaunchPad, I have 4 ADC Tasks (one for each channel) which reads ADC in DMA pingpong mode, provides data to a buffer and a Reader Task which reads this buffer out and does some processing. The buffer is guarded by the Osi SyncObj posted from ISR.

This is the writer task:


static OsiSyncObj_t g_dmaSyncObj0;
static OsiSyncObj_t g_dmaSyncObj1;
static OsiSyncObj_t g_dmaSyncObj2;
static OsiSyncObj_t g_dmaSyncObj3;

if (osi_SyncObjCreate (&g_dmaSyncObj3) != 0)
        UART_PRINT ("Object not created\n");

void DMATask1( void * params )
{
    PinTypeADC(60,0xFF);
    MAP_uDMAChannelAssign(UDMA_CH17_ADC_CH3);
    UDMASetupTransfer(UDMA_CH17_ADC_CH3|UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
            NO_OF_SAMPLES,
    UDMA_SIZE_32, UDMA_ARB_1,
    (void *)(0x4402E874+ADC_CH_3), UDMA_SRC_INC_NONE,
    (void *)&(DmaDataDumpPing3[0]), UDMA_DST_INC_32);

    UDMASetupTransfer(UDMA_CH17_ADC_CH3|UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
            NO_OF_SAMPLES,
            UDMA_SIZE_32, UDMA_ARB_1,
            (void *)(0x4402E874+ADC_CH_3), UDMA_SRC_INC_NONE,
            (void *)&(DmaDataDumpPong3[0]), UDMA_DST_INC_32);


    ADCIntRegister(ADC_BASE, ADC_CH_3,ADCIntHandler3);
    Status = ADCIntStatus(ADC_BASE, ADC_CH_3);
    ADCIntClear(ADC_BASE, ADC_CH_3,Status|ADC_DMA_DONE);
    ADCIntEnable(ADC_BASE, ADC_CH_3,ADC_DMA_DONE);
    ADCChannelEnable(ADC_BASE, ADC_CH_3);
    ADCDMAEnable(ADC_BASE, ADC_CH_3);
    ADCEnable(ADC_BASE);

    while(1)
        Task_yield ();

}

The interrupt Handler:


void ADCIntHandler3(void)
{
    unsigned long ulChannelStructIndex, ulMode, ulControl;
    tDMAControlTable *pControlTable;

    unsigned short Status;
    unsigned short uiIndex;


    Status = ADCIntStatus(ADC_BASE, ADC_CH_3);
    ADCIntClear(ADC_BASE, ADC_CH_3,Status|ADC_DMA_DONE);
    ulMode = MAP_uDMAChannelModeGet(UDMA_CH17_ADC_CH3 | UDMA_PRI_SELECT);
    if(ulMode == UDMA_MODE_STOP)
    {
        ulChannelStructIndex = UDMA_CH17_ADC_CH3 | UDMA_PRI_SELECT;
        pDataDumpBuff3 = &(DmaDataDumpPing3[0]);
    }
    else
    {
        ulMode = MAP_uDMAChannelModeGet(UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT);
        if(ulMode == UDMA_MODE_STOP)
        {
            ulChannelStructIndex = UDMA_CH16_ADC_CH2 | UDMA_ALT_SELECT;
            pDataDumpBuff3 = &(DmaDataDumpPong3[0]);
        }
}

    if(pDataDumpBuff3 != NULL)
    {
    //    ulChannelStructIndex &= 0x3f;
        pControlTable = uDMAControlBaseGet();
        ulControl = (pControlTable[ulChannelStructIndex].ulControl &
                ~(UDMA_CHCTL_XFERSIZE_M | UDMA_CHCTL_XFERMODE_M));
        ulControl |= UDMA_MODE_PINGPONG | ((NO_OF_SAMPLES - 1) << 4);
        uDMAChannelControlSet(ulChannelStructIndex,ulControl);

        //Signal the MQTT Thread from ISR to post the data
        osi_SyncObjSignalFromISR (&g_dmaSyncObj3);
    }
}

The Reader task:

void Reader (void *params)
{
 
     while (1)
    {


    if (!osi_SyncObjWait (&g_dmaSyncObj0, OSI_NO_WAIT)) {
            UART_PRINT ("#####WR 0\n");
    }
    if (!osi_SyncObjWait (&g_dmaSyncObj1, OSI_NO_WAIT)) {
                UART_PRINT ("#####WR 1\n");
        }
    if (!osi_SyncObjWait (&g_dmaSyncObj2, OSI_NO_WAIT)) {
                UART_PRINT ("#####WR 2\n");
        }
    if (!osi_SyncObjWait (&g_dmaSyncObj3, OSI_NO_WAIT)) {
                UART_PRINT ("#####WR 3\n");
        }

    }

Is there any obvious mistake in the code in terms of synchronization? The DMA is getting done and I can see that data has coming in, but I am not getting the signal from the ISR to the Reader task more than once or twice maximum. After that, the system goes to a hung state. The ROV shows that all the 4 Writer tasks are in "Ready" State and the Reader in "Running" State. What am I missing? I checked by changing the priorities as well. Is it too much to ask for a CC3200 board to do 4 channel DMA transfer at a shot?

Any clues for moving forward at all is of great help.

Many Thanks in advance,

Soumya

  • Soumya,

    I don't see anything obvious at the moment. Let's gather some more information.

    The OSI layer is an OS abstraction, yet I see that you are making native SYS/BIOS calls. It might simplify things if you replace the OSI calls with native SYS/BIOS calls. For example, osi_SyncObjSignalFromISR becomes Semaphore_post. You can look in ti/drivers/wifi/osi_tirtos.c to see how each one is implemented.

    It looks like each task is used to setup the ADC data flow and then just spins. It might be better to simply block on a semaphore inside the while loop. The call to Task_yield will simply move the current task to the end of the ready list and then switch to the next task. Down the road, if you want better power management, it is best to block the task and enter the Idle task.

    I'm a little worried about the reader task calling UART_PRINT. This call had better block or be re-entrant. What uart driver is being invoked by this macro?

    To simplify, how about making the reader block on the osi_SyncObj? Maybe reducing down to one write task?

    Looking a head, if you decide to go with native SYS/BIOS calls, then you can use an event object instead of the osi_SyncObj. The benefit of the event object is that the reader can block on multiple events. Then you maximize your idle time (power savings). When any ADC dma is ready, the reader task wakes up and processes the data. No need for the reader task to constantly spin looking for data.

    Which version of TI-RTOS are you using?

    Are you using the SPI bus to communicate with the ADCs? If so, are you using the GSPI controller?

    Would you make a list of uDMA channels you are using. We use a couple internally for communication with the NWP. Maybe there is a conflict there.

    ~Ramsey

  • Hi Ramsey,

    Thanks for the detailed explanation and steps to follow. I tried all your suggestions and with that and with an addition of Task_yield () at the end of while (1) in the Reader, I am able to see all the 4 channel data in the Reader task.

    Many many Thanks,

    Soumya