Hello Guys,
I am using a Tm4C129, with RTOS.
Below is the code, with the ADC triggered by a timer.
//--------------------------------------------------------------------------------- // Project: Blink TM4C BIOS Using Swi (SOLUTION) // Author: Eric Wilbur // Date: June 2014 // // Note: The function call TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT) HAS // to be in the ISR. This fxn clears the TIMER's interrupt flag coming // from the peripheral - it does NOT clear the CPU interrupt flag - that // is done by hardware. The author struggled figuring this part out - hence // the note. And, in the Swi lab, this fxn must be placed in the // Timer_ISR fxn because it will be the new ISR. // // Follow these steps to create this project in CCSv6.0: // 1. Project -> New CCS Project // 2. Select Template: // - TI-RTOS for Tiva-C -> Driver Examples -> EK-TM4C123 LP -> Example Projects -> // Empty Project // - Empty Project contains full instrumentation (UIA, RTOS Analyzer) and // paths set up for the TI-RTOS version of MSP430Ware // 3. Delete the following files: // - Board.h, empty.c, EK_TM4C123GXL.c/h, empty_readme.txt // 4. Add main.c from TI-RTOS Workshop Solution file for this lab // 5. Edit empty.cfg as needed (to add/subtract) BIOS services, delete given Task // 6. Build, load, run... //---------------------------------------------------------------------------------- //---------------------------------------- // BIOS header files //---------------------------------------- #include <xdc/std.h> //mandatory - have to include first, for BIOS types #include <ti/sysbios/BIOS.h> //mandatory - if you call APIs like BIOS_start() #include <xdc/runtime/Log.h> //needed for any Log_info() call #include <xdc/cfg/global.h> //header file for statically defined objects/handles //------------------------------------------ // TivaWare Header Files //------------------------------------------ #include <stdint.h> #include <stdbool.h> #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "inc/hw_ints.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include "driverlib/adc.h" //---------------------------------------- // Prototypes //---------------------------------------- void hardware_init(void); void ledToggle(void); void Timer_ISR(void); //--------------------------------------- // Globals //--------------------------------------- volatile int16_t i16ToggleCount = 0; //--------------------------------------------------------------------------- // main() //--------------------------------------------------------------------------- void main(void) { hardware_init(); // init hardware via Xware BIOS_start(); } void hardware_init(void) { uint32_t ui32Period; uint32_t ui32SysClkFreq; ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); //clock init SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); //GPIO init GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_4); //timer init TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC); ui32Period = ui32SysClkFreq; TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period -1); //IntEnable(INT_TIMER2A); //TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT); //IntMasterEnable(); TimerEnable(TIMER2_BASE, TIMER_A); TimerControlTrigger(TIMER2_BASE, TIMER_A, true); SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); ADCSequenceEnable(ADC0_BASE, 0); ADCIntEnable(ADC0_BASE, 0); } volatile uint32_t gui32ADC0Value[2]; volatile int x = 0; void Timer_ISR(void) { x^=0xFF; GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_4, x); ADCIntClear(ADC0_BASE, 0); ADCSequenceDataGet(ADC0_BASE, 0, gui32ADC0Value); }
The timer triggers every second, performing an ADC, transfer.
My question is, what is the process to get ADC triggered by a DMA, via a timer. I am using a timer, because I want to control the sample rate of the ADC.
This is my thinking.
Initalise Timer and ADC.
Every interrupt of the timer, perform the DMA transfer.
The code listed below, performs jut that. I replace the code inside the interrupt (From above), with the DMA transfer.
//Associated Java file:DatagramClient40 #include <stdio.h> #include<math.h> #include <stdbool.h> #include <string.h> #include <xdc/std.h> #include <xdc/runtime/Error.h> #include <xdc/runtime/System.h> #include "driverlib/eeprom.h" #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #include <ti/drivers/GPIO.h> #include <xdc/runtime/Timestamp.h> /* NDK BSD support */ /* Example/Board Header file */ #include "Board.h" #define TCPPACKETSIZE 20 #define NUMTCPWORKERS 3 #define MEM_BUFFER_SIZE 256 static uint8_t g_ui8RxBufA[25088*2]; //50176 #include <stdint.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "inc/hw_memmap.h" #include "inc/hw_nvic.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/flash.h" #include "driverlib/sysctl.h" #include "driverlib/systick.h" #include "driverlib/uart.h" #include "driverlib/udma.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "grlib/grlib.h" #include "grlib/widget.h" #include "grlib/canvas.h" #include "grlib/checkbox.h" #include "grlib/container.h" #include "grlib/pushbutton.h" #include "grlib/radiobutton.h" #include "grlib/slider.h" #include "utils/ustdlib.h" #include <xdc/std.h> #include <xdc/runtime/System.h> /* BIOS Header files */ #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/BIOS.h> /* TI-RTOS Header files */ #include <ti/drivers/GPIO.h> /* Example/Board Header files */ #include "Board.h" #include <stdbool.h> #include <stdint.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_adc.h" #include "inc/hw_types.h" #include "inc/hw_udma.h" #include "inc/hw_emac.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/adc.h" #include "driverlib/udma.h" #include "driverlib/emac.h" #include <xdc/std.h> //mandatory - have to include first, for BIOS types #include <ti/sysbios/BIOS.h> //mandatory - if you call APIs like BIOS_start() #include <xdc/runtime/Log.h> //needed for any Log_info() call #include <xdc/cfg/global.h> //header file for statically defined objects/handles #include <xdc/std.h> //mandatory - have to include first, for BIOS types #include <ti/sysbios/BIOS.h> //mandatory - if you call APIs like BIOS_start() #include <xdc/runtime/Log.h> //needed for any Log_info() call #include <xdc/cfg/global.h> //header file for statically defined objects/handles //------------------------------------------ // TivaWare Header Files //------------------------------------------ #include <stdint.h> #include <stdbool.h> #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "inc/hw_ints.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/debug.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/adc.h" #define TARGET_IS_TM4C129_RA1 #include "driverlib/rom.h" //---------------------------------------- // Prototypes //---------------------------------------- void hardware_init(void); void ledToggle(void); void Timer_ISR(void); #pragma DATA_ALIGN(pui8ControlTable, 1024) uint8_t pui8ControlTable[1024]; //--------------------------------------- // Globals //--------------------------------------- volatile int16_t i16ToggleCount = 0; //--------------------------------------------------------------------------- // main() //--------------------------------------------------------------------------- void main(void) { hardware_init(); // init hardware via Xware BIOS_start(); } void hardware_init(void) { uint32_t ui32Period; uint32_t ui32SysClkFreq; ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); //clock init SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAChannelAssign(UDMA_CH24_ADC1_0); uDMAControlBaseSet(pui8ControlTable); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); //GPIO init GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1); //timer init TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC); ui32Period = ui32SysClkFreq; TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period -1); //IntEnable(INT_TIMER2A); //TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT); //IntMasterEnable(); TimerEnable(TIMER2_BASE, TIMER_A); TimerControlTrigger(TIMER2_BASE, TIMER_A, true); // // SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // // ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); // // ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_TS); // ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); // ADCSequenceEnable(ADC0_BASE, 0); // // // ADCIntEnable(ADC0_BASE, 0); uint32_t div; SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0); ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1); // ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 30); ADCSequenceConfigure(ADC0_BASE, 0 /*SS0*/, ADC_TRIGGER_TIMER, 3 /*priority*/); // SS0-SS3 priorities must always be different ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 0, ADC_CTL_TS); // ADC_CTL_TS = read temp sensor ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 1, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 2, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 3, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 4, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 5, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 6, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 7, ADC_CTL_TS | ADC_CTL_END | ADC_CTL_IE); // ADC_CTL_IE fires every 8 samples ADCSequenceEnable(ADC0_BASE, 0); ADCSequenceDMAEnable(ADC0_BASE, 0); uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_8); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_8); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, MEM_BUFFER_SIZE); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, MEM_BUFFER_SIZE); uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY); uDMAChannelEnable(UDMA_CHANNEL_ADC0); ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0 ); } volatile uint32_t gui32ADC0Value[2]; volatile int x = 0; void Timer_ISR(void) { uint32_t ui32Status; uint32_t ui32Mode; ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0); ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { //test2(&counter, &enable); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, MEM_BUFFER_SIZE); // counter++; } ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { // test2(&counter, &enable); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, MEM_BUFFER_SIZE); //counter++; } uDMAChannelEnable(UDMA_CHANNEL_ADC0); }
This code does work, but not as expected.
Instead of interrupting every 1 second (as an example), the timer interrupt, is firing every 10-15 seconds. The ping pong works as expected though (alternate if statements are asserted).
Any ideas?
Thanks