help regarding burst mode

Hello Wiznet community!

I’m currently working on a project that involves SPI communication with the W5500 Ethernet controller on the Nucleo 446RE development board using Mbed OS. I would like to implement burst mode for improved performance, but I’m facing some challenges. I was hoping someone could provide some guidance or insights on this matter.

Here are the details of my setup:

  1. Development board: Nucleo 446RE
  2. Ethernet controller: W5500
  3. Software framework: Mbed OS (version 5.15)
  4. SPI communication interface

I have successfully established basic SPI communication with the W5500 using Mbed OS, but I want to leverage the burst mode feature to enhance the overall performance of my application. However, I’m not quite sure how to implement burst mode correctly.

Specifically, I have the following questions:

  1. How do I enable burst mode for SPI communication with the W5500 on the Nucleo 446RE board using Mbed OS?
  2. Are there any specific configurations or settings that I need to consider when using burst mode?
  3. What are the advantages and potential limitations of using burst mode with the W5500?

I would greatly appreciate any assistance or guidance on this topic. If anyone has successfully implemented burst mode with the W5500 on an STM32 board using Mbed OS, I would love to hear about your experiences and any recommendations you might have.

Thank you in advance for your support!

Best regards, Rohan

Hi, @dadahar

W5500 default operation is burst mode. You do not need to consider to use it. Just you can read or write any size of buffer to load SPI communication. Address will be automatically increased to next address.

1 Like

hi @lawrence ,

Thanks for the reply, i see that the default mode is in burst mode. I still have one question when i observe the data via a data analyzer i can see a delay of 2.5 us before each byte of transmission, can you assist me why is that happening? i have attached


the screenshot of the graph below.

Thank you

hi @dadahar

This is normal SPI master performance. SPI master controlled by MCU, normally MCU processor controls SPI master with delay (delay term is depending on mcu). If you do not want the delay, you need to use DMA. In DMA mode, you can remove the delay or control it.
It is not exactly the same condition, but could be helpful.

Hi @lawrence ,

This is helpful thanks, I am developing for nucleo 446re using mbed studio so can you help me how can i enable dma mode for spi for my setup and hardware. i have attached my code which i tried for dma mode can you look through it if that helps. Thanks a lot

code -
#include “mbed.h”
#include “w5500_spi.h”
#include “socket.h”
#include “header”

#define WIZCHIP W5500
#define WIZCHIP_IO_MODE WIZCHIP_IO_MODE_SPI_VDM
#define WAIT_TIME 1000 // msec
#define BUFFERLENGTH 12000
#define SOCKET_N 1

DigitalOut led1(LED1);
SPI spi1(D11, D12, D13);
DigitalOut cs(D10);
DigitalOut rst(D4);
DigitalOut toggle(D14);

wiz_NetInfo net_info = {
.mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef},
.ip = {192, 168, 1, 15},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_STATIC
};

wiz_PhyConf phyConf = {
.by = PHY_CONFBY_SW,
.mode = PHY_MODE_MANUAL,
.speed = PHY_SPEED_100,
.duplex = PHY_DUPLEX_FULL,
};

char buf[BUFFERLENGTH] = {0};

// DMA Configurations
#define DMA_CHANNEL_RX 2 // Define the DMA channel for SPI RX
#define DMA_CHANNEL_TX 3 // Define the DMA channel for SPI TX
#define DMA_TX_FLAG DMA_FLAG_TC_2 // Define the DMA TX flag
#define DMA_RX_FLAG DMA_FLAG_TC_3 // Define the DMA RX flag

DMA_HandleTypeDef hdma_rx;
DMA_HandleTypeDef hdma_tx;

