forked from xuos/xiuos
add w5500 for xidatong-riscv64
This commit is contained in:
parent
256857b6c5
commit
ba84afb179
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue