add w5500 for xidatong-riscv64

This commit is contained in:
wgzAIIT 2022-10-14 18:08:41 +08:00
parent 256857b6c5
commit ba84afb179
7 changed files with 1005 additions and 6 deletions

View File

@ -31,6 +31,10 @@ config CH376_WORK_MODE
endif # BSP_USING_CH376
menuconfig BSP_USING_ENET
bool "Using ENET device"
default n
menuconfig BSP_USING_CH438
bool "Using CH438 device"
default n

View File

@ -103,6 +103,14 @@ extern "C"
#define CH438_D7_PIN 34
#define CH438_INT_PIN 35
/* w5500 IO */
#define BSP_ENET_SCLK 9
#define BSP_ENET_MISO 10
#define BSP_ENET_MOSI 11
#define BSP_ENET_NCS 12
#define BSP_ENET_NRST 13
#define BSP_ENET_NINT 14
/* other mode io */
#define GPIO_E220_M0 44
#define GPIO_E220_M1 45
@ -137,6 +145,14 @@ extern "C"
#define FPIOA_CH438_D7 31
#define FPIOA_CH438_INT 22
/* w5500 FPIOA */
#define FPIOA_ENET_NRST 5
#define FPIOA_ENET_NINT 6
#define FPIOA_ENET_SCLK 7
#define FPIOA_ENET_MISO 8
#define FPIOA_ENET_MOSI 9
#define FPIOA_ENET_NCS 10
/* other mode FPIOA */
#define FPIOA_E220_M0 1
#define FPIOA_E220_M1 2

View File

@ -50,4 +50,7 @@ ifeq ($(CONFIG_BSP_USING_CH376),y)
CSRCS += k210_ch376.c ch376_demo.c
endif
ifeq ($(CONFIG_BSP_USING_ENET),y)
CSRCS += w5500.c
endif
include $(TOPDIR)/boards/Board.mk

View File

@ -108,10 +108,5 @@ int k210_bringup(void)
fpioa_set_function(GPIO_CH376T_TXD, FPOA_USART3_TX);
#endif
#ifdef CONFIG_BSP_USING_ENET
k210_sysctl_init();
board_enet_initialize();
#endif
return ret;
}

View File

@ -24,7 +24,6 @@
#include <nuttx/config.h>
#include <nuttx/board.h>
#include <nuttx/board.h>
#include <arch/board/board.h>

View File

