W5300 + I2S Audio Streaming Architecture Improvement
For Embedded Developers Working on Real-Time Audio over Ethernet

🔍 Original Architecture: Command-Driven Direct I2S Transmission
In the initial system, audio data sent from a PC is received by the W5300 Ethernet controller. The MCU then immediately forwards the data to the I2S peripheral via i2sWrite()
. This approach tightly couples reception and playback.
✅ Pros:
Simple and easy to implement
Minimal latency in ideal conditions
❌ Cons:
Tightly coupled timing: audio data must be written exactly when I2S is ready
Risk of underrun or data loss, especially if transmission is delayed
Compressed audio codecs like OPUS or ADPCM introduce decoding latency → causes playback instability
🔄 Improved Architecture: Asynchronous Audio Queue Buffer
To solve timing issues, the system introduces an intermediate 8KB audio buffer, located inside the cmdAudio
module. This buffer decouples network reception from I2S output.
Key Components:
Socket buffer (W5300): 8KB
Audio queue buffer (cmdAudio): 8KB
I2S ring buffer: 4KB
🧠 Why It Works
Removes the dependency between command timing and I2S availability
Supports buffered playback for compressed codecs
Allows for background processing, such as FFT or sample conversion
Enables flexible streaming with minimal jitter
🧩 Code Overview: Key Functions
1. cmdThreadUpdate()
— Core processing loop
bool cmdThreadUpdate(void)
{
for (int i = 0; i < CMD_DRIVER_MAX_CH; i++) {
if (cmd[i].is_init == true) {
if (cmdReceivePacket(&cmd[i]) == true) {
ret |= cmdAudioProcess(&cmd[i]);
}
cmdAudioUpdate(&cmd[i]); // Runs continuously in background
}
}
}
2. cmdAudioReady()
— Returns available space in buffer
static void cmdAudioReady(cmd_t *p_cmd)
{
data.u32D = (AUDIO_Q_BUF_LEN - qbufferAvailable(&audio_q)) - 1;
data.u32D = data.u32D - (data.u32D % 2);
}
3. cmdAudioWrite()
— Writes to audio buffer only
static void cmdAudioWrite(cmd_t *p_cmd, bool resp)
{
memcpy(&file_index, &p_cmd->packet.data[0], 4);
length = (p_cmd->packet.length - 4) / 2;
qbufferWrite(&audio_q, (uint8_t *)p_buf, length);
}
4. cmdAudioUpdate()
— Sends data to I2S when ready
if (state == STATE_BEGIN)
{
q_Len = qbufferAvailable(&audio_q);
length = cmin(q_Len, p_type->availableForWrite(p_type->ch));
if (length > 0) {
qbufferRead(&audio_q, (uint8_t *)p_buf, length);
p_type->write(p_type->ch, (int16_t *)p_buf, length);
}
}
5. cmdAudioInit()
— Abstracting I2S/SAI using function pointers
audio_type[AUDIO_TYPE_I2S].write = i2sWrite;
audio_type[AUDIO_TYPE_SAI].write = saiWrite;
🎯 Where Can This Architecture Be Applied?
MCU | Interface | Highlights |
---|---|---|
STM32 Series | I2S / SAI | Hardware audio blocks, DMA-friendly |
NXP i.MX RT | I2S / SAI | High-performance RTOS streaming |
RP2040 / RP2350 | PIO I2S | Software I2S via PIO + DMA (low-cost, flexible) |
ESP32 | I2S | Integrated I2S with Wi-Fi capability |
💡 Why This Matters
This buffered streaming structure enables:
✅ Codec-ready architecture (e.g., OPUS, ADPCM)
✅ Decoupled design for robust audio playback
✅ Multi-platform MCU support
✅ Real-time DSP/FFT possibilities in background
🚀 Even Better with W6300: A Modern, SPI-Based Alternative
While the W5300 delivers excellent performance, it relies on a parallel bus, which requires many MCU GPIOs and introduces routing complexity. An alternative is WIZnet’s W6300, which uses QSPI (Quad SPI) for high-speed Ethernet.
W6300 Advantages:
Feature | W5300 (Parallel) | W6300 (QSPI) |
---|---|---|
Interface type | parallel bus | QSPI (4-wire QSPI) |
MCU compatibility | GPIO-heavy, timing-sensitive | QSPI |
Max throughput | ~80Mbps | ~91 Mbps @ Quad QSPI |
PCB design | Complex | Simple, compact |
Peripheral SPI possibility | Limited | Supports basic SPI using Single QSPI mode(2-wire) |
RP2040 & RP2350 integration | Possible | Possible |
If you're redesigning your audio streaming system — especially on a compact or resource-constrained board — W6300 is a modern, viable replacement for W5300.