ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_esp_hosted_rtos_pool.c File Reference

Memory and queue half of the esp-hosted OS-abstraction vtable. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_esp_hosted_port.h"
#include "ra8_esp_hosted_rtos_internal.h"
#include "ra8_log.h"
#include "tx_api.h"
#include "port_esp_hosted_host_os.h"
Include dependency graph for ra8_esp_hosted_rtos_pool.c:

Go to the source code of this file.

Data Structures

struct  ra8_esp_hosted_alloc_hdr_t
 Bookkeeping written immediately below every allocated payload. More...
struct  ra8_esp_hosted_queue_slot_t
 One row of the fixed queue table. More...
struct  ra8_esp_hosted_pool_state_t
 Module state of the memory and queue half – entirely static. More...

Enumerations

enum  ra8_esp_hosted_pool_const_t : uint32_t {
  k_ra8_esp_hosted_hdr_bytes = 16U ,
  k_ra8_esp_hosted_hdr_magic = 0x52384D42U ,
  k_ra8_esp_hosted_align_none = 1U ,
  k_ra8_esp_hosted_align_max = 64U ,
  k_ra8_esp_hosted_alloc_max = 8192U ,
  k_ra8_esp_hosted_queue_words_max = 16U ,
  k_ra8_esp_hosted_queue_word_bytes = 4U ,
  k_ra8_esp_hosted_queue_elems_max = 64U
}
 Numeric constants of the fixed-storage allocator and queue table. More...

Functions

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.
void priv_ra8_esp_hosted_rtos_pool_stats (uint32_t *out_available, uint32_t *out_fragments)
 Read live transport-pool occupancy.
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.
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.
static void * internal_h_memcpy (void *dest, const void *src, uint32_t size)
 Copy a byte range for the vendored core.
static void * internal_h_memset (void *buf, int val, size_t len)
 Fill a byte range for the vendored core.
static void * internal_h_malloc (size_t size)
 Serve an unaligned allocation from the transport byte pool.
static void * internal_h_calloc (size_t blk_no, size_t size)
 Serve a zeroed array allocation from the transport byte pool.
static void internal_h_free (void *ptr)
 Return a block to the transport byte pool.
static void * internal_h_realloc (void *mem, size_t newsize)
 Resize a block, preserving its contents up to the shorter length.
static void * internal_h_malloc_align (size_t size, size_t align)
 Serve an aligned allocation from the transport byte pool.
static void internal_h_free_align (void *ptr)
 Return an aligned block to the transport byte pool.
static ra8_esp_hosted_queue_slot_tinternal_queue_slot (const void *handle)
 Resolve an opaque queue handle to its live table row.
static void * internal_h_create_queue (uint32_t qnum_elem, uint32_t qitem_size)
 Create a fixed-capacity message queue for the vendored core.
static int internal_h_queue_item (void *queue_handle, void *item, int timeout)
 Enqueue one message, blocking for at most timeout.
static int internal_h_dequeue_item (void *queue_handle, void *item, int timeout)
 Dequeue one message, blocking for at most timeout.
static int internal_h_queue_msg_waiting (void *queue_handle)
 Report how many messages a queue is currently holding.
static int internal_h_reset_queue (void *queue_handle)
 Discard every message a queue is holding.
static int internal_h_destroy_queue (void *queue_handle)
 Delete a queue and return its ring storage to the queue pool.
ra8_err_t priv_ra8_esp_hosted_rtos_bind_pool (hosted_osi_funcs_t *out)
 Populate the memory and queue slots of the vtable.

Variables

static const char * s_tag = "ESPH_MEM"
 Log tag for the memory and queue half of the port.
static ra8_esp_hosted_pool_state_t s_pool
 Singleton state of the memory and queue half.
static uint8_t s_transport_mem [k_ra8_esp_hosted_pool_bytes]
 Backing storage for the transport buffer pool.
static uint8_t s_queue_mem [k_ra8_esp_hosted_queue_pool_bytes]
 Backing storage for the queue message-storage pool.
static char s_tx_name_esph_buf [] = "esph_buf"
 Writable ThreadX object name for the esph_buf object.
static char s_tx_name_esph_q [] = "esph_q"
 Writable ThreadX object name for the esph_q object.

Detailed Description

Memory and queue half of the esp-hosted OS-abstraction vtable.

