ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_esp_hosted_rtos_sync.c
Go to the documentation of this file.
1
25
26#include <stddef.h>
27#include <stdint.h>
28#include <string.h>
29
30#include "ra8_attributes.h"
31#include "ra8_check.h"
32#include "ra8_err.h"
33#include "ra8_esp_hosted_port.h"
35#include "ra8_log.h"
36
37#ifdef RA8_OFF_TARGET
38#include "ra8_esp_hosted_tx_shim_sync_internal.h"
39#else
40#include "tx_api.h"
41#endif
42
44
53static const char* s_tag = "ESPH_SYNC";
54
74
97
108
109/* ----------------------------------------------------------------------- */
110/* Mutex vtable slots */
111/* ----------------------------------------------------------------------- */
112
129{
130 if (!s_sync.ready) {
131 return nullptr;
132 }
133 const uint32_t idx =
135 if (idx == (uint32_t)k_ra8_esp_hosted_max_mutexes) {
136 ra8_log_error(s_tag, "mutex table exhausted");
137 return nullptr;
138 }
139 if (tx_mutex_create(&s_sync.mutexes[idx], nullptr, TX_INHERIT) != TX_SUCCESS) {
140 s_sync.mutex_used[idx] = false;
141 return nullptr;
142 }
143 return &s_sync.mutexes[idx];
144}
145
165RA8_INTERNAL static int internal_h_lock_mutex(void* mutex_handle, int timeout_ms)
166{
167 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(mutex_handle,
168 s_sync.mutexes,
169 sizeof(s_sync.mutexes[0]),
171 s_sync.mutex_used);
172 if (idx == (uint32_t)k_ra8_esp_hosted_max_mutexes) {
173 return RET_INVALID;
174 }
175 const UINT rc =
177 return (rc == TX_SUCCESS) ? RET_OK : RET_FAIL_TIMEOUT;
178}
179
197RA8_INTERNAL static int internal_h_unlock_mutex(void* mutex_handle)
198{
199 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(mutex_handle,
200 s_sync.mutexes,
201 sizeof(s_sync.mutexes[0]),
203 s_sync.mutex_used);
204 if (idx == (uint32_t)k_ra8_esp_hosted_max_mutexes) {
205 return RET_INVALID;
206 }
207 return (tx_mutex_put(&s_sync.mutexes[idx]) == TX_SUCCESS) ? RET_OK : RET_FAIL;
208}
209
227RA8_INTERNAL static int internal_h_destroy_mutex(void* mutex_handle)
228{
229 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(mutex_handle,
230 s_sync.mutexes,
231 sizeof(s_sync.mutexes[0]),
233 s_sync.mutex_used);
234 if (idx == (uint32_t)k_ra8_esp_hosted_max_mutexes) {
235 return RET_INVALID;
236 }
237 const int rc = (tx_mutex_delete(&s_sync.mutexes[idx]) == TX_SUCCESS) ? RET_OK : RET_FAIL;
238 s_sync.mutex_used[idx] = false;
239 return rc;
240}
241
242/* ----------------------------------------------------------------------- */
243/* Semaphore vtable slots */
244/* ----------------------------------------------------------------------- */
245
273RA8_INTERNAL static void* internal_h_create_semaphore(int max_count)
274{
275 if (!s_sync.ready || (max_count <= 0)) {
276 return nullptr;
277 }
278 const uint32_t idx =
280 if (idx == (uint32_t)k_ra8_esp_hosted_max_semaphores) {
281 ra8_log_error(s_tag, "semaphore table exhausted");
282 return nullptr;
283 }
284 if (tx_semaphore_create(&s_sync.sems[idx], nullptr, (ULONG)k_ra8_esp_hosted_sem_initial) !=
285 TX_SUCCESS) {
286 s_sync.sem_used[idx] = false;
287 return nullptr;
288 }
289 return &s_sync.sems[idx];
290}
291
311RA8_INTERNAL static int internal_h_get_semaphore(void* semaphore_handle, int timeout_ms)
312{
313 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(semaphore_handle,
314 s_sync.sems,
315 sizeof(s_sync.sems[0]),
317 s_sync.sem_used);
318 if (idx == (uint32_t)k_ra8_esp_hosted_max_semaphores) {
319 return RET_INVALID;
320 }
321 const UINT rc =
322 tx_semaphore_get(&s_sync.sems[idx], (ULONG)priv_ra8_esp_hosted_rtos_ms_to_ticks(timeout_ms));
323 return (rc == TX_SUCCESS) ? RET_OK : RET_FAIL_TIMEOUT;
324}
325
344RA8_INTERNAL static int internal_h_post_semaphore(void* semaphore_handle)
345{
346 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(semaphore_handle,
347 s_sync.sems,
348 sizeof(s_sync.sems[0]),
350 s_sync.sem_used);
351 if (idx == (uint32_t)k_ra8_esp_hosted_max_semaphores) {
352 return RET_INVALID;
353 }
354 return (tx_semaphore_put(&s_sync.sems[idx]) == TX_SUCCESS) ? RET_OK : RET_FAIL;
355}
356
376{
377 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(semaphore_handle,
378 s_sync.sems,
379 sizeof(s_sync.sems[0]),
381 s_sync.sem_used);
382 if (idx == (uint32_t)k_ra8_esp_hosted_max_semaphores) {
383 return RET_INVALID;
384 }
385 return (tx_semaphore_put(&s_sync.sems[idx]) == TX_SUCCESS) ? RET_OK : RET_FAIL;
386}
387
405RA8_INTERNAL static int internal_h_destroy_semaphore(void* semaphore_handle)
406{
407 const uint32_t idx = priv_ra8_esp_hosted_rtos_slot_index(semaphore_handle,
408 s_sync.sems,
409 sizeof(s_sync.sems[0]),
411 s_sync.sem_used);
412 if (idx == (uint32_t)k_ra8_esp_hosted_max_semaphores) {
413 return RET_INVALID;
414 }
415 const int rc = (tx_semaphore_delete(&s_sync.sems[idx]) == TX_SUCCESS) ? RET_OK : RET_FAIL;
416 s_sync.sem_used[idx] = false;
417 return rc;
418}
419
421{
422 if (s_sync.ready) {
423 ra8_log_error(s_tag, "sync tables already initialised");
425 }
426 (void)memset(&s_sync, 0, sizeof(s_sync));
427 s_sync.ready = true;
428 return k_ra8_ok;
429}
430
432{
433 if (!s_sync.ready) {
434 ra8_log_error(s_tag, "sync tables not initialised");
436 }
437 ra8_err_t worst = k_ra8_ok;
438 for (uint32_t i = 0U; i < (uint32_t)k_ra8_esp_hosted_max_semaphores; ++i) {
439 if (s_sync.sem_used[i] && (internal_h_destroy_semaphore(&s_sync.sems[i]) != RET_OK)) {
440 worst = k_ra8_err_rtos_error;
441 }
442 }
443 for (uint32_t i = 0U; i < (uint32_t)k_ra8_esp_hosted_max_mutexes; ++i) {
444 if (s_sync.mutex_used[i] && (internal_h_destroy_mutex(&s_sync.mutexes[i]) != RET_OK)) {
445 worst = k_ra8_err_rtos_error;
446 }
447 }
448 (void)memset(&s_sync, 0, sizeof(s_sync));
449 return worst;
450}
451
453{
454 RA8_CHECK_NULL_PTR(out, s_tag, "vtable is NULL");
455 out->_h_create_mutex = internal_h_create_mutex;
456 out->_h_lock_mutex = internal_h_lock_mutex;
457 out->_h_unlock_mutex = internal_h_unlock_mutex;
458 out->_h_destroy_mutex = internal_h_destroy_mutex;
459 out->_h_create_semaphore = internal_h_create_semaphore;
460 out->_h_get_semaphore = internal_h_get_semaphore;
461 out->_h_post_semaphore = internal_h_post_semaphore;
462 out->_h_post_semaphore_from_isr = internal_h_post_semaphore_from_isr;
463 out->_h_destroy_semaphore = internal_h_destroy_semaphore;
464 return k_ra8_ok;
465}
esp-hosted port header: RTOS handle types, return codes and budgets.
#define RET_FAIL
Operation failed for an unspecified reason.
#define RET_FAIL_TIMEOUT
The requested wait expired before the operation could complete.
#define RET_INVALID
A parameter was out of contract (null handle, bad size).
#define RET_OK
Operation completed.
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_rtos_error
Generic RTOS error (reserved for future use).
Definition ra8_err.h:357
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Public entry point of the RA8D2 + ThreadX port of esp-hosted.
@ k_ra8_esp_hosted_max_mutexes
Mutexes the port can hand out, covering the bus lock and the mempool lock with headroom for the RPC l...
@ k_ra8_esp_hosted_max_semaphores
Counting semaphores the port can hand out before refusing.
uint32_t priv_ra8_esp_hosted_rtos_ms_to_ticks(int timeout_ms)
Convert an esp-hosted millisecond timeout to a ThreadX wait option.
uint32_t priv_ra8_esp_hosted_rtos_slot_take(bool *used, uint32_t count)
Claim the first free row of an occupancy bitmap.
uint32_t priv_ra8_esp_hosted_rtos_slot_index(const void *handle, const void *base, size_t stride, uint32_t count, const bool *used)
Resolve an opaque handle to its row index in a fixed table.
Module-private contract of the esp-hosted RTOS abstraction slice.
ra8_err_t priv_ra8_esp_hosted_rtos_sync_deinit(void)
Delete every outstanding mutex and semaphore.
static int internal_h_post_semaphore(void *semaphore_handle)
Post a semaphore from thread context.
static int internal_h_unlock_mutex(void *mutex_handle)
Release a mutex the caller owns.
static int internal_h_destroy_mutex(void *mutex_handle)
Delete a mutex and free its table row.
static int internal_h_lock_mutex(void *mutex_handle, int timeout_ms)
Take a mutex, blocking for at most timeout_ms.
ra8_err_t priv_ra8_esp_hosted_rtos_sync_init(void)
Clear the mutex and semaphore tables and mark them usable.
static int internal_h_get_semaphore(void *semaphore_handle, int timeout_ms)
Take a semaphore, blocking for at most timeout_ms.
ra8_err_t priv_ra8_esp_hosted_rtos_bind_sync(hosted_osi_funcs_t *out)
Populate the mutex and semaphore slots of the vtable.
static ra8_esp_hosted_sync_state_t s_sync
Singleton state of the mutex and semaphore half.
static int internal_h_destroy_semaphore(void *semaphore_handle)
Delete a semaphore and free its table row.
static void * internal_h_create_mutex(void)
Create a mutex from the fixed mutex table.
static void * internal_h_create_semaphore(int max_count)
Create a counting semaphore from the fixed semaphore table.
ra8_esp_hosted_sync_const_t
Numeric constants of the mutex and semaphore half.
@ k_ra8_esp_hosted_sem_initial
Instances a new semaphore starts with.
static int internal_h_post_semaphore_from_isr(void *semaphore_handle)
Post a semaphore from an interrupt handler.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
#define TX_SUCCESS
#define tx_mutex_delete
#define tx_mutex_create
#define tx_mutex_put
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
#define tx_mutex_get
Opaque mutex stand-in for the host build.
Module state of the mutex and semaphore half – entirely static.
TX_SEMAPHORE sems[k_ra8_esp_hosted_max_semaphores]
Semaphore table.
bool sem_used[k_ra8_esp_hosted_max_semaphores]
Semaphore occupancy.
TX_MUTEX mutexes[k_ra8_esp_hosted_max_mutexes]
Mutex table.
bool mutex_used[k_ra8_esp_hosted_max_mutexes]
Mutex occupancy.