@ -0,0 +1,683 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file w5500.c
* @brief w5500 driver based on simulated SPI
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-9-14
*/
#include "nuttx/arch.h"
#include "w5500.h"
#include "k210_gpio_common.h"
/****************************************************************************
* Private Data
****************************************************************************/
w5500_param_t w5500_param;
/****************************************************************************
* Name: spi_read_byte
* Description: Read one byte spi data returned
* input: None
* output: None
* return:Read register data
****************************************************************************/
static uint8_t spi_read_byte(void)
{
uint8_t i, dat = 0;
SCLK_L();
for(i = 0; i < 8; i++)
{
SCLK_H();
dat <<= 1;
dat |= k210_gpiohs_get_value(FPIOA_ENET_MISO);
up_udelay(1);
SCLK_L();
}
return dat;
}
/****************************************************************************
* Name: spi_write_byte
* Description: send 1 byte to spi
* input: data
* output: None
* return: None
****************************************************************************/
static void spi_write_byte(uint8_t dat)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
SCLK_L();
if((dat << i) & 0x80)
{
MOSI_H();
}
else
{
MOSI_L();
}
SCLK_H();
}
SCLK_L();
}
/****************************************************************************
* Name: spi_write_short
* Description: send 2 bytes to spi
* input: data
* output: None
* return: None
****************************************************************************/
static void spi_write_short(uint16_t dat)
{
spi_write_byte((uint8_t)(dat / 256));
spi_write_byte(dat);
}
/****************************************************************************
* Name: w5500_write_byte
*Description: Write 1 byte data to the specified address register through SPI
*Input: reg: 16 bit register address, dat: data to be written
* output: None
* return: None
****************************************************************************/
static void w5500_write_byte(uint16_t reg, uint8_t dat)
{
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM1 | RWB_WRITE | COMMON_R);
spi_write_byte(dat);
NCS_H();
}
/****************************************************************************
* Name: w5500_write_short
* Description: Write 2 bytes data to the specified address register through SPI
* Input: reg: 16 bit register address, dat: data to be written
* output: None
* return: None
****************************************************************************/
static void w5500_write_short(uint16_t reg, uint16_t dat)
{
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM2 | RWB_WRITE | COMMON_R);
spi_write_short(dat);
NCS_H();
}
/****************************************************************************
* Name: w5500_write_bytes
* Description: Write n bytes data to the specified address register through SPI
* Input: reg: 16 bit register address, dat: data to be written,size:Length of data to be written
* output: None
* return: None
****************************************************************************/
static void w5500_write_bytes(uint16_t reg, uint8_t *dat, uint16_t size)
{
uint16_t i;
NCS_L();
spi_write_short(reg);
spi_write_byte(VDM | RWB_WRITE | COMMON_R);
for(i = 0; i < size; i++)
{
spi_write_byte(*dat++);
}
NCS_H();
}
/****************************************************************************
* Name: w5500_write_sock_byte
* Description: Write 1 byte data to the specified port register through SPI
* Input: sock: port number, reg: 16 bit register address, dat: data to be written
* Output: None
* return: None
****************************************************************************/
void w5500_write_sock_byte(socket_t sock, uint16_t reg, uint8_t dat)
{
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM1 | RWB_WRITE | (sock * 0x20 + 0x08));
spi_write_byte(dat);
NCS_H();
}
/****************************************************************************
* Name: w5500_write_sock_short
* Description: Write 2 bytes data to the specified port register through SPI
* Input: sock: port number, reg: 16 bit register address, dat: data to be written
* Output: None
* return: None
****************************************************************************/
void w5500_write_sock_short(socket_t sock, uint16_t reg, uint16_t dat)
{
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM2 | RWB_WRITE | (sock * 0x20 + 0x08));
spi_write_short(dat);
NCS_H();
}
/****************************************************************************
* Name: w5500_write_sock_long
* Description: Write 4 bytes data to the specified port register through SPI
* Input: sock: port number, reg: 16 bit register address, dat: 4 byte buffer pointers to be written
* Output: None
* return: None
****************************************************************************/
void w5500_write_sock_long(socket_t sock, uint16_t reg, uint8_t *dat)
{
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM4 | RWB_WRITE | (sock * 0x20 + 0x08));
spi_write_byte(*dat++);
spi_write_byte(*dat++);
spi_write_byte(*dat++);
spi_write_byte(*dat++);
NCS_H();
}
/*******************************************************************************
*Function name: w5500_read_byte
*Description: Read 1 byte data of W5500 specified address register
*Input: reg: 16 bit register address
*Output: None
*Return : 1 byte data read from the register
*******************************************************************************/
uint8_t w5500_read_byte(uint16_t reg)
{
uint8_t val;
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM1 | RWB_READ | COMMON_R);
val = spi_read_byte();
NCS_H();
return val;
}
/*******************************************************************************
*Function name: w5500_read_sock_byte
*Description: Read 1 byte data of W5500 specified port register
*Input: sock: port number, reg: 16 bit register address
*Output: None
*Return: 1 byte data read from the register
*Description: None
*******************************************************************************/
uint8_t w5500_read_sock_byte(socket_t sock, uint16_t reg)
{
uint8_t val;
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM1 | RWB_READ | (sock * 0x20 + 0x08));
val = spi_read_byte();
NCS_H();
return val;
}
/*******************************************************************************
*Function name: w5500_read_sock_short
*Description: Read 2 bytes of W5500 specified port register
*Input: sock: port number, reg: 16 bit register address
*Output: None
*Return: read 2 bytes of data from the register (16 bits)
*******************************************************************************/
uint16_t w5500_read_sock_short(socket_t sock, uint16_t reg)
{
uint16_t val;
NCS_L();
spi_write_short(reg);
spi_write_byte(FDM2 | RWB_READ |(sock * 0x20 + 0x08));
val = spi_read_byte();
val *= 256;
val |= spi_read_byte();
NCS_H();
return val;
}
/*******************************************************************************
*Function name: w5500_read_sock_bytes
*Description: Read data from W5500 receive data buffer
*Input: sock: port number, * dat: data saving buffer pointer
*Output: None
*Return: read data length
*******************************************************************************/
uint16_t w5500_read_sock_bytes(socket_t sock, uint8_t *dat)
{
uint16_t recv_size, write_addr;
uint16_t recv_addr;
uint16_t i;
uint8_t val;
recv_size = w5500_read_sock_short(sock, W5500_SN_RX_RSR_REG);
//no receive data
if(recv_size == 0)
{
return 0;
}
if(recv_size > W5500_MAX_PACK_SIZE)
{
recv_size = W5500_MAX_PACK_SIZE;
}
recv_addr = w5500_read_sock_short(sock, W5500_SN_RX_RD_REG);
write_addr = recv_addr;
//calculate physical address
recv_addr &= (SOCK_RECV_SIZE - 1);
NCS_L();
spi_write_short(recv_addr);
spi_write_byte(VDM | RWB_READ | (sock * 0x20 + 0x18));
if((recv_addr + recv_size) < SOCK_RECV_SIZE)
{
for(i = 0; i < recv_size; i++)
{
val = spi_read_byte();
*dat = val;
dat++;
}
}
else
{
recv_addr = SOCK_RECV_SIZE - recv_addr;
for(i = 0; i < recv_addr; i++)
{
val = spi_read_byte();
*dat = val;
dat++;
}
NCS_H();
NCS_L();
spi_write_short(0x00);
spi_write_byte(VDM | RWB_READ | (sock * 0x20 + 0x18));
for(; i < recv_size; i++)
{
val= spi_read_byte();
*dat = val;
dat++;
}
}
NCS_H();
write_addr += recv_size;
w5500_write_sock_short(sock, W5500_SN_RX_RD_REG, write_addr);
//start receive
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_RECV);
return recv_size;
}
/*******************************************************************************
*Function name: w5500_write_sock_bytes
*Description: Write data to the data sending buffer of W5500
*Input: sock: port number, dat: data storage buffer pointer, size: length of data to be written
*Output: None
*Return: None
*******************************************************************************/
void w5500_write_sock_bytes(socket_t sock, uint8_t *dat, uint16_t size)
{
uint16_t recv_addr, write_addr;
uint16_t i;
// if udp mode, set ip and port
if(w5500_read_sock_byte(sock, W5500_SN_MR_REG) != SOCK_UDP)
{
w5500_write_sock_long(sock, W5500_SN_DIPR_REG, w5500_param.udp_ip);
w5500_write_sock_short(sock, W5500_SN_DPORTR_REG, w5500_param.udp_port);
}
recv_addr = w5500_read_sock_short(sock, W5500_SN_TX_WR_REG);
write_addr = recv_addr;
recv_addr &= (SOCK_SEND_SIZE - 1);
NCS_L();
spi_write_short(recv_addr);
spi_write_byte(VDM | RWB_WRITE | (sock * 0x20 + 0x10));
if((recv_addr + size) < SOCK_SEND_SIZE)
{
for(i = 0; i < size; i++)
{
spi_write_byte(*dat++);
}
}
else
{
recv_addr = SOCK_SEND_SIZE - recv_addr;
for(i = 0; i < recv_addr; i++)
{
spi_write_byte(*dat++);
}
NCS_H();
NCS_L();
spi_write_short(0x00);
spi_write_byte(VDM | RWB_WRITE | (sock * 0x20 + 0x10));
for(; i < size; i++)
{
spi_write_byte(*dat++);
}
}
NCS_H();
write_addr += size;
w5500_write_sock_short(sock, W5500_SN_TX_WR_REG, write_addr);
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_SEND);
}
/*******************************************************************************
*Function name: w5500_reset
*Description: Hardware reset W5500
*Input: None
*Output: None
*Return value: None
*Note: The reset pin of the W5500 can be encircled only when the low level is at least 500us
*******************************************************************************/
void w5500_reset(void)
{
uint8_t dat = 0;
RST_L();
RST_H();
//wait connect ok
while((dat & LINK) == 0)
{
up_mdelay(500);
dat = w5500_read_byte(W5500_PHYCFGR_REG);
}
}
/*******************************************************************************
*Function name: w5500_config_init
*Description: Initialize W5500 register functions
*Input: None
*Output: None
*Return value: None
*Note: Before using W5500, initialize W5500
*******************************************************************************/
void w5500_config_init(void)
{
uint8_t i = 0;
//software reset, set 1 and auto clear 0
w5500_write_byte(W5500_MR_REG, MR_RST);
up_mdelay(100);
w5500_write_bytes(W5500_GAR_REG, w5500_param.gw_addr, 4);
w5500_write_bytes(W5500_SUBR_REG, w5500_param.ip_mask, 4);
w5500_write_bytes(W5500_SHAR_REG, w5500_param.mac_addr, 6);
w5500_write_bytes(W5500_SIPR_REG, w5500_param.ip_addr, 4);
//set socket rx and tx memory size 2k
for(i = 0; i < 8; i++)
{
w5500_write_sock_byte(i, W5500_SN_RXBUF_SIZE_REG, 0x02);
w5500_write_sock_byte(i, W5500_SN_TXBUF_SIZE_REG, 0x02);
}
//set retry time 200ms (0x07d0 = 2000)
w5500_write_short(W5500_RTR_REG, 0x07d0);
//retry time with 8, when exceed it, produce overtime interrupt, set W5500_SN_IR_REG(TIMEOUT)
w5500_write_byte(W5500_RCR_REG, 8);
}
/*******************************************************************************
*Function name: Detect_Gateway
*Description: Check the gateway server
*Input: None
*Output: None
*Return value: TRUE (0xFF) for success, FALSE (0x00) for failure
*******************************************************************************/
uint8_t w5500_detect_gateway(void)
{
uint8_t ip_addr[4] = {w5500_param.ip_addr[0] + 1, w5500_param.ip_addr[1] + 1, w5500_param.ip_addr[2] + 1, w5500_param.ip_addr[3] + 1};
//check gateway and get gateway phyiscal address
w5500_write_sock_long(0, W5500_SN_DIPR_REG, ip_addr);
w5500_write_sock_byte(0, W5500_SN_MR_REG, SN_MR_TCP);
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_OPEN);
up_mdelay(5);
if(w5500_read_sock_byte(0, W5500_SN_SR_REG) != SOCK_INIT)
{
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE);
return FALSE;
}
//set socket connection mode
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CONNECT);
do
{
uint8_t val = 0;
//read socket0 interrupt register
val = w5500_read_sock_byte(0, W5500_SN_IR_REG);
if(val != 0)
{
w5500_write_sock_byte(0, W5500_SN_IR_REG, val);
}
up_mdelay(5);
if((val & IR_TIMEOUT) == IR_TIMEOUT)
{
return FALSE;
}
else if(w5500_read_sock_byte(0, W5500_SN_DHAR_REG) != 0xff)
{
//close socket
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE);
return TRUE;
}
} while(1);
return TRUE;
}
/*******************************************************************************
*Function name: w5500_socket_init
*Description: Specify Socket (0~7) initialization
*Input: sock: port to be initialized
*Output: None
*Return value: None
*******************************************************************************/
void w5500_socket_init(socket_t sock)
{
//max partition bytes = 30
w5500_write_sock_short(0, W5500_SN_MSSR_REG, 30);
switch(sock)
{
case 0:
w5500_write_sock_short(0, W5500_SN_PORT_REG, w5500_param.sock.local_port);
w5500_write_sock_short(0, W5500_SN_DPORTR_REG, w5500_param.sock.dst_port);
w5500_write_sock_long(0, W5500_SN_DIPR_REG, w5500_param.sock.dst_ip);
break;
default:
break;
}
}
/*******************************************************************************
*Function name: w5500_socket_connect
*Description: Set the specified Socket (0~7) as the client to connect with the remote server
*Input: sock: port to be set
*Output: None
*Return value: TRUE (0xFF) for success, FALSE (0x00) for failure
*******************************************************************************/
uint8_t w5500_socket_connect(socket_t sock)
{
w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_TCP);
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN);
up_mdelay(5);
if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_INIT)
{
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE);
return FALSE;
}
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CONNECT);
return TRUE;
}
/*******************************************************************************
*Function name: w5500_socket_listen
*Description: Set the specified Socket (0~7) as the server to wait for the connection of the remote host
*Input: sock: port to be set
*Output: None
*Return value: TRUE (0xFF) for success, FALSE (0x00) for failure
*******************************************************************************/
uint8_t w5500_socket_listen(socket_t sock)
{
w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_TCP);
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN);
up_mdelay(5);
if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_INIT)
{
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE);
return FALSE;
}
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_LISTEN);
up_mdelay(5);
if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_LISTEN)
{
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE);
return FALSE;
}
return TRUE;
}
/*******************************************************************************
*Function name: w5500_socket_set_udp
*Description: Set the specified Socket (0~7) to UDP mode
*Input: sock: port to be set
*Output: None
*Return value: TRUE (0xFF) for success, FALSE (0x00) for failure
*******************************************************************************/
uint8_t w5500_socket_set_udp(socket_t sock)
{
w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_UDP);
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN);
up_mdelay(5);
if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_UDP)
{
w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE);
return FALSE;
}
return TRUE;
}
/*******************************************************************************
*Function name: w5500_irq_process
*Description: W5500 interrupt handler framework
*Input: None
*Output: None
*Return value: None
*Description: None
*******************************************************************************/
void w5500_irq_process(void)
{
uint8_t ir_flag, sn_flag;
ir_flag = w5500_read_byte(W5500_SIR_REG);
do
{
//handle socket0 event
if((ir_flag & S0_INT) == S0_INT)
{
sn_flag = w5500_read_sock_byte(0, W5500_SN_IR_REG);
w5500_write_sock_byte(0, W5500_SN_IR_REG, sn_flag);
if(sn_flag & IR_CON)
{
//socket connection finished
w5500_param.sock.flag |= SOCK_FLAG_CONN;
}
if(sn_flag & IR_DISCON)
{
//disconnect state
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE);
w5500_socket_init(0);
w5500_param.sock.flag = 0;
}
if(sn_flag & IR_SEND_OK)
{
//send one package ok
w5500_param.sock.state |= SOCK_STAT_SEND;
}
if(sn_flag & IR_RECV)
{
w5500_param.sock.state |= SOCK_STAT_RECV;
}
if(sn_flag & IR_TIMEOUT)
{
//close socket, connection failed
w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE);
w5500_param.sock.flag = 0;
}
}
ir_flag = w5500_read_byte(W5500_SIR_REG);
}while(ir_flag);
}
/*******************************************************************************
*Function name: w5500_load_param
*Description: load param to w5500_param
*Input: src: source param
*Output: None
*Return value: None
*******************************************************************************/
void w5500_load_param(w5500_param_t *src)
{
w5500_param_t *dest = &w5500_param;
memcpy(dest->ip_addr, src->ip_addr, sizeof(src->ip_addr));
memcpy(dest->ip_mask, src->ip_mask, sizeof(src->ip_mask));
memcpy(dest->gw_addr, src->gw_addr, sizeof(src->gw_addr));
memcpy(dest->mac_addr, src->mac_addr, sizeof(src->mac_addr));
memcpy(dest->sock.dst_ip, src->sock.dst_ip, sizeof(src->sock.dst_ip));
dest->sock.local_port = src->sock.local_port;
dest->sock.dst_port = src->sock.dst_port;
dest->sock.mode = src->sock.mode;
}

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file w5500.h
* @brief w5500 driver
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-9-15
*/
#ifndef _W5500_H_
#define _W5500_H_
#include <nuttx/config.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <debug.h>
#include <assert.h>
#include <nuttx/time.h>
#include <nuttx/fs/fs.h>
#include "k210_config.h"
#include "k210_fpioa.h"
#include "k210_gpiohs.h"
#include "nuttx/arch.h"
#include "k210_gpio_common.h"
/***************** Common Register *****************/
#define W5500_MR_REG 0x0000
#define MR_RST 0x80
#define MR_WOL 0x20
#define MR_PB 0x10
#define MR_PPP 0x08
#define MR_FARP 0x02
#define W5500_GAR_REG 0x0001
#define W5500_SUBR_REG 0x0005
#define W5500_SHAR_REG 0x0009
#define W5500_SIPR_REG 0x000f
#define W5500_INT_REG 0x0013
#define W5500_IR_REG 0x0015
#define IR_CONFLICT 0x80
#define IR_UNREACH 0x40
#define IR_PPPOE 0x20
#define IR_MP 0x10
#define W5500_IMR_REG 0x0016
#define IMR_IR7 0x80
#define IMR_IR6 0x40
#define IMR_IR5 0x20
#define IMR_IR4 0x10
#define W5500_SIR_REG 0x0017
#define S7_INT 0x80
#define S6_INT 0x40
#define S5_INT 0x20
#define S4_INT 0x10
#define S3_INT 0x08
#define S2_INT 0x04
#define S1_INT 0x02
#define S0_INT 0x01
#define W5500_SIMR_REG 0x0018
#define S7_IMR 0x80
#define S6_IMR 0x40
#define S5_IMR 0x20
#define S4_IMR 0x10
#define S3_IMR 0x08
#define S2_IMR 0x04
#define S1_IMR 0x02
#define S0_IMR 0x01
#define W5500_RTR_REG 0x0019
#define W5500_RCR_REG 0x001B
#define W5500_PTIMER_REG 0x001C
#define W5500_PMAGIC_REG 0x001D
#define W5500_PHA_REG 0x001E
#define W5500_PSID_REG 0x0024
#define W5500_PMRU_REG 0x0026
#define W5500_UIPR_REG 0x0028
#define W5500_UPORT_REG 0x002C
#define W5500_PHYCFGR_REG 0x002E
#define RST_PHY 0x80
#define OPMODE 0x40
#define DPX 0x04
#define SPD 0x02
#define LINK 0x01
#define W5500_VER_REG 0x0039
/********************* Socket Register *******************/
#define W5500_SN_MR_REG 0x0000
#define SN_MR_MULTI_MFEN 0x80
#define SN_MR_BCASTB 0x40
#define SN_MR_ND_MC_MMB 0x20
#define SN_MR_UCASTB_MIP6B 0x10
#define SN_MR_CLOSE 0x00
#define SN_MR_TCP 0x01
#define SN_MR_UDP 0x02
#define SN_MR_MACRAW 0x04
#define W5500_SN_CR_REG 0x0001
#define SN_CR_OPEN 0x01
#define SN_CR_LISTEN 0x02
#define SN_CR_CONNECT 0x04
#define SN_CR_DISCON 0x08
#define SN_CR_CLOSE 0x10
#define SN_CR_SEND 0x20
#define SN_CR_SEND_MAC 0x21
#define SN_CR_SEND_KEEP 0x22
#define SN_CR_RECV 0x40
#define W5500_SN_IR_REG 0x0002
#define IR_SEND_OK 0x10
#define IR_TIMEOUT 0x08
#define IR_RECV 0x04
#define IR_DISCON 0x02
#define IR_CON 0x01
#define W5500_SN_SR_REG 0x0003
#define SOCK_CLOSED 0x00
#define SOCK_INIT 0x13
#define SOCK_LISTEN 0x14
#define SOCK_ESTABLISHED 0x17
#define SOCK_CLOSE_WAIT 0x1C
#define SOCK_UDP 0x22
#define SOCK_MACRAW 0x02
#define SOCK_SYNSEND 0x15
#define SOCK_SYNRECV 0x16
#define SOCK_FIN_WAI 0x18
#define SOCK_CLOSING 0x1A
#define SOCK_TIME_WAIT 0x1B
#define SOCK_LAST_ACK 0x1D
#define W5500_SN_PORT_REG 0x0004
#define W5500_SN_DHAR_REG 0x0006
#define W5500_SN_DIPR_REG 0x000C
#define W5500_SN_DPORTR_REG 0x0010
#define W5500_SN_MSSR_REG 0x0012
#define W5500_SN_TOS_REG 0x0015
#define W5500_SN_TTL_REG 0x0016
#define W5500_SN_RXBUF_SIZE_REG 0x001E
#define W5500_SN_TXBUF_SIZE_REG 0x001F
#define W5500_SN_TX_FSR_REG 0x0020
#define W5500_SN_TX_RD_REG 0x0022
#define W5500_SN_TX_WR_REG 0x0024
#define W5500_SN_RX_RSR_REG 0x0026
#define W5500_SN_RX_RD_REG 0x0028
#define W5500_SN_RX_WR_REG 0x002A
#define W5500_SN_IMR_REG 0x002C
#define IMR_SENDOK 0x10
#define IMR_TIMEOUT 0x08
#define IMR_RECV 0x04
#define IMR_DISCON 0x02
#define IMR_CON 0x01
#define W5500_SN_FRAG_REG 0x002D
#define W5500_SN_KPALVTR_REG 0x002F
/************************ SPI Control Data *************************/
/* Operation mode bits */
#define VDM 0x00
#define FDM1 0x01
#define FDM2 0x02
#define FDM4 0x03
/* Read_Write control bit */
#define RWB_READ 0x00
#define RWB_WRITE 0x04
/* Block select bits */
#define COMMON_R 0x00
/* Socket 0 */
#define S0_REG 0x08
#define S0_TX_BUF 0x10
#define S0_RX_BUF 0x18
/* Socket 1 */
#define S1_REG 0x28
#define S1_TX_BUF 0x30
#define S1_RX_BUF 0x38
/* Socket 2 */
#define S2_REG 0x48
#define S2_TX_BUF 0x50
#define S2_RX_BUF 0x58
/* Socket 3 */
#define S3_REG 0x68
#define S3_TX_BUF 0x70
#define S3_RX_BUF 0x78
/* Socket 4 */
#define S4_REG 0x88
#define S4_TX_BUF 0x90
#define S4_RX_BUF 0x98
/* Socket 5 */
#define S5_REG 0xa8
#define S5_TX_BUF 0xb0
#define S5_RX_BUF 0xb8
/* Socket 6 */
#define S6_REG 0xc8
#define S6_TX_BUF 0xd0
#define S6_RX_BUF 0xd8
/* Socket 7 */
#define S7_REG 0xe8
#define S7_TX_BUF 0xf0
#define S7_RX_BUF 0xf8
// socket receive buffer size based on RMSR
#define SOCK_RECV_SIZE 2048
// socket send buffer size based on RMSR
#define SOCK_SEND_SIZE 2048
#define W5500_IP_ADDR_LEN 4
#define W5500_IP_MASK_LEN 4
#define W5500_GW_ADDR_LEN 4
#define W5500_MAC_ADDR_LEN 6
//for every socket
// socket mode
#define SOCK_TCP_SVR 0 //server mode
#define SOCK_TCP_CLI 1 //client mode
#define SOCK_UDP_MOD 2 //udp mode
// socket flag
#define SOCK_FLAG_INIT 1
#define SOCK_FLAG_CONN 2
// socket data state
#define SOCK_STAT_RECV 1
#define SOCK_STAT_SEND 2
typedef struct w5500_socket_s
{
uint16_t local_port;
uint8_t dst_ip[W5500_IP_ADDR_LEN];
uint16_t dst_port;
uint8_t mode; // 0: TCP Server; 1: TCP client; 2: UDP
uint8_t flag; // 1: init ok; 2: connected
uint8_t state; // 1: receive one; 2: send ok
}w5500_socket_t;
typedef struct
{
uint8_t ip_addr[W5500_IP_ADDR_LEN];
uint8_t ip_mask[W5500_IP_MASK_LEN];
uint8_t gw_addr[W5500_GW_ADDR_LEN];
uint8_t mac_addr[W5500_MAC_ADDR_LEN];
uint8_t udp_ip[4];
uint16_t udp_port;
w5500_socket_t sock;
}w5500_param_t;
#define W5500_MAX_PACK_SIZE 1460
typedef unsigned char socket_t;
#define NCS_L() k210_gpiohs_set_value(FPIOA_ENET_NCS, GPIO_PV_LOW); up_udelay(1);
#define NCS_H() k210_gpiohs_set_value(FPIOA_ENET_NCS, GPIO_PV_HIGH); up_udelay(1);
#define SCLK_L() k210_gpiohs_set_value(FPIOA_ENET_SCLK, GPIO_PV_LOW); up_udelay(1);
#define SCLK_H() k210_gpiohs_set_value(FPIOA_ENET_SCLK, GPIO_PV_HIGH); up_udelay(1);
#define MOSI_L() k210_gpiohs_set_value(FPIOA_ENET_MOSI, GPIO_PV_LOW); up_udelay(1);
#define MOSI_H() k210_gpiohs_set_value(FPIOA_ENET_MOSI, GPIO_PV_HIGH); up_udelay(1);
#define RST_L() k210_gpiohs_set_value(FPIOA_ENET_NRST, GPIO_PV_LOW); up_mdelay(200);
#define RST_H() k210_gpiohs_set_value(FPIOA_ENET_NRST, GPIO_PV_HIGH); up_mdelay(200);
int w5500_net_test(void);
#endif