Viktor Shin
Published

Using Socket-less functions with RP2040 and W5100S

This project will demonstrate how to use W5100S socket-less commands.

IntermediateProtip2 hours478
Using Socket-less functions with RP2040 and W5100S

Things used in this project

Hardware components

W5100S-EVB-Pico
WIZnet W5100S-EVB-Pico
×1

Software apps and online services

WIZnet RP2040-HAT-C

Story

Read more

Schematics

W5100S-EVB-Pico

Code

w5100s_arp_ping.c

C/C++
Main file with test code
/**
 * Copyright (c) 2021 WIZnet Co.,Ltd
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/**
  * ----------------------------------------------------------------------------------------------------
  * Includes
  * ----------------------------------------------------------------------------------------------------
  */
#include <stdio.h>

#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "pico/critical_section.h"
#include "hardware/spi.h"
#include "hardware/dma.h"

#include "wizchip_conf.h"

/**
  * ----------------------------------------------------------------------------------------------------
  * Macros
  * ----------------------------------------------------------------------------------------------------
  */
/* SPI */
#define SPI_PORT spi0

#define PIN_SCK 18
#define PIN_MOSI 19
#define PIN_MISO 16
#define PIN_CS 17
#define PIN_RST 20

/* Buffer */
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

/* Socket */
#define SOCKET_LOOPBACK 0

/* Port */
#define PORT_LOOPBACK 5000

/* Use SPI DMA */
//#define USE_SPI_DMA // if you want to use SPI DMA, uncomment.

/**
  * ----------------------------------------------------------------------------------------------------
  * Variables
  * ----------------------------------------------------------------------------------------------------
  */
/* Critical section */
static critical_section_t g_wizchip_cri_sec;

/* Network */
static wiz_NetInfo g_net_info =
    {
        .mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, // MAC address
        .ip = {192, 168, 0, 20},                     // IP address
        .sn = {255, 255, 255, 0},                    // Subnet Mask
        .gw = {192, 168, 0, 1},                     // Gateway
        .dns = {8, 8, 8, 8},                         // DNS server
        .dhcp = NETINFO_STATIC                       // DHCP enable/disable
};

/* Loopback */
static uint8_t g_loopback_buf[ETHERNET_BUF_MAX_SIZE] = {
    0,
};

#ifdef USE_SPI_DMA
static uint dma_tx;
static uint dma_rx;
static dma_channel_config dma_channel_config_tx;
static dma_channel_config dma_channel_config_rx;
#endif

/**
  * ----------------------------------------------------------------------------------------------------
  * Functions
  * ----------------------------------------------------------------------------------------------------
  */
/* W5x00 */
static inline void wizchip_select(void);
static inline void wizchip_deselect(void);
static void wizchip_reset(void);
static uint8_t wizchip_read(void);
static void wizchip_write(uint8_t tx_data);
#ifdef USE_SPI_DMA
static void wizchip_read_burst(uint8_t *pBuf, uint16_t len);
static void wizchip_write_burst(uint8_t *pBuf, uint16_t len);
#endif
static void wizchip_critical_section_lock(void);
static void wizchip_critical_section_unlock(void);
static void wizchip_initialize(void);
static void wizchip_check(void);

/* Network */
static void network_initialize(void);
static void print_network_information(void);

/**
  * ----------------------------------------------------------------------------------------------------
  * Main
  * ----------------------------------------------------------------------------------------------------
  */
int main()
{
    /* Initialize */

    uint8_t addr0[6];
    uint8_t dest_ip[4]={192,168,0,4};

    stdio_init_all();

    // this example will use SPI0 at 5MHz
    spi_init(SPI_PORT, 5000 * 1000);

    critical_section_init(&g_wizchip_cri_sec);

    gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);

    // make the SPI pins available to picotool
    bi_decl(bi_3pins_with_func(PIN_MISO, PIN_MOSI, PIN_SCK, GPIO_FUNC_SPI));

    // chip select is active-low, so we'll initialise it to a driven-high state
    gpio_init(PIN_CS);
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_CS, 1);

    // make the SPI pins available to picotool
    bi_decl(bi_1pin_with_name(PIN_CS, "W5x00 CHIP SELECT"));

