Hi
I'm trying to generate interrupts from a SAMD51 timer - don't mind which one - but I'm failing to get anything to happen in the interrupt routine.
I have used code from MartinL and Microchip but it doesn't seem to do what I expect. It may be that I'm not understanding what the timer can do but it seems to be able to do what I want except it hasn't so far.
I'm generating a square wave using a timer and would like an interrupt to happen every compare match.
The Microchip site here implies the code will work but it doesn't on my Adafruit M4 Express Feather - it needs editing before it will compile in Arduino: (Configuring SAM D21 Interrupts - Developer Help). I know it SAMD21- based but the registers all look the same to me
volatile bool check = false;
volatile bool LED_state = false;
void setup() {
// put your setup code here, to run once:
pinMode(13, OUTPUT);
/* Enable TC3 Overflow Interrupt Signal */
TC0->COUNT16.INTENSET.bit.OVF = 1;
/* Enable TC3 Error Interrupt Signal */
TC0->COUNT16.INTENSET.bit.ERR = 1;
// Configure asynchronous clock source
// TC0 setup for PWM on pin A1
// 38kHz (+- 100Hz)
MCLK->APBAMASK.reg |= MCLK_APBAMASK_TC0; // Activate timer TC0
// Set up the generic clock (GCLK7) used to clock timers
GCLK->GENCTRL[7].reg = GCLK_GENCTRL_DIV(0) | // Divide the 48MHz clock source by divisor 1: 48MHz
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK7
GCLK_GENCTRL_SRC_DFLL; // Generate from 48MHz DFLL clock source
while (GCLK->SYNCBUSY.bit.GENCTRL7); // Wait for synchronization
GCLK->PCHCTRL[9].reg = GCLK_PCHCTRL_CHEN | // Enable perhipheral channel
GCLK_PCHCTRL_GEN_GCLK7; // Connect generic clock 7 to TC0
// Enable the peripheral multiplexer on pin A1
PORT->Group[g_APinDescription[A1].ulPort].PINCFG[g_APinDescription[A1].ulPin].bit.PMUXEN = 1;
// Set A1 the peripheral multiplexer to peripheral E(4): TC0, Channel 1
PORT->Group[g_APinDescription[A1].ulPort].PMUX[g_APinDescription[A1].ulPin >> 1].reg |= PORT_PMUX_PMUXO(4);
// Configure Count Mode (16-bit)
TC0->COUNT16.CTRLA.bit.MODE = 0x0;
// Configure Prescaler for divide by 2 (500kHz clock to COUNT)
TC0->COUNT16.CTRLA.bit.PRESCALER = 0x1;
// Configure TC0 Compare Mode for compare channel 0
TC0->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; // "Match Frequency" operation
// Initialize compare value for 100mS @ 500kHz
TC0->COUNT16.CC[0].reg = 50000;
// Enable TC0 compare mode interrupt generation
TC0->COUNT16.INTENSET.bit.MC0 = 0x1; // Enable match interrupts on compare channel 0
// Enable TC0
TC0->COUNT16.CTRLA.bit.ENABLE = 1;
/* Set TC3 Interrupt Priority to Level 3 */
NVIC_SetPriority(TC0_IRQn, 3);
NVIC_EnableIRQ(TC3_IRQn);
__enable_irq();
}
void loop() {
// put your main code here, to run repeatedly:
if(check)
{
Serial.print("Interrupt fired");
check = false;
}
}
void TC0_Handler(void)
{
// Interrupt processing code
// Acknowledge the interrupt (clear MC0 interrupt flag to re-arm)
TC0->COUNT16.INTFLAG.reg |= 0b00010000; // edited for clarity following westfw's question
check = true;
if(LED_state)
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);
LED_state = !LED_state;
}
I've added stuff to make the LED turn on and off for my benefit but the LED doesn't turn on.
It looks like it should be straightforward but I'm getting nothing at the moment. What am I doing wrong?
Thanks in advance.
Max