Data mover: A53 side#
Please refer first to the description of the RPU code.
graph TB
subgraph R5ISR["R5: ISR_Control"]
r5update[JavaScope_update] --> r5ipi[Trigger IPI to A53]
end
subgraph ISR["APU ISR: APU_IPI_ISR"]
ipi([IPI from R5]) --> read[Invalidate cache\nread javascope_data_t]
read --> check{Client\nactive?}
check -- no --> drop([skip])
check -- yes --> enq[enqueue sample]
read --> pop[pop command]
pop -- command --> reply([Return command to R5])
pop -- empty --> nop([Return no-op to R5])
end
r5ipi --> ipi
enq --> jsQ[(js_queue)]
ctrlQ[(js_control_queue)] --> pop
subgraph TCP["TCP worker: javascope_stream_thread"]
jsQ --> batch[Collect full batch]
batch --> send([Pack & lwip_send])
tcpIn([TCP stream]) --> asm[Reassemble APU_to_RPU_t]
asm --> push[enqueue command]
push --> ctrlQ
end
Fig. 57 A53-side view of the data mover#
Current implementation on A53#
The A53 data mover has a streaming path from the R5 to the TCP socket and a control path from the TCP socket back to the R5.
The A53 implementation is split into a fast ISR path and a TCP worker path.
Streaming path#
APU_IPI_ISRis triggered by the IPI issued fromISR_Controlon the R5, so its sample handling runs synchronously with the R5 control ISR.APU_IPI_ISRinvalidates the cache lines forMEM_SHARED_START_OCM_BANK_3_JAVASCOPE, reads the currentjavascope_data_tsample, and appends it tojs_queueonly while a JavaScope client is connected.The ISR updates the local
javascope_data_statusmirror and only callsportYIELD_FROM_ISRwhen the queue depth reaches one full batch, i.e.JS_SAMPLES_PER_PACKETsamples.javascope_stream_threadonly starts building an Ethernet payload once at least one full batch is queued.The queued samples are packed into one
NetworkSendStructand sent with non-blockinglwip_send, so streaming does not depend on an immediate receive-side reply from the TCP client.Partial writes are tracked with
tx_pending_offsetand retried until the whole frame has been transmitted.
Control path#
javascope_stream_threadreads the JavaScope control connection with non-blockinglwip_recvand treats the incoming data as a TCP byte stream rather than as one message perrecvcall.Complete
APU_to_RPU_tmessages are reassembled from the byte stream, while trailing partial bytes are kept in a buffer for the nextlwip_recvcall.Reassembled control messages are queued in
js_control_queuefor the ISR-to-R5 path.APU_IPI_ISRforwards at most one command fromjs_control_queueto the R5 per ISR invocation.If no command is pending, the ISR returns an explicit no-op
{id = 0, value = 0.0f}so that the R5 does not accidentally process an old command again.If
js_control_queueis full, newly received control messages are dropped and logged viauz_printfinstead of blocking the TCP worker.
Connection and recovery behavior#
javascope_socket_manager_threadandjavascope_stream_threadenforce a single active JavaScope client at a time using atomic replace/release helpers aroundjs_connection_established.When a new client becomes active, both
js_queueandjs_control_queueare reset so that no stale samples or commands survive the reconnect.js_queueholdsJS_QUEUE_SIZE_ELEMENTS= 1,000,000 samples, which corresponds to 100 s of buffering at 10 kHz.If
js_queueoverflows, the ISR increments the dropped counter and requests a purge. The TCP worker then resets the queue, reports how many samples were dropped or purged, and resumes real-time streaming.If the TCP send buffer is full, the worker waits with
lwip_selectinstead of busy-spinning. If transmission makes no progress forJS_TX_STALL_TIMEOUT_TICKS, the socket is closed as stale.If
USE_A53_AS_ACCELERATOR_FOR_R5_ISRis enabled, the A53 also exchanges user data with the R5 via OCM banks 1 and 2, using cache invalidate and flush operations around those shared-memory accesses.