#ifdef USE_SPI_DMA
    dma_tx = dma_claim_unused_channel(true);
    dma_rx = dma_claim_unused_channel(true);

    dma_channel_config_tx = dma_channel_get_default_config(dma_tx);
    channel_config_set_transfer_data_size(&dma_channel_config_tx, DMA_SIZE_8);
    channel_config_set_dreq(&dma_channel_config_tx, DREQ_SPI0_TX);

    // We set the inbound DMA to transfer from the SPI receive FIFO to a memory buffer paced by the SPI RX FIFO DREQ
    // We coinfigure the read address to remain unchanged for each element, but the write
    // address to increment (so data is written throughout the buffer)
    dma_channel_config_rx = dma_channel_get_default_config(dma_rx);
    channel_config_set_transfer_data_size(&dma_channel_config_rx, DMA_SIZE_8);
    channel_config_set_dreq(&dma_channel_config_rx, DREQ_SPI0_RX);
    channel_config_set_read_increment(&dma_channel_config_rx, false);
    channel_config_set_write_increment(&dma_channel_config_rx, true);
#endif

    wizchip_reset();
    wizchip_initialize();
    wizchip_check();

    network_initialize();

    /* Get network information */
    print_network_information();

    /* Infinite loop */
    while(dest_ip[3]<11)
    {
      
     printf("Send ARP to : %d.%d.%d.%d\n", dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]);    
     int8_t arp_ret=arp_auto(dest_ip);
     if(arp_ret==1)
       { 
        printf("ARP : successful\r\n");
        get_arp_MacAddress(addr0);
        printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\r\n",addr0[0],addr0[1],addr0[2],addr0[3],addr0[4],addr0[5],addr0[6]);
      }
       else printf("ARP : failure\r\n", arp_ret);
    
    printf("Sending PING to : %d.%d.%d.%d\n", dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]);   
    
    int8_t ping_ret=ping_auto(0, dest_ip);

    printf("Ping statistics for %d.%d.%d.%d:\n", dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]);
	printf("    Sent = 4, Received = %d, Lost = %d (%d%% of loss)\r\n", ping_ret, 4 - ping_ret, (1 - ping_ret/4) * 100);

    dest_ip[3] = dest_ip[3] +1;
    printf("--------------------------------------------------\n\n");
    } 
    
}

/**
  * ----------------------------------------------------------------------------------------------------
  * Functions
  * ----------------------------------------------------------------------------------------------------
  */
/* W5x00 */
static inline void wizchip_select(void)
{
    gpio_put(PIN_CS, 0);
}

static inline void wizchip_deselect(void)
{
    gpio_put(PIN_CS, 1);
}

static void wizchip_reset(void)
{
    gpio_set_dir(PIN_RST, GPIO_OUT);

    gpio_put(PIN_RST, 0);
    sleep_ms(100);

    gpio_put(PIN_RST, 1);
    sleep_ms(100);

    bi_decl(bi_1pin_with_name(PIN_RST, "W5x00 RESET"));
}

static uint8_t wizchip_read(void)
{
    uint8_t rx_data = 0;
    uint8_t tx_data = 0xFF;

    spi_read_blocking(SPI_PORT, tx_data, &rx_data, 1);

    return rx_data;
}

static void wizchip_write(uint8_t tx_data)
{
    spi_write_blocking(SPI_PORT, &tx_data, 1);
}

#ifdef USE_SPI_DMA
static void wizchip_read_burst(uint8_t *pBuf, uint16_t len)
{
    uint8_t dummy_data = 0xFF;

    channel_config_set_read_increment(&dma_channel_config_tx, false);
    channel_config_set_write_increment(&dma_channel_config_tx, false);
    dma_channel_configure(dma_tx, &dma_channel_config_tx,
                          &spi_get_hw(SPI_PORT)->dr, // write address
                          &dummy_data,               // read address
                          len,                       // element count (each element is of size transfer_data_size)
                          false);                    // don't start yet

    channel_config_set_read_increment(&dma_channel_config_rx, false);
    channel_config_set_write_increment(&dma_channel_config_rx, true);
    dma_channel_configure(dma_rx, &dma_channel_config_rx,
                          pBuf,                      // write address
                          &spi_get_hw(SPI_PORT)->dr, // read address
                          len,                       // element count (each element is of size transfer_data_size)
                          false);                    // don't start yet

    dma_start_channel_mask((1u << dma_tx) | (1u << dma_rx));
    dma_channel_wait_for_finish_blocking(dma_rx);
}

