/** Copyright (c) 2022 WIZnet Co.,Ltd SPDX-License-Identifier: BSD-3-Clause */ /** ---------------------------------------------------------------------------------------------------- Includes ---------------------------------------------------------------------------------------------------- */ #include #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])); }