I have this really weird situation with the RTC on the SAMC21. This code previously worked and now it does not. I have tried all sorts. It appears that the processor stops after my RTC setup function if I put break points in with the debugger. as soon as a break point is after the function it does not get reached, any further code does not run. The processor is still executing code though, the prescaler interrupts fire and the code in these runs. So if I toggle the pins in the interrupt routine I get a square wave out. If I put the pin toggle code in the main while loop, nothing.
Now if I break at the setup function and step through it it enters the while loop and toggles the pin. So why not when the program runs at normal speed?
full code attached
Main
#include "samc21.h"
#include "clock.h"
#include "rtc.h"
#include "nvic_hal.h"
#include "eic.h"
#include "adc_hal.h"
#include "tc_hal.h"
int main(void)
{
clock_setup();
//********************************************* Application setup code, DO NOT put any code above ******************************************
// ************************************************ digital output setup example
pin_mode(PB06, Digital_output) ;
//************************************************** TC PWM setup example *********************************************************
connect_peripheral_to_clock(TC0_TC1_GCLK , F_32kHz) ;
tc_pwm_setup_enable(TC0, 10, tc_prescaler_1) ; // connect counter to clock first
tc_pwm_duty_update(TC0, tc_ch1, 20) ;
pin_mode(PB09, TC_pin) ;
/******************************************************** ADC setup example ************************************************************
adc_setup_enable_rr(ADC0, ADC_SF_1MHz, ADC_CH0 , adc_resolution_16_filtered_4) ;
add_adc_channel(ADC0 , ADC_CH2 ) ;
*/
//******************************************************* DO NOT put any code below before the while loop call*************************
systick_setup_enable() ; // this runs time intervals of 100ms.
rtc_setup_enable() ; // this runs all time intervals to 32ms 2.34% faster than suggested by the names and all time intervals over 100ms with crystal accuracy
/* application code */
while (1)
{
pin_toggle(PB06) ;
// *************************************************************** 250 µs ********************************************************
if (rtc_return_250us_tick()) // 250 µs
{
} // end 250µs
// **************************************************************** 500 µs ***********************************************************
if (rtc_return_500us_tick()) // 500 µs
{
} // end 500 µs
// ***************************************************************** 1 ms ***********************************************************
if (rtc_return_1ms_tick()) // 1 ms
{
} // end 1 ms
// ********************************************************************* 1 ms **************************************************
if (rtc_return_2ms_tick()) // 2 ms
{
} // end 2ms
// ******************************************************************** 4 ms *********************************************************
if (rtc_return_4ms_tick()) // 4ms
{
} // end 4 ms
// ******************************************************************** 8 ms ******************************************************
if (rtc_return_8ms_tick()) // 8 ms
{
} // end 8 ms
// ************************************************************ ****** 16 ms ****************************************************************
if (rtc_return_16ms_tick()) // 16 ms
{
} // end 16 ms
// ******************************************************************* 32 ms *****************************************************************
if (rtc_return_32ms_tick()) // 32 ms
{
} // end 32 ms
// ****************************************************************** 100 ms ***************************************************************
if (systick_return_100ms_tick()) // 100 ms
{
} // end 100ms
// ******************************************************************* 250 ms *****************************************************************
if (rtc_return_250ms_tick()) // 250 ms
{
} // end 250 ms
// ******************************************************************* 500 ms *****************************************************************
if (rtc_return_500ms_tick()) // 500 ms
{
} // end 500 ms
// ******************************************************************* 1 s *****************************************************************
if (rtc_return_1s_tick()) // 1 s
{
} // end 1 s
} // end of main program while loop
} // end of main()
RTC
/*
* rtc.c
*
* Created: 16/06/2023 10:51:01
* Author: cbsadmin
*/
#include "samc21.h"
#include "nvic_hal.h"
#include "rtc.h"
#include "port_control.h"
static volatile uint8_t flag_250us_tick ;
static volatile uint8_t flag_500us_tick ;
static volatile uint8_t flag_1ms_tick ;
static volatile uint8_t flag_2ms_tick ;
static volatile uint8_t flag_4ms_tick ;
static volatile uint8_t flag_8ms_tick ;
static volatile uint8_t flag_16ms_tick ;
static volatile uint8_t flag_32ms_tick ;
static volatile uint8_t flag_250ms_tick ;
static volatile uint8_t flag_500ms_tick ;
static volatile uint8_t flag_1s_tick ;
volatile uint32_t _32ms_overflows ;
volatile uint32_t sys_time ;
volatile uint32_t rtcIntTime = 32 ;
void rtc_setup_enable( void )
{
//RTC->MODE0.CTRLA.bit.COUNTSYNC = 1 ;
RTC->MODE0.CTRLA.reg = 0xB << 8 ; // prescaler setup
//RTC->MODE0.CTRLA.bit.MATCHCLR = 1 ;
//RTC->MODE0.CTRLA.reg = 0x0 << 15 | 0xB << 8 | 0x1 << 7 ;
// REG_RTC_MODE0_INTENSET = 0x0F ; // replaced below
RTC->MODE0.INTENSET.reg = 0x0F ; // set up interrupts
//while ( RTC->MODE0.SYNCBUSY.bit.COMP0 ) ;
//RTC->MODE0.COMP[0].reg = rtcIntTime ; // counter interrupt every 1s
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) ;
RTC->MODE0.CTRLA.bit.ENABLE = 1 ;
interrupt_enable(NVIC_INT_RTC_CH) ;
}
uint32_t sys_time_ret(void)
{
return sys_time ;
}
// 250µs tick code
uint8_t rtc_return_250us_tick(void)
{
if (flag_250us_tick)
{
flag_250us_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 500us tick code
uint8_t rtc_return_500us_tick(void)
{
if (flag_500us_tick)
{
flag_500us_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 1ms tick code
uint8_t rtc_return_1ms_tick(void)
{
if (flag_1ms_tick)
{
flag_1ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 2ms tick code
uint8_t rtc_return_2ms_tick(void)
{
if (flag_2ms_tick)
{
flag_2ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 4ms tick code
uint8_t rtc_return_4ms_tick(void)
{
if (flag_4ms_tick)
{
flag_4ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 8ms tick code
uint8_t rtc_return_8ms_tick(void)
{
if (flag_8ms_tick)
{
flag_8ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 16ms tick code
uint8_t rtc_return_16ms_tick(void)
{
if (flag_16ms_tick)
{
flag_16ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 32ms tick code
uint8_t rtc_return_32ms_tick(void)
{
if (flag_32ms_tick)
{
flag_32ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 250ms tick code
uint8_t rtc_return_250ms_tick()
{
if (flag_250ms_tick)
{
flag_250ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 500ms tick code
uint8_t rtc_return_500ms_tick()
{
if (flag_500ms_tick)
{
flag_500ms_tick = 0 ;
return 1 ;
}
else return 0 ;
}
// 1s tick code
uint8_t rtc_return_1s_tick()
{
if (flag_1s_tick)
{
flag_1s_tick = 0 ;
return 1 ;
}
else return 0 ;
}
void RTC_Handler( void )
{
if (RTC->MODE0.INTFLAG.bit.PER0)
{
flag_250us_tick ++ ;
sys_time ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 0 ;
}
if (RTC->MODE0.INTFLAG.bit.PER1)
{
flag_500us_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 1 ;
}
if (RTC->MODE0.INTFLAG.bit.PER2)
{
flag_1ms_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 2 ;
}
if (RTC->MODE0.INTFLAG.bit.PER3)
{
flag_2ms_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 3 ;
}
if (RTC->MODE0.INTFLAG.bit.PER4)
{
flag_4ms_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 4 ;
}
if (RTC->MODE0.INTFLAG.bit.PER5)
{
flag_8ms_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 5 ;
}
if (RTC->MODE0.INTFLAG.bit.PER6)
{
flag_16ms_tick ++ ;
RTC->MODE0.INTFLAG.reg = 0x1 << 6 ;
}
if (RTC->MODE0.INTFLAG.bit.PER7)
{
flag_32ms_tick ++ ;
_32ms_overflows ++ ;
if ( (_32ms_overflows & 0x0F) == (0x1 << 3) ) flag_250ms_tick = 1 ;
if ( (_32ms_overflows & 0x1F) == (0x1 << 4) ) flag_500ms_tick = 1 ;
if ( (_32ms_overflows & 0x3F) == (0x1 << 5) ) flag_1s_tick = 1 ;
RTC->MODE0.INTFLAG.reg = 0x1 << 7 ;
}
}
// https://developer.arm.com/documentation/dui0497/a/cortex-m0-peripherals/optional-system-timer--systick?lang=en
#define SYST_CSR ( *(RwReg *) 0xE000E010 ) // SysTick Control and Status Register
#define SYST_RVR ( *(RwReg *) 0xE000E014 ) // SysTick Reload Value Register
#define SYST_CVR ( *(RwReg *) 0xE000E018 ) // SysTick Current Value Register
volatile uint8_t sysTick_flag ;
static volatile uint32_t systick_overflows ;
const static uint32_t SYSTICK_TIMEOUT = 4800000 ;
void systick_setup_enable()
{
SYST_RVR = SYSTICK_TIMEOUT ; // will roll over every 100 ms
SYST_CVR = SYSTICK_TIMEOUT ;
SYST_CSR = 0x1 << 2 | 0x1 << 1 | 0x1 << 0 ;
}
void SysTick_Handler()
{
sysTick_flag = 1 ;
systick_overflows ++ ;
}
uint8_t systick_return_100ms_tick()
{
if (sysTick_flag)
{
sysTick_flag = 0 ;
return 1 ;
}
else return 0 ;
}