static void wizchip_write_burst(uint8_t *pBuf, uint16_t len)
{
    uint8_t dummy_data;

    channel_config_set_read_increment(&dma_channel_config_tx, true);
    channel_config_set_write_increment(&dma_channel_config_tx, false);
    dma_channel_configure(dma_tx, &dma_channel_config_tx,
                          &spi_get_hw(SPI_PORT)->dr, // write address
                          pBuf,                      // read address
                          len,                       // element count (each element is of size transfer_data_size)
                          false);                    // don't start yet

    channel_config_set_read_increment(&dma_channel_config_rx, false);
    channel_config_set_write_increment(&dma_channel_config_rx, false);
    dma_channel_configure(dma_rx, &dma_channel_config_rx,
                          &dummy_data,               // write address
                          &spi_get_hw(SPI_PORT)->dr, // read address
                          len,                       // element count (each element is of size transfer_data_size)
                          false);                    // don't start yet

    dma_start_channel_mask((1u << dma_tx) | (1u << dma_rx));
    dma_channel_wait_for_finish_blocking(dma_rx);
}
#endif

static void wizchip_critical_section_lock(void)
{
    critical_section_enter_blocking(&g_wizchip_cri_sec);
}

static void wizchip_critical_section_unlock(void)
{
    critical_section_exit(&g_wizchip_cri_sec);
}

static void wizchip_initialize(void)
{
    /* Deselect the FLASH : chip select high */
    wizchip_deselect();

    /* CS function register */
    reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);

    /* SPI function register */
    reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);
#ifdef USE_SPI_DMA
    reg_wizchip_spiburst_cbfunc(wizchip_read_burst, wizchip_write_burst);
#endif
    reg_wizchip_cris_cbfunc(wizchip_critical_section_lock, wizchip_critical_section_unlock);

    /* W5x00 initialize */
    uint8_t temp;
    uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};

    if (ctlwizchip(CW_INIT_WIZCHIP, (void *)memsize) == -1)
    {
        printf(" W5x00 initialized fail\n");

        return;
    }

    /* Check PHY link status */
    do
    {
        if (ctlwizchip(CW_GET_PHYLINK, (void *)&temp) == -1)
        {
            printf(" Unknown PHY link status\n");

            return;
        }
    } while (temp == PHY_LINK_OFF);
}

static void wizchip_check(void)
{
    /* Read version register */
    if (getVER() != 0x51) // W5100S
    {
        printf(" ACCESS ERR : VERSIONR != 0x51, read value = 0x%02x\n", getVER());

        while (1)
            ;
    }
}

/* Network */
static void network_initialize(void)
{
    ctlnetwork(CN_SET_NETINFO, (void *)&g_net_info);
}

static void print_network_information(void)
{
    uint8_t tmp_str[8] = {
        0,
    };

    ctlnetwork(CN_GET_NETINFO, (void *)&g_net_info);
    ctlwizchip(CW_GET_ID, (void *)tmp_str);

    if (g_net_info.dhcp == NETINFO_DHCP)
    {
        printf("====================================================================================================\n");
        printf(" %s network configuration : DHCP\n\n", (char *)tmp_str);
    }
    else
    {
        printf("====================================================================================================\n");
        printf(" %s network configuration : static\n\n", (char *)tmp_str);
    }

    printf(" MAC         : %02X:%02X:%02X:%02X:%02X:%02X\n", g_net_info.mac[0], g_net_info.mac[1], g_net_info.mac[2], g_net_info.mac[3], g_net_info.mac[4], g_net_info.mac[5]);
    printf(" IP          : %d.%d.%d.%d\n", g_net_info.ip[0], g_net_info.ip[1], g_net_info.ip[2], g_net_info.ip[3]);
    printf(" Subnet Mask : %d.%d.%d.%d\n", g_net_info.sn[0], g_net_info.sn[1], g_net_info.sn[2], g_net_info.sn[3]);
    printf(" Gateway     : %d.%d.%d.%d\n", g_net_info.gw[0], g_net_info.gw[1], g_net_info.gw[2], g_net_info.gw[3]);
    printf(" DNS         : %d.%d.%d.%d\n", g_net_info.dns[0], g_net_info.dns[1], g_net_info.dns[2], g_net_info.dns[3]);
    printf("====================================================================================================\n\n");
}

