|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
ThreadX inter-thread queue (TX_QUEUE) demo on the EK-RA8D2. More...
#include <stdint.h>#include "ra8_board_ek_ra8d2.h"#include "ra8_boot_entry.h"#include "ra8_cgc.h"#include "ra8_err.h"#include "ra8_isr.h"#include "ra8_time.h"#include "tx_api.h"Go to the source code of this file.
Enumerations | |
| enum | ipc_demo_cfg_t : uint32_t { k_ipc_demo_baud = 115200U , k_ipc_demo_period_ms = 1000U , k_ipc_demo_period_ticks = 1000U , k_ipc_demo_thread_stack = 2048U , k_ipc_demo_producer_prio = 5U , k_ipc_demo_consumer_prio = 4U , k_ipc_demo_queue_capacity = 8U } |
| Compile-time configuration for the ThreadX IPC demo. More... | |
| enum | ipc_demo_payload_t : uint32_t { k_ipc_demo_payload_ping = 0x676E6970U , k_ipc_demo_payload_pong = 0x676E6F70U } |
| 32-bit ASCII payload tags exchanged across the queue. More... | |
Functions | |
| static void | ipc_demo_panic_halt (void) |
| Halt forever in WFI on a fatal init failure. | |
| static void | ipc_demo_log (const uint8_t *s, uint32_t len) |
| Write a static ASCII string to SCI8. | |
| static void | ipc_demo_setup_or_halt (void) |
| Bring CGC + SCI8 up. | |
| static void | ipc_producer_thread_entry (ULONG thread_input) |
| Producer thread body – 1 Hz "ping" enqueue. | |
| static void | ipc_consumer_thread_entry (ULONG thread_input) |
| Consumer thread body – blocking receive + log. | |
| void | tx_application_define (void *first_unused_memory) |
| ThreadX application init callback. | |
| void | main (void) |
| Application entry. | |
Variables | |
| static const uint8_t | k_ipc_demo_banner [] = "[ipc_demo] M85 starting\r\n" |
| Static log lines streamed over SCI8 (must remain ASCII). | |
| static const uint8_t | k_ipc_demo_send_msg [] = "[ipc_demo] -> ping\r\n" |
| static const uint8_t | k_ipc_demo_recv_msg [] = "[ipc_demo] <- pong\r\n" |
| volatile uint32_t | g_ipc_demo_tick = 0U |
| HIL liveness counter – incremented per consumer wakeup. | |
| static TX_QUEUE | s_ipc_queue |
| ThreadX queue control block + backing storage. | |
| static ULONG | s_ipc_queue_storage [k_ipc_demo_queue_capacity] |
| static TX_THREAD | s_producer_thread |
| ThreadX control block + stack for the producer thread. | |
| static uint8_t | s_producer_stack [k_ipc_demo_thread_stack] |
| static TX_THREAD | s_consumer_thread |
| ThreadX control block + stack for the consumer thread. | |
| static uint8_t | s_consumer_stack [k_ipc_demo_thread_stack] |
ThreadX inter-thread queue (TX_QUEUE) demo on the EK-RA8D2.
Single-core (Cortex-M85, CPU0) ThreadX demo exercising the ThreadX queue primitive (tx_queue_create / tx_queue_send / tx_queue_receive) as a producer/consumer IPC channel between two threads. This used to drive the on-chip IPC FIFO between the M85 and a (never-flashed) M33 peer, which left the send FIFO permanently full after four 1 Hz iterations and printed send err on every subsequent tick. The HIL gate explicitly fails on send err or <no reply>, so the demo is recast as an entirely-local ThreadX queue exchange:
Failure modes guarded against:
| Name | Priority | Period | Action |
|---|---|---|---|
| producer | 5 | 1000ms | tx_queue_send("ping") + log "-> ping" |
| consumer | 4 | block | tx_queue_receive() + log "<- pong" |
Definition in file main.c.
| enum ipc_demo_cfg_t : uint32_t |
Compile-time configuration for the ThreadX IPC demo.
SCI8 is the J-Link OB CDC channel on the EK-RA8D2 board. period_ms is the inter-iteration sleep used by the producer. queue_capacity is the slot count for the inter-thread queue; the consumer always drains faster than the 1 Hz producer can fill, so two slots would be enough, but 8 gives slack for any one-off scheduler hiccup.
| enum ipc_demo_payload_t : uint32_t |
32-bit ASCII payload tags exchanged across the queue.
Each queue slot holds a single ULONG (32-bit). Using printable ASCII tags keeps the protocol observable from a debugger memory window: "ping" shows up as 0x67_6E_69_70 in little-endian.
| Enumerator | |
|---|---|
| k_ipc_demo_payload_ping | "ping" little-endian. |
| k_ipc_demo_payload_pong | "pong" little-endian. |
|
static |
Consumer thread body – blocking receive + log.
Sits in tx_queue_receive with TX_WAIT_FOREVER. When the producer enqueues a token the consumer unblocks, validates the payload is the expected "ping" magic, logs the synthetic <- pong reply (the demo loops back locally; no second core is involved), and bumps g_ipc_demo_tick for the J-Link memprobe.
Using TX_WAIT_FOREVER rather than TX_NO_WAIT is the key difference from the broken pre-fix path: TX_NO_WAIT would return TX_QUEUE_EMPTY on every miss and force a busy-poll loop with no scheduler yield, which was the second classic ThreadX queue bug.
| [in] | thread_input | Unused ThreadX cookie. |
Definition at line 306 of file main.c.
References g_ipc_demo_tick, ipc_demo_log(), k_ipc_demo_payload_ping, k_ipc_demo_recv_msg, s_ipc_queue, TX_SUCCESS, and TX_WAIT_FOREVER.
Referenced by tx_application_define().
|
static |
Write a static ASCII string to SCI8.
| [in] | s | NUL-terminated source buffer (caller-owned, static). |
| [in] | len | Length in bytes excluding the NUL terminator. |
Definition at line 167 of file main.c.
References ra8_board_uart_console_write().
Referenced by ipc_consumer_thread_entry(), and ipc_producer_thread_entry().
|
static |
Halt forever in WFI on a fatal init failure.
Definition at line 147 of file main.c.
Referenced by ipc_demo_setup_or_halt(), main(), and tx_application_define().
|
static |
Bring CGC + SCI8 up.
Panic-halts on any failure.
Order matters: ra8_cgc_init MUST run before the kernel enters its scheduler tick, otherwise SysTick (programmed by _tx_initialize_low_level against RA8_BOOT_CLOCK_HZ = 1e9) ticks at the wrong rate and tx_thread_sleep becomes ~119x slower than expected. Without that fix the consumer thread's -> ping log lines would appear every ~2 minutes instead of every 1 s, and the HIL UART scrape would time out.
Definition at line 195 of file main.c.
References ipc_demo_panic_halt(), k_ipc_demo_baud, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), and ra8_time_init().
Referenced by main().
|
static |
Producer thread body – 1 Hz "ping" enqueue.
Each iteration writes the "ping" token into the shared TX_QUEUE with TX_WAIT_FOREVER. The queue capacity (8) far exceeds the single message in flight at any time, so the call returns TX_SUCCESS immediately. Logs -> ping to SCI8 so the UART scrape can observe the producer side, then sleeps one period.
| [in] | thread_input | Unused ThreadX cookie. |
Definition at line 262 of file main.c.
References ipc_demo_log(), k_ipc_demo_banner, k_ipc_demo_payload_ping, k_ipc_demo_period_ticks, k_ipc_demo_send_msg, s_ipc_queue, TX_SUCCESS, tx_thread_sleep, and TX_WAIT_FOREVER.
Referenced by tx_application_define().
| void main | ( | void | ) |
Application entry.
The application entry point Reset_Handler hands control to.
Brings up CGC + SCI8 then drops into the ThreadX scheduler.
Definition at line 405 of file main.c.
References ipc_demo_panic_halt(), ipc_demo_setup_or_halt(), and ra8_isr_globals_enable().
| void tx_application_define | ( | void * | first_unused_memory | ) |
ThreadX application init callback.
| [in] | first_unused_memory | Pointer to first free byte after kernel internal allocations. Unused (static stacks). |
Definition at line 337 of file main.c.
References ipc_consumer_thread_entry(), ipc_demo_panic_halt(), ipc_producer_thread_entry(), k_ipc_demo_consumer_prio, k_ipc_demo_producer_prio, k_ipc_demo_thread_stack, s_consumer_stack, s_consumer_thread, s_ipc_queue, s_ipc_queue_storage, s_producer_stack, s_producer_thread, TX_AUTO_START, TX_NO_TIME_SLICE, TX_SUCCESS, and tx_thread_create.
| volatile uint32_t g_ipc_demo_tick = 0U |
HIL liveness counter – incremented per consumer wakeup.
Bumped by ipc_consumer_thread on every successful tx_queue_receive. Read externally by scripts/hil/jlink_memprobe.sh to gate the demo independent of UART scraping.
Definition at line 133 of file main.c.
Referenced by ipc_consumer_thread_entry().
|
static |
Static log lines streamed over SCI8 (must remain ASCII).
Definition at line 117 of file main.c.
Referenced by ipc_producer_thread_entry().
|
static |
Definition at line 119 of file main.c.
Referenced by ipc_consumer_thread_entry().
|
static |
Definition at line 118 of file main.c.
Referenced by ipc_producer_thread_entry().
|
static |
Definition at line 241 of file main.c.
Referenced by tx_application_define().
|
static |
ThreadX control block + stack for the consumer thread.
Definition at line 240 of file main.c.
Referenced by tx_application_define().
|
static |
ThreadX queue control block + backing storage.
tx_queue_create takes the message size in 32-bit ULONGs (TX_1_ULONG == 1) and the queue size in BYTES of backing storage (sizeof(s_ipc_queue_storage) == capacity * sizeof(ULONG)). Mixing those two units is the canonical ThreadX queue bug – using bytes for message_size causes tx_queue_create to silently slice the buffer wrong and tx_queue_send returns TX_QUEUE_ERROR / TX_PTR_ERROR.
Definition at line 232 of file main.c.
Referenced by ipc_consumer_thread_entry(), ipc_producer_thread_entry(), and tx_application_define().
|
static |
Definition at line 233 of file main.c.
Referenced by tx_application_define().
|
static |
Definition at line 237 of file main.c.
Referenced by tx_application_define().
|
static |
ThreadX control block + stack for the producer thread.
Definition at line 236 of file main.c.
Referenced by tx_application_define().