|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Module-private contract of the esp-hosted RTOS abstraction slice. More...
#include <stddef.h>#include <stdint.h>#include "esp_hosted_os_abstraction.h"#include "ra8_attributes.h"#include "ra8_err.h"Go to the source code of this file.
Functions | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_init (void) |
| Bring the RTOS substrate up: byte pools and empty object tables. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_deinit (void) |
| Tear the RTOS substrate down, deleting every outstanding object. | |
| bool | priv_ra8_esp_hosted_rtos_is_ready (void) |
| Report whether the RTOS substrate is currently initialised. | |
| void | priv_ra8_esp_hosted_rtos_pool_stats (uint32_t *out_available, uint32_t *out_fragments) |
| Read live transport-pool occupancy. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_bind (hosted_osi_funcs_t *out) |
| Populate the thread, sleep, timer and clock slots of the vtable. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_bind_pool (hosted_osi_funcs_t *out) |
| Populate the memory and queue slots of the vtable. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_bind_sync (hosted_osi_funcs_t *out) |
| Populate the mutex and semaphore slots of the vtable. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_sync_init (void) |
| Clear the mutex and semaphore tables and mark them usable. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_sync_deinit (void) |
| Delete every outstanding mutex and semaphore. | |
| 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. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_pool_init (void) |
| Create the two byte pools over their static backing arrays. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_pool_deinit (void) |
| Destroy every queue and both byte pools. | |
| 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_queue_words (uint32_t item_bytes) |
| Round an esp-hosted queue element size up to whole ThreadX words. | |
| uint32_t | priv_ra8_esp_hosted_rtos_us_spin_iters (uint32_t cpu_hz, uint32_t usec) |
| Size the busy-wait loop that stands in for a microsecond delay. | |
| void * | priv_ra8_esp_hosted_rtos_alloc (size_t size, size_t align) |
| Allocate an aligned block from the transport byte pool. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_release (void *ptr) |
| Release a block obtained from priv_ra8_esp_hosted_rtos_alloc. | |
| ra8_err_t | priv_ra8_esp_hosted_rtos_block_size (const void *ptr, size_t *out_size) |
| Read back the payload size recorded for an allocated block. | |
Module-private contract of the esp-hosted RTOS abstraction slice.
The vendored esp-hosted core reaches ThreadX only through the 72-entry hosted_osi_funcs_t vtable. This header declares the port-private symbols that build the RTOS part of that vtable and the fixed-storage substrate underneath it: the byte pools, the object tables, and the three pieces of arithmetic (millisecond-to-tick, queue word rounding, microsecond spin sizing) that carry real decisions and therefore have to be reachable from tests/ on their own terms.
Nothing here is public API. Production code outside port/esp-hosted/src/ must go through ra8_esp_hosted_port_init and then through g_h.funcs.
Definition in file ra8_esp_hosted_rtos_internal.h.
|
nodiscard |
Allocate an aligned block from the transport byte pool.
The single allocation primitive underneath _h_malloc, _h_calloc, _h_realloc and _h_malloc_align. ThreadX byte pools neither record a block's size nor honour an alignment request, and tx_byte_release demands the exact pointer tx_byte_allocate returned – so the port over-allocates and lays each block out as:
* base ---> [ padding 0..align-1 ][ 16-byte header ][ payload (size bytes) ] * ^ ^ * | +-- returned to caller * +-- header sits immediately below it *
The header holds the base pointer (so the release can hand ThreadX exactly what it gave out), the payload size (so _h_realloc can copy the right number of bytes) and a sentinel (so a foreign pointer is rejected rather than followed). It is written and read with memcpy because its address inherits only the requested alignment, which may be weaker than the pointer's own.
Worst-case overhead is 16 + align - 1 bytes: 16 bytes for a plain _h_malloc (which asks for no extra alignment) and 79 bytes for a 64-byte-aligned transport buffer.
| [in] | size | Payload bytes required. Must be non-zero. |
| [in] | align | Required payload alignment in bytes; must be a power of two no greater than k_ra8_esp_hosted_align_max. Pass 1 for "no particular alignment". |
| nullptr | The substrate is down, an argument was out of contract, or the pool could not satisfy the request. |
| non-null | A block of at least size bytes aligned to align. |
Definition at line 305 of file ra8_esp_hosted_rtos_pool.c.
References ra8_esp_hosted_alloc_hdr_t::base, k_ra8_esp_hosted_align_max, k_ra8_esp_hosted_alloc_max, k_ra8_esp_hosted_hdr_bytes, k_ra8_esp_hosted_hdr_magic, ra8_esp_hosted_alloc_hdr_t::magic, memcpy(), s_pool, ra8_esp_hosted_alloc_hdr_t::size, and TX_SUCCESS.
Referenced by internal_h_calloc(), internal_h_malloc(), internal_h_malloc_align(), and internal_h_realloc().
| ra8_err_t priv_ra8_esp_hosted_rtos_bind | ( | hosted_osi_funcs_t * | out | ) |
Populate the thread, sleep, timer and clock slots of the vtable.
Writes the ten rows this translation unit implements. It does not call the sibling binders: each unit binds only the rows whose implementations it can see, so a row can never be assigned from a unit that cannot name the function behind it. priv_ra8_esp_hosted_osi_bind_all calls all three. Every slot outside this group – memory, queue, mutex, semaphore, GPIO, bus, logging, transport – is left exactly as the caller had it.
| [out] | out | Vtable to populate. Must be non-null. |
| k_ra8_ok | The ten thread, sleep, timer and clock slots are set. |
| k_ra8_err_null_ptr | out was null. |
Definition at line 814 of file ra8_esp_hosted_rtos.c.
References internal_h_blocking_delay(), internal_h_get_time_ms(), internal_h_msleep(), internal_h_sleep(), internal_h_thread_cancel(), internal_h_thread_create(), internal_h_thread_yield(), internal_h_timer_start(), internal_h_timer_stop(), internal_h_usleep(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by priv_ra8_esp_hosted_osi_bind_all().
| ra8_err_t priv_ra8_esp_hosted_rtos_bind_pool | ( | hosted_osi_funcs_t * | out | ) |
Populate the memory and queue slots of the vtable.
The binder of the pool translation unit, which owns the byte pools the allocators and queue rings draw from. Called by priv_ra8_esp_hosted_osi_bind_all alongside the other two binders.
| [out] | out | Vtable to populate. Must be non-null. |
| k_ra8_ok | Every memory and queue slot is populated. |
| k_ra8_err_null_ptr | out was null. |
Definition at line 845 of file ra8_esp_hosted_rtos_pool.c.
References internal_h_calloc(), internal_h_create_queue(), internal_h_dequeue_item(), internal_h_destroy_queue(), internal_h_free(), internal_h_free_align(), internal_h_malloc(), internal_h_malloc_align(), internal_h_memcpy(), internal_h_memset(), internal_h_queue_item(), internal_h_queue_msg_waiting(), internal_h_realloc(), internal_h_reset_queue(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by priv_ra8_esp_hosted_osi_bind_all().
| ra8_err_t priv_ra8_esp_hosted_rtos_bind_sync | ( | hosted_osi_funcs_t * | out | ) |
Populate the mutex and semaphore slots of the vtable.
The binder of the synchronisation translation unit, which owns the mutex and semaphore tables. Called by priv_ra8_esp_hosted_osi_bind_all alongside the other two binders. There are no mempool-lock rows to fill; see the file-level note on H_USE_MEMPOOL.
| [out] | out | Vtable to populate. Must be non-null. |
| k_ra8_ok | Every mutex and semaphore slot is populated. |
| k_ra8_err_null_ptr | out was null. |
Definition at line 452 of file ra8_esp_hosted_rtos_sync.c.
References internal_h_create_mutex(), internal_h_create_semaphore(), internal_h_destroy_mutex(), internal_h_destroy_semaphore(), internal_h_get_semaphore(), internal_h_lock_mutex(), internal_h_post_semaphore(), internal_h_post_semaphore_from_isr(), internal_h_unlock_mutex(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by priv_ra8_esp_hosted_osi_bind_all().
| ra8_err_t priv_ra8_esp_hosted_rtos_block_size | ( | const void * | ptr, |
| size_t * | out_size ) |
Read back the payload size recorded for an allocated block.
Exists because _h_realloc has to copy min(old, new) bytes and ThreadX byte pools do not record a block's size. The value comes from the header priv_ra8_esp_hosted_rtos_alloc wrote, so it is the size the caller asked for, not the rounded pool footprint.
| [in] | ptr | Payload pointer previously returned by the allocator. |
| [out] | out_size | Receives the recorded payload size in bytes. |
| k_ra8_ok | out_size holds the recorded size. |
| k_ra8_err_null_ptr | ptr or out_size was null. |
| k_ra8_err_invalid_arg | The header sentinel did not match. |
Definition at line 360 of file ra8_esp_hosted_rtos_pool.c.
References k_ra8_err_invalid_arg, k_ra8_esp_hosted_hdr_bytes, k_ra8_esp_hosted_hdr_magic, k_ra8_ok, ra8_esp_hosted_alloc_hdr_t::magic, memcpy(), RA8_CHECK_NULL_PTR, s_tag, and ra8_esp_hosted_alloc_hdr_t::size.
Referenced by internal_h_realloc().
|
nodiscard |
Tear the RTOS substrate down, deleting every outstanding object.
Walks each object table and deletes whatever is still in use – timers are deactivated then deleted, threads terminated then deleted, queues, mutexes and semaphores deleted – then deletes both byte pools and clears the module state. Objects the vendored core still holds handles to are deleted regardless, so the core must be stopped first.
| k_ra8_ok | Everything was released. |
| k_ra8_err_not_initialized | The substrate was not up. |
| k_ra8_err_rtos_error | ThreadX refused to delete an object or a pool. |
Definition at line 787 of file ra8_esp_hosted_rtos.c.
References internal_h_thread_cancel(), internal_h_timer_stop(), k_ra8_err_not_initialized, k_ra8_err_rtos_error, k_ra8_esp_hosted_max_threads, k_ra8_esp_hosted_max_timers, k_ra8_ok, memset(), priv_ra8_esp_hosted_rtos_pool_deinit(), priv_ra8_esp_hosted_rtos_sync_deinit(), ra8_log_error, RET_OK, s_rtos, and s_tag.
Referenced by internal_unwind().
|
nodiscard |
Bring the RTOS substrate up: byte pools and empty object tables.
Creates the two TX_BYTE_POOL instances – the transport buffer pool sized by k_ra8_esp_hosted_pool_bytes and the queue-storage pool sized by k_ra8_esp_hosted_queue_pool_bytes – over static arrays, clears every object table and caches the CPU rate used to size the sub-millisecond spin in _h_usleep. This is the only allocation the RTOS slice ever performs and it happens exactly here, during initialisation.
A second call is an error, not a no-op: a silent success would hand the caller pools whose contents the first caller still owns, and would hide a double bring-up that is always a bug in the calling sequence.
| k_ra8_ok | The substrate is ready; the vtable may be bound. |
| k_ra8_err_invalid_state | The substrate was already initialised. |
| k_ra8_err_rtos_error | ThreadX refused to create a byte pool. |
Definition at line 767 of file ra8_esp_hosted_rtos.c.
References k_ra8_clock_id_cpuclk0, k_ra8_err_invalid_state, k_ra8_esp_hosted_default_cpu_hz, k_ra8_ok, memset(), priv_ra8_esp_hosted_rtos_pool_init(), priv_ra8_esp_hosted_rtos_sync_init(), ra8_cgc_get_clock_hz(), ra8_log_error, ra8_log_warn, RA8_RETURN_ON_ERROR, s_rtos, s_tag, and tx_time_get.
Referenced by internal_bring_up().
|
nodiscard |
Report whether the RTOS substrate is currently initialised.
Reads the single module-state flag so callers can decide whether a teardown is needed without provoking an error return, and so host tests can assert the state machine without reaching into the module.
| true | priv_ra8_esp_hosted_rtos_init completed and no teardown has run. |
| false | The substrate has never been up, failed, or was torn down. |
Definition at line 762 of file ra8_esp_hosted_rtos.c.
References s_rtos.
|
nodiscard |
Convert an esp-hosted millisecond timeout to a ThreadX wait option.
The vendored core expresses every timeout in milliseconds through an int parameter, and ThreadX takes a tick count. Two values are special: zero means "do not block" and HOSTED_BLOCK_MAX (all ones) means "block until satisfied". HOSTED_BLOCK_MAX reaches the vtable as -1 after its conversion to int, so the rule this function implements is "any negative value blocks forever" – deliberately wider than "exactly -1", so a sign-extension bug elsewhere can never turn an intended block into a zero-tick busy loop. The kernel runs at 1 kHz (TX_TIMER_TICKS_PER_SECOND is 1000), so the positive case is the identity; it is still spelled out here rather than inlined at 30 call sites so that changing the tick rate is a one-line change and so the mapping is directly testable.
| [in] | timeout_ms | Timeout in milliseconds: 0 = do not block, negative = block forever, positive = that many milliseconds. |
| 0 | timeout_ms was zero: TX_NO_WAIT. |
| 0xFFFFFFFF | timeout_ms was negative: TX_WAIT_FOREVER. |
| 1..0x7FFFFFFF | The millisecond count, unchanged. |
Definition at line 364 of file ra8_esp_hosted_rtos.c.
References k_ra8_esp_hosted_ms_per_tick, and TX_WAIT_FOREVER.
Referenced by internal_h_dequeue_item(), internal_h_get_semaphore(), internal_h_lock_mutex(), internal_h_queue_item(), and internal_h_timer_start().
|
nodiscard |
Destroy every queue and both byte pools.
The pool half of priv_ra8_esp_hosted_rtos_deinit: deletes any queue still in use, releases its storage, then deletes both pools and clears the pool state so a later allocation fails cleanly rather than touching a dead control block.
| k_ra8_ok | Both pools and every queue were released. |
| k_ra8_err_not_initialized | The pools were not created. |
| k_ra8_err_rtos_error | ThreadX refused a delete. |
Definition at line 255 of file ra8_esp_hosted_rtos_pool.c.
References k_ra8_err_not_initialized, k_ra8_err_rtos_error, k_ra8_esp_hosted_max_queues, k_ra8_ok, memset(), ra8_log_error, s_pool, s_tag, and TX_SUCCESS.
Referenced by priv_ra8_esp_hosted_rtos_deinit().
|
nodiscard |
Create the two byte pools over their static backing arrays.
The pool half of priv_ra8_esp_hosted_rtos_init. Separated so the memory translation unit owns both the arrays and the control blocks, and so a test can bring the allocator up without the thread and timer tables.
| k_ra8_ok | Both pools are ready. |
| k_ra8_err_invalid_state | The pools were already created. |
| k_ra8_err_rtos_error | ThreadX refused one of the pools. |
Definition at line 228 of file ra8_esp_hosted_rtos_pool.c.
References k_ra8_err_invalid_state, k_ra8_err_rtos_error, k_ra8_ok, memset(), ra8_log_error, s_pool, s_queue_mem, s_tag, s_transport_mem, s_tx_name_esph_buf, s_tx_name_esph_q, and TX_SUCCESS.
Referenced by priv_ra8_esp_hosted_rtos_init().
| void priv_ra8_esp_hosted_rtos_pool_stats | ( | uint32_t * | out_available, |
| uint32_t * | out_fragments ) |
Read live transport-pool occupancy.
Calls tx_byte_pool_info_get on the transport buffer pool and hands back the two numbers a fragmentation problem actually shows up in: bytes still available, and the fragment count. These are real ThreadX numbers, not a port-side tally, which is the whole reason the port keeps a real byte pool rather than a bump allocator. Backs ra8_esp_hosted_mem_dump.
| [out] | out_available | Receives bytes still allocatable. May be null. |
| [out] | out_fragments | Receives the pool's fragment count. May be null. |
Definition at line 284 of file ra8_esp_hosted_rtos_pool.c.
References s_pool.
Referenced by ra8_esp_hosted_mem_dump().
|
nodiscard |
Round an esp-hosted queue element size up to whole ThreadX words.
tx_queue_create takes its message size in 32-bit words, capped at TX_16_ULONG. The core asks for byte sizes that are not necessarily a whole number of words – sizeof(interface_buffer_handle_t) is 28 bytes on this ABI, which is seven words exactly, but nothing in the vtable contract guarantees that. The rounding is upward, so an element always fits; the cost is at most three unused bytes per message, which is why rounding is preferable to rejecting an odd size.
A request that would need more than sixteen words is rejected rather than truncated: ThreadX would refuse the create anyway, and a truncating port would silently corrupt every message.
| [in] | item_bytes | Element size in bytes as the core supplied it. |
| 0 | item_bytes was zero, or exceeded sixteen words. |
| 1..16 | The rounded-up word count. |
Definition at line 375 of file ra8_esp_hosted_rtos_pool.c.
References k_ra8_esp_hosted_queue_word_bytes, and k_ra8_esp_hosted_queue_words_max.
Referenced by internal_h_create_queue().
| ra8_err_t priv_ra8_esp_hosted_rtos_release | ( | void * | ptr | ) |
Release a block obtained from priv_ra8_esp_hosted_rtos_alloc.
Reads the header immediately below ptr, checks its sentinel, and hands ThreadX the original base pointer. Because every allocation carries the same header, an aligned block and a plain one are released identically – which is why _h_free and _h_free_align can be, and are, the same operation.
| [in] | ptr | Payload pointer previously returned by the allocator. A null pointer is accepted and reported as invalid rather than dereferenced. |
| k_ra8_ok | The block was returned to the pool. |
| k_ra8_err_null_ptr | ptr was null. |
| k_ra8_err_invalid_arg | The header sentinel did not match. |
| k_ra8_err_rtos_error | ThreadX refused the release. |
Definition at line 343 of file ra8_esp_hosted_rtos_pool.c.
References ra8_esp_hosted_alloc_hdr_t::base, k_ra8_err_invalid_arg, k_ra8_err_rtos_error, k_ra8_esp_hosted_hdr_bytes, k_ra8_esp_hosted_hdr_magic, k_ra8_ok, ra8_esp_hosted_alloc_hdr_t::magic, memcpy(), RA8_CHECK_NULL_PTR, ra8_log_error, s_tag, and TX_SUCCESS.
Referenced by internal_h_free(), internal_h_free_align(), and internal_h_realloc().
|
nodiscard |
Resolve an opaque handle to its row index in a fixed table.
Every handle the port hands the vendored core is the address of a table row. Rather than trusting that address, this scans the table for pointer identity and checks the occupancy flag, so a foreign pointer or a handle retained past its destroy is rejected instead of followed. The tables hold at most eight rows, so the scan is cheaper than any bookkeeping that would replace it.
| [in] | handle | Opaque handle the core is holding. |
| [in] | base | Address of the table's first row. |
| [in] | stride | Bytes between consecutive rows. |
| [in] | count | Number of rows in the table. |
| [in] | used | Occupancy flags for the same table. |
| count | The handle is null, foreign, or names a freed row. |
| 0..count-1 | The live row index. |
Definition at line 230 of file ra8_esp_hosted_rtos.c.
Referenced by internal_h_destroy_mutex(), internal_h_destroy_semaphore(), internal_h_get_semaphore(), internal_h_lock_mutex(), internal_h_post_semaphore(), internal_h_post_semaphore_from_isr(), internal_h_thread_cancel(), internal_h_timer_stop(), and internal_h_unlock_mutex().
|
nodiscard |
Claim the first free row of an occupancy bitmap.
The one place a table row is taken, shared by every object kind so none of them can grow its table by accident. Returning count rather than a sentinel index keeps the caller's bound check and the failure check the same comparison.
| [in,out] | used | Occupancy flags; must cover count entries. |
| [in] | count | Number of rows in the table. |
| count | Every row was occupied, or used was null. |
| 0..count-1 | The claimed row, now marked in use. |
Definition at line 216 of file ra8_esp_hosted_rtos.c.
Referenced by internal_h_create_mutex(), internal_h_create_semaphore(), internal_h_thread_create(), and internal_h_timer_start().
|
nodiscard |
Delete every outstanding mutex and semaphore.
The synchronisation half of priv_ra8_esp_hosted_rtos_deinit: walks both tables and deletes whatever is still in use, then clears the state so a later create fails cleanly rather than touching a dead control block.
| k_ra8_ok | Every object was released. |
| k_ra8_err_not_initialized | The tables were not initialised. |
| k_ra8_err_rtos_error | ThreadX refused a delete. |
Definition at line 431 of file ra8_esp_hosted_rtos_sync.c.
References internal_h_destroy_mutex(), internal_h_destroy_semaphore(), k_ra8_err_not_initialized, k_ra8_err_rtos_error, k_ra8_esp_hosted_max_mutexes, k_ra8_esp_hosted_max_semaphores, k_ra8_ok, memset(), ra8_log_error, RET_OK, s_sync, and s_tag.
Referenced by priv_ra8_esp_hosted_rtos_deinit().
|
nodiscard |
Clear the mutex and semaphore tables and mark them usable.
The synchronisation half of priv_ra8_esp_hosted_rtos_init. Separated so the unit that owns the tables also owns their lifecycle, and so a test can bring the locks up without the allocator.
| k_ra8_ok | Both tables are empty and usable. |
| k_ra8_err_invalid_state | The tables were already initialised. |
Definition at line 420 of file ra8_esp_hosted_rtos_sync.c.
References k_ra8_err_invalid_state, k_ra8_ok, memset(), ra8_log_error, s_sync, and s_tag.
Referenced by priv_ra8_esp_hosted_rtos_init().
|
nodiscard |
Size the busy-wait loop that stands in for a microsecond delay.
There is no microsecond timer on this target: ra8_time.h offers a millisecond tick and a millisecond busy delay, and nothing finer. Rather than fake a microsecond sleep or round every sub-millisecond request to zero, _h_usleep spins, and this function decides for how long. The estimate is cpu_hz / 1e6 cycles per microsecond divided by k_ra8_esp_hosted_spin_cycles_per_iter, the measured cost of one iteration of the volatile-counter loop on the Cortex-M85.
The result is clamped to k_ra8_esp_hosted_spin_iters_max so the loop is statically bounded (NASA Power of 10 Rule 2) whatever the caller asks for. Accuracy is roughly a factor of two: cache state, the branch predictor and any interrupt taken mid-spin all move the real duration, and none of them is modelled. That is stated rather than hidden – a caller needing better than that needs a hardware timer, not a better guess.
| [in] | cpu_hz | Core clock in hertz; zero means "rate unknown". |
| [in] | usec | Microseconds to spin for. |
| 0 | cpu_hz or usec was zero: do not spin at all. |
| 1..k_ra8_esp_hosted_spin_iters_max | The clamped iteration count. |
Definition at line 375 of file ra8_esp_hosted_rtos.c.
References k_ra8_esp_hosted_hz_per_mhz, k_ra8_esp_hosted_spin_cycles_per_iter, and k_ra8_esp_hosted_spin_iters_max.
Referenced by internal_spin_us().