diff --git a/.vscode/settings.json b/.vscode/settings.json index 37286d8..c3fa59a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "wizchip_conf.h": "c", "socket.h": "c", "type_traits": "c", - "compare": "c" + "compare": "c", + "uart.h": "c" } } \ No newline at end of file diff --git a/include/gpio.h b/include/gpio.h new file mode 100644 index 0000000..ca8be97 --- /dev/null +++ b/include/gpio.h @@ -0,0 +1,9 @@ +#ifndef GPIO_H +#define GPIO_H + +#include + +// Function prototype for initializing GPIO +void init_gpio(void); + +#endif // GPIO_H \ No newline at end of file diff --git a/include/spi_dma.h b/include/spi_dma.h new file mode 100644 index 0000000..6e718cc --- /dev/null +++ b/include/spi_dma.h @@ -0,0 +1,35 @@ +#ifndef SPI_DMA_H +#define SPI_DMA_H + +#include "ch32v003fun.h" + +typedef enum { + IDLE, + TRANSMITTING, + RECEIVING, + TX_DONE, + RX_DONE +} transfer_state_t; + +// SPI DMA initialization function +void init_spidma(void); + +// SPI DMA buffer read +void spidma_read_buffer(uint8_t *buf, uint16_t len); + +// SPI DMA buffer write +void spidma_write_buffer(uint8_t *buf, uint16_t len); + +// SPI (non-DMA) byte read +uint8_t spi_read_byte(); + +// SPI (non-DMA) byte write +void spi_write_byte(uint8_t byte); + +// activate CS +void spi_select(void); + +// deactivate CS +void spi_unselect(void); + +#endif // SPI_DMA_H diff --git a/include/uart.h b/include/uart.h index b1336a1..58de5a5 100644 --- a/include/uart.h +++ b/include/uart.h @@ -12,6 +12,6 @@ (UART_BAUD_RATE)) // USART1 // Function prototypes -void setup_uart(int uart_brr); +void init_uart(int uart_brr); #endif // UART_H diff --git a/include/w5500.h b/include/w5500.h index 8e69fd2..fbfa154 100644 --- a/include/w5500.h +++ b/include/w5500.h @@ -4,21 +4,27 @@ #include // Sets the CS pin low -void W5500_Select(void); +void w5500_select(void); // Sets the CS pin high -void W5500_Unselect(void); +void w5500_unselect(void); // Reads a byte via SPI -uint8_t W5500_ReadByte(void); +uint8_t w5500_read_byte(void); // Writes a byte via SPI -void W5500_WriteByte(uint8_t byte); +void w5500_write_byte(uint8_t byte); // Reads multiple bytes via SPI -void W5500_ReadBuff(uint8_t* buff, uint16_t len); +void w5500_read_buffer(uint8_t* buff, uint16_t len); // Writes multiple bytes via SPI -void W5500_WriteBuff(uint8_t* buff, uint16_t len); +void w5500_write_buffer(uint8_t* buff, uint16_t len); + +// Initializes the W5500 chip +void configure_network(void); + +// resolves a domain name +void resolve_domain_name(const char* domain_name); #endif // W5500_H diff --git a/platformio.ini b/platformio.ini index 9c6397d..00dd182 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,9 +8,8 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:genericCH32V203C8T6] +[env] platform = https://git.hye.su/mira/platform-ch32v.git - platform_packages = toolchain-riscv @ https://git.hye.su/mira/toolchain-riscv-linux.git ; gcc 14.2.0 framework-ch32v003fun @ https://github.com/cnlohr/ch32v003fun.git ; upstream cnlohr repo @@ -19,7 +18,8 @@ framework = ch32v003fun upload_protocol = wlink # isp, minichlink, wch-link, wlink build_unflags = -march=rv32imacxw build_flags = -march=rv32imac -Wall -Wextra -; dbg -; build_type = debug -; debug_build_unflags = -Og -; debug_build_flags = -Os -ggdb3 -g3 + +[env:local] +platform_packages = + toolchain-riscv @ symlink:///home/mira/src/xpack-riscv-none-elf-gcc-14.2.0-2 ; gcc 14.2.0 + framework-ch32v003fun @ https://github.com/cnlohr/ch32v003fun.git ; upstream cnlohr repo diff --git a/src/gpio.c b/src/gpio.c new file mode 100644 index 0000000..b2d0677 --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,13 @@ +#include "gpio.h" + +#include "ch32v003fun.h" + +void init_gpio(void) { + // Enable clock for GPIOB + RCC->APB2PCENR |= RCC_APB2Periph_GPIOB; + + // GPIOB Configuration: Pins 3 and 4 as Output, Push-Pull, 10MHz + GPIOB->CFGLR &= ~((0xF << (4 * 3)) | (0xF << (4 * 4))); + GPIOB->CFGLR |= ((GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 3)) | + ((GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 4)); +} diff --git a/src/main.c b/src/main.c index d8c2dd9..2d8f486 100644 --- a/src/main.c +++ b/src/main.c @@ -1,197 +1,26 @@ -#include -#include -#include -#include + #include #include "ch32v003fun.h" +#include "gpio.h" +#include "spi_dma.h" #include "uart.h" #include "w5500.h" -#define DHCP_SOCKET 0 -#define DNS_SOCKET 1 -#define HTTP_SOCKET 2 - -volatile uint32_t count = 0; - -void init_system(void) { - SystemInit(); // from ch32v003fun.h - - RCC->APB2PCENR |= - RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB; // Enable GPIO clocks - - setup_uart(UART_BRR_APB1); // 115200 baud -} - -void init_gpio(void) { - // GPIO PB3 pp - GPIOB->CFGLR &= ~(0xf << (4 * 3)); - GPIOB->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 3); - - // GPIO PB4 pp - GPIOB->CFGLR &= ~(0xf << (4 * 4)); - GPIOB->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 4); -} - -void init_spi(void) { - // Enable SPI1 - RCC->APB2PCENR |= RCC_APB2Periph_SPI1; - - // CS on PA4, 10MHz Output, open-drain - GPIOA->CFGLR &= ~(0xf << (4 * 4)); - GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD) << (4 * 4); - - // SCK on PA5, 10MHz Output, alt func, push-pull - GPIOA->CFGLR &= ~(0xf << (4 * 5)); - GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 5); - - // MOSI on PA7, 10MHz input, floating - GPIOA->CFGLR &= ~(0xf << (4 * 6)); - GPIOA->CFGLR |= (GPIO_CNF_IN_FLOATING) << (4 * 6); - - // MISO on PA6, 10MHz Output, alt func, push-pull - GPIOA->CFGLR &= ~(0xf << (4 * 7)); - GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 7); - - // SPI1->CTLR1 = (0 << 15) | // BIDIMODE - // (0 << 14) | // BIDIOE - // (0 << 13) | // CRCEN - // (0 << 12) | // CRCNEXT - // (0 << 11) | // DFF - // (0 << 10) | // RXONLY - // (1 << 9) | // SSM - // (0 << 8) | // SSI - // (0 << 7) | // LSBFIRST - // (0 << 6) | // SPE (Enable SPI) - // (1 << 5) | // BR[2] (Set baud rate) - // (0 << 4) | // BR[1] - // (0 << 3) | // BR[0] - // (1 << 2) | // MSTR (Master mode) - // (0 << 1) | // CPOL - // (0); // CPHA - - // reset control register - SPI1->CTLR1 = 0; - - // set prescaler - // 011: FPCLK/16 - SPI1->CTLR1 = (SPI1->CTLR1 & ~SPI_CTLR1_BR) | (0x3 << 3); - - // set clock polarity and phase - SPI1->CTLR1 |= (SPI_CPOL_Low | SPI_CPHA_1Edge); - - // configure NSS pin, master mode - SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode - - // CH32V203 is master - SPI1->CTLR1 |= SPI_Mode_Master; - - // set data direction and configure data pins - SPI1->CTLR1 |= SPI_Direction_2Lines_FullDuplex; - - // disable I2S mode - SPI1->I2SCFGR &= SPI_Mode_Select; - SPI1->CTLR1 &= ~(SPI_CTLR1_DFF); // DFF 16bit data-length enable, writable - // only when SPE is 0 - SPI1->CTLR1 |= SPI_CTLR1_SPE; -} - -volatile int ip_assigned = 0; - -void Callback_IPAssigned(void) { - printf("Callback: IP assigned! Leased time: %ld sec\r\n", getDHCPLeasetime()); - ip_assigned = 1; -} - -void Callback_IPConflict(void) { printf("Callback: IP conflict!\r\n"); } - -// 1K should be enough, see https://forum.wiznet.io/t/topic/1612/2 -uint8_t dhcp_buffer[1024]; -// 1K seems to be enough for this buffer as well -uint8_t dns_buffer[1024]; +void init_system(void); int main(void) { init_system(); + configure_network(); + resolve_domain_name("hye.su"); + return 0; +} + +void init_system(void) { + SystemInit(); + init_gpio(); - init_spi(); - - printf("SystemClk: %u\r\n", (unsigned)FUNCONF_SYSTEM_CORE_CLOCK); - - printf("Registering W5500 callbacks...\r\n"); - reg_wizchip_cs_cbfunc(W5500_Select, W5500_Unselect); - reg_wizchip_spi_cbfunc(W5500_ReadByte, W5500_WriteByte); - // reg_wizchip_spiburst_cbfunc(W5500_ReadBuff, W5500_WriteBuff); - - printf("Calling wizchip_init()...\r\n"); - uint8_t rx_tx_buff_sizes[] = {2, 2, 2, 2, 2, 2, 2, 2}; - wizchip_init(rx_tx_buff_sizes, rx_tx_buff_sizes); - - printf("Calling DHCP_init()...\r\n"); - wiz_NetInfo net_info = {.mac = {0xEA, 0x11, 0x22, 0x33, 0x44, 0xEA}, - .dhcp = NETINFO_DHCP}; - // set MAC address before using DHCP - setSHAR(net_info.mac); - DHCP_init(DHCP_SOCKET, dhcp_buffer); - - uint8_t version = getVERSIONR(); - - printf("W5500 VERSIONR: 0x%02X\n", version); - - printf("Registering DHCP callbacks...\r\n"); - reg_dhcp_cbfunc(Callback_IPAssigned, Callback_IPAssigned, - Callback_IPConflict); - - printf("Calling DHCP_run()...\r\n"); - // actually should be called in a loop, e.g. by timer - uint32_t ctr = 1e5; - while ((!ip_assigned) && (ctr > 0)) { - DHCP_run(); - ctr--; - } - if (!ip_assigned) { - printf("\r\nIP was not assigned :(\r\n"); - return 1; - } - - getIPfromDHCP(net_info.ip); - getGWfromDHCP(net_info.gw); - getSNfromDHCP(net_info.sn); - - uint8_t dns[4]; - getDNSfromDHCP(dns); - - printf( - "IP: %d.%d.%d.%d\r\nGW: %d.%d.%d.%d\r\nNet: %d.%d.%d.%d\r\nDNS: " - "%d.%d.%d.%d\r\n", - net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3], - net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3], - net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3], dns[0], - dns[1], dns[2], dns[3]); - - printf("Calling wizchip_setnetinfo()...\r\n"); - wizchip_setnetinfo(&net_info); - - printf("Calling DNS_init()...\r\n"); - DNS_init(DNS_SOCKET, dns_buffer); - - const char domain_name[] = "hye.su"; - uint8_t addr[4]; - int8_t res; - uint8_t retries = 0; - - while (retries < 2) { - Delay_Ms(250); - - printf("Resolving domain name \"%s\"...\r\n", domain_name); - - res = DNS_run(dns, (uint8_t *)domain_name, addr); - - if (res == 1) { - printf("Result: %d.%d.%d.%d\r\n", addr[0], addr[1], addr[2], addr[3]); - } else { - printf("DNS_run() failed, res = %d. Retries: %u\r\n", res, retries); - } - - retries++; - } -} \ No newline at end of file + init_uart(UART_BRR_APB1); + // init_spi(); + init_spidma(); +} diff --git a/src/spi_dma.c b/src/spi_dma.c new file mode 100644 index 0000000..59d4215 --- /dev/null +++ b/src/spi_dma.c @@ -0,0 +1,163 @@ +#include "spi_dma.h" + +#include "ch32v003fun.h" + +volatile transfer_state_t tx_state = IDLE; +volatile transfer_state_t rx_state = IDLE; + +static const uint8_t tx_dummy_byte = 0xFF; +static uint8_t rx_dummy; // Static RX dummy buffer + +static inline void wait_for_transfer_complete(void) { + while (tx_state != TX_DONE || rx_state != RX_DONE); +} + +// static inline void spi_wait_not_busy(void) { +// while ((SPI1->STATR & SPI_STATR_BSY) != 0); +// } + +void set_transfer_states(void) { + tx_state = TRANSMITTING; + rx_state = RECEIVING; +} + +void clear_transfer_states(void) { + tx_state = IDLE; + rx_state = IDLE; +} + +void DMA1_HandleIrq(uint32_t channel_interrupt, + volatile transfer_state_t* state, + transfer_state_t active_state, + transfer_state_t done_state) { + if (DMA1->INTFR & channel_interrupt) { // check if DMA interrupt occurred + DMA1->INTFCR = channel_interrupt; // clear the interrupt flag + if (*state == active_state) { + *state = done_state; + } + } +} +void DMA1_Channel3_IRQHandler(void) __attribute__((interrupt)); +void DMA1_Channel2_IRQHandler(void) __attribute__((interrupt)); + +void DMA1_Channel3_IRQHandler(void) { + DMA1_HandleIrq(DMA1_IT_TC3, &tx_state, TRANSMITTING, TX_DONE); +} + +void DMA1_Channel2_IRQHandler(void) { + DMA1_HandleIrq(DMA1_IT_TC2, &rx_state, RECEIVING, RX_DONE); +} + +void configure_dma(DMA_Channel_TypeDef* tx_channel, uint32_t tx_addr, + DMA_Channel_TypeDef* rx_channel, uint32_t rx_addr, + int rx_circular, uint16_t len) { + // disable DMA channels + tx_channel->CFGR &= ~DMA_CFGR1_EN; + rx_channel->CFGR &= ~DMA_CFGR1_EN; + + // set memory addresses and transfer count + tx_channel->MADDR = tx_addr; + tx_channel->CNTR = len; + rx_channel->MADDR = rx_addr; + rx_channel->CNTR = len; + + // set or clear the circular mode for RX + rx_channel->CFGR = + (rx_channel->CFGR & ~DMA_CFGR1_CIRC) | (rx_circular ? DMA_CFGR1_CIRC : 0); + + // enable DMA channels + tx_channel->CFGR |= DMA_CFGR1_EN; + rx_channel->CFGR |= DMA_CFGR1_EN; +} + +void spidma_read_buffer(uint8_t* buf, uint16_t len) { + set_transfer_states(); + configure_dma(DMA1_Channel3, (uint32_t)&tx_dummy_byte, DMA1_Channel2, + (uint32_t)buf, 0, len); + + wait_for_transfer_complete(); + clear_transfer_states(); +} + +void spidma_write_buffer(uint8_t* buf, uint16_t len) { + set_transfer_states(); + configure_dma(DMA1_Channel3, (uint32_t)buf, DMA1_Channel2, (uint32_t)rx_dummy, + 1, len); + + wait_for_transfer_complete(); + clear_transfer_states(); +} + +uint8_t spi_transfer(uint8_t data) { + while (!(SPI1->STATR & SPI_STATR_TXE)); + SPI1->DATAR = data; + + while (!(SPI1->STATR & SPI_STATR_RXNE)); + return SPI1->DATAR; +} + +uint8_t spi_read_byte() { return spi_transfer(tx_dummy_byte); } + +void spi_write_byte(uint8_t byte) { spi_transfer(byte); } + +void spi_select(void) { + GPIOA->BCR = (1 << 4); // Set PA4 (CS) low +} + +void spi_unselect(void) { + GPIOA->BSHR = (1 << 4); // Set PA4 (CS) high +} + +void init_spidma(void) { + // Enable clock for GPIOA and SPI1 + RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1; + // Enable clock for DMA1 + RCC->AHBPCENR |= RCC_AHBPeriph_DMA1; + + // SPI1 Pin Configuration + // CS on PA4, 10MHz Output, open-drain + GPIOA->CFGLR &= ~(0xf << (4 * 4)); + GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD) << (4 * 4); + // SCK on PA5, 10MHz Output, alt func, push-pull + GPIOA->CFGLR &= ~(0xf << (4 * 5)); + GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 5); + // MOSI on PA7, 10MHz input, floating + GPIOA->CFGLR &= ~(0xf << (4 * 6)); + GPIOA->CFGLR |= (GPIO_CNF_IN_FLOATING) << (4 * 6); + // MISO on PA6, 10MHz Output, alt func, push-pull + GPIOA->CFGLR &= ~(0xf << (4 * 7)); + GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 7); + + // Reset and Configure SPI1 + SPI1->CTLR1 = 0; // Clear CTLR1 initially + + SPI1->CTLR1 = SPI_Mode_Master | // Master mode + SPI_Direction_2Lines_FullDuplex | // Full duplex + SPI_DataSize_8b | // 8-bit data frame format + SPI_CPOL_Low | // Clock polarity + SPI_CPHA_1Edge | // Clock phase + SPI_BaudRatePrescaler_8 | // Baud rate prescaler + SPI_NSS_Soft; // Software NSS management + + // Enable TX and RX DMA + SPI1->CTLR2 = SPI_CTLR2_TXDMAEN | SPI_CTLR2_RXDMAEN; + + SPI1->I2SCFGR &= SPI_Mode_Select; // Disable I2S mode + SPI1->CTLR1 |= SPI_CTLR1_SPE; // Enable SPI + + // DMA setup + DMA1_Channel3->PADDR = (uint32_t)&SPI1->DATAR; // TX Channel + DMA1_Channel3->CFGR = DMA_M2M_Disable | DMA_Priority_VeryHigh | + DMA_MemoryDataSize_Byte | DMA_PeripheralDataSize_Byte | + DMA_MemoryInc_Enable | DMA_PeripheralInc_Disable | + DMA_Mode_Normal | DMA_DIR_PeripheralDST | DMA_IT_TC; + + DMA1_Channel2->PADDR = (uint32_t)&SPI1->DATAR; // RX Channel + DMA1_Channel2->CFGR = DMA_M2M_Disable | DMA_Priority_VeryHigh | + DMA_MemoryDataSize_Byte | DMA_PeripheralDataSize_Byte | + DMA_MemoryInc_Enable | DMA_PeripheralInc_Disable | + DMA_Mode_Normal | DMA_DIR_PeripheralSRC | DMA_IT_TC; + + NVIC_EnableIRQ(DMA1_Channel3_IRQn); + NVIC_EnableIRQ(DMA1_Channel2_IRQn); +} diff --git a/src/uart.c b/src/uart.c index a3e2a01..33dfd9e 100644 --- a/src/uart.c +++ b/src/uart.c @@ -3,7 +3,7 @@ #include "ch32v003fun.h" // Write multiple chars to UART -int _write(int fd, const char *buf, int size) { +int _write(__attribute__((unused)) int fd, const char *buf, int size) { for (int i = 0; i < size; i++) { while (!(USART2->STATR & USART_FLAG_TC)); // Wait for transmission complete USART2->DATAR = *buf++; // Send character @@ -18,8 +18,8 @@ int putchar(int c) { return 1; } -void setup_uart(int uart_brr) { - // RCC->APB2PCENR |= RCC_APB2Periph_GPIOA; // Enable GPIOA on APB2 +void init_uart(int uart_brr) { + RCC->APB2PCENR |= RCC_APB2Periph_GPIOA; // Enable GPIOA on APB2 RCC->APB1PCENR |= RCC_APB1Periph_USART2; // Enable USART2 on APB1 GPIOA->CFGLR &= ~(0xf << (4 * 2)); // Clear bits for PA2 diff --git a/src/w5500.c b/src/w5500.c index d5c37f7..49f9d28 100644 --- a/src/w5500.c +++ b/src/w5500.c @@ -1,46 +1,123 @@ #include "w5500.h" +#include +#include +#include +#include +#include + #include "ch32v003fun.h" +// #include "spi.h" +#include "spi_dma.h" -static inline uint8_t SPI_is_RX_empty() { return SPI1->STATR & SPI_STATR_RXNE; } +// Definitions for socket indexes +#define DHCP_SOCKET 0 +#define DNS_SOCKET 1 +#define HTTP_SOCKET 2 -static inline void SPI_wait_not_busy() { - while ((SPI1->STATR & SPI_STATR_BSY) != 0); -} +// Global variables +volatile uint32_t count = 0; +volatile int ip_assigned = 0; -static inline uint8_t SPI_transfer(uint8_t data) { - while (!(SPI1->STATR & SPI_STATR_TXE)); - // SPI_wait_not_busy(); - SPI1->DATAR = data; +// Global buffers for DHCP and DNS +uint8_t dhcp_buffer[1024]; +uint8_t dns_buffer[1024]; - while (!(SPI1->STATR & SPI_STATR_RXNE)); - return SPI1->DATAR; -} - -void W5500_Select(void) { +void w5500_select(void) { GPIOA->BCR = (1 << 4); // Set PA4 (CS) low - // Delay_Ms(2); } -void W5500_Unselect(void) { +void w5500_unselect(void) { GPIOA->BSHR = (1 << 4); // Set PA4 (CS) high - // Delay_Ms(2); } -uint8_t W5500_ReadByte() { - return SPI_transfer(0xFF); // dummy byte to init read +// Function to handle IP assignment details +void handle_ip_assigned(void) { + printf("IP Assigned!\n"); + + wiz_NetInfo net_info; + getIPfromDHCP(net_info.ip); + getGWfromDHCP(net_info.gw); + getSNfromDHCP(net_info.sn); + + uint8_t dns[4]; + getDNSfromDHCP(dns); + + printf( + "IP: %d.%d.%d.%d\nGW: %d.%d.%d.%d\nNet: %d.%d.%d.%d\nDNS: " + "%d.%d.%d.%d\n", + net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3], + net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3], + net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3], dns[0], + dns[1], dns[2], dns[3]); + + wizchip_setnetinfo(&net_info); } -void W5500_WriteByte(uint8_t byte) { SPI_transfer(byte); } +// Callback functions +void callback_ip_assigned(void) { + printf("Callback: IP assigned! Leased time: %u sec\n", getDHCPLeasetime()); + ip_assigned = 1; +} -void W5500_ReadBuff(uint8_t* buffer, uint16_t len) { - for (uint16_t i = 0; i < len; i++) { - buffer[i] = W5500_ReadByte(); +void callback_ip_conflict(void) { printf("Callback: IP conflict!\n"); } + +void configure_network(void) { + printf("Starting network configuration...\n"); + + // Setup chip select and SPI callbacks + reg_wizchip_cs_cbfunc(spi_select, spi_unselect); + reg_wizchip_spi_cbfunc(spi_read_byte, spi_write_byte); + reg_wizchip_spiburst_cbfunc(spidma_read_buffer, spidma_write_buffer); + + uint8_t rx_tx_buff_sizes[] = {2, 2, 2, 2, 2, 2, 2, 2}; + wizchip_init(rx_tx_buff_sizes, rx_tx_buff_sizes); + + // Start DHCP process + wiz_NetInfo net_info = {.mac = {0xEA, 0x11, 0x22, 0x33, 0x44, 0xEA}, + .dhcp = NETINFO_DHCP}; + setSHAR(net_info.mac); + DHCP_init(DHCP_SOCKET, dhcp_buffer); + + // Register DHCP callbacks + reg_dhcp_cbfunc(callback_ip_assigned, callback_ip_assigned, + callback_ip_conflict); + + // Attempt to acquire an IP address using DHCP + const uint32_t max_attempts = 1e5; + for (uint32_t attempt = 0; !ip_assigned && attempt < max_attempts; + ++attempt) { + DHCP_run(); } + + if (!ip_assigned) { + printf("\r\nIP was not assigned :(\r\n"); + return; + } + + handle_ip_assigned(); } -void W5500_WriteBuff(uint8_t* buffer, uint16_t len) { - for (uint16_t i = 0; i < len; i++) { - W5500_WriteByte(buffer[i]); +void resolve_domain_name(const char* domain_name) { + printf("Resolving domain name \"%s\"...\n", domain_name); + + DNS_init(DNS_SOCKET, dns_buffer); + // cloudflare dns + uint8_t dns[] = {1, 1, 1, 1}; + uint8_t addr[4]; + int8_t res; + uint8_t retries = 0; + + while (retries < 3) { + Delay_Ms(250); + + res = DNS_run(dns, (uint8_t*)domain_name, addr); + if (res == 1) { + printf("Result: %d.%d.%d.%d\n", addr[0], addr[1], addr[2], addr[3]); + break; + } else { + printf("DNS_run() failed, res = %d. Retries: %u\n", res, retries); + } + retries++; } } \ No newline at end of file