This is the current set up of the code now. Since I'm only interested in creating one event per timer cycle I've swaped to a timer that does not use the RC compare reset, and swapped to triggering the interrupt on the RA compare. I was mistaken before, the interrupts were raised on the RC compare.
void set_up_timer(Tc *tc, uint32_t channel, IRQn_Type irq) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
// Note using 'TC_CMR_WAVSEL_UP' rather than ' TC_CMR_WAVSEL_UP_RC'
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1);
TC_SetRA(tc, channel, 500);
// No need to set RC, only interested in creating one event.
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPAS; // Enable interupt on RA compare
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPAS; // Disable all other interupts.
NVIC_EnableIRQ(irq);
}
void change_speed(uint32_t pulse_period){
if (pulse_period == 0) {
// If pulse period set to 0 the timer is checked to see if it is enabled. If so it is disabled.
if ((TC1->TC_CHANNEL[0].TC_SR & TC_SR_CLKSTA) == TC_SR_CLKSTA){
TC_Stop(TC1, 0);
}
}
else {
// If pulse period set to anythin other than 0 the timer is checked to see if it is disabled. If so it is enabled.
if ((TC1->TC_CHANNEL[0].TC_SR & TC_SR_CLKSTA) != TC_SR_CLKSTA){
TC_Start(TC1, 0);
}
}
}
void TC3_Handler() {
TC_GetStatus(TC1, 0);
...doing stuff here...
if (pulse_period != TC1->TC_CHANNEL[0].TC_RA) {
// If value of RA is not equal to the pulse period it is updated.
TC1->TC_CHANNEL[0].TC_RA = pulse_period;
}
// The following triggers a software reset of the timer.
TC1->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG;
}