Part Number: J784S4XEVM
Other Parts Discussed in Thread: AM69, SYSCONFIG
# MCSPI FIFO transfer > 32 bytes: TXx_EMPTY does not re-assert (J784S4, controller mode)
Device: J784S4 (AM69), MCSPI5, MAIN-domain R5F, FreeRTOS, interrupt-driven.
TRM: SPRUJ52E, MCSPI chapter 12.1.5.
## Problem statement
We are implementing an interrupt-driven, full-duplex MCSPI transfer in controller
mode using the built-in FIFO, for transfers larger than one FIFO load (> 32 bytes
at 8-bit words). The FIFO is 64 bytes, split 32 TX / 32 RX. The intent: prime the
TX FIFO, then service TXx_EMPTY (§12.1.5.3.7.1.1) to refill TX and RXx_FULL
(§12.1.5.3.7.1.3) to drain RX in bursts until the transfer completes, using EOW
(§12.1.5.3.7.1.4) as the completion signal.
Transfers <= 32 bytes (one FIFO load) work correctly. Transfers > 32 bytes stall.
## Anomaly
For a 40-byte transfer, only one TXx_EMPTY interrupt is ever generated. After the
initial TX FIFO contents clock out, TXx_EMPTY does not re-assert, so the TX FIFO is
never refilled, the transfer stalls, and EOW never fires.
RXx_FULL re-asserts and is serviced correctly (observed 2x for a 32-byte-clocked
transfer). The asymmetry — RXx_FULL re-fires, TXx_EMPTY does not — is the core
anomaly. No TXx_UNDERFLOW is generated. CHSTAT[2] EOT is set with the transfer
incomplete.
## Configuration (verified by reading back the control registers)
Per §12.1.5.3.6 (FIFO buffer management) and §12.1.5.3.7 (interrupts):
- MCSPI_XFERLEVEL: AFL = 15, AEL = 15 (almost-full/almost-empty trip at 16 bytes).
WCNT was tested both = 0 (counter unused) and = transfer word count (40); no
difference in the TXx_EMPTY behavior.
- MCSPI_CHCONF_0 read back as 0x17027: FORCE=1 (manual CS asserted), FFEW=1 (TX FIFO
enabled), FFER=1 (RX FIFO enabled), TURBO=0, SBE=0, IS/DPE per full-duplex,
TRM=00 (transmit-and-receive), WL=0x7 (8-bit).
- MCSPI_CHCTRL_0[0] EN = 1 (channel enabled, confirmed still set after the stall).
- MCSPI_MODULCTRL: MS=0 (controller), SINGLE=1, PIN34=0, MOA=0, FDAA=0,
INITDLY=8 cycles.
- MCSPI_SYSCONFIG: AUTOIDLE=0, SIDLEMODE=NO_IDLE, CLOCKACTIVITY=BOTH, ENAWAKEUP=1.
- MCSPI_IRQENABLE: TX0_EMPTY, RX0_FULL, EOW enabled.
## ISR design (brief)
Single ISR per MCSPI instance. On entry it reads MCSPI_IRQSTATUS, then:
- If EOW: drain the RX tail and complete the transfer (single completion authority).
- Else:
- on TXx_EMPTY, write up to AEL+1 (16) words to MCSPI_TX (bounded by words
still owed); on first write, up to 32 words to fill the FIFO.
- on RXx_FULL, read AFL+1 (16) words from MCSPI_RX.
- Each serviced flag is written back to MCSPI_IRQSTATUS (write-1-to-clear) at the end of the ISR.
The transfer is started (§12.1.5.4.1.1.8.1) by asserting the channel and CS. This is when we
observe the first (and only) TX EMPTY interrupt.
## Results (40-byte transfer, 8-bit words, loopback, SPI clock 375 kHz)
Two priming strategies were tested, same result:
1. Prime 16 words, refill via TXx_EMPTY:
`tx_empty=1 rx_full=1 eow=0 rx=16 tx=16` — 16 bytes clock on the bus, then stall.
Post-stall CHSTAT = 0xD5: TXFFE=1 (TX FIFO empty), RXFFE=1 (RX FIFO empty),
TXS=1 (TX register empty), RXS=0 (no RX back-pressure), EOT=1, EN=1.
MCSPI_IRQSTATUS read back = 0x0 (no flags pending; the write-1-to-clear
succeeded and no new TXx_EMPTY is asserted).
2. Prime the full FIFO (32 words):
`tx_empty=1 rx_full=2 eow=0 rx=32 tx=32` — 32 bytes clock (the primed FIFO
contents), then stall. CHSTAT = 0x800D5 (same low byte 0xD5, WCNT high half = 8,
i.e. 40 - 32 = 8 words remaining, confirming WCNT decremented correctly).
TXx_EMPTY still fired only once; RXx_FULL fired twice and re-armed correctly.
In both cases the bytes that were placed in the TX FIFO are transmitted on the bus
correctly. The transfer stops exactly when the primed TX FIFO contents are
exhausted, with CHSTAT[2] EOT set, MCSPI_IRQSTATUS = 0, TX FIFO empty, and no
further TXx_EMPTY event.
## Question
In controller, full-duplex, single-channel, manual-CS (FORCE) FIFO mode with the
configuration above, why does MCSPI_IRQSTATUS TXx_EMPTY not re-assert after the TX
FIFO drains below AEL, given that the processor performed the AEL+1 writes required
by §12.1.5.3.7.1.1 to re-arm the event, while RXx_FULL re-asserts normally under the
symmetric AFL rule? Specifically: does CHSTAT[2] EOT being set on TX-FIFO-empty
suppress further TXx_EMPTY generation, and if so, what is the required sequence to
continue a > FIFO-load transfer without terminating at EOT?
On a similar vein, if the status EOT is indicated (presumably when the FIFO empties),
why isn't the EOT interrupt generated in this case?