Project Description

WIZnet W5500 supports up to 80MHz SPI Clock so users with an MCU that provide a high-speed SPI communication can enjoy maximum ethernet throughput. In this post, I will show how STM32 MCU can achieve the best throughput with W5500.

When using Cortex M3/M4 line’s 32bit processors from STMicro, the ethernet throughput greatly varies upon which SPI communication mode is used. I will compare the difference of throughput between using SPI standard mode and using SPI DMA mode.

Consist of

MCU board : Nucleo STM32F401RE

Ethernet controller : WIZnet WIZ550io(W5500 inside)

Pin connection
The pin connection between the MCU board and WIZnet WIZ550io is shown in the table below.
First, connect the Power line.

Second, connect SPI signals. But, connect SCS pin to GPIOA_Pin12 because I’m going to handle it in Software method.

Third, connect RSTn pin to GPIOA_Pin11 to reset WIZ550io.

Finally, connect RDY pin that signals WIZ550io initialization is complete to GPIOA_Pin1 .

It is not crucial that RSTn pin and RDY pin be connected but it’s best for stability.




How to implement SPI protocol 

SPI protocol to control W5500 is the same in both SPI Standard mode and SPI DMA mode. However, the difference between two modes is whether there is idle time between data on SPI bus.

SPI protocol for W5500 is provided in W5500.c of WIZnet ioLibrary and has the below four functions.

  • WIZCHIP_READ(uint32_t AddrSel)
  • WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb)
  • WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
  • WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)

When SPI DMA mode is not used, the inside of the function calls standard SPI read/write function like the below WIZCHIP_READ_BUF() function.

#if !defined (SPI_DMA)
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
for(i = 0; i < len; i++) pBuf[i] = WIZCHIP.IF.SPI._read_byte();

When SPI DMA mode is used, it prepares commands data, which consists of address and opcode, and  calls SPI_DMA_READ() function.

spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
SPI_DMA_READ(spi_data, pBuf, len);

As explained on “How to implement the full duplex communication using the SPI DMA in STM32F2xx or STM32F4xx“, SPI_DMA_READ() and SPI_DMA_WRITE() are composed of the code to use SPI DMA mode.

Performance Comparison between Standard SPI mode & SPI DMA mode 

The source code in the related data below is a sample code for loopback testing. It shows how much difference exists in performance between Standard SPI mode and SPI DMA mode.

Standard SPI mode

In spi_handler.h
#ifndef SPI_DMA
//#define SPI_DMA

If you make “#define SPI_DMA” line as comment and compile it, then it will operate in standard SPI mode.

If you download the binary file which you got after compilation onto a Nucleo board and do loopback test with AX1.exe which WIZnet provides, then the transmission and reception will each achieve 1.6Mbps like the image below and we can know that the SPI full throughput is up to 3.2Mbps.


Here, SPI clock is 24MHz and you can clearly see the idle time between SPI data.


SPI DMA mode

#ifndef SPI_DMA
#define SPI_DMA

Like above, make “#define SPI_DMA” line enabled from comment and compile it.

Next, if you download the binary file onto Nucleo, then you can see the throughput of SPI DMA mode. The loopback test performance of transmission and reception is each 4.3Mbps and SPI full throughput is over 8Mbps. If you use your own board that has a high speed external clock instead of Nucleo board, then you can get much faster throughput.

Here, you can see SPI communicate happen continuously without any idle time like the image below.



written by James YS Kim