Tag
[Ring 4 / PORT] {World: NS}

See port/esp-hosted/src/ra8_esp_hosted_rtos_internal.h for the contracts. This translation unit owns both ThreadX byte pools – the transport buffer pool the vendored allocators draw from, and the queue-storage pool the message rings are carved out of – so the two vtable groups that depend on them live together here. It also owns the host-build ThreadX model's shared state; that is what the RA8_ESP_HOSTED_TX_SHIM_IMPL define below selects.

Since
0.1.0

Definition in file ra8_esp_hosted_rtos_pool.c.

Enumeration Type Documentation

◆ ra8_esp_hosted_pool_const_t

enum ra8_esp_hosted_pool_const_t : uint32_t

Numeric constants of the fixed-storage allocator and queue table.

Every literal the allocator layout depends on lives here so the documented block layout and the code cannot drift apart.

Invariant
k_ra8_esp_hosted_hdr_bytes is at least sizeof the header struct on every supported ABI, which a static_assert checks.
k_ra8_esp_hosted_align_max is a power of two.
Example:
void * priv_ra8_esp_hosted_rtos_alloc(size_t size, size_t align)
Allocate an aligned block from the transport byte pool.
@ k_ra8_esp_hosted_align_none
"No extra alignment" selector.
See also
priv_ra8_esp_hosted_rtos_alloc
Since
0.1.0
Enumerator
k_ra8_esp_hosted_hdr_bytes 

Per-block header footprint.

k_ra8_esp_hosted_hdr_magic 

'R8MB' sentinel in each header.

k_ra8_esp_hosted_align_none 

"No extra alignment" selector.

k_ra8_esp_hosted_align_max 

Strictest alignment served.

k_ra8_esp_hosted_alloc_max 

Largest single payload served.

k_ra8_esp_hosted_queue_words_max 

ThreadX message-size cap, words.

k_ra8_esp_hosted_queue_word_bytes 

Bytes in one ThreadX message word.

k_ra8_esp_hosted_queue_elems_max 

Deepest ring the port will make.

Definition at line 85 of file ra8_esp_hosted_rtos_pool.c.

Function Documentation

◆ internal_h_calloc()

void * internal_h_calloc ( size_t blk_no,
size_t size )
static

Serve a zeroed array allocation from the transport byte pool.

Multiplies the two operands with an overflow guard before calling the allocator, then zeroes the payload.

Parameters
[in]blk_noElement count.
[in]sizeBytes per element.
Returns
Pointer to the zeroed payload, or null on failure.
Return values
nullptrAn operand was zero, the product overflowed, or the pool could not satisfy the request.
non-nullA zeroed block of blk_no * size bytes.
Precondition
The substrate is initialised.
The product is within k_ra8_esp_hosted_alloc_max.
Postcondition
On success every payload byte is zero.
On failure nothing is allocated.
Note
Thread-safe; ThreadX serialises the pool.
Since
0.1.0

Definition at line 479 of file ra8_esp_hosted_rtos_pool.c.

References k_ra8_esp_hosted_align_none, k_ra8_esp_hosted_alloc_max, memset(), priv_ra8_esp_hosted_rtos_alloc(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_create_queue()

void * internal_h_create_queue ( uint32_t qnum_elem,
uint32_t qitem_size )
static

Create a fixed-capacity message queue for the vendored core.

Rounds the element size up to whole ThreadX words, carves the ring out of the queue byte pool and takes the first free table row. Rejects an element size larger than sixteen words, which ThreadX cannot express.

Parameters
[in]qnum_elemRing depth in messages.
[in]qitem_sizeElement size in bytes.
Returns
Opaque queue handle, or null on failure.
Return values
nullptrAn argument was out of contract, the table is full, or the queue pool could not supply the ring.
non-nullA handle usable with the other queue slots.
Precondition
The substrate is initialised.
qitem_size is at most sixty-four bytes.
Postcondition
On success one table row is occupied and reports zero messages.
On failure no ring storage is leaked.
Note
Not thread-safe against a concurrent create or destroy.
Since
0.1.0

Definition at line 648 of file ra8_esp_hosted_rtos_pool.c.

References k_ra8_esp_hosted_max_queues, k_ra8_esp_hosted_queue_elems_max, k_ra8_esp_hosted_queue_word_bytes, priv_ra8_esp_hosted_rtos_queue_words(), RA8_INTERNAL, ra8_log_error, s_pool, s_tag, s_tx_name_esph_q, and TX_SUCCESS.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_dequeue_item()

int internal_h_dequeue_item ( void * queue_handle,
void * item,
int timeout )
static

Dequeue one message, blocking for at most timeout.

A zero timeout is a non-blocking receive returning RET_OK on success and non-zero when empty – the exact shape spi_drv.c chains three of together to drain its priority queues.

Parameters
[in]queue_handleHandle from _h_create_queue.
[out]itemReceives the message.
[in]timeoutWait in milliseconds; 0 = try, negative = forever.
Returns
RET_OK on success, a negative RET_* code otherwise.
Return values
RET_OKA message was copied into item.
RET_INVALIDThe handle or the item pointer was not usable.
RET_FAIL_TIMEOUTThe queue stayed empty for the whole wait.
RET_FAILThreadX rejected the receive for another reason.
Precondition
The substrate is initialised.
item covers the element size the queue was created with.
Postcondition
On success the queue's message count has fallen by one.
On failure item is untouched.
Note
Thread-safe; ThreadX serialises the queue. Validation is by return code because the vtable signature has no error channel.
Since
0.1.0

Definition at line 737 of file ra8_esp_hosted_rtos_pool.c.

References ra8_esp_hosted_queue_slot_t::cb, ra8_esp_hosted_queue_slot_t::enqueued, internal_queue_slot(), priv_ra8_esp_hosted_rtos_ms_to_ticks(), RA8_INTERNAL, RET_FAIL, RET_FAIL_TIMEOUT, RET_INVALID, RET_OK, and TX_SUCCESS.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_destroy_queue()

int internal_h_destroy_queue ( void * queue_handle)
static

Delete a queue and return its ring storage to the queue pool.

Frees the table row last, so a concurrent handle lookup either sees a live queue or none at all.

Parameters
[in]queue_handleHandle from _h_create_queue.
Returns
RET_OK on success, a negative RET_* code otherwise.
Return values
RET_OKThe queue and its storage were released.
RET_INVALIDThe handle was not usable.
RET_FAILThreadX rejected the delete or the storage release.
Precondition
The substrate is initialised.
No thread is blocked on the queue.
Postcondition
The table row is free for reuse.
The ring storage is available to the queue pool again.
Note
Not thread-safe against a concurrent create or destroy. Validation is by return code because the vtable signature has no error channel.
Since
0.1.0

Definition at line 826 of file ra8_esp_hosted_rtos_pool.c.

References ra8_esp_hosted_queue_slot_t::cb, ra8_esp_hosted_queue_slot_t::enqueued, internal_queue_slot(), RA8_INTERNAL, RET_FAIL, RET_INVALID, RET_OK, ra8_esp_hosted_queue_slot_t::storage, TX_SUCCESS, and ra8_esp_hosted_queue_slot_t::used.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_free()

void internal_h_free ( void * ptr)
static

Return a block to the transport byte pool.

Forwards to priv_ra8_esp_hosted_rtos_release. Because every block carries the same header, this also correctly frees an aligned block.

Parameters
[in]ptrPayload pointer previously handed out by this port.
Precondition
ptr came from this port's allocator, or is null.
The block has not already been freed.
Postcondition
On success the pool reports the bytes as available again.
A null or foreign pointer leaves the pool unchanged.
Note
Thread-safe; ThreadX serialises the pool. Validation is by log because the vtable signature returns void.
Since
0.1.0

Definition at line 508 of file ra8_esp_hosted_rtos_pool.c.

References priv_ra8_esp_hosted_rtos_release(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_free_align()

void internal_h_free_align ( void * ptr)
static

Return an aligned block to the transport byte pool.

The same operation as _h_free: the uniform header means the release path never has to know whether the block was aligned.

Parameters
[in]ptrAligned payload pointer previously handed out by this port.
Precondition
ptr came from _h_malloc_align, or is null.
The block has not already been freed.
Postcondition
On success the pool reports the padding and payload as available.
A null or foreign pointer leaves the pool unchanged.
Note
Thread-safe; ThreadX serialises the pool. Validation is by log because the vtable signature returns void.
Since
0.1.0

Definition at line 592 of file ra8_esp_hosted_rtos_pool.c.

References priv_ra8_esp_hosted_rtos_release(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_malloc()

void * internal_h_malloc ( size_t size)
static

Serve an unaligned allocation from the transport byte pool.

Forwards to priv_ra8_esp_hosted_rtos_alloc with no alignment demand, so the block costs the sixteen-byte header and nothing more.

Parameters
[in]sizePayload bytes required.
Returns
Pointer to the payload, or null on failure.
Return values
nullptrThe substrate is down, the size is out of contract, or the pool is exhausted.
non-nullA block of at least size bytes.
Precondition
The substrate is initialised.
size is non-zero and within k_ra8_esp_hosted_alloc_max.
Postcondition
On success the pool reports fewer bytes available.
On failure the pool is unchanged.
Note
Thread-safe; ThreadX serialises the pool.
Since
0.1.0

Definition at line 457 of file ra8_esp_hosted_rtos_pool.c.

References k_ra8_esp_hosted_align_none, priv_ra8_esp_hosted_rtos_alloc(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_malloc_align()

void * internal_h_malloc_align ( size_t size,
size_t align )
static

Serve an aligned allocation from the transport byte pool.

Forwards to priv_ra8_esp_hosted_rtos_alloc, which over-allocates and stashes the base pointer immediately below the aligned payload. The vendored transport asks for HOSTED_MEM_ALIGNMENT_64, which is also the Cortex-M85 cache-line size, so a DMA buffer can be cleaned and invalidated without disturbing a neighbouring allocation.

Parameters
[in]sizePayload bytes required.
[in]alignRequired alignment; a power of two up to 64.
Returns
Pointer to the aligned payload, or null on failure.
Return values
nullptrAn argument was out of contract or the pool is exhausted.
non-nullA block whose address is a multiple of align.
Precondition
The substrate is initialised.
align is a power of two no greater than 64.
Postcondition
On success the returned address is a multiple of align.
Worst-case overhead is 16 + align - 1 bytes.
Note
Thread-safe; ThreadX serialises the pool.
Since
0.1.0

Definition at line 574 of file ra8_esp_hosted_rtos_pool.c.

References priv_ra8_esp_hosted_rtos_alloc(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_memcpy()

void * internal_h_memcpy ( void * dest,
const void * src,
uint32_t size )
static

Copy a byte range for the vendored core.

Thin memcpy wrapper; the slot exists so a port may substitute a DMA copy without touching the core.

Parameters
[out]destDestination buffer of at least size bytes.
[in]srcSource buffer of at least size bytes.
[in]sizeByte count to copy.
Returns
The destination pointer, or null when a pointer argument was null.
Return values
destThe copy completed.
nullptrdest or src was null; nothing was copied.
Precondition
The buffers do not overlap.
Both buffers cover size bytes.
Postcondition
dest holds a byte-for-byte copy of src on success.
No allocation is performed.
Note
Thread-safe; touches only caller storage. Validation is by return value because the vtable signature has no error channel.
Since
0.1.0

Definition at line 407 of file ra8_esp_hosted_rtos_pool.c.

References memcpy(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_memset()

void * internal_h_memset ( void * buf,
int val,
size_t len )
static

Fill a byte range for the vendored core.

Thin memset wrapper kept behind the vtable for the same reason as _h_memcpy.

Parameters
[out]bufBuffer of at least len bytes.
[in]valByte value to write, taken modulo 256 as memset does.
[in]lenByte count to write.
Returns
The buffer pointer, or null when buf was null.
Return values
bufThe fill completed.
nullptrbuf was null; nothing was written.
Precondition
buf covers len bytes.
The caller tolerates a null return rather than a fault.
Postcondition
Every byte of the range equals val on success.
No allocation is performed.
Note
Thread-safe; touches only caller storage. Validation is by return value because the vtable signature has no error channel.
Since
0.1.0

Definition at line 433 of file ra8_esp_hosted_rtos_pool.c.

References memset(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_queue_item()

int internal_h_queue_item ( void * queue_handle,
void * item,
int timeout )
static

Enqueue one message, blocking for at most timeout.

Zero milliseconds is a try-send; HOSTED_BLOCK_MAX (and any negative value) blocks until there is room, which is what the vendored SPI driver relies on when it hands a frame to the transmit queue.

Parameters
[in]queue_handleHandle from _h_create_queue.
[in]itemMessage to copy in.
[in]timeoutWait in milliseconds; 0 = try, negative = forever.
Returns
RET_OK on success, a negative RET_* code otherwise.
Return values
RET_OKThe message was enqueued.
RET_INVALIDThe handle or the item pointer was not usable.
RET_FAIL_TIMEOUTThe queue stayed full for the whole wait.
RET_FAILThreadX rejected the send for another reason.
Precondition
The substrate is initialised.
item covers the element size the queue was created with.
Postcondition
On success the queue's message count has risen by one.
On failure the queue is unchanged.
Note
Thread-safe; ThreadX serialises the queue. Validation is by return code because the vtable signature has no error channel.
Since
0.1.0

Definition at line 701 of file ra8_esp_hosted_rtos_pool.c.

References ra8_esp_hosted_queue_slot_t::cb, ra8_esp_hosted_queue_slot_t::enqueued, internal_queue_slot(), priv_ra8_esp_hosted_rtos_ms_to_ticks(), RA8_INTERNAL, RET_FAIL, RET_FAIL_TIMEOUT, RET_INVALID, RET_OK, and TX_SUCCESS.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_queue_msg_waiting()

int internal_h_queue_msg_waiting ( void * queue_handle)
static

Report how many messages a queue is currently holding.

Reads the port's own tally rather than calling tx_queue_info_get: the tally is maintained by the only two functions that move messages, so it costs nothing and cannot disagree.

Parameters
[in]queue_handleHandle from _h_create_queue.
Returns
Message count, or a negative RET_* code.
Return values
RET_INVALIDThe handle was not usable.
0..nThe number of messages waiting.
Precondition
The substrate is initialised.
The caller treats a negative result as an error, not a count.
Postcondition
No queue state is modified.
The result never exceeds the ring depth.
Note
Thread-safe for reads; the tally is a single aligned word.
Since
0.1.0

Definition at line 770 of file ra8_esp_hosted_rtos_pool.c.

References ra8_esp_hosted_queue_slot_t::enqueued, internal_queue_slot(), RA8_INTERNAL, and RET_INVALID.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_realloc()

void * internal_h_realloc ( void * mem,
size_t newsize )
static

Resize a block, preserving its contents up to the shorter length.

ThreadX byte pools cannot grow a block in place and do not record its size, so this allocates a fresh block, copies min(old, new) bytes from the header-recorded size, and releases the original. A null pointer behaves as an allocation and a zero size behaves as a free, matching what the vendored core expects of realloc.

Parameters
[in]memExisting payload pointer, or null to allocate.
[in]newsizeNew payload size in bytes; zero frees.
Returns
Pointer to the resized payload, or null.
Return values
nullptrThe block was freed, or the new block could not be served.
non-nullA block of newsize bytes holding the old contents.
Precondition
mem came from this port's allocator, or is null.
The substrate is initialised.
Postcondition
On success the first min(old, new) bytes are preserved.
On failure the original block is still valid and still owned by the caller.
Note
Thread-safe; ThreadX serialises the pool.
Since
0.1.0

Definition at line 533 of file ra8_esp_hosted_rtos_pool.c.

References k_ra8_esp_hosted_align_none, k_ra8_ok, memcpy(), priv_ra8_esp_hosted_rtos_alloc(), priv_ra8_esp_hosted_rtos_block_size(), priv_ra8_esp_hosted_rtos_release(), and RA8_INTERNAL.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_h_reset_queue()

int internal_h_reset_queue ( void * queue_handle)
static

Discard every message a queue is holding.

Flushes the ThreadX ring and clears the port's tally so the two cannot drift.

Parameters
[in]queue_handleHandle from _h_create_queue.
Returns
RET_OK on success, a negative RET_* code otherwise.
Return values
RET_OKThe queue is empty.
RET_INVALIDThe handle was not usable.
RET_FAILThreadX rejected the flush.
Precondition
The substrate is initialised.
The caller accepts that queued messages are lost.
Postcondition
The queue reports zero messages waiting.
The ring's capacity is unchanged.
Note
Thread-safe; ThreadX serialises the queue. Validation is by return code because the vtable signature has no error channel.
Since
0.1.0

Definition at line 796 of file ra8_esp_hosted_rtos_pool.c.

References ra8_esp_hosted_queue_slot_t::cb, ra8_esp_hosted_queue_slot_t::enqueued, internal_queue_slot(), RA8_INTERNAL, RET_FAIL, RET_INVALID, RET_OK, and TX_SUCCESS.

Referenced by priv_ra8_esp_hosted_rtos_bind_pool().

◆ internal_queue_slot()

ra8_esp_hosted_queue_slot_t * internal_queue_slot ( const void * handle)
static

Resolve an opaque queue handle to its live table row.

Scans the fixed table for pointer identity rather than trusting the handle, so a foreign or stale pointer is rejected instead of followed.

Parameters
[in]handleOpaque handle the core is holding.
Returns
The matching live slot, or null.
Return values
nullptrThe handle is null, foreign, or names a freed slot.
non-nullThe live table row for that handle.
Precondition
The substrate is initialised.
The caller does not retain the pointer past a destroy.
Postcondition
No state is modified.
The returned slot, when non-null, has its in-use flag set.
Note
Thread-safe for reads; the table is only mutated during bring-up and teardown.
Since
0.1.0

Definition at line 617 of file ra8_esp_hosted_rtos_pool.c.

References k_ra8_esp_hosted_max_queues, RA8_INTERNAL, and s_pool.

Referenced by internal_h_dequeue_item(), internal_h_destroy_queue(), internal_h_queue_item(), internal_h_queue_msg_waiting(), and internal_h_reset_queue().

◆ priv_ra8_esp_hosted_rtos_alloc()

void * priv_ra8_esp_hosted_rtos_alloc ( size_t size,
size_t align )
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.

Parameters
[in]sizePayload bytes required. Must be non-zero.
[in]alignRequired 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".
Returns
Pointer to the aligned payload, or null on failure.
Return values
nullptrThe substrate is down, an argument was out of contract, or the pool could not satisfy the request.
non-nullA block of at least size bytes aligned to align.
Precondition
The substrate is initialised.
align is a power of two.
Postcondition
On success the returned address is a multiple of align.
On failure the pool is left exactly as it was.
Note
Thread-safe; ThreadX serialises the pool internally.
Warning
The block must be released with priv_ra8_esp_hosted_rtos_release, not with tx_byte_release, or the padding leaks.
Example:
void* p = priv_ra8_esp_hosted_rtos_alloc(1600U, 64U);
See also
priv_ra8_esp_hosted_rtos_release
Since
0.1.0
NASA Power of 10 Compliance:
  • Rule 3: draws from a fixed init-time pool; never grows.
  • Rule 5: three preconditions and two postconditions are checked.

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().

◆ priv_ra8_esp_hosted_rtos_bind_pool()

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.

Parameters
[out]outVtable to populate. Must be non-null.
Returns
ra8_err_t Error code.
Return values
k_ra8_okEvery memory and queue slot is populated.
k_ra8_err_null_ptrout was null.
Precondition
out points at storage that outlives the vendored core.
priv_ra8_esp_hosted_rtos_init has run, or the slots will report failures.
Postcondition
The eight memory slots and six queue slots are non-null.
No other slot is written.
Note
Not thread-safe; call once during bring-up.
Example:
ra8_err_t priv_ra8_esp_hosted_rtos_bind_pool(hosted_osi_funcs_t *out)
Populate the memory and queue slots of the vtable.
See also
priv_ra8_esp_hosted_rtos_bind
Since
0.1.0

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().

◆ priv_ra8_esp_hosted_rtos_block_size()

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.

Parameters
[in]ptrPayload pointer previously returned by the allocator.
[out]out_sizeReceives the recorded payload size in bytes.
Returns
ra8_err_t Error code.
Return values
k_ra8_okout_size holds the recorded size.
k_ra8_err_null_ptrptr or out_size was null.
k_ra8_err_invalid_argThe header sentinel did not match.
Precondition
ptr came from priv_ra8_esp_hosted_rtos_alloc.
out_size is writable.
Postcondition
On success *out_size is the size originally requested.
No pool state is modified.
Note
Thread-safe; reads immutable header bytes.
Example:
size_t n = 0U;
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.
See also
priv_ra8_esp_hosted_rtos_alloc
Since
0.1.0

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().

◆ priv_ra8_esp_hosted_rtos_pool_deinit()

ra8_err_t priv_ra8_esp_hosted_rtos_pool_deinit ( void )
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.

Returns
ra8_err_t Error code.
Return values
k_ra8_okBoth pools and every queue were released.
k_ra8_err_not_initializedThe pools were not created.
k_ra8_err_rtos_errorThreadX refused a delete.
Precondition
No thread is blocked on a port queue.
The vendored core has stopped allocating.
Postcondition
The queue table is empty.
Neither pool satisfies a later allocation.
Note
Not thread-safe; call from the same context as the init.
Example:
ra8_err_t priv_ra8_esp_hosted_rtos_pool_deinit(void)
Destroy every queue and both byte pools.
See also
priv_ra8_esp_hosted_rtos_pool_init
Since
0.1.0

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().

◆ priv_ra8_esp_hosted_rtos_pool_init()

ra8_err_t priv_ra8_esp_hosted_rtos_pool_init ( void )
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.

Returns
ra8_err_t Error code.
Return values
k_ra8_okBoth pools are ready.
k_ra8_err_invalid_stateThe pools were already created.
k_ra8_err_rtos_errorThreadX refused one of the pools.
Precondition
The ThreadX kernel is running.
No block from a previous incarnation of the pools is still held.
Postcondition
On success both pools report their full size available.
On failure neither pool is left half-created.
Note
Not thread-safe; call once during bring-up.
Example:
ra8_err_t priv_ra8_esp_hosted_rtos_pool_init(void)
Create the two byte pools over their static backing arrays.
See also
priv_ra8_esp_hosted_rtos_pool_deinit
Since
0.1.0

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().

◆ priv_ra8_esp_hosted_rtos_pool_stats()

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.

Parameters
[out]out_availableReceives bytes still allocatable. May be null.
[out]out_fragmentsReceives the pool's fragment count. May be null.
Precondition
The substrate is initialised, or both outputs are set to zero.
At least one output pointer is non-null for the call to be useful.
Postcondition
No pool state is modified.
Every non-null output has been written.
Note
Safe from any thread; ThreadX guards the pool internally.
Example:
uint32_t avail = 0U;
uint32_t frags = 0U;
void priv_ra8_esp_hosted_rtos_pool_stats(uint32_t *out_available, uint32_t *out_fragments)
Read live transport-pool occupancy.
See also
priv_ra8_esp_hosted_rtos_init
Since
0.1.0

Definition at line 284 of file ra8_esp_hosted_rtos_pool.c.

References s_pool.

Referenced by ra8_esp_hosted_mem_dump().

◆ priv_ra8_esp_hosted_rtos_queue_words()

uint32_t priv_ra8_esp_hosted_rtos_queue_words ( uint32_t item_bytes)
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.

Parameters
[in]item_bytesElement size in bytes as the core supplied it.
Returns
Message size in 32-bit words, or zero when unusable.
Return values
0item_bytes was zero, or exceeded sixteen words.
1..16The rounded-up word count.
Precondition
item_bytes is the size the core will actually copy.
The caller treats zero as "refuse to create the queue".
Postcondition
No state is modified.
The result multiplied by four is at least item_bytes.
Note
Pure function; safe from any context.
Warning
A zero return must not be passed to tx_queue_create.
MC/DC:
Decision (item_bytes == 0U) || (words > k_ra8_esp_hosted_queue_words_max) (2 conditions). Vector 1: 28 bytes -> false/false. Vector 2: 0 bytes -> true/(short-circuit). Vector 3: 68 bytes -> false/true. Vectors 1+2 prove the emptiness condition's independent influence; 1+3 prove the same for the word cap. N+1 = 3 vectors for N=2: minimal MC/DC.
Example:
const uint32_t words = priv_ra8_esp_hosted_rtos_queue_words((uint32_t)qitem_size);
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.
See also
priv_ra8_esp_hosted_rtos_ms_to_ticks
Since
0.1.0

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().

◆ priv_ra8_esp_hosted_rtos_release()

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.

Parameters
[in]ptrPayload pointer previously returned by the allocator. A null pointer is accepted and reported as invalid rather than dereferenced.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe block was returned to the pool.
k_ra8_err_null_ptrptr was null.
k_ra8_err_invalid_argThe header sentinel did not match.
k_ra8_err_rtos_errorThreadX refused the release.
Precondition
ptr came from priv_ra8_esp_hosted_rtos_alloc.
The block has not already been released.
Postcondition
On success the pool reports the block's bytes as available again.
On failure no pool state changes.
Note
Thread-safe; ThreadX serialises the pool internally.
Warning
Releasing a foreign pointer is detected by the sentinel, but a double release of a reallocated address is not.
Example:
ra8_err_t priv_ra8_esp_hosted_rtos_release(void *ptr)
Release a block obtained from priv_ra8_esp_hosted_rtos_alloc.
See also
priv_ra8_esp_hosted_rtos_alloc
Since
0.1.0

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().

Variable Documentation

◆ s_pool

Singleton state of the memory and queue half.

Zero-initialised at link time; brought up by priv_ra8_esp_hosted_rtos_pool_init.

Note
Static; do not access outside this TU.
Warning
Direct modification bypasses every ThreadX consistency check.
Since
0.1.0

Definition at line 174 of file ra8_esp_hosted_rtos_pool.c.

Referenced by internal_c6_cam_http_send(), internal_c6_cam_net_create(), internal_h_create_queue(), internal_queue_slot(), priv_net_create_ip(), priv_net_create_ip(), priv_ra8_esp_hosted_rtos_alloc(), priv_ra8_esp_hosted_rtos_pool_deinit(), priv_ra8_esp_hosted_rtos_pool_init(), and priv_ra8_esp_hosted_rtos_pool_stats().

◆ s_queue_mem

uint8_t s_queue_mem[k_ra8_esp_hosted_queue_pool_bytes]
static

Backing storage for the queue message-storage pool.

Aligned to k_ra8_esp_hosted_align_max; ThreadX only needs word alignment for a message ring, so this is comfortably stricter.

Note
Static; owned exclusively by s_pool.queue_pool.
Warning
Never write to it except through a ThreadX queue service.
Since
0.1.0

Definition at line 196 of file ra8_esp_hosted_rtos_pool.c.

Referenced by priv_ra8_esp_hosted_rtos_pool_init().

◆ s_tag

const char* s_tag = "ESPH_MEM"
static

Log tag for the memory and queue half of the port.

Shared by every diagnostic this translation unit emits.

Note
Static; do not access outside this TU.
Warning
Changing it changes log-scraping expectations on the bench.
Since
0.1.0

Definition at line 68 of file ra8_esp_hosted_rtos_pool.c.

◆ s_transport_mem

uint8_t s_transport_mem[k_ra8_esp_hosted_pool_bytes]
static

Backing storage for the transport buffer pool.

Aligned to k_ra8_esp_hosted_align_max so a 64-byte-aligned transport buffer never needs the full worst-case padding.

Note
Static; owned exclusively by s_pool.transport.
Warning
Never write to it except through the allocator.
Since
0.1.0

Definition at line 185 of file ra8_esp_hosted_rtos_pool.c.

Referenced by priv_ra8_esp_hosted_rtos_pool_init().

◆ s_tx_name_esph_buf

char s_tx_name_esph_buf[] = "esph_buf"
static

Writable ThreadX object name for the esph_buf object.

ThreadX takes object names as CHAR* rather than const CHAR*, so a string literal would have to be cast and would drop a qualifier the object really has. A writable array removes the cast instead of hiding it.

Note
Read by the create call only; ThreadX keeps the pointer.
Warning
Must outlive the object it names; file-scope storage does.
Since
0.1.0

Definition at line 209 of file ra8_esp_hosted_rtos_pool.c.

Referenced by priv_ra8_esp_hosted_rtos_pool_init().

◆ s_tx_name_esph_q

char s_tx_name_esph_q[] = "esph_q"
static

Writable ThreadX object name for the esph_q object.

ThreadX takes object names as CHAR* rather than const CHAR*, so a string literal would have to be cast and would drop a qualifier the object really has. A writable array removes the cast instead of hiding it.

Note
Read by the create call only; ThreadX keeps the pointer.
Warning
Must outlive the object it names; file-scope storage does.
Since
0.1.0

Definition at line 222 of file ra8_esp_hosted_rtos_pool.c.

Referenced by internal_h_create_queue(), and priv_ra8_esp_hosted_rtos_pool_init().