W5500 SPI DMA example


Does anyone ever managed to get W5500 communicating with MCU in DMA (SPI) mode?
Is there any non CooCox (which is dead) based example?

“How to use STM32 DMA & SPI for WIZnet” states this:

Register the function that you want to use as SPI in the callback function.
reg_wizchip_spi_cbfunc(spiReadByte, spiWriteByte);
reg_wizchip_spiburst_cbfunc(spiReadBurst, spiWriteBurst);

Do I have to register both functions? How can I register reg_wizchip_spi_cbfunc in DMA mode? It requires a byte to be returned by spiReadByte function. Does that mean I should have two sets of functions (for single byte r/w and DMA r/w)?

Yes you should implement both functions. Single read/write and multiple read/write.

You can find examples on the wizwiki.net web pages below. It’s for the W5100S but you can use it with small changes.


Hi bangbh.
Thanks for reply!

I have tried with one byte functions, but result is the same as without them.
As a test I’m trying to send a simple message to UDP port, by using sendto function in main cycle. For the first attempt it returns error -13 (SOCKERR_TIMEOUT) and for the every other it returns -12 (SOCKERR_IPINVALID).

Here is how I do set up my W5500 chip:

uint8_t rcvBuf[20], bufSize = {4, 4, 4, 4, 0, 0, 0, 0};
wiz_NetInfo netInfo = {
.mac = {0xA5, 0x08, 0xdc, 0xab, 0xcd, 0xef}, // Mac address
.ip = {192, 168, 0, 123}, // IP address
.sn = {255, 255, 255, 0}, // Subnet mask
.gw = {192, 168, 0, 1}, // Gateway address
.dns = {192, 168, 0, 1}, // DNS address

wiz_NetInfo netInfoRead = {0};

uint8_t Broadcast[4] = {192, 168, 0, 255};
uint8_t ControlIP[4] = {192, 168, 0, 1};
uint8_t DataIP[4] = {192, 168, 0, 1};

uint16_t ctrlport = 9000, dataport = 4000;
const uint8_t ctrlsocknum = 0;
const uint8_t datasocknum = 1;

I perform the hardware reset before configuring the chip by pulling down nRST pin on Wiz550:

void Wiz_Rst(void)
LL_GPIO_ResetOutputPin(SPI1_nRST_GPIO_Port, SPI1_nRST_Pin);
LL_mDelay(2); //500us minimum
LL_GPIO_SetOutputPin(SPI1_nRST_GPIO_Port, SPI1_nRST_Pin);
LL_mDelay(5); //1ms minimum

void WIZ_SetParam(void)
reg_wizchip_cs_cbfunc(SPI_Hard_nSS_On, SPI_Hard_nSS_Off); //SPI nSS line select/deselect
reg_wizchip_spi_cbfunc(SPI1_ReadBye, SPI1_WriteByte); //One byte read/write functions
reg_wizchip_spiburst_cbfunc( SPI1_DMA_Rx_Burst, SPI1_DMA_Tx_Burst); //SPI burst in DMA polling

uint8_t initresult = wizchip_init(bufSize, bufSize); //Setting buffer sizes

uint8_t USARTTxBuffer3[18];
sprintf((char*) USARTTxBuffer3, “\r\nwizchip_init = %.2d\r\n”, initresult);
StartUSARTTransfers((uint32_t)USARTTxBuffer3, sizeof(USARTTxBuffer3));

wizchip_setnetinfo(&netInfo); //Configure network parameters

uint8_t USARTTxBuffer4 = “\r\nwizchip_setnetinfo”;
StartUSARTTransfers((uint32_t)USARTTxBuffer4, sizeof(USARTTxBuffer4));
uint8_t MACbuf[26], IPBuf[23], SNBuf[23], GWBuf[23];
sprintf((char*) MACbuf, “\r\n MAC: %.2X.%.2X.%.2X.%.2X.%.2X.%.2X”, netInfoRead.mac[0],netInfoRead.mac[1],netInfoRead.mac[2],netInfoRead.mac[3],netInfoRead.mac[4],netInfoRead.mac[5]);
sprintf((char*) IPBuf, “\r\n IP: %03d.%03d.%03d.%03d”, netInfoRead.ip[0],netInfoRead.ip[1],netInfoRead.ip[2],netInfoRead.ip[3]);
sprintf((char*) SNBuf, “\r\n SN: %03d.%03d.%03d.%03d”, netInfoRead.sn[0],netInfoRead.sn[1],netInfoRead.sn[2],netInfoRead.sn[3]);
sprintf((char*) GWBuf, “\r\n GW: %03d.%03d.%03d.%03d”, netInfoRead.gw[0],netInfoRead.gw[1],netInfoRead.gw[2],netInfoRead.gw[3]);
StartUSARTTransfers((uint32_t)MACbuf, sizeof(MACbuf));
StartUSARTTransfers((uint32_t)IPBuf, sizeof(IPBuf));
StartUSARTTransfers((uint32_t)SNBuf, sizeof(SNBuf));
StartUSARTTransfers((uint32_t)GWBuf, sizeof(GWBuf));

Then I open sockets:

void setSockets(void)
int32_t retsckt0, retsckt1;

retsckt0 = socket(ctrlsocknum, Sn_MR_UDP, ctrlport, 0);

uint8_t charbuf0[28];
snprintf ((char*) charbuf0, sizeof(charbuf0), “\r\nOpening Control socket: %d”, retsckt0);
StartUSARTTransfers((uint32_t)charbuf0 , sizeof(charbuf0));

retsckt1 = socket(datasocknum, Sn_MR_UDP, dataport, 0);

uint8_t charbuf1[25];
snprintf ((char*) charbuf1, sizeof(charbuf1), “\r\nOpening Data socket: %d”, retsckt1);
StartUSARTTransfers((uint32_t)charbuf1 , sizeof(charbuf1));

//Enable interrupts for control socket
//wizchip_setinterruptmask(IK_SOCK_0); // = setSIMR(0x01);
//setSn_IMR(ctrlsocknum, Sn_IR_RECV | Sn_IR_SENDOK | Sn_IR_TIMEOUT);


In main cycle (part of it):

uint8_t charbuf1[22];
int retcode;
snprintf ((char*) charbuf1, 22, “%s\r\n”, “Riders on the storm”); //Test string
retcode = sendto(ctrlsocknum, (uint8_t*) charbuf1, sizeof(charbuf1), ControlIP, ctrlport);

uint8_t retbuf[23];
snprintf ((char*) retbuf, 23, “\r\nSocket %d return: %03d”, ctrlsocknum, retcode);
StartUSARTTransfers((uint32_t)retbuf , sizeof(retbuf));

  retcode = sendto(datasocknum, (uint8_t*) charbuf1, sizeof(charbuf1), DataIP, dataport);

uint8_t retbuf1[23];
snprintf ((char*) retbuf1, 23, “\r\nSocket %d return: %03d”, datasocknum, retcode);
StartUSARTTransfers((uint32_t)retbuf1, sizeof(retbuf1));

As far as I can see, the only place, where reg_wizchip_spi_cbfunc is used is function WIZCHIP_READ in W5500.c. Since reg_wizchip_spiburst_cbfunc is defined, WIZCHIP_READ will send three bytes in burst (DMA) mode and read one in regular way. Here is my one byte read function:

uint8_t SPI1_ReadByte(void)
while (!(LL_SPI_IsActiveFlag_TXE(SPI1)));
LL_SPI_TransmitData8(SPI1, 0xFF);
while (!(LL_SPI_IsActiveFlag_RXNE(SPI1)));
return LL_SPI_ReceiveData8(SPI1);

Initially I have modified WIZCHIP_READ function, so it will use burst function to read one byte as well (see my other post One byte transfer in burst mode - #2 by becky), but since this didn’t help, I thought that my modification is not correct. However, now I have tried to utilize both functions (rolled back to non-modified ioLibrary and added one byte read/write functions) and still facing the same issue as before, leads me to believe, that probably initialisation is not correct.

Summary: I can configure the networking and open the sockets, with socket numbers returned, but cannot send the data.
Will much appreciate if somebody will spot an error in my code.