Other Parts Discussed in Thread: TM4C123AH6PM, TM4C1294NCPDT
Hello.
I have found a piece of code, on this forum, that is used to set up timer triggered ADC with uDMA. link: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/546435/2025521
I have read TivaWare user's guide and understood what the functions do, and what's the overall process of setting up
the whole thing. But, it doesn't work for me. It's giving me zeros in the array dedicated to storing the data.
I will add the summary of what I think the code does, there is some redundancy in code which I will keep in.
I'm using Keil, and have put the TARGET_IS_TM4C123_RB1, PART_TM4C123AH6PM in the preproessor symbols.
- start and stop are redundant variables, for measuring how often the interrupts happen, along with the SysTick counter and its handler. Correct me if I'm wrong.
- ADCseq0Handler is what triggers when the 8 levels deep FIFO gets full. Then we have a uDMAChannelTransferSet, which should take care of the next 64 samples. Then the FIFO will start to get full, and we go again.
- main() Set the clock frequency, we enable the timer, ADC0, uDMA and portE. We set the SysTick period and set the timer periodic(repeating) to 1/16000 s
- init_ADC() Sets the ADC's clock to 8 MHz (unneccesary step), disables interrupts and the sequencer.
- StepConfigure configures ADC0 with seq 0 with priority 0, channel 1 as input, to cause an interrupt, and this step is last. (Now what happends with all other steps in the FIFO?)
- on specific uDMA channel we disable unwanted properties (no idea waht they're for), and enable burst transfers. Control parameters are primary structure, data size, source addres won't be incremented, since it's all from the same FIFO, destination address is going to be incremented, and we have arbitration after 64 such transfers
- We then set the array's address and enable interrupts
I'm getting all 0s in the array. And I have checked on a simple ADC program that an analog input is properly configured.
I hope someone can help me out with all of this. I feel like all that should be set is set, but since I have no experience with this I can't find the mistake.
Any advice is also welcome.
UPDATE1: I found out the program gets stuck in the SysTickHandler, which I have removed since it's unnecessary, but then it stops at SS0 Handler.
UPDATE2: After the line"ROM_TimerEnable(TIMER0_BASE, TIMER_A);" the first element gets loaded with the correct value, but all others have the same, presumably random, value. Also, I've put a breakpoint at the beginning of SS0 Handler, but it's never reached?
UPDATE3: There is something wrong with the interrupts, definitely. Basic SysTick Handler wont execute, just stalls. Thanks everyone for pitching in, I hope to resolve this thing soon.
FINAL UPDATE: Startup had different vector names! That's what was causing all of this. Thanks to Bob Crosby, hope you didn't spend too much time looking at this, cb1_mobile, thanks on the advice, John Piliounis and to Phil LaFayette10, your code was better than mine! UDMA_ARB_1 instead of UDMA_ARB_1024
#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/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/udma.h"
#include "driverlib/emac.h"
#include "driverlib/timer.h"
#include "driverlib/rom.h"
#define ADC_SAMPLE_BUF_SIZE 64
#pragma DATA_ALIGN(ucControlTable, 1024)
uint8_t ucControlTable[1024];
static uint16_t ADC_OUT[ADC_SAMPLE_BUF_SIZE];
uint32_t n=0;
void init_ADC(void);
static uint32_t g_ui32DMAErrCount = 0;
static uint32_t g_ui32SysTickCount;
volatile uint32_t start, stop;
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
ui32Status = ROM_uDMAErrorStatusGet();
if(ui32Status)
{
ROM_uDMAErrorStatusClear();
g_ui32DMAErrCount++;
}
}
void SysTickIntHandler(void)
{
//
// Update our system tick counter.
//
g_ui32SysTickCount++;
}
void ADCseq0Handler()
{
stop = g_ui32SysTickCount;
ADCIntClear(ADC0_BASE, 0);
n++;
if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_ADC0))
{
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable(UDMA_CHANNEL_ADC0);
}
start = stop;
}
int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
SysCtlDelay(20);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //Enable the clock to ADC module
SysCtlDelay(10); // Time for the peripheral enable to set
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //Enable the clock to uDMA
SysCtlDelay(10);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Enables the clock to PORT E
SysCtlDelay(30);
ROM_SysTickPeriodSet(SysCtlClockGet() / 1000000); //Sets the period of the SysTic counter to 1us
ROM_SysTickIntEnable();
ROM_SysTickEnable();
ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, ROM_SysCtlClockGet()/16000 -1); //TODO: Timer Load Value is set here
ROM_TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
SysCtlDelay(80);
IntMasterEnable();
init_ADC();
TimerEnable(TIMER0_BASE, TIMER_A);
start = g_ui32SysTickCount;
while(1)
{
}
}
void init_ADC()
{
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1);
SysCtlDelay(10); // Time for the clock configuration to set
IntDisable(INT_ADC0SS0);
ADCIntDisable(ADC0_BASE, 0);
ADCSequenceDisable(ADC0_BASE,0);
// With sequence disabled, it is now safe to load the new configuration parameters
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0);
ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CTL_CH1| ADC_CTL_END | ADC_CTL_IE);
ADCSequenceEnable(ADC0_BASE,0); //Once configuration is set, re-enable the sequencer
ADCIntClear(ADC0_BASE,0);
uDMAEnable(); // Enables uDMA
uDMAControlBaseSet(ucControlTable);
ADCSequenceDMAEnable(ADC0_BASE,0);
// Allows DMA requests to be generated based on the FIFO level of the sample sequencer (SS0)
uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST);
// Only allow burst transfers
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE);
ADCIntEnable(ADC0_BASE,0);
IntEnable(INT_ADC0SS0);
uDMAChannelEnable(UDMA_CHANNEL_ADC0); // Enables DMA channel so it can perform transfers
}