388 lines
14 KiB
C
388 lines
14 KiB
C
|
|
/**
|
||
|
|
Copyright (c) 2022 WIZnet Co.,Ltd
|
||
|
|
|
||
|
|
SPDX-License-Identifier: BSD-3-Clause
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
Includes
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
#include "port_common.h"
|
||
|
|
|
||
|
|
#include "wizchip_conf.h"
|
||
|
|
#include "wizchip_spi.h"
|
||
|
|
#include "board_list.h"
|
||
|
|
|
||
|
|
|
||
|
|
#include "wizchip_qspi_pio.h"
|
||
|
|
#include "pico/stdlib.h"
|
||
|
|
#include "pico/binary_info.h"
|
||
|
|
#include "pico/critical_section.h"
|
||
|
|
#include "hardware/dma.h"
|
||
|
|
|
||
|
|
/**
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
Macros
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
Variables
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
static critical_section_t g_wizchip_cri_sec;
|
||
|
|
|
||
|
|
#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
|
||
|
|
|
||
|
|
#ifdef USE_PIO
|
||
|
|
#if (_WIZCHIP_ == W6300)
|
||
|
|
wiznet_spi_config_t g_spi_config = {
|
||
|
|
.clock_div_major = WIZNET_SPI_CLKDIV_MAJOR_DEFAULT,
|
||
|
|
.clock_div_minor = WIZNET_SPI_CLKDIV_MINOR_DEFAULT,
|
||
|
|
.clock_pin = PIO_SPI_SCK_PIN,
|
||
|
|
.data_io0_pin = PIO_SPI_DATA_IO0_PIN,
|
||
|
|
.data_io1_pin = PIO_SPI_DATA_IO1_PIN,
|
||
|
|
.data_io2_pin = PIO_SPI_DATA_IO2_PIN,
|
||
|
|
.data_io3_pin = PIO_SPI_DATA_IO3_PIN,
|
||
|
|
.cs_pin = PIN_CS,
|
||
|
|
.reset_pin = PIN_RST,
|
||
|
|
.irq_pin = PIN_INT,
|
||
|
|
};
|
||
|
|
#else
|
||
|
|
wiznet_spi_config_t g_spi_config = {
|
||
|
|
.data_in_pin = PIN_MISO,
|
||
|
|
.data_out_pin = PIN_MOSI,
|
||
|
|
.cs_pin = PIN_CS,
|
||
|
|
.clock_pin = PIN_SCK,
|
||
|
|
.irq_pin = PIN_INT,
|
||
|
|
.reset_pin = PIN_RST,
|
||
|
|
.clock_div_major = WIZNET_SPI_CLKDIV_MAJOR_DEFAULT,
|
||
|
|
.clock_div_minor = WIZNET_SPI_CLKDIV_MINOR_DEFAULT,
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
wiznet_spi_handle_t spi_handle;
|
||
|
|
|
||
|
|
/**
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
Functions
|
||
|
|
----------------------------------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
static inline void wizchip_select(void) {
|
||
|
|
gpio_put(PIN_CS, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static inline void wizchip_deselect(void) {
|
||
|
|
gpio_put(PIN_CS, 1);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void wizchip_reset() {
|
||
|
|
gpio_init(PIN_RST);
|
||
|
|
|
||
|
|
#if defined(USE_PIO) && (_WIZCHIP_ == W5500)
|
||
|
|
gpio_pull_up(PIN_RST);
|
||
|
|
gpio_set_dir(PIN_RST, GPIO_OUT);
|
||
|
|
sleep_ms(5);
|
||
|
|
#else
|
||
|
|
gpio_set_dir(PIN_RST, GPIO_OUT);
|
||
|
|
#endif
|
||
|
|
gpio_put(PIN_RST, 0);
|
||
|
|
sleep_ms(100);
|
||
|
|
|
||
|
|
gpio_put(PIN_RST, 1);
|
||
|
|
sleep_ms(100);
|
||
|
|
|
||
|
|
bi_decl(bi_1pin_with_name(PIN_RST, "WIZCHIP RESET"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifndef USE_PIO
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#if (_WIZCHIP_ == W6100)
|
||
|
|
static void wizchip_read_buf(uint8_t* rx_data, datasize_t len) {
|
||
|
|
uint8_t tx_data = 0xFF;
|
||
|
|
|
||
|
|
spi_read_blocking(SPI_PORT, tx_data, rx_data, len);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void wizchip_write_buf(uint8_t* tx_data, datasize_t len) {
|
||
|
|
spi_write_blocking(SPI_PORT, tx_data, len);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
#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
|
||
|
|
#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);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wizchip_spi_initialize(void) {
|
||
|
|
#ifdef USE_PIO
|
||
|
|
spi_handle = wiznet_spi_pio_open(&g_spi_config);
|
||
|
|
(*spi_handle)->set_active(spi_handle);
|
||
|
|
#else
|
||
|
|
// this example will use SPI0 at 5MHz
|
||
|
|
spi_init(SPI_PORT, SPI_CLK * 1000 * 1000);
|
||
|
|
|
||
|
|
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
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void wizchip_cris_initialize(void) {
|
||
|
|
critical_section_init(&g_wizchip_cri_sec);
|
||
|
|
reg_wizchip_cris_cbfunc(wizchip_critical_section_lock, wizchip_critical_section_unlock);
|
||
|
|
}
|
||
|
|
|
||
|
|
void wizchip_initialize(void) {
|
||
|
|
|
||
|
|
#ifdef USE_PIO
|
||
|
|
(*spi_handle)->frame_end();
|
||
|
|
#if (_WIZCHIP_ == W6300)
|
||
|
|
reg_wizchip_qspi_cbfunc((*spi_handle)->read_byte, (*spi_handle)->write_byte);
|
||
|
|
#else
|
||
|
|
reg_wizchip_spi_cbfunc((*spi_handle)->read_byte, (*spi_handle)->write_byte);
|
||
|
|
reg_wizchip_spiburst_cbfunc((*spi_handle)->read_buffer, (*spi_handle)->write_buffer);
|
||
|
|
#endif
|
||
|
|
reg_wizchip_cs_cbfunc((*spi_handle)->frame_start, (*spi_handle)->frame_end);
|
||
|
|
|
||
|
|
#else
|
||
|
|
/* Deselect the FLASH : chip select high */
|
||
|
|
wizchip_deselect();
|
||
|
|
/* CS function register */
|
||
|
|
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
|
||
|
|
/* SPI function register */
|
||
|
|
#if (_WIZCHIP_ == W6100)
|
||
|
|
reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write, wizchip_read_buf, wizchip_write_buf);
|
||
|
|
#else
|
||
|
|
reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#ifdef USE_SPI_DMA
|
||
|
|
reg_wizchip_spiburst_cbfunc(wizchip_read_burst, wizchip_write_burst);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* W5x00, W6x00 initialize */
|
||
|
|
uint8_t temp;
|
||
|
|
#if (_WIZCHIP_ == W5100S)
|
||
|
|
uint8_t memsize[2][4] = {{2, 2, 2, 2}, {2, 2, 2, 2}};
|
||
|
|
#elif (_WIZCHIP_ == W5500)
|
||
|
|
uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
|
||
|
|
#elif (_WIZCHIP_ == W6100)
|
||
|
|
uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
|
||
|
|
#elif (_WIZCHIP_ == W6300)
|
||
|
|
uint8_t memsize[2][8] = {{4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4}};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (ctlwizchip(CW_INIT_WIZCHIP, (void *)memsize) == -1) {
|
||
|
|
#if _WIZCHIP_ <= W5500
|
||
|
|
printf(" W5x00 initialized fail\n");
|
||
|
|
#else
|
||
|
|
printf(" W6x00 initialized fail\n");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void wizchip_check(void) {
|
||
|
|
#if (_WIZCHIP_ == W5100S)
|
||
|
|
/* Read version register */
|
||
|
|
if (getVER() != 0x51) {
|
||
|
|
printf(" ACCESS ERR : VERSION != 0x51, read value = 0x%02x\n", getVER());
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
;
|
||
|
|
}
|
||
|
|
#elif (_WIZCHIP_ == W5500)
|
||
|
|
/* Read version register */
|
||
|
|
if (getVERSIONR() != 0x04) {
|
||
|
|
printf(" ACCESS ERR : VERSION != 0x04, read value = 0x%02x\n", getVERSIONR());
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
;
|
||
|
|
}
|
||
|
|
#elif (_WIZCHIP_ == W6100)
|
||
|
|
/* Read version register */
|
||
|
|
if (getCIDR() != 0x6100) {
|
||
|
|
printf(" ACCESS ERR : VERSION != 0x6100, read value = 0x%02x\n", getCIDR());
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
;
|
||
|
|
}
|
||
|
|
#elif (_WIZCHIP_ == W6300)
|
||
|
|
/* Read version register */
|
||
|
|
if (getCIDR() != 0x6300) {
|
||
|
|
printf(" ACCESS ERR : VERSION != 0x6100, read value = 0x%02x\n", getCIDR());
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Network */
|
||
|
|
void network_initialize(wiz_NetInfo net_info) {
|
||
|
|
#if _WIZCHIP_ <= W5500
|
||
|
|
ctlnetwork(CN_SET_NETINFO, (void *)&net_info);
|
||
|
|
#else
|
||
|
|
uint8_t syslock = SYS_NET_LOCK;
|
||
|
|
ctlwizchip(CW_SYS_UNLOCK, &syslock);
|
||
|
|
ctlnetwork(CN_SET_NETINFO, (void *)&net_info);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void print_network_information(wiz_NetInfo net_info) {
|
||
|
|
uint8_t tmp_str[8] = {
|
||
|
|
0,
|
||
|
|
};
|
||
|
|
|
||
|
|
ctlnetwork(CN_GET_NETINFO, (void *)&net_info);
|
||
|
|
ctlwizchip(CW_GET_ID, (void *)tmp_str);
|
||
|
|
#if _WIZCHIP_ <= W5500
|
||
|
|
if (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", net_info.mac[0], net_info.mac[1], net_info.mac[2], net_info.mac[3], net_info.mac[4], net_info.mac[5]);
|
||
|
|
printf(" IP : %d.%d.%d.%d\n", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3]);
|
||
|
|
printf(" Subnet Mask : %d.%d.%d.%d\n", net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3]);
|
||
|
|
printf(" Gateway : %d.%d.%d.%d\n", net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3]);
|
||
|
|
printf(" DNS : %d.%d.%d.%d\n", net_info.dns[0], net_info.dns[1], net_info.dns[2], net_info.dns[3]);
|
||
|
|
printf("====================================================================================================\n\n");
|
||
|
|
#else
|
||
|
|
printf("==========================================================\n");
|
||
|
|
printf(" %s network configuration\n\n", (char *)tmp_str);
|
||
|
|
|
||
|
|
printf(" MAC : %02X:%02X:%02X:%02X:%02X:%02X\n", net_info.mac[0], net_info.mac[1], net_info.mac[2], net_info.mac[3], net_info.mac[4], net_info.mac[5]);
|
||
|
|
printf(" IP : %d.%d.%d.%d\n", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3]);
|
||
|
|
printf(" Subnet Mask : %d.%d.%d.%d\n", net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3]);
|
||
|
|
printf(" Gateway : %d.%d.%d.%d\n", net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3]);
|
||
|
|
printf(" DNS : %d.%d.%d.%d\n", net_info.dns[0], net_info.dns[1], net_info.dns[2], net_info.dns[3]);
|
||
|
|
print_ipv6_addr(" GW6 ", net_info.gw6);
|
||
|
|
print_ipv6_addr(" LLA ", net_info.lla);
|
||
|
|
print_ipv6_addr(" GUA ", net_info.gua);
|
||
|
|
print_ipv6_addr(" SUB6", net_info.sn6);
|
||
|
|
print_ipv6_addr(" DNS6", net_info.dns6);
|
||
|
|
printf("==========================================================\n\n");
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void print_ipv6_addr(uint8_t* name, uint8_t* ip6addr) {
|
||
|
|
printf("%s : ", name);
|
||
|
|
printf("%04X:%04X", ((uint16_t)ip6addr[0] << 8) | ((uint16_t)ip6addr[1]), ((uint16_t)ip6addr[2] << 8) | ((uint16_t)ip6addr[3]));
|
||
|
|
printf(":%04X:%04X", ((uint16_t)ip6addr[4] << 8) | ((uint16_t)ip6addr[5]), ((uint16_t)ip6addr[6] << 8) | ((uint16_t)ip6addr[7]));
|
||
|
|
printf(":%04X:%04X", ((uint16_t)ip6addr[8] << 8) | ((uint16_t)ip6addr[9]), ((uint16_t)ip6addr[10] << 8) | ((uint16_t)ip6addr[11]));
|
||
|
|
printf(":%04X:%04X\r\n", ((uint16_t)ip6addr[12] << 8) | ((uint16_t)ip6addr[13]), ((uint16_t)ip6addr[14] << 8) | ((uint16_t)ip6addr[15]));
|
||
|
|
}
|