arp_ping.c

C/C++
File containing functions to operate W5100S ARP and PING SLC.
#include "arp_ping.h"

/**
* ----------------------------------------------------------------------------------------------------
* ARP
* ----------------------------------------------------------------------------------------------------
*/

static uint16_t ArpRCR = 0x08;
static uint16_t ArpRTR = 0x07d0;

void configure_arp_request(void)
{
  	setSLIR(SLIR_TIMEOUT | SLIR_ARP);
  	setSLRCR(ArpRCR);
  	setSLRTR(ArpRTR);
}

uint8_t arp_auto(uint8_t *addr)
{
	uint8_t ret=0;
	configure_arp_request();
	send_arp_request(addr);
	while(1)
	{
		ret=recv_arp_reply();
		if(ret!=ARP_FAIL) break;
	}
	return ret;
}

uint8_t send_arp_request(uint8_t *addr)
{
	setSLPIPR(addr);
	setSLCR(SLCMD_ARP);
}

uint8_t recv_arp_reply()
{
	 if(getSLIR()&SLIR_ARP){
		 setSLIR(SLIR_ARP);
		 return ARP_SUCCESS;
	 }
	 else if(getSLIR()&SLIR_TIMEOUT){
		 setSLIR(SLIR_TIMEOUT);
		 return TIMEOUT_ERROR;
	 }
	 else return ARP_FAIL;

}// arp_reply

void get_arp_MacAddress(uint8_t* addr)
{
	getSLPHAR(addr);
}

/**
* ----------------------------------------------------------------------------------------------------
* PING
* ----------------------------------------------------------------------------------------------------
*/

static uint16_t RandomID = 0x1234; 
static uint16_t RandomSeqNum = 0x4321;
static uint16_t PingRCR = 0x08;
static uint16_t PingRTR = 0x07d0;

void configure_ping_request(void){

  	setSLIR(SLIR_TIMEOUT | SLIR_PING);
  	setSLRCR(PingRCR);
  	setSLRTR(PingRTR);
	setPINGSEQR(RandomID);
  	setPINGIDR(RandomSeqNum);  

} // ping request


uint8_t send_ping_request(uint8_t s, uint8_t *addr)
{
	setSLPIPR(addr);
	setSLCR(SLCMD_PING);
}

uint8_t recv_ping_reply(uint8_t s){

	 if(getSLIR()&SLIR_PING){
		 setSLIR(SLIR_PING);
		 return PING_SUCCESS;
	 }
	 else if(getSLIR()&SLIR_TIMEOUT){
		 setSLIR(SLIR_TIMEOUT);
		 return TIMEOUT_ERROR;
	 }
	 else return PING_FAIL;
}// ping_reply

uint8_t ping_auto(uint8_t s, uint8_t *addr)
{
	uint8_t i, ret, rep = 0;
	configure_ping_request();
	for(i = 0; i<=3; i++)
	{
		send_ping_request(s, addr);
		wiz_delay_ms(500);
		while(1)
		{
			ret=recv_ping_reply(s);
			if(ret==PING_SUCCESS) 
			{
				rep++;
				break;
			}
			else if(ret == TIMEOUT_ERROR) break;
		}
	}
	return rep;
}

arp_ping.h

C/C++
Header file for arp_ping
#include "wizchip_conf.h"

/**
* ----------------------------------------------------------------------------------------------------
* ARP
* ----------------------------------------------------------------------------------------------------
*/

#define ARP_SUCCESS 1
#define TIMEOUT_ERROR 2
#define ARP_FAIL 0

uint8_t arp_auto(uint8_t *addr);
void configure_arp_request(void);
uint8_t send_arp_request(uint8_t *addr);
uint8_t recv_arp_reply();
void get_arp_MacAddress(uint8_t* addr);

/**
* ----------------------------------------------------------------------------------------------------
* PING
* ----------------------------------------------------------------------------------------------------
*/

#define PING_SUCCESS 1
#define PING_FAIL 0

uint8_t ping_auto(uint8_t s, uint8_t *addr);
void configure_ping_request(void);
uint8_t send_ping_request(uint8_t s, uint8_t *addr);
uint8_t recv_ping_reply(uint8_t s);

Credits

Viktor Shin

Viktor Shin

9 projects • 6 followers
Business Development Manager at WIZnet

Comments