From 42b9dd8f789cfc0df4ac9fc9a4020ba4da3472c3 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Sat, 31 Jan 2026 12:04:37 +0100 Subject: [PATCH 1/2] Implement hardware GPIO pulse counter API --- src/hal/gpio.h | 73 ++++++++ src/silabs/hal/gpio_counter.c | 35 ++++ src/silabs/slcp_files/zigbee.slcp | 1 + src/silabs/slcp_files/zigbee_end_device.slcp | 1 + src/stub/commands.c | 26 +++ src/stub/hal/gpio.c | 80 +++++++++ src/stub/hal/stub.h | 3 + src/stub/stub_app.c | 1 + src/telink/Makefile | 1 + src/telink/hal/gpio.c | 2 +- src/telink/hal/gpio_counter.c | 172 +++++++++++++++++++ tests/conftest.py | 4 + 12 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 src/silabs/hal/gpio_counter.c create mode 100644 src/telink/hal/gpio_counter.c diff --git a/src/hal/gpio.h b/src/hal/gpio.h index 624f7e4ecc..487aef14a2 100644 --- a/src/hal/gpio.h +++ b/src/hal/gpio.h @@ -94,4 +94,77 @@ hal_gpio_pin_t hal_gpio_parse_pin(const char *s); */ hal_gpio_pull_t hal_gpio_parse_pull(const char *pull_str); +/* + * Hardware GPIO Pulse Counter API + * + * Some platforms support hardware-based pulse counting on GPIO pins, + * allowing accurate counting without CPU intervention. + */ + +#define HAL_GPIO_COUNTER_INVALID -1 + +typedef int8_t hal_gpio_counter_t; + +typedef enum { + HAL_GPIO_COUNTER_RISING = 0, + HAL_GPIO_COUNTER_FALLING = 1, +} hal_gpio_counter_edge_t; + +/** + * Initialize a hardware pulse counter on a GPIO pin + * @param gpio_pin GPIO pin to count pulses on + * @param edge Edge polarity to trigger counting (rising or falling) + * @param pull Pull resistor configuration for the pin + * @return Counter handle (>=0) on success, HAL_GPIO_COUNTER_INVALID on failure + */ +hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, + hal_gpio_counter_edge_t edge, + hal_gpio_pull_t pull); + +/** + * Deinitialize a hardware pulse counter and free resources + * @param counter Counter handle from hal_gpio_counter_init + */ +void hal_gpio_counter_deinit(hal_gpio_counter_t counter); + +/** + * Read current pulse count from hardware counter + * @param counter Counter handle from hal_gpio_counter_init + * @return Current pulse count + */ +uint32_t hal_gpio_counter_read(hal_gpio_counter_t counter); + +/** + * Reset hardware counter to zero + * @param counter Counter handle from hal_gpio_counter_init + */ +void hal_gpio_counter_reset(hal_gpio_counter_t counter); + +/** + * Start an already allocated hardware counter + * @param counter Counter handle from hal_gpio_counter_init + */ +void hal_gpio_counter_start(hal_gpio_counter_t counter); + +/** + * Stop hardware counter but leaves the resource allocated + * @param counter Counter handle from hal_gpio_counter_init + */ +void hal_gpio_counter_stop(hal_gpio_counter_t counter); + +/** + * Read current pulse count and reset the counter to zero + * Note: Counter is stopped during read/reset, pulses during this brief + * window may be lost. Counter is always restarted after this call. + * @param counter Counter handle from hal_gpio_counter_init + * @return Current pulse count before reset + */ +static inline uint32_t hal_gpio_counter_read_and_reset(hal_gpio_counter_t counter) { + hal_gpio_counter_stop(counter); + uint32_t count = hal_gpio_counter_read(counter); + hal_gpio_counter_reset(counter); + hal_gpio_counter_start(counter); + return count; +} + #endif diff --git a/src/silabs/hal/gpio_counter.c b/src/silabs/hal/gpio_counter.c new file mode 100644 index 0000000000..3dcd582546 --- /dev/null +++ b/src/silabs/hal/gpio_counter.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "hal/gpio.h" +#include + + +hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, + hal_gpio_counter_edge_t edge, + hal_gpio_pull_t pull) { + // No-op for now + + return HAL_GPIO_COUNTER_INVALID; +} + +void hal_gpio_counter_deinit(hal_gpio_counter_t counter) { + // No-op for now +} + +uint32_t hal_gpio_counter_read(hal_gpio_counter_t counter) { + return 0; +} + +void hal_gpio_counter_reset(hal_gpio_counter_t counter) { + // No-op for now +} + +void hal_gpio_counter_start(hal_gpio_counter_t counter) { + // No-op for now +} + +void hal_gpio_counter_stop(hal_gpio_counter_t counter) { + // No-op for now +} diff --git a/src/silabs/slcp_files/zigbee.slcp b/src/silabs/slcp_files/zigbee.slcp index a8c8c985b5..ca1803d9e5 100644 --- a/src/silabs/slcp_files/zigbee.slcp +++ b/src/silabs/slcp_files/zigbee.slcp @@ -10,6 +10,7 @@ source: - {path: ../../silabs/main.c} - {path: ../../silabs/hal/zigbee.c} - {path: ../../silabs/hal/gpio.c} +- {path: ../../silabs/hal/gpio_counter.c} - {path: ../../silabs/hal/nvm.c} - {path: ../../silabs/hal/tasks.c} - {path: ../../silabs/hal/timer.c} diff --git a/src/silabs/slcp_files/zigbee_end_device.slcp b/src/silabs/slcp_files/zigbee_end_device.slcp index d677951ae0..66f7d93284 100644 --- a/src/silabs/slcp_files/zigbee_end_device.slcp +++ b/src/silabs/slcp_files/zigbee_end_device.slcp @@ -10,6 +10,7 @@ source: - {path: ../../silabs/main.c} - {path: ../../silabs/hal/zigbee.c} - {path: ../../silabs/hal/gpio.c} +- {path: ../../silabs/hal/gpio_counter.c} - {path: ../../silabs/hal/nvm.c} - {path: ../../silabs/hal/tasks.c} - {path: ../../silabs/hal/timer.c} diff --git a/src/stub/commands.c b/src/stub/commands.c index 030360eac8..67a4693898 100644 --- a/src/stub/commands.c +++ b/src/stub/commands.c @@ -333,6 +333,31 @@ static int cmd_step_time(int argc, char **argv) { return 0; } +static int cmd_set_counter(int argc, char **argv) { + if (argc != 3) { + fprintf(stderr, "Usage: set_counter \n"); + io_res_err("usage"); + return -1; + } + char *e = NULL; + long pin = strtol(argv[1], &e, 10); + if (*argv[1] == '\0' || *e) { + fprintf(stderr, "Bad pin\n"); + io_res_err("bad_pin=%s", argv[1]); + return -1; + } + long value = strtol(argv[2], &e, 10); + if (*argv[2] == '\0' || *e || value < 0) { + fprintf(stderr, "Bad counter value\n"); + io_res_err("bad_value=%s", argv[2]); + return -1; + } + stub_set_pulse_counter((int)pin, (uint32_t)value); + printf("Set pulse counter on pin %ld to %ld\n", pin, value); + io_res_ok("pin=%ld value=%ld", pin, value); + return 0; +} + /* Command table */ static const SimpleReplCommand kCmds[] = { { "machine", cmd_machine }, @@ -348,6 +373,7 @@ static const SimpleReplCommand kCmds[] = { { "zcl_cmd", cmd_zcl_cmd }, { "freeze_time", cmd_freeze_time }, { "step_time", cmd_step_time }, + { "set_counter", cmd_set_counter }, { "q", cmd_quit }, { "quit", cmd_quit }, }; diff --git a/src/stub/hal/gpio.c b/src/stub/hal/gpio.c index c975551186..23e8fbb26b 100644 --- a/src/stub/hal/gpio.c +++ b/src/stub/hal/gpio.c @@ -178,3 +178,83 @@ void ensure_valid_output_pin(hal_gpio_pin_t gpio_pin) { exit(1); } } + +typedef struct { + uint8_t initialized; + uint32_t value; + hal_gpio_pin_t gpio_pin; + hal_gpio_counter_t *handle; +} stub_gpio_counter_t; + +static stub_gpio_counter_t gpio_counter[2]; + + +hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, + hal_gpio_counter_edge_t edge, + hal_gpio_pull_t pull) { + + for (int i = 0; i < 2; i++) { + if (!gpio_counter[i].initialized) { + gpio_counter[i].initialized = 1; + gpio_counter[i].value = 0; + gpio_counter[i].gpio_pin = gpio_pin; + gpio_counter[i].handle = (hal_gpio_counter_t *)(uintptr_t)i; + io_log("GPIO", "Initialized GPIO counter %d on pin %d", i, gpio_pin); + return (hal_gpio_counter_t)(uintptr_t)i; + } + } + + return HAL_GPIO_COUNTER_INVALID; +} + +uint32_t hal_gpio_counter_read(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= 2 || !gpio_counter[counter].initialized) { + io_log("GPIO", "Error: Invalid GPIO counter %d read", counter); + return 0; + } + + io_log("GPIO", "Read GPIO counter %d = %u", counter, + gpio_counter[counter].value); + + for (int i = 0; i < 2; i++) { + if (gpio_counter[i].initialized && gpio_counter[i].handle == counter) { + return gpio_counter[i].value; + } + } + + return 0; +} + +void hal_gpio_counter_reset(hal_gpio_counter_t counter) { + if (!counter) { + return; + } + + for (int i = 0; i < 2; i++) { + if (gpio_counter[i].initialized && gpio_counter[i].handle == counter) { + gpio_counter[i].value = 0; + break; + } + } +} + +void hal_gpio_counter_stop(hal_gpio_counter_t counter) { + // No-op in stub +} + +void hal_gpio_counter_start(hal_gpio_counter_t counter) { + // No-op in stub +} + +void stub_set_pulse_counter(hal_gpio_pin_t gpio_pin, uint32_t value) { + io_log("GPIO", "Stub: set pulse counter on pin %d to %u", gpio_pin, value); + + for (int i = 0; i < 2; i++) { + if (gpio_counter[i].initialized && gpio_counter[i].gpio_pin == gpio_pin) { + gpio_counter[i].value = value; + return; + } + } + + io_log("GPIO", "Stub: no pulse counter found on pin %d to set value", gpio_pin); +} \ No newline at end of file diff --git a/src/stub/hal/stub.h b/src/stub/hal/stub.h index 3a2e35497d..dd781ef7ca 100644 --- a/src/stub/hal/stub.h +++ b/src/stub/hal/stub.h @@ -10,6 +10,9 @@ void stub_gpio_enable_debug(int enable); void stub_gpio_simulate_input(hal_gpio_pin_t gpio_pin, uint8_t value); uint8_t stub_gpio_get_output(hal_gpio_pin_t gpio_pin); +// GPIO counter stub functions +void stub_set_pulse_counter(hal_gpio_pin_t gpio_pin, uint32_t value); + // Tasks stub functions void stub_tasks_poll(void); diff --git a/src/stub/stub_app.c b/src/stub/stub_app.c index 164b802da8..4b83a6c504 100644 --- a/src/stub/stub_app.c +++ b/src/stub/stub_app.c @@ -101,6 +101,7 @@ void stub_app_print_help(void) { "bytes)"); puts(" freeze_time <0|1> - Freeze/unfreeze time"); puts(" step_time - Advance time by ms"); + puts(" set_counter - Set pulse counter value"); puts(" q, quit - Exit"); } diff --git a/src/telink/Makefile b/src/telink/Makefile index be1088869b..8e92dd9e82 100644 --- a/src/telink/Makefile +++ b/src/telink/Makefile @@ -129,6 +129,7 @@ TELINK_SOURCES := \ hal/tasks.c \ hal/gpio.c \ hal/gpio_interrupts.c \ + hal/gpio_counter.c \ hal/nvm.c \ hal/zigbee.c \ hal/zigbee_network.c \ diff --git a/src/telink/hal/gpio.c b/src/telink/hal/gpio.c index 0afcff4c66..4d9ef33140 100644 --- a/src/telink/hal/gpio.c +++ b/src/telink/hal/gpio.c @@ -10,7 +10,7 @@ // hal_gpio_pin_t directly stores GPIO_PinTypeDef values // Convert HAL pull type to Telink pull type -static GPIO_PullTypeDef hal_to_telink_pull(hal_gpio_pull_t pull) { +GPIO_PullTypeDef hal_to_telink_pull(hal_gpio_pull_t pull) { switch (pull) { case HAL_GPIO_PULL_NONE: return PM_PIN_UP_DOWN_FLOAT; diff --git a/src/telink/hal/gpio_counter.c b/src/telink/hal/gpio_counter.c new file mode 100644 index 0000000000..f1f852a99f --- /dev/null +++ b/src/telink/hal/gpio_counter.c @@ -0,0 +1,172 @@ +#pragma pack(push, 1) +#include "tl_common.h" +#pragma pack(pop) + +#include "hal/gpio.h" +#include + +extern GPIO_PullTypeDef hal_to_telink_pull(hal_gpio_pull_t pull); + +// Maximum number of hardware counters available (TIMER0 and TIMER1) +#define MAX_GPIO_COUNTERS 2 + +typedef struct { + hal_gpio_pin_t gpio_pin; + uint8_t timer_idx; + uint8_t in_use; +} gpio_counter_state_t; + +static gpio_counter_state_t counter_state[MAX_GPIO_COUNTERS]; +static uint8_t counters_initialized = 0; + +static void init_counter_state(void) { + if (!counters_initialized) { + for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { + counter_state[i].gpio_pin = HAL_INVALID_PIN; + counter_state[i].timer_idx = i; // TIMER0=0, TIMER1=1 + counter_state[i].in_use = 0; + } + counters_initialized = 1; + } +} + +hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, + hal_gpio_counter_edge_t edge, + hal_gpio_pull_t pull) { + init_counter_state(); + + // Find a free counter slot + gpio_counter_state_t *slot = NULL; + hal_gpio_counter_t handle = HAL_GPIO_COUNTER_INVALID; + + for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { + if (!counter_state[i].in_use) { + slot = &counter_state[i]; + handle = i; + break; + } + } + + if (slot == NULL) { + return HAL_GPIO_COUNTER_INVALID; + } + + // Map HAL edge to Telink polarity + GPIO_PolTypeDef pol = (edge == HAL_GPIO_COUNTER_RISING) ? POL_RISING : POL_FALLING; + GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)gpio_pin; + + // Configure GPIO for timer trigger mode + timer_gpio_init(slot->timer_idx, telink_pin, pol); + + // Enable GPIO interrupt for the selected timer + if (slot->timer_idx == 0) { + drv_gpio_irq_risc0_en(telink_pin); + } else if (slot->timer_idx == 1) { + drv_gpio_irq_risc1_en(telink_pin); + } + + // Set pull resistor + gpio_setup_up_down_resistor(telink_pin, hal_to_telink_pull(pull)); + + // Set timer to GPIO trigger (counter) mode + timer_set_mode(slot->timer_idx, TIMER_MODE_GPIO_TRIGGER); + + // Reset counter to 0 + timer_set_init_tick(slot->timer_idx, 0); + + // Set max count value + timer_set_cap_tick(slot->timer_idx, 0xFFFFFFFF); + + // Enable timer interrupt (needed for counter operation) + timer_irq_enable(slot->timer_idx); + + // Start the timer/counter + timer_start(slot->timer_idx); + + // Mark slot as in use + slot->gpio_pin = gpio_pin; + slot->in_use = 1; + + return handle; +} + +void hal_gpio_counter_deinit(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } + + // Stop the timer/counter + hal_gpio_counter_stop(counter); + + // Reset the counter + hal_gpio_counter_reset(counter); + + // Disable GPIO interrupt for the selected timer + GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)slot->gpio_pin; + if (slot->timer_idx == 0) { + drv_gpio_irq_risc0_dis(telink_pin); + } else if (slot->timer_idx == 1) { + drv_gpio_irq_risc1_dis(telink_pin); + } + + // Reset slot state + slot->gpio_pin = HAL_INVALID_PIN; + slot->in_use = 0; +} + +uint32_t hal_gpio_counter_read(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return 0; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return 0; + } + + return reg_tmr_tick(slot->timer_idx); +} + +void hal_gpio_counter_reset(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } + + timer_set_init_tick(slot->timer_idx, 0); +} + +void hal_gpio_counter_start(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } + + timer_start(slot->timer_idx); +} + +void hal_gpio_counter_stop(hal_gpio_counter_t counter) { + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } + + timer_stop(slot->timer_idx); +} diff --git a/tests/conftest.py b/tests/conftest.py index 48762b92ea..697ac03394 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -214,6 +214,10 @@ def step_time(self, ms: int) -> None: res = self.p.exec(f"step_time {ms}") assert res.ok, f"Step time failed: {res.payload}" + def set_pulse_counter(self, pin: str, value: int) -> None: + res = self.p.exec(f"set_counter {self._parse_pin(pin)} {value}") + assert res.ok, f"Set pulse counter failed: {res.payload}" + def _evt_parser(self, evt: Event) -> None: if evt.kind == "gpio": pin = int(evt.payload.get("pin", "-1")) From 47611b7d9d4b782556392416769fdb24226a8302 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Benecke Date: Mon, 2 Mar 2026 09:19:34 +0100 Subject: [PATCH 2/2] Format --- src/hal/gpio.h | 20 ++-- src/telink/hal/gpio_counter.c | 218 +++++++++++++++++----------------- 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/src/hal/gpio.h b/src/hal/gpio.h index 487aef14a2..642c7d9711 100644 --- a/src/hal/gpio.h +++ b/src/hal/gpio.h @@ -96,18 +96,18 @@ hal_gpio_pull_t hal_gpio_parse_pull(const char *pull_str); /* * Hardware GPIO Pulse Counter API - * + * * Some platforms support hardware-based pulse counting on GPIO pins, * allowing accurate counting without CPU intervention. */ -#define HAL_GPIO_COUNTER_INVALID -1 +#define HAL_GPIO_COUNTER_INVALID -1 typedef int8_t hal_gpio_counter_t; typedef enum { - HAL_GPIO_COUNTER_RISING = 0, - HAL_GPIO_COUNTER_FALLING = 1, + HAL_GPIO_COUNTER_RISING = 0, + HAL_GPIO_COUNTER_FALLING = 1, } hal_gpio_counter_edge_t; /** @@ -124,7 +124,7 @@ hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, /** * Deinitialize a hardware pulse counter and free resources * @param counter Counter handle from hal_gpio_counter_init - */ + */ void hal_gpio_counter_deinit(hal_gpio_counter_t counter); /** @@ -160,11 +160,11 @@ void hal_gpio_counter_stop(hal_gpio_counter_t counter); * @return Current pulse count before reset */ static inline uint32_t hal_gpio_counter_read_and_reset(hal_gpio_counter_t counter) { - hal_gpio_counter_stop(counter); - uint32_t count = hal_gpio_counter_read(counter); - hal_gpio_counter_reset(counter); - hal_gpio_counter_start(counter); - return count; + hal_gpio_counter_stop(counter); + uint32_t count = hal_gpio_counter_read(counter); + hal_gpio_counter_reset(counter); + hal_gpio_counter_start(counter); + return count; } #endif diff --git a/src/telink/hal/gpio_counter.c b/src/telink/hal/gpio_counter.c index f1f852a99f..de39941585 100644 --- a/src/telink/hal/gpio_counter.c +++ b/src/telink/hal/gpio_counter.c @@ -8,165 +8,165 @@ extern GPIO_PullTypeDef hal_to_telink_pull(hal_gpio_pull_t pull); // Maximum number of hardware counters available (TIMER0 and TIMER1) -#define MAX_GPIO_COUNTERS 2 +#define MAX_GPIO_COUNTERS 2 typedef struct { - hal_gpio_pin_t gpio_pin; - uint8_t timer_idx; - uint8_t in_use; + hal_gpio_pin_t gpio_pin; + uint8_t timer_idx; + uint8_t in_use; } gpio_counter_state_t; static gpio_counter_state_t counter_state[MAX_GPIO_COUNTERS]; static uint8_t counters_initialized = 0; static void init_counter_state(void) { - if (!counters_initialized) { - for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { - counter_state[i].gpio_pin = HAL_INVALID_PIN; - counter_state[i].timer_idx = i; // TIMER0=0, TIMER1=1 - counter_state[i].in_use = 0; + if (!counters_initialized) { + for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { + counter_state[i].gpio_pin = HAL_INVALID_PIN; + counter_state[i].timer_idx = i; // TIMER0=0, TIMER1=1 + counter_state[i].in_use = 0; + } + counters_initialized = 1; } - counters_initialized = 1; - } } hal_gpio_counter_t hal_gpio_counter_init(hal_gpio_pin_t gpio_pin, hal_gpio_counter_edge_t edge, hal_gpio_pull_t pull) { - init_counter_state(); + init_counter_state(); - // Find a free counter slot - gpio_counter_state_t *slot = NULL; - hal_gpio_counter_t handle = HAL_GPIO_COUNTER_INVALID; + // Find a free counter slot + gpio_counter_state_t *slot = NULL; + hal_gpio_counter_t handle = HAL_GPIO_COUNTER_INVALID; - for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { - if (!counter_state[i].in_use) { - slot = &counter_state[i]; - handle = i; - break; + for (int i = 0; i < MAX_GPIO_COUNTERS; i++) { + if (!counter_state[i].in_use) { + slot = &counter_state[i]; + handle = i; + break; + } } - } - if (slot == NULL) { - return HAL_GPIO_COUNTER_INVALID; - } + if (slot == NULL) { + return HAL_GPIO_COUNTER_INVALID; + } - // Map HAL edge to Telink polarity - GPIO_PolTypeDef pol = (edge == HAL_GPIO_COUNTER_RISING) ? POL_RISING : POL_FALLING; - GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)gpio_pin; + // Map HAL edge to Telink polarity + GPIO_PolTypeDef pol = (edge == HAL_GPIO_COUNTER_RISING) ? POL_RISING : POL_FALLING; + GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)gpio_pin; - // Configure GPIO for timer trigger mode - timer_gpio_init(slot->timer_idx, telink_pin, pol); + // Configure GPIO for timer trigger mode + timer_gpio_init(slot->timer_idx, telink_pin, pol); - // Enable GPIO interrupt for the selected timer - if (slot->timer_idx == 0) { - drv_gpio_irq_risc0_en(telink_pin); - } else if (slot->timer_idx == 1) { - drv_gpio_irq_risc1_en(telink_pin); - } + // Enable GPIO interrupt for the selected timer + if (slot->timer_idx == 0) { + drv_gpio_irq_risc0_en(telink_pin); + } else if (slot->timer_idx == 1) { + drv_gpio_irq_risc1_en(telink_pin); + } - // Set pull resistor - gpio_setup_up_down_resistor(telink_pin, hal_to_telink_pull(pull)); + // Set pull resistor + gpio_setup_up_down_resistor(telink_pin, hal_to_telink_pull(pull)); - // Set timer to GPIO trigger (counter) mode - timer_set_mode(slot->timer_idx, TIMER_MODE_GPIO_TRIGGER); + // Set timer to GPIO trigger (counter) mode + timer_set_mode(slot->timer_idx, TIMER_MODE_GPIO_TRIGGER); - // Reset counter to 0 - timer_set_init_tick(slot->timer_idx, 0); + // Reset counter to 0 + timer_set_init_tick(slot->timer_idx, 0); - // Set max count value - timer_set_cap_tick(slot->timer_idx, 0xFFFFFFFF); + // Set max count value + timer_set_cap_tick(slot->timer_idx, 0xFFFFFFFF); - // Enable timer interrupt (needed for counter operation) - timer_irq_enable(slot->timer_idx); + // Enable timer interrupt (needed for counter operation) + timer_irq_enable(slot->timer_idx); - // Start the timer/counter - timer_start(slot->timer_idx); + // Start the timer/counter + timer_start(slot->timer_idx); - // Mark slot as in use - slot->gpio_pin = gpio_pin; - slot->in_use = 1; + // Mark slot as in use + slot->gpio_pin = gpio_pin; + slot->in_use = 1; - return handle; + return handle; } void hal_gpio_counter_deinit(hal_gpio_counter_t counter) { - if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { - return; - } - - gpio_counter_state_t *slot = &counter_state[counter]; - if (!slot->in_use) { - return; - } - - // Stop the timer/counter - hal_gpio_counter_stop(counter); - - // Reset the counter - hal_gpio_counter_reset(counter); - - // Disable GPIO interrupt for the selected timer - GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)slot->gpio_pin; - if (slot->timer_idx == 0) { - drv_gpio_irq_risc0_dis(telink_pin); - } else if (slot->timer_idx == 1) { - drv_gpio_irq_risc1_dis(telink_pin); - } - - // Reset slot state - slot->gpio_pin = HAL_INVALID_PIN; - slot->in_use = 0; + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } + + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } + + // Stop the timer/counter + hal_gpio_counter_stop(counter); + + // Reset the counter + hal_gpio_counter_reset(counter); + + // Disable GPIO interrupt for the selected timer + GPIO_PinTypeDef telink_pin = (GPIO_PinTypeDef)slot->gpio_pin; + if (slot->timer_idx == 0) { + drv_gpio_irq_risc0_dis(telink_pin); + } else if (slot->timer_idx == 1) { + drv_gpio_irq_risc1_dis(telink_pin); + } + + // Reset slot state + slot->gpio_pin = HAL_INVALID_PIN; + slot->in_use = 0; } uint32_t hal_gpio_counter_read(hal_gpio_counter_t counter) { - if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { - return 0; - } + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return 0; + } - gpio_counter_state_t *slot = &counter_state[counter]; - if (!slot->in_use) { - return 0; - } + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return 0; + } - return reg_tmr_tick(slot->timer_idx); + return reg_tmr_tick(slot->timer_idx); } void hal_gpio_counter_reset(hal_gpio_counter_t counter) { - if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { - return; - } + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } - gpio_counter_state_t *slot = &counter_state[counter]; - if (!slot->in_use) { - return; - } + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } - timer_set_init_tick(slot->timer_idx, 0); + timer_set_init_tick(slot->timer_idx, 0); } void hal_gpio_counter_start(hal_gpio_counter_t counter) { - if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { - return; - } + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } - gpio_counter_state_t *slot = &counter_state[counter]; - if (!slot->in_use) { - return; - } + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } - timer_start(slot->timer_idx); + timer_start(slot->timer_idx); } void hal_gpio_counter_stop(hal_gpio_counter_t counter) { - if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { - return; - } + if (counter < 0 || counter >= MAX_GPIO_COUNTERS) { + return; + } - gpio_counter_state_t *slot = &counter_state[counter]; - if (!slot->in_use) { - return; - } + gpio_counter_state_t *slot = &counter_state[counter]; + if (!slot->in_use) { + return; + } - timer_stop(slot->timer_idx); + timer_stop(slot->timer_idx); }