Hi Nordic,
I am implementing a micros() in the arduino using nrfx driver.
Below is test code and I got some questions.
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/types.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/poweroff.h>
#include <zephyr/sys/util.h>
#include <nrfx_timer.h>
#include <stdio.h> // Include for printf (or use printk for Zephyr)
#define NRFX_LOG_MODULE EXAMPLE
#define NRFX_EXAMPLE_CONFIG_LOG_ENABLED 1
#define NRFX_EXAMPLE_CONFIG_LOG_LEVEL 3
#include <nrfx_log.h>
#define TIMER_INST_IDX 1
// Timer instance
static nrfx_timer_t timer = NRFX_TIMER_INSTANCE(TIMER_INST_IDX);
// Timer handler
static void timer_handler(nrf_timer_event_t event_type, void *p_context)
{
printk("timer_handler() \n");
if (event_type == NRF_TIMER_EVENT_COMPARE0)
{
char *p_msg = p_context;
printk("Timer finished. Context passed to the handler: >%s<", p_msg);
// NRFX_LOG_INFO("Timer finished.");
}
if (event_type == NRF_TIMER_EVENT_COMPARE1)
{
char *p_msg = p_context;
printk("Timer finished. Context passed to the handler: >%s<", p_msg);
// NRFX_LOG_INFO("Timer finished.");
}
}
// Initialize timer for high-resolution timing
uint32_t ticks;
void timer_init(void)
{
nrfx_err_t status;
/* configure IRQ */
IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER_INST_IDX)), IRQ_PRIO_LOWEST,
NRFX_TIMER_INST_HANDLER_GET(TIMER_INST_IDX), 0, 0);
/* get base frequency of given timer (in our case timer-0) */
uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer.p_reg);
nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
config.bit_width = NRF_TIMER_BIT_WIDTH_32; // 32-bit timer
config.p_context = "Some context";
// printk("config.frequency: %d\n", config.frequency);
// note: .frequency represents base frequency not a prescaler factor
// config.frequency = NRF_TIMER_FREQ_1MHz; // Set timer frequency to 1 MHz (1 us resolution)
// config.frequency = NRF_TIMER_FREQ_500kHz; // Set timer frequency to 1 MHz (1 us resolution)
// config.frequency = NRF_TIMER_FREQ_250kHz; // Set timer frequency to 1 MHz (1 us resolution)
// config.frequency = NRF_TIMER_FREQ_125kHz; // Set timer frequency to 1 MHz (1 us resolution)
/* init timer */
status = nrfx_timer_init(&timer, &config, timer_handler);
if (status != NRFX_SUCCESS)
{
printk("Timer initialization failed: %d\n", status); // Use printk() if in Zephyr
return;
}
nrfx_timer_clear(&timer);
/* configure prescaler */
nrf_timer_prescaler_set(timer.p_reg, NRF_TIMER_FREQ_1MHz);
// nrf_timer_prescaler_set(timer.p_reg, NRF_TIMER_FREQ_16MHz);
// Convert 3,000,000 microseconds (3 seconds) to ticks
// uint32_t ticks = nrfx_timer_us_to_ticks(&timer, (uint32_t)3000000);
ticks = nrfx_timer_us_to_ticks(&timer, (uint32_t)3000000);
printk("ticks: %d\n", ticks);
// nrfx_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true);
nrfx_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL1, ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
// nrfx_timer_clear(&timer);
nrfx_timer_enable(&timer);
}
// Get current time in microseconds
uint32_t micros(void)
{
// Capture the current timer value
return nrfx_timer_capture(&timer, NRF_TIMER_CC_CHANNEL0);
}
int main(void)
{
set_led_color_cyan();
/* init button irq */
int ret = init_button_irq();
if (ret != 0)
{
printk("Error init_button_irq()\n");
return 0;
}
timer_init();
while (1)
{
uint32_t time_us = micros();
printf("Current time: %u us (%u)\n", time_us, ticks); // Use printk() if in Zephyr
// if (time_us > ticks)
// {
// nrfx_timer_disable(&timer);
// }
// Add a delay to avoid flooding the output
k_msleep(100); // Sleep for 100 milli second, if using Zephyr
// k_msleep(1000); // Sleep for 1 second, if using Zephyr
}
}

[Question 1]
Timer 1 and Timer 2 works perfectly as I expected. You can check it on the Segger RTT Viewer (upper image)
However, Timer 0 doesn't cleared correctly and just keep increasing it's value. Can you please chek on your side?
FYI, I am using SPIM and TWIM simultaneously. Could it impact on Timer 0's unexpected behavior?
[Question 2]:
A timer could have multiple C/C (=Capture and Compare) channel (=register).
So by having multiple channel, we can capture (=read timer value) and configure compare mode (=configure interrupt on/off or clear/stop a timer).
Please see below method's signature.
// nrfx_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true);
nrfx_timer_extended_compare(&timer, NRF_TIMER_CC_CHANNEL1, ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
Is there any case that 2nd arg (=channel) and 3rd arg (=action) not to be the same channel?
If not it's prone to make a human error on the application side.
How do you think?
