Other Parts Discussed in Thread: SYSCONFIG
Hi. I'm using CCS Version: 12.3.0.00005, SimpleLink v6.41.0.17
I have an architecture where I'm waiting for a packet, then using a one shot timer to wait an offset in microseconds, followed by a continuous timer for a few cycles of fixed interval.
For example, I get a packet at t=1000us, I wait an offset of 2000us, then fire a continuous timer every 3000 us for 10 cycles.
I am using a GPIO on a scope to verify the timing, it looks great running concurrently with my radio thread and UART threads.
The ultimate purpose for this is to schedule system events such as GPIO toggles or ADC reads exactly when I want them to occur, outside of a chained set of radio commands.
It seems these need to be decoupled when using the chained API.
After a random interval of time, functioning perfectly for minutes and even hours, I get a hardfault, jump to invalid PC @ 0x00.
This was not happening until I started using the continous timer. I was using lots of one shot timers before, now I'm using the combination of one shot + continuous when I noticed this failure mode.
The timer callbacks are set at boot, and those values never change.
My tasks have plenty of stack space, which was my next guess that the environment is trashed.
Here's the code - not optimized for production, just trying things.
A few questions
- Are there better ways to schedule system events when using radio command chains?
- Do I need to re-register the callback for a timer after so many cycles?
- Is there a better tool to investigate hard faults?
- I need to use ROV to get PC,LR,SP, then over write them in the register view to see the call stack of the hard fault
- Not quite giving me the smoking gun I'm looking for
void gpTimerWithCBOneShot(int timer_num, int timeout_us, void(cb)(Timer_Handle myHandle, int_fast16_t status)) {
Timer_Params params;
Timer_Params_init(¶ms);
params.period = timeout_us;
params.periodUnits = Timer_PERIOD_US;
params.timerMode = Timer_ONESHOT_CALLBACK;
params.timerCallback = cb;
timer[timer_num] = Timer_open(timer_num, ¶ms);
if (timer[timer_num] == NULL)
{
while (1) {} // should only happen when adding new timers and not closing them
}
}
void gpTimerWithCBContinuous(int timer_num, int timeout_us, void(cb)(Timer_Handle myHandle, int_fast16_t status)) {
Timer_Params params;
Timer_Params_init(¶ms);
params.period = timeout_us;
params.periodUnits = Timer_PERIOD_US;
params.timerMode = Timer_CONTINUOUS_CALLBACK;
params.timerCallback = cb;
timer[timer_num] = Timer_open(timer_num, ¶ms);
if (timer[timer_num] == NULL)
{
while (1) {} // should only happen when adding new timers and not closing them
}
}
...
// init timers w/ callbacks but do not start
gpTimerWithCBOneShot(CONFIG_TIMER_5,1, &offsetCb);
gpTimerWithCBContinuous(CONFIG_TIMER_7,1, &slotTimerCb);
...
// radio RX callback, time to start offset timer
gpStopTimer(CONFIG_TIMER_5);
gpStartTimer(CONFIG_TIMER_5, offsetInterval);
...
// offsetCb
void offsetCb(Timer_Handle myHandle, int_fast16_t status) {
gpStopTimer(CONFIG_TIMER_5); // turn off offset timer
gpStopTimer(CONFIG_TIMER_7);
gpStartTimer(CONFIG_TIMER_7, peroidicInterval);
}
...
// after a number of periodic interrupts, we shut off the peroidic timer
gpStopTimer(CONFIG_TIMER_7);



