feat: SPI DMA

Squashed commit of the following:

commit c3e1f696b4fbafb6dd30c6934e4c7c181562e055
Author: kuwoyuki <kuwoyuki@cock.li>
Date:   Sat Oct 12 20:43:12 2024 +0600

    chore: spi dma

commit d1e7df60be3e06ed85ce8639516e299085d3c72b
Author: kuwoyuki <kuwoyuki@cock.li>
Date:   Sat Oct 12 15:14:11 2024 +0600

    static dummies

commit 81682428b471f825e3350e37aa74c373b46d4fef
Author: kuwoyuki <kuwoyuki@cock.li>
Date:   Sat Oct 12 14:45:39 2024 +0600

    dma works?

commit 150c97a4b566712a502d8a2861a2dc0864324d61
Author: kuwoyuki <kuwoyuki@cock.li>
Date:   Sat Oct 12 02:07:39 2024 +0600

    dma?
This commit is contained in:
2024-10-12 20:43:38 +06:00
parent 259d63197e
commit ec9dcc76f7
11 changed files with 362 additions and 229 deletions

View File

@@ -7,6 +7,7 @@
"wizchip_conf.h": "c",
"socket.h": "c",
"type_traits": "c",
"compare": "c"
"compare": "c",
"uart.h": "c"
}
}

9
include/gpio.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef GPIO_H
#define GPIO_H
#include <stdint.h>
// Function prototype for initializing GPIO
void init_gpio(void);
#endif // GPIO_H

35
include/spi_dma.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -4,21 +4,27 @@
#include <stdint.h>
// 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

View File

@@ -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

13
src/gpio.c Normal file
View File

@@ -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));
}

View File

@@ -1,197 +1,26 @@
#include <DHCP/dhcp.h>
#include <DNS/dns.h>
#include <W5500/w5500.h>
#include <socket.h>
#include <stdio.h>
#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++;
}
}
init_uart(UART_BRR_APB1);
// init_spi();
init_spidma();
}

163
src/spi_dma.c Normal file
View File

@@ -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);
}

View File

@@ -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

View File

@@ -1,46 +1,123 @@
#include "w5500.h"
#include <DHCP/dhcp.h>
#include <DNS/dns.h>
#include <W5500/w5500.h>
#include <socket.h>
#include <stdio.h>
#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++;
}
}