ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_esp_hosted_gpio_edge.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35
36#include "ra8_attributes.h"
37#include "ra8_err.h"
39#include "ra8_icu_regs.h"
40#include "ra8_log.h"
41#include "ra8_pin_interface.h"
42#include "ra8_port_constants.h"
43#include "ra8_port_utils.h"
44#ifdef RA8_OFF_TARGET
45#include "ra8_esp_hosted_tx_shim_sync_internal.h"
46#else
47#include "tx_api.h"
48#endif
49
59static const char* const s_tag = "eh_edge";
60
89
120
131
143static TX_TIMER s_timer;
144
155static bool s_timer_live;
156
167
179static char s_tx_name_eh_edge[] = "eh_edge";
180
181RA8_PRIV bool
182priv_ra8_esp_hosted_gpio_edge_seen(uint8_t prev_level, uint8_t now_level, uint8_t sense)
183{
184 if (sense > (uint8_t)k_ra8_icu_irqmd_low) {
185 return false;
186 }
187 if (sense == (uint8_t)k_ra8_icu_irqmd_low) {
188 return now_level == (uint8_t)k_ra8_esp_hosted_gpio_edge_low;
189 }
190 if (prev_level == now_level) {
191 return false;
192 }
193 if (sense == (uint8_t)k_ra8_icu_irqmd_both) {
194 return true;
195 }
196 if (sense == (uint8_t)k_ra8_icu_irqmd_rising) {
197 return now_level == (uint8_t)k_ra8_esp_hosted_gpio_edge_high;
198 }
199 return now_level == (uint8_t)k_ra8_esp_hosted_gpio_edge_low;
200}
201
228{
229 for (uint8_t i = 0U; i < (uint8_t)k_ra8_esp_hosted_gpio_row_max; i++) {
230 if (s_rows[i].used && (s_rows[i].pin == pin)) {
231 return i;
232 }
233 }
234 return (uint8_t)k_ra8_esp_hosted_gpio_row_max;
235}
236
262static bool internal_sample(ra8_port_pin_t pin, uint8_t* out_level)
263{
266 if (pin_if->read(pin_if->ctx, pin, &level) != k_ra8_ok) {
267 return false;
268 }
269 *out_level = (level == k_ra8_level_high) ? (uint8_t)k_ra8_esp_hosted_gpio_edge_high
271 return true;
272}
273
296{
297 (void)arg;
299}
300
326{
327 if (s_timer_live) {
328 return k_ra8_ok;
329 }
330 const ULONG ticks = (ULONG)s_poll_ms;
331 const UINT st = tx_timer_create(&s_timer,
334 (ULONG)0,
335 ticks,
336 ticks,
337 TX_AUTO_ACTIVATE);
338 if (st != TX_SUCCESS) {
339 ra8_log_error_val(s_tag, "edge timer create failed", (uint32_t)st);
341 }
342 s_timer_live = true;
343 return k_ra8_ok;
344}
345
368{
369 if (!s_timer_live) {
370 return k_ra8_ok;
371 }
372 const UINT st = tx_timer_delete(&s_timer);
373 if (st != TX_SUCCESS) {
374 ra8_log_error_val(s_tag, "edge timer delete failed", (uint32_t)st);
376 }
377 s_timer_live = false;
378 return k_ra8_ok;
379}
380
382{
383 uint8_t count = 0U;
384 for (uint8_t i = 0U; i < (uint8_t)k_ra8_esp_hosted_gpio_row_max; i++) {
385 if (s_rows[i].used) {
386 count = (uint8_t)(count + (uint8_t)k_ra8_esp_hosted_gpio_edge_one_row);
387 }
388 }
389 return count;
390}
391
393{
394 if (period_ms == 0U) {
396 }
397 s_poll_ms = period_ms;
398 if (!s_timer_live) {
399 return k_ra8_ok;
400 }
401 const ra8_err_t err = internal_timer_disarm();
402 return (err == k_ra8_ok) ? internal_timer_arm() : err;
403}
404
406 uint8_t sense,
407 void (*handler)(void*),
408 void* arg)
409{
410 if (handler == nullptr) {
411 return k_ra8_err_null_ptr;
412 }
413 if (sense > (uint8_t)k_ra8_icu_irqmd_low) {
415 }
417 return k_ra8_err_exists;
418 }
419 uint8_t slot = (uint8_t)k_ra8_esp_hosted_gpio_row_max;
420 for (uint8_t i = 0U; i < (uint8_t)k_ra8_esp_hosted_gpio_row_max; i++) {
421 if (!s_rows[i].used) {
422 slot = i;
423 break;
424 }
425 }
426 if (slot >= (uint8_t)k_ra8_esp_hosted_gpio_row_max) {
427 return k_ra8_err_no_mem;
428 }
429
431 if (err != k_ra8_ok) {
432 ra8_log_error_val(s_tag, "polled pin input init failed", (uint32_t)err);
433 return err;
434 }
435 uint8_t level = (uint8_t)k_ra8_esp_hosted_gpio_edge_low;
436 (void)internal_sample(pin, &level);
437
438 s_rows[slot].pin = pin;
439 s_rows[slot].handler = handler;
440 s_rows[slot].arg = arg;
441 s_rows[slot].sense = sense;
442 s_rows[slot].last_level = level;
443 s_rows[slot].used = true;
444
445 const ra8_err_t timer_err = internal_timer_arm();
446 if (timer_err != k_ra8_ok) {
448 (void)ra8_gpio_release(pin);
449 }
450 return timer_err;
451}
452
454{
455 const uint8_t slot = internal_find(pin);
456 if (slot >= (uint8_t)k_ra8_esp_hosted_gpio_row_max) {
457 return k_ra8_err_not_found;
458 }
460 (void)ra8_gpio_release(pin);
462 return k_ra8_ok;
463 }
464 return internal_timer_disarm();
465}
466
468{
469 for (uint8_t i = 0U; i < (uint8_t)k_ra8_esp_hosted_gpio_row_max; i++) {
471 uint8_t now = (uint8_t)k_ra8_esp_hosted_gpio_edge_low;
472 if (row->used && internal_sample(row->pin, &now)) {
473 const uint8_t prev = row->last_level;
474 row->last_level = now;
475 if (priv_ra8_esp_hosted_gpio_edge_seen(prev, now, row->sense)) {
476 row->handler(row->arg);
477 }
478 }
479 }
480}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
ra8_board_eth_pin_t pin
Pin.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_exists
Item already exists – cannot create again.
Definition ra8_err.h:216
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_rtos_error
Generic RTOS error (reserved for future use).
Definition ra8_err.h:357
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
const ra8_pin_interface_t * priv_ra8_esp_hosted_gpio_pin_interface(void)
Report the pin driver currently installed in the slice.
static void internal_timer_expiry(ULONG arg)
ThreadX expiry function: run one sampling pass.
static bool internal_sample(ra8_port_pin_t pin, uint8_t *out_level)
Read one pin through the slice's injected pin interface.
ra8_err_t priv_ra8_esp_hosted_gpio_edge_register(ra8_port_pin_t pin, uint8_t sense, void(*handler)(void *), void *arg)
Take a pin under software edge detection.
void priv_ra8_esp_hosted_gpio_edge_poll_once(void)
Sample every polled row once and dispatch the edges seen.
static uint8_t internal_find(ra8_port_pin_t pin)
Find the row watching a pin.
static char s_tx_name_eh_edge[]
Writable ThreadX object name for the eh_edge object.
static ra8_err_t internal_timer_arm(void)
Create the shared periodic timer if it is not already running.
ra8_err_t priv_ra8_esp_hosted_gpio_edge_unregister(ra8_port_pin_t pin)
Drop a pin from software edge detection.
static bool s_timer_live
True while s_timer has been created and not yet deleted.
static uint16_t s_poll_ms
Sampling period in milliseconds, shared by every polled row.
ra8_esp_hosted_gpio_edge_const_t
Named constants the detector needs beyond the shared limits.
@ k_ra8_esp_hosted_gpio_edge_low
Sample read low.
@ k_ra8_esp_hosted_gpio_edge_high
Sample read high.
@ k_ra8_esp_hosted_gpio_edge_one_row
Rows one registration adds.
struct ra8_esp_hosted_gpio_edge_row ra8_esp_hosted_gpio_edge_row_t
static ra8_err_t internal_timer_disarm(void)
Delete the shared periodic timer if it is running.
ra8_err_t priv_ra8_esp_hosted_gpio_set_edge_poll_ms(uint16_t period_ms)
Set the sampling period the software edge detector runs at.
static TX_TIMER s_timer
The one periodic ThreadX timer shared by every polled row.
uint8_t priv_ra8_esp_hosted_gpio_edge_count(void)
Report how many pins are under software edge detection.
bool priv_ra8_esp_hosted_gpio_edge_seen(uint8_t prev_level, uint8_t now_level, uint8_t sense)
Decide whether two consecutive samples show the configured edge.
static ra8_esp_hosted_gpio_edge_row_t s_rows[k_ra8_esp_hosted_gpio_row_max]
Every pin currently under software edge detection.
Module-private surface of the esp-hosted side-band GPIO slice.
@ k_ra8_esp_hosted_gpio_poll_ms_default
Sampling period used until priv_ra8_esp_hosted_gpio_set_edge_poll_ms runs.
@ k_ra8_esp_hosted_gpio_row_max
Rows in the polled edge table; also the registration ceiling.
Interrupt Control Unit (ICU) register layout for the Renesas RA8D2.
@ k_ra8_icu_irqmd_rising
01: rising edge.
@ k_ra8_icu_irqmd_both
10: rising OR falling.
@ k_ra8_icu_irqmd_low
11: low-level sensitive.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error_val(tag, message, value)
RA8 log error val.
Definition ra8_log.h:337
Abstract pin-driver interface for dependency injection.
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
ra8_level_t
Digital output / input level.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
@ k_ra8_pull_none
No internal pull.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_input_init(ra8_port_pin_t pin, ra8_pin_pull_t pull)
Configure a pin as a digital input.
Definition gpio.c:121
ra8_err_t ra8_gpio_release(ra8_port_pin_t pin)
Release a GPIO pin claim.
Definition gpio.c:233
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
#define TX_SUCCESS
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
One pin under software edge detection.
ra8_port_pin_t pin
Packed pin being sampled.
uint8_t last_level
Level seen by the previous sample.
uint8_t sense
Edge selector, ra8_icu_irqmd_t.
void(* handler)(void *arg)
Vendored callback to invoke.
bool used
True while the row is occupied.
void * arg
Opaque argument for handler.
Vtable for a pin driver.
void * ctx
Opaque context handed to every call.
ra8_err_t(* read)(void *ctx, ra8_port_pin_t pin, ra8_level_t *out_level)
Read a pin.