void spiReadBurst(uint8_t* pBuf, uint16_t len) {
hdma_tx.Instance = DMA_INSTANCE_SPI_TX; // Set the DMA instance for SPI TX
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_tx.Init.Mode = DMA_NORMAL;
hdma_tx.Init.Priority = DMA_PRIORITY_HIGH;

hdma_rx.Instance = ...; // Set the DMA instance for SPI RX
hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.Mode = DMA_NORMAL;
hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;

HAL_DMA_Init(&hdma_tx);
HAL_DMA_Init(&hdma_rx);

/* Enable SPI Rx/Tx DMA Request */
__HAL_SPI_ENABLE_DMA(&spi1, SPI_DMA_TX);
__HAL_SPI_ENABLE_DMA(&spi1, SPI_DMA_RX);

/* Configure the DMA TX channel */
HAL_DMA_Start(&hdma_tx, (uint32_t)pBuf, (uint32_t)&spi1.Instance->DR, len);

/* Configure the DMA RX channel */
HAL_DMA_Start(&hdma_rx, (uint32_t)&spi1.Instance->DR, (uint32_t)pBuf, len);

/* Wait for the end of Data Transfer */
HAL_DMA_PollForTransfer(&hdma_tx, HAL_DMA_FULL_TRANSFER, 1000);
HAL_DMA_PollForTransfer(&hdma_rx, HAL_DMA_FULL_TRANSFER, 1000);

/* Disable SPI Rx/Tx DMA Request */
__HAL_SPI_DISABLE_DMA(&spi1, SPI_DMA_TX);
__HAL_SPI_DISABLE_DMA(&spi1, SPI_DMA_RX);

/* Clear the DMA transfer complete flags */
__HAL_DMA_CLEAR_FLAG(&hdma_tx, DMA_TX_FLAG);
__HAL_DMA_CLEAR_FLAG(&hdma_rx, DMA_RX_FLAG);

HAL_DMA_DeInit(&hdma_tx);
HAL_DMA_DeInit(&hdma_rx);

}

int main() {
spi1.format(8, 0);
spi1.frequency(33000000);

w5500Init(&spi1, &cs, &rst);
printf("W5500 initialized\n\r");

int8_t err;

if (ctlwizchip(CW_SET_PHYCONF, (void*) &phyConf) == -1) {
    printf("Failed to set phyconf\n\r");
    return -1;
}
printf("PHY configuration set\n\r");

if (ctlnetwork(CN_SET_NETINFO, (void*) &net_info) == -1) {
    printf("Failed to set netinfo\n\r");
    return -1;
}
printf("Network info set\n\r");

wiz_PhyConf currentStatus;
ctlwizchip(CW_GET_PHYSTATUS, (void*) &currentStatus);
printf("Speed is %d Mb/s. ", currentStatus.speed == PHY_SPEED_100 ? 100 : 10);
printf("%s.\n\r", currentStatus.duplex == PHY_DUPLEX_FULL ? "Full Duplex" : "Half Duplex");

err = socket(SOCKET_N, Sn_MR_TCP, 1234, SF_TCP_NODELAY);
if (err != SOCK_OK) {
    printf("Failed to open socket. Error %d\n\r", err);
    return -1;
}
printf("Socket opened\n\r");

err = listen(SOCKET_N);
if (err != SOCK_OK) {
    printf("Failed to listen/accept socket. Error %d\n\r", err);
    return -1;
}
printf("Listening for connection...\n\r");

uint8_t sock_state = 0;
while (sock_state != SOCK_ESTABLISHED) {
    getsockopt(SOCKET_N, SO_STATUS, (void*) &sock_state);
    printf("Sock State is: %d\n\r", sock_state);
    thread_sleep_for(WAIT_TIME);
}
printf("Connection established\n\r");

Timer t;

while (true) {
    for (int i = 0; i < BUFFERLENGTH-1; i++) {
        buf[i] = 'A' + (i % 26);
    }
    buf[BUFFERLENGTH-1] = '\0';

    t.reset();
    t.start();

    toggle.write(1);
    spiReadBurst((uint8_t*) buf, strlen(buf));
    toggle.write(0);

    t.stop();
    float elapsed_time = t.read();

    int num_bytes_transmitted = strlen(buf);
    float transfer_speed = (num_bytes_transmitted / elapsed_time) * 8 / 1000000.0f;

    printf("Sent %d bytes in %.6f seconds, transfer speed: %.8f Mbps\n", num_bytes_transmitted, elapsed_time, transfer_speed);

    memset(buf, 0, BUFFERLENGTH);
    printf("Buffer cleared\n\r");

    led1 = !led1;
    printf("LED toggled\n\r");

    thread_sleep_for(1000);
}

}