From 480a4a1ca5da86b6eb928dbe9fc72619848d7fc2 Mon Sep 17 00:00:00 2001 From: kuwoyuki Date: Sun, 13 Oct 2024 05:32:44 +0600 Subject: [PATCH] dhcp attempts --- .vscode/settings.json | 9 ++- include/config.h | 25 +++++++ include/debug.h | 14 ++++ include/systick.h | 14 ++++ include/w5500.h | 38 +++++++---- lib/ioLibrary_Driver/DHCP/dhcp.h | 2 +- lib/ioLibrary_Driver/DNS/dns.h | 2 +- mosquitto.conf | 8 +++ src/funconfig.h | 15 +++-- src/main.c | 105 +++++++++++++++++++++++++---- src/systick.c | 50 ++++++++++++++ src/w5500.c | 110 +++++++++++++++++++++++-------- 12 files changed, 329 insertions(+), 63 deletions(-) create mode 100644 include/config.h create mode 100644 include/debug.h create mode 100644 include/systick.h create mode 100644 mosquitto.conf create mode 100644 src/systick.c diff --git a/.vscode/settings.json b/.vscode/settings.json index c3fa59a..fbd54d8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,13 @@ "socket.h": "c", "type_traits": "c", "compare": "c", - "uart.h": "c" + "uart.h": "c", + "mqttclient.h": "c", + "config.h": "c", + "dns.h": "c", + "spi_dma.h": "c", + "dhcp.h": "c", + "debug.h": "c", + "systick.h": "c" } } \ No newline at end of file diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..2d4625f --- /dev/null +++ b/include/config.h @@ -0,0 +1,25 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include + +#define DEBUG_MODE 1 + +#define DNS_RUN_INTERVAL_MS 100 + +// #define LOCAL_PORT 5000 + +// MQTT configuration +#define CLIENT_ID "ch32_node" + +#define MQTT_TARGET_IP {192, 168, 102, 147} +#define MQTT_TARGET_PORT 1883 + +#define MQTT_KEEP_ALIVE_INTERVAL 60 +#define MQTT_TX_BUFFER_SIZE 128 +#define MQTT_RX_BUFFER_SIZE 128 +#define MQTT_COMMAND_TIMEOUT_MS 1000 +#define SUB_TOPIC "listen/world" +#define PUB_TOPIC "hello/world" + +#endif // CONFIG_H diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..0eca7f9 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,14 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include + +#include "config.h" + +#ifdef DEBUG_MODE +#define DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define DEBUG_PRINT(fmt, ...) +#endif + +#endif // DEBUG_H diff --git a/include/systick.h b/include/systick.h new file mode 100644 index 0000000..9b8df87 --- /dev/null +++ b/include/systick.h @@ -0,0 +1,14 @@ +#ifndef SYSTICK_H +#define SYSTICK_H + +#include + +#define SYSTICK_ONE_MILLISECOND ((uint32_t)FUNCONF_SYSTEM_CORE_CLOCK / 1000) +#define millis() (systick_millis) + +void systick_init(void); + +// ms counter incremented by SysTick +extern volatile uint32_t systick_millis; + +#endif // SYSTICK_H diff --git a/include/w5500.h b/include/w5500.h index fbfa154..4e3fa84 100644 --- a/include/w5500.h +++ b/include/w5500.h @@ -1,25 +1,25 @@ #ifndef W5500_H #define W5500_H +#include #include -// Sets the CS pin low -void w5500_select(void); +// Definitions for socket indexes +#define DHCP_SOCKET 0 +#define DNS_SOCKET 1 +#define TCP_SOCKET 2 -// Sets the CS pin high -void w5500_unselect(void); +// Options structure for client identification +typedef struct { + char* clientid; + char* username; + char* password; + int qos; +} ch32_mqtt_options_t; -// Reads a byte via SPI -uint8_t w5500_read_byte(void); +extern volatile int ip_assigned; -// Writes a byte via SPI -void w5500_write_byte(uint8_t byte); - -// Reads multiple bytes via SPI -void w5500_read_buffer(uint8_t* buff, uint16_t len); - -// Writes multiple bytes via SPI -void w5500_write_buffer(uint8_t* buff, uint16_t len); +void handle_ip_assigned(void); // Initializes the W5500 chip void configure_network(void); @@ -27,4 +27,14 @@ void configure_network(void); // resolves a domain name void resolve_domain_name(const char* domain_name); +// init and connect the MQTT client +MQTTClient setup_mqtt_client(Network* network, ch32_mqtt_options_t* opts); + +int subscribe_to_topic(MQTTClient* client, const char* topic, enum QoS qos, + messageHandler message_callback); + +// publish a message to a topic +void publish_message(MQTTClient* client, const char* payload, + const char* topic); + #endif // W5500_H diff --git a/lib/ioLibrary_Driver/DHCP/dhcp.h b/lib/ioLibrary_Driver/DHCP/dhcp.h index 658703c..f5c36f6 100644 --- a/lib/ioLibrary_Driver/DHCP/dhcp.h +++ b/lib/ioLibrary_Driver/DHCP/dhcp.h @@ -57,7 +57,7 @@ extern "C" { * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ * @note If defined, it depends on */ -#define _DHCP_DEBUG_ +// #define _DHCP_DEBUG_ /* Retry to processing DHCP */ diff --git a/lib/ioLibrary_Driver/DNS/dns.h b/lib/ioLibrary_Driver/DNS/dns.h index 5e50c7b..c23edce 100644 --- a/lib/ioLibrary_Driver/DNS/dns.h +++ b/lib/ioLibrary_Driver/DNS/dns.h @@ -60,7 +60,7 @@ extern "C" { * @brief Define it for Debug & Monitor DNS processing. * @note If defined, it dependens on */ -#define _DNS_DEBUG_ +// #define _DNS_DEBUG_ #define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ /* diff --git a/mosquitto.conf b/mosquitto.conf new file mode 100644 index 0000000..6343c92 --- /dev/null +++ b/mosquitto.conf @@ -0,0 +1,8 @@ +# mosquitto.conf - Basic Mosquitto configuration for development purposes + +# Port to listen on (default is 1883) +listener 1883 + +# Allow anonymous access (no authentication) +allow_anonymous true + diff --git a/src/funconfig.h b/src/funconfig.h index 3502626..c4a704d 100644 --- a/src/funconfig.h +++ b/src/funconfig.h @@ -2,14 +2,15 @@ #define _FUNCONFIG_H // board definition file will already take care of this -//#define CH32V003 1 +// #define CH32V003 1 -#define FUNCONF_USE_HSI 0 // Use HSI Internal Oscillator -#define FUNCONF_USE_HSE 1 // Use External Oscillator -#define FUNCONF_SYSTEM_CORE_CLOCK 144000000 // System Core Clock in Hz +#define FUNCONF_USE_HSI 0 // Use HSI Internal Oscillator +#define FUNCONF_USE_HSE 1 // Use External Oscillator +#define FUNCONF_SYSTEM_CORE_CLOCK 144000000 // System Core Clock in Hz #define FUNCONF_USE_DEBUGPRINTF 0 -#define FUNCONF_USE_UARTPRINTF 0 -#define FUNCONF_UART_PRINTF_BAUD 115200 // Only used if FUNCONF_USE_UARTPRINTF is set. -#define FUNCONF_USE_CLK_SEC 0 +#define FUNCONF_USE_UARTPRINTF 0 +#define FUNCONF_UART_PRINTF_BAUD \ + 115200 // Only used if FUNCONF_USE_UARTPRINTF is set. +#define FUNCONF_USE_CLK_SEC 0 #endif diff --git a/src/main.c b/src/main.c index 2d8f486..bcddce9 100644 --- a/src/main.c +++ b/src/main.c @@ -1,26 +1,107 @@ - -#include +#include #include "ch32v003fun.h" +#include "debug.h" #include "gpio.h" +#include "socket.h" #include "spi_dma.h" +#include "systick.h" #include "uart.h" #include "w5500.h" -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_uart(UART_BRR_APB1); - // init_spi(); init_spidma(); + // systick_init(); +} + +// cb fn for when a message is received +void message_arrived(MessageData* md) { + if (md == NULL || md->message == NULL) { + DEBUG_PRINT("Error: MessageData is NULL.\n"); + return; + } + + MQTTMessage* message = md->message; + DEBUG_PRINT("MQTT Message Arrived:\n"); + DEBUG_PRINT("QoS: %d\n", message->qos); + DEBUG_PRINT("Retained: %d\n", message->retained); + DEBUG_PRINT("Duplicate: %d\n", message->dup); + DEBUG_PRINT("Message ID: %u\n", message->id); + DEBUG_PRINT("Payload Length: %u\n", (unsigned int)message->payloadlen); + + if (message->payload != NULL && message->payloadlen > 0) { + DEBUG_PRINT("Payload: "); + for (unsigned int i = 0; i < (unsigned int)message->payloadlen; ++i) { + putchar(((unsigned char*)message->payload)[i]); + } + DEBUG_PRINT("\n"); + } else { + DEBUG_PRINT("Payload: \n"); + } +} + +int main(void) { + init_system(); + configure_network(); + + // todo: fucking systick + // uint32_t dhcp_last_invocation = 0; + // const uint32_t DHCP_INTERVAL = 100; // DHCP processing interval in ms + + // // DHCP process blocking loop + // while (!ip_assigned) { + // if ((millis() - dhcp_last_invocation) >= DHCP_INTERVAL) { + // dhcp_last_invocation = millis(); + // DEBUG_PRINT("Running DHCP...\n"); + // DHCP_run(); // Attempt to obtain an IP address + // } + // } + + // 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) { + // DEBUG_PRINT("\r\nIP was not assigned :(\r\n"); + // return -1; + // } + // handle_ip_assigned(); + // ip_assigned = 0; + + resolve_domain_name("hye.su"); + + Network network; + ch32_mqtt_options_t opts = {CLIENT_ID, "", "", QOS0}; + + // Set up MQTT client + MQTTClient client = setup_mqtt_client(&network, &opts); + subscribe_to_topic(&client, SUB_TOPIC, QOS0, message_arrived); + + // Publish a message + publish_message(&client, "hi", PUB_TOPIC); + + while (1) { + // if ((millis() - dhcp_last_invocation) >= DHCP_INTERVAL) { + // dhcp_last_invocation = millis(); + // DHCP_run(); // Run the DHCP processing function + // } + MQTTYield(&client, 1000); // Keep the connection alive + + // if (ip_assigned) { + // handle_ip_assigned(); + // ip_assigned = 0; + // } + } + + MQTTDisconnect(&client); + close(TCP_SOCKET); + + return 0; } diff --git a/src/systick.c b/src/systick.c new file mode 100644 index 0000000..604ed2f --- /dev/null +++ b/src/systick.c @@ -0,0 +1,50 @@ +#include "systick.h" + +#include + +#include "ch32v003fun.h" + +// ms counter +volatile uint32_t systick_millis = 0; + +void systick_init(void) { + // Reset any pre-existing configuration + SysTick->CTLR = 0x0000; + + // Set the compare register to trigger once per millisecond + SysTick->CMP = SYSTICK_ONE_MILLISECOND - 1; + + // Reset the Count Register and variables + SysTick->CNT = 0x00000000; + systick_millis = 0x00000000; + + // Set the SysTick Configuration + // NOTE: By not setting SYSTICK_CTLR_STRE, we maintain compatibility with + // busywait delay funtions used by ch32v003_fun. + SysTick->CTLR |= SYSTICK_CTLR_STE | // Enable Counter + SYSTICK_CTLR_STIE | // Enable Interrupts + SYSTICK_CTLR_STCLK; // Set Clock Source to HCLK/1 + + // Enable the SysTick IRQ + NVIC_EnableIRQ(SysTicK_IRQn); +} + +/* + * SysTick ISR - must be lightweight to prevent the CPU from bogging down. + * Increments Compare Register and systick_millis when triggered (every 1ms) + * NOTE: the `__attribute__((interrupt))` attribute is very important + */ +void SysTick_Handler(void) __attribute__((interrupt)); +void SysTick_Handler(void) { + // Increment the Compare Register for the next trigger + // If more than this number of ticks elapse before the trigger is reset, + // you may miss your next interrupt trigger + // (Make sure the IQR is lightweight and CMP value is reasonable) + SysTick->CMP += SYSTICK_ONE_MILLISECOND; + + // Clear the trigger state for the next IRQ + SysTick->SR = 0x00000000; + + // Increment the milliseconds count + systick_millis++; +} \ No newline at end of file diff --git a/src/w5500.c b/src/w5500.c index 49f9d28..58b7c41 100644 --- a/src/w5500.c +++ b/src/w5500.c @@ -2,38 +2,26 @@ #include #include +#include #include #include -#include +#include #include "ch32v003fun.h" -// #include "spi.h" +#include "config.h" +#include "debug.h" #include "spi_dma.h" -// Definitions for socket indexes -#define DHCP_SOCKET 0 -#define DNS_SOCKET 1 -#define HTTP_SOCKET 2 - -// Global variables volatile uint32_t count = 0; volatile int ip_assigned = 0; // Global buffers for DHCP and DNS -uint8_t dhcp_buffer[1024]; -uint8_t dns_buffer[1024]; - -void w5500_select(void) { - GPIOA->BCR = (1 << 4); // Set PA4 (CS) low -} - -void w5500_unselect(void) { - GPIOA->BSHR = (1 << 4); // Set PA4 (CS) high -} +static uint8_t dhcp_buffer[512]; +static uint8_t dns_buffer[512]; // Function to handle IP assignment details void handle_ip_assigned(void) { - printf("IP Assigned!\n"); + DEBUG_PRINT("IP Assigned!\n"); wiz_NetInfo net_info; getIPfromDHCP(net_info.ip); @@ -43,7 +31,7 @@ void handle_ip_assigned(void) { uint8_t dns[4]; getDNSfromDHCP(dns); - printf( + DEBUG_PRINT( "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], @@ -56,14 +44,15 @@ void handle_ip_assigned(void) { // Callback functions void callback_ip_assigned(void) { - printf("Callback: IP assigned! Leased time: %u sec\n", getDHCPLeasetime()); + DEBUG_PRINT("Callback: IP assigned! Leased time: %lu sec\n", + getDHCPLeasetime()); ip_assigned = 1; } -void callback_ip_conflict(void) { printf("Callback: IP conflict!\n"); } +void callback_ip_conflict(void) { DEBUG_PRINT("Callback: IP conflict!\n"); } void configure_network(void) { - printf("Starting network configuration...\n"); + DEBUG_PRINT("Starting network configuration...\n"); // Setup chip select and SPI callbacks reg_wizchip_cs_cbfunc(spi_select, spi_unselect); @@ -85,21 +74,24 @@ void configure_network(void) { // Attempt to acquire an IP address using DHCP const uint32_t max_attempts = 1e5; + + // todo: run in a loop by a timer or sth for (uint32_t attempt = 0; !ip_assigned && attempt < max_attempts; ++attempt) { DHCP_run(); } if (!ip_assigned) { - printf("\r\nIP was not assigned :(\r\n"); + DEBUG_PRINT("\r\nIP was not assigned :(\r\n"); return; } handle_ip_assigned(); } +// todo: rm void resolve_domain_name(const char* domain_name) { - printf("Resolving domain name \"%s\"...\n", domain_name); + DEBUG_PRINT("Resolving domain name \"%s\"...\n", domain_name); DNS_init(DNS_SOCKET, dns_buffer); // cloudflare dns @@ -113,11 +105,75 @@ void resolve_domain_name(const char* domain_name) { 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]); + DEBUG_PRINT("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); + DEBUG_PRINT("DNS_run() failed, res = %d. Retries: %u\n", res, retries); } retries++; } +} + +MQTTClient setup_mqtt_client(Network* network, ch32_mqtt_options_t* opts) { + static unsigned char tx_buffer[MQTT_TX_BUFFER_SIZE]; + static unsigned char rx_buffer[MQTT_RX_BUFFER_SIZE]; + MQTTClient client; + int rc; + uint8_t target_ip[] = MQTT_TARGET_IP; + + NewNetwork(network, TCP_SOCKET); + if (ConnectNetwork(network, target_ip, MQTT_TARGET_PORT) != SOCK_OK) { + DEBUG_PRINT("Network connection failed.\n"); + return (MQTTClient){0}; // Return an empty client on failure + } + + // Initialize the MQTT client + MQTTClientInit(&client, network, MQTT_COMMAND_TIMEOUT_MS, tx_buffer, + sizeof(tx_buffer), rx_buffer, sizeof(rx_buffer)); + + // Setup MQTT connection data + MQTTPacket_connectData connect_data = MQTTPacket_connectData_initializer; + connect_data.willFlag = 0; + connect_data.MQTTVersion = 3; + connect_data.clientID.cstring = opts->clientid; + connect_data.username.cstring = opts->username; + connect_data.password.cstring = opts->password; + connect_data.keepAliveInterval = MQTT_KEEP_ALIVE_INTERVAL; + connect_data.cleansession = 1; + + // Connect to MQTT broker + rc = MQTTConnect(&client, &connect_data); + if (rc != 0) { + DEBUG_PRINT("Failed to connect: %d\n", rc); + return (MQTTClient){0}; // Return an empty client on failure + } + + return client; +} + +int subscribe_to_topic(MQTTClient* client, const char* topic, enum QoS qos, + messageHandler message_callback) { + int rc = MQTTSubscribe(client, topic, qos, message_callback); + if (rc != 0) { + DEBUG_PRINT("Failed to subscribe to %s: %d\n", topic, rc); + return rc; + } + return 0; // Success +} + +void publish_message(MQTTClient* client, const char* payload, + const char* topic) { + MQTTMessage message = {.qos = QOS0, + .retained = 0, + .dup = 0, + .payload = (void*)payload, + .payloadlen = strlen(payload) + + }; + + if (MQTTPublish(client, topic, &message) != 0) { + DEBUG_PRINT("Publish failed\n"); + } else { + DEBUG_PRINT("Message published successfully\n"); + } } \ No newline at end of file