Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/hal/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
35 changes: 35 additions & 0 deletions src/silabs/hal/gpio_counter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

#include "hal/gpio.h"
#include <stdio.h>


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
}
1 change: 1 addition & 0 deletions src/silabs/slcp_files/zigbee.slcp
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
1 change: 1 addition & 0 deletions src/silabs/slcp_files/zigbee_end_device.slcp
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
26 changes: 26 additions & 0 deletions src/stub/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <pin> <value>\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 },
Expand All @@ -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 },
};
Expand Down
80 changes: 80 additions & 0 deletions src/stub/hal/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
3 changes: 3 additions & 0 deletions src/stub/hal/stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/stub/stub_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ void stub_app_print_help(void) {
"bytes)");
puts(" freeze_time <0|1> - Freeze/unfreeze time");
puts(" step_time <ms> - Advance time by ms");
puts(" set_counter <pin> <value> - Set pulse counter value");
puts(" q, quit - Exit");
}

Expand Down
1 change: 1 addition & 0 deletions src/telink/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 1 addition & 1 deletion src/telink/hal/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading