Simple CTIMER interrupt example

Here’s how to make the ctimer on the apollo3 (I have the Artemis ATP board) repeatedly trigger an interrupt service routine, from an Arduino sketch.

This kind of thing is likely obvious to many here, but took me a little while to figure out so I thought I’d share for others like me :wink:

As the code says it is heavily based on the earlier ctimer example posted here by Nic Ivy (thanks for that one!)

//
//   Author: Andreas Eriksen, heavily based on another CTIMER example by Nic Ivy
//   Created: March 17, 2022
//   License: MIT
//
//   This example demonstrates how to trigger an interrupt using a counter timer
//   (i.e. CTIMER) on the Apollo3. The example uses the Ambiq Micro hardware
//   abstraction layer provided with the SparkFun Arduino core for their Artemis
//   line of microcontrollers.
//

#ifdef __cplusplus
  extern "C" {
#endif
// C++ compilations must declare the ISR as a "C" routine or else its name will get mangled
// and the linker will not use this routine to replace the default ISR
void my_isr();

#ifdef __cplusplus
  }
#endif

static int myTimer = 2;

volatile uint32_t capturedCount = 0;

extern "C" void my_isr()
{
  capturedCount++;
}

void setup( ) {
  Serial.begin(115200);
  while (!Serial) {
    ; // Wait for serial port to connect. Needed for native USB port only.
  }
  Serial.println("CTIMER will trigger an interrupt, calling the function my_isr at regular intervals.");

  setupTimerA(myTimer); // timerNum, period, padNum

  am_hal_ctimer_start(myTimer, AM_HAL_CTIMER_TIMERA);

  NVIC_EnableIRQ(CTIMER_IRQn);

  Serial.println("CTIMER started");
  
  am_hal_ctimer_int_clear(AM_HAL_CTIMER_INT_TIMERA2);
  am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA2);  
  am_hal_ctimer_int_register(AM_HAL_CTIMER_INT_TIMERA2, my_isr);
}

void loop( ) {
  Serial.print("Interrupt fired ");
  Serial.print(capturedCount);
  Serial.print(" times\n");
  delay(1000);
}

void setupTimerA(int timerNum)
{
  //
  //  Configure one timer.
  //
  //  Refer to Ambiq Micro Apollo3 Blue MCU datasheet section 13.2.2
  //  and am_hal_ctimer.c line 710 of 2210.
  //
  am_hal_ctimer_config_single(timerNum, AM_HAL_CTIMER_TIMERA,
                              AM_HAL_CTIMER_LFRC_32HZ |
                              AM_HAL_CTIMER_FN_REPEAT |
                              AM_HAL_CTIMER_INT_ENABLE);

  //
  //  Set the timing parameters.
  //  32 Hz = 1 tick on and 1 tick off, so the interrupt will trigger at 16Hz
  //
  //  Repeated Count: Periodic 1-clock-cycle wide pulses with optional interrupts.
  //  The last parameter to am_hal_ctimer_period_set() has no effect in this mode.
  //
  am_hal_ctimer_period_set(timerNum, AM_HAL_CTIMER_TIMERA, 1, 1);

  Serial.print("Timer A");
  Serial.print(timerNum);
  Serial.println(" configured");
}

Thanks for sharing! We’ll leave this here in case anyone else finds it useful

Thanks for this example! It was just what I was looking for.

A couple questions:

  1. Was the choice to use timer ‘2’ for myTimer arbitrary? Are some or all of the other timers used for other purposes?

  2. Is there any reason not to make myTimer a local variable in the setup() function (instead of global)?

Thanks!

Phil

Likely arbitrary. I don’t know, I copied it from the other example without giving it much though. Just happy I could make it work! Try different values or check the datasheet for hints :mrgreen:

Same for the myTimer variable, but I’m quite certain it could be a local as you suggest.

Sounds good. Thanks again