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.

Code is stuck on TimerEnable



Hello,

I am doing a project where I have an ADC sampling at 1 MHz, with the samples transferred to memory via uDMA, and then sent to a computer via a TCP connection.

I am using TI-RTOS, where I have one task object initializing the ADC, uDMA, and the timer - which works. I have another task object that is created inside netOpenHook(), which creates the TCP server and handles incoming connections - which works.

My problem is: I can't get both task objects to work at the same time. Specifically, I can see that uDMA is working by checking the memory browser, and seeing that the memory is changing according to the signal that I'm passing into the ADC. But the program seems to halt there, no TCP server is created.

I've narrowed down the problem (to my understanding) to a particular code segment:

Void ADC_init_task(UArg arg0, UArg arg1) {

	uint32_t ui32ClockFreq;

	// Set clock frequency
	ui32ClockFreq = SysCtlClockFreqSet(
			SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL
					| SYSCTL_CFG_VCO_480, CLK_FREQ);

	dma_init();
	dma_start(25, CHAN_A);
	adc_init();
	adc_trigger_timer_init(ui32ClockFreq, 1000000);

	System_printf("ADC_init_task: Done\n"); System_flush();
}

In the above code, the line:

System_printf("ADC_init_task: Done\n"); System_flush();

Is never run (or I'm not seeing it in the console).

I have commented out the lines, and deduced that the error should be from:

adc_trigger_timer_init(ui32ClockFreq, 1000000);

Which is:

void adc_trigger_timer_init(uint32_t ui32ClockFreq, uint32_t ui32SampleFreq) {

	// Enable timer peripheral clock
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
	while (!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER1)) {
	}

	TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC_UP);
	TimerLoadSet(TIMER1_BASE, TIMER_A, (ui32ClockFreq / ui32SampleFreq));
	TimerControlTrigger(TIMER1_BASE, TIMER_A, true);
	TimerADCEventSet(TIMER1_BASE, TIMER_ADC_TIMEOUT_A);

	System_printf("Enabling timer\n");
	System_flush();
	TimerEnable(TIMER1_BASE, TIMER_A);
	System_printf("Finished enabling timer\n");
	System_flush();

}

In the above code, the line:

TimerEnable(TIMER1_BASE, TIMER_A);

Causes the program to halt there, so "Finished enabling timer\n" is not printed to the console.

I did notice that commenting out the line:

TimerControlTrigger(TIMER1_BASE, TIMER_A, true);

Will make halting go away, and I am able to make TCP connections once again, but then I won't be able to get ADC samples, since the ADC isn't being triggered by the timer.

How do I fix this? Any help would be much appreciated. Thanks

I've attached my project to this post, if that helpsDigiscope.rar

  • Hello user4633873

    Great debug till this point. When the timer is enabled then what does it show the CPU is executing?

    Also if you replace TIMER_CFG_A_PERIODIC_UP with TIMER_CFG_PERIODIC_UP then does it work correctly?

    Regards
    Amit
  • Hello Amit,

    I've replaced TIMER_CFG_A_PERIODIC_UP with TIMER_CFG_PERIODIC_UP but the problem is still here.

    I have tried putting a break point at where the timer is enabled, when I stepped over, I believe the CPU is running the uDMA interrupt:

    void adc_A_dma_irq(void) {
    
    	uint32_t modePrimary;
    	uint32_t modeAlternate;
    
    	ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);
    
    	// Get mode statuses
    	modePrimary = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    	modeAlternate = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
    
    	// Reload the control structures
    	if ((modePrimary == UDMA_MODE_STOP) && (modeAlternate != UDMA_MODE_STOP)) {
    		// Need to reload primary control structure
    		uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
    		UDMA_MODE_PINGPONG, (void *) (ADC0_BASE + ADC_O_SSFIFO0), pui16DMADestA,
    		DMA_TRANSFER_SIZE);
    		uDMATransferCount++;
    		advance_dma_dest(CHAN_A);
    
    	} else if ((modePrimary != UDMA_MODE_STOP)
    			&& (modeAlternate == UDMA_MODE_STOP)) {
    		// Need to reload alternate control structure
    		uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
    		UDMA_MODE_PINGPONG, (void *) (ADC0_BASE + ADC_O_SSFIFO0), pui16DMADestA,
    		DMA_TRANSFER_SIZE);
    		uDMATransferCount++;
    		advance_dma_dest(CHAN_A);
    
    	} else {
    		// Either both still not stopped, or both stopped. This is an error
    		System_printf("Error in uDMA control structure modes\n");
    		System_printf("uDMATransferCount: %d\n", uDMATransferCount);
    		System_printf("Primary mode: %d\nAlternate mode: %d\n", modePrimary,
    				modeAlternate);
    		System_printf(
    				"For reference: Stop:%d, Basic:%d, Auto:%d, PingPong:%d, MemScatter:%d, PerScatter:%d\n",
    				UDMA_MODE_STOP, UDMA_MODE_BASIC, UDMA_MODE_AUTO,
    				UDMA_MODE_PINGPONG, UDMA_MODE_MEM_SCATTER_GATHER,
    				UDMA_MODE_PER_SCATTER_GATHER);
    		System_flush();
    	}
    }

    The console kept printing "Error in uDMA control structure modes" ... and the rest of the printf statements above. I'm not entirely sure, but halting the program doesn't halt the uDMA, which is what is causing the prints to happen.

    Nonetheless I've noticed that:

    System_printf("Finished enabling timer\n");

    Still doesn't run, I don't see the message "Finished enabling timer".

    The uDMA runs fine if I don't put in a breakpoint, it's just the program doesn't seem to run beyond TimerEnable

  • I don't know much of TI-RTOS, but I would be vary wary with using printf-like functions (System_printf()) in interrupts. Depending on the output channel, it will saturate the core, because it stretches the interrupt runtime beyond it's frequency. And a 1 MHz interrupt frequency (if I got this right) is a challenge. I use GPIO toggling in such situations.

  • Hello user4633873,

    I agree with f.m. Put a GPIO toggle to see if the UDMA interrupt handler is being invoked at 1MHz. To make it easier, reduce the interval from 1MHz to 1KHz.

    Regards
    Amit