I have some working code that dumps a sine wave out to a DAC via SSI. Right now I use a system tick timer to detect elapsed time to figure out what value to output next.
I'm converting this to output on a fixed interval based on a pre-calc'd table. This is a small step in my overall project, so it's important that I be able to output to SSI at a fixed interval.
If I modify my code to enable a timer (I've tried both Timer 1a and TImer 2a), the calls to SSIDataPut (and PutNonBlocking) immediately dump me into the fault ISR. If I comment out the enabling of the timer, everything works fine again. Is there some conflict between SSI0 and Timer1a and Timer2a?
Am I doing something silly? I can comment out all SSIDataPut calls and validate via breakpoint that my timer interrupt handler is actually being called, so it definitely appears to be some sort of negative interaction between ssi and timers. (note: I removed some commented code relating to pulsing the on board LED, so ignore the unused variables)
unsigned long COLOR_RED[3] = {0xFF, 0, 0};
unsigned long COLOR_GREEN[3] = {0, 0xFF, 0};
unsigned long COLOR_BLUE[3] = {0, 0, 0xFF};
void delayMS(int ms) {
ROM_SysCtlDelay( (ROM_SysCtlClockGet()/(3*1000))*ms );
}
#define SYSTICKS_PER_SECOND 1000000
static unsigned long g_ulTicks = 0;
void
SysTickHandler(void)
{
g_ulTicks++;
}
#define SAMPLE_RATE 20000
#define NUM_SAMPLES 2048
unsigned short g_freq = 440;
unsigned short g_outputBuffer[NUM_SAMPLES];
volatile unsigned char g_advanceOutput = 0;
volatile unsigned short g_outputIndex = 0;
//output
void
Timer1AIntHandler(void)
{
ROM_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
//g_advanceOutput = 1;
}
void
InitOutputTimer()
{
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
ROM_TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
ROM_TimerLoadSet(TIMER1_BASE, TIMER_A, ROM_SysCtlClockGet() / (SAMPLE_RATE - 1));
ROM_IntEnable(INT_TIMER1A);
ROM_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
ROM_TimerEnable(TIMER1_BASE, TIMER_A);
}
void
PopulateDebugBuffer()
{
unsigned short i = 0;
for(i=0; i < NUM_SAMPLES; i++)
{
g_outputBuffer[i] = (0.5 * sin(2 * 3.14159 * g_freq * i / SAMPLE_RATE) * 2047) + 2048;
}
}
int
main(void)
{
volatile unsigned long ulLoop;
ROM_FPUEnable();
ROM_FPULazyStackingEnable();
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);
//
// Initialize the UART.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioInit(0);
UARTprintf("Hello, world!\n");
// init ssi
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH2_SSI0);
ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);
ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
GPIO_PIN_2);
ROM_SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1,
SSI_MODE_MASTER, 20000000, 16);
ROM_SSIEnable(SSI0_BASE);
ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKS_PER_SECOND);
ROM_SysTickIntEnable();
ROM_SysTickEnable();
float intensity = 0;
float increment = 0.1;
unsigned long * color = (ROM_SysCtlClockGet() == 80000000 ? COLOR_BLUE : COLOR_RED);
unsigned short spiData = 0;
unsigned short spiSine = 0;
short spiIncrement = 400;
PopulateDebugBuffer();
InitOutputTimer(); // !!!! If I comment out this line, everything works. If I leave it uncommented i breaks
while(1)
{
spiSine = (0.5 * sin(2 * 3.14159 * 440 * g_ulTicks / SYSTICKS_PER_SECOND) * 2047) + 2048;
ROM_SSIDataPut(SSI0_BASE, 0x4000 | spiSine);
delayMS(1);
intensity += increment;
if((intensity >= 1.0) || (intensity <= 0))
{
increment *= -1;
}
spiData += spiIncrement;
if((spiData >= 4000) || (spiData <= 0))
{
spiIncrement *= -1;
}
}
}