diff --git a/bootloader-tftp/.settings/language.settings.xml b/bootloader-tftp/.settings/language.settings.xml index 988333f..cd32509 100644 --- a/bootloader-tftp/.settings/language.settings.xml +++ b/bootloader-tftp/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/bootloader-tftp/Makefile.GD32 b/bootloader-tftp/Makefile.GD32 index 500b196..f29c2d9 100644 --- a/bootloader-tftp/Makefile.GD32 +++ b/bootloader-tftp/Makefile.GD32 @@ -4,14 +4,16 @@ DEFINES+=DISABLE_FS DEFINES+=DISABLE_PRINTF_FLOAT DEFINES+=ENABLE_TFTP_SERVER -DEFINES+=CONFIG_REMOTECONFIG_MINIMUM DEFINES+=UDP_MAX_PORTS_ALLOWED=2 #DEFINES+=ENET_LINK_CHECK_REG_POLL +DEFINES+=CONFIG_REMOTECONFIG_MINIMUM DEFINES+=CONFIG_STORE_USE_ROM +DEFINES+=DEBUG_STACK + DEFINES+=NDEBUG SRCDIR=firmware lib diff --git a/bootloader-tftp/firmware/main.cpp b/bootloader-tftp/firmware/main.cpp index 8726d75..c987886 100644 --- a/bootloader-tftp/firmware/main.cpp +++ b/bootloader-tftp/firmware/main.cpp @@ -63,7 +63,10 @@ int main(void) { gpio_mode_set(KEY_BOOTLOADER_TFTP_GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, KEY_BOOTLOADER_TFTP_GPIO_PINx); #endif - if ((bkp_data_read(BKP_DATA_1) != 0xA5A5) && (gpio_input_bit_get(KEY_BOOTLOADER_TFTP_GPIOx, KEY_BOOTLOADER_TFTP_GPIO_PINx))) { + const auto isNotRemote = (bkp_data_read(BKP_DATA_1) != 0xA5A5); + const auto isNotKey = (gpio_input_bit_get(KEY_BOOTLOADER_TFTP_GPIOx, KEY_BOOTLOADER_TFTP_GPIO_PINx)); + + if (isNotRemote && isNotKey) { // https://developer.arm.com/documentation/ka001423/1-0 //1. Disable interrupt response. __disable_irq(); @@ -94,18 +97,15 @@ int main(void) { } Hardware hw; - Network nw; Display display(4); + ConfigStore configStore; + StoreNetwork storeNetwork; + Network nw(&storeNetwork); FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); - - fw.Print("Bootloader TFTP Server"); - FlashCodeInstall flashCodeInstall; - ConfigStore configStore; - StoreNetwork storeNetwork; - nw.SetNetworkStore(&storeNetwork); - nw.Init(&storeNetwork); + printf("Remote=%c, Key=%c\n", isNotRemote ? 'N' : 'Y', isNotKey ? 'N' : 'Y'); + fw.Print("Bootloader TFTP Server"); nw.Print(); hw.SetMode(hardware::ledblink::Mode::OFF_ON); @@ -121,6 +121,7 @@ int main(void) { remoteConfig.SetEnableReboot(true); + network::display_ip(); display.Printf(3, "Bootloader TFTP Srvr"); hw.SetMode(hardware::ledblink::Mode::FAST); diff --git a/bootloader-tftp/gd32f10x.size b/bootloader-tftp/gd32f10x.size new file mode 100644 index 0000000..026e0e9 --- /dev/null +++ b/bootloader-tftp/gd32f10x.size @@ -0,0 +1,12 @@ +build_gd32/main.elf : +section size addr +.vectors 0x150 0x8000000 +.text 0x5d0c 0x8000150 +.rodata 0xbc0 0x8005e5c +.stack 0x800 0x20000000 +.heap 0x400 0x20000800 +.data 0x70 0x20000c00 +.bss 0x16834 0x20000c70 +Total 0x1dec0 + + diff --git a/bootloader-tftp/include/software_version.h b/bootloader-tftp/include/software_version.h index 0870a5b..46a34e9 100644 --- a/bootloader-tftp/include/software_version.h +++ b/bootloader-tftp/include/software_version.h @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "1.7"; +constexpr char SOFTWARE_VERSION[] = "2.0"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/bootloader-tftp/lib/networkdisplay.cpp b/bootloader-tftp/lib/networkdisplay.cpp index a910557..dfe5e9e 100644 --- a/bootloader-tftp/lib/networkdisplay.cpp +++ b/bootloader-tftp/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,16 +33,26 @@ namespace network { static constexpr auto LINE_IP = 2U; +void display_emac_config() { + Display::Get()->ClearEndOfLine(); + Display::Get()->Printf(LINE_IP, "Ethernet config"); +} + void display_emac_start() { - Display::Get()->ClearLine(LINE_IP); - Display::Get()->PutString("Ethernet start"); + Display::Get()->ClearEndOfLine(); + Display::Get()->Printf(LINE_IP, "Ethernet start"); } void display_ip() { - Display::Get()->ClearLine(LINE_IP); + Display::Get()->ClearEndOfLine(); Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); } +void display_emac_status(const bool isLinkUp) { + Display::Get()->ClearEndOfLine(); + Display::Get()->Printf(LINE_IP, "Ethernet Link %s", isLinkUp ? "UP" : "DOWN"); +} + void display_netmask() { display_ip(); } @@ -54,7 +64,7 @@ void display_hostname() { } void display_emac_shutdown() { - Display::Get()->ClearLine(LINE_IP); + Display::Get()->ClearEndOfLine(); Display::Get()->PutString("Ethernet shutdown"); } diff --git a/firmware-template-gd32/Rules.mk b/firmware-template-gd32/Rules.mk index 8f635d0..1155a4f 100644 --- a/firmware-template-gd32/Rules.mk +++ b/firmware-template-gd32/Rules.mk @@ -9,15 +9,16 @@ AR = $(PREFIX)ar BOARD?=BOARD_GD32F107RC ENET_PHY?=DP83848 FAMILY?=gd32f10x +MCU?=gd32f107 FAMILY:=$(shell echo $(FAMILY) | tr A-Z a-z) FAMILY_UC=$(shell echo $(FAMILY) | tr a-w A-W) $(info $$FAMILY [${FAMILY}]) $(info $$FAMILY_UC [${FAMILY_UC}]) - + # Output -TARGET=gd32f107.bin +TARGET=$(MCU).bin LIST=$(FAMILY).list MAP=$(FAMILY).map BUILD=build_gd32/ @@ -34,7 +35,6 @@ LIBS+=c++ c gd32 $(info [${LIBS}]) DEFINES:=$(addprefix -D,$(DEFINES)) -DEFINES+=-DCONFIG_STORE_USE_ROM include ../firmware-template-gd32/Includes.mk @@ -118,7 +118,9 @@ lisdep: $(LIBDEP) $(LIBDEP): $(MAKE) -f Makefile.GD32 $(MAKECMDGOALS) 'FAMILY=${FAMILY}' 'BOARD=${BOARD}' 'PHY_TYPE=${ENET_PHY}' 'MAKE_FLAGS=$(DEFINES)' -C $@ +# # Build bin +# $(BUILD_DIRS) : mkdir -p $(BUILD_DIRS) @@ -129,9 +131,14 @@ $(BUILD)startup_$(FAMILY)_cl.o : $(FIRMWARE_DIR)/startup_$(FAMILY)_cl.S $(BUILD)main.elf: Makefile.GD32 $(LINKER) $(BUILD)startup_$(FAMILY)_cl.o $(OBJECTS) $(LIBDEP) $(LD) $(BUILD)startup_$(FAMILY)_cl.o $(OBJECTS) -Map $(MAP) -T $(LINKER) $(LDOPS) -o $(BUILD)main.elf $(LIBGD32) $(LDLIBS) $(PLATFORM_LIBGCC) -lgcc $(PREFIX)objdump -D $(BUILD)main.elf | $(PREFIX)c++filt > $(LIST) - $(PREFIX)size -A -x $(BUILD)main.elf + $(PREFIX)size -A -x $(BUILD)main.elf > $(FAMILY).size + $(MAKE) -f Makefile.GD32 calculate_unused_ram SIZE_FILE=$(FAMILY).size LINKER_SCRIPT=$(LINKER) $(TARGET) : $(BUILD)main.elf $(PREFIX)objcopy $(BUILD)main.elf -O binary $(TARGET) -$(foreach bdir,$(SRCDIR),$(eval $(call compile-objects,$(bdir)))) \ No newline at end of file +$(foreach bdir,$(SRCDIR),$(eval $(call compile-objects,$(bdir)))) + +.PHONY: calculate_unused_ram +calculate_unused_ram: $(FAMILY).size $(LINKER) + @$(FIRMWARE_DIR)/calculate_unused_ram.sh $(FAMILY).size $(LINKER) diff --git a/firmware-template-gd32/calculate_unused_ram.sh b/firmware-template-gd32/calculate_unused_ram.sh new file mode 100755 index 0000000..f2c1576 --- /dev/null +++ b/firmware-template-gd32/calculate_unused_ram.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +if [ $# -lt 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +size_file="$1" +linker_script="$2" + +used_stack=$(grep ".stack" "$size_file" | awk '{print $2}') +used_heap=$(grep ".heap" "$size_file" | awk '{print $2}') +used_data=$(grep '.data' "$size_file" | tail -n 1 | awk '{print $2}') +used_bss=$(grep ".bss" "$size_file" | awk '{print $2}') + +total_ram=$(grep "RAM (xrw)" "$linker_script" | awk '{print $NF}' | sed 's/K$//' | awk '{printf "%d", $0 * 1024}') +unused_ram=$(( $(echo $total_ram) - $(echo $used_stack) - $(echo $used_heap) - $(echo $used_data) - $(echo $used_bss) )) + +cat $1 +echo "RAM $total_ram bytes, Unused: $unused_ram bytes" +echo \ No newline at end of file diff --git a/firmware-template-gd32/gd32f107rc_flash.ld b/firmware-template-gd32/gd32f107rc_flash.ld index 82d600d..8f557b6 100644 --- a/firmware-template-gd32/gd32f107rc_flash.ld +++ b/firmware-template-gd32/gd32f107rc_flash.ld @@ -9,7 +9,7 @@ ENTRY(Reset_Handler) SECTIONS { __heap_size = DEFINED(__heap_size) ? __heap_size : 1K; - __stack_size = DEFINED(__stack_size) ? __stack_size : 1K; + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; .vectors : { @@ -30,10 +30,8 @@ SECTIONS *(.glue_7) *(.glue_7t) *(.eh_frame) - KEEP (*(.init)) KEEP (*(.fini)) - . = ALIGN(4); _etext = .; } >FLASH @@ -46,19 +44,6 @@ SECTIONS . = ALIGN(4); } >FLASH - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } >FLASH - - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .ARM.attributes : { *(.ARM.attributes) } > FLASH - .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); @@ -82,6 +67,24 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH + .stack : + { + . = ALIGN(4); + PROVIDE( stack_low = . ); + . = __stack_size; + PROVIDE( _sp = . ); + . = ALIGN(4); + } >RAM AT>RAM + + .heap : + { + . = ALIGN(4); + heap_low = .; + . = . + __heap_size; + heap_top = .; + . = ALIGN(4); + } >RAM AT>RAM + _sidata = LOADADDR(.data); .data : { @@ -109,28 +112,10 @@ SECTIONS . = ALIGN(8); PROVIDE ( end = _ebss ); PROVIDE ( _end = _ebss ); - - .heap ORIGIN(RAM) + LENGTH(RAM) - __stack_size - __heap_size : - { - . = ALIGN(4); - heap_low = .; - . = . + __heap_size; - heap_top = .; - . = ALIGN(4); - } >RAM AT>RAM - - .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : - { - . = ALIGN(4); - PROVIDE( _heap_end = . ); - . = __stack_size; - PROVIDE( _sp = . ); - . = ALIGN(4); - } >RAM AT>RAM /DISCARD/ : { - *(*.ARM.attributes) + *(*.ARM.*) *(*.comment) *(*.debug*) } diff --git a/firmware-template-gd32/startup_gd32f10x_cl.S b/firmware-template-gd32/startup_gd32f10x_cl.S index 1d6fc08..039ff96 100644 --- a/firmware-template-gd32/startup_gd32f10x_cl.S +++ b/firmware-template-gd32/startup_gd32f10x_cl.S @@ -16,9 +16,6 @@ .type Reset_Handler, %function Reset_Handler: - ldr r0, =_sp - mov sp, r0 - movs r1, #0 b DataInit @@ -44,6 +41,9 @@ Zerobss: ldr r3, = _ebss cmp r2, r3 bcc FillZerobss +#if defined (DEBUG_STACK) + bl stack_debug_init +#endif bl SystemInit bl main bx lr diff --git a/include/.settings/org.eclipse.core.resources.prefs b/include/.settings/org.eclipse.core.resources.prefs old mode 100644 new mode 100755 diff --git a/include/README.md b/include/README.md new file mode 100755 index 0000000..bf3a51f --- /dev/null +++ b/include/README.md @@ -0,0 +1,72 @@ +A freestanding implementation has an implementation-defined set of headers. The following headers are provided by the C/C++ standard: + +#c11 +> 4 Conformance +> +> 6 ... A conforming freestanding implementation shall accept any strictly conforming program that does not use complex types and in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and <stdint.h>. + +Reference: [https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf) + +#c++11 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Types<cstddef>
Implementation properties<limits>
<cfloat>
<climits>
Integer types<cstdint>
Start and termination<cstdlib> (partial)
Dynamic memory management<new>
Type identification<typeinfo>
Exception handling<exception>
Initializer lists<initializer_list>
Other runtime support<cstdarg>
Type traits<type_traits>
Atomics<atomic>
+ +Reference: [https://en.cppreference.com/w/cpp/freestanding](https://en.cppreference.com/w/cpp/freestanding) + +[http://www.gd32-dmx.org](http://www.gd32-dmx.org) + +[http://www.orangepi-dmx.org](http://www.orangepi-dmx.org) + + diff --git a/include/algorithm b/include/algorithm old mode 100644 new mode 100755 diff --git a/include/climits b/include/cmath old mode 100644 new mode 100755 similarity index 87% rename from include/climits rename to include/cmath index 807e30b..9236889 --- a/include/climits +++ b/include/cmath @@ -1,8 +1,8 @@ /** - * @file climits + * @file cmath * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,11 @@ * THE SOFTWARE. */ -#ifndef CLIMITS_ -#define CLIMITS_ +#ifndef CMATH_ +#define CMATH_ #ifdef __cplusplus -# include +# include #endif -#endif /* CLIMITS_ */ +#endif /* CMATH_ */ diff --git a/include/ctype.h b/include/ctype.h index b5a30b1..09b7154 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -2,7 +2,7 @@ * @file ctype.h * */ -/* Copyright (C) 2017 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,38 +30,42 @@ extern "C" { #endif -inline static int isdigit(int c) { +inline int isdigit(int c) { return (c >= (int) '0' && c <= (int) '9') ? 1 : 0; } -inline static int isxdigit(int c) { +inline int isxdigit(int c) { return ((isdigit(c) != 0) || (((unsigned) c | 32) - (int) 'a' < 6)) ? 1 : 0; } -inline static int isprint(int c) { +inline int isprint(int c) { return ((c >= (int) ' ' && c <= (int) '~')) ? 1 : 0; } -inline static int isupper(int c) { +inline int isupper(int c) { return (c >= (int) 'A' && c <= (int) 'Z') ? 1 : 0; } -inline static int islower(int c) { +inline int islower(int c) { return (c >= (int) 'a' && c <= (int) 'z') ? 1 : 0; } -inline static int isalpha(int c) { +inline int isalpha(int c) { return ((isupper(c) != 0) || (islower(c) != 0)) ? 1 : 0; } -inline static int tolower(int c) { +inline int tolower(int c) { return ((isupper(c) != 0) ? (c + 32) : c); } -inline static int toupper(int c) { +inline int toupper(int c) { return ((islower(c) != 0) ? (c - 32) : c); } +inline int isspace(int c) { + return (c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || c == ' ' ? 1 : 0); +} + #ifdef __cplusplus } #endif diff --git a/include/stdlib.h b/include/stdlib.h index 2b1c274..4b12f45 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -2,7 +2,7 @@ * @file stdlib.h * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,13 +34,14 @@ extern "C" { #endif +extern int atoi(const char *nptr); + extern void *malloc(size_t size); extern void free(void *ptr); extern void *calloc(size_t nmemb, size_t size); extern void *realloc(void *ptr, size_t size); -/* Return the absolute value of I. */ -inline static int abs(int i) { +inline int abs(int i) { return i < 0 ? -i : i; } diff --git a/include/string.h b/include/string.h index b01dd39..fdbdbb4 100644 --- a/include/string.h +++ b/include/string.h @@ -2,7 +2,7 @@ * @file string.h * */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,7 +36,7 @@ extern "C" { extern char *strerror(int errnum); extern char *strtok(char *str, const char *delim); -inline static int memcmp(const void *s1, const void *s2, size_t n) { +inline int memcmp(const void *s1, const void *s2, size_t n) { unsigned char u1, u2; unsigned char *t1, *t2; @@ -54,7 +54,7 @@ inline static int memcmp(const void *s1, const void *s2, size_t n) { return 0; } -inline static void* memcpy(void *__restrict__ dest, const void *__restrict__ src, size_t n) { +inline void *memcpy(void *__restrict__ dest, const void *__restrict__ src, size_t n) { char *dp = (char *) dest; const char *sp = (const char *) src; @@ -65,11 +65,11 @@ inline static void* memcpy(void *__restrict__ dest, const void *__restrict__ src return dest; } -inline static void* mempcpy(void *__restrict__ dest, const void *__restrict__ src, size_t n) { +inline void *mempcpy(void *__restrict__ dest, const void *__restrict__ src, size_t n) { return (char *)memcpy (dest, src, n) + n; } -inline static void *memmove(/*@only@*/void *dst, const void *src, size_t n) { +inline void *memmove(void *dst, const void *src, size_t n) { char *dp = (char *) dst; const char *sp = (const char *) src; @@ -88,7 +88,7 @@ inline static void *memmove(/*@only@*/void *dst, const void *src, size_t n) { return dst; } -inline static void *memset(/*@only@*/void *dest, int c, size_t n) { +inline void *memset(void *dest, int c, size_t n) { char *dp = (char *) dest; while (n-- != (size_t) 0) { @@ -98,7 +98,7 @@ inline static void *memset(/*@only@*/void *dest, int c, size_t n) { return dest; } -inline static size_t strlen(const char *s) { +inline size_t strlen(const char *s) { const char *p = s; while (*s != (char) 0) { @@ -108,7 +108,7 @@ inline static size_t strlen(const char *s) { return (size_t) (s - p); } -inline static char *strcpy(char * __restrict__ s1, const char * __restrict__ s2) { +inline char *strcpy(char * __restrict__ s1, const char * __restrict__ s2) { char *s = s1; while ((*s++ = *s2++) != '\0') @@ -116,7 +116,7 @@ inline static char *strcpy(char * __restrict__ s1, const char * __restrict__ s2) return s1; } -inline static char *strncpy(char * __restrict__ s1, const char * __restrict__ s2, size_t n) { +inline char *strncpy(char * __restrict__ s1, const char * __restrict__ s2, size_t n) { char *s = s1; while (n > 0 && *s2 != '\0') { @@ -132,7 +132,7 @@ inline static char *strncpy(char * __restrict__ s1, const char * __restrict__ s2 return s1; } -inline static int strcmp(const char *s1, const char *s2) { +inline int strcmp(const char *s1, const char *s2) { unsigned char *p1 = (unsigned char *) s1; unsigned char *p2 = (unsigned char *) s2; @@ -145,7 +145,7 @@ inline static int strcmp(const char *s1, const char *s2) { return (*p1 - *p2); } -inline static int strncmp(const char *s1, const char *s2, size_t n) { +inline int strncmp(const char *s1, const char *s2, size_t n) { unsigned char *p1 = (unsigned char *) s1; unsigned char *p2 = (unsigned char *) s2; @@ -160,7 +160,7 @@ inline static int strncmp(const char *s1, const char *s2, size_t n) { return 0; } -inline static int strcasecmp(const char *s1, const char *s2) { +inline int strcasecmp(const char *s1, const char *s2) { unsigned char *p1 = (unsigned char *) s1; unsigned char *p2 = (unsigned char *) s2; @@ -173,7 +173,7 @@ inline static int strcasecmp(const char *s1, const char *s2) { return (tolower((int) *p1) - tolower((int) *p2)); } -inline static int strncasecmp(const char *s1, const char *s2, size_t n) { +inline int strncasecmp(const char *s1, const char *s2, size_t n) { unsigned char *p1 = (unsigned char *) s1; unsigned char *p2 = (unsigned char *) s2; @@ -188,7 +188,7 @@ inline static int strncasecmp(const char *s1, const char *s2, size_t n) { return 0; } -inline static char *strcat(char *s1, const char *s2) { +inline char *strcat(char *s1, const char *s2) { strcpy(s1 + strlen(s1), s2); return s1; } diff --git a/lib-c++/.settings/language.settings.xml b/lib-c++/.settings/language.settings.xml index c7a065e..d19e91f 100644 --- a/lib-c++/.settings/language.settings.xml +++ b/lib-c++/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-c/.settings/language.settings.xml b/lib-c/.settings/language.settings.xml index 8119740..4ffdec6 100644 --- a/lib-c/.settings/language.settings.xml +++ b/lib-c/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-c/src/malloc.c b/lib-c/src/malloc.c index 0224ab8..e6af3cb 100644 --- a/lib-c/src/malloc.c +++ b/lib-c/src/malloc.c @@ -8,7 +8,7 @@ * Copyright (C) 2014-2016 R. Stange * https://github.com/rsta2/circle/blob/master/lib/alloc.cpp */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,9 +65,7 @@ struct block_bucket { struct block_header *free_list; }; -#include "../lib-flashcodeinstall/include/flashcodeinstall.h" - -static struct block_bucket s_block_bucket[] __attribute__((aligned(4))) = {{0x20, 0}, {0x40, 0}, {0x60, 0}, {0x80,0}, {0x100,0}, {0x140,0}, {0x180,0}, {0x200,0}, {0x300,0}, {0x400,0}, {FIRMWARE_MAX_SIZE,0}, {0,0}}; +static struct block_bucket s_block_bucket[] __attribute__((aligned(4))) = {{0x10, 0}, {0x20, 0}, {0x40, 0}, {0x60, 0}, {0x80,0}, {0x100,0}, {0x140,0}, {0x180,0}, {0x200,0}, {0x300,0}, {0x400,0}, {0x500,0}, {0,0}}; size_t get_allocated(void *p) { if (p == 0) { @@ -205,7 +203,7 @@ void *calloc(size_t n, size_t size) { *dst8++ = (uint8_t) 0; } - assert(((void *)dst8 - (void *)p) == (n * size)); + assert((size_t)((void *)dst8 - (void *)p) == (n * size)); return (void *) p; } @@ -252,7 +250,7 @@ void *realloc(void *ptr, size_t size) { *dst8++ = *src8++; } - assert(((void *)dst8 - (void *)newblk) == size); + assert((size_t)((void *)dst8 - (void *)newblk) == size); free(ptr); } diff --git a/lib-configstore/.settings/language.settings.xml b/lib-configstore/.settings/language.settings.xml index 8f77e88..74bbff4 100755 --- a/lib-configstore/.settings/language.settings.xml +++ b/lib-configstore/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-configstore/Rules.mk b/lib-configstore/Rules.mk index 240584a..31498ee 100644 --- a/lib-configstore/Rules.mk +++ b/lib-configstore/Rules.mk @@ -1,7 +1,7 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) EXTRA_INCLUDES =../lib-flashcode/include ../lib-flash/include -EXTRA_INCLUDES+=../lib-hal/include ../lib-network/include ../lib-properties/include ../lib-lightset/include +EXTRA_INCLUDES+=../lib-hal/include ../lib-properties/include ../lib-lightset/include ../lib-network/include ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONFIG_STORE_USE_FILE,$(MAKE_FLAGS))) @@ -25,13 +25,34 @@ ifneq ($(MAKE_FLAGS),) endif RDM= + + ifneq (,$(findstring ESP8266,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/network + EXTRA_INCLUDES+=../lib-network/include + # Remote config is not used with ESP8266 + EXTRA_INCLUDES+=../lib-remoteconfig/include + endif + + ifeq (,$(findstring NO_EMAC,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/network + EXTRA_INCLUDES+=../lib-network/include + EXTRA_INCLUDES+=../lib-remoteconfig/include + endif + + ifeq ($(findstring DISPLAY_UDF,$(MAKE_FLAGS)), DISPLAY_UDF) + EXTRA_SRCDIR+=src/displayudf + EXTRA_INCLUDES+=../lib-displayudf/include + endif ifeq ($(findstring NODE_ARTNET,$(MAKE_FLAGS)), NODE_ARTNET) EXTRA_SRCDIR+=src/artnet - EXTRA_INCLUDES+=../lib-artnet/include ../lib-artnet4/include + EXTRA_INCLUDES+=../lib-artnet/include EXTRA_SRCDIR+=src/rdm RDM=1 EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include + ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) + EXTRA_INCLUDES+=../lib-e131/include + endif endif ifeq ($(findstring NODE_E131,$(MAKE_FLAGS)), NODE_E131) @@ -59,16 +80,36 @@ ifneq ($(MAKE_FLAGS),) EXTRA_INCLUDES+=../lib-oscclient/include endif + ifeq ($(findstring OUTPUT_DMX_SEND,$(MAKE_FLAGS)),OUTPUT_DMX_SEND) + EXTRA_SRCDIR+=src/dmx + EXTRA_INCLUDES+=../lib-dmx/include + endif + ifeq ($(findstring OUTPUT_DMX_PIXEL,$(MAKE_FLAGS)), OUTPUT_DMX_PIXEL) EXTRA_SRCDIR+=src/pixel EXTRA_INCLUDES+=../lib-ws28xxdmx/include ../lib-ws28xx/include endif + + ifeq ($(findstring OUTPUT_DMX_SHOWFILE,$(MAKE_FLAGS)), OUTPUT_DMX_SHOWFILE) + EXTRA_SRCDIR+=src/showfile + EXTRA_INCLUDES+=../lib-showfile/include + endif + + ifeq ($(findstring OUTPUT_DMX_SERIAL,$(MAKE_FLAGS)), OUTPUT_DMX_SERIAL) + EXTRA_SRCDIR+=src/dmxserial + EXTRA_INCLUDES+=../lib-dmxserial/include + endif ifeq ($(findstring OUTPUT_DMX_STEPPER,$(MAKE_FLAGS)), OUTPUT_DMX_STEPPER) EXTRA_SRCDIR+=src/stepper EXTRA_INCLUDES+=../lib-l6470dmx/include ../lib-l6470/include endif + ifeq ($(findstring OUTPUT_DMX_TLC59711,$(MAKE_FLAGS)), OUTPUT_DMX_TLC59711) + EXTRA_SRCDIR+=src/tlc59711 + EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include + endif + ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) ifdef RDM else @@ -101,7 +142,7 @@ ifneq ($(MAKE_FLAGS),) endif else EXTRA_SRCDIR+=src/artnet - EXTRA_INCLUDES+=../lib-artnet/include ../lib-artnet4/include + EXTRA_INCLUDES+=../lib-artnet/include EXTRA_SRCDIR+=src/e131 EXTRA_INCLUDES+=../lib-e131/include EXTRA_SRCDIR+=src/node @@ -115,21 +156,20 @@ else EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include EXTRA_SRCDIR+=src/stepper EXTRA_INCLUDES+=../lib-l6470dmx/include ../lib-l6470/include + EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include + DEFINES+=ARTNET_VERSION=4 DEFINES+=LIGHTSET_PORTS=4 DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 DEFINES+=CONFIG_DDPDISPLAY_MAX_PORTS=8 endif EXTRA_INCLUDES+=../lib-displayudf/include ../lib-display/include -EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include EXTRA_INCLUDES+=../lib-dmxsend/include -EXTRA_INCLUDES+=../lib-dmxserial/include EXTRA_INCLUDES+=../lib-dmxmonitor/include EXTRA_INCLUDES+=../lib-dmxreceiver/include ../lib-dmx/include EXTRA_INCLUDES+=../lib-oscserver/include EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include -EXTRA_INCLUDES+=../lib-remoteconfig/include EXTRA_INCLUDES+=../lib-spiflashinstall/include EXTRA_INCLUDES+=../lib-device/include -EXTRA_INCLUDES+=../lib-midi/include ../lib-showfile/include \ No newline at end of file +EXTRA_INCLUDES+=../lib-midi/include \ No newline at end of file diff --git a/lib-configstore/include/configstore.h b/lib-configstore/include/configstore.h index c95372e..73b23ae 100755 --- a/lib-configstore/include/configstore.h +++ b/lib-configstore/include/configstore.h @@ -2,7 +2,7 @@ * @file configstore.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,10 +33,8 @@ namespace configstore { enum class Store { NETWORK, - ARTNET, DMXSEND, WS28XXDMX, - E131, LTC, MIDI, LTCETC, @@ -81,25 +79,26 @@ class ConfigStore: StoreDevice { return s_bHaveFlashChip; } - void Update(configstore::Store tStore, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList = 0, uint32_t nOffsetSetList = 0); - void Update(configstore::Store tStore, const void *pData, uint32_t nDataLength) { - Update(tStore, 0, pData, nDataLength); + void Update(configstore::Store store, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList = 0, uint32_t nOffsetSetList = 0); + void Update(configstore::Store store, const void *pData, uint32_t nDataLength) { + Update(store, 0, pData, nDataLength); } - void Copy(configstore::Store tStore, void *pData, uint32_t nDataLength, uint32_t nOffset = 0, bool isSetList = true); - void CopyTo(configstore::Store tStore, void *pData, uint32_t& nDataLength); - void ResetSetList(configstore::Store tStore); + void Copy(const configstore::Store store, void *pData, uint32_t nDataLength, uint32_t nOffset = 0); + + void ResetSetList(configstore::Store store); bool Flash(); void Dump(); + void Delay(); + static ConfigStore *Get() { return s_pThis; } private: - bool Init(); uint32_t GetStoreOffset(configstore::Store tStore); private: @@ -108,7 +107,6 @@ class ConfigStore: StoreDevice { }; static bool s_bHaveFlashChip; - static bool s_bIsNew; static configstore::State s_State; static uint32_t s_nStartAddress; diff --git a/lib-configstore/src/config_delay.cpp b/lib-configstore/src/config_delay.cpp new file mode 100755 index 0000000..1ff2fb4 --- /dev/null +++ b/lib-configstore/src/config_delay.cpp @@ -0,0 +1,13 @@ +/* + * config_delay.cpp + */ + +#include "configstore.h" + +namespace configstore { + void delay() { + ConfigStore::Get()->Delay(); + } +} // namespace configstore + + diff --git a/lib-configstore/src/configstore.cpp b/lib-configstore/src/configstore.cpp index bb4d1a3..5e325d4 100644 --- a/lib-configstore/src/configstore.cpp +++ b/lib-configstore/src/configstore.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include @@ -37,15 +38,14 @@ using namespace configstore; -static constexpr uint8_t s_aSignature[] = {'A', 'v', 'V', 0x10}; +static constexpr uint8_t s_aSignature[] = {'A', 'v', 'V', 0x01}; static constexpr auto OFFSET_STORES = ((((sizeof(s_aSignature) + 15) / 16) * 16) + 16); // +16 is reserved for future use -static constexpr uint32_t s_aStorSize[static_cast(Store::LAST)] = {96, 144, 32, 64, 96, 64, 32, 32, 480, 64, 32, 96, 48, 32, 944, 48, 64, 32, 96, 32, 1024, 32, 32, 64, 96, 32, 32, 192}; +static constexpr uint32_t s_aStorSize[static_cast(Store::LAST)] = {96, 32, 64, 64, 32, 32, 480, 64, 32, 96, 48, 32, 944, 48, 64, 32, 96, 32, 1024, 32, 32, 64, 96, 32, 32, 320}; #ifndef NDEBUG -static constexpr char s_aStoreName[static_cast(Store::LAST)][16] = {"Network", "Art-Net", "DMX", "Pixel", "E1.31", "LTC", "MIDI", "LTC ETC", "OSC Server", "TLC59711", "USB Pro", "RDM Device", "RConfig", "TCNet", "OSC Client", "Display", "LTC Display", "Monitor", "SparkFun", "Slush", "Motors", "Show", "Serial", "RDM Sensors", "RDM SubDevices", "GPS", "RGB Panel", "Node"}; +static constexpr char s_aStoreName[static_cast(Store::LAST)][16] = {"Network", "DMX", "Pixel", "LTC", "MIDI", "LTC ETC", "OSC Server", "TLC59711", "USB Pro", "RDM Device", "RConfig", "TCNet", "OSC Client", "Display", "LTC Display", "Monitor", "SparkFun", "Slush", "Motors", "Show", "Serial", "RDM Sensors", "RDM SubDevices", "GPS", "RGB Panel", "Node"}; #endif bool ConfigStore::s_bHaveFlashChip; -bool ConfigStore::s_bIsNew; State ConfigStore::s_State; uint32_t ConfigStore::s_nStartAddress; uint32_t ConfigStore::s_nSpiFlashStoreSize; @@ -60,54 +60,29 @@ ConfigStore::ConfigStore() { assert(s_pThis == nullptr); s_pThis = this; - if (StoreDevice::IsDetected()) { - s_bHaveFlashChip = Init(); - } - - if (s_bHaveFlashChip) { - s_nSpiFlashStoreSize = OFFSET_STORES; - - for (uint32_t j = 0; j < static_cast(Store::LAST); j++) { - s_nSpiFlashStoreSize += s_aStorSize[j]; - } + s_bHaveFlashChip = StoreDevice::IsDetected(); - DEBUG_PRINTF("OFFSET_STORES=%d, m_nSpiFlashStoreSize=%d", static_cast(OFFSET_STORES), s_nSpiFlashStoreSize); + assert(FlashStore::SIZE <= StoreDevice::GetSize()); - assert(s_nSpiFlashStoreSize <= FlashStore::SIZE); - } - - DEBUG_EXIT -} + const auto nEraseSize = StoreDevice::GetSectorSize(); + assert(nEraseSize <= FlashStore::SIZE); -bool ConfigStore::Init() { - DEBUG_ENTRY + const auto nSectors = FlashStore::SIZE / nEraseSize; - const auto nEraseSize = StoreDevice::GetSectorSize(); - assert(FlashStore::SIZE == nEraseSize); + DEBUG_PRINTF("KB_NEEDED=%u, nEraseSize=%u, nSectors=%u", FlashStore::SIZE, nEraseSize, nSectors); - if (FlashStore::SIZE != nEraseSize) { - DEBUG_EXIT - return false; - } + assert((nSectors * nEraseSize) <= StoreDevice::GetSize()); - s_nStartAddress = StoreDevice::GetSize() - nEraseSize; + s_nStartAddress = StoreDevice::GetSize() - (nSectors * nEraseSize); -#if !defined (GD32F4XX) //FIXME Remove #if !defined (GD32F4XX) -# if !defined (CONFIG_STORE_USE_I2C) - assert(s_nStartAddress != 0); -# endif - assert(!(s_nStartAddress % nEraseSize)); -#endif + DEBUG_PRINTF("s_nStartAddress=%p", reinterpret_cast(s_nStartAddress)); - if (s_nStartAddress % nEraseSize) { - DEBUG_EXIT - return false; + if (s_bHaveFlashChip) { + storedevice::result result; + StoreDevice::Read(s_nStartAddress, FlashStore::SIZE, reinterpret_cast(&s_SpiFlashData), result); + assert(result == storedevice::result::OK); } - storedevice::result result; - StoreDevice::Read(s_nStartAddress, FlashStore::SIZE, reinterpret_cast(&s_SpiFlashData), result); - assert(result == storedevice::result::OK); - bool bSignatureOK = true; for (uint32_t i = 0; i < sizeof(s_aSignature); i++) { @@ -119,54 +94,32 @@ bool ConfigStore::Init() { if (!bSignatureOK) { DEBUG_PUTS("No signature"); - - s_bIsNew = true; - - // Clear nSetList - for (uint32_t j = 0; j < static_cast(Store::LAST); j++) { - const auto nOffset = GetStoreOffset(static_cast(j)); - auto k = nOffset; - s_SpiFlashData[k++] = 0x00; - s_SpiFlashData[k++] = 0x00; - s_SpiFlashData[k++] = 0x00; - s_SpiFlashData[k++] = 0x00; - - // Clear rest of data - for (; k < nOffset + s_aStorSize[j]; k++) { - s_SpiFlashData[k] = 0xFF; - } - } - + memset(&s_SpiFlashData[OFFSET_STORES], 0, FlashStore::SIZE - OFFSET_STORES); s_State = State::CHANGED; - - DEBUG_EXIT - return true; } + s_nSpiFlashStoreSize = OFFSET_STORES; + for (uint32_t j = 0; j < static_cast(Store::LAST); j++) { - auto *pbSetList = &s_SpiFlashData[GetStoreOffset(static_cast(j))]; - if ((pbSetList[0] == 0xFF) && (pbSetList[1] == 0xFF) && (pbSetList[2] == 0xFF) && (pbSetList[3] == 0xFF)) { - DEBUG_PRINTF("[%s]: nSetList \'FF...FF\'", s_aStoreName[j]); - // Clear bSetList - *pbSetList++ = 0x00; - *pbSetList++ = 0x00; - *pbSetList++ = 0x00; - *pbSetList = 0x00; - - s_State = State::CHANGED; - } + s_nSpiFlashStoreSize += s_aStorSize[j]; } + DEBUG_PRINTF("OFFSET_STORES=%d, m_nSpiFlashStoreSize=%d", static_cast(OFFSET_STORES), s_nSpiFlashStoreSize); + + assert(s_nSpiFlashStoreSize <= FlashStore::SIZE); + + DEBUG_PUTS(""); + debug_dump(s_SpiFlashData, FlashStore::SIZE); + DEBUG_EXIT - return true; } -uint32_t ConfigStore::GetStoreOffset(Store tStore) { - assert(tStore < Store::LAST); +uint32_t ConfigStore::GetStoreOffset(Store store) { + assert(store < Store::LAST); uint32_t nOffset = OFFSET_STORES; - for (uint32_t i = 0; i < static_cast(tStore); i++) { + for (uint32_t i = 0; i < static_cast(store); i++) { nOffset += s_aStorSize[i]; } @@ -175,10 +128,10 @@ uint32_t ConfigStore::GetStoreOffset(Store tStore) { return nOffset; } -void ConfigStore::ResetSetList(Store tStore) { - assert(tStore < Store::LAST); +void ConfigStore::ResetSetList(Store store) { + assert(store < Store::LAST); - auto *pbSetList = &s_SpiFlashData[GetStoreOffset(tStore)]; + auto *pbSetList = &s_SpiFlashData[GetStoreOffset(store)]; *pbSetList++ = 0x00; *pbSetList++ = 0x00; @@ -188,28 +141,27 @@ void ConfigStore::ResetSetList(Store tStore) { s_State = State::CHANGED; } -void ConfigStore::Update(Store tStore, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList, uint32_t nOffsetSetList) { +void ConfigStore::Update(Store store, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList, uint32_t nOffsetSetList) { DEBUG_ENTRY + DEBUG_PRINTF("[%s]:%u:%p, nOffset=%d, nDataLength=%d-%u, bSetList=0x%x, nOffsetSetList=%d", s_aStoreName[static_cast(store)], static_cast(store), pData, nOffset, nDataLength, static_cast(s_State), nSetList, nOffsetSetList); - if (!s_bHaveFlashChip) { - return; - } - - DEBUG_PRINTF("[%s]:%u:%p, nOffset=%d, nDataLength=%d-%u, bSetList=0x%x, nOffsetSetList=%d", s_aStoreName[static_cast(tStore)], static_cast(tStore), pData, nOffset, nDataLength, static_cast(s_State), nSetList, nOffsetSetList); - - assert(tStore < Store::LAST); + assert(store < Store::LAST); assert(pData != nullptr); - assert((nOffset + nDataLength) <= s_aStorSize[static_cast(tStore)]); + assert((nOffset + nDataLength) <= s_aStorSize[static_cast(store)]); auto bIsChanged = false; + const auto nBase = nOffset + GetStoreOffset(store); - const auto nBase = nOffset + GetStoreOffset(tStore); - - const auto *pSrc = static_cast(pData); + const auto *pSrc = static_cast(pData); auto *pDst = &s_SpiFlashData[nBase]; DEBUG_PRINTF("pSrc=%p [pData], pDst=%p", reinterpret_cast(pSrc), reinterpret_cast(pDst)); +#if defined(__linux__) || defined (__APPLE__) +// debug_dump(pSrc, nDataLength); +// debug_dump(pDst, nDataLength); +#endif + for (uint32_t i = 0; i < nDataLength; i++) { if (*pSrc != *pDst) { bIsChanged = true; @@ -219,77 +171,54 @@ void ConfigStore::Update(Store tStore, uint32_t nOffset, const void *pData, uint pSrc++; } - if (bIsChanged) { - if ((s_State == State::IDLE) || (s_State == State::WRITING)) { - s_State = State::CHANGED; - } - s_nWaitMillis = Hardware::Get()->Millis(); - } - if ((0 != nOffset) && (bIsChanged) && (nSetList != 0)) { - auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(tStore)] + nOffsetSetList)); + auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(store)] + nOffsetSetList)); *pSet |= nSetList; } - DEBUG_PRINTF("s_State=%u", static_cast(s_State)); + if (bIsChanged) { + s_State = State::CHANGED; + } + DEBUG_EXIT } -void ConfigStore::Copy(Store tStore, void *pData, uint32_t nDataLength, uint32_t nOffset, bool isSetList) { +void ConfigStore::Copy(const Store store, void *pData, uint32_t nDataLength, uint32_t nOffset) { DEBUG_ENTRY + DEBUG_PRINTF("[%s]:%u pData=%p, nDataLength=%u, nOffset=%u", s_aStoreName[static_cast(store)], static_cast(store), pData, nDataLength, nOffset); - if (!s_bHaveFlashChip) { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("[%s]:%u pData=%p, nDataLength=%u, nOffset=%u, isSetList=%d", s_aStoreName[static_cast(tStore)], static_cast(tStore), pData, nDataLength, nOffset, isSetList); - - assert(tStore < Store::LAST); + assert(store < Store::LAST); assert(pData != nullptr); - assert((nDataLength + nOffset) <= s_aStorSize[static_cast(tStore)]); + assert((nDataLength + nOffset) <= s_aStorSize[static_cast(store)]); - if (isSetList) { - const auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(tStore)] + nOffset)); + const auto *pSrc = const_cast(&s_SpiFlashData[GetStoreOffset(store)]) + nOffset; + auto *pDst = static_cast(pData); - DEBUG_PRINTF("*pSet=0x%x", reinterpret_cast(*pSet)); + auto isEmpty = true; - if (*pSet == 0) { - Update(tStore, nOffset, pData, nDataLength); - DEBUG_EXIT - return; + for (uint32_t nIndex = 0; nIndex < nDataLength; nIndex++) { + if (pSrc[nIndex] != 0) { + isEmpty = false; + break; } } - const auto *pSrc = const_cast(&s_SpiFlashData[GetStoreOffset(tStore)]) + nOffset; - auto *pDst = static_cast(pData); - - for (uint32_t i = 0; i < nDataLength; i++) { - *pDst++ = *pSrc++; - } - - DEBUG_EXIT -} - -void ConfigStore::CopyTo(Store tStore, void* pData, uint32_t& nDataLength) { - DEBUG_ENTRY - - if (tStore >= Store::LAST) { - nDataLength = 0; + if (!isEmpty) { + memcpy(pDst, pSrc, nDataLength); + DEBUG_EXIT return; } - nDataLength = static_cast(s_aStorSize[static_cast(tStore)]); + Update(store, pData, nDataLength); - const auto *pSrc = const_cast(&s_SpiFlashData[GetStoreOffset(tStore)]); - auto *pDst = static_cast(pData); + DEBUG_EXIT +} - for (uint32_t i = 0; i < nDataLength; i++) { - *pDst++ = *pSrc++; +void ConfigStore::Delay() { + if (s_State != State::IDLE) { + s_State = State::CHANGED; } - - DEBUG_EXIT } bool ConfigStore::Flash() { @@ -316,6 +245,7 @@ bool ConfigStore::Flash() { s_State = State::ERASED_WAITING; } assert(result == storedevice::result::OK); + DEBUG_PRINTF("s_State=%u", static_cast(s_State)); return true; } break; diff --git a/lib-debug/.settings/language.settings.xml b/lib-debug/.settings/language.settings.xml index 3a910c6..dbdef46 100755 --- a/lib-debug/.settings/language.settings.xml +++ b/lib-debug/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-display/.settings/language.settings.xml b/lib-display/.settings/language.settings.xml index 08576d4..70044aa 100644 --- a/lib-display/.settings/language.settings.xml +++ b/lib-display/.settings/language.settings.xml @@ -1,11 +1,14 @@ - + - - + + + + + diff --git a/lib-display/Rules.mk b/lib-display/Rules.mk index 2196d17..71e8f49 100644 --- a/lib-display/Rules.mk +++ b/lib-display/Rules.mk @@ -2,8 +2,14 @@ ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONFIG_DISPLAY_USE_SPI,$(MAKE_FLAGS))) EXTRA_SRCDIR+=src/spi else - EXTRA_SRCDIR+=src/i2c + ifneq (,$(findstring CONFIG_DISPLAY_USE_CUSTOM,$(MAKE_FLAGS))) + else + EXTRA_SRCDIR+=src/i2c + endif endif else + DEFINES+=CONFIG_DISPLAY_ENABLE_CURSOR_MODE + DEFINES+=CONFIG_DISPLAY_FIX_FLIP_VERTICALLY + DEFINES+=CONFIG_DISPLAY_ENABLE_RUN EXTRA_SRCDIR+=src/i2c endif diff --git a/lib-display/include/display.h b/lib-display/include/display.h index 93082ba..c8d9215 100644 --- a/lib-display/include/display.h +++ b/lib-display/include/display.h @@ -2,7 +2,7 @@ * @file display.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,7 +46,12 @@ bool gpio_renew(); # include "i2c/display.h" # endif #else -# include "custom/display.h" +# if !defined(STR_HELPER) +# define STR_HELPER(x) #x +# define STR(x) STR_HELPER(x) +# endif +# define EXPAND(x) x +# include STR(EXPAND(DISPLAY_USE_CUSTOM_INCLUDE)/custom/display.h) #endif #endif /* DISPLAY_H_ */ diff --git a/lib-display/include/displayset.h b/lib-display/include/displayset.h index f440fd1..52ac2dd 100644 --- a/lib-display/include/displayset.h +++ b/lib-display/include/displayset.h @@ -30,10 +30,10 @@ namespace display { namespace cursor { -static constexpr auto OFF = 0; -static constexpr auto ON = (1 << 0); -static constexpr auto BLINK_OFF = 0; -static constexpr auto BLINK_ON = (1 << 1); +static constexpr uint32_t OFF = 0; +static constexpr uint32_t ON = (1U << 0); +static constexpr uint32_t BLINK_OFF = 0; +static constexpr uint32_t BLINK_ON = (1U << 1); } // namespace cursor_mode } // namespace display @@ -49,12 +49,8 @@ class DisplaySet { return m_nRows; } - uint8_t GetContrast() const { - return m_nContrast; - } - - bool GetFlipVertically() const { - return m_bIsFlippedVertically; + void ClearEndOfLine() { + m_bClearEndOfLine = true; } virtual bool Start()= 0; @@ -79,8 +75,7 @@ class DisplaySet { protected: uint32_t m_nCols; uint32_t m_nRows; - uint8_t m_nContrast { 0x7F }; - bool m_bIsFlippedVertically { false }; + bool m_bClearEndOfLine { false }; }; #endif /* DISPLAYSET_H_ */ diff --git a/lib-display/include/i2c/display.h b/lib-display/include/i2c/display.h index 508d795..56ba79d 100644 --- a/lib-display/include/i2c/display.h +++ b/lib-display/include/i2c/display.h @@ -36,6 +36,7 @@ #include #include "displayset.h" +#include "display7segment.h" #include "hal_i2c.h" #include "hardware.h" @@ -214,7 +215,7 @@ class Display { } void SetSleepTimeout(uint32_t nSleepTimeout = display::Defaults::SEEP_TIMEOUT) { - m_nSleepTimeout = 1000 * 60 * nSleepTimeout; + m_nSleepTimeout = 1000U * 60U * nSleepTimeout; } uint32_t GetSleepTimeout() const { @@ -222,6 +223,8 @@ class Display { } void SetContrast(uint8_t nContrast) { + m_nContrast = nContrast; + if (m_LcdDisplay == nullptr) { return; } @@ -229,7 +232,13 @@ class Display { m_LcdDisplay->SetContrast(nContrast); } + uint8_t GetContrast() const { + return m_nContrast; + } + void SetFlipVertically(bool doFlipVertically) { + m_bIsFlippedVertically = doFlipVertically; + if (m_LcdDisplay == nullptr) { return; } @@ -237,36 +246,32 @@ class Display { m_LcdDisplay->SetFlipVertically(doFlipVertically); } - uint32_t GetColumns() const { + void ClearEndOfLine() { if (m_LcdDisplay == nullptr) { - return 0; + return; } - return m_LcdDisplay->GetColumns(); + m_LcdDisplay->ClearEndOfLine(); } - uint32_t GetRows() const { - if (m_LcdDisplay == nullptr) { - return 0; - } - - return m_LcdDisplay->GetRows(); + bool GetFlipVertically() const { + return m_bIsFlippedVertically; } - bool GetFlipVertically() const { + uint32_t GetColumns() const { if (m_LcdDisplay == nullptr) { - return false; + return 0; } - return m_LcdDisplay->GetFlipVertically(); + return m_LcdDisplay->GetColumns(); } - uint8_t GetContrast() const { + uint32_t GetRows() const { if (m_LcdDisplay == nullptr) { return 0; } - return m_LcdDisplay->GetContrast(); + return m_LcdDisplay->GetRows(); } void Status(Display7SegmentMessage nData) { @@ -418,6 +423,9 @@ class Display { bool m_bHave7Segment { false }; uint32_t m_nSleepTimeout { 1000 * 60 * display::Defaults::SEEP_TIMEOUT }; + uint8_t m_nContrast { 0x7F }; + bool m_bIsFlippedVertically { false }; + DisplaySet *m_LcdDisplay { nullptr }; static Display *s_pThis; }; diff --git a/lib-display/include/i2c/ssd1306.h b/lib-display/include/i2c/ssd1306.h index 7054818..b9b8332 100644 --- a/lib-display/include/i2c/ssd1306.h +++ b/lib-display/include/i2c/ssd1306.h @@ -52,7 +52,6 @@ class Ssd1306 final: public DisplaySet { #endif } - bool Start() override; void Cls() override; @@ -100,10 +99,12 @@ class Ssd1306 final: public DisplaySet { TOledPanel m_OledPanel { OLED_PANEL_128x64_8ROWS }; bool m_bHaveSH1106 { false }; uint32_t m_nPages; -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) - uint32_t m_tCursorMode { display::cursor::OFF }; +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) char *m_pShadowRam { nullptr }; - uint16_t m_nShadowRamIndex { 0 }; + uint32_t m_nShadowRamIndex { 0 }; +#endif +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) + uint32_t m_nCursorMode { display::cursor::OFF }; uint8_t m_nCursorOnChar; uint8_t m_nCursorOnCol; uint8_t m_nCursorOnRow; diff --git a/lib-display/include/i2c/ssd1311.h b/lib-display/include/i2c/ssd1311.h index e956c23..667f124 100644 --- a/lib-display/include/i2c/ssd1311.h +++ b/lib-display/include/i2c/ssd1311.h @@ -80,7 +80,7 @@ class Ssd1311 final: public DisplaySet { private: HAL_I2C m_I2C; - uint8_t m_nDisplayControl{1U << 3}; // Section 9.1.4 Display ON/OFF Control + uint8_t m_nDisplayControl { 1U << 3 }; // Section 9.1.4 Display ON/OFF Control static Ssd1311 *s_pThis; }; diff --git a/lib-display/include/spi/display.h b/lib-display/include/spi/display.h index 1507e9f..6ecee92 100644 --- a/lib-display/include/spi/display.h +++ b/lib-display/include/spi/display.h @@ -97,6 +97,10 @@ class Display { Text(pText, nLength); } + void ClearEndOfLine() { + m_bClearEndOfLine = true; + } + void Status(__attribute__((unused)) Display7SegmentMessage nValue) { } void Status(__attribute__((unused)) uint8_t nValue, __attribute__((unused)) bool bHex) {} @@ -256,15 +260,18 @@ class Display { #endif uint32_t m_nCols; uint32_t m_nRows; - uint8_t m_nContrast { 0x7F }; - bool m_bIsFlippedVertically { false }; - bool m_bIsSleep { false }; uint32_t m_nSleepTimeout { 1000U * 60U * display::Defaults::SEEP_TIMEOUT }; uint32_t m_nMillis { 0 }; + bool m_bIsFlippedVertically { false }; + bool m_bIsSleep { false }; + bool m_bClearEndOfLine { false }; + uint16_t m_nCursorX { 0 }; uint16_t m_nCursorY { 0 }; + uint8_t m_nContrast { 0x7F }; + static Display *s_pThis; }; diff --git a/lib-display/include/spi/ili9341.h b/lib-display/include/spi/ili9341.h index 2b16ef9..fe72a20 100644 --- a/lib-display/include/spi/ili9341.h +++ b/lib-display/include/spi/ili9341.h @@ -88,7 +88,7 @@ static constexpr uint16_t GRAY = 0X8430; class ILI9341 : public Paint { public: ILI9341(); - ~ILI9341(); + ~ILI9341() override; void Init(); diff --git a/lib-display/include/spi/spi_lcd.h b/lib-display/include/spi/spi_lcd.h index 33c61c6..b15481a 100644 --- a/lib-display/include/spi/spi_lcd.h +++ b/lib-display/include/spi/spi_lcd.h @@ -57,7 +57,7 @@ inline static void DC_Clear() { FUNC_PREFIX(gpio_clr(SPI_LCD_DC_PIN)); } -inline static void HW_Reset(void) { +inline static void HW_Reset() { #if defined (SPI_LCD_RST_PIN) ms_delay(200); FUNC_PREFIX(gpio_clr(SPI_LCD_RST_PIN)); diff --git a/lib-display/include/spi/st7789.h b/lib-display/include/spi/st7789.h index 2e8dddd..d9712b4 100644 --- a/lib-display/include/spi/st7789.h +++ b/lib-display/include/spi/st7789.h @@ -56,7 +56,7 @@ static constexpr auto ROTATION_3_SHIFT_Y = 0; class ST7789 : public ST77XX { public: ST7789(); - ~ST7789(); + ~ST7789() override; void Init(); diff --git a/lib-display/include/spi/st77xx.h b/lib-display/include/spi/st77xx.h index 853ae6d..0371d4a 100644 --- a/lib-display/include/spi/st77xx.h +++ b/lib-display/include/spi/st77xx.h @@ -95,7 +95,7 @@ static constexpr uint16_t GRAY = 0X8430; class ST77XX : public Paint { public: ST77XX(); - ~ST77XX(); + ~ST77XX() override; void SetBackLight(uint32_t nValue); diff --git a/lib-display/src/i2c/display.cpp b/lib-display/src/i2c/display.cpp index 7ab8563..649b43b 100644 --- a/lib-display/src/i2c/display.cpp +++ b/lib-display/src/i2c/display.cpp @@ -41,9 +41,7 @@ #include "hal_i2c.h" -using namespace display; - -Display *Display::s_pThis = nullptr; +Display *Display::s_pThis; Display::Display() : m_nMillis(Hardware::Get()->Millis()), m_I2C(display::segment7::I2C_ADDRESS) { assert(s_pThis == nullptr); @@ -60,7 +58,7 @@ Display::Display() : m_nMillis(Hardware::Get()->Millis()), m_I2C(display::segmen Detect7Segment(); if (m_LcdDisplay != nullptr) { - timeout::gpio_init(); + display::timeout::gpio_init(); } PrintInfo(); @@ -75,7 +73,7 @@ Display::Display(uint32_t nRows) : m_nMillis(Hardware::Get()->Millis()), m_I2C(d Detect7Segment(); if (m_LcdDisplay != nullptr) { - timeout::gpio_init(); + display::timeout::gpio_init(); } PrintInfo(); @@ -90,7 +88,7 @@ Display::Display(display::Type type): m_tType(type), m_nMillis(Hardware::Get()-> Detect7Segment(); if (m_LcdDisplay != nullptr) { - timeout::gpio_init(); + display::timeout::gpio_init(); } PrintInfo(); diff --git a/lib-display/src/i2c/hd44780.cpp b/lib-display/src/i2c/hd44780.cpp index c1726a2..070476e 100644 --- a/lib-display/src/i2c/hd44780.cpp +++ b/lib-display/src/i2c/hd44780.cpp @@ -128,7 +128,7 @@ void Hd44780::PutChar(int c) { void Hd44780::PutString(const char *pString) { const char *p = pString; - for (uint32_t i = 0; *p != '\0'; i++) { + while (*p != '\0') { Hd44780::PutChar(static_cast(*p)); p++; } diff --git a/lib-display/src/i2c/ssd1306.cpp b/lib-display/src/i2c/ssd1306.cpp index 58d0fab..5281a4f 100644 --- a/lib-display/src/i2c/ssd1306.cpp +++ b/lib-display/src/i2c/ssd1306.cpp @@ -299,14 +299,11 @@ bool Ssd1306::Start() { Ssd1306::Cls(); SendCommand(cmd::DISPLAY_ON); - - m_bIsFlippedVertically = true; - return true; } void Ssd1306::Cls() { - uint8_t nColumnAdd = 0; + uint32_t nColumnAdd = 0; if (m_bHaveSH1106) { nColumnAdd = 4; @@ -316,28 +313,16 @@ void Ssd1306::Cls() { SendCommand(cmd::SET_LOWCOLUMN | (nColumnAdd & 0XF)); SendCommand(static_cast(cmd::SET_HIGHCOLUMN | (nColumnAdd))); SendCommand(static_cast(cmd::SET_STARTPAGE | nPage)); - - switch (m_OledPanel) { - case OLED_PANEL_128x64_8ROWS: - SendData(reinterpret_cast(&_ClearBuffer), static_cast(nColumnAdd + SSD1306_LCD_WIDTH + 1)); - break; - case OLED_PANEL_128x64_4ROWS: - /* no break */ - case OLED_PANEL_128x32_4ROWS: - SendData(reinterpret_cast(&_ClearBuffer), static_cast(nColumnAdd + SSD1306_LCD_WIDTH + 1)); - break; - default: - break; - } + SendData(reinterpret_cast(&_ClearBuffer), (nColumnAdd + SSD1306_LCD_WIDTH + 1)); } SendCommand(cmd::SET_LOWCOLUMN | (nColumnAdd & 0XF)); SendCommand(static_cast(cmd::SET_HIGHCOLUMN | (nColumnAdd))); SendCommand(cmd::SET_STARTPAGE); -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE)|| defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) m_nShadowRamIndex = 0; - memset(m_pShadowRam, ' ', m_nCols * m_nRows); + memset(m_pShadowRam, ' ', oled::font8x6::COLS * m_nRows); #endif } @@ -345,15 +330,15 @@ void Ssd1306::PutChar(int c) { int i; if (c < 32 || c > 127) { -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) c = 32; #endif i = 0; } else { - i = (c - 32); + i = c - 32; } -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) m_pShadowRam[m_nShadowRamIndex++] = static_cast(c); #endif const uint8_t *base = _OledFont8x6 + (oled::font8x6::CHAR_W + 1) * i; @@ -363,10 +348,17 @@ void Ssd1306::PutChar(int c) { void Ssd1306::PutString(const char *pString) { const char *p = pString; - for (uint32_t i = 0; *p != '\0'; i++) { + while (*p != '\0') { Ssd1306::PutChar(static_cast(*p)); p++; } + + if (m_bClearEndOfLine) { + m_bClearEndOfLine = false; + for (auto i = static_cast(p - pString); i < m_nCols; i++) { + Ssd1306::PutChar(' '); + } + } } /** @@ -380,6 +372,10 @@ void Ssd1306::ClearLine(uint32_t nLine) { Ssd1306::SetCursorPos(0, static_cast(nLine - 1)); SendData(reinterpret_cast(&_ClearBuffer), SSD1306_LCD_WIDTH + 1); Ssd1306::SetCursorPos(0, static_cast(nLine - 1)); + +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) + memset(&m_pShadowRam[m_nShadowRamIndex], ' ', oled::font8x6::COLS); +#endif } void Ssd1306::TextLine(uint32_t nLine, const char *pData, uint32_t nLength) { @@ -396,9 +392,18 @@ void Ssd1306::Text(const char *pData, uint32_t nLength) { nLength = m_nCols; } - for (uint32_t i = 0; i < nLength; i++) { + uint32_t i; + + for (i = 0; i < nLength; i++) { Ssd1306::PutChar(pData[i]); } + + if (m_bClearEndOfLine) { + m_bClearEndOfLine = false; + for (; i < m_nCols; i++) { + Ssd1306::PutChar(' '); + } + } } /** @@ -419,13 +424,14 @@ void Ssd1306::SetCursorPos(uint32_t nCol, uint32_t nRow) { SendCommand(static_cast(cmd::SET_HIGHCOLUMN | (nCol >> 4))); SendCommand(static_cast(cmd::SET_STARTPAGE | nRow)); -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) m_nShadowRamIndex = static_cast((nRow * oled::font8x6::COLS) + (nCol / oled::font8x6::CHAR_W)); - - if (m_tCursorMode == display::cursor::ON) { +#endif +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) + if (m_nCursorMode == display::cursor::ON) { SetCursorOff(); SetCursorOn(); - } else if (m_tCursorMode == static_cast((display::cursor::ON | display::cursor::BLINK_ON))) { + } else if (m_nCursorMode == (display::cursor::ON | display::cursor::BLINK_ON)) { SetCursorOff(); SetCursorBlinkOn(); } @@ -441,48 +447,53 @@ void Ssd1306::SetSleep(bool bSleep) { } void Ssd1306::SetContrast(uint8_t nContrast) { - m_nContrast = nContrast; - SendCommand(cmd::SET_CONTRAST); SendCommand(nContrast); } - -void Ssd1306::SetFlipVertically(bool doFlipVertically) { - m_bIsFlippedVertically = doFlipVertically; - +void Ssd1306::SetFlipVertically(bool doFlipVertically) { if (doFlipVertically) { + SendCommand(cmd::SEGREMAP); ///< Data already stored in GDDRAM will have no changes. SendCommand(cmd::COMSCAN_INC); - SendCommand(cmd::SEGREMAP); } else { + SendCommand(cmd::SEGREMAP | 0x01); ///< Data already stored in GDDRAM will have no changes. SendCommand(cmd::COMSCAN_DEC); - SendCommand(cmd::SEGREMAP | 0x01); } + +#if defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) + for (uint32_t i = 0; i < m_nRows; i++) { + Ssd1306::SetCursorPos(0, static_cast(i)); + for (uint32_t j = 0; j < oled::font8x6::COLS; j++) { + const auto n = m_pShadowRam[i * oled::font8x6::COLS + j] - 32; + const uint8_t *base = _OledFont8x6 + (oled::font8x6::CHAR_W + 1) * n; + SendData(base, oled::font8x6::CHAR_W + 1); + } + } +#endif } void Ssd1306::InitMembers() { + m_nCols = oled::font8x6::COLS; + switch (m_OledPanel) { case OLED_PANEL_128x64_8ROWS: - m_nCols = oled::font8x6::COLS; m_nRows = 64 / oled::font8x6::CHAR_H; break; case OLED_PANEL_128x64_4ROWS: // Trick : 128x32 /* no break */ case OLED_PANEL_128x32_4ROWS: - m_nCols = oled::font8x6::COLS; m_nRows = 32 / oled::font8x6::CHAR_H; break; default: - m_nCols = oled::font8x6::COLS; m_nRows = 64 / oled::font8x6::CHAR_H; break; } m_nPages = (m_OledPanel == OLED_PANEL_128x64_8ROWS ? 8 : 4); -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) m_pShadowRam = new char[oled::font8x6::COLS * m_nRows]; - m_nShadowRamIndex = 0; + assert(m_pShadowRam != nullptr); memset(m_pShadowRam, ' ', oled::font8x6::COLS * m_nRows); #endif } @@ -505,15 +516,15 @@ void Ssd1306::SendData(const uint8_t *pData, uint32_t nLength) { # define UNUSED __attribute__((unused)) #endif -void Ssd1306::SetCursor(UNUSED uint32_t tCursorMode) { +void Ssd1306::SetCursor(UNUSED uint32_t nCursorMode) { #if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) - if (tCursorMode == m_tCursorMode) { + if (nCursorMode == m_nCursorMode) { return; } - m_tCursorMode = tCursorMode; + m_nCursorMode = nCursorMode; - switch (static_cast(tCursorMode)) { + switch (nCursorMode) { case display::cursor::OFF: SetCursorOff(); break; @@ -600,7 +611,7 @@ void Ssd1306::SetColumnRow(UNUSED uint8_t nColumn, UNUSED uint8_t nRow) { } void Ssd1306::DumpShadowRam() { -#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) +#if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) || defined(CONFIG_DISPLAY_FIX_FLIP_VERTICALLY) #ifndef NDEBUG for (uint32_t i = 0; i < m_nRows; i++) { printf("%d: [%.*s]\n", i, oled::font8x6::COLS, &m_pShadowRam[i * oled::font8x6::COLS]); diff --git a/lib-display/src/i2c/ssd1311.cpp b/lib-display/src/i2c/ssd1311.cpp index 77fc5d6..5c9c76d 100644 --- a/lib-display/src/i2c/ssd1311.cpp +++ b/lib-display/src/i2c/ssd1311.cpp @@ -115,7 +115,7 @@ void Ssd1311::PutChar(int c) { void Ssd1311::PutString(const char *pString) { assert(pString != nullptr); - uint16_t n = MAX_COLUMNS; + uint32_t n = MAX_COLUMNS; auto *pSrc = pString; auto *s = reinterpret_cast(&_TextBuffer[1]); @@ -124,6 +124,17 @@ void Ssd1311::PutString(const char *pString) { --n; } + if (m_bClearEndOfLine) { + m_bClearEndOfLine = false; + + for (auto i = static_cast(pSrc - pString); i < MAX_COLUMNS; i++) { + *s++ = ' '; + } + + SendData(_TextBuffer, 1U + MAX_COLUMNS); + return; + } + SendData(_TextBuffer, 1U + MAX_COLUMNS - n); } @@ -146,21 +157,25 @@ void Ssd1311::TextLine(uint32_t nLine, const char *pData, uint32_t nLength) { } Ssd1311::SetCursorPos(0, static_cast(nLine - 1)); + Text(pData, nLength); +} +void Ssd1311::Text(const char *pData, uint32_t nLength) { if (nLength > MAX_COLUMNS) { nLength = MAX_COLUMNS; } memcpy(&_TextBuffer[1], pData, nLength); - SendData(_TextBuffer, 1U + nLength); -} -void Ssd1311::Text(const char *pData, uint32_t nLength) { - if (nLength > MAX_COLUMNS) { - nLength = MAX_COLUMNS; + if (m_bClearEndOfLine) { + m_bClearEndOfLine = false; + + memset(&_TextBuffer[nLength + 1], ' ', MAX_COLUMNS - nLength); + + SendData(_TextBuffer, 1U + MAX_COLUMNS); + return; } - memcpy(&_TextBuffer[1], pData, nLength); SendData(_TextBuffer, 1U + nLength); } @@ -308,8 +323,6 @@ void Ssd1311::SetSleep(bool bSleep) { } void Ssd1311::SetContrast(uint8_t nContrast) { - m_nContrast = nContrast; - // [IS=X,RE=1,SD=1] SetRE(FunctionSet::RE_ONE); SetSD(CommandSet::ENABLED); diff --git a/lib-display/src/spi/paint.cpp b/lib-display/src/spi/paint.cpp index 054c50a..f9d3e76 100644 --- a/lib-display/src/spi/paint.cpp +++ b/lib-display/src/spi/paint.cpp @@ -2,7 +2,7 @@ * @file paint.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,7 +69,7 @@ void Paint::FillColour(uint16_t nColour) { fill_framebuffer(nColour); - for (auto i = 0; i < config::HEIGHT / FRAME_BUFFER_ROWS; i++) { + for (uint32_t i = 0; i < config::HEIGHT / FRAME_BUFFER_ROWS; i++) { WriteData(reinterpret_cast(s_FrameBuffer), sizeof(s_FrameBuffer)); } } diff --git a/lib-display/src/spi/st7789.cpp b/lib-display/src/spi/st7789.cpp index 2dde321..4a34009 100644 --- a/lib-display/src/spi/st7789.cpp +++ b/lib-display/src/spi/st7789.cpp @@ -48,7 +48,7 @@ ST7789::~ST7789() { DEBUG_EXIT } -void ST7789::Init(void) { +void ST7789::Init() { DEBUG_ENTRY #if defined(SPI_LCD_RST_PIN) diff --git a/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp b/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp index 00a6215..3247023 100644 --- a/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp +++ b/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp @@ -34,10 +34,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI OF SUCH DAMAGE. */ +#include "gd32.h" #include "fmc_operation.h" -#include "gd32f4xx.h" - /*! \brief get the sector number, size and range of the given address \param[in] address: The flash address diff --git a/lib-flashcode/src/gd32/fmc/flashcode.cpp b/lib-flashcode/src/gd32/fmc/flashcode.cpp index 51555ec..9338ba5 100644 --- a/lib-flashcode/src/gd32/fmc/flashcode.cpp +++ b/lib-flashcode/src/gd32/fmc/flashcode.cpp @@ -52,7 +52,7 @@ enum class State { static State s_State = State::IDLE; static uint32_t s_nPage; -static uint32_t s_nLength;; +static uint32_t s_nLength; static uint32_t s_nAddress; static uint32_t *s_pData; static bool s_isBank0; @@ -187,6 +187,7 @@ bool FlashCode::Erase(uint32_t nOffset, uint32_t nLength, flashcode::result& nRe } else { FMC_CTL1 &= ~FMC_CTL1_PG; } + /*@fallthrough@*/ /* no break */ case State::WRITE_PROGRAM: s_State = State::IDLE; @@ -285,6 +286,7 @@ bool FlashCode::Write(uint32_t nOffset, uint32_t nLength, const uint8_t *pBuffer } else { FMC_CTL1 &= ~FMC_CTL1_PER; } + /*@fallthrough@*/ /* no break */ case State::ERASE_PROGAM: s_State = State::IDLE; diff --git a/lib-gd32/Makefile.GD32 b/lib-gd32/Makefile.GD32 index 5a61083..3bbe2a4 100644 --- a/lib-gd32/Makefile.GD32 +++ b/lib-gd32/Makefile.GD32 @@ -14,6 +14,27 @@ endif ifeq ($(findstring gd32f20x,$(FAMILY)), gd32f20x) EXTRA_SRCDIR=gd32f20x/CMSIS/GD/GD32F20x/Source EXTRA_SRCDIR+=gd32f20x/GD32F20x_standard_peripheral/Source + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/core/Source + + EXTRA_C_SOURCE_FILES=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c + EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c + EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c + + EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/driver/Include + EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/host/core/Include + EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/ustd/common + + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source + + EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include + EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/ustd/class/msc + + EXTRA_INCLUDES+=../lib-hal/ff12c + endif + + endif endif ifeq ($(findstring gd32f30x,$(FAMILY)), gd32f30x) @@ -24,18 +45,59 @@ endif ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) EXTRA_SRCDIR=gd32f4xx/CMSIS/GD/GD32F4xx/Source EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_standard_peripheral/Source + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/core/Source + + EXTRA_C_SOURCE_FILES=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_core.c + EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_host.c + EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c + + EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/driver/Include + EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/host/core/Include + EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/ustd/common + + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/class/msc/Source + + EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/host/class/msc/Include + EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/ustd/class/msc + + EXTRA_INCLUDES+=../lib-hal/ff12c + endif + + endif endif $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) -ifeq ($(findstring NO_EMAC,$(MAKE_FLAGS)), NO_EMAC) +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring NO_EMAC,$(MAKE_FLAGS)), NO_EMAC) + else + EXTRA_SRCDIR+=device/emac + endif + + ifeq ($(findstring CONFIG_USE_SOFTUART0,$(MAKE_FLAGS)), CONFIG_USE_SOFTUART0) + EXTRA_SRCDIR+=src/softuart0 + else + ifeq ($(findstring CONSOLE_NULL,$(MAKE_FLAGS)), CONSOLE_NULL) + else + EXTRA_SRCDIR+=src/uart0 + endif + endif + + ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) + EXTRA_SRCDIR+=device/emac/dsa + endif + + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=device/usb + endif else - EXTRA_SRCDIR+=device/emac -endif - -ifeq ($(findstring DISABLE_FS,$(MAKE_FLAGS)), DISABLE_FS) -else - EXTRA_SRCDIR+=device/sdio + EXTRA_SRCDIR+=device/emac device/emac/dsa + EXTRA_SRCDIR+=device/usb + EXTRA_SRCDIR+=src/uart0 src/softuart0 + + DEFINES=ENABLE_USB_HOST CONFIG_USB_HOST_MSC endif include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-gd32/gd32f10x/CMSIS/GD/GD32F10x/Include/gd32f10x.h b/lib-gd32/gd32f10x/CMSIS/GD/GD32F10x/Include/gd32f10x.h index 2797f5c..16d1d34 100644 --- a/lib-gd32/gd32f10x/CMSIS/GD/GD32F10x/Include/gd32f10x.h +++ b/lib-gd32/gd32f10x/CMSIS/GD/GD32F10x/Include/gd32f10x.h @@ -38,6 +38,14 @@ OF SUCH DAMAGE. #ifndef GD32F10X_H #define GD32F10X_H +/* AvV BEGIN */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wduplicated-cond" +/* AvV END */ + #ifdef __cplusplus extern "C" { #endif diff --git a/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h b/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h index e26315d..6473e5b 100644 --- a/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h +++ b/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Include/gd32f10x_exmc.h @@ -222,7 +222,7 @@ typedef struct exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash common space */ exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO space */ -}exmc_pccard_parameter_struct;; +}exmc_pccard_parameter_struct; /* EXMC register address */ #define EXMC_SNCTL(region) REG32(EXMC + 0x08U * (region)) /*!< EXMC SRAM/NOR flash control register */ diff --git a/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c b/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c index 15bef68..1c937f6 100644 --- a/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c +++ b/lib-gd32/gd32f10x/GD32F10x_standard_peripheral/Source/gd32f10x_enet.c @@ -327,12 +327,12 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum ErrStatus phy_state= ERROR, enet_state = ERROR; /* PHY interface configuration, configure SMI clock and reset PHY chip */ - if(ERROR == enet_phy_config()){ - _ENET_DELAY_(PHY_RESETDELAY); - if(ERROR == enet_phy_config()){ - return enet_state; - } - } +// if(ERROR == enet_phy_config()){ +// _ENET_DELAY_(PHY_RESETDELAY); +// if(ERROR == enet_phy_config()){ +// return enet_state; +// } +// } /* initialize ENET peripheral with generally concerned parameters */ enet_default_init(); @@ -396,15 +396,15 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum media_temp |= ENET_SPEEDMODE_100M; } }else{ - phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); - phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); - phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); - if(!phy_state){ - /* return ERROR due to write timeout */ - return enet_state; - } - /* PHY configuration need some time */ - _ENET_DELAY_(PHY_CONFIGDELAY); +// phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); +// phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); +// phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +// if(!phy_state){ +// /* return ERROR due to write timeout */ +// return enet_state; +// } +// /* PHY configuration need some time */ +// _ENET_DELAY_(PHY_CONFIGDELAY); } /* after configuring the PHY, use mediamode to configure registers */ reg_value = ENET_MAC_CFG; diff --git a/lib-gd32/include/board/gd32f107rc.h b/lib-gd32/include/board/gd32f107rc.h index 58cc341..9028ec0 100644 --- a/lib-gd32/include/board/gd32f107rc.h +++ b/lib-gd32/include/board/gd32f107rc.h @@ -54,22 +54,6 @@ #define LED_BLINK_GPIO_PORT LED1_GPIOx #define LED_BLINK_GPIO_CLK LED1_RCU_GPIOx -/** - * LEDs bit-banging 595 --> Using SPI2 pin's: MOSI, SCK and NSS - */ - -#define LED595_DATA_GPIO_PINx GPIO_PIN_5 -#define LED595_DATA_RCU_GPIOx RCU_GPIOB -#define LED595_DATA_GPIOx GPIOB - -#define LED595_CLK_GPIO_PINx GPIO_PIN_3 -#define LED595_CLK_RCU_GPIOx RCU_GPIOB -#define LED595_CLK_GPIOx GPIOB - -#define LED595_LOAD_GPIO_PINx GPIO_PIN_15 -#define LED595_LOAD_RCU_GPIOx RCU_GPIOA -#define LED595_LOAD_GPIOx GPIOA - /** * KEYs */ @@ -82,10 +66,6 @@ #define KEY2_GPIOx GPIOB #define KEY2_RCU_GPIOx RCU_GPIOB -#define KEY3_PINx GPIO_PIN_11 -#define KEY3_GPIOx GPIOA -#define KEY3_RCU_GPIOx RCU_GPIOA - #define KEY_BOOTLOADER_TFTP_GPIO_PINx KEY2_PINx #define KEY_BOOTLOADER_TFTP_GPIOx KEY2_GPIOx #define KEY_BOOTLOADER_TFTP_RCU_GPIOx KEY2_RCU_GPIOx @@ -158,8 +138,6 @@ static constexpr uint32_t TCNET = 0; // DMX static constexpr uint32_t PORT_A_RX = 0; static constexpr uint32_t PORT_A_TX = 0; -// -static constexpr uint32_t INVERTED = 0; } // namespace panelled } // namespace hal #endif diff --git a/lib-gd32/include/board/logic_analyzer.h b/lib-gd32/include/board/logic_analyzer.h index c07c795..e3bc5fa 100644 --- a/lib-gd32/include/board/logic_analyzer.h +++ b/lib-gd32/include/board/logic_analyzer.h @@ -2,7 +2,7 @@ * @file logic_analyzer.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,27 +54,27 @@ # define LOGIC_ANALYZER_CH6_RCU_GPIOx # define LOGIC_ANALYZER_CH7_RCU_GPIOx #else -# define LOGIC_ANALYZER_CH0_GPIO_PINx GPIO_PIN_3 // GPIO_EXT_23 -# define LOGIC_ANALYZER_CH1_GPIO_PINx GPIO_PIN_4 // GPIO_EXT_21 -# define LOGIC_ANALYZER_CH2_GPIO_PINx GPIO_PIN_5 // GPIO_EXT_19 -# define LOGIC_ANALYZER_CH3_GPIO_PINx GPIO_PIN_14 // GPIO_EXT_26 -//# define LOGIC_ANALYZER_CH4_GPIO_PINx GPIO_PIN_11 // GPIO_EXT_22 -# define LOGIC_ANALYZER_CH5_GPIO_PINx GPIO_PIN_13 // GPIO_EXT_18 +# define LOGIC_ANALYZER_CH0_GPIO_PINx GPIO_PIN_8 // PC8 +# define LOGIC_ANALYZER_CH1_GPIO_PINx GPIO_PIN_9 // PC9 +# define LOGIC_ANALYZER_CH2_GPIO_PINx GPIO_PIN_13 // PC13 +# define LOGIC_ANALYZER_CH3_GPIO_PINx GPIO_PIN_4 // PA4 +# define LOGIC_ANALYZER_CH4_GPIO_PINx GPIO_PIN_5 // PA5 +# define LOGIC_ANALYZER_CH5_GPIO_PINx GPIO_PIN_13 // PA13 //# define LOGIC_ANALYZER_CH6_GPIO_PINx GPIO_PIN_ //# define LOGIC_ANALYZER_CH7_GPIO_PINx GPIO_PIN_ -# define LOGIC_ANALYZER_CH0_GPIOx GPIOB -# define LOGIC_ANALYZER_CH1_GPIOx GPIOB -# define LOGIC_ANALYZER_CH2_GPIOx GPIOB +# define LOGIC_ANALYZER_CH0_GPIOx GPIOC +# define LOGIC_ANALYZER_CH1_GPIOx GPIOC +# define LOGIC_ANALYZER_CH2_GPIOx GPIOC # define LOGIC_ANALYZER_CH3_GPIOx GPIOA # define LOGIC_ANALYZER_CH4_GPIOx GPIOA # define LOGIC_ANALYZER_CH5_GPIOx GPIOA # define LOGIC_ANALYZER_CH6_GPIOx GPIO # define LOGIC_ANALYZER_CH7_GPIOx GPIO -# define LOGIC_ANALYZER_CH0_RCU_GPIOx RCU_GPIOB -# define LOGIC_ANALYZER_CH1_RCU_GPIOx RCU_GPIOB -# define LOGIC_ANALYZER_CH2_RCU_GPIOx RCU_GPIOB +# define LOGIC_ANALYZER_CH0_RCU_GPIOx RCU_GPIOC +# define LOGIC_ANALYZER_CH1_RCU_GPIOx RCU_GPIOC +# define LOGIC_ANALYZER_CH2_RCU_GPIOx RCU_GPIOC # define LOGIC_ANALYZER_CH3_RCU_GPIOx RCU_GPIOA # define LOGIC_ANALYZER_CH4_RCU_GPIOx RCU_GPIOA # define LOGIC_ANALYZER_CH5_RCU_GPIOx RCU_GPIOA diff --git a/lib-gd32/include/gd32.h b/lib-gd32/include/gd32.h index 3923493..b13f5dc 100644 --- a/lib-gd32/include/gd32.h +++ b/lib-gd32/include/gd32.h @@ -2,7 +2,7 @@ * @file gd32.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,7 +37,14 @@ # endif #endif +/* + * Needed for GD32 Firmware and CMSIS + */ +#pragma GCC diagnostic push + #ifdef __cplusplus +# pragma GCC diagnostic ignored "-Wold-style-cast" +# pragma GCC diagnostic ignored "-Wuseless-cast" extern "C" { #endif diff --git a/lib-gd32/include/gd32_bitbanging595.h b/lib-gd32/include/gd32_bitbanging595.h deleted file mode 100644 index 7cb875e..0000000 --- a/lib-gd32/include/gd32_bitbanging595.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file gd32_bitbanging595.h - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef BITBANGING595_H_ -#define BITBANGING595_H_ - -#include -#include - -#include "gd32.h" - -#include "debug.h" - -#if !defined(BITBANGING595_COUNT) -# define BITBANGING595_COUNT 1 -#endif - -namespace bitbanging595 { -#if (BITBANGING595_COUNT == 1) -static constexpr uint32_t MASK_HIGH = (1U << 7); -#elif (BITBANGING595_COUNT == 2) -static constexpr uint32_t MASK_HIGH = (1U << 15); -#elif (BITBANGING595_COUNT == 3) -static constexpr uint32_t MASK_HIGH = (1U << 23); -#else -static constexpr uint32_t MASK_HIGH = (1U << 31); -#endif -} // namespace bitbanging595 - -class BitBanging595 { -public: - BitBanging595(void) { - DEBUG_PRINTF("Mask=%x", bitbanging595::MASK_HIGH); - - assert(s_pThis == nullptr); - s_pThis = this; - - rcu_periph_clock_enable(LED595_DATA_RCU_GPIOx); - rcu_periph_clock_enable(LED595_CLK_RCU_GPIOx); - rcu_periph_clock_enable(LED595_LOAD_RCU_GPIOx); - -#if !defined (GD32F4XX) - gpio_init(LED595_DATA_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED595_DATA_GPIO_PINx); - gpio_init(LED595_CLK_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED595_CLK_GPIO_PINx); - gpio_init(LED595_LOAD_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED595_LOAD_GPIO_PINx); -#else - gpio_af_set(LED595_DATA_GPIOx, GPIO_AF_0, LED595_DATA_GPIO_PINx); - gpio_mode_set(LED595_DATA_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED595_DATA_GPIO_PINx); - gpio_output_options_set(LED595_DATA_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED595_DATA_GPIO_PINx); - - gpio_af_set(LED595_CLK_GPIOx, GPIO_AF_0, LED595_CLK_GPIO_PINx); - gpio_mode_set(LED595_CLK_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED595_CLK_GPIO_PINx); - gpio_output_options_set(LED595_CLK_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED595_CLK_GPIO_PINx); - - gpio_af_set(LED595_LOAD_GPIOx, GPIO_AF_0, LED595_LOAD_GPIO_PINx); - gpio_mode_set(LED595_LOAD_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED595_LOAD_GPIO_PINx); - gpio_output_options_set(LED595_LOAD_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED595_LOAD_GPIO_PINx); -#endif - - GPIO_BOP(LED595_CLK_GPIOx) = LED595_CLK_GPIO_PINx; - GPIO_BOP(LED595_LOAD_GPIOx) = LED595_LOAD_GPIO_PINx; - - ShiftOut(); - } - - void SetOn(uint32_t nData) { - s_nData |= nData; -// s_nData ^= hal::panelled::INVERTED; - } - - void SetOff(uint32_t nData) { - s_nData &= ~nData; -// s_nData ^= hal::panelled::INVERTED; - } - - void Run() { - if (__builtin_expect ((s_nData != s_nDataPrevious), 0)) { - s_nDataPrevious = s_nData; - ShiftOut(); - } - } - - static BitBanging595* Get() { - return s_pThis; - } - -private: - void ShiftOut() { - gpio_bit_reset(LED595_LOAD_GPIOx, LED595_LOAD_GPIO_PINx); - __ISB(); - - for (uint32_t nMask = bitbanging595::MASK_HIGH; nMask != 0; nMask = static_cast(nMask >> 1U)) { - if (s_nData & nMask) { - gpio_bit_set(LED595_DATA_GPIOx, LED595_DATA_GPIO_PINx); - } else { - gpio_bit_reset(LED595_DATA_GPIOx, LED595_DATA_GPIO_PINx); - } - - __ISB(); - gpio_bit_reset(LED595_CLK_GPIOx, LED595_CLK_GPIO_PINx); - __ISB(); - gpio_bit_set(LED595_CLK_GPIOx, LED595_CLK_GPIO_PINx); - } - - gpio_bit_set(LED595_LOAD_GPIOx, LED595_LOAD_GPIO_PINx); - __ISB(); - } - -private: - uint32_t s_nData { 0 }; - uint32_t s_nDataPrevious { 0 }; - - static BitBanging595 *s_pThis; -}; - -#endif /* BITBANGING595_H_ */ diff --git a/lib-gd32/include/gd32_board.h b/lib-gd32/include/gd32_board.h index f65a80c..bb1ec55 100644 --- a/lib-gd32/include/gd32_board.h +++ b/lib-gd32/include/gd32_board.h @@ -2,7 +2,7 @@ * @file gd32_board.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,8 +32,10 @@ # include "board/gd32f107rc.h" #elif defined (BOARD_GD32F207RG) # include "board/gd32f207rg.h" -#elif defined (BOARD_GD32F207VC) -# include "board/gd32f207vc.h" +#elif defined (BOARD_GD32F207VC_2) +# include "board/gd32f207vc_2.h" +#elif defined (BOARD_GD32F207VC_4) +# include "board/gd32f207vc_4.h" #elif defined (BOARD_GD32F303RC) # include "board/gd32f303rc.h" #elif defined (BOARD_GD32F407RE) @@ -42,10 +44,14 @@ # include "board/gd32f450ve.h" #elif defined (BOARD_GD32F450VI) # include "board/gd32f450vi.h" +#elif defined (BOARD_16X4U_PIXEL) +# include "board/16x4u-pixel.h" #elif defined (BOARD_GD32F207C_EVAL) # include "board/gd32f207c_eval.h" #elif defined (BOARD_BW_OPIDMX4) # include "board/bw_opidmx4.h" +#elif defined (BOARD_DMX3) +# include "board/dmx3.h" #elif defined (BOARD_DMX4) # include "board/dmx4.h" #else diff --git a/lib-gd32/include/gd32_gpio.h b/lib-gd32/include/gd32_gpio.h index b2e90fa..7591f93 100644 --- a/lib-gd32/include/gd32_gpio.h +++ b/lib-gd32/include/gd32_gpio.h @@ -26,9 +26,11 @@ #ifndef GD32_GPIO_H_ #define GD32_GPIO_H_ +#include + #define GD32_PORT_TO_GPIO(p,n) ((p * 16) + n) -#define GD32_GPIO_TO_PORT(g) (g / 16) -#define GD32_GPIO_TO_NUMBER(g) (g - (16 * GD32_GPIO_TO_PORT(g))) +#define GD32_GPIO_TO_PORT(g) (uint8_t)(g / 16) +#define GD32_GPIO_TO_NUMBER(g) (uint8_t)(g - (16 * GD32_GPIO_TO_PORT(g))) typedef enum T_GD32_Port { GD32_GPIO_PORTA = 0, @@ -40,8 +42,6 @@ typedef enum T_GD32_Port { GD32_GPIO_PORTG, } GD32_Port_TypeDef; -#include - #include "gd32.h" #if defined (GD32F10X) || defined (GD32F20X) || defined (GD32F30X) diff --git a/lib-gd32/include/gd32_micros.h b/lib-gd32/include/gd32_micros.h index 5156612..14e654d 100644 --- a/lib-gd32/include/gd32_micros.h +++ b/lib-gd32/include/gd32_micros.h @@ -2,7 +2,7 @@ * @file gd32_micros.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,22 +30,25 @@ #include "gd32.h" -#if defined (GD32F20X_CL) -static inline uint32_t micros() { - uint32_t msw, lsw; - do { - msw = TIMER_CNT(TIMER9); - lsw = TIMER_CNT(TIMER8); - } while (msw != TIMER_CNT(TIMER9)); - return (msw << 16) | lsw; -} -#elif defined (GD32F4XX) +#if defined (GD32F4XX) && !defined(MICROS_DO_NOT_USE_TIMER4) static inline uint32_t micros() { return TIMER_CNT(TIMER4); } #else static inline uint32_t micros() { - return DWT->CYCCNT / (MCU_CLOCK_FREQ / 1000000U); + static uint32_t nMicrosPrevious; + static uint32_t nResult; + const auto nMicros = DWT->CYCCNT / (MCU_CLOCK_FREQ / 1000000U); + + if (nMicros > nMicrosPrevious) { + nResult += (nMicros - nMicrosPrevious); + } else { + nResult += ((UINT32_MAX/ (MCU_CLOCK_FREQ / 1000000U)) - nMicrosPrevious + nMicros); + } + + nMicrosPrevious = nMicros; + + return nResult; } #endif diff --git a/lib-gd32/include/gd32_uart.h b/lib-gd32/include/gd32_uart.h index d857ccc..5f3c759 100644 --- a/lib-gd32/include/gd32_uart.h +++ b/lib-gd32/include/gd32_uart.h @@ -54,7 +54,7 @@ extern void gd32_uart_set_baudrate(const uint32_t usart_periph, uint32_t baudrat extern void gd32_uart_transmit(const uint32_t usart_periph, const uint8_t *data, uint32_t length); extern void gd32_uart_transmit_string(const uint32_t uart_base, const char *data); -static inline uint32_t gd32_uart_get_rx_fifo_level(const uint32_t usart_periph) { +static inline uint32_t gd32_uart_get_rx_fifo_level(__attribute__((unused)) const uint32_t usart_periph) { return 1; } diff --git a/lib-gd32/include/logic_analyzer.h b/lib-gd32/include/logic_analyzer.h index 2b59a04..ff116a0 100644 --- a/lib-gd32/include/logic_analyzer.h +++ b/lib-gd32/include/logic_analyzer.h @@ -2,7 +2,7 @@ * @file logic_analyzer.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,9 @@ * THE SOFTWARE. */ +#ifndef LOGIC_ANALYZER_H_ +#define LOGIC_ANALYZER_H_ + #include "gd32.h" namespace logic_analyzer { @@ -37,7 +40,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH0_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH0_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH0_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH0_GPIOx) = LOGIC_ANALYZER_CH0_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH1_RCU_GPIOx); # if !defined (GD32F4XX) @@ -46,7 +51,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH1_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH1_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH1_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH1_GPIOx) = LOGIC_ANALYZER_CH1_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH2_RCU_GPIOx); # if !defined (GD32F4XX) @@ -55,7 +62,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH2_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH2_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH2_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH2_GPIOx) = LOGIC_ANALYZER_CH2_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH3_RCU_GPIOx); # if !defined (GD32F4XX) @@ -64,7 +73,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH3_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH3_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH3_GPIOx) = LOGIC_ANALYZER_CH3_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH4_RCU_GPIOx); # if !defined (GD32F4XX) @@ -73,7 +84,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH4_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH4_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH4_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH4_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH4_GPIOx) = LOGIC_ANALYZER_CH4_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH5_RCU_GPIOx); # if !defined (GD32F4XX) @@ -82,7 +95,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH5_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH5_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH5_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH5_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH5_GPIOx) = LOGIC_ANALYZER_CH5_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH6_RCU_GPIOx); # if !defined (GD32F4XX) @@ -91,7 +106,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH6_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH6_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH6_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH6_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH6_GPIOx) = LOGIC_ANALYZER_CH6_GPIO_PINx; # endif + # if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH7_RCU_GPIOx); # if !defined (GD32F4XX) @@ -100,7 +117,9 @@ static void init() { gpio_mode_set(LOGIC_ANALYZER_CH7_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH7_GPIO_PINx); gpio_output_options_set(LOGIC_ANALYZER_CH7_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH7_GPIO_PINx); # endif + GPIO_BC(LOGIC_ANALYZER_CH7_GPIOx) = LOGIC_ANALYZER_CH7_GPIO_PINx; # endif + #endif } @@ -203,7 +222,4 @@ static void ch7_set() { } // namespace logic_analyzer -#ifndef LOGIC_ANALYZER_H_ -#define LOGIC_ANALYZER_H_ - #endif /* LOGIC_ANALYZER_H_ */ diff --git a/lib-gd32/src/gd32_adc.cpp b/lib-gd32/src/gd32_adc.cpp index 1a3c49c..4347921 100644 --- a/lib-gd32/src/gd32_adc.cpp +++ b/lib-gd32/src/gd32_adc.cpp @@ -2,7 +2,7 @@ * @file gd32_adc.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -88,20 +88,20 @@ void gd32_adc_init(void) { float gd32_adc_gettemp(void) { /* value convert */ - const float temperature = (1.43 - ADC_IDATA0(ADC0) * 3.3 / 4096) * 1000 / 4.3 + 25; + const float temperature = (1.43f - ADC_IDATA0(ADC0) * 3.3f / 4096) * 1000 / 4.3f + 25; adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return temperature; } float gd32_adc_getvref(void) { - const float vref_value = (ADC_IDATA1(ADC0) * 3.3 / 4096); + const float vref_value = (ADC_IDATA1(ADC0) * 3.3f / 4096); adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return vref_value; } #if defined (GD32F4XX) float gd32_adc_getvbat(void) { - const float vref_value = (ADC_IDATA2(ADC0) * 3.3 / 4096) * 4; + const float vref_value = (ADC_IDATA2(ADC0) * 3.3f / 4096) * 4; adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return vref_value; } diff --git a/lib-gd32/src/gd32_i2c.cpp b/lib-gd32/src/gd32_i2c.cpp index 4c35bc8..2a23399 100644 --- a/lib-gd32/src/gd32_i2c.cpp +++ b/lib-gd32/src/gd32_i2c.cpp @@ -104,7 +104,7 @@ static int32_t _stop(void) { static int32_t _senddata(uint8_t *pData, uint32_t nCount) { int32_t nTimeout; - for (auto i = 0; i < nCount; i++) { + for (uint32_t i = 0; i < nCount; i++) { i2c_data_transmit(I2C_PERIPH, *pData); /* point to the next byte to be written */ @@ -188,7 +188,7 @@ void gd32_i2c_set_address(uint8_t nAddress) { uint8_t gd32_i2c_write(const char *pBuffer, uint32_t nLength) { const auto ret = _write((char *)pBuffer, (int) nLength); - return (uint8_t)-ret;; + return (uint8_t)-ret; } uint8_t gd32_i2c_read(char *pBuffer, uint32_t nLength) { diff --git a/lib-gd32/src/gd32_uart0.c b/lib-gd32/src/gd32_uart0.c index d6e63f8..17335bd 100644 --- a/lib-gd32/src/gd32_uart0.c +++ b/lib-gd32/src/gd32_uart0.c @@ -2,7 +2,7 @@ * @file gd32_uart0.c * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,29 +23,12 @@ * THE SOFTWARE. */ -#include #include #include -#include "gd32.h" -#include "gd32_uart.h" +extern void uart0_putc(int); -void uart0_init(void) { - gd32_uart_begin(USART0, 115200U, GD32_UART_BITS_8, GD32_UART_PARITY_NONE, GD32_UART_STOP_1BIT); -} - -void uart0_putc(int c) { - if (c == '\n') { - while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) - ; - USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) '\r'); - } - - while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) - ; - - USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) c); -} +static char s_buffer[128]; void uart0_puts(const char *s) { while (*s != '\0') { @@ -58,8 +41,6 @@ void uart0_puts(const char *s) { // uart0_putc('\n'); //TODO Add '\n' } -static char s_buffer[128]; - int uart0_printf(const char *fmt, ...) { va_list arp; diff --git a/lib-gd32/src/i2s_psc_config_dump.cpp b/lib-gd32/src/i2s_psc_config_dump.cpp index db86c1c..e364ec2 100644 --- a/lib-gd32/src/i2s_psc_config_dump.cpp +++ b/lib-gd32/src/i2s_psc_config_dump.cpp @@ -2,7 +2,7 @@ * @file i2s_psc_config_dump_cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,7 +45,7 @@ #define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ #define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ -void i2s_psc_config_dump(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) { +void i2s_psc_config_dump(__attribute__((unused)) uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) { uint32_t i2sdiv = 2U, i2sof = 0U; uint32_t clks = 0U; uint32_t i2sclock = 0U; diff --git a/lib-gd32/src/micros.cpp b/lib-gd32/src/micros.cpp deleted file mode 100644 index 0834917..0000000 --- a/lib-gd32/src/micros.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file micros.cpp - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -#include - -#include "gd32.h" - -#if defined (GD32F20X_CL) -/** - * Timer 9 is Master -> TIMER9_TRGO - * Timer 8 is Slave -> ITI2 - */ - -static void _master_init() { - rcu_periph_clock_enable(RCU_TIMER9); - - timer_deinit(TIMER9); - TIMER_CNT(TIMER9) = 0; - - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = TIMER_PSC_1MHZ; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = static_cast(~0); - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - - timer_init(TIMER9, &timer_initpara); - - timer_master_slave_mode_config(TIMER9, TIMER_MASTER_SLAVE_MODE_DISABLE); - timer_master_output_trigger_source_select(TIMER9, TIMER_TRI_OUT_SRC_UPDATE); - - timer_enable(TIMER9); -} - -static void _slave_init() { - rcu_periph_clock_enable(RCU_TIMER8); - - timer_deinit(TIMER8); - TIMER_CNT(TIMER8) = 0; - - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = 0; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = static_cast(~0); - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - - timer_init(TIMER8, &timer_initpara); - - timer_master_slave_mode_config(TIMER8, TIMER_MASTER_SLAVE_MODE_DISABLE); - timer_slave_mode_select(TIMER8, TIMER_SLAVE_MODE_EXTERNAL0); - timer_input_trigger_source_select(TIMER8, TIMER_SMCFG_TRGSEL_ITI2); - - timer_enable(TIMER8); -} - -void micros_init(void) { - _slave_init(); - _master_init(); -} -#elif defined (GD32F4XX) -void micros_init() { - rcu_periph_clock_enable(RCU_TIMER4); - - timer_deinit(TIMER4); - TIMER_CNT(TIMER4) = 0; - - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = TIMER_PSC_1MHZ; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = static_cast(~0); - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - - timer_init(TIMER4, &timer_initpara); - - timer_enable(TIMER4); -} -#else -void micros_init() { -} -#endif diff --git a/lib-gd32/src/softuart0/gd32_uart0.c b/lib-gd32/src/softuart0/gd32_uart0.c new file mode 100644 index 0000000..7f8dee8 --- /dev/null +++ b/lib-gd32/src/softuart0/gd32_uart0.c @@ -0,0 +1,189 @@ +/** + * @file gd32_uart0.c + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (NDEBUG) +# undef NDEBUG +#endif + +#include +#include +#include + +#include "gd32.h" + +#if !defined (SOFTUART_TX_PINx) +# define SOFTUART_TX_PINx GPIO_PIN_9 +# define SOFTUART_TX_GPIOx GPIOA +# define SOFTUART_TX_RCU_GPIOx RCU_GPIOA +#endif + +#if defined (GD32F4XX) +# define TIMER_CLOCK (APB2_CLOCK_FREQ * 2) +#else +# define TIMER_CLOCK (APB2_CLOCK_FREQ) +#endif + +#define BAUD_RATE (115200U) +#define TIMER_PERIOD ((TIMER_CLOCK / BAUD_RATE) - 1U) +#define BUFFER_SIZE (128U) + +typedef enum { + SOFTUART_IDLE, + SOFTUART_START_BIT, + SOFTUART_DATA, + SOFTUART_STOP_BIT, +} softuart_state; + +struct circular_buffer { + uint8_t buffer[BUFFER_SIZE]; + uint32_t head; + uint32_t tail; + bool full; +}; + +static volatile softuart_state s_state; +static volatile struct circular_buffer s_circular_buffer; +static volatile uint8_t s_data; +static volatile uint8_t s_shift; + +static bool is_circular_buffer_empty() { + return (!s_circular_buffer.full && (s_circular_buffer.head == s_circular_buffer.tail)); +} + +void TIMER0_UP_TIMER9_IRQHandler() { + GPIO_BOP(LED3_GPIOx) = LED3_GPIO_PINx; + + switch (s_state) { + case SOFTUART_IDLE: + break; + case SOFTUART_START_BIT: + GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + s_state = SOFTUART_DATA; + s_data = s_circular_buffer.buffer[s_circular_buffer.tail]; + s_circular_buffer.tail = (s_circular_buffer.tail + 1) & (BUFFER_SIZE - 1); + s_circular_buffer.full = false; + s_shift = 0; + break; + case SOFTUART_DATA: + if (s_data & (1U << s_shift)) { + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + } else { + GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + } + + s_shift++; + + if (s_shift == 8) { + s_state = SOFTUART_STOP_BIT; + } + break; + case SOFTUART_STOP_BIT: + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + if (is_circular_buffer_empty()) { + s_state = SOFTUART_IDLE; + timer_disable(TIMER9); + } else { + s_state = SOFTUART_START_BIT; + } + break; + default: + break; + } + + timer_interrupt_flag_clear(TIMER9, TIMER_INT_FLAG_UP); + + GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; +} + +void uart0_init() { + rcu_periph_clock_enable (LED3_RCU_GPIOx); +#if !defined (GD32F4XX) + gpio_init(LED3_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED3_GPIO_PINx); +#else + gpio_mode_set(LED3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, LED3_GPIO_PINx); + gpio_output_options_set(LED3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED3_GPIO_PINx); + gpio_af_set(LED3_GPIOx, GPIO_AF_0, LED3_GPIO_PINx); +#endif + + GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; + + rcu_periph_clock_enable (SOFTUART_TX_RCU_GPIOx); + +#if !defined (GD32F4XX) + gpio_init(SOFTUART_TX_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFTUART_TX_PINx); +#else + gpio_mode_set(SOFTUART_TX_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, SOFTUART_TX_PINx); + gpio_output_options_set(SOFTUART_TX_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SOFTUART_TX_PINx); + gpio_af_set(SOFTUART_TX_GPIOx, GPIO_AF_0, SOFTUART_TX_PINx); +#endif + + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + rcu_periph_clock_enable(RCU_TIMER9); + + timer_deinit(TIMER9); + + timer_parameter_struct timer_initpara; + timer_initpara.prescaler = 0; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = TIMER_PERIOD; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + + timer_init(TIMER9, &timer_initpara); + + timer_flag_clear(TIMER9, ~0); + timer_interrupt_flag_clear(TIMER9, ~0); + + timer_interrupt_enable(TIMER9, TIMER_INT_UP); + + NVIC_SetPriority(TIMER0_UP_TIMER9_IRQn, 2); + NVIC_EnableIRQ(TIMER0_UP_TIMER9_IRQn); +} + +static void _putc(int c) { + while (s_circular_buffer.full) + ; + + s_circular_buffer.buffer[s_circular_buffer.head] = (uint8_t) c; + s_circular_buffer.head = (s_circular_buffer.head + 1) & (BUFFER_SIZE - 1); + s_circular_buffer.full = s_circular_buffer.head == s_circular_buffer.tail; + + if (s_state == SOFTUART_IDLE) { + timer_counter_value_config(TIMER9, 0); + timer_enable(TIMER9); + s_state = SOFTUART_START_BIT; + } +} + +void uart0_putc(int c) { + if (c == '\n') { + _putc('\r'); + } + + _putc(c); +} diff --git a/lib-gd32/src/stack_debug.c b/lib-gd32/src/stack_debug.c deleted file mode 100644 index ae7f713..0000000 --- a/lib-gd32/src/stack_debug.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * stack_debug.c - */ - - -#include - -extern unsigned char _heap_end; -extern unsigned char _sp; - -void stack_debug_init() { - uint32_t *start = (uint32_t *) &_heap_end; - uint32_t *end = (uint32_t *) &_sp; - - while (start < end) { - *start = 0xABCDABCD; - start++; - } -} - -#include - -void stack_debug_print(uint32_t line) { - uint32_t *start = (uint32_t *) &_heap_end; - uint32_t *end = (uint32_t *) &_sp; - uint32_t size = end - start; - - uint32_t *p = (uint32_t *) &_heap_end; - - while (p < end) { - if (*p != 0xABCDABCD) { - break; - } - p++; - } - - printf("%u: stack %p:%p:%p [%u:%u]\n", line, start, p, end, 4 * (p - start), ((p - start) * 100) / size); -} diff --git a/include/limits.h b/lib-gd32/src/uart0/gd32_uart0.c similarity index 64% rename from include/limits.h rename to lib-gd32/src/uart0/gd32_uart0.c index 97e3aaf..e7c531f 100644 --- a/include/limits.h +++ b/lib-gd32/src/uart0/gd32_uart0.c @@ -1,8 +1,8 @@ /** - * @file limits.h + * @file gd32_uart0.c * */ -/* Copyright (C) 2017 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,19 +23,25 @@ * THE SOFTWARE. */ -#ifndef LIMITS_H_ -#define LIMITS_H_ +#include +#include -/* Minimum and maximum values a `signed int' can hold. */ -# ifndef __INT_MAX__ -# define __INT_MAX__ 2147483647 -# endif -# undef INT_MIN -# define INT_MIN (-INT_MAX-1) -# undef INT_MAX -# define INT_MAX __INT_MAX__ +#include "gd32.h" +#include "gd32_uart.h" -#undef CHAR_BIT -#define CHAR_BIT 8 +void uart0_init(void) { + gd32_uart_begin(USART0, 115200U, GD32_UART_BITS_8, GD32_UART_PARITY_NONE, GD32_UART_STOP_1BIT); +} -#endif /* LIMITS_H_ */ +void uart0_putc(int c) { + if (c == '\n') { + while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) + ; + USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) '\r'); + } + + while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) + ; + + USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) c); +} diff --git a/lib-hal/Makefile.GD32 b/lib-hal/Makefile.GD32 index bd89f41..a03d2ca 100644 --- a/lib-hal/Makefile.GD32 +++ b/lib-hal/Makefile.GD32 @@ -4,6 +4,23 @@ ifneq ($(MAKE_FLAGS),) ifeq ($(findstring USE_LEDBLINK_BITBANGING595,$(MAKE_FLAGS)), USE_LEDBLINK_BITBANGING595) EXTRA_SRCDIR=src/gd32/bitbanging endif + + ifneq (,$(findstring DEBUG_EMAC,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=debug/emac/gd32 + endif + + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=device/usb/host/gd32 + EXTRA_INCLUDES+=device/usb/host/gd32 + endif +else + EXTRA_SRCDIR+=debug/emac/gd32 + EXTRA_SRCDIR+=ff12c ff12c/option + + EXTRA_SRCDIR+=device/usb/host/gd32 + EXTRA_INCLUDES+=device/usb/host/gd32 + + DEFINES=ENABLE_USB_HOST CONFIG_USB_HOST_MSC endif include Rules.mk diff --git a/lib-hal/Rules.mk b/lib-hal/Rules.mk old mode 100755 new mode 100644 index e6e277c..cea16ff --- a/lib-hal/Rules.mk +++ b/lib-hal/Rules.mk @@ -4,10 +4,15 @@ ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONSOLE_I2C,$(MAKE_FLAGS))) EXTRA_SRCDIR+=console/i2c else - EXTRA_SRCDIR+=console/uart0 - endif - ifneq ($(findstring NDEBUG,$(MAKE_FLAGS)), NDEBUG) - EXTRA_SRCDIR+=debug + ifneq (,$(findstring CONSOLE_FB,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=console console/h3 + else + ifneq (,$(findstring CONSOLE_NULL,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=console/null + else + EXTRA_SRCDIR+=console/uart0 + endif + endif endif ifneq ($(findstring DISABLE_RTC,$(MAKE_FLAGS)), DISABLE_RTC) EXTRA_SRCDIR+=rtc @@ -17,6 +22,15 @@ ifneq ($(MAKE_FLAGS),) EXTRA_SRCDIR+=rtc/gd32 endif endif + ifneq (,$(findstring DEBUG_I2C,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=debug/i2c + EXTRA_INCLUDES+=debug/i2c + endif + ifneq (,$(findstring DEBUG_STACK,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=debug/stack + endif else - EXTRA_SRCDIR+=console/i2c console/uart0 rtc debug + DEFINES+=DEBUG_I2C DEBUG_STACK + EXTRA_INCLUDES+=debug/i2c + EXTRA_SRCDIR+=console/i2c console/null console/uart0 rtc debug/stack debug/i2c endif diff --git a/lib-gd32/src/bitbanging595.cpp b/lib-hal/console/font.S similarity index 85% rename from lib-gd32/src/bitbanging595.cpp rename to lib-hal/console/font.S index f934567..6f5b143 100644 --- a/lib-gd32/src/bitbanging595.cpp +++ b/lib-hal/console/font.S @@ -1,28 +1,29 @@ -/** - * @file bitbanging595.cpp - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "gd32_bitbanging595.h" - -BitBanging595 *BitBanging595::s_pThis; +/** + * @file font.S + * + */ +/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@raspberrypi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +.align 4 +.global FONT +FONT: + .incbin "../console/font.bin" diff --git a/lib-hal/console/h3/console.c b/lib-hal/console/h3/console.c new file mode 100644 index 0000000..809a5be --- /dev/null +++ b/lib-hal/console/h3/console.c @@ -0,0 +1,381 @@ +/** + * @file console.c + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "console.h" + +#include "device/fb.h" + +#include "arm/arm.h" + +extern unsigned char FONT[] __attribute__((aligned(4))); + +static const uint32_t FB_CHAR_W = 8; +static const uint32_t FB_CHAR_H = 16; + +static uint32_t current_x = 0; +static uint32_t current_y = 0; +static uint32_t saved_x = 0; +static uint32_t saved_y = 0; + +static uint32_t top_row = 0; + +static uint32_t cur_fore = CONSOLE_WHITE; +static uint32_t cur_back = CONSOLE_BLACK; +static uint32_t saved_fore = CONSOLE_WHITE; +static uint32_t saved_back = CONSOLE_BLACK; + +#if defined(USE_UBOOT_HDMI) +#undef FB_WIDTH +#define FB_WIDTH fb_width + +#undef FB_HEIGHT +#define FB_HEIGHT fb_height + +#undef FB_PITCH +#define FB_PITCH fb_pitch + +#undef FB_ADDRESS +#define FB_ADDRESS fb_addr +#endif + +void __attribute__((cold)) console_init(void) { + const int r = fb_init(); + + if (r == FB_OK) { + console_clear(); + } +} + +uint32_t console_get_line_width(void) { + return FB_WIDTH / FB_CHAR_W; +} + +void console_set_top_row(uint32_t row) { + if (row > FB_HEIGHT / FB_CHAR_H) { + top_row = 0; + } else { + top_row = row; + } + + current_x = 0; + current_y = row; +} + +inline static void clear_row(uint32_t *address) { + uint32_t i; + + for (i = 0 ; i < (FB_CHAR_H * FB_WIDTH) ; i++) { + *address++ = cur_back; + } +} + +inline static void newline(void) { + uint32_t i; + uint32_t *address; + uint32_t *to; + uint32_t *from; + + current_y++; + current_x = 0; + + if (current_y == FB_HEIGHT / FB_CHAR_H) { + if (top_row == 0) { + /* Pointer to row = 0 */ + to = (uint32_t *) (FB_ADDRESS); + /* Pointer to row = 1 */ + from = to + (FB_CHAR_H * FB_WIDTH); + /* Copy block from {row = 1, rows} to {row = 0, rows - 1} */ + i = ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH); + } else { + to = (uint32_t *) (FB_ADDRESS) + ((FB_CHAR_H * FB_WIDTH) * top_row); + from = to + (FB_CHAR_H * FB_WIDTH); + i = ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH - ((FB_CHAR_H * FB_WIDTH) * top_row)); + } + + memcpy_blk(to, from, i/8); + + /* Clear last row */ + address = (uint32_t *)(FB_ADDRESS) + ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH); + clear_row(address); + + current_y--; + } +} + +inline static void draw_pixel(uint32_t x, uint32_t y, uint32_t color) { + volatile uint32_t *address = (volatile uint32_t *)(FB_ADDRESS + (x * FB_BYTES_PER_PIXEL) + (y * FB_WIDTH * FB_BYTES_PER_PIXEL)); + *address = (uint32_t) color; +} + +inline static void draw_char(int c, uint32_t x, uint32_t y, uint32_t fore, uint32_t back) { + uint32_t i, j; + uint8_t line; + unsigned char *p = FONT + (c * (int) FB_CHAR_H); + + for (i = 0; i < FB_CHAR_H; i++) { + line = (uint8_t) *p++; + for (j = x; j < (FB_CHAR_W + x); j++) { + if ((line & 0x1) != 0) { + draw_pixel(j, y, fore); + } else { + draw_pixel(j, y, back); + } + line >>= 1; + } + y++; + } +} + +int console_draw_char(int ch, uint16_t x, uint16_t y, uint32_t fore, uint32_t back) { + draw_char(ch, x * FB_CHAR_W, y * FB_CHAR_H, fore, back); + return (int)ch; +} + +void console_putc(int ch) { + if (ch == (int)'\n') { + newline(); + } else if (ch == (int)'\r') { + current_x = 0; + } else if (ch == (int)'\t') { + current_x += 4; + } else { + draw_char(ch, current_x * FB_CHAR_W, current_y * FB_CHAR_H, cur_fore, cur_back); + current_x++; + if (current_x == FB_WIDTH / FB_CHAR_W) { + newline(); + } + } +} + +void console_puts(const char *s) { + char c; + while ((c = *s++) != (char) 0) { + console_putc((int) c); + } +} + +void console_write(const char *s, unsigned int n) { + char c; + + while (((c = *s++) != (char) 0) && (n-- != 0)) { + console_putc((int) c); + } +} + +void console_error(const char *s) { + uint32_t fore_current = cur_fore; + uint32_t back_current = cur_back; + + cur_fore = CONSOLE_RED; + cur_back = CONSOLE_BLACK; + + console_puts("Error <"); + console_puts((char *) s); + console_puts(">\n"); + + cur_fore = fore_current; + cur_back = back_current; +} + +void console_status(uint32_t color, const char *s) { + const uint32_t fore_current = cur_fore; + const uint32_t back_current = cur_back; + + const uint32_t s_y = current_y; + const uint32_t s_x = current_x; + + console_clear_line(29); + + cur_fore = color; + cur_back = CONSOLE_BLACK; + + console_puts((char *)s); + + current_y = s_y; + current_x = s_x; + + cur_fore = fore_current; + cur_back = back_current; +} + +#define TO_HEX(i) ((i) < 10) ? (uint8_t)'0' + (i) : (uint8_t)'A' + ((i) - (uint8_t)10) + +void console_puthex(uint8_t data) { + console_putc((int) (TO_HEX(((data & 0xF0) >> 4)))); + console_putc((int) (TO_HEX(data & 0x0F))); +} + +void console_puthex_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { + uint32_t fore_current = cur_fore; + uint32_t back_current = cur_back; + + cur_fore = fore; + cur_back = back; + + (void) console_putc((int) (TO_HEX(((data & 0xF0) >> 4)))); + (void) console_putc((int) (TO_HEX(data & 0x0F))); + + cur_fore = fore_current; + cur_back = back_current; +} + +void console_putpct_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { + uint32_t fore_current = cur_fore; + uint32_t back_current = cur_back; + + cur_fore = fore; + cur_back = back; + + if (data < 100) { + console_putc((int) ((char) '0' + (char) (data / 10))); + console_putc((int) ((char) '0' + (char) (data % 10))); + } else { + console_puts("%%"); + } + + cur_fore = fore_current; + cur_back = back_current; +} + +void console_put3dec_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { + uint32_t fore_current = cur_fore; + uint32_t back_current = cur_back; + + cur_fore = fore; + cur_back = back; + + const uint8_t i = data / 100; + + (void) console_putc((int) ((char) '0' + (char) i)); + + data = (uint8_t)(data - (i * 100)); + + console_putc((int) ((char) '0' + (char) (data / 10))); + console_putc((int) ((char) '0' + (char) (data % 10))); + + cur_fore = fore_current; + cur_back = back_current; +} + +void console_newline(void){ + newline(); +} + +void console_clear(void) { + uint32_t *address = (uint32_t *)(fb_addr); + uint32_t i; + + for (i = 0; i < (FB_HEIGHT * FB_WIDTH); i++) { + *address++ = (uint32_t) cur_back; + } + + current_x = 0; + current_y = 0; +} + +void console_set_cursor(uint32_t x, uint32_t y) { + if (x > FB_WIDTH / FB_CHAR_W) + current_x = 0; + else + current_x = x; + + if (y > FB_HEIGHT / FB_CHAR_H) + current_y = 0; + else + current_y = y; +} + +void console_save_cursor(void) { + saved_y = current_y; + saved_x = current_x; + saved_back = cur_back; + saved_fore = cur_fore; +} + +void console_restore_cursor(void) { + current_y = saved_y; + current_x = saved_x; + cur_back = saved_back; + cur_fore = saved_fore; +} + +void console_save_color(void) { + saved_back = cur_back; + saved_fore = cur_fore; +} + +void console_restore_color(void) { + cur_back = saved_back; + cur_fore = saved_fore; +} + +void console_set_fg_color(uint32_t fore) { + cur_fore = fore; +} + +void console_set_bg_color(uint32_t back) { + cur_back = back; +} + +void console_set_fg_bg_color(uint32_t fore, uint32_t back) { + cur_fore = fore; + cur_back = back; +} + +void console_clear_line(uint32_t line) { + uint32_t *address; + + if (line > FB_HEIGHT / FB_CHAR_H) { + return; + } else { + current_y = line; + } + + current_x = 0; + + address = (uint32_t *)(fb_addr) + (line * FB_CHAR_H * FB_WIDTH); + clear_row(address); +} + +void console_clear_top_row(void) { + uint32_t line; + uint32_t *address; + + for (line = top_row; line < (FB_HEIGHT / FB_CHAR_H) - 1; line++) { + address = (uint32_t*) (fb_addr) + (line * FB_CHAR_H * FB_WIDTH); + clear_row(address); + } + + current_x = 0; + current_y = top_row; +} + +void console_putpixel(uint32_t x, uint32_t y, uint32_t color) { + draw_pixel(x, y, color); +} + diff --git a/lib-hal/console/i2c/console_i2c.c b/lib-hal/console/i2c/console.c similarity index 97% rename from lib-hal/console/i2c/console_i2c.c rename to lib-hal/console/i2c/console.c index 56e2d3f..d33e8a7 100644 --- a/lib-hal/console/i2c/console_i2c.c +++ b/lib-hal/console/i2c/console.c @@ -1,8 +1,8 @@ /** - * @file console_i2c.c + * @file console.c * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -157,13 +157,13 @@ static void set_baud(uint32_t nBaud) { write_register(SC16IS7X0_LCR, nRegisterLCR); } -int __attribute__((cold)) console_init(void) { +void __attribute__((cold)) console_init(void) { FUNC_PREFIX(i2c_begin()); s_isConnected = is_connected(CONSOLE_I2C_ADDRESS, 100000); if (!s_isConnected) { - return -1; + return; } uint8_t LCR = LCR_BITS8; @@ -178,7 +178,7 @@ int __attribute__((cold)) console_init(void) { if ((read_register(SC16IS7X0_SPR) != test_character)) { s_isConnected = false; - return -2; + return; } s_isConnected = true; @@ -196,8 +196,6 @@ int __attribute__((cold)) console_init(void) { write_register(SC16IS7X0_FCR, (uint8_t) (FCR_TX_FIFO_RST)); write_register(SC16IS7X0_FCR, FCR_ENABLE_FIFO); - - return CONSOLE_OK; } void console_putc(int c) { diff --git a/include/stdarg.h b/lib-hal/console/null/console.c old mode 100644 new mode 100755 similarity index 68% rename from include/stdarg.h rename to lib-hal/console/null/console.c index a2e970d..49df711 --- a/include/stdarg.h +++ b/lib-hal/console/null/console.c @@ -1,8 +1,8 @@ /** - * @file stdarg.h + * @file console.c * */ -/* Copyright (C) 2017 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,22 @@ * THE SOFTWARE. */ -#ifndef STDARG_H_ -#define STDARG_H_ +#include -typedef __builtin_va_list va_list; +void console_init(void) { +} -#define va_start(arg, last) __builtin_va_start (arg, last) -#define va_end(arg) __builtin_va_end (arg) -#define va_arg(arg, type) __builtin_va_arg (arg, type) +void console_putc(__attribute__((unused)) int i) { +} -#endif /* STDARG_H_ */ +void console_puts(__attribute__((unused)) const char *p) { +} + +void console_write(__attribute__((unused)) const char *p, __attribute__((unused)) unsigned int i) { +} + +void console_status(__attribute__((unused)) uint32_t i, __attribute__((unused)) const char *p) { +} + +void console_error(__attribute__((unused)) const char *p) { +} diff --git a/lib-hal/console/uart0/console_uart0.c b/lib-hal/console/uart0/console.c similarity index 94% rename from lib-hal/console/uart0/console_uart0.c rename to lib-hal/console/uart0/console.c index 46f7d6b..9fca1a3 100644 --- a/lib-hal/console/uart0/console_uart0.c +++ b/lib-hal/console/uart0/console.c @@ -1,8 +1,8 @@ /** - * @file console_uart0.c + * @file console.c * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,13 +31,11 @@ extern void uart0_init(void); extern void uart0_putc(int); extern void uart0_puts(const char *); -int __attribute__((cold)) console_init(void) { +void __attribute__((cold)) console_init(void) { uart0_init(); console_set_fg_color(CONSOLE_WHITE); console_set_bg_color(CONSOLE_BLACK); - - return CONSOLE_OK; } void console_putc(int c) { diff --git a/include/stddef.h b/lib-hal/debug/emac/gd32/emac_debug.cpp similarity index 72% rename from include/stddef.h rename to lib-hal/debug/emac/gd32/emac_debug.cpp index db6355f..b42aa6c 100644 --- a/include/stddef.h +++ b/lib-hal/debug/emac/gd32/emac_debug.cpp @@ -1,8 +1,8 @@ /** - * @file stddef.h + * @file emac_debug.cpp * */ -/* Copyright (C) 2017 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,17 +23,18 @@ * THE SOFTWARE. */ -#ifndef STDDEF_H_ -#define STDDEF_H_ +#include -#ifndef __cplusplus -#define NULL ((void *)0) -#else /* C++ */ -#define NULL 0 -#endif /* C++ */ +#include "gd32.h" -typedef unsigned int size_t; +static uint32_t s_nCounter; -typedef int ptrdiff_t; +void emac_debug_run() { + uint32_t rxfifo_drop; + uint32_t rxdma_drop; + enet_missed_frame_counter_get(&rxfifo_drop, &rxdma_drop); -#endif /* STDDEF_H_ */ + if ((rxfifo_drop != 0) || (rxdma_drop != 0)) { + printf("%u: RxFIFO: %u RxDMA: %u\n", ++s_nCounter, rxfifo_drop, rxdma_drop); + } +} diff --git a/lib-hal/debug/i2cdetect.cpp b/lib-hal/debug/i2c/i2cdetect.cpp similarity index 100% rename from lib-hal/debug/i2cdetect.cpp rename to lib-hal/debug/i2c/i2cdetect.cpp diff --git a/lib-hal/debug/i2cdetect.h b/lib-hal/debug/i2c/i2cdetect.h similarity index 100% rename from lib-hal/debug/i2cdetect.h rename to lib-hal/debug/i2c/i2cdetect.h diff --git a/lib-hal/debug/stack/stack_debug.cpp b/lib-hal/debug/stack/stack_debug.cpp new file mode 100644 index 0000000..45eac74 --- /dev/null +++ b/lib-hal/debug/stack/stack_debug.cpp @@ -0,0 +1,96 @@ +/** + * @file stack_debug.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +extern unsigned char stack_low; +extern unsigned char _sp; + +static constexpr uint32_t MAGIC_WORD = 0xABCDABCD; + +extern "C" { +void stack_debug_init() { + auto *pStart = reinterpret_cast(&stack_low); + auto *pEnd = reinterpret_cast( &_sp); + + while (pStart < pEnd) { + *pStart = MAGIC_WORD; + pStart++; + } +} +} + +#include + +static uint32_t s_nUsedBytesPrevious; + +void stack_debug_print() { + const auto *pStart = reinterpret_cast(&stack_low); + const auto *pEnd = reinterpret_cast(&_sp); + const auto nSize = pEnd - pStart; + + auto *p = pStart; + + while (p < pEnd) { + if (*p != MAGIC_WORD) { + break; + } + p++; + } + + const auto nUsedBytes = static_cast(4 * (pEnd - p)); + const auto nFreeBytes = static_cast(4 * (p - pStart)); + const auto nFreePct = ((p - pStart) * 100) / nSize; + + if (s_nUsedBytesPrevious != nUsedBytes) { + s_nUsedBytesPrevious = nUsedBytes; + if (nFreePct == 0) { + printf("\x1b[31m"); + } else if (nFreePct == 1) { + printf("\x1b[33m"); + } else { + printf("\x1b[34m"); + } + +#ifndef NDEBUG + printf("Stack: Size %uKB, [%p:%p:%p], Used: %u, Free: %u [%u]", nSize / (1024 / 4), pStart, p, pEnd, nUsedBytes, nFreeBytes, nFreePct); +#else + printf("Stack: Size %uKB, Used: %u, Free: %u", nSize / (1024 / 4), nUsedBytes, nFreeBytes); +#endif + printf("\x1b[39m\n"); + } +} + +#include + +static time_t s_nTimePrevious; + +void stack_debug_run() { + auto nTime = time(nullptr); + if (nTime != s_nTimePrevious) { + s_nTimePrevious = nTime; + stack_debug_print(); + } +} diff --git a/lib-hal/device/usb/host/gd32/usb_host.cpp b/lib-hal/device/usb/host/gd32/usb_host.cpp new file mode 100644 index 0000000..c0b2ff5 --- /dev/null +++ b/lib-hal/device/usb/host/gd32/usb_host.cpp @@ -0,0 +1,127 @@ +/** + * usb_host.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "gd32.h" + +extern "C" { +#include "usbh_core.h" +#include "usbh_msc_core.h" + +#include "drv_usbh_int.h" +} + +static void usb_gpio_config() { +#if !defined (GD32F4XX) +#else + rcu_periph_clock_enable(RCU_SYSCFG); + + rcu_periph_clock_enable(RCU_GPIOA); + + /* USBFS_DM(PA11) and USBFS_DP(PA12) GPIO pin configuration */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_11 | GPIO_PIN_12); + + gpio_af_set(GPIOA, GPIO_AF_10, GPIO_PIN_11 | GPIO_PIN_12); +#endif +} + +#if !defined (GD32F4XX) +__IO uint32_t usbfs_prescaler = 0U; +__IO uint16_t timer_prescaler = 5U; +#else +#endif + +static void usb_rcu_config() { +#if !defined (GD32F4XX) + uint32_t system_clock = rcu_clock_freq_get(CK_SYS); + + if (48000000U == system_clock) { + timer_prescaler = 3U; + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1; + } else if (72000000U == system_clock) { + timer_prescaler = 5U; + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1_5; + } else if (96000000U == system_clock) { + timer_prescaler = 7U; + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV2; + } else if (120000000U == system_clock) { + timer_prescaler = 9U; + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV2_5; + } else { + /* reserved */ + } + + rcu_usbfs_trng_clock_config(usbfs_prescaler); + rcu_periph_clock_enable(RCU_USBFS); +#else + rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLQ); + rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M); + + rcu_periph_clock_enable(RCU_USBFS); +#endif +} + +static void usb_intr_config() { + nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); + nvic_irq_enable((uint8_t)USBFS_IRQn, 2U, 0U); + +#if !defined (GD32F4XX) +#else +#endif +} + +usbh_host usb_host_msc; +#if !defined (GD32F4XX) +extern usb_core_driver usbh_core; +#else +usb_core_driver usbh_core; +#endif +extern usbh_user_cb usr_cb; + +void usb_init() { + usb_gpio_config(); + usb_rcu_config(); + + usbh_class_register(&usb_host_msc, &usbh_msc); + +#if !defined (GD32F4XX) + usbh_init (&usb_host_msc, &usr_cb); +#else + usbh_init(&usb_host_msc, + &usbh_core, + USB_CORE_ENUM_FS, + &usr_cb); +#endif + + usb_intr_config (); +} + +extern "C" { +void USBFS_IRQHandler(void) { + usbh_isr (&usbh_core); +} +} diff --git a/lib-hal/device/usb/host/gd32/usb_host_msc.cpp b/lib-hal/device/usb/host/gd32/usb_host_msc.cpp new file mode 100644 index 0000000..227d0b1 --- /dev/null +++ b/lib-hal/device/usb/host/gd32/usb_host_msc.cpp @@ -0,0 +1,159 @@ +/** + * usb_host_msc.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "gd32.h" + +extern "C" { +#include "usb_host_msc.h" +#include "usbh_core.h" +} + +usbh_user_cb usr_cb = { + usbh_user_init, + usbh_user_deinit, + usbh_user_device_connected, + usbh_user_device_reset, + usbh_user_device_disconnected, + usbh_user_over_current_detected, + usbh_user_device_speed_detected, + usbh_user_device_desc_available, + usbh_user_device_address_assigned, + usbh_user_configuration_descavailable, + usbh_user_manufacturer_string, + usbh_user_product_string, + usbh_user_serialnum_string, + usbh_user_enumeration_finish, + usbh_user_userinput, + usbh_usr_msc_application, + usbh_user_device_not_supported, + usbh_user_unrecovered_error +}; + +#define USBH_USR_FS_INIT 0 +#define USBH_USR_FS_READLIST 1 +#define USBH_USR_FS_WRITEFILE 2 +#define USBH_USR_FS_DRAW 3 +#define USBH_USR_FS_DEMOEND 4 + +static uint32_t usbh_usr_application_state = USBH_USR_FS_INIT; + +void usbh_user_init() { + static uint32_t startup = 0U; + + if (0U == startup) { + startup = 1U; + puts("USB host library started."); + } +} + +void usbh_user_deinit() { + usbh_usr_application_state = USBH_USR_FS_INIT; +} + +void usbh_user_device_connected() { + puts("> Device Attached."); +} + +void usbh_user_unrecovered_error() { + puts("> Unrecovered error state."); +} + +void usbh_user_device_disconnected() { + puts("> Device Disconnected."); +} + +void usbh_user_device_reset() { + puts("> Reset the USB device."); +} + +void usbh_user_device_speed_detected(uint32_t device_speed) { + if (PORT_SPEED_HIGH == device_speed) { + puts("> High speed device detected."); + } else if (PORT_SPEED_FULL == device_speed) { + puts("> Full speed device detected."); + } else if (PORT_SPEED_LOW == device_speed) { + puts("> Low speed device detected."); + } else { + puts("> Device Fault."); + } +} + +void usbh_user_device_desc_available(void *device_desc) { + auto *pDevStr = reinterpret_cast(device_desc); + + printf("VID: %04Xh\n", static_cast(pDevStr->idVendor)); + printf("PID: %04Xh\n", static_cast(pDevStr->idProduct)); +} + +void usbh_user_device_address_assigned() { + puts("usbh_user_device_address_assigned"); +} + +void usbh_user_configuration_descavailable(usb_desc_config *cfg_desc, usb_desc_itf *itf_desc, usb_desc_ep *ep_desc) { + auto *id = reinterpret_cast(itf_desc); + + if (0x08U == (*id).bInterfaceClass) { + puts("> Mass storage device connected."); + } else if (0x03U == (*id).bInterfaceClass) { + puts("> HID device connected."); + } +} + +void usbh_user_manufacturer_string(void *manufacturer_string) { + printf("Manufacturer: %s\n", reinterpret_cast(manufacturer_string)); +} + +void usbh_user_product_string(void *product_string) { + printf("Product: %s\n", reinterpret_cast(product_string)); +} + +void usbh_user_serialnum_string(void *serial_num_string) { + printf("Serial Number: %s\n", reinterpret_cast(serial_num_string)); +} + +void usbh_user_enumeration_finish() { + puts("> Enumeration completed."); +} + +void usbh_user_device_not_supported() { + puts("> Device not supported."); +} + +usbh_user_status usbh_user_userinput() { + puts("usbh_user_userinput"); + + return static_cast(1); +} + +void usbh_user_over_current_detected() { + puts("> Overcurrent detected."); +} + +int usbh_usr_msc_application() { + return 0; +} diff --git a/lib-hal/device/usb/host/gd32/usb_host_msc.h b/lib-hal/device/usb/host/gd32/usb_host_msc.h new file mode 100644 index 0000000..7987d40 --- /dev/null +++ b/lib-hal/device/usb/host/gd32/usb_host_msc.h @@ -0,0 +1,70 @@ +/** + * usb_host_msc.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef USB_HOST_MSC_H_ +#define USB_HOST_MSC_H_ + +#include "usbh_core.h" +#include "usb_conf.h" + +/* function declarations */ +/* user operation for host-mode initialization */ +void usbh_user_init(void); +/* deinitialize user state and associated variables */ +void usbh_user_deinit(void); +/* user operation for device attached */ +void usbh_user_device_connected(void); +/* user operation for reset USB Device */ +void usbh_user_device_reset(void); +/* user operation for device disconnect event */ +void usbh_user_device_disconnected(void); +/* user operation for device over current detection event */ +void usbh_user_over_current_detected(void); +/* user operation for detecting device speed */ +void usbh_user_device_speed_detected(uint32_t DeviceSpeed); +/* user operation when device descriptor is available */ +void usbh_user_device_desc_available(void *); +/* usb device is successfully assigned the address */ +void usbh_user_device_address_assigned(void); +/* user operation when configuration descriptor is available */ +void usbh_user_configuration_descavailable(usb_desc_config *cfgDesc, usb_desc_itf *itfDesc, usb_desc_ep *epDesc); +/* user operation when manufacturer string exists */ +void usbh_user_manufacturer_string(void *); +/* user operation when product string exists */ +void usbh_user_product_string(void *); +/* user operation when serialNum string exists */ +void usbh_user_serialnum_string(void *); +/* user response request is displayed to ask for application jump to class */ +void usbh_user_enumeration_finish(void); +/* user action for application state entry */ +usbh_user_status usbh_user_userinput(void); +/* user operation when device is not supported */ +void usbh_user_device_not_supported(void); +/* user operation when unrecovered error happens */ +void usbh_user_unrecovered_error(void); +/* demo application for mass storage */ +int usbh_usr_msc_application(void); + +#endif /* USB_HOST_MSC_H_ */ diff --git a/lib-hal/include/console.h b/lib-hal/include/console.h index b3cda46..38aab85 100644 --- a/lib-hal/include/console.h +++ b/lib-hal/include/console.h @@ -2,7 +2,7 @@ * @file console.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,6 @@ #ifndef CONSOLE_H_ #define CONSOLE_H_ -#define CONSOLE_OK 0 ///< Call console_init() OK - #ifdef __cplusplus # include # define RGB(r, g, b) static_cast(((((r) & 0xFF) << 16) | (((g) & 0xFF) << 8) | (((b) & 0xFF)))) @@ -37,7 +35,6 @@ #endif #if defined (CONSOLE_NULL) || !defined (CONSOLE_FB) -// ANSI colors typedef enum { CONSOLE_BLACK = 0, CONSOLE_RED = 1, @@ -58,12 +55,12 @@ typedef enum { # include "rpi/console_fb.h" # endif #elif defined (CONSOLE_NULL) -inline static int console_init(void) {return CONSOLE_OK;} -inline static console_putc(__attribute__((unused)) int i) {} -inline static void console_puts(__attribute__((unused)) const char *p) {} -inline static void console_write(__attribute__((unused)) const char *p, __attribute__((unused)) unsigned int i) {} -inline static void console_status(__attribute__((unused)) uint32_t i, __attribute__((unused)) const char *p) {} -inline static void console_error(__attribute__((unused)) const char *p) {} +inline void console_init(void) {} +inline void console_putc(__attribute__((unused)) int i) {} +inline void console_puts(__attribute__((unused)) const char *p) {} +inline void console_write(__attribute__((unused)) const char *p, __attribute__((unused)) unsigned int i) {} +inline void console_status(__attribute__((unused)) uint32_t i, __attribute__((unused)) const char *p) {} +inline void console_error(__attribute__((unused)) const char *p) {} #else #ifdef __cplusplus extern "C" { @@ -81,14 +78,14 @@ extern void console_set_bg_color(uint16_t); extern "C" { #endif -extern int console_init(void); - +#if !defined (CONSOLE_NULL) +extern void console_init(void); extern void console_putc(int); extern void console_puts(const char*); extern void console_write(const char*, unsigned int); - extern void console_status(uint32_t, const char *); extern void console_error(const char*); +#endif #ifdef __cplusplus } diff --git a/lib-hal/include/firmwareversion.h b/lib-hal/include/firmwareversion.h index 8d8238b..b2a91a2 100644 --- a/lib-hal/include/firmwareversion.h +++ b/lib-hal/include/firmwareversion.h @@ -28,6 +28,11 @@ #include +#if !defined(STR_HELPER) +# define STR_HELPER(x) #x +# define STR(x) STR_HELPER(x) +#endif + namespace firmwareversion { namespace length { static constexpr auto SOFTWARE_VERSION = 3; @@ -49,7 +54,7 @@ class FirmwareVersion { puts(s_Print); if (pTitle != nullptr) { - printf("\x1b[32m%s\x1b[37m\n", pTitle); + printf("\x1b[32m%s\x1b[0m\n", pTitle); } } diff --git a/lib-hal/include/gd32/hal_api.h b/lib-hal/include/gd32/hal_api.h index a4275ae..a41381e 100644 --- a/lib-hal/include/gd32/hal_api.h +++ b/lib-hal/include/gd32/hal_api.h @@ -2,7 +2,7 @@ * @file hal_api.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,11 +26,10 @@ #ifndef GD32_HAL_API_H_ #define GD32_HAL_API_H_ -#include - #define FUNC_PREFIX(x) gd32_##x #if defined __cplusplus +# include # if !defined(GD32_UDELAY) # define GD32_UDELAY void udelay(uint32_t us, uint32_t offset = 0); diff --git a/lib-hal/include/gd32/hardware.h b/lib-hal/include/gd32/hardware.h index d6a2aa5..bda7f28 100644 --- a/lib-hal/include/gd32/hardware.h +++ b/lib-hal/include/gd32/hardware.h @@ -36,6 +36,20 @@ #include "gd32_adc.h" #include "gd32_micros.h" +#if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) +extern "C" { +#include "usbh_core.h" +extern usbh_host usb_host_msc; +} +#endif + +#if defined (DEBUG_STACK) + void stack_debug_run(); +#endif +#if defined (DEBUG_EMAC) + void emac_debug_run(); +#endif + #if defined (USE_LEDBLINK_BITBANGING595) # include "gd32_bitbanging595.h" # include "panel_led.h" @@ -139,6 +153,9 @@ class Hardware { } void Run() { +#if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) + usbh_core_task(&usb_host_msc); +#endif if (__builtin_expect (m_nTicksPerSecond != 0, 1)) { if (__builtin_expect (!(s_nSysTickMillis - m_nMillisPrevious < m_nTicksPerSecond), 1)) { m_nMillisPrevious = s_nSysTickMillis; @@ -164,6 +181,14 @@ class Hardware { #if defined (USE_LEDBLINK_BITBANGING595) bitBanging595.Run(); #endif + +#if defined (DEBUG_STACK) + stack_debug_run(); +#endif + +#if defined (DEBUG_EMAC) + emac_debug_run(); +#endif } static Hardware *Get() { diff --git a/lib-hal/include/gd32/panel_led.h b/lib-hal/include/gd32/panel_led.h index 4d29ac8..8b6f323 100644 --- a/lib-hal/include/gd32/panel_led.h +++ b/lib-hal/include/gd32/panel_led.h @@ -1,8 +1,8 @@ /** - * @file panel_led + * @file panel_led.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,64 +27,100 @@ #define GD32_PANEL_LED_H_ #include -#include -#include "gd32_bitbanging595.h" +#include "gd32.h" + +#if !defined (LEDPANEL_595_COUNT) +# if !defined (UNUSED) +# define UNUSED __attribute__((unused)) +# endif +#else +# if !defined (UNUSED) +# define UNUSED +# endif +#endif namespace hal { -#if defined(BOARD_GD32F207VC) || defined(BOARD_GD32F450VE) - -static constexpr uint32_t led_map[16] = { - 0x4000, // A_TX - 0x1000, // B_TX - 0x0400, // C_TX - 0x0100, // D_TX - 0x0080, // E_TX - 0x0020, // F_TX - 0x0008, // G_TX - 0x0002, // H_TX - 0x8000, // A_RX - 0x2000, // B_RX - 0x0800, // C_RX - 0x0200, // D_RX - 0x0040, // E_RX - 0x0010, // F_RX - 0x0004, // G_RX - 0x0001 // H_RX -}; - -inline static void panel_led_on(uint32_t on) { - const uint32_t nDMX = on & 0xFFFF; - - if (nDMX != 0) { - on &= ~(0xFFFF); - const auto nIndex = 31 - __CLZ(nDMX); - assert(nIndex < 16); - on |= (led_map[nIndex]); - } +namespace panelled { +extern uint32_t g_nData; +} // namespace panelled - BitBanging595::Get()->SetOn(on); -} +inline static void panel_led_spi(const UNUSED uint32_t nData) { +#if defined(LEDPANEL_595_COUNT) + GPIO_BC(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; -inline static void panel_led_off(uint32_t off) { - const uint32_t nDMX = off & 0xFFFF; +#if (LEDPANEL_595_COUNT >= 1) + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) + ; - if (nDMX != 0) { - off &= ~(0xFFFF); - const auto nIndex = 31 - __CLZ(nDMX); - assert(nIndex < 16); - off |= (led_map[nIndex]); - } + SPI_DATA(SPI_PERIPH) = (nData & 0xFF); - BitBanging595::Get()->SetOff(off); -} -#else -inline static void panel_led_on(uint32_t __attribute__((unused)) on) { + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_RBNE)) + ; + + static_cast(SPI_DATA(SPI_PERIPH)); +#endif +#if (LEDPANEL_595_COUNT >= 2) + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) + ; + + SPI_DATA(SPI_PERIPH) = ((nData >> 8) & 0xFF); + + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_RBNE)) + ; + + static_cast(SPI_DATA(SPI_PERIPH)); +#endif +#if (LEDPANEL_595_COUNT >= 3) + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) + ; + + SPI_DATA(SPI_PERIPH) = ((nData >> 16) & 0xFF); + + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_RBNE)) + ; + + static_cast(SPI_DATA(SPI_PERIPH)); +#endif +#if (LEDPANEL_595_COUNT == 4) + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) + ; + + SPI_DATA(SPI_PERIPH) = ((nData >> 24) & 0xFF); + + while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_RBNE)) + ; + + static_cast(SPI_DATA(SPI_PERIPH)); +#endif + + GPIO_BOP(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; +#endif } -inline static void panel_led_off(uint32_t __attribute__((unused)) off) { +inline static void panel_led_on(uint32_t UNUSED on) { +#if defined(LEDPANEL_595_COUNT) + if (panelled::g_nData == (panelled::g_nData | on)) { + return; + } + + panelled::g_nData |= on; + + panel_led_spi(panelled::g_nData); +#endif } + +inline static void panel_led_off(uint32_t UNUSED off) { +#if defined(LEDPANEL_595_COUNT) + if (panelled::g_nData == (panelled::g_nData & ~off)) { + return; + } + + panelled::g_nData &= ~off; + + panel_led_spi(panelled::g_nData); #endif +} } // namespace hal #endif /* GD32_PANEL_LED_H_ */ diff --git a/lib-hal/include/hal_i2c.h b/lib-hal/include/hal_i2c.h index ffdcd72..f366408 100644 --- a/lib-hal/include/hal_i2c.h +++ b/lib-hal/include/hal_i2c.h @@ -2,7 +2,7 @@ * @file hal_i2c.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,6 @@ #ifndef HAL_I2C_H_ #define HAL_I2C_H_ -#include - #if defined(__linux__) || defined (__APPLE__) # include "linux/hal_api.h" # include "linux/hal_i2c.h" @@ -43,6 +41,7 @@ #endif #ifdef __cplusplus +#include namespace hal { namespace i2c { @@ -72,9 +71,10 @@ class HAL_I2C { return IsConnected_(nAddress, nBaudrate); } - void Write(char pData) { + void Write(uint8_t pData) { Setup(); - FUNC_PREFIX(i2c_write(&pData, 1)); + const char buffer[] = { static_cast(pData) }; + FUNC_PREFIX(i2c_write(buffer, 1)); } void Write(const char *pData, uint32_t nLength) { diff --git a/lib-hal/include/hal_spi.h b/lib-hal/include/hal_spi.h index 24f4ccf..ef7e22c 100644 --- a/lib-hal/include/hal_spi.h +++ b/lib-hal/include/hal_spi.h @@ -2,7 +2,7 @@ * @file hal_spi.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,6 @@ #ifndef HAL_SPI_H_ #define HAL_SPI_H_ -#include - #if defined(__linux__) || defined (__APPLE__) # include "linux/hal_api.h" # include "linux/hal_spi.h" @@ -42,6 +40,8 @@ # include "rpi/hal_spi.h" #endif +#include + class HAL_SPI { void Setup() { FUNC_PREFIX(spi_chipSelect(m_nChipSelect)); diff --git a/lib-hal/rtc/i2c/hwclockrtc.cpp b/lib-hal/rtc/i2c/hwclockrtc.cpp index ff0e956..2bc00b7 100644 --- a/lib-hal/rtc/i2c/hwclockrtc.cpp +++ b/lib-hal/rtc/i2c/hwclockrtc.cpp @@ -2,7 +2,7 @@ * @file hwclockrtc.cpp * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -91,13 +91,15 @@ void HwClock::RtcProbe() { FUNC_PREFIX(i2c_set_baudrate(hal::i2c::NORMAL_SPEED)); + char registers[1]; + +#if !defined (CONFIG_RTC_DISABLE_MCP7941X) /** * MCP7941X */ FUNC_PREFIX(i2c_set_address(i2caddress::MCP7941X)); - char registers[1]; registers[0] = reg::YEAR; // The I2C bus is not stable at cold start? These dummy write/read helps. @@ -135,7 +137,9 @@ void HwClock::RtcProbe() { DEBUG_EXIT return; } +#endif +#if !defined (CONFIG_RTC_DISABLE_DS3231) /** * DS3231 */ @@ -171,7 +175,9 @@ void HwClock::RtcProbe() { DEBUG_EXIT return; } +#endif +#if !defined (CONFIG_RTC_DISABLE_PCF8563) /** * PCF8563 */ @@ -226,6 +232,7 @@ void HwClock::RtcProbe() { DEBUG_EXIT return; } +#endif DEBUG_EXIT } diff --git a/lib-hal/src/gd32/hardware.cpp b/lib-hal/src/gd32/hardware.cpp index 9e83635..57a9656 100644 --- a/lib-hal/src/gd32/hardware.cpp +++ b/lib-hal/src/gd32/hardware.cpp @@ -34,28 +34,48 @@ #include "gd32_adc.h" #include "gd32_board.h" -#ifndef NDEBUG -# include "../debug/i2cdetect.h" +#if defined (DEBUG_I2C) +# include "../debug/i2c/i2cdetect.h" +#endif + +#if defined (ENABLE_USB_HOST) +void usb_init(); #endif #include "debug.h" extern "C" { void console_init(void); +void __libc_init_array(void); void systick_config(void); } -void micros_init(); void udelay_init(); void gd32_adc_init(); Hardware *Hardware::s_pThis = nullptr; Hardware::Hardware() { + DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; console_init(); +#if !defined (ENABLE_TFTP_SERVER) + __libc_init_array(); +#endif + systick_config(); + udelay_init(); + gd32_adc_init(); + gd32_i2c_begin(); + + rcu_periph_clock_enable(RCU_TIMER5); + timer_deinit(TIMER5); + timer_parameter_struct timer_initpara; + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.period = static_cast(~0); + timer_init(TIMER5, &timer_initpara); + timer_enable(TIMER5); #if !defined (GD32F4XX) #else @@ -73,10 +93,6 @@ Hardware::Hardware() { assert(nAPB2 == APB2_CLOCK_FREQ); #endif - systick_config(); - udelay_init(); - micros_init(); - #if !defined (GD32F4XX) rcu_periph_clock_enable (RCU_BKPI); rcu_periph_clock_enable (RCU_PMU); @@ -89,32 +105,43 @@ Hardware::Hardware() { #endif bkp_data_write(BKP_DATA_1, 0x0); -#if !defined (GD32F4XX) - // There is no tightly coupled RAM +#if !defined (ENABLE_TFTP_SERVER) +# if defined (GD32F207RG) || defined (GD32F4XX) + // clear section .dmx + extern unsigned char _sdmx; + extern unsigned char _edmx; + DEBUG_PRINTF("clearing .dmx at %p, size %u", &_sdmx, &_edmx - &_sdmx); + memset(&_sdmx, 0, &_edmx - &_sdmx); +# if defined (GD32F450VI) + // clear section .lightset + extern unsigned char _slightset; + extern unsigned char _elightset; + DEBUG_PRINTF("clearing .lightset at %p, size %u", &_slightset, &_elightset - &_slightset); + memset(&_slightset, 0, &_elightset - &_slightset); +# endif + // clear section .network + extern unsigned char _snetwork; + extern unsigned char _enetwork; + DEBUG_PRINTF("clearing .network at %p, size %u", &_snetwork, &_enetwork - &_snetwork); + memset(&_snetwork, 0, &_enetwork - &_snetwork); +# if !defined (GD32F450VE) + // clear section .pixel + extern unsigned char _spixel; + extern unsigned char _epixel; + DEBUG_PRINTF("clearing .pixel at %p, size %u", &_spixel, &_epixel - &_spixel); + memset(&_spixel, 0, &_epixel - &_spixel); +# endif +# endif #else - // clear TCM SRAM - extern unsigned char _stcmsram; - extern unsigned char _etcmsram; - DEBUG_PRINTF("%p:%u", &_stcmsram, &_etcmsram - &_stcmsram); - memset(&_stcmsram, 0, &_etcmsram - &_stcmsram); - // clear RAMADD SRAM - extern unsigned char _sramadd; - extern unsigned char _eramadd; - DEBUG_PRINTF("%p:%u", &_sramadd, &_eramadd - &_sramadd); - memset(&_sramadd, 0, &_eramadd - &_sramadd); +# if defined (GD32F207RG) || defined (GD32F4XX) + // clear section .network + extern unsigned char _snetwork; + extern unsigned char _enetwork; + DEBUG_PRINTF("clearing .network at %p, size %u", &_snetwork, &_enetwork - &_snetwork); + memset(&_snetwork, 0, &_enetwork - &_snetwork); +# endif #endif - rcu_periph_clock_enable(RCU_TIMER5); - - timer_deinit(TIMER5); - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = TIMER_PSC_1MHZ; - timer_initpara.period = static_cast(~0); - timer_init(TIMER5, &timer_initpara); - timer_enable(TIMER5); - - gd32_adc_init(); - struct tm tmbuf; tmbuf.tm_hour = 0; @@ -126,13 +153,11 @@ Hardware::Hardware() { tmbuf.tm_isdst = 0; // 0 (DST not in effect, just take RTC time) const auto seconds = mktime(&tmbuf); - const struct timeval tv = { .tv_sec = seconds, .tv_usec = 0 }; + const struct timeval tv = { seconds, 0 }; settimeofday(&tv, nullptr); - gd32_i2c_begin(); - -#ifndef NDEBUG +#if defined (DEBUG_I2C) I2cDetect i2cdetect; #endif @@ -152,6 +177,23 @@ Hardware::Hardware() { # endif GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; #endif + +#if defined (LEDPANEL_595_CS_GPIOx) + rcu_periph_clock_enable(LEDPANEL_595_CS_RCU_GPIOx); +# if !defined (GD32F4XX) + gpio_init(LEDPANEL_595_CS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LEDPANEL_595_CS_GPIO_PINx); +# else + gpio_mode_set(LEDPANEL_595_CS_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LEDPANEL_595_CS_GPIO_PINx); + gpio_output_options_set(LEDPANEL_595_CS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LEDPANEL_595_CS_GPIO_PINx); +# endif + GPIO_BOP(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; +#endif + +#if defined ENABLE_USB_HOST + usb_init(); +#endif + + DEBUG_EXIT } typedef union pcast32 { diff --git a/include/cstdarg b/lib-hal/src/panel_led.cpp old mode 100644 new mode 100755 similarity index 82% rename from include/cstdarg rename to lib-hal/src/panel_led.cpp index c91b936..f1b6a87 --- a/include/cstdarg +++ b/lib-hal/src/panel_led.cpp @@ -1,8 +1,8 @@ /** - * @file cstdarg + * @file panel_led.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,11 @@ * THE SOFTWARE. */ -#ifndef CSTDARG_ -#define CSTDARG_ +#include -#ifdef __cplusplus -# include -#endif - -#endif /* CSTDARG_ */ +namespace hal { +namespace panelled { +uint32_t g_nData; +uint32_t g_nDataPrevious; +} // namespace panelled +} // namespace hal diff --git a/lib-network/.settings/language.settings.xml b/lib-network/.settings/language.settings.xml index 072a137..2550dd6 100644 --- a/lib-network/.settings/language.settings.xml +++ b/lib-network/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-network/Rules.mk b/lib-network/Rules.mk index 72eee99..069b63b 100755 --- a/lib-network/Rules.mk +++ b/lib-network/Rules.mk @@ -1,7 +1,11 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) +$(info $$DEFINES [${DEFINES}]) + +COND= ifneq ($(MAKE_FLAGS),) ifeq ($(findstring ESP8266,$(MAKE_FLAGS)), ESP8266) + EXTRA_SRCDIR+=src/esp8266 src/params COND=1 endif ifndef COND @@ -11,8 +15,33 @@ ifneq ($(MAKE_FLAGS),) endif endif ifndef COND - EXTRA_SRCDIR+=src/net src/apps src/emac src/params + EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp + EXTRA_SRCDIR+=src/emac src/params src/net + EXTRA_SRCDIR+=src/emac/phy + ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) + EXTRA_SRCDIR+=src/emac/dsa + endif + PHY= + ifeq ($(findstring DP83848,$(ENET_PHY)), DP83848) + EXTRA_SRCDIR+=src/emac/phy/dp83848 + PHY=1 + endif + ifeq ($(findstring LAN8700,$(ENET_PHY)), LAN8700) + EXTRA_SRCDIR+=src/emac/phy/lan8700 + PHY=1 + endif + ifeq ($(findstring RTL8201F,$(ENET_PHY)), RTL8201F) + EXTRA_SRCDIR+=src/emac/phy/rtl8201f + PHY=1 + endif + ifndef PHY + EXTRA_SRCDIR+=src/emac/phy/phygen + endif endif else - EXTRA_SRCDIR+=src/net src/apps src/params src/emac + EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp + EXTRA_SRCDIR+=src/emac src/net + EXTRA_SRCDIR+=src/emac/phy + EXTRA_SRCDIR+=src/emac/phy/dp83848 src/emac/phy/lan8700 src/emac/phy/phygen src/emac/phy/rtl8201f + DEFINES+=RTL8201F_LED1_LINK_ALL endif diff --git a/lib-network/include/emac/emac.h b/lib-network/include/emac/emac.h new file mode 100755 index 0000000..dbb8597 --- /dev/null +++ b/lib-network/include/emac/emac.h @@ -0,0 +1,35 @@ +/* + * emac.h + */ + +#ifndef EMAC_EMAC_H_ +#define EMAC_EMAC_H_ + +#include + +/** \defgroup platform Platform implementation + @{ +*/ +/** + * Configure the PHY interface + * - Call \ref net::phy_config + */ +void emac_config(); + +/** + * + * - Soft MAC reset + * - Set the MAC address + * - Initialize rx/tx descriptors + * - PHY Start Up -> \ref net::phy_start + * - Adjust the link with duplex and speed returned from \ref net::phy_start + * - Start RX/TX DMA + * - Enable RX/TX + * + * @param[out] macAddress + * + */ +void emac_start(uint8_t macAddress[], net::Link& link); +/** @} */ + +#endif /* EMAC_EMAC_H_ */ diff --git a/lib-network/include/emac/mmi.h b/lib-network/include/emac/mmi.h new file mode 100755 index 0000000..f1d6ae6 --- /dev/null +++ b/lib-network/include/emac/mmi.h @@ -0,0 +1,101 @@ +/** + * @file mmi.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef EMAC_MMI_H_ +#define EMAC_MMI_H_ + +#include + +namespace net { +namespace mmi { + +/* Generic MII registers. */ +static constexpr uint32_t REG_BMCR = 0x00; /* Basic mode control register */ +static constexpr uint32_t REG_BMSR = 0x01; /* Basic mode status register */ +static constexpr uint32_t REG_PHYSID1 = 0x02; /* PHYS ID 1 */ +static constexpr uint32_t REG_PHYSID2 = 0x03; /* PHYS ID 2 */ +static constexpr uint32_t REG_ADVERTISE = 0x04; /* Advertisement control register */ +static constexpr uint32_t REG_LPA = 0x05; /* Link partner ability register */ + +/* Basic mode control register. */ +static constexpr uint16_t BMCR_HALFDUPLEX_10M = 0x0000; /* configure speed to 10 Mbit/s and the half-duplex mode */ +static constexpr uint16_t BMCR_FULLDUPLEX_10M = 0x0100; /* configure speed to 10 Mbit/s and the full-duplex mode */ +static constexpr uint16_t BMCR_RESTART_AUTONEGOTIATION = 0x0200; /* restart auto-negotiation function */ +static constexpr uint16_t BMCR_ISOLATE = 0x0400; /* isolate PHY from MII */ +static constexpr uint16_t BMCR_POWERDOWN = 0x0800; /* enable the power down mode */ +static constexpr uint16_t BMCR_AUTONEGOTIATION = 0x1000; /* enable auto-negotiation function */ +static constexpr uint16_t BMCR_HALFDUPLEX_100M = 0x2000; /* configure speed to 100 Mbit/s and the half-duplex mode */ +static constexpr uint16_t BMCR_FULLDUPLEX_100M = 0x2100; /* configure speed to 100 Mbit/s and the full-duplex mode */ +static constexpr uint16_t BMCR_LOOPBACK = 0x4000; /* enable phy loop-back mode */ +static constexpr uint16_t BMCR_RESET = 0x8000; /* PHY reset */ + +/* PHY basic mode status register */ +static constexpr uint16_t BMSR_JABBER_DETECTION = 0x0002; /* jabber condition detected */ +static constexpr uint16_t BMSR_LINKED_STATUS = 0x0004; /* valid link established */ +static constexpr uint16_t BMSR_AUTONEGO_COMPLETE = 0x0020; /* auto-negotioation process completed */ + +/* Advertisement control register. */ +static constexpr uint16_t ADVERTISE_SLCT = 0x001f; /* Selector bits */ +static constexpr uint16_t ADVERTISE_CSMA = 0x0001; /* Only selector supported */ +static constexpr uint16_t ADVERTISE_10HALF = 0x0020; /* Try for 10mbps half-duplex */ +static constexpr uint16_t ADVERTISE_1000XFULL = 0x0020; /* Try for 1000BASE-X full-duplex */ +static constexpr uint16_t ADVERTISE_10FULL = 0x0040; /* Try for 10mbps full-duplex */ +static constexpr uint16_t ADVERTISE_1000XHALF = 0x0040; /* Try for 1000BASE-X half-duplex */ +static constexpr uint16_t ADVERTISE_100HALF = 0x0080; /* Try for 100mbps half-duplex */ +static constexpr uint16_t ADVERTISE_1000XPAUSE = 0x0080; /* Try for 1000BASE-X pause */ +static constexpr uint16_t ADVERTISE_100FULL = 0x0100; /* Try for 100mbps full-duplex */ +static constexpr uint16_t ADVERTISE_1000XPSE_ASYM = 0x0100; /* Try for 1000BASE-X asym pause */ +static constexpr uint16_t ADVERTISE_100BASE4 = 0x0200; /* Try for 100mbps 4k packets */ +static constexpr uint16_t ADVERTISE_PAUSE_CAP = 0x0400; /* Try for pause */ +static constexpr uint16_t ADVERTISE_PAUSE_ASYM = 0x0800; /* Try for asymetric pause */ +static constexpr uint16_t ADVERTISE_RESV = 0x1000; /* Unused... */ +static constexpr uint16_t ADVERTISE_RFAULT = 0x2000; /* Say we can detect faults */ +static constexpr uint16_t ADVERTISE_LPACK = 0x4000; /* Ack link partners response */ +static constexpr uint16_t ADVERTISE_NPAGE = 0x8000; /* Next page bit */ + +static constexpr uint16_t ADVERTISE_FULL = (ADVERTISE_100FULL | ADVERTISE_10FULL | ADVERTISE_CSMA); +static constexpr uint16_t ADVERTISE_ALL = (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL); + +/* Link partner ability register. */ +static constexpr uint16_t LPA_SLCT = 0x001f; /* Same as advertise selector */ +static constexpr uint16_t LPA_10HALF = 0x0020; /* Can do 10mbps half-duplex */ +static constexpr uint16_t LPA_1000XFULL = 0x0020; /* Can do 1000BASE-X full-duplex */ +static constexpr uint16_t LPA_10FULL = 0x0040; /* Can do 10mbps full-duplex */ +static constexpr uint16_t LPA_1000XHALF = 0x0040; /* Can do 1000BASE-X half-duplex */ +static constexpr uint16_t LPA_100HALF = 0x0080; /* Can do 100mbps half-duplex */ +static constexpr uint16_t LPA_1000XPAUSE = 0x0080; /* Can do 1000BASE-X pause */ +static constexpr uint16_t LPA_100FULL = 0x0100; /* Can do 100mbps full-duplex */ +static constexpr uint16_t LPA_1000XPAUSE_ASYM = 0x0100; /* Can do 1000BASE-X pause asym*/ +static constexpr uint16_t LPA_100BASE4 = 0x0200; /* Can do 100mbps 4k packets */ +static constexpr uint16_t LPA_PAUSE_CAP = 0x0400; /* Can pause */ +static constexpr uint16_t LPA_PAUSE_ASYM = 0x0800; /* Can pause asymetrically */ +static constexpr uint16_t LPA_RFAULT = 0x2000; /* Link partner faulted */ +static constexpr uint16_t LPA_LPACK = 0x4000; /* Link partner acked us */ +static constexpr uint16_t LPA_NPAGE = 0x8000; /* Next page bit */ + +} // namespace mmi +} // namespace net + +#endif /* EMAC_MMI_H_ */ diff --git a/lib-network/include/emac/net_link_check.h b/lib-network/include/emac/net_link_check.h index d43c554..82eeffd 100644 --- a/lib-network/include/emac/net_link_check.h +++ b/lib-network/include/emac/net_link_check.h @@ -2,7 +2,7 @@ * net_link_check.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,30 +26,33 @@ #ifndef EMAC_NET_LINK_CHECK_H_ #define EMAC_NET_LINK_CHECK_H_ +#include "phy.h" + namespace net { -enum class Link { - STATE_UP, STATE_DOWN -}; +net::Link link_status_read(); /** * Platform defined implementations */ -net::Link link_register_read(); +#if defined (ENET_LINK_CHECK_USE_INT) || defined (ENET_LINK_CHECK_USE_PIN_POLL) + void link_gpio_init(); + void link_pin_enable(); + void link_pin_recovery(); +#endif #if defined (ENET_LINK_CHECK_USE_INT) + void link_exti_init(); void link_interrupt_init(); #elif defined (ENET_LINK_CHECK_USE_PIN_POLL) void link_pin_poll_init(); void link_pin_poll(); -#elif defined (ENET_LINK_CHECK_REG_POLL) - void link_register_poll(); #endif /** - * User defined implementation + * + * @param state */ - void link_handle_change(const net::Link state); } // namespace net diff --git a/lib-network/include/emac/network.h b/lib-network/include/emac/network.h index de78ef0..0e946b2 100755 --- a/lib-network/include/emac/network.h +++ b/lib-network/include/emac/network.h @@ -45,37 +45,42 @@ class Network { public: - Network(); + Network(NetworkParamsStore *pNetworkParamsStore); ~Network() {} - void Init(NetworkParamsStore *pNetworkParamsStore = nullptr); - void Print(); void Shutdown() { network::display_emac_shutdown(); + network::mdns_shutdown(); net_shutdown(); } void MacAddressCopyTo(uint8_t *pMacAddress) { - for (uint32_t i = 0; i < network::MAC_SIZE; i++) { - pMacAddress[i] = m_aNetMacaddr[i]; - } + memcpy(pMacAddress, m_aNetMacaddr, network::MAC_SIZE); + } + + uint32_t GetSecondaryIp() const { + return m_IpInfo.secondary_ip.addr; } void SetIp(uint32_t nIp); uint32_t GetIp() const { - return m_nLocalIp; + return m_IpInfo.ip.addr; } void SetNetmask(uint32_t nNetmask); uint32_t GetNetmask() const { - return m_nNetmask; + return m_IpInfo.netmask.addr; } void SetGatewayIp(uint32_t nGatewayIp); uint32_t GetGatewayIp() const { - return m_nGatewayIp; + return m_IpInfo.gw.addr; + } + + uint32_t GetBroadcastIp() const { + return m_IpInfo.broadcast_ip.addr; } /* @@ -198,11 +203,7 @@ class Network { bool ApplyQueuedConfig(); uint32_t GetNetmaskCIDR() const { - return static_cast(__builtin_popcount(m_nNetmask)); - } - - uint32_t GetBroadcastIp() const { - return m_nLocalIp | ~m_nNetmask; + return static_cast(__builtin_popcount(m_IpInfo.netmask.addr)); } char GetAddressingMode() { @@ -235,12 +236,8 @@ class Network { return m_fNtpUtcOffset; } - void SetNetworkStore(NetworkStore *pNetworkStore) { - m_pNetworkStore = pNetworkStore; - } - bool IsValidIp(uint32_t nIp) { - return (m_nLocalIp & m_nNetmask) == (nIp & m_nNetmask); + return (m_IpInfo.ip.addr & m_IpInfo.netmask.addr) == (nIp & m_IpInfo.netmask.addr); } void Run() { @@ -248,7 +245,7 @@ class Network { #if defined (ENET_LINK_CHECK_USE_PIN_POLL) net::link_pin_poll(); #elif defined (ENET_LINK_CHECK_REG_POLL) - const net::Link link_state = net::link_register_read(); + const net::Link link_state = net::link_status_read(); if (link_state != s_lastState) { s_lastState = link_state; @@ -271,9 +268,7 @@ class Network { uint32_t m_nNtpServerIp { 0 }; float m_fNtpUtcOffset { 0 }; - uint32_t m_nLocalIp { 0 }; - uint32_t m_nGatewayIp { 0 }; - uint32_t m_nNetmask { 0 }; + struct IpInfo m_IpInfo; char m_aHostName[network::HOSTNAME_SIZE]; char m_aDomainName[network::DOMAINNAME_SIZE]; @@ -282,15 +277,6 @@ class Network { NetworkStore *m_pNetworkStore { nullptr }; - void SetDefaultIp() { - m_nLocalIp = 2 - + ((static_cast(m_aNetMacaddr[3])) << 8) - + ((static_cast(m_aNetMacaddr[4])) << 16) - + ((static_cast(m_aNetMacaddr[5])) << 24); - m_nNetmask = 255; - m_nGatewayIp = m_nLocalIp; - } - struct QueuedConfig { static constexpr uint32_t NONE = 0; static constexpr uint32_t STATIC_IP = (1U << 0); @@ -304,7 +290,7 @@ class Network { QueuedConfig m_QueuedConfig; - bool isQueuedMaskSet(uint32_t nMask) { + bool isQueuedMaskSet(const uint32_t nMask) { return (m_QueuedConfig.nMask & nMask) == nMask; } diff --git a/lib-network/include/emac/phy.h b/lib-network/include/emac/phy.h new file mode 100755 index 0000000..ddae083 --- /dev/null +++ b/lib-network/include/emac/phy.h @@ -0,0 +1,127 @@ +/** + * @file phy.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef EMAC_PHY_H_ +#define EMAC_PHY_H_ + +#include + +namespace net { +enum class Link { + STATE_UP, STATE_DOWN +}; + +enum class Duplex { + DUPLEX_HALF, DUPLEX_FULL +}; + +enum class Speed { + SPEED10, SPEED100, SPEED1000 +}; + +struct PhyStatus { + Link link; + Duplex duplex; + Speed speed; + bool bAutonegotiation; +}; + +struct PhyIdentifier { + uint32_t nOui; ///< 24-bit Organizationally Unique Identifier. + uint16_t nVendorModel; ///< 6-bit Manufacturer’s model number. + uint16_t nModelRevision; ///< 4-bit Manufacturer’s revision number. +}; + +/** \defgroup generic Generic implementation + @{ +*/ + +bool phy_get_id(const uint32_t nAddress, PhyIdentifier& phyIdentifier); + +/** + * + * @param nAddress PHY address + * @return true for success, false for failure + */ +bool phy_powerdown(const uint32_t nAddress); + +/** + * + * Called from \ref emac_start + * + * @param nAddress PHY address + * @return true for success, false for failure + */ +bool phy_start(const uint32_t nAddress, PhyStatus& phyStatus); + + +const char *phy_string_get_link(const Link link); +const char *phy_string_get_duplex(const Duplex duplex); +const char *phy_string_get_speed(const Speed speed); +const char *phy_string_get_autonegotiation(const bool autonegotiation); + +/** @} */ + +/** \defgroup platform Platform implementation + @{ +*/ + +/** + * Reading a given PHY register + * @param nAddress PHY address + * @param nRegister PHY register number to read + * @param nValue Returned value + * @return + */ +bool phy_read(const uint32_t nAddress, const uint32_t nRegister, uint16_t& nValue); + +/** + * + * @param nAddress PHY address + * @param nRegister PHY register number to write + * @param nValue Value to write + * @return true for success, false for failure + */ +bool phy_write(const uint32_t nAddress, const uint32_t nRegister, uint16_t nValue); + +/** + * PHY interface configuration (configure SMI and reset PHY) + * Called from \ref emac_config + * @param nAddress true for success, false for failure + * @return + */ +bool phy_config(const uint32_t nAddress); +/** @} */ + +/** \defgroup specific PHY specific + @{ +*/ +void phy_customized_led(); +void phy_customized_timing(); +void phy_customized_status(PhyStatus& phyStatus); +/** @} */ +} + +#endif /* EMAC_PHY_H_ */ diff --git a/lib-network/include/network.h b/lib-network/include/network.h index 5cb3673..da33407 100644 --- a/lib-network/include/network.h +++ b/lib-network/include/network.h @@ -2,7 +2,7 @@ * @file network.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,6 +35,7 @@ #define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" namespace network { +static constexpr auto STORE = 96; ///< Configuration store in bytes static constexpr auto IP_SIZE = 4U; static constexpr auto MAC_SIZE = 6U; static constexpr auto HOSTNAME_SIZE = 64U; ///< Including a terminating null byte. @@ -58,7 +59,7 @@ static constexpr uint32_t convert_to_uint(const uint8_t a, const uint8_t b, cons static_cast(d) << 24; } -inline static bool is_netmask_valid(uint32_t nNetMask) { +inline bool is_netmask_valid(uint32_t nNetMask) { if (nNetMask == 0) { return false; } @@ -69,7 +70,7 @@ inline static bool is_netmask_valid(uint32_t nNetMask) { /** * The private address ranges are defined in RFC1918. */ -inline static bool is_private_ip(const uint32_t nIp) { +inline bool is_private_ip(const uint32_t nIp) { const uint8_t n = (nIp >> 8) & 0xFF; switch (nIp & 0xFF) { @@ -87,7 +88,7 @@ inline static bool is_private_ip(const uint32_t nIp) { return false; } -inline static bool is_multicast_ip(const uint32_t nIp) { +inline bool is_multicast_ip(const uint32_t nIp) { if ((nIp & 0xE0) != 0xE0) { return false; } @@ -103,7 +104,7 @@ inline static bool is_multicast_ip(const uint32_t nIp) { return true; } -inline static uint32_t cidr_to_netmask(uint8_t nCIDR) { +inline uint32_t cidr_to_netmask(const uint8_t nCIDR) { if (nCIDR != 0) { const auto nNetmask = __builtin_bswap32(static_cast(~0x0) << (32 - nCIDR)); return nNetmask; @@ -112,13 +113,18 @@ inline static uint32_t cidr_to_netmask(uint8_t nCIDR) { return 0; } +void display_emac_config(); void display_emac_start(); +void display_emac_status(const bool isLinkUp); void display_ip(); void display_netmask(); void display_gateway(); void display_hostname(); void display_dhcp_status(network::dhcp::ClientStatus nStatus); void display_emac_shutdown(); + +void mdns_announcement(); +void mdns_shutdown(); } // namespace network class NetworkStore { diff --git a/lib-network/include/tftpdaemon.h b/lib-network/include/tftpdaemon.h index 42c496e..5cb7977 100644 --- a/lib-network/include/tftpdaemon.h +++ b/lib-network/include/tftpdaemon.h @@ -2,7 +2,7 @@ * @file tftpdaemon.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,20 +28,21 @@ #include -enum class TFTPMode { - BINARY, - ASCII +namespace tftp { +enum class Mode { + BINARY, ASCII }; +} // namespace tftp class TFTPDaemon { public: TFTPDaemon(); virtual ~TFTPDaemon(); - bool Run(); + void Run(); - virtual bool FileOpen(const char *pFileName, TFTPMode tMode)=0; - virtual bool FileCreate(const char *pFileName, TFTPMode tMode)=0; + virtual bool FileOpen(const char *pFileName, tftp::Mode mode)=0; + virtual bool FileCreate(const char *pFileName, tftp::Mode mode)=0; virtual bool FileClose()=0; virtual size_t FileRead(void *pBuffer, size_t nCount, unsigned nBlockNumber)=0; virtual size_t FileWrite(const void *pBuffer, size_t nCount, unsigned nBlockNumber)=0; @@ -52,7 +53,7 @@ class TFTPDaemon { void HandleRequest(); void HandleRecvAck(); void HandleRecvData(); - void SendError (uint16_t usErrorCode, const char *pErrorMessage); + void SendError (const uint16_t nsErrorCode, const char *pErrorMessage); void DoRead(); void DoWriteAck(); @@ -67,7 +68,7 @@ class TFTPDaemon { }; TFTPState m_nState { TFTPState::INIT }; int m_nIdx { -1 }; - uint8_t m_Buffer[528]; + uint8_t *m_pBuffer { nullptr }; uint32_t m_nFromIp { 0 }; uint16_t m_nFromPort { 0 }; size_t m_nLength { 0 }; diff --git a/lib-network/src/apps/mdns.cpp b/lib-network/src/apps/mdns.cpp deleted file mode 100644 index 25dd546..0000000 --- a/lib-network/src/apps/mdns.cpp +++ /dev/null @@ -1,620 +0,0 @@ -/** - * @file mdns.cpp - * - */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "mdns.h" - -#include "network.h" -#include "hardware.h" - -#include "debug.h" - -#define MDNS_MULTICAST_ADDRESS "224.0.0.251" -#define MDNS_TLD ".local" -#define DNS_SD_SERVICE "_services._dns-sd._udp.local" -#define MDNS_RESPONSE_TTL (120) ///< (in seconds) -#define ANNOUNCE_TIMEOUT ((MDNS_RESPONSE_TTL / 2) + (MDNS_RESPONSE_TTL / 4)) - -enum TDNSClasses { - DNSClassInternet = 1 -}; - -enum TDNSRecordTypes { - DNSRecordTypeA = 1, ///< 0x01 - DNSRecordTypePTR = 12, ///< 0x0c - DNSRecordTypeTXT = 16, ///< 0x10 - DNSRecordTypeSRV = 33 ///< 0x21 -}; - -enum TDNSCacheFlush { - DNSCacheFlushTrue = 0x8000 -}; - -enum TDNSOpCodes { - DNSOpQuery = 0, - DNSOpIQuery = 1, - DNSOpStatus = 2, - DNSOpNotify = 4, - DNSOpUpdate = 5 -}; - -struct TmDNSHeader { - uint16_t xid; - uint16_t nFlags; - uint16_t queryCount; - uint16_t answerCount; - uint16_t authorityCount; - uint16_t additionalCount; -} __attribute__((__packed__)); - -using namespace mdns; - -uint32_t MDNS::s_nMulticastIp; -int32_t MDNS::s_nHandle = -1; -uint32_t MDNS::s_nRemoteIp; -uint16_t MDNS::s_nRemotePort; -uint16_t MDNS::s_nBytesReceived; -uint32_t MDNS::s_nLastAnnounceMillis; -uint32_t MDNS::s_nDNSServiceRecords; -ServiceRecord MDNS::s_ServiceRecords[SERVICE_RECORDS_MAX]; -RecordData MDNS::s_AnswerLocalIp; -RecordData MDNS::s_ServiceRecordsData; -char *MDNS::s_pName; -uint8_t *MDNS::s_pBuffer; - -static constexpr const char *get_protocol_name(Protocol nProtocol) { - return nProtocol == Protocol::TCP ? "_tcp" MDNS_TLD : "_udp" MDNS_TLD; -} - -MDNS::MDNS() { - struct in_addr group_ip; - static_cast(inet_aton(MDNS_MULTICAST_ADDRESS, &group_ip)); - s_nMulticastIp = group_ip.s_addr; -} - -MDNS::~MDNS() { - if (s_pName != nullptr) { - delete[] s_pName; - } - - for (uint32_t i = 0; i < SERVICE_RECORDS_MAX; i++) { - if (s_ServiceRecords[i].pName != nullptr) { - delete[] s_ServiceRecords[i].pName; - } - - if (s_ServiceRecords[i].pServName != nullptr) { - delete[] s_ServiceRecords[i].pServName; - } - - if (s_ServiceRecords[i].pTextContent != nullptr) { - delete[] s_ServiceRecords[i].pTextContent; - } - } -} - -void MDNS::Start() { - assert(s_nHandle == -1); - - s_nHandle = Network::Get()->Begin(UDP_PORT); - assert(s_nHandle != -1); - - Network::Get()->JoinGroup(s_nHandle, s_nMulticastIp); - - if (s_pName == nullptr) { - SetName(Network::Get()->GetHostName()); - } - - CreateAnswerLocalIpAddress(); - - Network::Get()->SendTo(s_nHandle, s_AnswerLocalIp.aBuffer, static_cast(s_AnswerLocalIp.nSize), s_nMulticastIp, UDP_PORT); - Network::Get()->SetDomainName(&MDNS_TLD[1]); -} - -void MDNS::SetName(const char *pName) { - assert(pName != nullptr); - assert(strlen(pName) != 0); - - if (s_pName != nullptr) { - delete[] s_pName; - } - - s_pName = new char[strlen(pName) + sizeof(MDNS_TLD)]; - assert(s_pName != nullptr); - - strcpy(s_pName, pName); - strcat(s_pName, MDNS_TLD); - - DEBUG_PUTS(s_pName); -} - -void MDNS::CreateMDNSMessage(uint32_t nIndex) { - DEBUG_ENTRY - - auto *pHeader = reinterpret_cast(&s_ServiceRecordsData.aBuffer); - - pHeader->nFlags = __builtin_bswap16(0x8400); - pHeader->queryCount = 0; - pHeader->answerCount = __builtin_bswap16(4); - pHeader->authorityCount = __builtin_bswap16(1); - pHeader->additionalCount = __builtin_bswap16(0); - - auto *pData = reinterpret_cast(&s_ServiceRecordsData.aBuffer) + sizeof(struct TmDNSHeader); - - pData += CreateAnswerServiceSrv(nIndex, pData); - pData += CreateAnswerServiceTxt(nIndex, pData); - pData += CreateAnswerServiceDnsSd(nIndex, pData); - pData += CreateAnswerServicePtr(nIndex, pData); - - memcpy(pData, &s_AnswerLocalIp.aBuffer[sizeof (struct TmDNSHeader)], s_AnswerLocalIp.nSize - sizeof (struct TmDNSHeader)); - pData += (s_AnswerLocalIp.nSize - sizeof (struct TmDNSHeader)); - - s_ServiceRecordsData.nSize = static_cast(pData - reinterpret_cast(pHeader)); - -// DEBUG_dump(&s_ServiceRecordsData.aBuffer, static_cast(s_ServiceRecordsData.nSize)); - - DEBUG_EXIT -} - -uint32_t MDNS::DecodeDNSNameNotation(const char *pDNSNameNotation, char *pString) { - DEBUG_ENTRY - - const auto *pSrc = pDNSNameNotation; - auto *pDst = pString; - - uint32_t nLenght = 0; - uint32_t nSize = 0; - auto isCompressed = false; - - while (*pSrc != 0) { - nLenght = static_cast(*pSrc++); -// DEBUG_PRINTF("nLenght=%.2x", (int) nLenght); - - if (nLenght > 63) { - if (!isCompressed) { - nSize += 1; - } - - isCompressed = true; - const auto nCompressedOffset = ((nLenght & static_cast(~(0xC0))) << 8) | ((*pSrc & 0xFF)); - nLenght = s_pBuffer[nCompressedOffset]; - -// DEBUG_PRINTF("--> nCompressedOffset=%.4x", (int) nCompressedOffset); - - pSrc = reinterpret_cast(&s_pBuffer[nCompressedOffset + 1]); - - for (uint32_t i = 0; i < nLenght; i++) { - *pDst = *pSrc; - pDst++; - pSrc++; - } - - } else if (nLenght > 0) { - - for (uint32_t i = 0; i < nLenght; i++) { - *pDst = *pSrc; - pDst++; - pSrc++; - } - - if (!isCompressed) { - nSize += (nLenght + 1); - } - } - - if (*pSrc != 0) { - *pDst++ = '.'; - } - } - - *pDst = '\0'; - - DEBUG_PRINTF("pString=[%s]:%u", pString, 1 + nSize); - DEBUG_EXIT - return 1 + nSize; -} - -bool MDNS::AddServiceRecord(const char *pName, const char *pServName, uint16_t nPort, mdns::Protocol nProtocol, const char *pTextContent) { - assert(pServName != nullptr); - assert(nPort != 0); - - uint32_t i; - - for (i = 0; i < SERVICE_RECORDS_MAX; i++) { - if (s_ServiceRecords[i].pName == nullptr) { - s_ServiceRecords[i].nPort = nPort; - s_ServiceRecords[i].nProtocol = nProtocol; - - if (pName == nullptr) { - s_ServiceRecords[i].pName = new char[1 + strlen(Network::Get()->GetHostName()) + strlen(pServName)]; - assert(s_ServiceRecords[i].pName != nullptr); - - strcpy(s_ServiceRecords[i].pName, Network::Get()->GetHostName()); - } else { - s_ServiceRecords[i].pName = new char[1 + strlen(pName) + strlen(pServName)]; - assert(s_ServiceRecords[i].pName != nullptr); - - strcpy(s_ServiceRecords[i].pName, pName); - } - - strcat(s_ServiceRecords[i].pName, pServName); - - const char *p = FindFirstDotFromRight(pServName); - - s_ServiceRecords[i].pServName = new char[1 + strlen(p) + 12]; - assert(s_ServiceRecords[i].pServName != nullptr); - - strcpy(s_ServiceRecords[i].pServName, p); - strcat(s_ServiceRecords[i].pServName, "."); - strcat(s_ServiceRecords[i].pServName, get_protocol_name(nProtocol)); - - if (pTextContent != nullptr) { - s_ServiceRecords[i].pTextContent = new char[1 + strlen(pTextContent)]; - assert(s_ServiceRecords[i].pTextContent != nullptr); - - strcpy(s_ServiceRecords[i].pTextContent, pTextContent); - } - - break; - } - } - - if (i == SERVICE_RECORDS_MAX) { - assert(0); - return false; - } - - DEBUG_PRINTF("[%d].nPort = %d", i, s_ServiceRecords[i].nPort); - DEBUG_PRINTF("[%d].nProtocol = [%s]", i, s_ServiceRecords[i].nProtocol == Protocol::TCP ? "TCP" : "UDP"); - DEBUG_PRINTF("[%d].pName = [%s]", i, s_ServiceRecords[i].pName); - DEBUG_PRINTF("[%d].pServName = [%s]", i, s_ServiceRecords[i].pServName); - DEBUG_PRINTF("[%d].pTextContent = [%s]", i, s_ServiceRecords[i].pTextContent != nullptr ? s_ServiceRecords[i].pTextContent : "><"); - - CreateMDNSMessage(i); - - DEBUG_PRINTF("%d:%d %p -> %d " IPSTR, i, s_nHandle, reinterpret_cast(&s_ServiceRecordsData.aBuffer), s_ServiceRecordsData.nSize, IP2STR(s_nMulticastIp)); - - Network::Get()->SendTo(s_nHandle, &s_ServiceRecordsData.aBuffer, static_cast(s_ServiceRecordsData.nSize), s_nMulticastIp, UDP_PORT); - return true; -} - - -const char *MDNS::FindFirstDotFromRight(const char *pString) const { - const char *p = pString + strlen(pString); - while (p > pString && *p-- != '.') - ; - return &p[1]; -} - -uint32_t MDNS::WriteDnsName(const char *pSource, char *pDestination, bool bNullTerminated) { - DEBUG_PUTS(pSource); - - const auto *pSrc = pSource; - auto *pDst = pDestination; - - while (1 == 1) { - auto *pLength = pDst++; - const auto *pSrcStart = pSrc; - - while ((*pSrc != 0) && (*pSrc != '.')) { - *pDst = *pSrc; - pDst++; - pSrc++; - } - - *pLength = static_cast(pSrc - pSrcStart); - - if (*pSrc == 0) { - if (bNullTerminated) { - *pDst++ = 0; - } - break; - } - - pSrc++; - } - - return static_cast(pDst - pDestination); -} - -void MDNS::CreateAnswerLocalIpAddress() { - DEBUG_ENTRY - - auto *pHeader = reinterpret_cast(&s_AnswerLocalIp.aBuffer); - - pHeader->nFlags = __builtin_bswap16(0x8400); - pHeader->queryCount = 0; - pHeader->answerCount = __builtin_bswap16(1); - pHeader->authorityCount = 0; - pHeader->additionalCount = 0; - - uint8_t *pData = reinterpret_cast(&s_AnswerLocalIp.aBuffer) + sizeof(struct TmDNSHeader); - - pData += WriteDnsName(s_pName, reinterpret_cast(pData)); - - *reinterpret_cast(pData) = __builtin_bswap16(DNSRecordTypeA); - pData += 2; - *reinterpret_cast(pData) = __builtin_bswap16(DNSCacheFlushTrue | DNSClassInternet); - pData += 2; - *reinterpret_cast(pData) = __builtin_bswap32(MDNS_RESPONSE_TTL); - pData += 4; - *reinterpret_cast(pData) = __builtin_bswap16(4); // Data length - pData += 2; - *reinterpret_cast(pData) = Network::Get()->GetIp(); - pData += 4; - - s_AnswerLocalIp.nSize = static_cast(pData - reinterpret_cast(pHeader)); - - DEBUG_EXIT -} - -uint32_t MDNS::CreateAnswerServiceSrv(uint32_t nIndex, uint8_t *pDestination) { - DEBUG_ENTRY - - auto *pDst = pDestination; - - pDst += WriteDnsName(s_ServiceRecords[nIndex].pName, reinterpret_cast(pDst), false); - pDst += WriteDnsName(get_protocol_name(s_ServiceRecords[nIndex].nProtocol), reinterpret_cast(pDst)); - - *reinterpret_cast(pDst) = __builtin_bswap16(DNSRecordTypeSRV); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16(DNSCacheFlushTrue | DNSClassInternet); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap32(MDNS_RESPONSE_TTL); - pDst += 4; - *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(8 + strlen(s_pName))); - pDst += 2; - *reinterpret_cast(pDst) = 0; // Priority and Weight - pDst += 4; - *reinterpret_cast(pDst) = __builtin_bswap16(s_ServiceRecords[nIndex].nPort); - pDst += 2; - pDst += WriteDnsName(s_pName, reinterpret_cast(pDst)); - - DEBUG_EXIT - return static_cast(pDst - pDestination); -} - -uint32_t MDNS::CreateAnswerServiceTxt(uint32_t nIndex, uint8_t *pDestination) { - DEBUG_ENTRY - - auto *pDst = pDestination; - - pDst += WriteDnsName(s_ServiceRecords[nIndex].pName, reinterpret_cast(pDst), false); - pDst += WriteDnsName(get_protocol_name(s_ServiceRecords[nIndex].nProtocol), reinterpret_cast(pDst)); - - *reinterpret_cast(pDst) = __builtin_bswap16(DNSRecordTypeTXT); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16(DNSCacheFlushTrue | DNSClassInternet); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap32(MDNS_RESPONSE_TTL); - pDst += 4; - - if (s_ServiceRecords[nIndex].pTextContent == nullptr) { - *reinterpret_cast(pDst) = __builtin_bswap16(0x0001); // Data length - pDst += 2; - *pDst = 0; // Text length - pDst++; - } else { - const uint32_t nSize = strlen(s_ServiceRecords[nIndex].pTextContent); - *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(1 + nSize)); // Data length - pDst += 2; - *pDst = static_cast(nSize); // Text length - pDst++; - strcpy(reinterpret_cast(pDst), s_ServiceRecords[nIndex].pTextContent); - pDst += nSize; - } - - DEBUG_EXIT - return static_cast(pDst - pDestination); -} - -uint32_t MDNS::CreateAnswerServicePtr(uint32_t nIndex, uint8_t *pDestination) { - DEBUG_ENTRY - - auto *pDst = pDestination; - - pDst += WriteDnsName(s_ServiceRecords[nIndex].pServName, reinterpret_cast(pDst)); - - *reinterpret_cast(pDst) = __builtin_bswap16(DNSRecordTypePTR); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16(DNSClassInternet); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap32(MDNS_RESPONSE_TTL); - pDst += 4; - *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(13 + strlen(s_ServiceRecords[nIndex].pName))); - pDst += 2; - pDst += WriteDnsName(s_ServiceRecords[nIndex].pName, reinterpret_cast(pDst), false); - pDst += WriteDnsName(get_protocol_name(s_ServiceRecords[nIndex].nProtocol), reinterpret_cast(pDst)); - - DEBUG_EXIT - return static_cast(pDst - pDestination); -} - -uint32_t MDNS::CreateAnswerServiceDnsSd(uint32_t nIndex, uint8_t *pDestination) { - DEBUG_ENTRY - - auto *pDst = pDestination; - - pDst += WriteDnsName(DNS_SD_SERVICE, reinterpret_cast(pDst)); - - *reinterpret_cast(pDst) = __builtin_bswap16(DNSRecordTypePTR); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16(DNSClassInternet); - pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap32(MDNS_RESPONSE_TTL); - pDst += 4; - *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(2 + strlen(s_ServiceRecords[nIndex].pServName))); - pDst += 2; - pDst += WriteDnsName(s_ServiceRecords[nIndex].pServName, reinterpret_cast(pDst)); - - DEBUG_EXIT - return static_cast(pDst - pDestination); -} - -void MDNS::HandleRequest(uint16_t nQuestions) { - DEBUG_ENTRY - - char DnsName[255]; - - uint32_t nOffset = sizeof(struct TmDNSHeader); - - for (uint32_t i = 0; i < nQuestions; i++) { - nOffset += DecodeDNSNameNotation(reinterpret_cast(&s_pBuffer[nOffset]), DnsName); - - const auto nType = __builtin_bswap16(*reinterpret_cast(&s_pBuffer[nOffset])); - nOffset += 2; - - const auto nClass = __builtin_bswap16(*reinterpret_cast(&s_pBuffer[nOffset])) & 0x7F; - nOffset += 2; - - DEBUG_PRINTF("%s ==> Type : %d, Class: %d", DnsName, nType, nClass); - - if (nClass == DNSClassInternet) { - DEBUG_PRINTF("%s:%s", s_pName, DnsName); - - if ((strcmp(s_pName, DnsName) == 0) && (nType == DNSRecordTypeA)) { - Network::Get()->SendTo(s_nHandle, s_AnswerLocalIp.aBuffer, static_cast(s_AnswerLocalIp.nSize), s_nMulticastIp, UDP_PORT); - } - - const auto isDnsDs = (strcmp(DNS_SD_SERVICE, DnsName) == 0); - - for (uint32_t i = 0; i < SERVICE_RECORDS_MAX; i++) { - if (s_ServiceRecords[i].pName != nullptr) { - if ((isDnsDs || (strcmp(s_ServiceRecords[i].pServName, DnsName) == 0)) && (nType == DNSRecordTypePTR) ) { - CreateMDNSMessage(i); - Network::Get()->SendTo(s_nHandle, &s_ServiceRecordsData.aBuffer, static_cast(s_ServiceRecordsData.nSize), s_nMulticastIp, UDP_PORT); - } - } - } - } - - } - - DEBUG_EXIT -} - -void MDNS::Parse() { - DEBUG_ENTRY - - auto *pmDNSHeader = reinterpret_cast(s_pBuffer); - const auto nFlags = __builtin_bswap16(pmDNSHeader->nFlags); - -#ifndef NDEBUG -// Dump(pmDNSHeader, nFlags); -#endif - - if ((((nFlags >> 15) & 1) == 0) && (((nFlags >> 14) & 0xf) == DNSOpQuery)) { - if (pmDNSHeader->queryCount != 0) { - HandleRequest(__builtin_bswap16(pmDNSHeader->queryCount)); - } - } - - DEBUG_EXIT -} - -void MDNS::Run() { -#if 0 - uint32_t nNow = Hardware::Get()->Millis(); -#endif - - s_nBytesReceived = Network::Get()->RecvFrom(s_nHandle, const_cast(reinterpret_cast(&s_pBuffer)), &s_nRemoteIp, &s_nRemotePort); - - if ((s_nRemotePort == UDP_PORT) && (s_nBytesReceived > sizeof(struct TmDNSHeader))) { - Parse(); - } - -#if 0 - if (__builtin_expect(((nNow - s_nLastAnnounceMillis) > 1000 * ANNOUNCE_TIMEOUT), 0)) { - DEBUG_PUTS("> Announce <"); - for (uint32_t i = 0; i < s_nDNSServiceRecords; i++) { - if (s_ServiceRecords[i].pName != 0) { - //Network::Get()->SendTo(m_nHandle, (uint8_t *)&m_aServiceRecordsData[i].aBuffer, m_aServiceRecordsData[i].nSize, m_nMulticastIp, UDP_PORT); - } - } - - s_nLastAnnounceMillis = nNow; - } -#endif -} - -#include - -void MDNS::Print() { - printf("mDNS\n"); - if (s_nHandle == -1) { - printf(" Not running\n"); - return; - } - printf(" Name : %s\n", s_pName); - for (uint32_t i = 0; i < SERVICE_RECORDS_MAX; i++) { - if (s_ServiceRecords[i].pName != nullptr) { - printf(" %s %d %s\n", s_ServiceRecords[i].pServName, s_ServiceRecords[i].nPort, s_ServiceRecords[i].pTextContent == nullptr ? "" : s_ServiceRecords[i].pTextContent); - } - } -} - -#ifndef NDEBUG -void MDNS::Dump(const struct TmDNSHeader *pmDNSHeader, uint16_t nFlags) { - Flags tmDNSFlags; - - tmDNSFlags.rcode = nFlags & 0xf; - tmDNSFlags.cd = (nFlags >> 4) & 1; - tmDNSFlags.ad = (nFlags >> 5) & 1; - tmDNSFlags.zero = (nFlags) & 1; - tmDNSFlags.ra = (nFlags >> 7) & 1; - tmDNSFlags.rd = (nFlags >> 8) & 1; - tmDNSFlags.tc = (nFlags >> 9) & 1; - tmDNSFlags.aa = (nFlags >> 10) & 1; - tmDNSFlags.opcode = (nFlags >> 14) & 0xf; - tmDNSFlags.qr = (nFlags >> 15) & 1; - - const uint16_t nQuestions = __builtin_bswap16(pmDNSHeader->queryCount); - const uint16_t nAnswers = __builtin_bswap16(pmDNSHeader->answerCount); - const uint16_t nAuthority = __builtin_bswap16(pmDNSHeader->authorityCount); - const uint16_t nAdditional = __builtin_bswap16(pmDNSHeader->additionalCount); - - printf("ID: %u\n", pmDNSHeader->xid); - printf("Flags: \n"); - printf(" QR: %u", tmDNSFlags.qr); - printf(" OPCODE: %u", tmDNSFlags.opcode); - printf(" AA: %u", tmDNSFlags.aa); - printf(" TC: %u", tmDNSFlags.tc); - printf(" RD: %u", tmDNSFlags.rd); - printf(" RA: %u", tmDNSFlags.ra); - printf(" Z: %u", tmDNSFlags.zero); - printf(" AD: %u", tmDNSFlags.ad); - printf(" CD: %u", tmDNSFlags.cd); - printf(" RCODE: %u\n", tmDNSFlags.rcode); - printf("Questions : %u\n", nQuestions); - printf("Answers : %u\n", nAnswers); - printf("Authority : %u\n", nAuthority); - printf("Additional: %u\n", nAdditional); - -} -#endif diff --git a/lib-network/src/apps/ntpclient.cpp b/lib-network/src/apps/ntpclient.cpp deleted file mode 100644 index d06d0af..0000000 --- a/lib-network/src/apps/ntpclient.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/** - * @file ntpclient.cpp - * - */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "ntpclient.h" -#include "ntp.h" - -#include "utc.h" - -#include "network.h" -#include "hardware.h" - -#include "debug.h" - -static constexpr auto RETRIES = 3; -static constexpr auto TIMEOUT_MILLIS = 3000; // 3 seconds -static constexpr auto POLL_SECONDS = 1024; // 2ˆ10 -static constexpr auto JAN_1970 = 0x83aa7e80; // 2208988800 1970 - 1900 in seconds - -/* How to multiply by 4294.967296 quickly (and not quite exactly) - * without using floating point or greater than 32-bit integers. - * If you want to fix the last 12 microseconds of error, add in - * (2911*(x))>>28) - */ -#define NTPFRAC(x) ( 4294U*static_cast(x) + ( (1981U*static_cast(x))>>11 ) + ((2911U*static_cast(x))>>28) ) - -/* The reverse of the above, needed if we want to set our microsecond - * clock (via clock_settime) based on the incoming time in NTP format. - * Basically exact. - */ -#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) ) - -/* -Timestamp Name ID When Generated ----------------------------------------------------------------- -Originate Timestamp T1 time request sent by client -Receive Timestamp T2 time request received by server -Transmit Timestamp T3 time reply sent by server -Destination Timestamp T4 time reply received by client -*/ - -NtpClient *NtpClient::s_pThis = nullptr; - -NtpClient::NtpClient(uint32_t nServerIp): m_nServerIp(nServerIp) { - DEBUG_ENTRY - assert(s_pThis == nullptr); - s_pThis = this; - - if (m_nServerIp == 0) { - m_nServerIp = Network::Get()->GetNtpServerIp(); - } - - SetUtcOffset(Network::Get()->GetNtpUtcOffset()); - - memset(&m_Request, 0, sizeof m_Request); - memset(&m_Reply, 0, sizeof m_Reply); - - m_Request.LiVnMode = NTP_VERSION | NTP_MODE_CLIENT; - m_Request.Poll = 10; // Poll: 1024 seconds - m_Request.ReferenceID = ('A' << 0) | ('V' << 8) | ('S' << 16); - - DEBUG_EXIT -} - -void NtpClient::SetUtcOffset(float fUtcOffset) { - // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - m_nUtcOffset = Utc::Validate(fUtcOffset); -} - -/* - * Seconds and Fractions since 01.01.1900 - */ -void NtpClient::GetTimeNtpFormat(uint32_t &nSeconds, uint32_t &nFraction) { - struct timeval now; - gettimeofday(&now, nullptr); - nSeconds = static_cast(now.tv_sec - m_nUtcOffset) + JAN_1970; - nFraction = NTPFRAC(now.tv_usec); -} - -void NtpClient::Send() { - GetTimeNtpFormat(T1.nSeconds, T1.nFraction); - - m_Request.OriginTimestamp_s = __builtin_bswap32(T1.nSeconds); - m_Request.OriginTimestamp_f = __builtin_bswap32(T1.nFraction); - - Network::Get()->SendTo(m_nHandle, &m_Request, sizeof m_Request, m_nServerIp, NTP_UDP_PORT); -} - -bool NtpClient::Receive() { - uint32_t nFromIp; - uint16_t nFromPort; - - const uint16_t nBytesReceived = Network::Get()->RecvFrom(m_nHandle, &m_Reply, sizeof m_Reply, &nFromIp, &nFromPort); - - if (__builtin_expect((nBytesReceived != sizeof m_Reply), 1)) { - return false; - } - - GetTimeNtpFormat(T4.nSeconds, T4.nFraction); - - if (__builtin_expect((nFromIp != m_nServerIp), 0)) { - DEBUG_PUTS("nFromIp != m_nServerIp"); - return false; - } - - T2.nSeconds = __builtin_bswap32(m_Reply.ReceiveTimestamp_s); - T2.nFraction = __builtin_bswap32(m_Reply.ReceiveTimestamp_f); - - T3.nSeconds = __builtin_bswap32(m_Reply.TransmitTimestamp_s); - T3.nFraction = __builtin_bswap32(m_Reply.TransmitTimestamp_f); - - PrintNtpTime("Originate", &T1); - PrintNtpTime("Receive", &T2); - PrintNtpTime("Transmit", &T3); - PrintNtpTime("Destination", &T4); - - return true; -} - -void NtpClient::Difference(const struct TimeStamp *Start, const struct TimeStamp *Stop, int32_t &nDiffSeconds, uint32_t &nDiffMicros) { - nDiffSeconds = static_cast(Stop->nSeconds - Start->nSeconds); - uint32_t nDiffFraction; - - if (Stop->nFraction >= Start->nFraction) { - nDiffFraction = Stop->nFraction - Start->nFraction; - } else { - nDiffFraction = Start->nFraction - Stop->nFraction; - nDiffFraction = ~nDiffFraction; - nDiffSeconds -= 1; - } - - nDiffMicros = USEC(nDiffFraction); - - DEBUG_PRINTF("Seconds %u - %u = %d", Stop->nSeconds, Start->nSeconds, nDiffSeconds); - DEBUG_PRINTF("Micros %u - %u = %u", USEC(Stop->nFraction), USEC(Start->nFraction), nDiffMicros); -} - -int NtpClient::SetTimeOfDay() { - int32_t nDiffSeconds1, nDiffSeconds2 ; - uint32_t nDiffFraction1, nDiffFraction2; - - Difference(&T1, &T2, nDiffSeconds1, nDiffFraction1); - Difference(&T4, &T3, nDiffSeconds2, nDiffFraction2); - - m_nOffsetSeconds = nDiffSeconds1 + nDiffSeconds2; - m_nOffsetMicros = nDiffFraction1 + nDiffFraction2; - - if (m_nOffsetMicros >= 1000000u) { - m_nOffsetMicros -= 1000000u; - m_nOffsetSeconds += 1; - } - - m_nOffsetSeconds /= 2; - m_nOffsetMicros /= 2; - - struct timeval tv; - - tv.tv_sec = static_cast(T4.nSeconds - JAN_1970) + m_nOffsetSeconds + m_nUtcOffset; - tv.tv_usec = static_cast(static_cast(USEC(T4.nFraction)) + static_cast(m_nOffsetMicros)); - - if (tv.tv_usec >= 1000000) { - tv.tv_sec++; - tv.tv_usec = 1000000 - tv.tv_usec; - } - - DEBUG_PRINTF("(%ld, %d) %s ", tv.tv_sec, static_cast(tv.tv_usec) , tv.tv_usec >= 1E6 ? "!" : ""); - DEBUG_PRINTF("%d %u",m_nOffsetSeconds, m_nOffsetMicros); - - return settimeofday(&tv, nullptr); -} - -void NtpClient::Start() { - DEBUG_ENTRY - - if (m_nServerIp == 0) { - m_tStatus = ntpclient::Status::FAILED; - DEBUG_EXIT - return; - } - - if ((m_tStatus != ntpclient::Status::IDLE) && (m_tStatus != ntpclient::Status::STOPPED)) { - DEBUG_EXIT - return; - } - - m_nHandle = Network::Get()->Begin(NTP_UDP_PORT); - assert(m_nHandle != -1); - - if (m_pNtpClientDisplay != nullptr) { - m_pNtpClientDisplay->ShowNtpClientStatus(ntpclient::Status::IDLE); - } - - const uint32_t nNow = Hardware::Get()->Millis(); - uint32_t nRetries; - - for (nRetries = 0; nRetries < RETRIES; nRetries++) { - Send(); - - while (!Receive()) { -#if defined (HAVE_NET_HANDLE) - net_handle(); -#endif - if ((Hardware::Get()->Millis() - nNow) > TIMEOUT_MILLIS) { - break; - } - } - - if ((m_Reply.LiVnMode & NTP_MODE_SERVER) == NTP_MODE_SERVER) { - if (SetTimeOfDay() == 0) { - m_tStatus = ntpclient::Status::IDLE; - } else { - // Error - } - } else { - DEBUG_PUTS("!>> Invalid reply <Millis(); - - if (nRetries == RETRIES) { - m_tStatus = ntpclient::Status::FAILED; - - if (m_pNtpClientDisplay != nullptr) { - m_pNtpClientDisplay->ShowNtpClientStatus(ntpclient::Status::FAILED); - } - } - - - DEBUG_PRINTF("nRetries=%d, m_tStatus=%d", nRetries, static_cast(m_tStatus)); - -#if !defined(DISABLE_RTC) - if (m_tStatus != ntpclient::Status::FAILED) { - printf("Set RTC from System Clock\n"); - HwClock::Get()->SysToHc(); -#ifndef NDEBUG - const auto rawtime = time(nullptr); - printf(asctime(localtime(&rawtime))); -#endif - } -#endif - - DEBUG_EXIT -} - -void NtpClient::Stop() { - DEBUG_ENTRY - - if (m_tStatus == ntpclient::Status::STOPPED) { - return; - } - - m_nHandle = Network::Get()->End(NTP_UDP_PORT); - m_tStatus = ntpclient::Status::STOPPED; - - if (m_pNtpClientDisplay != nullptr) { - m_pNtpClientDisplay->ShowNtpClientStatus(ntpclient::Status::STOPPED); - } - - DEBUG_EXIT -} - -void NtpClient::Run() { - if (__builtin_expect((m_nServerIp == 0), 0)) { - return; - } - - if ((m_tStatus == ntpclient::Status::IDLE) || (m_tStatus == ntpclient::Status::FAILED)) { - if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisLastPoll) > (1000 * POLL_SECONDS)), 0)) { - Send(); - m_MillisRequest = Hardware::Get()->Millis(); - m_tStatus = ntpclient::Status::WAITING; - DEBUG_PUTS("ntpclient::Status::WAITING"); - } - - return; - } - - if (m_tStatus == ntpclient::Status::WAITING) { - if (!Receive()) { - if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisRequest) > TIMEOUT_MILLIS), 0)) { - m_tStatus = ntpclient::Status::FAILED; - - if (m_pNtpClientDisplay != nullptr) { - m_pNtpClientDisplay->ShowNtpClientStatus(ntpclient::Status::FAILED); - } - DEBUG_PUTS("ntpclient::Status::FAILED"); - } - - return; - } - - if (__builtin_expect(((m_Reply.LiVnMode & NTP_MODE_SERVER) == NTP_MODE_SERVER), 1)) { - m_MillisLastPoll = Hardware::Get()->Millis(); - - if (SetTimeOfDay() == 0) { -#ifndef NDEBUG - const time_t nTime = time(nullptr); - const struct tm *pLocalTime = localtime(&nTime); - DEBUG_PRINTF("%.4d/%.2d/%.2d %.2d:%.2d:%.2d", pLocalTime->tm_year, pLocalTime->tm_mon, pLocalTime->tm_mday, pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec); -#endif - } else { - // Error - } - } else { - DEBUG_PUTS("!>> Invalid reply <(pNtpTime->nSeconds - JAN_1970); - const auto *pTm = localtime(&nSeconds); - printf("%s %02d:%02d:%02d.%06d %04d [%u]\n", pText, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, USEC(pNtpTime->nFraction), pTm->tm_year + 1900, pNtpTime->nSeconds); -#endif -} - -void NtpClient::Print() { - printf("NTP v%d Client\n", NTP_VERSION >> 3); - if (m_nServerIp == 0) { - printf(" Not enabled\n"); - return; - } - printf(" Server : " IPSTR ":%d\n", IP2STR(m_nServerIp), NTP_UDP_PORT); - printf(" Status : %d\n", static_cast(m_tStatus)); - printf(" UTC offset : %d (seconds)\n", m_nUtcOffset); -#ifndef NDEBUG - PrintNtpTime("Originate", &T1); - PrintNtpTime("Receive", &T2); - PrintNtpTime("Transmit", &T3); - PrintNtpTime("Destination", &T4); -#endif -} diff --git a/lib-network/src/apps/tftpdaemon.cpp b/lib-network/src/apps/tftp/tftpdaemon.cpp similarity index 74% rename from lib-network/src/apps/tftpdaemon.cpp rename to lib-network/src/apps/tftp/tftpdaemon.cpp index 72ea53e..ca31123 100644 --- a/lib-network/src/apps/tftpdaemon.cpp +++ b/lib-network/src/apps/tftp/tftpdaemon.cpp @@ -56,7 +56,8 @@ enum TErrorCode { ERROR_CODE_INV_USER = 7 ///< No such user. }; -#define TFTP_UDP_PORT 69 +namespace tftp { +static constexpr uint16_t UDP_PORT = 69; namespace min { static constexpr auto FILENAME_MODE_LEN = (1 + 1 + 1 + 1); @@ -71,32 +72,33 @@ namespace max { } #if !defined (PACKED) - #define PACKED __attribute__((packed)) +# define PACKED __attribute__((packed)) #endif -struct TTFTPReqPacket { +struct ReqPacket { uint16_t OpCode; char FileNameMode[max::FILENAME_MODE_LEN]; } PACKED; -struct TTFTPAckPacket { +struct AckPacket { uint16_t OpCode; uint16_t BlockNumber; } PACKED; -struct TTFTPErrorPacket { +struct ErrorPacket { uint16_t OpCode; uint16_t ErrorCode; char ErrMsg[max::ERRMSG_LEN]; } PACKED; -struct TTFTPDataPacket { +struct DataPacket { uint16_t OpCode; uint16_t BlockNumber; uint8_t Data[max::DATA_LEN]; } PACKED; +} // namespace tftp -TFTPDaemon *TFTPDaemon::s_pThis = nullptr; +TFTPDaemon *TFTPDaemon::s_pThis; TFTPDaemon::TFTPDaemon() { DEBUG_ENTRY @@ -109,10 +111,6 @@ TFTPDaemon::TFTPDaemon() { s_pThis = this; DEBUG_PRINTF("s_pThis=%p", reinterpret_cast(s_pThis)); - - assert(Network::Get() != nullptr); - memset(m_Buffer, 0, sizeof(m_Buffer)); - DEBUG_EXIT } @@ -127,28 +125,26 @@ TFTPDaemon::~TFTPDaemon() { DEBUG_EXIT } -bool TFTPDaemon::Run() { - +void TFTPDaemon::Run() { if (m_nState == TFTPState::INIT) { if (m_nFromPort != 0) { Network::Get()->End(m_nFromPort); m_nIdx = -1; } - m_nIdx = Network::Get()->Begin(TFTP_UDP_PORT); + m_nIdx = Network::Get()->Begin(tftp::UDP_PORT); DEBUG_PRINTF("m_nIdx=%d", m_nIdx); - m_nFromPort = TFTP_UDP_PORT; + m_nFromPort = tftp::UDP_PORT; m_nBlockNumber = 0; m_nState = TFTPState::WAITING_RQ; m_bIsLastBlock = false; - memset(&m_Buffer, 0, sizeof(struct TTFTPReqPacket)); } else { - m_nLength = Network::Get()->RecvFrom(m_nIdx, &m_Buffer, sizeof(m_Buffer), &m_nFromIp, &m_nFromPort); + m_nLength = Network::Get()->RecvFrom(m_nIdx, const_cast(reinterpret_cast(&m_pBuffer)), &m_nFromIp, &m_nFromPort); switch (m_nState) { case TFTPState::WAITING_RQ: - if (m_nLength > min::FILENAME_MODE_LEN) { + if (m_nLength > tftp::min::FILENAME_MODE_LEN) { HandleRequest(); } break; @@ -156,12 +152,12 @@ bool TFTPDaemon::Run() { DoRead(); break; case TFTPState::RRQ_RECV_ACK: - if (m_nLength == sizeof(struct TTFTPAckPacket)) { + if (m_nLength == sizeof(struct tftp::AckPacket)) { HandleRecvAck(); } break; case TFTPState::WRQ_RECV_PACKET: - if (m_nLength <= sizeof(struct TTFTPDataPacket)) { + if (m_nLength <= sizeof(struct tftp::DataPacket)) { HandleRecvData(); } break; @@ -170,37 +166,35 @@ bool TFTPDaemon::Run() { __builtin_unreachable(); break; } - } - - return true; } void TFTPDaemon::HandleRequest() { - auto *packet = reinterpret_cast(&m_Buffer); + auto *const pPacket = reinterpret_cast(m_pBuffer); + assert(pPacket != nullptr); - const uint16_t nOpCode = __builtin_bswap16(packet->OpCode); + const auto nOpCode = __builtin_bswap16(pPacket->OpCode); if ((nOpCode != OP_CODE_RRQ && nOpCode != OP_CODE_WRQ)) { SendError(ERROR_CODE_ILL_OPER, "Invalid operation"); return; } - const char *pFileName = packet->FileNameMode; - const size_t nNameLen = strlen(pFileName); + const char *const pFileName = pPacket->FileNameMode; + const auto nFileNameLength = strlen(pFileName); - if (!(1 <= nNameLen && nNameLen <= max::FILENAME_LEN)) { + if (!(1 <= nFileNameLength && nFileNameLength <= tftp::max::FILENAME_LEN)) { SendError(ERROR_CODE_OTHER, "Invalid file name"); return; } - const char *pMode = &packet->FileNameMode[nNameLen + 1]; - TFTPMode tMode; + const char *const pMode = &pPacket->FileNameMode[nFileNameLength + 1]; + tftp::Mode mode; if (strncmp(pMode, "octet", 5) == 0) { - tMode = TFTPMode::BINARY; + mode = tftp::Mode::BINARY; } else if (strncmp(pMode, "netascii", 8) == 0) { - tMode = TFTPMode::ASCII; + mode = tftp::Mode::ASCII; } else { SendError(ERROR_CODE_ILL_OPER, "Invalid operation"); return; @@ -210,22 +204,22 @@ void TFTPDaemon::HandleRequest() { switch (nOpCode) { case OP_CODE_RRQ: - if(!FileOpen(pFileName, tMode)) { + if(!FileOpen(pFileName, mode)) { SendError(ERROR_CODE_NO_FILE, "File not found"); m_nState = TFTPState::WAITING_RQ; } else { - Network::Get()->End(TFTP_UDP_PORT); + Network::Get()->End(tftp::UDP_PORT); m_nIdx = Network::Get()->Begin(m_nFromPort); m_nState = TFTPState::RRQ_SEND_PACKET; DoRead(); } break; case OP_CODE_WRQ: - if(!FileCreate(pFileName, tMode)) { + if(!FileCreate(pFileName, mode)) { SendError(ERROR_CODE_ACCESS, "Access violation"); m_nState = TFTPState::WAITING_RQ; } else { - Network::Get()->End(TFTP_UDP_PORT); + Network::Get()->End(tftp::UDP_PORT); m_nIdx = Network::Get()->Begin(m_nFromPort); m_nState = TFTPState::WRQ_SEND_ACK; DoWriteAck(); @@ -238,8 +232,8 @@ void TFTPDaemon::HandleRequest() { } } -void TFTPDaemon::SendError (uint16_t nErrorCode, const char *pErrorMessage) { - TTFTPErrorPacket ErrorPacket; +void TFTPDaemon::SendError (const uint16_t nErrorCode, const char *pErrorMessage) { + tftp::ErrorPacket ErrorPacket; ErrorPacket.OpCode = __builtin_bswap16 (OP_CODE_ERROR); ErrorPacket.ErrorCode = __builtin_bswap16 (nErrorCode); @@ -249,16 +243,17 @@ void TFTPDaemon::SendError (uint16_t nErrorCode, const char *pErrorMessage) { } void TFTPDaemon::DoRead() { - auto *const pDataPacket = reinterpret_cast(&m_Buffer); + auto *const pDataPacket = reinterpret_cast(m_pBuffer); + assert(pDataPacket != nullptr); if (m_nState == TFTPState::RRQ_SEND_PACKET) { - m_nDataLength = FileRead(pDataPacket->Data, max::DATA_LEN, ++m_nBlockNumber); + m_nDataLength = FileRead(pDataPacket->Data, tftp::max::DATA_LEN, ++m_nBlockNumber); pDataPacket->OpCode = __builtin_bswap16(OP_CODE_DATA); pDataPacket->BlockNumber = __builtin_bswap16(m_nBlockNumber); m_nPacketLength = static_cast(sizeof pDataPacket->OpCode + sizeof pDataPacket->BlockNumber + m_nDataLength); - m_bIsLastBlock = m_nDataLength < max::DATA_LEN; + m_bIsLastBlock = m_nDataLength < tftp::max::DATA_LEN; if (m_bIsLastBlock) { FileClose(); @@ -269,13 +264,14 @@ void TFTPDaemon::DoRead() { DEBUG_PRINTF("Sending to " IPSTR ":%d", IP2STR(m_nFromIp), m_nFromPort); - Network::Get()->SendTo(m_nIdx, &m_Buffer, m_nPacketLength, m_nFromIp, m_nFromPort); + Network::Get()->SendTo(m_nIdx, m_pBuffer, m_nPacketLength, m_nFromIp, m_nFromPort); m_nState = TFTPState::RRQ_RECV_ACK; } void TFTPDaemon::HandleRecvAck() { - const auto *const pAckPacket = reinterpret_cast(&m_Buffer); + const auto *const pAckPacket = reinterpret_cast(m_pBuffer); + assert(pAckPacket != nullptr); if (pAckPacket->OpCode == __builtin_bswap16(OP_CODE_ACK)) { @@ -288,7 +284,8 @@ void TFTPDaemon::HandleRecvAck() { } void TFTPDaemon::DoWriteAck() { - auto *const pAckPacket = reinterpret_cast(&m_Buffer); + auto *const pAckPacket = reinterpret_cast(m_pBuffer); + assert(pAckPacket != nullptr); pAckPacket->OpCode = __builtin_bswap16(OP_CODE_ACK); pAckPacket->BlockNumber = __builtin_bswap16(m_nBlockNumber); @@ -296,21 +293,22 @@ void TFTPDaemon::DoWriteAck() { DEBUG_PRINTF("Sending to " IPSTR ":%d, m_nState=%d", IP2STR(m_nFromIp), m_nFromPort, static_cast(m_nState)); - Network::Get()->SendTo(m_nIdx, &m_Buffer, sizeof(struct TTFTPAckPacket), m_nFromIp, m_nFromPort); + Network::Get()->SendTo(m_nIdx, m_pBuffer, sizeof(struct tftp::AckPacket), m_nFromIp, m_nFromPort); } void TFTPDaemon::HandleRecvData() { - const auto *const pDataPacket = reinterpret_cast(&m_Buffer); + const auto *const pDataPacket = reinterpret_cast(m_pBuffer); + assert(pDataPacket != nullptr); if (pDataPacket->OpCode == __builtin_bswap16(OP_CODE_DATA)) { m_nDataLength = m_nLength - 4; m_nBlockNumber = __builtin_bswap16(pDataPacket->BlockNumber); - DEBUG_PRINTF("Incoming from " IPSTR ", m_nLength=%ld, m_nBlockNumber=%d, m_nDataLength=%ld", IP2STR(m_nFromIp), m_nLength, m_nBlockNumber,m_nDataLength); + DEBUG_PRINTF("Incoming from " IPSTR ", m_nLength=%u, m_nBlockNumber=%d, m_nDataLength=%u", IP2STR(m_nFromIp), static_cast(m_nLength), m_nBlockNumber, static_cast(m_nDataLength)); if (m_nDataLength == FileWrite(pDataPacket->Data, m_nDataLength, m_nBlockNumber)) { - if (m_nDataLength < max::DATA_LEN) { + if (m_nDataLength < tftp::max::DATA_LEN) { m_bIsLastBlock = true; FileClose(); } diff --git a/include/cstddef b/lib-network/src/emac/gd32/debug_print_bits.c similarity index 70% rename from include/cstddef rename to lib-network/src/emac/gd32/debug_print_bits.c index 68a245a..4874795 100644 --- a/include/cstddef +++ b/lib-network/src/emac/gd32/debug_print_bits.c @@ -1,8 +1,8 @@ /** - * @file cstddef + * @file debug_print_bits.c * */ -/* Copyright (C) 2017-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,26 @@ * THE SOFTWARE. */ -#ifndef CSTDDEF_ -#define CSTDDEF_ +#include +#include -#ifdef __cplusplus -# include +#if defined (H3) +extern int uart0_printf(const char* fmt, ...); +# define printf uart0_printf #endif -#endif /* CSTDDEF_ */ +void debug_print_bits(uint32_t u) { + uint32_t i; + + uint32_t b = 1U << 31; + + for (i = 0; i < 32; i++) { + if ((b & u) == b) { + uint32_t bit_number = 31 - i; + printf("%-2d ", bit_number); + } + b = b >> 1; + } + + printf("\n"); +} diff --git a/lib-gd32/device/emac/emac.cpp b/lib-network/src/emac/gd32/emac.cpp similarity index 74% rename from lib-gd32/device/emac/emac.cpp rename to lib-network/src/emac/gd32/emac.cpp index ec3a06e..811fedf 100644 --- a/lib-gd32/device/emac/emac.cpp +++ b/lib-network/src/emac/gd32/emac.cpp @@ -28,6 +28,8 @@ #include "gd32.h" +#include "emac/phy.h" + #include "debug.h" extern enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; @@ -140,41 +142,11 @@ static void enet_gpio_config(void) { DEBUG_EXIT } -static ErrStatus enet_mac_config(void) { - DEBUG_ENTRY - rcu_periph_clock_enable(RCU_ENET); - rcu_periph_clock_enable(RCU_ENETTX); - rcu_periph_clock_enable(RCU_ENETRX); - - enet_deinit(); - - if (enet_software_reset() == ERROR) { - DEBUG_EXIT - return ERROR; - } - - ErrStatus enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_CUSTOM); - - DEBUG_PRINTF("enet_init_status=%u", (uint32_t)enet_init_status); - -#ifndef NDEBUG - uint16_t phy_value; - ErrStatus phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); - printf("BCR: %.4x %s\n", phy_value, phy_state == SUCCESS ? "SUCCES" : "ERROR" ); - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); - phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); - printf("BSR: %.4x %s\n", phy_value & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS | PHY_JABBER_DETECTION), phy_state == SUCCESS ? "SUCCES" : "ERROR" ); -#endif - - return enet_init_status; - DEBUG_EXIT -} - /* * Public function */ -int emac_start(uint8_t mac_address[]) { +void __attribute__((cold)) emac_config() { DEBUG_ENTRY #if(PHY_TYPE == LAN8700) puts("LAN8700"); @@ -185,11 +157,74 @@ int emac_start(uint8_t mac_address[]) { #else #error PHY_TYPE is not set #endif - DEBUG_PRINTF("ENET_RXBUF_NUM=%u, ENET_TXBUF_NUM=%u", ENET_RXBUF_NUM, ENET_TXBUF_NUM); enet_gpio_config(); - const auto enet_dma_status = enet_mac_config(); + rcu_periph_clock_enable(RCU_ENET); + rcu_periph_clock_enable(RCU_ENETTX); + rcu_periph_clock_enable(RCU_ENETRX); + + enet_deinit(); + enet_software_reset(); + + net::phy_config(PHY_ADDRESS); + + DEBUG_EXIT +} + +void __attribute__((cold)) emac_start(uint8_t mac_address[], net::Link& link) { + DEBUG_ENTRY + DEBUG_PRINTF("ENET_RXBUF_NUM=%u, ENET_TXBUF_NUM=%u", ENET_RXBUF_NUM, ENET_TXBUF_NUM); + + net::PhyStatus phyStatus; + net::phy_start(PHY_ADDRESS, phyStatus); + + link = phyStatus.link; + +#ifndef NDEBUG + { + uint16_t phy_value; + ErrStatus phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + printf("BCR: %.4x %s\n", phy_value, phy_state == SUCCESS ? "SUCCES" : "ERROR" ); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + printf("BSR: %.4x %s\n", phy_value & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS | PHY_JABBER_DETECTION), phy_state == SUCCESS ? "SUCCES" : "ERROR" ); + } +#endif + + enet_mediamode_enum mediamode = ENET_10M_HALFDUPLEX; + + if (phyStatus.speed == net::Speed::SPEED100) { + if (phyStatus.duplex == net::Duplex::DUPLEX_FULL) { + mediamode = ENET_100M_FULLDUPLEX; + } else { + mediamode = ENET_100M_HALFDUPLEX; + } + } else if (phyStatus.duplex == net::Duplex::DUPLEX_FULL) { + mediamode = ENET_10M_FULLDUPLEX; + } + + printf("Link %s, %d, %s\n", + phyStatus.link == net::Link::STATE_UP ? "Up" : "Down", + phyStatus.speed == net::Speed::SPEED10 ? 10 : 100, + phyStatus.duplex == net::Duplex::DUPLEX_HALF ? "HALF" : "FULL"); + + const auto enet_init_status = enet_init(mediamode, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_CUSTOM); + + if (enet_init_status != SUCCESS) {} + + DEBUG_PRINTF("enet_init_status=%s", enet_init_status == SUCCESS ? "SUCCES" : "ERROR" ); + +#ifndef NDEBUG + { + uint16_t phy_value; + ErrStatus phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); + printf("BCR: %.4x %s\n", phy_value, phy_state == SUCCESS ? "SUCCES" : "ERROR" ); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + printf("BSR: %.4x %s\n", phy_value & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS | PHY_JABBER_DETECTION), phy_state == SUCCESS ? "SUCCES" : "ERROR" ); + } +#endif mac_address_get(mac_address); @@ -205,5 +240,4 @@ int emac_start(uint8_t mac_address[]) { enet_enable(); DEBUG_EXIT - return (enet_dma_status == ERROR) ? - 1 : 0; } diff --git a/lib-gd32/device/emac/net.c b/lib-network/src/emac/gd32/net.c similarity index 100% rename from lib-gd32/device/emac/net.c rename to lib-network/src/emac/gd32/net.c diff --git a/lib-network/src/emac/gd32/net_link_check.cpp b/lib-network/src/emac/gd32/net_link_check.cpp index fa54edc..1571107 100644 --- a/lib-network/src/emac/gd32/net_link_check.cpp +++ b/lib-network/src/emac/gd32/net_link_check.cpp @@ -33,51 +33,15 @@ #include "debug.h" namespace net { -#if (PHY_TYPE == RTL8201F) - void phy_write_paged(uint16_t phy_page, uint16_t phy_reg, uint16_t phy_value, uint16_t mask = 0x0); -#endif - -static void link_pin_enable() { - uint16_t phy_value; -#if (PHY_TYPE == LAN8700) - -#elif (PHY_TYPE == DP83848) - phy_value = PHY_INT_AND_OUTPUT_ENABLE; - enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_MICR, &phy_value); - - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_MICR, &phy_value); - - if (PHY_INT_AND_OUTPUT_ENABLE != phy_value) { - DEBUG_PUTS("PHY_INT_AND_OUTPUT_ENABLE != phy_value"); - } - - phy_value = PHY_LINK_INT_ENABLE; - enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_MISR, &phy_value); -#elif (PHY_TYPE == RTL8201F) - phy_write_paged(0x07, PHY_REG_IER, PHY_REG_IER_INT_ENABLE, PHY_REG_IER_INT_ENABLE); - // Clear interrupt - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_ISR, &phy_value); -#endif -} - -static void link_gpio_init() { +#if defined (ENET_LINK_CHECK_USE_INT) || defined (ENET_LINK_CHECK_USE_PIN_POLL) +void link_gpio_init() { rcu_periph_clock_enable(LINK_CHECK_GPIO_CLK); LINK_CHECK_GPIO_CONFIG; } - -static void link_pin_recovery() { - uint16_t phy_value; -#if (PHY_TYPE == LAN8700) - -#elif (PHY_TYPE == DP83848) - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_MISR, &phy_value); -#elif (PHY_TYPE == RTL8201F) - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_ISR, &phy_value); #endif - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); -} -static void link_exti_init() { +#if defined (ENET_LINK_CHECK_USE_INT) +void link_exti_init() { rcu_periph_clock_enable(LINK_CHECK_EXTI_CLK); NVIC_SetPriority(LINK_CHECK_EXTI_IRQn, 7); @@ -88,38 +52,17 @@ static void link_exti_init() { exti_init(LINK_CHECK_EXTI_LINE, EXTI_INTERRUPT, EXTI_TRIG_FALLING); exti_interrupt_flag_clear(LINK_CHECK_EXTI_LINE); } +#endif -void link_interrupt_init() { - link_pin_enable(); - link_pin_recovery(); - link_gpio_init(); - link_exti_init(); -} - -void link_pin_poll_init() { - link_pin_enable(); - link_pin_recovery(); - link_gpio_init(); -} - +#if defined (ENET_LINK_CHECK_USE_PIN_POLL) void link_pin_poll() { if (RESET == gpio_input_bit_get(LINK_CHECK_GPIO_PORT, LINK_CHECK_GPIO_PIN)) { link_pin_recovery(); - link_handle_change(link_register_read()); + link_handle_change(link_status_read()); } } +#endif -net::Link link_register_read() { - uint16_t phy_value; - - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); - - if (PHY_LINKED_STATUS == (phy_value & PHY_LINKED_STATUS)) { - return net::Link::STATE_UP; - } - - return net::Link::STATE_DOWN; -} } // namespace net #if defined (ENET_LINK_CHECK_USE_INT) @@ -128,7 +71,7 @@ void LINK_CHECK_IRQ_HANDLE(void) { if (RESET != exti_interrupt_flag_get(LINK_CHECK_EXTI_LINE)) { exti_interrupt_flag_clear(LINK_CHECK_EXTI_LINE); net::link_pin_recovery(); - net::link_handle_change(net::link_register_read()); + net::link_handle_change(net::link_status_read()); } } } diff --git a/lib-network/src/emac/gd32/net_phy.cpp b/lib-network/src/emac/gd32/net_phy.cpp new file mode 100644 index 0000000..018729a --- /dev/null +++ b/lib-network/src/emac/gd32/net_phy.cpp @@ -0,0 +1,138 @@ +/** + * net_phy.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "emac/phy.h" +#include "emac/mmi.h" + +#include "gd32.h" + +#include "debug.h" + +extern volatile uint32_t s_nSysTickMillis; + +namespace net { + +bool phy_read(uint32_t nAddress, const uint32_t nRegister, uint16_t &nValue) { + const auto bResult = enet_phy_write_read(ENET_PHY_READ, nAddress, nRegister, &nValue) == SUCCESS; +// DEBUG_PRINTF("%d %.2x %.2x %.4x", bResult, nAddress, nRegister, nValue); + return bResult; +} + +bool phy_write(uint32_t nAddress, const uint32_t nRegister, uint16_t nValue) { + const auto bResult = enet_phy_write_read(ENET_PHY_WRITE, nAddress, nRegister, &nValue) == SUCCESS; +// DEBUG_PRINTF("%d %.2x %.2x %.4x", bResult, nAddress, nRegister, nValue); + return bResult; +} + +bool phy_config(const uint32_t nAddress) { + DEBUG_ENTRY + + uint32_t reg = ENET_MAC_PHY_CTL; + reg &= ~ENET_MAC_PHY_CTL_CLR; + + const uint32_t ahbclk = rcu_clock_freq_get(CK_AHB); + +#if defined GD32F10X_CL + if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { + reg |= ENET_MDC_HCLK_DIV16; + } else if (ENET_RANGE(ahbclk, 35000000U, 60000000U)) { + reg |= ENET_MDC_HCLK_DIV26; + } else if (ENET_RANGE(ahbclk, 60000000U, 90000000U)) { + reg |= ENET_MDC_HCLK_DIV42; + } else if ((ENET_RANGE(ahbclk, 90000000U, 108000000U)) || (108000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV62; + } else { + return false; + } +#elif defined GD32F20X + if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { + reg |= ENET_MDC_HCLK_DIV16; + } else if (ENET_RANGE(ahbclk, 35000000U, 60000000U)) { + reg |= ENET_MDC_HCLK_DIV26; + } else if (ENET_RANGE(ahbclk, 60000000U, 100000000U)) { + reg |= ENET_MDC_HCLK_DIV42; + } else if ((ENET_RANGE(ahbclk, 100000000U, 120000000U)) || (120000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV62; + } else { + return false; + } +#elif defined GD32F4XX + if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { + reg |= ENET_MDC_HCLK_DIV16; + } else if (ENET_RANGE(ahbclk, 35000000U, 60000000U)) { + reg |= ENET_MDC_HCLK_DIV26; + } else if (ENET_RANGE(ahbclk, 60000000U, 100000000U)) { + reg |= ENET_MDC_HCLK_DIV42; + } else if (ENET_RANGE(ahbclk, 100000000U, 150000000U)) { + reg |= ENET_MDC_HCLK_DIV62; + } else if ((ENET_RANGE(ahbclk, 150000000U, 200000000U)) || (200000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV102; + } else { + return false; + } +#endif + + ENET_MAC_PHY_CTL = reg; + + if (!phy_write(nAddress, mmi::REG_BMCR, mmi::BMCR_RESET)) { + DEBUG_PUTS("PHY reset failed"); + return false; + } + + /* + * Poll the control register for the reset bit to go to 0 (it is + * auto-clearing). This should happen within 0.5 seconds per the + * IEEE spec. + */ + + const auto nMillis = s_nSysTickMillis; + uint16_t nValue; + + while (s_nSysTickMillis - nMillis < 500) { + if (!phy_read(nAddress, mmi::REG_BMCR, nValue)) { + DEBUG_PUTS("PHY status read failed"); + return false; + } + + if (!(nValue & mmi::BMCR_RESET)) { + DEBUG_PRINTF("%u", s_nSysTickMillis - nMillis); + DEBUG_EXIT + return true; + } + } + + if (nValue & mmi::BMCR_RESET) { + DEBUG_PUTS("PHY reset timed out"); + return false; + } + + DEBUG_PRINTF("%u", s_nSysTickMillis - nMillis); + DEBUG_EXIT + return true; +} + +} // namespace net diff --git a/lib-network/src/emac/network.cpp b/lib-network/src/emac/network.cpp index dc2084b..8ad248a 100755 --- a/lib-network/src/emac/network.cpp +++ b/lib-network/src/emac/network.cpp @@ -2,7 +2,7 @@ * network.cpp * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,68 +35,68 @@ #include "../net/net.h" #include "../../config/net_config.h" + +#include "emac/emac.h" +#include "emac/phy.h" +#include "emac/mmi.h" #include "emac/net_link_check.h" #include "debug.h" -namespace net { -void __attribute__((weak)) phy_customized_led() {} -void __attribute__((weak)) phy_customized_timing() {} -} // namespace net +namespace network { +void __attribute__((weak)) mdns_announcement() {} +void __attribute__((weak)) mdns_shutdown() {} +} // namespace network -#define TO_HEX(i) static_cast(((i) < 10) ? '0' + (i) : 'A' + ((i) - 10)) +static constexpr char TO_HEX(const char i) { + return static_cast(((i) < 10) ? '0' + i : 'A' + (i - 10)); +} -int emac_start(uint8_t paddr[]); +#if !defined PHY_ADDRESS +# define PHY_ADDRESS 1 +#endif Network *Network::s_pThis; -Network::Network() { +Network::Network(NetworkParamsStore *pNetworkParamsStore) { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - m_aNetMacaddr[0] = '\0'; - m_aHostName[0] = '\0'; m_aDomainName[0] = '\0'; strcpy(m_aIfName, "eth0"); - DEBUG_EXIT -} + network::display_emac_config(); -void Network::Init(NetworkParamsStore *pNetworkParamsStore) { - DEBUG_ENTRY + emac_config(); + + network::display_emac_start(); + + emac_start(m_aNetMacaddr, s_lastState); NetworkParams params(pNetworkParamsStore); if (params.Load()) { params.Dump(); } - - network::display_emac_start(); - - struct ip_info ipInfo; - - ipInfo.ip.addr = params.GetIpAddress(); - ipInfo.netmask.addr = params.GetNetMask(); - ipInfo.gw.addr = params.GetDefaultGateway(); + m_IpInfo.ip.addr = params.GetIpAddress(); + m_IpInfo.netmask.addr = params.GetNetMask(); + m_IpInfo.gw.addr = params.GetDefaultGateway(); m_IsDhcpUsed = params.isDhcpUsed(); - m_nNtpServerIp = params.GetNtpServer(); m_fNtpUtcOffset = params.GetNtpUtcOffset(); - emac_start(m_aNetMacaddr); - net::phy_customized_timing(); net::phy_customized_led(); const auto *p = params.GetHostName(); if (*p == '\0') { - unsigned k = 0; + uint32_t k = 0; - for (unsigned i = 0; (HOST_NAME_PREFIX[i] != 0) && (i < network::HOSTNAME_SIZE - 7); i++) { + for (uint32_t i = 0; (i < (sizeof(HOST_NAME_PREFIX) - 1)) && (i < network::HOSTNAME_SIZE - 7); i++) { m_aHostName[k++] = HOST_NAME_PREFIX[i]; } @@ -117,28 +117,21 @@ void Network::Init(NetworkParamsStore *pNetworkParamsStore) { #elif defined (ENET_LINK_CHECK_USE_PIN_POLL) net::link_pin_poll_init(); #elif defined (ENET_LINK_CHECK_REG_POLL) - net::link_register_read(); + net::link_status_read(); #endif - s_lastState = net::link_register_read(); + network::display_emac_status(net::Link::STATE_UP == s_lastState); if (net::Link::STATE_UP == s_lastState) { DEBUG_PUTS("net::Link::STATE_UP"); if (!m_IsDhcpUsed) { DEBUG_PUTS(""); - if (ipInfo.ip.addr == 0) { + if (m_IpInfo.ip.addr == 0) { DEBUG_PUTS(""); - - SetDefaultIp(); - - ipInfo.ip.addr = m_nLocalIp; - ipInfo.netmask.addr = m_nNetmask; - ipInfo.gw.addr = m_nLocalIp; - } else if (!IsValidIp(m_nGatewayIp)) { + } else if (!IsValidIp(m_IpInfo.gw.addr)) { DEBUG_PUTS(""); - - ipInfo.gw.addr = m_nLocalIp; + m_IpInfo.gw.addr = m_IpInfo.ip.addr; } } @@ -146,7 +139,7 @@ void Network::Init(NetworkParamsStore *pNetworkParamsStore) { network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); } - net_init(m_aNetMacaddr, &ipInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); + net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); if (m_IsZeroconfUsed) { network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); @@ -173,7 +166,7 @@ void Network::Init(NetworkParamsStore *pNetworkParamsStore) { m_IsDhcpUsed = true; m_IsZeroconfUsed = false; - net_init(m_aNetMacaddr, &ipInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); + net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); if (m_IsDhcpUsed) { break; @@ -184,21 +177,19 @@ void Network::Init(NetworkParamsStore *pNetworkParamsStore) { if (m_IsDhcpUsed) { DEBUG_PUTS("m_IsDhcpUsed=true"); - ipInfo.ip.addr = 0; - m_nNetmask = 0; - m_nGatewayIp = 0; + m_IpInfo.ip.addr = 0; + m_IpInfo.netmask.addr = 0; + m_IpInfo.gw.addr = 0; } auto bFalse = false; - net_init(m_aNetMacaddr, &ipInfo, m_aHostName, &bFalse, &bFalse); + net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &bFalse, &bFalse); } - m_nLocalIp = ipInfo.ip.addr; - m_nNetmask = ipInfo.netmask.addr; - m_nGatewayIp = ipInfo.gw.addr; - network::display_ip(); + network::display_netmask(); + network::display_gateway(); DEBUG_EXIT } @@ -213,22 +204,23 @@ void Network::SetIp(uint32_t nIp) { m_IsZeroconfUsed = false; + m_IpInfo.ip.addr = nIp; + if (nIp == 0) { - SetDefaultIp(); - net_set_ip(m_nLocalIp); - // We do not store } else { - net_set_ip(nIp); + m_IpInfo.gw.addr = m_IpInfo.ip.addr; + } - m_nLocalIp = nIp; - m_nGatewayIp = m_nLocalIp; + net_set_ip(&m_IpInfo); + net_set_gw(&m_IpInfo); - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveIp(nIp); - m_pNetworkStore->SaveDhcp(false); - } + if (m_pNetworkStore != nullptr) { + m_pNetworkStore->SaveIp(m_IpInfo.ip.addr); + m_pNetworkStore->SaveGatewayIp(m_IpInfo.gw.addr); + m_pNetworkStore->SaveDhcp(false); } + network::mdns_announcement(); network::display_ip(); network::display_netmask(); @@ -238,15 +230,16 @@ void Network::SetIp(uint32_t nIp) { void Network::SetNetmask(uint32_t nNetmask) { DEBUG_ENTRY - if (m_nNetmask == nNetmask) { + if (m_IpInfo.netmask.addr == nNetmask) { DEBUG_EXIT return; } - m_nNetmask = nNetmask; + m_IpInfo.netmask.addr = nNetmask; + net_set_netmask(&m_IpInfo); if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveNetMask(nNetmask); + m_pNetworkStore->SaveNetMask(m_IpInfo.netmask.addr); } network::display_ip(); @@ -258,15 +251,16 @@ void Network::SetNetmask(uint32_t nNetmask) { void Network::SetGatewayIp(uint32_t nGatewayIp) { DEBUG_ENTRY - if (m_nGatewayIp == nGatewayIp) { + if (m_IpInfo.gw.addr == nGatewayIp) { DEBUG_EXIT return; } - net_set_gw(nGatewayIp); + m_IpInfo.gw.addr = nGatewayIp; + net_set_gw(&m_IpInfo); if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveGatewayIp(nGatewayIp); + m_pNetworkStore->SaveGatewayIp(m_IpInfo.gw.addr); } network::display_gateway(); @@ -284,6 +278,7 @@ void Network::SetHostName(const char *pHostName) { m_pNetworkStore->SaveHostName(m_aHostName, static_cast(strlen(m_aHostName))); } + network::mdns_announcement(); network::display_hostname(); DEBUG_EXIT @@ -292,15 +287,15 @@ void Network::SetHostName(const char *pHostName) { bool Network::SetZeroconf() { DEBUG_ENTRY - struct ip_info tIpInfo; + const auto bWatchdog = Hardware::Get()->IsWatchdog(); - m_IsZeroconfUsed = net_set_zeroconf(&tIpInfo); + if (bWatchdog) { + Hardware::Get()->WatchdogStop(); + } - if (m_IsZeroconfUsed) { - m_nLocalIp = tIpInfo.ip.addr; - m_nNetmask = tIpInfo.netmask.addr; - m_nGatewayIp = tIpInfo.gw.addr; + m_IsZeroconfUsed = net_set_zeroconf(&m_IpInfo); + if (m_IsZeroconfUsed) { m_IsDhcpUsed = false; if (m_pNetworkStore != nullptr) { @@ -308,9 +303,14 @@ bool Network::SetZeroconf() { } } + network::mdns_announcement(); network::display_ip(); network::display_netmask(); + if (bWatchdog) { + Hardware::Get()->WatchdogInit(); + } + DEBUG_EXIT return m_IsZeroconfUsed; } @@ -318,9 +318,7 @@ bool Network::SetZeroconf() { bool Network::EnableDhcp() { DEBUG_ENTRY - struct ip_info tIpInfo; - - const bool bWatchdog = Hardware::Get()->IsWatchdog(); + const auto bWatchdog = Hardware::Get()->IsWatchdog(); if (bWatchdog) { Hardware::Get()->WatchdogStop(); @@ -328,32 +326,29 @@ bool Network::EnableDhcp() { network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - m_IsDhcpUsed = net_set_dhcp(&tIpInfo, m_aHostName, &m_IsZeroconfUsed); + m_IsDhcpUsed = net_set_dhcp(&m_IpInfo, m_aHostName, &m_IsZeroconfUsed); - if (m_IsZeroconfUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); - } else { - network::display_dhcp_status(network::dhcp::ClientStatus::GOT_IP); - } - - DEBUG_PRINTF("m_IsDhcpUsed=%d, m_IsZeroconfUsed=%d", m_IsDhcpUsed, m_IsZeroconfUsed); - - if (bWatchdog) { - Hardware::Get()->WatchdogInit(); + if (m_IsZeroconfUsed) { + network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); + } else { + network::display_dhcp_status(network::dhcp::ClientStatus::GOT_IP); } - m_nLocalIp = tIpInfo.ip.addr; - m_nNetmask = tIpInfo.netmask.addr; - m_nGatewayIp = tIpInfo.gw.addr; + DEBUG_PRINTF("m_IsDhcpUsed=%d, m_IsZeroconfUsed=%d", m_IsDhcpUsed, m_IsZeroconfUsed); if (m_pNetworkStore != nullptr) { m_pNetworkStore->SaveDhcp(m_IsDhcpUsed); } + network::mdns_announcement(); network::display_ip(); network::display_netmask(); network::display_gateway(); + if (bWatchdog) { + Hardware::Get()->WatchdogInit(); + } + DEBUG_EXIT return m_IsDhcpUsed; } @@ -414,13 +409,10 @@ bool Network::ApplyQueuedConfig() { #include void Network::Print() { - printf("Network\n"); + printf("Network [%c]\n", GetAddressingMode()); printf(" Hostname : %s\n", m_aHostName); - printf(" IfName : %d: %s\n", m_nIfIndex, m_aIfName); - printf(" Inet : " IPSTR "/%d\n", IP2STR(m_nLocalIp), GetNetmaskCIDR()); - printf(" Netmask : " IPSTR "\n", IP2STR(m_nNetmask)); - printf(" Gateway : " IPSTR "\n", IP2STR(m_nGatewayIp)); + printf(" IfName : %d: %s " MACSTR "\n", m_nIfIndex, m_aIfName, MAC2STR(m_aNetMacaddr)); + printf(" Primary : " IPSTR "/%d (HTTP only " IPSTR ")\n", IP2STR(m_IpInfo.ip.addr), GetNetmaskCIDR(), IP2STR(m_IpInfo.secondary_ip.addr)); + printf(" Gateway : " IPSTR "\n", IP2STR(m_IpInfo.gw.addr)); printf(" Broadcast : " IPSTR "\n", IP2STR(GetBroadcastIp())); - printf(" Mac : " MACSTR "\n", MAC2STR(m_aNetMacaddr)); - printf(" Mode : %c\n", GetAddressingMode()); } diff --git a/lib-network/src/emac/phy/dp83848/net_link_check.cpp b/lib-network/src/emac/phy/dp83848/net_link_check.cpp new file mode 100755 index 0000000..076445b --- /dev/null +++ b/lib-network/src/emac/phy/dp83848/net_link_check.cpp @@ -0,0 +1,65 @@ +/** + * net_link_check.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "emac/net_link_check.h" +#include "emac/phy.h" +#include "emac/mmi.h" + +#include "debug.h" + +#define PHY_REG_MICR 0x11U +#define PHY_REG_MISR 0x12U +#define PHY_INT_AND_OUTPUT_ENABLE 0x03U +#define PHY_LINK_INT_ENABLE 0x20U + +#if !defined (PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif + +namespace net { +#if defined (ENET_LINK_CHECK_USE_INT) || defined (ENET_LINK_CHECK_USE_PIN_POLL) +void link_pin_enable() { + uint16_t phy_value = PHY_INT_AND_OUTPUT_ENABLE; + phy_write(PHY_ADDRESS, PHY_REG_MICR, phy_value); + + phy_read(PHY_ADDRESS, PHY_REG_MICR, phy_value); + + if (PHY_INT_AND_OUTPUT_ENABLE != phy_value) { + DEBUG_PUTS("PHY_INT_AND_OUTPUT_ENABLE != phy_value"); + } + + phy_value = PHY_LINK_INT_ENABLE; + phy_write(PHY_ADDRESS, PHY_REG_MISR, phy_value); +} + +void link_pin_recovery() { + uint16_t phy_value; + phy_read(PHY_ADDRESS, PHY_REG_MISR, phy_value); + phy_read(PHY_ADDRESS, mmi::REG_BMSR, phy_value); +} +#endif +} // namespace net diff --git a/lib-network/src/emac/phy/dp83848/net_phy.cpp b/lib-network/src/emac/phy/dp83848/net_phy.cpp new file mode 100755 index 0000000..028cf2c --- /dev/null +++ b/lib-network/src/emac/phy/dp83848/net_phy.cpp @@ -0,0 +1,69 @@ +/** + * net_phy.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "emac/phy.h" +#include "emac/net_link_check.h" +#include "emac/mmi.h" + +#include "debug.h" + +#if !defined (BIT) +# define BIT(x) static_cast(1U<<(x)) +#endif + +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif + +namespace net { +void phy_customized_led() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void phy_customized_timing() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +/** + * PHY Status Register (PHYSTS), address 10h + * @param phyStatus + */ +void phy_customized_status(PhyStatus& phyStatus) { + uint16_t nValue; + phy_read(PHY_ADDRESS, 0x10, nValue); + + phyStatus.link = ((nValue & BIT(0)) == BIT(0)) ? Link::STATE_UP : Link::STATE_DOWN; + phyStatus.duplex = ((nValue & BIT(2)) == BIT(2)) ? Duplex::DUPLEX_FULL : Duplex::DUPLEX_HALF; + phyStatus.speed = ((nValue & BIT(1)) == BIT(1)) ? Speed::SPEED10 : Speed::SPEED100; + phyStatus.bAutonegotiation = ((nValue & BIT(4)) == BIT(4)); + +} +} // namespace net diff --git a/lib-network/src/emac/phy/json_get_phystatus.cpp b/lib-network/src/emac/phy/json_get_phystatus.cpp new file mode 100755 index 0000000..73fa4ee --- /dev/null +++ b/lib-network/src/emac/phy/json_get_phystatus.cpp @@ -0,0 +1,45 @@ +/** + * json_get_phystatus.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "emac/phy.h" + +namespace remoteconfig { +namespace net { +uint16_t json_get_phystatus(char *pOutBuffer, const uint16_t nOutBufferSize) { + ::net::PhyStatus phyStatus; + ::net::phy_customized_status(phyStatus); + + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"link\":\"%s\",\"speed\":\"%s\",\"duplex\":\"%s\",\"autonegotiation\":\"%s\"}", + ::net::phy_string_get_link(phyStatus.link), + ::net::phy_string_get_speed(phyStatus.speed), + ::net::phy_string_get_duplex(phyStatus.duplex), + ::net::phy_string_get_autonegotiation(phyStatus.bAutonegotiation))); + return nLength; +} +} // namespace net +} // namespace remoteconfig diff --git a/lib-network/src/emac/phy/lan8700/net_phy.cpp b/lib-network/src/emac/phy/lan8700/net_phy.cpp new file mode 100755 index 0000000..67c45e1 --- /dev/null +++ b/lib-network/src/emac/phy/lan8700/net_phy.cpp @@ -0,0 +1,70 @@ +/** + * net_phy.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "emac/phy.h" +#include "emac/net_link_check.h" +#include "emac/mmi.h" + +#include "debug.h" + +#if !defined (BIT) +# define BIT(x) static_cast(1U<<(x)) +#endif + +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif + +namespace net { +void phy_customized_led() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void phy_customized_timing() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +/** + * PHY SPECIAL CONTROL/STATUS REGISTER Index (In Decimal): 31 + * @param phyStatus + */ +void phy_customized_status(PhyStatus& phyStatus) { + phyStatus.link = link_status_read(); + + uint16_t nValue; + phy_read(PHY_ADDRESS, 0x1f, nValue); + + phyStatus.duplex = ((nValue & BIT(4)) == BIT(4)) ? Duplex::DUPLEX_FULL : Duplex::DUPLEX_HALF; + phyStatus.speed = ((nValue & BIT(2)) == BIT(2)) ? Speed::SPEED10 : Speed::SPEED100; + phyStatus.bAutonegotiation = ((nValue & BIT(12)) == BIT(12)); +} + +} // namespace net diff --git a/lib-network/src/emac/link_handle_change.cpp b/lib-network/src/emac/phy/link_handle_change.cpp similarity index 98% rename from lib-network/src/emac/link_handle_change.cpp rename to lib-network/src/emac/phy/link_handle_change.cpp index 7397c39..5b86f3a 100644 --- a/lib-network/src/emac/link_handle_change.cpp +++ b/lib-network/src/emac/phy/link_handle_change.cpp @@ -37,6 +37,7 @@ void __attribute__((weak)) link_handle_change(const net::Link state) { if (net::Link::STATE_UP == state) { if (Network::Get()->IsDhcpUsed()) { + DEBUG_PUTS("Enable DHCP"); Network::Get()->EnableDhcp(); } } diff --git a/include/stdbool.h b/lib-network/src/emac/phy/net_link_check.cpp similarity index 58% rename from include/stdbool.h rename to lib-network/src/emac/phy/net_link_check.cpp index a37b8bc..c266780 100644 --- a/include/stdbool.h +++ b/lib-network/src/emac/phy/net_link_check.cpp @@ -1,8 +1,8 @@ /** - * @file stdbool.h + * net_link_check.cpp * */ -/* Copyright (C) 2017 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,22 +23,38 @@ * THE SOFTWARE. */ -#ifndef STDBOOL_H_ -#define STDBOOL_H_ - -/* Don't define bool, true, and false in C++, except as a GNU extension. */ -#ifndef __cplusplus - #define bool _Bool - #define true 1 - #define false 0 -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) - /* Define _Bool, bool, false, true as a GNU extension. */ - #define _Bool bool - #define bool bool - #define false false - #define true true +#include "emac/net_link_check.h" +#include "emac/phy.h" +#include "emac/mmi.h" + +#define PHY_ADDRESS 1 + +namespace net { +#if defined (ENET_LINK_CHECK_USE_INT) +void link_interrupt_init() { + link_pin_enable(); + link_pin_recovery(); + link_gpio_init(); + link_exti_init(); +} #endif -#define __bool_true_false_are_defined 1 +#if defined (ENET_LINK_CHECK_USE_PIN_POLL) +void link_pin_poll_init() { + link_pin_enable(); + link_pin_recovery(); + link_gpio_init(); +} +#endif + +net::Link link_status_read() { + uint16_t nValue = 0; + phy_read(PHY_ADDRESS, mmi::REG_BMSR, nValue); + + if (mmi::BMSR_LINKED_STATUS == (nValue & mmi::BMSR_LINKED_STATUS)) { + return net::Link::STATE_UP; + } -#endif /* STDBOOL_H_ */ + return net::Link::STATE_DOWN; +} +} // namespace net diff --git a/lib-network/src/emac/phy/net_phy.cpp b/lib-network/src/emac/phy/net_phy.cpp new file mode 100755 index 0000000..61be500 --- /dev/null +++ b/lib-network/src/emac/phy/net_phy.cpp @@ -0,0 +1,268 @@ +/** + * net_phy.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "emac/phy.h" +#include "emac/mmi.h" + +#include "hardware.h" +#include "debug.h" + +namespace net { + +static PhyStatus s_phyStatus; + +bool phy_get_id(const uint32_t nAddress, PhyIdentifier& phyIdentifier) { + DEBUG_ENTRY + DEBUG_PRINTF("nAddress=%.2x", nAddress); + + uint16_t nValue; + + if (!phy_read(nAddress, mmi::REG_PHYSID1, nValue)) { + DEBUG_EXIT + return false; + } + + phyIdentifier.nOui =(static_cast(nValue) << 14); + + if (!phy_read(nAddress, mmi::REG_PHYSID2, nValue)) { + DEBUG_EXIT + return false; + } + + phyIdentifier.nOui |= (((nValue & 0xfc00) >> 10)); + phyIdentifier.nVendorModel = ((nValue & 0x03f0) >> 4) ; + phyIdentifier.nModelRevision = nValue & 0x000f; + + DEBUG_PRINTF("%.8x %.4x %.4x", phyIdentifier.nOui, phyIdentifier.nVendorModel, phyIdentifier.nModelRevision); + DEBUG_EXIT + return true; +} + +bool phy_powerdown(const uint32_t nAddress) { + return phy_write(nAddress, mmi::REG_BMCR, mmi::BMCR_POWERDOWN); +} + +static int32_t phy_config_advertise(const uint32_t nAddress, const uint16_t nAdvertisement) { + DEBUG_ENTRY + + uint16_t nAdvertise; + phy_read(nAddress, mmi::REG_ADVERTISE, nAdvertise); + +#ifndef NDEBUG + debug_print_bits(nAdvertise); +#endif + + nAdvertise &= static_cast(mmi::ADVERTISE_ALL | mmi::ADVERTISE_100BASE4 | mmi::ADVERTISE_PAUSE_CAP | mmi::ADVERTISE_PAUSE_ASYM); + nAdvertise |= nAdvertisement; + +#ifndef NDEBUG + debug_print_bits(nAdvertise); + debug_print_bits(nAdvertisement); +#endif + + if (nAdvertise != nAdvertisement) { + if (!phy_write(nAddress, mmi::REG_ADVERTISE, nAdvertisement)) { + DEBUG_EXIT + /* error */ + return -1; + } + /* Changed */ + return 1; + } + + DEBUG_EXIT + /* No change */ + return 0; +} + +static bool phy_restart_autonegotiation(const uint32_t nAddress) { + uint16_t nValue; + auto nResult = phy_read(nAddress, mmi::REG_BMCR, nValue); + + nValue |= (mmi::BMCR_AUTONEGOTIATION | mmi::BMCR_RESTART_AUTONEGOTIATION); + /* Don't isolate the PHY if we're negotiating */ + nValue &= static_cast(~(mmi::BMCR_ISOLATE)); + + nResult = phy_write(nAddress, mmi::REG_BMCR, nValue); + return nResult; +} + +static bool phy_config_autonegotiation(const uint32_t nAddress, const uint16_t nAdvertisement) { + DEBUG_ENTRY + + auto nResult = phy_config_advertise(nAddress, nAdvertisement); + + if (nResult < 0) { + DEBUG_EXIT + return false; + } + + if (nResult == 0) { + /* + * Advertisement hasn't changed, but maybe aneg was never on to + * begin with? Or maybe phy was isolated? + */ + + uint16_t nCR; + + if (!phy_read(nAddress, mmi::REG_BMCR, nCR)) { + DEBUG_EXIT + return false; + } + + if (!(nCR & mmi::BMCR_AUTONEGOTIATION) || (nCR & mmi::BMCR_ISOLATE)) { + nResult = 1; /* do restart aneg */ + } + } + + /* + * Only restart autonegotiation if we are advertising something different + * than we were before. + */ + + if (nResult > 0) { + const auto bResult = phy_restart_autonegotiation(nAddress); + DEBUG_EXIT + return bResult; + } + + + DEBUG_EXIT + return true; +} + +/** + * Update the value in \ref s_phyStatus to reflect the current link value. + * + * @param nAddress PHY address + * @return true for success, false for failure + */ +static bool phy_update_link(const uint32_t nAddress) { + DEBUG_ENTRY + + uint16_t nBMSR; + + if (!phy_read(nAddress, mmi::REG_BMSR, nBMSR)) { + DEBUG_EXIT + return false; + } + + /* + * If we already saw the link up, and it hasn't gone down, then + * we don't need to wait for autoneg again + */ + + if ((s_phyStatus.link == Link::STATE_DOWN) && (nBMSR & mmi::BMSR_LINKED_STATUS)) { + DEBUG_EXIT + return true; + } + + if (!(nBMSR & mmi::BMSR_AUTONEGO_COMPLETE)) { + puts("Waiting for PHY auto negotiation to complete"); + + const auto nMillis = Hardware::Get()->Millis(); + while (!(nBMSR & mmi::BMSR_AUTONEGO_COMPLETE)) { + if ((Hardware::Get()->Millis() - nMillis) > 5000) { + DEBUG_EXIT + return false; + } + phy_read(nAddress, mmi::REG_BMSR, nBMSR); + } + + s_phyStatus.link = Link::STATE_UP; + + DEBUG_PRINTF("%u", Hardware::Get()->Millis() - nMillis); + DEBUG_EXIT + return true; + } else { + phy_read(nAddress, mmi::REG_BMSR, nBMSR); + s_phyStatus.link = nBMSR & mmi::BMSR_LINKED_STATUS ? Link::STATE_UP : Link::STATE_DOWN; + + DEBUG_EXIT + return true; + } + + DEBUG_EXIT + assert(0); + __builtin_unreachable(); + return true; +} + +static bool phy_parse_link(const uint32_t nAddress) { + + s_phyStatus.duplex = Duplex::DUPLEX_HALF; + s_phyStatus.speed = Speed::SPEED10; + + uint16_t nADVERTISE; + phy_read(nAddress, mmi::REG_ADVERTISE, nADVERTISE); + uint16_t nLPA; + phy_read(nAddress, mmi::REG_LPA, nLPA); + + nLPA &= nADVERTISE; + + if (nLPA & (mmi::LPA_100FULL | mmi::LPA_100HALF)) { + s_phyStatus.speed = Speed::SPEED100; + + if (nLPA & mmi::LPA_100FULL) { + s_phyStatus.duplex = Duplex::DUPLEX_FULL; + } + } else if (nLPA & mmi::LPA_10FULL) { + s_phyStatus.duplex = Duplex::DUPLEX_FULL; + } + + return true; +} + +bool phy_start(const uint32_t nAddress, PhyStatus& phyStatus) { + DEBUG_ENTRY + + constexpr auto nAdvertisement = net::mmi::ADVERTISE_FULL; + + if (!phy_config_autonegotiation(nAddress, nAdvertisement)) { + DEBUG_EXIT + return false; + } + + if (!phy_update_link(nAddress)) { + DEBUG_EXIT + return false; + } + + if (!phy_parse_link(nAddress)) { + DEBUG_EXIT + return false; + } + + phyStatus = s_phyStatus; + + DEBUG_EXIT + return true; +} + +} // namespace net diff --git a/include/stdint.h b/lib-network/src/emac/phy/net_phy_string.cpp old mode 100644 new mode 100755 similarity index 57% rename from include/stdint.h rename to lib-network/src/emac/phy/net_phy_string.cpp index 590edcb..7805df2 --- a/include/stdint.h +++ b/lib-network/src/emac/phy/net_phy_string.cpp @@ -1,8 +1,8 @@ /** - * @file stdint.h + * net_phy_string.cpp * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,42 +23,35 @@ * THE SOFTWARE. */ -#ifndef STDINT_H_ -#define STDINT_H_ +#include +#include -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; +#include "emac/phy.h" -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; - -typedef int intptr_t; -typedef unsigned int uintptr_t; - -#if !defined(UINT32_MAX) - #ifdef __cplusplus - #define UINT32_MAX (static_cast(-1)) - #else - #define UINT32_MAX ((uint32_t)-1) - #endif +#if !defined (ARRAY_SIZE) +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif -#if !defined(UINT16_MAX) - #ifdef __cplusplus - #define UINT16_MAX (static_cast(-1)) - #else - #define UINT16_MAX ((uint16_t)-1) - #endif -#endif +namespace net { +static constexpr char SPEED[3][10] = { "10baseT", "100baseTX", "1000baseT" }; +const char *phy_string_get_link(const Link link) { + return link == Link::STATE_UP ? "up" : "down"; +} -#define INT16_MIN (-0x7fff - 1) +const char *phy_string_get_duplex(const Duplex duplex) { + return duplex == Duplex::DUPLEX_HALF ? "half" : "full"; +} -#define INT16_MAX 0x7fff +const char *phy_string_get_speed(const Speed speed) { + const auto nIndex = static_cast(speed); -#endif + assert(nIndex < ARRAY_SIZE(SPEED)); + return SPEED[nIndex]; +} + +const char *phy_string_get_autonegotiation(const bool autonegotiation) { + return autonegotiation ? "on" : "off"; +} +} diff --git a/include/cstdint b/lib-network/src/emac/phy/phygen/net_phy.cpp old mode 100644 new mode 100755 similarity index 53% rename from include/cstdint rename to lib-network/src/emac/phy/phygen/net_phy.cpp index 947e959..07b68f2 --- a/include/cstdint +++ b/lib-network/src/emac/phy/phygen/net_phy.cpp @@ -1,8 +1,8 @@ /** - * @file cstdint + * net_phy.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,46 @@ * THE SOFTWARE. */ -#ifndef CSTDINT_ -#define CSTDINT_ +#include -#ifdef __cplusplus -# include +#include "emac/phy.h" +#include "emac/net_link_check.h" +#include "emac/mmi.h" + +#include "debug.h" + +#if !defined (BIT) +# define BIT(x) static_cast(1U<<(x)) +#endif + +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 #endif -#endif /* CSTDINT_ */ +namespace net { +void phy_customized_led() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void phy_customized_timing() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void phy_customized_status(PhyStatus& phyStatus) { + phyStatus.link = link_status_read(); + + uint16_t nValue; + phy_read(PHY_ADDRESS, mmi::REG_BMCR, nValue); + + debug_print_bits(nValue); + + phyStatus.duplex = ((nValue & BIT(8)) == BIT(8)) ? Duplex::DUPLEX_FULL : Duplex::DUPLEX_HALF; + phyStatus.speed = ((nValue & BIT(13)) == BIT(13)) ? Speed::SPEED100 : Speed::SPEED10; + phyStatus.bAutonegotiation = ((nValue & mmi::BMCR_AUTONEGOTIATION) == mmi::BMCR_AUTONEGOTIATION); + +} +} // namespace net diff --git a/lib-debug/src/debug_exception.c b/lib-network/src/emac/phy/rtl8201f/net_link_check.cpp similarity index 54% rename from lib-debug/src/debug_exception.c rename to lib-network/src/emac/phy/rtl8201f/net_link_check.cpp index 6bbcd0f..0da2be9 100755 --- a/lib-debug/src/debug_exception.c +++ b/lib-network/src/emac/phy/rtl8201f/net_link_check.cpp @@ -1,9 +1,8 @@ -#if defined(BARE_METAL) /** - * @file debug_exception.c + * net_link_check.cpp * */ -/* Copyright (C) 2018 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,41 +23,37 @@ * THE SOFTWARE. */ -#include +#include -#include "console.h" +#include "emac/net_link_check.h" +#include "emac/phy.h" +#include "emac/mmi.h" -#if defined (H3) - void h3_watchdog_disable(void); -#else - void bcm2835_watchdog_stop(void); +#if !defined (PHY_ADDRESS) +# define PHY_ADDRESS 1 #endif -void debug_exception(unsigned int type, unsigned int address) { - __sync_synchronize(); +#define PHY_REG_IER 0x13 + #define IER_INT_ENABLE (1U << 13) - console_set_fg_color(CONSOLE_RED); +#define PHY_REG_ISR 0x1e + #define ISR_LINK (1U << 11) - if (type == 0) { - printf("\nUndefined exception at address: %p\n",address); - } else if (type == 1) { - printf("\nPrefetch abort at address: %p\n",address); - } else if (type == 2) { - printf("\nData abort at address: %p\n", address); - } else { - printf("\nUnknown exception! [%d]\n", type); - } +namespace net { +#if defined (ENET_LINK_CHECK_USE_INT) || defined (ENET_LINK_CHECK_USE_PIN_POLL) +void phy_write_paged(uint16_t phy_page, uint16_t phy_reg, uint16_t phy_value, uint16_t mask = 0x0); - console_set_fg_color(CONSOLE_WHITE); - -#if defined (H3) - h3_watchdog_disable(); -#else - bcm2835_watchdog_stop(); -#endif +void link_pin_enable() { + phy_write_paged(0x07, PHY_REG_IER, IER_INT_ENABLE, IER_INT_ENABLE); + // Clear interrupt + uint16_t phy_value; + phy_read(PHY_ADDRESS, PHY_REG_ISR, phy_value); +} - for(;;); +void link_pin_recovery() { + uint16_t phy_value; + phy_read(PHY_ADDRESS, PHY_REG_ISR, phy_value); + phy_read(PHY_ADDRESS, mmi::REG_BMSR, phy_value); } -#else - typedef int ISO_C_forbids_an_empty_translation_unit; #endif +} // namespace net diff --git a/lib-network/src/emac/gd32/rtl8201f/rtl8201f.cpp b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp old mode 100644 new mode 100755 similarity index 63% rename from lib-network/src/emac/gd32/rtl8201f/rtl8201f.cpp rename to lib-network/src/emac/phy/rtl8201f/net_phy.cpp index 782ead3..f8c5433 --- a/lib-network/src/emac/gd32/rtl8201f/rtl8201f.cpp +++ b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp @@ -1,5 +1,5 @@ /** - * rtl8201f.cpp + * phy.cpp * */ /* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org @@ -25,37 +25,51 @@ #include -#include "gd32.h" -#include "./../enet_config.h" +#include "emac/phy.h" +#include "emac/net_link_check.h" +#include "emac/mmi.h" #include "debug.h" +#if !defined (BIT) +# define BIT(x) static_cast(1U<<(x)) +#endif + +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif + +#define PHY_REG_RMSR 0x10 +#define PHY_REG_PAGE_SELECT 0x1f +#define PHY_REG_IER 0x13 + #define IER_CUSTOM_LED (1U << 3) + namespace net { void phy_write_paged(uint16_t phy_page, uint16_t phy_reg, uint16_t phy_value, uint16_t mask = 0x0) { - enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_PAGE_SELECT, &phy_page); + phy_write(PHY_ADDRESS, PHY_REG_PAGE_SELECT, phy_page); uint16_t tmp_value; - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, phy_reg, &tmp_value); + phy_read(PHY_ADDRESS, phy_reg, tmp_value); DEBUG_PRINTF("tmp_value=0x%.4x, mask=0x%.4x", tmp_value, mask); - tmp_value &= ~mask; + tmp_value &= static_cast(~mask); tmp_value |= phy_value; DEBUG_PRINTF("tmp_value=0x%.4x, phy_value=0x%.4x", tmp_value, phy_value); - enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, phy_reg, &tmp_value); + phy_write(PHY_ADDRESS, phy_reg, tmp_value); phy_page = 0; - enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_PAGE_SELECT, &phy_page); + phy_write(PHY_ADDRESS, PHY_REG_PAGE_SELECT, phy_page); } void phy_customized_led() { DEBUG_ENTRY #if defined (RTL8201F_LED1_LINK_ALL) || defined (RTL8201F_LED1_LINK_ALL_ACT) - phy_write_paged(0x07, PHY_REG_IER, PHY_REG_IER_CUSTOM_LED, PHY_REG_IER_CUSTOM_LED); + phy_write_paged(0x07, PHY_REG_IER, IER_CUSTOM_LED, IER_CUSTOM_LED); # if defined (RTL8201F_LED1_LINK_ALL) - phy_write_paged(0x07, 0x11, BIT(3) | BIT(4) | BIT(5)); + phy_write_paged(0x07, 0x11, (1U << 3) | (1U << 4) | (1U << 5)); # else - phy_write_paged(0x07, 0x11, BIT(3) | BIT(4) | BIT(5) | BIT(7)); + phy_write_paged(0x07, 0x11, (1U << 3) | (1U << 4) | (1U << 5) | (1U << 7)); # endif #endif DEBUG_EXIT @@ -63,7 +77,7 @@ void phy_customized_led() { void phy_customized_timing() { DEBUG_ENTRY -#if defined (GD32F4XX) +#if defined (GD32F407) || defined (GD32F450) # define RMSR_RX_TIMING_SHIFT 4 # define RMSR_RX_TIMING_MASK 0xF0 # define RMSR_RX_TIMING_VAL 0x4 @@ -77,4 +91,16 @@ void phy_customized_timing() { #endif DEBUG_EXIT } + +void phy_customized_status(PhyStatus& phyStatus) { + phyStatus.link = link_status_read(); + + uint16_t nValue; + phy_read(PHY_ADDRESS, mmi::REG_BMCR, nValue); + + phyStatus.duplex = ((nValue & BIT(8)) == BIT(8)) ? Duplex::DUPLEX_FULL : Duplex::DUPLEX_HALF; + phyStatus.speed = ((nValue & BIT(13)) == BIT(13)) ? Speed::SPEED100 : Speed::SPEED10; + phyStatus.bAutonegotiation = ((nValue & mmi::BMCR_AUTONEGOTIATION) == mmi::BMCR_AUTONEGOTIATION); + +} } // namespace net diff --git a/lib-network/src/net/arp.cpp b/lib-network/src/net/arp.cpp index 72b5626..1cb8e09 100644 --- a/lib-network/src/net/arp.cpp +++ b/lib-network/src/net/arp.cpp @@ -29,142 +29,203 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" #include "../../config/net_config.h" -static struct t_arp s_arp_announce ALIGNED; +namespace net { +namespace arp { +enum class RequestType { + REQUEST, + PROBE, + ANNNOUNCEMENT +}; +} // namespace arp +} // namespace net + static struct t_arp s_arp_request ALIGNED ; static struct t_arp s_arp_reply ALIGNED; +static net::arp::RequestType s_requestType ALIGNED; +static bool s_isProbeReplyReceived ALIGNED; -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net typedef union pcast32 { uint32_t u32; uint8_t u8[4]; } _pcast32; -void arp_announce() { - DEBUG_ENTRY +void __attribute__((cold)) arp_init() { + arp_cache_init(); - if (s_arp_announce.arp.sender_ip == 0) { - DEBUG_EXIT - return; - } + s_requestType = net::arp::RequestType::REQUEST; - debug_dump(&s_arp_announce, sizeof(struct t_arp)); + // ARP Request template + // Ethernet header + memcpy(s_arp_request.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); + s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); - emac_eth_send(reinterpret_cast(&s_arp_announce), sizeof(struct t_arp)); + // ARP Header + s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); - DEBUG_EXIT -} + memcpy(s_arp_request.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); + _pcast32 ip_addr; + ip_addr.u32 = net::globals::ipInfo.ip.addr; + memcpy(s_arp_request.arp.sender_ip, ip_addr.u8, IPv4_ADDR_LEN); + memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); -void arp_handle_request(struct t_arp *p_arp) { - DEBUG_ENTRY + // ARP Reply Template + // Ethernet header + memcpy(s_arp_reply.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); - _pcast32 target; + // ARP Header + s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); - const auto *p = reinterpret_cast(&p_arp->arp.target_ip); + memcpy(s_arp_reply.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); +} - memcpy(target.u8, p, IPv4_ADDR_LEN); +bool arp_do_probe() { + int32_t nTimeout; + auto nRetries = 3; - DEBUG_PRINTF("Sender " IPSTR " Target " IPSTR, IP2STR(p_arp->arp.sender_ip), IP2STR(target.u32)); + while (nRetries--) { + arp_send_probe(); - if (target.u32 != s_arp_announce.arp.sender_ip) { - DEBUG_EXIT - return; + nTimeout = 0x1FFFF; +#ifndef NDEBUG + nTimeout+= 0x40000; +#endif + + while ((nTimeout-- > 0) && !s_isProbeReplyReceived) { + net_handle(); + } + + if (s_isProbeReplyReceived) { + return true; + } } - // Ethernet header - memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); + return false; +} - // ARP Header - memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); - s_arp_reply.arp.target_ip = p_arp->arp.sender_ip; +void arp_send_request(uint32_t nIp) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(nIp)); - emac_eth_send(reinterpret_cast(&s_arp_reply), sizeof(struct t_arp)); + s_requestType = net::arp::RequestType::REQUEST; + + _pcast32 ip_addr; + ip_addr.u32 = nIp; + + memcpy(s_arp_request.arp.target_ip, ip_addr.u8, IPv4_ADDR_LEN); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); DEBUG_EXIT } -void arp_handle_reply(struct t_arp *p_arp) { +/* + * The Sender IP is set to all zeros, + * which means it cannot map to the Sender MAC address. + * The Target MAC address is all zeros, + * which means it cannot map to the Target IP address. + */ +void arp_send_probe() { DEBUG_ENTRY - arp_cache_update(p_arp->arp.sender_mac, p_arp->arp.sender_ip); + s_requestType = net::arp::RequestType::PROBE; + s_isProbeReplyReceived = false; + + memset(s_arp_request.arp.sender_ip, 0, IPv4_ADDR_LEN); + + arp_send_request(net::globals::ipInfo.ip.addr); + + _pcast32 ip_addr; + ip_addr.u32 = net::globals::ipInfo.ip.addr; + memcpy(s_arp_request.arp.sender_ip, ip_addr.u8, IPv4_ADDR_LEN); DEBUG_EXIT } -void __attribute__((cold)) arp_init() { - arp_cache_init(); +/* + * The packet structure is identical to the ARP Probe above, + * with the exception that a complete mapping exists. + * Both the Sender MAC address and the Sender IP address create a complete ARP mapping, + * and hosts on the network can use this pair of addresses in their ARP table. + */ +void arp_send_announcement() { + DEBUG_ENTRY - const auto nLocalIp = g_ip_info.ip.addr; + s_requestType = net::arp::RequestType::ANNNOUNCEMENT; - // ARP Announce - // Ethernet header - memcpy(s_arp_announce.ether.src, g_mac_address, ETH_ADDR_LEN); - memset(s_arp_announce.ether.dst, 0xFF , ETH_ADDR_LEN); - s_arp_announce.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + arp_send_request(net::globals::ipInfo.ip.addr); - // ARP Header - s_arp_announce.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_announce.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_announce.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_announce.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_announce.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); + DEBUG_EXIT +} - memcpy(s_arp_announce.arp.sender_mac, g_mac_address, ETH_ADDR_LEN); - s_arp_announce.arp.sender_ip = nLocalIp; - memset(s_arp_announce.arp.target_mac, 0x00, ETH_ADDR_LEN); - s_arp_announce.arp.target_ip = nLocalIp; +void arp_handle_request(struct t_arp *p_arp) { + DEBUG_ENTRY + _pcast32 target; - // ARP Request template - // Ethernet header - memcpy(s_arp_request.ether.src, g_mac_address, ETH_ADDR_LEN); - memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); - s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + memcpy(target.u8, p_arp->arp.target_ip, IPv4_ADDR_LEN); - // ARP Header - s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); + _pcast32 sender; - memcpy(s_arp_request.arp.sender_mac, g_mac_address, ETH_ADDR_LEN); - s_arp_request.arp.sender_ip = nLocalIp; - memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); + memcpy(sender.u8, p_arp->arp.sender_ip, IPv4_ADDR_LEN); - // ARP Reply Template - // Ethernet header - memcpy(s_arp_reply.ether.src, g_mac_address, ETH_ADDR_LEN); - s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + DEBUG_PRINTF("Sender " IPSTR " Target " IPSTR, IP2STR(sender.u32), IP2STR(target.u32)); + if (!((target.u32 == net::globals::ipInfo.ip.addr) || (target.u32 == net::globals::ipInfo.secondary_ip.addr) || (target.u32 == net::globals::ipInfo.broadcast_ip.addr))) { + DEBUG_PUTS("No for me."); + DEBUG_EXIT + return; + } + + // Ethernet header + memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); // ARP Header - s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); + memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); + memcpy(s_arp_reply.arp.target_ip, p_arp->arp.sender_ip, IPv4_ADDR_LEN); + memcpy(s_arp_reply.arp.sender_ip, target.u8, IPv4_ADDR_LEN); - memcpy(s_arp_reply.arp.sender_mac, g_mac_address, ETH_ADDR_LEN); - s_arp_reply.arp.sender_ip = nLocalIp; + emac_eth_send(reinterpret_cast(&s_arp_reply), sizeof(struct t_arp)); - arp_announce(); + DEBUG_EXIT } -void arp_send_request(uint32_t nIp) { +void arp_handle_reply(struct t_arp *p_arp) { DEBUG_ENTRY - // ARP Header - s_arp_request.arp.target_ip = nIp; - - DEBUG_PRINTF(IPSTR, IP2STR(nIp)); - - emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + switch (s_requestType) { + case net::arp::RequestType::REQUEST: { + _pcast32 sender; + memcpy(sender.u8, p_arp->arp.sender_ip, IPv4_ADDR_LEN); + arp_cache_update(p_arp->arp.sender_mac, sender.u32); + } + break; + case net::arp::RequestType::PROBE: + s_isProbeReplyReceived = true; + break; + default: + assert(0); + __builtin_unreachable(); + break; + } DEBUG_EXIT } diff --git a/lib-network/src/net/arp_cache.cpp b/lib-network/src/net/arp_cache.cpp index 8c2019a..97f2795 100644 --- a/lib-network/src/net/arp_cache.cpp +++ b/lib-network/src/net/arp_cache.cpp @@ -32,22 +32,28 @@ #include "net_platform.h" #include "net_debug.h" +#include "emac/net_link_check.h" + #include "../../config/net_config.h" -#define MAX_RECORDS 32 +#if !defined ARP_MAX_RECORDS +static constexpr auto MAX_RECORDS = 32; +#else +static constexpr auto MAX_RECORDS = ARP_MAX_RECORDS; +#endif -struct t_arp_record { - uint32_t ip; +struct ArpRecord { + uint32_t nIp; uint8_t mac_address[ETH_ADDR_LEN]; -} ALIGNED; +}; typedef union pcast32 { uint32_t u32; uint8_t u8[4]; } _pcast32; -static struct t_arp_record s_arp_records[MAX_RECORDS] SECTION_NETWORK ALIGNED; -static uint16_t s_entry_current SECTION_NETWORK ALIGNED; +static ArpRecord s_ArpRecords[MAX_RECORDS] SECTION_NETWORK ALIGNED; +static uint16_t s_Entries SECTION_NETWORK ALIGNED; #ifndef NDEBUG # define TICKER_COUNT 100 ///< 10 seconds @@ -55,11 +61,10 @@ static uint16_t s_entry_current SECTION_NETWORK ALIGNED; #endif void __attribute__((cold)) arp_cache_init() { - s_entry_current = 0; + s_Entries = 0; - for (auto i = 0; i < MAX_RECORDS; i++) { - s_arp_records[i].ip = 0; - memset(s_arp_records[i].mac_address, 0, ETH_ADDR_LEN); + for (auto& record : s_ArpRecords) { + memset(&record, 0, sizeof(struct ArpRecord)); } #ifndef NDEBUG @@ -69,22 +74,24 @@ void __attribute__((cold)) arp_cache_init() { void arp_cache_update(const uint8_t *pMacAddress, uint32_t nIp) { DEBUG_ENTRY + DEBUG_PRINTF(MACSTR " " IPSTR, MAC2STR(pMacAddress), IP2STR(nIp)); - if (s_entry_current == MAX_RECORDS) { - console_error("arp_cache_update\n"); + if (s_Entries == MAX_RECORDS) { + console_error("ARP cache is full\n"); return; } - for (auto i = 0; i < s_entry_current; i++) { - if (s_arp_records[i].ip == nIp) { + for (auto i = 0; i < s_Entries; i++) { + if (s_ArpRecords[i].nIp == nIp) { + DEBUG_EXIT return; } } - memcpy(s_arp_records[s_entry_current].mac_address, pMacAddress, ETH_ADDR_LEN); - s_arp_records[s_entry_current].ip = nIp; + memcpy(s_ArpRecords[s_Entries].mac_address, pMacAddress, ETH_ADDR_LEN); + s_ArpRecords[s_Entries].nIp = nIp; - s_entry_current++; + s_Entries++; DEBUG_EXIT } @@ -93,37 +100,49 @@ uint32_t arp_cache_lookup(uint32_t nIp, uint8_t *pMacAddress) { DEBUG_ENTRY DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nIp), MAC2STR(pMacAddress)); - for (auto i = 0; i < MAX_RECORDS; i++) { - if (s_arp_records[i].ip == nIp) { - memcpy(pMacAddress, s_arp_records[i].mac_address, ETH_ADDR_LEN); + uint32_t i; + + for (i = 0; i < MAX_RECORDS; i++) { + if (s_ArpRecords[i].nIp == nIp) { + memcpy(pMacAddress, s_ArpRecords[i].mac_address, ETH_ADDR_LEN); + DEBUG_EXIT return nIp; } - if (s_arp_records[i].ip == 0) { + if (s_ArpRecords[i].nIp == 0) { break; } } - const auto current_entry = s_entry_current; - int32_t timeout; - auto retries = 3; + if (net::link_status_read() == net::Link::STATE_DOWN) { + DEBUG_EXIT + return 0; + } + + const auto nEntries = s_Entries; + int32_t nTimeout; + auto nRetries = 3; - while (retries--) { + while (nRetries--) { arp_send_request(nIp); - timeout = 0x1FFFF; + nTimeout = 0x1FFFF; +#ifndef NDEBUG + nTimeout+= 0x40000; +#endif - while ((timeout-- > 0) && (current_entry == s_entry_current)) { + while ((nTimeout-- > 0) && (nEntries == s_Entries)) { net_handle(); } - if (current_entry != s_entry_current) { - memcpy(pMacAddress, s_arp_records[current_entry].mac_address, ETH_ADDR_LEN); - DEBUG_PRINTF("timeout=%x", timeout); + if (nEntries != s_Entries) { + memcpy(pMacAddress, s_ArpRecords[nEntries].mac_address, ETH_ADDR_LEN); + DEBUG_PRINTF("timeout=%x", nTimeout); + DEBUG_EXIT return nIp; } - DEBUG_PRINTF("i=%d, timeout=%d, current_entry=%d, s_entry_current=%d", i, timeout, current_entry, s_entry_current); + DEBUG_PRINTF("timeout=%d, current_entry=%d, s_entry_current=%d", nTimeout, nEntries, s_Entries); } DEBUG_EXIT @@ -132,10 +151,10 @@ uint32_t arp_cache_lookup(uint32_t nIp, uint8_t *pMacAddress) { void arp_cache_dump() { #ifndef NDEBUG - printf("ARP Cache size=%d\n", s_entry_current); + printf("ARP Cache size=%d\n", s_Entries); - for (auto i = 0; i < s_entry_current; i++) { - printf("%02d " IPSTR " " MACSTR "\n", i, IP2STR(s_arp_records[i].ip),MAC2STR(s_arp_records[i].mac_address)); + for (auto i = 0; i < s_Entries; i++) { + printf("%02d " IPSTR " " MACSTR "\n", i, IP2STR(s_ArpRecords[i].nIp),MAC2STR(s_ArpRecords[i].mac_address)); } #endif } @@ -150,4 +169,3 @@ void arp_cache_timer(void) { } } #endif - diff --git a/lib-network/src/net/dhcp.cpp b/lib-network/src/net/dhcp.cpp index b026337..a160ece 100644 --- a/lib-network/src/net/dhcp.cpp +++ b/lib-network/src/net/dhcp.cpp @@ -31,15 +31,17 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" #include "hardware.h" #include "../../config/net_config.h" -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net typedef union pcast32 { uint32_t u32; @@ -48,7 +50,8 @@ typedef union pcast32 { // https://tools.ietf.org/html/rfc1541 -struct t_dhcp_message { +namespace dhcp { +struct Message { uint8_t op; uint8_t htype; uint8_t hlen; @@ -65,6 +68,7 @@ struct t_dhcp_message { uint8_t file[128]; uint8_t options[DHCP_OPT_SIZE]; }PACKED; +} // namespace dhcp enum OPTIONS { OPTIONS_PAD_OPTION = 0, @@ -83,17 +87,17 @@ enum OPTIONS { OPTIONS_END_OPTION = 255 }; -static struct t_dhcp_message s_dhcp_message ALIGNED; +static dhcp::Message s_dhcp_message ALIGNED; static uint8_t s_dhcp_server_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; static uint8_t s_dhcp_allocated_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; static uint8_t s_dhcp_allocated_gw[IPv4_ADDR_LEN] ALIGNED = { 0, }; static uint8_t s_dhcp_allocated_netmask[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static void _message_init(const uint8_t *pMacAddress) { +static void message_init(const uint8_t *pMacAddress) { auto *p = reinterpret_cast(&s_dhcp_message); - for (uint32_t i = 0; i < sizeof(struct t_dhcp_message); i++) { + for (uint32_t i = 0; i < sizeof(dhcp::Message); i++) { *p++ = 0; } @@ -111,7 +115,7 @@ static void _message_init(const uint8_t *pMacAddress) { s_dhcp_message.options[5] = 0x01; } -static void _send_discover(int nHandle, const uint8_t *pMacAddress) { +static void send_discover(int nHandle, const uint8_t *pMacAddress) { DEBUG_ENTRY uint32_t k = 6; @@ -138,7 +142,7 @@ static void _send_discover(int nHandle, const uint8_t *pMacAddress) { s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; s_dhcp_message.options[k++] = OPTIONS_END_OPTION; - udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(struct t_dhcp_message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); DEBUG_EXIT } @@ -192,13 +196,13 @@ static void _send_request(int idx, const uint8_t *pMacAddress, const char *pHost s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; s_dhcp_message.options[k++] = OPTIONS_END_OPTION; - udp_send(idx, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(struct t_dhcp_message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(idx, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); DEBUG_EXIT } -static int _parse_response(int nHandle, const uint8_t *pMacAddress) { - t_dhcp_message response; +static int parse_response(int nHandle, const uint8_t *pMacAddress) { + uint8_t *pResponse; const auto nMillis = Hardware::Get()->Millis(); uint32_t nSize = 0; @@ -208,10 +212,13 @@ static int _parse_response(int nHandle, const uint8_t *pMacAddress) { uint32_t nFromIp; uint16_t nFromPort; - nSize = udp_recv1(nHandle, reinterpret_cast(&response), sizeof(struct t_dhcp_message), &nFromIp, &nFromPort); + nSize = udp_recv2(nHandle, const_cast(&pResponse), &nFromIp, &nFromPort); if ((nSize > 0) && (nFromPort == DHCP_PORT_SERVER)) { - if (memcmp(response.chaddr, pMacAddress, ETH_ADDR_LEN) == 0) { + + const auto *const pDhcpMessage = reinterpret_cast(pResponse); + + if (memcmp(pDhcpMessage->chaddr, pMacAddress, ETH_ADDR_LEN) == 0) { break; } } @@ -223,9 +230,9 @@ static int _parse_response(int nHandle, const uint8_t *pMacAddress) { uint8_t opt_len = 0; if (nSize > 0) { - auto *p = reinterpret_cast(&response); - p = p + sizeof(struct t_dhcp_message) - DHCP_OPT_SIZE + 4; - auto *e = reinterpret_cast(&response) + nSize; + auto *p = pResponse; + p = p + sizeof(dhcp::Message) - DHCP_OPT_SIZE + 4; + auto *e = pResponse + nSize; while (p < e) { switch (*p) { @@ -274,10 +281,11 @@ static int _parse_response(int nHandle, const uint8_t *pMacAddress) { } if (type == DCHP_TYPE_OFFER) { - s_dhcp_allocated_ip[0] = response.yiaddr[0]; - s_dhcp_allocated_ip[1] = response.yiaddr[1]; - s_dhcp_allocated_ip[2] = response.yiaddr[2]; - s_dhcp_allocated_ip[3] = response.yiaddr[3]; + const auto *const pDhcpMessage = reinterpret_cast(pResponse); + s_dhcp_allocated_ip[0] = pDhcpMessage->yiaddr[0]; + s_dhcp_allocated_ip[1] = pDhcpMessage->yiaddr[1]; + s_dhcp_allocated_ip[2] = pDhcpMessage->yiaddr[2]; + s_dhcp_allocated_ip[3] = pDhcpMessage->yiaddr[3]; } return type; @@ -292,7 +300,7 @@ int dhcp_client(const char *pHostname) { auto bHaveIp = false; int32_t retries = 20; - _message_init(g_mac_address); + message_init(net::globals::macAddress); auto nHandle = udp_begin(DHCP_PORT_CLIENT); @@ -300,14 +308,17 @@ int dhcp_client(const char *pHostname) { return -1; } - int type; + net::globals::ipInfo.ip.addr = 0; + ip_set_ip(); while (!bHaveIp && (retries-- > 0)) { DEBUG_PRINTF("retries=%d", retries); - _send_discover(static_cast(nHandle), g_mac_address); + send_discover(static_cast(nHandle), net::globals::macAddress); + + int type; - if ((type =_parse_response(static_cast(nHandle), g_mac_address)) < 0) { + if ((type = parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { continue; } @@ -319,9 +330,9 @@ int dhcp_client(const char *pHostname) { DEBUG_PRINTF(IPSTR, s_dhcp_server_ip[0],s_dhcp_server_ip[1],s_dhcp_server_ip[2],s_dhcp_server_ip[3]); - _send_request(static_cast(nHandle), g_mac_address, pHostname); + _send_request(static_cast(nHandle), net::globals::macAddress, pHostname); - if ((type =_parse_response(static_cast(nHandle), g_mac_address)) < 0) { + if ((type =parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { continue; } @@ -339,13 +350,13 @@ int dhcp_client(const char *pHostname) { _pcast32 ip; memcpy(ip.u8, s_dhcp_allocated_ip, IPv4_ADDR_LEN); - g_ip_info.ip.addr = ip.u32; + net::globals::ipInfo.ip.addr = ip.u32; memcpy(ip.u8, s_dhcp_allocated_gw, IPv4_ADDR_LEN); - g_ip_info.gw.addr = ip.u32; + net::globals::ipInfo.gw.addr = ip.u32; memcpy(ip.u8, s_dhcp_allocated_netmask, IPv4_ADDR_LEN); - g_ip_info.netmask.addr = ip.u32; + net::globals::ipInfo.netmask.addr = ip.u32; } DEBUG_EXIT @@ -375,7 +386,7 @@ void dhcp_client_release() { s_dhcp_message.options[k++] = OPTIONS_END_OPTION; - udp_send(static_cast(nHandle), reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(struct t_dhcp_message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(static_cast(nHandle), reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); udp_end(DHCP_PORT_CLIENT); DEBUG_EXIT diff --git a/lib-network/src/net/icmp.cpp b/lib-network/src/net/icmp.cpp index fce7be3..17afb63 100644 --- a/lib-network/src/net/icmp.cpp +++ b/lib-network/src/net/icmp.cpp @@ -28,13 +28,15 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" #include "../../config/net_config.h" -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net typedef union pcast32 { uint32_t u32; @@ -46,14 +48,14 @@ __attribute__((hot)) void icmp_handle(struct t_icmp *p_icmp) { if (p_icmp->icmp.code == ICMP_CODE_ECHO) { // Ethernet memcpy(p_icmp->ether.dst, p_icmp->ether.src, ETH_ADDR_LEN); - memcpy(p_icmp->ether.src, g_mac_address, ETH_ADDR_LEN); + memcpy(p_icmp->ether.src, net::globals::macAddress, ETH_ADDR_LEN); // IPv4 p_icmp->ip4.id = static_cast(~p_icmp->ip4.id); + uint8_t dst[IPv4_ADDR_LEN]; + memcpy(dst, p_icmp->ip4.dst, IPv4_ADDR_LEN); memcpy(p_icmp->ip4.dst, p_icmp->ip4.src, IPv4_ADDR_LEN); - _pcast32 src; - src.u32 = g_ip_info.ip.addr; - memcpy(p_icmp->ip4.src, src.u8, IPv4_ADDR_LEN); + memcpy(p_icmp->ip4.src, dst, IPv4_ADDR_LEN); p_icmp->ip4.chksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) p_icmp->ip4.chksum = net_chksum(reinterpret_cast(&p_icmp->ip4), 20); //TODO diff --git a/lib-network/src/net/igmp.cpp b/lib-network/src/net/igmp.cpp index 9d48d12..ac58a96 100644 --- a/lib-network/src/net/igmp.cpp +++ b/lib-network/src/net/igmp.cpp @@ -29,9 +29,6 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_platform.h" -#include "net_debug.h" #include "../../config/net_config.h" @@ -61,15 +58,19 @@ static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; static struct t_group_info s_groups[IGMP_MAX_JOINS_ALLOWED] SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net -static void _send_report(uint32_t group_address); +static void _send_report(uint32_t nGroupAddress); void igmp_set_ip() { _pcast32 src; - src.u32 = g_ip_info.ip.addr; + src.u32 = net::globals::ipInfo.ip.addr; memcpy(s_report.ip4.src, src.u8, IPv4_ADDR_LEN); memcpy(s_leave.ip4.src, src.u8, IPv4_ADDR_LEN); @@ -83,7 +84,7 @@ void __attribute__((cold)) igmp_init() { s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_report.ether.src, g_mac_address, ETH_ADDR_LEN); + memcpy(s_report.ether.src, net::globals::macAddress, ETH_ADDR_LEN); s_report.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -107,7 +108,7 @@ void __attribute__((cold)) igmp_init() { s_leave.ether.dst[3] = 0x00; s_leave.ether.dst[4] = 0x00; s_leave.ether.dst[5] = 0x02; - memcpy(s_leave.ether.src, g_mac_address, ETH_ADDR_LEN); + memcpy(s_leave.ether.src, net::globals::macAddress, ETH_ADDR_LEN); s_leave.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -141,25 +142,22 @@ void __attribute__((cold)) igmp_init() { void __attribute__((cold)) igmp_shutdown() { DEBUG_ENTRY - for (auto i = 0; i < IGMP_MAX_JOINS_ALLOWED; i++) { - if (s_groups[i].nGroupAddress != 0) { - igmp_leave(s_groups[i].nGroupAddress); - s_groups[i].nGroupAddress = 0; - s_groups[i].state = NON_MEMBER; - s_groups[i].nTimer = 0; + for (auto& group : s_groups) { + if (group.nGroupAddress != 0) { + DEBUG_PRINTF(IPSTR, IP2STR(group.nGroupAddress)); - DEBUG_PRINTF(IPSTR, IP2STR(s_groups[i].nGroupAddress)); + igmp_leave(group.nGroupAddress); } } DEBUG_EXIT } -static void _send_report(uint32_t group_address) { +static void _send_report(const uint32_t nGroupAddress) { DEBUG_ENTRY _pcast32 multicast_ip; - multicast_ip.u32 = group_address; + multicast_ip.u32 = nGroupAddress; s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; s_multicast_mac[4] = multicast_ip.u8[2]; @@ -169,20 +167,15 @@ static void _send_report(uint32_t group_address) { // Ethernet memcpy(s_report.ether.dst, s_multicast_mac, ETH_ADDR_LEN); - // IPv4 s_report.ip4.id = s_id; memcpy(s_report.ip4.dst, multicast_ip.u8, IPv4_ADDR_LEN); s_report.ip4.chksum = 0; -#if !defined (CHECKSUM_BY_HARDWARE) s_report.ip4.chksum = net_chksum(reinterpret_cast(&s_report.ip4), 24); //TODO -#endif // IGMP memcpy(s_report.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); s_report.igmp.report.igmp.checksum = 0; -#if !defined (CHECKSUM_BY_HARDWARE) s_report.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_report.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); -#endif emac_eth_send(reinterpret_cast(&s_report), IGMP_REPORT_PACKET_SIZE); @@ -191,11 +184,11 @@ static void _send_report(uint32_t group_address) { DEBUG_EXIT } -static void _send_leave(uint32_t group_address) { +static void _send_leave(const uint32_t nGroupAddress) { DEBUG_ENTRY _pcast32 multicast_ip; - multicast_ip.u32 = group_address; + multicast_ip.u32 = nGroupAddress; DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress), MAC2STR(s_multicast_mac)); @@ -234,22 +227,22 @@ __attribute__((hot)) void igmp_handle(struct t_igmp *p_igmp) { isGeneralRequest = true; } - for (auto i = 0; i < IGMP_MAX_JOINS_ALLOWED; i++) { - if (s_groups[i].nGroupAddress == 0) { + for (auto& group : s_groups) { + if (group.nGroupAddress == 0) { continue; } _pcast32 group_address; - group_address.u32 = s_groups[i].nGroupAddress; + group_address.u32 = group.nGroupAddress; if (isGeneralRequest || ( memcmp(p_igmp->ip4.dst, group_address.u8, IPv4_ADDR_LEN) == 0)) { - if (s_groups[i].state == DELAYING_MEMBER) { - if (p_igmp->igmp.igmp.max_resp_time < s_groups[i].nTimer) { - s_groups[i].nTimer = (1 + p_igmp->igmp.igmp.max_resp_time / 2); + if (group.state == DELAYING_MEMBER) { + if (p_igmp->igmp.igmp.max_resp_time < group.nTimer) { + group.nTimer = (1 + p_igmp->igmp.igmp.max_resp_time / 2); } } else { // s_groups[s_joins_allowed_index].state == IDLE_MEMBER - s_groups[i].state = DELAYING_MEMBER; - s_groups[i].nTimer = (1 + p_igmp->igmp.igmp.max_resp_time / 2); + group.state = DELAYING_MEMBER; + group.nTimer = (1 + p_igmp->igmp.igmp.max_resp_time / 2); } } } @@ -259,14 +252,13 @@ __attribute__((hot)) void igmp_handle(struct t_igmp *p_igmp) { } void igmp_timer() { - for (auto i = 0; i < IGMP_MAX_JOINS_ALLOWED ; i++) { - - if ((s_groups[i].state == DELAYING_MEMBER) && (s_groups[i].nTimer > 0)) { - s_groups[i].nTimer--; + for (auto& group : s_groups) { + if ((group.state == DELAYING_MEMBER) && (group.nTimer > 0)) { + group.nTimer--; - if (s_groups[i].nTimer == 0) { - _send_report(s_groups[i].nGroupAddress); - s_groups[i].state = IDLE_MEMBER; + if (group.nTimer == 0) { + _send_report(group.nGroupAddress); + group.state = IDLE_MEMBER; } } } @@ -274,71 +266,62 @@ void igmp_timer() { // --> Public -int igmp_join(uint32_t nGroupAddress) { +void igmp_join(uint32_t nGroupAddress) { DEBUG_ENTRY DEBUG_PRINTF(IPSTR, IP2STR(nGroupAddress)); if ((nGroupAddress & 0xE0) != 0xE0) { DEBUG_ENTRY - return -1; + return; } - int i; - - for (i = 0; i < IGMP_MAX_JOINS_ALLOWED; i++) { + for (int i = 0; i < IGMP_MAX_JOINS_ALLOWED; i++) { if (s_groups[i].nGroupAddress == nGroupAddress) { DEBUG_EXIT - return i; + return; } if (s_groups[i].nGroupAddress == 0) { - break; - } - } + s_groups[i].nGroupAddress = nGroupAddress; + s_groups[i].state = DELAYING_MEMBER; + s_groups[i].nTimer = 2; // TODO - if (i == IGMP_MAX_JOINS_ALLOWED) { - console_error("igmp_join\n"); - DEBUG_ENTRY - return -2; - } + _send_report(nGroupAddress); - s_groups[i].nGroupAddress = nGroupAddress; - s_groups[i].state = DELAYING_MEMBER; - s_groups[i].nTimer = 2; // TODO + DEBUG_EXIT + return; + } + } - _send_report(nGroupAddress); - DEBUG_EXIT - return i; +#ifndef NDEBUG + console_error("igmp_join\n"); +#endif + DEBUG_ENTRY } -int igmp_leave(uint32_t nGroupAddress) { +void igmp_leave(uint32_t nGroupAddress) { DEBUG_ENTRY DEBUG_PRINTF(IPSTR, IP2STR(nGroupAddress)); - uint32_t i; + for (auto& group : s_groups) { + if (group.nGroupAddress == nGroupAddress) { + _send_leave(group.nGroupAddress); - for (i = 0; i < IGMP_MAX_JOINS_ALLOWED; i++) { - if (s_groups[i].nGroupAddress == nGroupAddress) { - break; - } - } + group.nGroupAddress = 0; + group.state = NON_MEMBER; + group.nTimer = 0; - if (i == IGMP_MAX_JOINS_ALLOWED) { - console_error("igmp_leave: "); - printf(IPSTR "\n", IP2STR(nGroupAddress)); - DEBUG_EXIT - return -1; + DEBUG_EXIT + return; + } } - _send_leave(s_groups[i].nGroupAddress); - - s_groups[i].nGroupAddress = 0; - s_groups[i].state = NON_MEMBER; - s_groups[i].nTimer = 0; - +#ifndef NDEBUG + console_error("igmp_leave: "); + printf(IPSTR "\n", IP2STR(nGroupAddress)); +#endif DEBUG_EXIT - return 0; } // <--- diff --git a/lib-network/src/net/ip.cpp b/lib-network/src/net/ip.cpp index a701183..e697459 100644 --- a/lib-network/src/net/ip.cpp +++ b/lib-network/src/net/ip.cpp @@ -27,10 +27,6 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" - -#include "debug.h" #include "../../config/net_config.h" @@ -44,6 +40,7 @@ void __attribute__((cold)) ip_init() { udp_init(); igmp_init(); + tcp_init(); DEBUG_EXIT } @@ -51,8 +48,8 @@ void __attribute__((cold)) ip_init() { void __attribute__((cold)) ip_shutdown() { DEBUG_ENTRY + tcp_shutdown(); igmp_shutdown(); - udp_shutdown(); DEBUG_EXIT } diff --git a/lib-network/src/net/net.cpp b/lib-network/src/net/net.cpp index b313631..0afe1e2 100644 --- a/lib-network/src/net/net.cpp +++ b/lib-network/src/net/net.cpp @@ -31,30 +31,65 @@ #include "net_packets.h" #include "net_debug.h" -#include "debug.h" - #include "../../config/net_config.h" -struct ip_info g_ip_info __attribute__ ((aligned (4))); -uint8_t g_mac_address[ETH_ADDR_LEN] __attribute__ ((aligned (4))); +namespace net { +namespace globals { +struct IpInfo ipInfo ALIGNED; +uint32_t nBroadcastMask; +uint32_t nOnNetworkMask; +uint8_t macAddress[ETH_ADDR_LEN] ALIGNED; +} // namespace globals +} // namespace net static uint8_t *s_p; static bool s_isDhcp = false; -void __attribute__((cold)) net_init(const uint8_t *const pMacAddress, struct ip_info *p_ip_info, const char *pHostname, bool *bUseDhcp, bool *isZeroconfUsed) { - DEBUG_ENTRY +static void refresh_and_init(struct IpInfo *pIpInfo, bool doInit) { + net::globals::ipInfo.broadcast_ip.addr = net::globals::ipInfo.ip.addr | ~net::globals::ipInfo.netmask.addr; + + net::globals::nBroadcastMask = ~(net::globals::ipInfo.netmask.addr); + net::globals::nOnNetworkMask = net::globals::ipInfo.ip.addr & net::globals::ipInfo.netmask.addr; - for (auto i = 0; i < ETH_ADDR_LEN; i++) { - g_mac_address[i] = pMacAddress[i]; + if (doInit) { + arp_init(); + ip_set_ip(); } - const auto *src = reinterpret_cast(p_ip_info); - auto *dst = reinterpret_cast(&g_ip_info); + const auto *pSrc = reinterpret_cast(&net::globals::ipInfo); + auto *pDst = reinterpret_cast(pIpInfo); - for (uint32_t i = 0; i < sizeof(struct ip_info); i++) { - *dst++ = *src++; - } + memcpy(pDst, pSrc, sizeof(struct IpInfo)); +} + +void set_secondary_ip() { + net::globals::ipInfo.ip.addr = net::globals::ipInfo.secondary_ip.addr; + net::globals::ipInfo.netmask.addr = 255; + net::globals::ipInfo.gw.addr = net::globals::ipInfo.ip.addr; +} + +void __attribute__((cold)) net_init(const uint8_t *const pMacAddress, struct IpInfo *pIpInfo, const char *pHostname, bool *bUseDhcp, bool *isZeroconfUsed) { + DEBUG_ENTRY + + memcpy(net::globals::macAddress, pMacAddress, ETH_ADDR_LEN); + + const auto *pSrc = reinterpret_cast(pIpInfo); + auto *pDst = reinterpret_cast(&net::globals::ipInfo); + + memcpy(pDst, pSrc, sizeof(struct IpInfo)); + + net::globals::ipInfo.secondary_ip.addr = 2 + + ((static_cast(net::globals::macAddress[3])) << 8) + + ((static_cast(net::globals::macAddress[4])) << 16) + + ((static_cast(net::globals::macAddress[5])) << 24); + + if (net::globals::ipInfo.ip.addr == 0) { + set_secondary_ip(); + } + /* + * The macAddress is set + */ ip_init(); *isZeroconfUsed = false; @@ -67,19 +102,17 @@ void __attribute__((cold)) net_init(const uint8_t *const pMacAddress, struct ip_ } } - arp_init(); - ip_set_ip(); - tcp_init(); + refresh_and_init(pIpInfo, true); - src = reinterpret_cast(&g_ip_info); - dst = reinterpret_cast(p_ip_info); + s_isDhcp = *bUseDhcp; - for (uint32_t i = 0; i < sizeof(struct ip_info); i++) { - *dst++ = *src++; + if (!arp_do_probe()) { + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); + arp_send_announcement(); + } else { + console_error("IP Conflict!\n"); } - s_isDhcp = *bUseDhcp; - DEBUG_EXIT } @@ -91,20 +124,36 @@ void __attribute__((cold)) net_shutdown() { } } -void net_set_ip(uint32_t ip) { - g_ip_info.ip.addr = ip; +void net_set_ip(struct IpInfo *pIpInfo) { + net::globals::ipInfo.ip.addr = pIpInfo->ip.addr; - arp_init(); - ip_set_ip(); + if (net::globals::ipInfo.ip.addr == 0) { + set_secondary_ip(); + } + + refresh_and_init(pIpInfo, true); + + if (!arp_do_probe()) { + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); + arp_send_announcement(); + } else { + console_error("IP Conflict!\n"); + } +} + +void net_set_netmask(struct IpInfo *pIpInfo) { + net::globals::ipInfo.netmask.addr = pIpInfo->netmask.addr; + + refresh_and_init(pIpInfo, false); } -void net_set_gw(uint32_t gw) { - g_ip_info.gw.addr = gw; +void net_set_gw(struct IpInfo *pIpInfo) { + net::globals::ipInfo.gw.addr = pIpInfo->gw.addr; ip_set_ip(); } -bool net_set_dhcp(struct ip_info *p_ip_info, const char *const pHostname, bool *isZeroconfUsed) { +bool net_set_dhcp(struct IpInfo *pIpInfo, const char *const pHostname, bool *isZeroconfUsed) { bool isDhcp = false; *isZeroconfUsed = false; @@ -115,17 +164,17 @@ bool net_set_dhcp(struct ip_info *p_ip_info, const char *const pHostname, bool * isDhcp = true; } - arp_init(); - ip_set_ip(); + refresh_and_init(pIpInfo, true); - const auto *pSrc = reinterpret_cast(&g_ip_info); - auto *pDst = reinterpret_cast(p_ip_info); + s_isDhcp = isDhcp; - for (uint32_t i = 0; i < sizeof(struct ip_info); i++) { - *pDst++ = *pSrc++; + if (!arp_do_probe()) { + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); + arp_send_announcement(); + } else { + console_error("IP Conflict!\n"); } - s_isDhcp = isDhcp; return isDhcp; } @@ -134,21 +183,17 @@ void net_dhcp_release() { s_isDhcp = false; } -bool net_set_zeroconf(struct ip_info *p_ip_info) { +bool net_set_zeroconf(struct IpInfo *pIpInfo) { const auto b = rfc3927(); if (b) { - arp_init(); - ip_set_ip(); + refresh_and_init(pIpInfo, true); - const auto *pSrc = reinterpret_cast(&g_ip_info); - auto *pDst = reinterpret_cast(p_ip_info); + s_isDhcp = false; - for (uint32_t i = 0; i < sizeof(struct ip_info); i++) { - *pDst++ = *pSrc++; - } + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); + arp_send_announcement(); - s_isDhcp = false; return true; } @@ -160,12 +205,12 @@ __attribute__((hot)) void net_handle() { const auto nLength = emac_eth_recv(&s_p); if (__builtin_expect((nLength > 0), 0)) { - const auto *const eth = reinterpret_cast( s_p); + const auto *const eth = reinterpret_cast(s_p); if (eth->type == __builtin_bswap16(ETHER_TYPE_IPv4)) { - ip_handle(reinterpret_cast( s_p)); + ip_handle(reinterpret_cast(s_p)); } else if (eth->type == __builtin_bswap16(ETHER_TYPE_ARP)) { - arp_handle(reinterpret_cast( s_p)); + arp_handle(reinterpret_cast(s_p)); } else { DEBUG_PRINTF("type %04x is not implemented", __builtin_bswap16(eth->type)); } diff --git a/lib-network/src/net/net.h b/lib-network/src/net/net.h index 8b52802..47a2786 100644 --- a/lib-network/src/net/net.h +++ b/lib-network/src/net/net.h @@ -34,37 +34,40 @@ struct ip_addr { typedef struct ip_addr ip_addr_t; -struct ip_info { +struct IpInfo { struct ip_addr ip; struct ip_addr netmask; struct ip_addr gw; + struct ip_addr broadcast_ip; + struct ip_addr secondary_ip; }; #define IP_BROADCAST (0xFFFFFFFF) #define HOST_NAME_MAX 64 /* including a terminating null byte. */ -extern void net_init(const uint8_t *const, struct ip_info *, const char *, bool *, bool *); -extern void net_shutdown(); -extern void net_handle(); +void net_init(const uint8_t *const, struct IpInfo *, const char *, bool *, bool *); +void net_shutdown(); +void net_handle(); -extern void net_set_ip(uint32_t); -extern void net_set_gw(uint32_t); -extern bool net_set_zeroconf(struct ip_info *); +void net_set_ip(struct IpInfo *); +void net_set_netmask(struct IpInfo *); +void net_set_gw(struct IpInfo *); +bool net_set_zeroconf(struct IpInfo *); -extern bool net_set_dhcp(struct ip_info *, const char *const, bool *); -extern void net_dhcp_release(); +bool net_set_dhcp(struct IpInfo *, const char *const, bool *); +void net_dhcp_release(); -extern int udp_begin(uint16_t); -extern int udp_end(uint16_t); -extern uint16_t udp_recv1(int, uint8_t *, uint16_t, uint32_t *, uint16_t *); -extern uint16_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); -extern int udp_send(int, const uint8_t *, uint16_t, uint32_t, uint16_t); +int udp_begin(uint16_t); +int udp_end(uint16_t); +uint16_t udp_recv1(int, uint8_t *, uint16_t, uint32_t *, uint16_t *); +uint16_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); +int udp_send(int, const uint8_t *, uint16_t, uint32_t, uint16_t); -extern int igmp_join(uint32_t); -extern int igmp_leave(uint32_t); +void igmp_join(uint32_t); +void igmp_leave(uint32_t); -extern int tcp_begin(const uint16_t); -extern uint16_t tcp_read(const int32_t, const uint8_t **, uint32_t &); -extern void tcp_write(const int32_t, const uint8_t *, uint16_t, const uint32_t); +int tcp_begin(const uint16_t); +uint16_t tcp_read(const int32_t, const uint8_t **, uint32_t &); +void tcp_write(const int32_t, const uint8_t *, uint16_t, const uint32_t); #endif /* NET_H_ */ diff --git a/lib-network/src/net/net_memcpy.h b/lib-network/src/net/net_memcpy.h index cb4242f..c7a70bd 100644 --- a/lib-network/src/net/net_memcpy.h +++ b/lib-network/src/net/net_memcpy.h @@ -25,8 +25,9 @@ #define NET_MEMCPY_H_ #include +#include -void *net_memcpy(void *__restrict__ dest, void const *__restrict__ src, size_t n) { +inline void *net_memcpy(void *__restrict__ dest, void const *__restrict__ src, size_t n) { auto *plDst = reinterpret_cast(dest); auto const *plSrc = reinterpret_cast(src); diff --git a/lib-network/src/net/net_packets.h b/lib-network/src/net/net_packets.h index 0952c9c..d3b0f3e 100644 --- a/lib-network/src/net/net_packets.h +++ b/lib-network/src/net/net_packets.h @@ -26,10 +26,10 @@ #ifndef NET_PACKETS_H_ #define NET_PACKETS_H_ -#include +#include #if !defined (PACKED) - #define PACKED __attribute__((packed)) +# define PACKED __attribute__((packed)) #endif enum MTU { @@ -52,7 +52,7 @@ enum IPv4_ADDR { enum IPv4_PROTO { IPv4_PROTO_ICMP = 1, IPv4_PROTO_IGMP = 2, - IPv4_PROTO_TCP = 6, // Not implemented + IPv4_PROTO_TCP = 6, IPv4_PROTO_UDP = 17 }; @@ -104,19 +104,20 @@ struct ether_header { uint8_t dst[ETH_ADDR_LEN]; /* 6 */ uint8_t src[ETH_ADDR_LEN]; /* 12 */ uint16_t type; /* 14 */ -}PACKED; +} PACKED; struct arp_packet { - uint16_t hardware_type; - uint16_t protocol_type; - uint8_t hardware_size; - uint8_t protocol_size; - uint16_t opcode; - uint8_t sender_mac[ETH_ADDR_LEN]; - uint32_t sender_ip; - uint8_t target_mac[ETH_ADDR_LEN]; - uint32_t target_ip; -}PACKED; + uint16_t hardware_type; /* 2 */ + uint16_t protocol_type; /* 4 */ + uint8_t hardware_size; /* 5 */ + uint8_t protocol_size; /* 6 */ + uint16_t opcode; /* 8 */ + uint8_t sender_mac[ETH_ADDR_LEN];/*14 */ + uint8_t sender_ip[IPv4_ADDR_LEN];/* 18 */ + uint8_t target_mac[ETH_ADDR_LEN];/*24 */ + uint8_t target_ip[IPv4_ADDR_LEN];/* 28 */ + uint8_t padding[18]; /* 46 */ /* +14 = 60 */ +} PACKED; struct ip4_header { uint8_t ver_ihl; /* 1 */ @@ -129,24 +130,24 @@ struct ip4_header { uint16_t chksum; /* 12 */ uint8_t src[IPv4_ADDR_LEN]; /* 16 */ uint8_t dst[IPv4_ADDR_LEN]; /* 20 */ -}PACKED; +} PACKED; struct t_igmp_packet { uint8_t type; uint8_t max_resp_time; uint16_t checksum; uint8_t group_address[IPv4_ADDR_LEN]; -}PACKED; +} PACKED; struct t_icmp_packet { uint8_t type; /* 1 */ uint8_t code; /* 2 */ uint16_t checksum; /* 4 */ uint8_t parameter[4]; /* 8 */ -#define ICMP_HEADER_SIZE 8 -#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) +#define ICMP_HEADER_SIZE 8 +#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) uint8_t payload[ICMP_PAYLOAD_SIZE]; -}PACKED; +} PACKED; struct t_udp_packet { uint16_t source_port; /* 2 */ @@ -176,12 +177,12 @@ struct t_tcp_packet { struct t_arp { struct ether_header ether; struct arp_packet arp; -}PACKED; +} PACKED; struct t_ip4 { struct ether_header ether; struct ip4_header ip4; -}PACKED; +} PACKED; struct t_igmp { struct ether_header ether; @@ -193,25 +194,25 @@ struct t_igmp { } report; struct t_igmp_packet igmp; } igmp; -}PACKED; +} PACKED; struct t_icmp { struct ether_header ether; struct ip4_header ip4; struct t_icmp_packet icmp; -}PACKED; +} PACKED; struct t_udp { struct ether_header ether; struct ip4_header ip4; struct t_udp_packet udp; -}PACKED; +} PACKED; struct t_tcp { struct ether_header ether; struct ip4_header ip4; struct t_tcp_packet tcp; -}PACKED; +} PACKED; #define IPv4_UDP_HEADERS_SIZE (sizeof(struct ip4_header) + UDP_HEADER_SIZE) /* IP | UDP */ #define UDP_PACKET_HEADERS_SIZE (sizeof(struct ether_header) + IPv4_UDP_HEADERS_SIZE) /* ETH | IP | UDP */ diff --git a/lib-network/src/net/net_platform.h b/lib-network/src/net/net_platform.h index faea3da..79f9343 100644 --- a/lib-network/src/net/net_platform.h +++ b/lib-network/src/net/net_platform.h @@ -2,7 +2,7 @@ * @file net_platform.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,11 +27,14 @@ #define NET_PLATFORM_H_ #if defined (GD32) +/** + * https://www.gd32-dmx.org/memory.html + */ # include "gd32.h" -# if !defined (GD32F4XX) -# define SECTION_NETWORK -# else +# if defined (GD32F207RG) || defined (GD32F4XX) # define SECTION_NETWORK __attribute__ ((section (".network"))) +# else +# define SECTION_NETWORK # endif #else # define SECTION_NETWORK diff --git a/lib-network/src/net/net_private.h b/lib-network/src/net/net_private.h index 5889cb6..93c4da7 100755 --- a/lib-network/src/net/net_private.h +++ b/lib-network/src/net/net_private.h @@ -29,28 +29,23 @@ #include #include "net_packets.h" +#include "net_platform.h" +#include "net_debug.h" + +#include "dhcp_internal.h" +#include "tftp_internal.h" +#include "ntp_internal.h" #ifndef ALIGNED # define ALIGNED __attribute__ ((aligned (4))) #endif -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifdef __cplusplus extern "C" { -#endif - -extern int console_error(const char *); - -extern void emac_eth_send(void *, int); -extern int emac_eth_recv(uint8_t **); -extern void emac_free_pkt(void); - -#ifdef __cplusplus +int console_error(const char *); +void emac_eth_send(void *, int); +int emac_eth_recv(uint8_t **); +void emac_free_pkt(void); } -#endif void net_handle(); @@ -59,10 +54,13 @@ void net_timers_run(); void arp_init(); void arp_handle(struct t_arp *); +bool arp_do_probe(); void arp_cache_init(); void arp_send_request(uint32_t); +void arp_send_probe(); +void arp_send_announcement(); void arp_cache_update(const uint8_t *, uint32_t); -uint32_t arp_cache_lookup(uint32_t ip, uint8_t *); +uint32_t arp_cache_lookup(uint32_t, uint8_t *); void ip_init(); void ip_set_ip(); @@ -91,5 +89,6 @@ void icmp_shutdown(); void tcp_init(); void tcp_run(); void tcp_handle(struct t_tcp *); +void tcp_shutdown(); #endif /* NET_PRIVATE_H_ */ diff --git a/lib-network/src/net/rfc3927.cpp b/lib-network/src/net/rfc3927.cpp index c8231b8..ba7b9c4 100644 --- a/lib-network/src/net/rfc3927.cpp +++ b/lib-network/src/net/rfc3927.cpp @@ -28,8 +28,6 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" #include "hardware.h" @@ -42,13 +40,18 @@ static const uint32_t s_ip_begin = 0x0100FEA9; // 169.254.0.1 static const uint32_t s_ip_end = 0xFFFEFEA9; // 169.254.254.255 -static uint8_t s_mac_address_arp_reply[6] __attribute__ ((aligned (4))); -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net bool rfc3927() { - const auto mask = g_mac_address[3] + (g_mac_address[4] << 8); + DEBUG_ENTRY + + const auto mask = net::globals::macAddress[3] + (net::globals::macAddress[4] << 8); auto ip = s_ip_begin | static_cast(mask << 16); DEBUG_PRINTF("ip=" IPSTR, IP2STR(ip)); @@ -59,11 +62,13 @@ bool rfc3927() { do { DEBUG_PRINTF(IPSTR, IP2STR(ip)); - if (0 == arp_cache_lookup(ip, s_mac_address_arp_reply)) { - g_ip_info.ip.addr = ip; - g_ip_info.gw.addr = ip; - g_ip_info.netmask.addr = 0x0000FFFF; + net::globals::ipInfo.ip.addr = ip; + + if (!arp_do_probe()) { + net::globals::ipInfo.gw.addr = ip; + net::globals::ipInfo.netmask.addr = 0x0000FFFF; + DEBUG_EXIT return true; } @@ -76,9 +81,10 @@ bool rfc3927() { nCount++; } while ((nCount < 0xFF) && ((Hardware::Get()->Millis() - nMillis) < 500)); - g_ip_info.ip.addr = 0; - g_ip_info.gw.addr = 0; - g_ip_info.netmask.addr = 0; + net::globals::ipInfo.ip.addr = 0; + net::globals::ipInfo.gw.addr = 0; + net::globals::ipInfo.netmask.addr = 0; + DEBUG_EXIT return false; } diff --git a/lib-network/src/net/tcp.cpp b/lib-network/src/net/tcp.cpp index e11f222..4dda207 100644 --- a/lib-network/src/net/tcp.cpp +++ b/lib-network/src/net/tcp.cpp @@ -42,9 +42,6 @@ #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_platform.h" -#include "net_debug.h" #include "hardware.h" @@ -57,19 +54,24 @@ #define TCP_TX_MSS (TCP_DATA_SIZE) -#define MAX_TCBS_ALLOWED 4 +#define MAX_TCBS_ALLOWED 6 -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net /** * Transmission control block (TCB) */ struct tcb { - uint16_t nLocalPort; + uint8_t localIp[IPv4_ADDR_LEN]; + uint8_t remoteIp[IPv4_ADDR_LEN]; + uint16_t nLocalPort; uint16_t nRemotePort; - uint32_t nRemoteIp; + uint8_t remoteEthAddr[ETH_ADDR_LEN]; /* Send Sequence Variables */ @@ -319,14 +321,10 @@ static void _init_tcb(struct tcb *pTcb, const uint16_t nLocalPort) { __attribute__((cold)) void tcp_init() { DEBUG_ENTRY - _pcast32 src; - /* Ethernet */ - memcpy(s_tcp.ether.src, g_mac_address, ETH_ADDR_LEN); + memcpy(s_tcp.ether.src, net::globals::macAddress, ETH_ADDR_LEN); s_tcp.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); /* IPv4 */ - src.u32 = g_ip_info.ip.addr; - memcpy(s_tcp.ip4.src, src.u8, IPv4_ADDR_LEN); s_tcp.ip4.ver_ihl = 0x45; s_tcp.ip4.tos = 0; s_tcp.ip4.flags_froff = __builtin_bswap16(IPv4_FLAG_DF); @@ -336,6 +334,12 @@ __attribute__((cold)) void tcp_init() { DEBUG_EXIT } +void tcp_shutdown() { + DEBUG_ENTRY + + DEBUG_EXIT +} + /* TCP Checksum Pseudo Header */ struct tcpPseudo { uint8_t srcIp[IPv4_ADDR_LEN]; @@ -356,8 +360,8 @@ static uint16_t _chksum(struct t_tcp *pTcp, const struct tcb *pTcb, uint16_t nLe memcpy(buf, pseu, TCP_PSEUDO_LEN); // Generate TCP psuedo header - memcpy(pseu->srcIp, &g_ip_info.ip.addr, IPv4_ADDR_LEN); - memcpy(pseu->dstIp, &pTcb->nRemoteIp, IPv4_ADDR_LEN); + memcpy(pseu->srcIp, pTcb->localIp, IPv4_ADDR_LEN); + memcpy(pseu->dstIp, pTcb->remoteIp, IPv4_ADDR_LEN); pseu->zero = 0; pseu->proto = IPv4_PROTO_TCP; pseu->length = __builtin_bswap16(nLength); @@ -391,7 +395,8 @@ static void send_package(const struct tcb *pTcb, const struct SendInfo &sendInfo /* IPv4 */ s_tcp.ip4.id = s_id++; s_tcp.ip4.len = __builtin_bswap16(static_cast(tcplen + sizeof(struct ip4_header))); - memcpy(s_tcp.ip4.dst, &pTcb->nRemoteIp, IPv4_ADDR_LEN); + memcpy(s_tcp.ip4.src, pTcb->localIp, IPv4_ADDR_LEN); + memcpy(s_tcp.ip4.dst, pTcb->remoteIp, IPv4_ADDR_LEN); s_tcp.ip4.chksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) s_tcp.ip4.chksum = net_chksum(reinterpret_cast(&s_tcp.ip4), 20); @@ -504,7 +509,7 @@ static void scan_options(struct t_tcp *pTcp, struct tcb *pTcb, const int32_t nDa const auto *p = &pOptions->Data; auto nMSS = (p[0] << 8) + p[1]; // RFC 1122 section 4.2.2.6 - nMSS = std::min((nMSS + 20), static_cast(TCP_TX_MSS)) - TCP_HEADER_SIZE; // - IP_OPTION_SIZE; + nMSS = std::min(static_cast(nMSS + 20), static_cast(TCP_TX_MSS)) - TCP_HEADER_SIZE; // - IP_OPTION_SIZE; pTcb->SendMSS = static_cast(nMSS); } pOptions = reinterpret_cast(reinterpret_cast(pOptions) + pOptions->nLength); @@ -572,7 +577,12 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { DEBUG_PRINTF(IPSTR ":%d[%d] -> %d", pTcp->ip4.src[0], pTcp->ip4.src[1], pTcp->ip4.src[2], pTcp->ip4.src[3], pTcp->tcp.dstpt, pTcp->tcp.srcpt, tcplen); uint32_t nIndexPort; - uint32_t nIndexTCB; + /* + src/net/tcp.cpp: In function 'void tcp_handle(t_tcp*)': +src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this function [-Werror=maybe-uninitialized] + 871 | switch (pTCB->state) { + */ + uint32_t nIndexTCB = 0; // Find a TCB for (nIndexPort = 0; nIndexPort < TCP_MAX_PORTS_ALLOWED; nIndexPort++) { @@ -581,9 +591,7 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { for (nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; if (pTCB->state != STATE_LISTEN) { - _pcast32 src; - memcpy(src.u8, pTcp->ip4.src, IPv4_ADDR_LEN); - if ((pTCB->nRemotePort == pTcp->tcp.srcpt) && (pTCB->nRemoteIp == src.u32)) { + if ((pTCB->nRemotePort == pTcp->tcp.srcpt) && (memcmp(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN) == 0)) { break; } } @@ -616,15 +624,16 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { if (nIndexPort == TCP_MAX_PORTS_ALLOWED) { DEBUG_PUTS("TCP_MAX_PORTS_ALLOWED"); struct tcb TCB; - _pcast32 src; memset(&TCB, 0, sizeof(struct tcb)); TCB.nLocalPort = pTcp->tcp.dstpt; + memcpy(TCB.localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + TCB.nRemotePort = pTcp->tcp.srcpt; - memcpy(src.u8, pTcp->ip4.src, IPv4_ADDR_LEN); - TCB.nRemoteIp = src.u32; + memcpy(TCB.remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); memcpy(TCB.remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); + _bswap32(pTcp); scan_options(pTcp, &TCB, nDataOffset); @@ -654,7 +663,6 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { nDataLength); SendInfo sendInfo; - _pcast32 src; const auto SEG_LEN = nDataLength; const auto SEG_ACK = _get_acknum(pTcp); @@ -683,9 +691,10 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { // https://www.rfc-editor.org/rfc/rfc9293.html#name-listen-state if (pTCB->state == STATE_LISTEN) { + memcpy(pTCB->localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + pTCB->nRemotePort = pTcp->tcp.srcpt; - memcpy(src.u8, pTcp->ip4.src, IPv4_ADDR_LEN); - pTCB->nRemoteIp = src.u32; + memcpy(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); memcpy(pTCB->remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); // First, check for a RST @@ -829,7 +838,7 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { return; } - // third check security and precedence. Nothing todo here + // third check security and precedence. No code needed here /* fourth, check the SYN bit, *//* Page 71 */ if (pTcp->tcp.control & Control::SYN) { @@ -941,7 +950,7 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { break; } - // sixth, check the URG bit. Nothing todo here + // sixth, check the URG bit. No code needed here // seventh, process the segment text switch (pTCB->state) { @@ -1066,32 +1075,29 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { int tcp_begin(const uint16_t nLocalPort) { DEBUG_PRINTF("nLocalPort=%u", nLocalPort); - int i; - - for (i = 0; i < TCP_MAX_PORTS_ALLOWED; i++) { + for (int i = 0; i < TCP_MAX_PORTS_ALLOWED; i++) { if (s_Port[i].nLocalPort == nLocalPort) { return i; } if (s_Port[i].nLocalPort == 0) { - break; - } - } - - if (i == TCP_MAX_PORTS_ALLOWED) { - console_error("tcp_begin"); - return -1; - } + s_Port[i].nLocalPort = nLocalPort; - s_Port[i].nLocalPort = nLocalPort; + for (uint32_t nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { + // create transmission control block's (TCB) + _init_tcb(&s_Port[i].TCB[nIndexTCB], nLocalPort); + } - for (uint32_t nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { - // create transmission control block's (TCB) - _init_tcb(&s_Port[i].TCB[nIndexTCB], nLocalPort); + DEBUG_PRINTF("i=%d, nLocalPort=%d[%x]", i, nLocalPort, nLocalPort); + return i; + } } - DEBUG_PRINTF("i=%d, nLocalPort=%d[%x]", i, nLocalPort, nLocalPort); - return i; +#ifndef NDEBUG + console_error("tcp_begin\n"); +#endif + return -1; + } uint16_t tcp_read(const int32_t nHandleListen, const uint8_t **pData, uint32_t &nHandleConnection) { @@ -1125,7 +1131,7 @@ void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLe assert(pBuffer != nullptr); assert(nHandleConnection < MAX_TCBS_ALLOWED); - nLength = MIN(nLength, TCP_DATA_SIZE); + nLength = std::min(nLength, static_cast(TCP_DATA_SIZE)); auto *pTCB = &s_Port[nHandleListen].TCB[nHandleConnection]; diff --git a/lib-network/src/net/udp.cpp b/lib-network/src/net/udp.cpp index 25cdead..5def0c6 100644 --- a/lib-network/src/net/udp.cpp +++ b/lib-network/src/net/udp.cpp @@ -26,22 +26,15 @@ #include #include #include +#include #include -#include "dhcp_internal.h" -#include "tftp_internal.h" -#include "ntp_internal.h" - #include "net.h" #include "net_private.h" #include "net_memcpy.h" -#include "net_packets.h" -#include "net_debug.h" #include "../../config/net_config.h" -#define SECTION_NETWORK - struct data_entry { uint32_t from_ip; uint16_t from_port; @@ -54,29 +47,35 @@ typedef union pcast32 { uint8_t u8[4]; } _pcast32; -static uint16_t s_ports_allowed[UDP_MAX_PORTS_ALLOWED] SECTION_NETWORK ALIGNED; +static uint16_t s_Port[UDP_MAX_PORTS_ALLOWED] SECTION_NETWORK ALIGNED; static struct data_entry s_data[UDP_MAX_PORTS_ALLOWED] SECTION_NETWORK ALIGNED; static struct t_udp s_send_packet SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; -static uint32_t broadcast_mask SECTION_NETWORK; -static uint32_t on_network_mask SECTION_NETWORK; -static uint8_t s_multicast_mac[ETH_ADDR_LEN] = {0x01, 0x00, 0x5E}; // Fixed part +static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; -extern struct ip_info g_ip_info; -extern uint8_t g_mac_address[ETH_ADDR_LEN]; +namespace net { +namespace globals { +extern struct IpInfo ipInfo; +extern uint32_t nBroadcastMask; +extern uint32_t nOnNetworkMask; +extern uint8_t macAddress[ETH_ADDR_LEN]; +} // namespace globals +} // namespace net void udp_set_ip() { _pcast32 src; - src.u32 = g_ip_info.ip.addr; + src.u32 = net::globals::ipInfo.ip.addr; memcpy(s_send_packet.ip4.src, src.u8, IPv4_ADDR_LEN); - broadcast_mask = ~(g_ip_info.netmask.addr); - on_network_mask = g_ip_info.ip.addr & g_ip_info.netmask.addr; } void __attribute__((cold)) udp_init() { + // Multicast fixed part + s_multicast_mac[0] = 0x01; + s_multicast_mac[1] = 0x00; + s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_send_packet.ether.src, g_mac_address, ETH_ADDR_LEN); + memcpy(s_send_packet.ether.src, net::globals::macAddress, ETH_ADDR_LEN); s_send_packet.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 s_send_packet.ip4.ver_ihl = 0x45; @@ -98,43 +97,31 @@ void __attribute__((cold)) udp_shutdown() { __attribute__((hot)) void udp_handle(struct t_udp *pUdp) { const auto nDestinationPort = __builtin_bswap16(pUdp->udp.destination_port); - if ((nDestinationPort != DHCP_PORT_CLIENT) - && (nDestinationPort != TFTP_PORT_SERVER) - && (nDestinationPort != NTP_PORT_SERVER) - && (nDestinationPort < 1024)) { // There is no support for other UDP defined services - DEBUG_PRINTF("Not supported -> " IPSTR ":%d", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort); - return; - } - - uint32_t nPortIndex; + for (uint32_t nPortIndex = 0; nPortIndex < UDP_MAX_PORTS_ALLOWED; nPortIndex++) { + if (s_Port[nPortIndex] == nDestinationPort) { + if (__builtin_expect ((s_data[nPortIndex].size != 0), 0)) { + DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); + } - for (nPortIndex = 0; nPortIndex < UDP_MAX_PORTS_ALLOWED; nPortIndex++) { - if (s_ports_allowed[nPortIndex] == nDestinationPort) { - break; - } - } + auto *p_queue_entry = &s_data[nPortIndex]; + const auto nDataLength = static_cast(__builtin_bswap16(pUdp->udp.len) - UDP_HEADER_SIZE); + const auto i = std::min(static_cast(UDP_DATA_SIZE), nDataLength); - if (__builtin_expect ((nPortIndex == UDP_MAX_PORTS_ALLOWED), 0)) { - DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); - return; - } + net_memcpy(p_queue_entry->data, pUdp->udp.data, i); - if (s_data[nPortIndex].size != 0) { - DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); - } + _pcast32 src; - auto *p_queue_entry = &s_data[nPortIndex]; - const auto nDataLength = static_cast(__builtin_bswap16(pUdp->udp.len) - UDP_HEADER_SIZE); - const auto i = MIN(UDP_DATA_SIZE, nDataLength); + memcpy(src.u8, pUdp->ip4.src, IPv4_ADDR_LEN); + p_queue_entry->from_ip = src.u32; + p_queue_entry->from_port = __builtin_bswap16(pUdp->udp.source_port); + p_queue_entry->size = static_cast(i); - net_memcpy(p_queue_entry->data, pUdp->udp.data, i); + return; - _pcast32 src; + } + } - memcpy(src.u8, pUdp->ip4.src, IPv4_ADDR_LEN); - p_queue_entry->from_ip = src.u32; - p_queue_entry->from_port = __builtin_bswap16(pUdp->udp.source_port); - p_queue_entry->size = static_cast(i); + DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); } // --> @@ -142,35 +129,31 @@ __attribute__((hot)) void udp_handle(struct t_udp *pUdp) { int udp_begin(uint16_t nLocalPort) { DEBUG_PRINTF("nLocalPort=%u", nLocalPort); - int i; - - for (i = 0; i < UDP_MAX_PORTS_ALLOWED; i++) { - if (s_ports_allowed[i] == nLocalPort) { + for (int i = 0; i < UDP_MAX_PORTS_ALLOWED; i++) { + if (s_Port[i] == nLocalPort) { return i; } - if (s_ports_allowed[i] == 0) { - break; - } - } + if (s_Port[i] == 0) { + s_Port[i] = nLocalPort; - if (i == UDP_MAX_PORTS_ALLOWED) { - console_error("udp_begin"); - return -1; + DEBUG_PRINTF("i=%d, local_port=%d[%x]", i, nLocalPort, nLocalPort); + return i; + } } - s_ports_allowed[i] = nLocalPort; - - DEBUG_PRINTF("i=%d, local_port=%d[%x]", i, nLocalPort, nLocalPort); - return i; +#ifndef NDEBUG + console_error("udp_begin\n"); +#endif + return -1; } int udp_end(uint16_t nLocalPort) { DEBUG_PRINTF("nLocalPort=%u[%x]", nLocalPort, nLocalPort); for (auto i = 0; i < UDP_MAX_PORTS_ALLOWED; i++) { - if (s_ports_allowed[i] == nLocalPort) { - s_ports_allowed[i] = 0; + if (s_Port[i] == nLocalPort) { + s_Port[i] = 0; s_data[i].size = 0; return 0; } @@ -189,7 +172,7 @@ uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp } auto *p_data = &s_data[nIndex]; - const auto i = MIN(nSize, p_data->size); + const auto i = std::min(nSize, p_data->size); net_memcpy(pData, p_data->data, i); @@ -201,7 +184,7 @@ uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp return i; } -uint16_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *FromIp, uint16_t *FromPort) { +uint16_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *pFromIp, uint16_t *pFromPort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); @@ -212,23 +195,22 @@ uint16_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *FromIp, uint16_t auto *p_data = &s_data[nIndex]; *pData = p_data->data; - *FromIp = p_data->from_ip; - *FromPort = p_data->from_port; + *pFromIp = p_data->from_ip; + *pFromPort = p_data->from_port; - const auto size = p_data->size; + const auto nSize = p_data->size; p_data->size = 0; - return size; + return nSize; } int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp, uint16_t RemotePort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); - _pcast32 dst; - if (__builtin_expect ((s_ports_allowed[nIndex] == 0), 0)) { + if (__builtin_expect ((s_Port[nIndex] == 0), 0)) { DEBUG_PUTS("ports_allowed[idx] == 0"); return -1; } @@ -236,7 +218,7 @@ int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp if (RemoteIp == IPv4_BROADCAST) { memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); memset(s_send_packet.ip4.dst, 0xFF, IPv4_ADDR_LEN); - } else if ((RemoteIp & broadcast_mask) == broadcast_mask) { + } else if ((RemoteIp & net::globals::nBroadcastMask) == net::globals::nBroadcastMask) { memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); dst.u32 = RemoteIp; memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); @@ -255,12 +237,15 @@ int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp dst.u32 = RemoteIp; memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); } else { - if (__builtin_expect((on_network_mask != (RemoteIp & on_network_mask)), 0)) { - if (g_ip_info.gw.addr == arp_cache_lookup(g_ip_info.gw.addr, s_send_packet.ether.dst)) { + if (__builtin_expect((net::globals::nOnNetworkMask != (RemoteIp & net::globals::nOnNetworkMask)), 0)) { + if (net::globals::ipInfo.gw.addr == arp_cache_lookup(net::globals::ipInfo.gw.addr, s_send_packet.ether.dst)) { dst.u32 = RemoteIp; memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); } else { - console_error("ARP lookup failed -> default gateway\n"); +#ifndef NDEBUG + console_error("ARP lookup failed -> default gateway :"); + printf(IPSTR " [%d]\n", IP2STR(RemoteIp), s_Port[nIndex]); +#endif return -3; } } else { @@ -268,8 +253,10 @@ int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp dst.u32 = RemoteIp; memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); } else { +#ifndef NDEBUG console_error("ARP lookup failed: "); printf(IPSTR "\n", IP2STR(RemoteIp)); +#endif return -2; } } @@ -284,11 +271,11 @@ int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp s_send_packet.ip4.chksum = net_chksum(reinterpret_cast(&s_send_packet.ip4), sizeof(s_send_packet.ip4)); #endif //UDP - s_send_packet.udp.source_port = __builtin_bswap16( s_ports_allowed[nIndex]); + s_send_packet.udp.source_port = __builtin_bswap16( s_Port[nIndex]); s_send_packet.udp.destination_port = __builtin_bswap16(RemotePort); s_send_packet.udp.len = __builtin_bswap16((nSize + UDP_HEADER_SIZE)); - net_memcpy(s_send_packet.udp.data, pData, MIN(UDP_DATA_SIZE, nSize)); + net_memcpy(s_send_packet.udp.data, pData, std::min(static_cast(UDP_DATA_SIZE), nSize)); emac_eth_send(reinterpret_cast(&s_send_packet), nSize + UDP_PACKET_HEADERS_SIZE); diff --git a/lib-network/src/params/networkparams.cpp b/lib-network/src/params/networkparams.cpp index 537b09b..03d4eaf 100644 --- a/lib-network/src/params/networkparams.cpp +++ b/lib-network/src/params/networkparams.cpp @@ -2,7 +2,7 @@ * @file networkparams.cpp * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,7 +63,6 @@ bool NetworkParams::Load() { ReadConfigFile configfile(NetworkParams::staticCallbackFunction, this); if (configfile.Read(NetworkParamsConst::FILE_NAME)) { - // There is a configuration file if (m_pNetworkParamsStore != nullptr) { m_pNetworkParamsStore->Update(&m_Params); } @@ -82,14 +81,9 @@ bool NetworkParams::Load() { void NetworkParams::Load(const char *pBuffer, uint32_t nLength) { DEBUG_ENTRY + assert(pBuffer != nullptr); assert(nLength != 0); - assert(m_pNetworkParamsStore != nullptr); - - if (m_pNetworkParamsStore == nullptr) { - DEBUG_EXIT - return; - } m_Params.nSetList = 0; @@ -97,6 +91,7 @@ void NetworkParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); + assert(m_pNetworkParamsStore != nullptr); m_pNetworkParamsStore->Update(&m_Params); DEBUG_EXIT @@ -130,9 +125,11 @@ void NetworkParams::callbackFunction(const char *pLine) { uint32_t nValue32; if (Sscan::IpAddress(pLine, NetworkParamsConst::IP_ADDRESS, nValue32) == Sscan::OK) { - if ((network::is_private_ip(nValue32)) || (nValue32 == 0)) { + if ((network::is_private_ip(nValue32)) || ((nValue32 & 0xFF) == 2U) || (nValue32 == 0)) { m_Params.nLocalIp = nValue32; m_Params.nSetList |= networkparams::Mask::IP_ADDRESS; + } else { + m_Params.nSetList &= ~networkparams::Mask::IP_ADDRESS; } return; } @@ -141,6 +138,8 @@ void NetworkParams::callbackFunction(const char *pLine) { if (network::is_netmask_valid(nValue32)) { m_Params.nNetmask = nValue32; m_Params.nSetList |= networkparams::Mask::NET_MASK; + } else { + m_Params.nSetList &= ~networkparams::Mask::NET_MASK; } return; } @@ -175,11 +174,11 @@ void NetworkParams::callbackFunction(const char *pLine) { if (Sscan::Float(pLine, NetworkParamsConst::NTP_UTC_OFFSET, fValue) == Sscan::OK) { // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - if ((static_cast(fValue) >= -12) && (static_cast(fValue) <= 14) && (fValue != defaults::NTP_UTC_OFFSET)) { + if ((static_cast(fValue) >= -12) && (static_cast(fValue) <= 14) && (static_cast(fValue) != 0)) { m_Params.fNtpUtcOffset = fValue; m_Params.nSetList |= networkparams::Mask::NTP_UTC_OFFSET; } else { - m_Params.fNtpUtcOffset = defaults::NTP_UTC_OFFSET; + m_Params.fNtpUtcOffset = 0; m_Params.nSetList &= ~networkparams::Mask::NTP_UTC_OFFSET; } return; @@ -224,10 +223,12 @@ void NetworkParams::Builder(const struct networkparams::Params *ptNetworkParams, if (ptNetworkParams != nullptr) { memcpy(&m_Params, ptNetworkParams, sizeof(struct networkparams::Params)); } else { + assert(m_pNetworkParamsStore != nullptr); m_pNetworkParamsStore->Copy(&m_Params); } PropertiesBuilder builder(NetworkParamsConst::FILE_NAME, pBuffer, nLength); + builder.AddIpAddress("secondary_ip", Network::Get()->GetSecondaryIp(), false); if (!isMaskSet(networkparams::Mask::IP_ADDRESS)) { m_Params.nLocalIp = Network::Get()->GetIp(); @@ -269,15 +270,3 @@ void NetworkParams::Builder(const struct networkparams::Params *ptNetworkParams, DEBUG_PRINTF("nSize=%d", nSize); DEBUG_EXIT } - -void NetworkParams::Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { - DEBUG_ENTRY - - if (m_pNetworkParamsStore == nullptr) { - nSize = 0; - DEBUG_EXIT - return; - } - - Builder(nullptr, pBuffer, nLength, nSize); -} diff --git a/lib-network/src/params/networkparamsdump.cpp b/lib-network/src/params/networkparamsdump.cpp index 6aaaf61..ada0652 100644 --- a/lib-network/src/params/networkparamsdump.cpp +++ b/lib-network/src/params/networkparamsdump.cpp @@ -38,44 +38,21 @@ void NetworkParams::Dump() { #ifndef NDEBUG - if (m_Params.nSetList == 0) { - return; - } - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, NetworkParamsConst::FILE_NAME); - if (isMaskSet(networkparams::Mask::DHCP)) { - printf(" %s=%d [%s]\n", NetworkParamsConst::USE_DHCP, static_cast(m_Params.bIsDhcpUsed), m_Params.bIsDhcpUsed != 0 ? "Yes" : "No"); - } - - if (isMaskSet(networkparams::Mask::IP_ADDRESS)) { - printf(" %s=" IPSTR "\n", NetworkParamsConst::IP_ADDRESS, IP2STR(m_Params.nLocalIp)); - } + debug_print_bits(m_Params.nSetList); - if (isMaskSet(networkparams::Mask::NET_MASK)) { - printf(" %s=" IPSTR "\n", NetworkParamsConst::NET_MASK, IP2STR(m_Params.nNetmask)); - } + printf(" %s=%d [%s]\n", NetworkParamsConst::USE_DHCP, static_cast(m_Params.bIsDhcpUsed), m_Params.bIsDhcpUsed != 0 ? "Yes" : "No"); + printf(" %s=" IPSTR "\n", NetworkParamsConst::IP_ADDRESS, IP2STR(m_Params.nLocalIp)); + printf(" %s=" IPSTR "\n", NetworkParamsConst::NET_MASK, IP2STR(m_Params.nNetmask)); #if defined (ESP8266) - if (isMaskSet(networkparams::Mask::DEFAULT_GATEWAY)) { - printf(" %s=" IPSTR "\n", NetworkParamsConst::DEFAULT_GATEWAY, IP2STR(m_Params.nGatewayIp)); - } - - if (isMaskSet(networkparams::Mask::NAME_SERVER)) { - printf(" %s=" IPSTR "\n", NetworkParamsConst::NAME_SERVER, IP2STR(m_Params.nNameServerIp)); - } + printf(" %s=" IPSTR "\n", NetworkParamsConst::DEFAULT_GATEWAY, IP2STR(m_Params.nGatewayIp)); + printf(" %s=" IPSTR "\n", NetworkParamsConst::NAME_SERVER, IP2STR(m_Params.nNameServerIp)); #endif - if (isMaskSet(networkparams::Mask::HOSTNAME)) { - printf(" %s=%s\n", NetworkParamsConst::HOSTNAME, m_Params.aHostName); - } - - if (isMaskSet(networkparams::Mask::NTP_SERVER)) { - printf(" %s=" IPSTR "\n", NetworkParamsConst::NTP_SERVER, IP2STR(m_Params.nNtpServerIp)); - } - - if (isMaskSet(networkparams::Mask::NTP_UTC_OFFSET)) { - printf(" %s=%1.1f\n", NetworkParamsConst::NTP_UTC_OFFSET, m_Params.fNtpUtcOffset); - } + printf(" %s=%s\n", NetworkParamsConst::HOSTNAME, m_Params.aHostName); + printf(" %s=" IPSTR "\n", NetworkParamsConst::NTP_SERVER, IP2STR(m_Params.nNtpServerIp)); + printf(" %s=%1.1f\n", NetworkParamsConst::NTP_UTC_OFFSET, m_Params.fNtpUtcOffset); #endif } diff --git a/lib-properties/.settings/language.settings.xml b/lib-properties/.settings/language.settings.xml index 5263bab..5628db3 100755 --- a/lib-properties/.settings/language.settings.xml +++ b/lib-properties/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-remoteconfig/.settings/language.settings.xml b/lib-remoteconfig/.settings/language.settings.xml index 055bc4c..97a1d3a 100644 --- a/lib-remoteconfig/.settings/language.settings.xml +++ b/lib-remoteconfig/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-remoteconfig/include/httpd/httpd.h b/lib-remoteconfig/include/httpd/httpd.h old mode 100644 new mode 100755 index 1fbdf97..dee20a5 --- a/lib-remoteconfig/include/httpd/httpd.h +++ b/lib-remoteconfig/include/httpd/httpd.h @@ -28,9 +28,10 @@ #include -#define BUFSIZE 1440 +#include "network.h" namespace http { +static constexpr uint32_t BUFSIZE = 1440; enum class Status { OK = 200, BAD_REQUEST = 400, @@ -46,14 +47,28 @@ enum class Status { enum class RequestMethod { GET, POST, UNKNOWN }; + +enum class contentTypes { + TEXT_HTML, TEXT_CSS, TEXT_JS, APPLICATION_JSON, NOT_DEFINED +}; } // namespace http class HttpDaemon { public: HttpDaemon(); - void Run(); + void Run() { + uint32_t nConnectionHandle; + m_nBytesReceived = Network::Get()->TcpRead(m_nHandle, const_cast(reinterpret_cast(&m_RequestHeaderResponse)), nConnectionHandle); + + if (__builtin_expect((m_nBytesReceived == 0), 1)) { + return; + } + + HandleRequest(nConnectionHandle); + } private: + void HandleRequest(const uint32_t nConnectionHandle); http::Status ParseRequest(); http::Status ParseMethod(char *pLine); http::Status ParseHeaderField(char *pLine); @@ -66,17 +81,21 @@ class HttpDaemon { char *m_pUri { nullptr }; char *m_pFileData { nullptr }; char *m_RequestHeaderResponse { nullptr }; + + uint32_t m_nContentLength { 0 }; + uint32_t m_nFileDataLength { 0 }; + uint32_t m_nRequestContentLength { 0 }; int32_t m_nHandle { -1 }; - int m_nBytesReceived { 0 }; + + uint32_t m_nBytesReceived { 0 }; + http::Status m_Status { http::Status::UNKNOWN_ERROR }; http::RequestMethod m_RequestMethod { http::RequestMethod::UNKNOWN }; + bool m_bContentTypeJson { false }; bool m_IsAction { false }; - uint16_t m_nContentLength { 0 }; - uint16_t m_nFileDataLength { 0 }; - uint16_t m_nRequestContentLength { 0 }; - static char m_Content[BUFSIZE]; + static char m_Content[http::BUFSIZE]; }; #endif /* HTTPD_H_ */ diff --git a/lib-remoteconfig/include/remoteconfig.h b/lib-remoteconfig/include/remoteconfig.h index dc553cb..25d76f5 100644 --- a/lib-remoteconfig/include/remoteconfig.h +++ b/lib-remoteconfig/include/remoteconfig.h @@ -198,13 +198,33 @@ class RemoteConfig { uint32_t HandleGet(void *pBuffer, uint32_t nBufferLength); void HandleSet(void *pBuffer, uint32_t nBufferLength); - void Run(); + void Run() { + if (__builtin_expect((m_bDisable), 1)) { + return; + } + +#if defined (ENABLE_TFTP_SERVER) + if (__builtin_expect((m_pTFTPFileServer != nullptr), 0)) { + m_pTFTPFileServer->Run(); + } +#endif + + uint16_t nForeignPort; + m_nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &m_nIPAddressFrom, &nForeignPort); + + if (__builtin_expect((m_nBytesReceived < 4), 1)) { + return; + } + + HandleRequest(); + } static RemoteConfig *Get() { return s_pThis; } private: + void HandleRequest(); void HandleReboot(); void HandleFactory(); void HandleList(); diff --git a/lib-remoteconfig/include/remoteconfigjson.h b/lib-remoteconfig/include/remoteconfigjson.h index ab8a969..d959dbe 100644 --- a/lib-remoteconfig/include/remoteconfigjson.h +++ b/lib-remoteconfig/include/remoteconfigjson.h @@ -2,7 +2,7 @@ * @file remoteconfig.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,12 @@ uint16_t json_get_version(char *pOutBuffer, const uint16_t nOutBufferSize); uint16_t json_get_uptime(char *pOutBuffer, const uint16_t nOutBufferSize); uint16_t json_get_display(char *pOutBuffer, const uint16_t nOutBufferSize); uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize); +namespace net { +uint16_t json_get_phystatus(char *pOutBuffer, const uint16_t nOutBufferSize); +} // namespace net +namespace dsa { +uint16_t json_get_portstatus(char *pOutBuffer, const uint16_t nOutBufferSize); +} // namespace dsa } // namespace remoteconfig #endif /* REMOTECONFIGJSON_H_ */ diff --git a/lib-remoteconfig/include/remoteconfigparams.h b/lib-remoteconfig/include/remoteconfigparams.h index dd48419..ea161ed 100644 --- a/lib-remoteconfig/include/remoteconfigparams.h +++ b/lib-remoteconfig/include/remoteconfigparams.h @@ -61,13 +61,15 @@ class RemoteConfigParamsStore { class RemoteConfigParams { public: - RemoteConfigParams(RemoteConfigParamsStore *pRemoteConfigParamsStore = nullptr); + RemoteConfigParams(RemoteConfigParamsStore *pRemoteConfigParamsStore); bool Load(); void Load(const char *pBuffer, uint32_t nLength); void Builder(const struct TRemoteConfigParams *pRemoteConfigParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); - void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { + Builder(nullptr, pBuffer, nLength, nSize); + } void Set(RemoteConfig *); diff --git a/lib-remoteconfig/include/tftp/tftpfileserver.h b/lib-remoteconfig/include/tftp/tftpfileserver.h index 6e3abe8..e5c5e40 100644 --- a/lib-remoteconfig/include/tftp/tftpfileserver.h +++ b/lib-remoteconfig/include/tftp/tftpfileserver.h @@ -2,7 +2,7 @@ * @file tftpfileserver.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -60,14 +60,14 @@ namespace tftpfileserver { class TFTPFileServer final: public TFTPDaemon { public: - TFTPFileServer (uint8_t *pBuffer, uint32_t nSize); - ~TFTPFileServer () override {} + TFTPFileServer(uint8_t *pBuffer, uint32_t nSize); + ~TFTPFileServer() override {} - bool FileOpen (const char *pFileName, TFTPMode tMode) override; - bool FileCreate (const char *pFileName, TFTPMode tMode) override; - bool FileClose () override; - size_t FileRead (void *pBuffer, size_t nCount, unsigned nBlockNumber) override; - size_t FileWrite (const void *pBuffer, size_t nCount, unsigned nBlockNumber) override; + bool FileOpen(const char *pFileName, tftp::Mode mode) override; + bool FileCreate(const char *pFileName, tftp::Mode mode) override; + bool FileClose() override; + size_t FileRead(void *pBuffer, size_t nCount, unsigned nBlockNumber) override; + size_t FileWrite(const void *pBuffer, size_t nCount, unsigned nBlockNumber) override; void Exit() override; uint32_t GetFileSize() const { diff --git a/lib-remoteconfig/src/remoteconfig.cpp b/lib-remoteconfig/src/remoteconfig.cpp index b0258a7..b3f9685 100644 --- a/lib-remoteconfig/src/remoteconfig.cpp +++ b/lib-remoteconfig/src/remoteconfig.cpp @@ -198,7 +198,6 @@ namespace get { enum class Command { REBOOT, LIST, - LIST_BROADCAST, UPTIME, VERSION, DISPLAY, @@ -220,7 +219,6 @@ enum class Command { const struct RemoteConfig::Commands RemoteConfig::s_GET[] = { { &RemoteConfig::HandleReboot, "reboot##", 8, false }, { &RemoteConfig::HandleList, "list#", 5, false }, - { &RemoteConfig::HandleList, "list#*", 6, false }, { &RemoteConfig::HandleUptime, "uptime#", 7, false }, { &RemoteConfig::HandleVersion, "version#", 8, false }, { &RemoteConfig::HandleDisplayGet, "display#", 8, false }, @@ -315,26 +313,9 @@ void RemoteConfig::SetDisplayName(const char *pDisplayName) { DEBUG_EXIT } -void RemoteConfig::Run() { - if (__builtin_expect((m_bDisable), 1)) { - return; - } - -#if defined (ENABLE_TFTP_SERVER) - if (__builtin_expect((m_pTFTPFileServer != nullptr), 0)) { - m_pTFTPFileServer->Run(); - } -#endif - - uint16_t nForeignPort; - m_nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &m_nIPAddressFrom, &nForeignPort); - - if (__builtin_expect((m_nBytesReceived < 4), 1)) { - return; - } - +void RemoteConfig::HandleRequest() { #ifndef NDEBUG - debug_dump(s_pUdpBuffer, m_nBytesReceived); + debug_dump(s_pUdpBuffer, static_cast(m_nBytesReceived)); #endif if (s_pUdpBuffer[m_nBytesReceived - 1] == '\n') { @@ -424,8 +405,6 @@ void RemoteConfig::HandleVersion() { DEBUG_ENTRY const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::VERSION)].nLength; - DEBUG_PRINTF("%u:%u", m_nBytesReceived, nCmdLength); - if (m_nBytesReceived == nCmdLength) { const auto *p = FirmwareVersion::Get()->GetPrint(); const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "version:%s", p); @@ -441,6 +420,12 @@ void RemoteConfig::HandleList() { DEBUG_ENTRY const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::LIST)].nLength; + + if (m_nBytesReceived != nCmdLength) { + DEBUG_EXIT + return; + } + auto *pListResponse = &s_pUdpBuffer[nCmdLength + 2U]; const auto nListResponseBufferLength = remoteconfig::udp::BUFFER_SIZE - (nCmdLength + 2U); int32_t nListLength; @@ -460,18 +445,7 @@ void RemoteConfig::HandleList() { m_nActiveOutputs); } - if (m_nBytesReceived == nCmdLength) { - Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } else if (m_nBytesReceived == nCmdLength + 1) { - DEBUG_PRINTF("%c", nCmdLength + 1); - if (s_pUdpBuffer[nCmdLength + 1] == '*') { - Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), network::IP4_BROADCAST, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } - } + Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -534,7 +508,7 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { if (pBuffer == nullptr) { Network::Get()->SendTo(m_nHandle, "ERROR#?get\n", 11, m_nIPAddressFrom, remoteconfig::udp::PORT); } else { - memcpy(pBuffer, "ERROR#?get\n", std::min(11U, nBufferLength)); + memcpy(pBuffer, "ERROR#?get\n", std::min(static_cast(11), nBufferLength)); } DEBUG_EXIT return 12; diff --git a/lib-remoteconfig/src/remoteconfigjson.cpp b/lib-remoteconfig/src/remoteconfigjson.cpp index 988240d..8810391 100644 --- a/lib-remoteconfig/src/remoteconfigjson.cpp +++ b/lib-remoteconfig/src/remoteconfigjson.cpp @@ -1,8 +1,8 @@ /** - * @file remoteconfig.cpp; + * @file remoteconfigjson.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,11 +26,11 @@ #include #include +#include "remoteconfig.h" #include "hardware.h" +#include "network.h" #include "display.h" #include "firmwareversion.h" -#include "network.h" -#include "remoteconfig.h" namespace remoteconfig { @@ -91,12 +91,15 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { "\"ldisplay.txt\":\"Display\"," "\"tcnet.txt\":\"TCNet\"," "\"gps.txt\":\"GPS\"," + "\"etc.txt\":\"ETC gateway\"," #endif #if defined(NODE_SHOWFILE) "\"show.txt\":\"Showfile\"," #endif -#if defined(NODE_DDP_DISPLAY) - "\"ddpdisp.txt\":\"DDP Display\"," +#if defined(NODE_NODE) + "\"node.txt\":\"Node\"," + "\"artnet.txt\":\"Art-Net\"," + "\"e131.txt\":\"sACN E1.31\"," #endif #if defined (OUTPUT_DMX_SEND) "\"params.txt\":\"DMX Transmit\"," @@ -104,6 +107,9 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { #if defined (OUTPUT_DMX_PIXEL) "\"devices.txt\":\"DMX Pixel\"," #endif +#if defined (OUTPUT_DMX_TLC59711) + "\"devices.txt\":\"DMX TLC59711\"," +#endif #if defined (OUTPUT_DMX_MONITOR) "\"mon.txt\":\"DMX Monitor\"," #endif @@ -113,9 +119,20 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { #if defined (OUTPUT_RGB_PANEL) "\"rgbpanel.txt\":\"RGB panel\"," #endif +#if defined (OUTPUT_DMX_STEPPER) + "\"sparkfun.txt\":\"SparkFun\"," + "\"motor0.txt\":\"Stepper 1\"," + "\"motor1.txt\":\"Stepper 2\"," + "\"motor2.txt\":\"Stepper 3\"," + "\"motor3.txt\":\"Stepper 4\"," + "\"motor4.txt\":\"Stepper 5\"," + "\"motor5.txt\":\"Stepper 6\"," + "\"motor6.txt\":\"Stepper 7\"," + "\"motor7.txt\":\"Stepper 8\"," +#endif #if defined (RDM_RESPONDER) + "\"rdm_device.txt\":\"RDM Device\"," "\"sensors.txt\":\"RDM Sensors\"," - "\"subdev.txt\":\"RDM Sub devices\"," #endif #if defined(DISPLAY_UDF) "\"display.txt\":\"Display UDF\"," @@ -126,5 +143,4 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { )); return nLength; } - -} +} // namespace remoteconfig diff --git a/lib-remoteconfig/src/remoteconfigparams.cpp b/lib-remoteconfig/src/remoteconfigparams.cpp index 112ab56..89945d7 100644 --- a/lib-remoteconfig/src/remoteconfigparams.cpp +++ b/lib-remoteconfig/src/remoteconfigparams.cpp @@ -69,9 +69,10 @@ bool RemoteConfigParams::Load() { } void RemoteConfigParams::Load(const char* pBuffer, uint32_t nLength) { + DEBUG_ENTRY + assert(pBuffer != nullptr); assert(nLength != 0); - assert(m_pRemoteConfigParamsStore != nullptr); m_tRemoteConfigParams.nSetList = 0; @@ -79,7 +80,10 @@ void RemoteConfigParams::Load(const char* pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); + assert(m_pRemoteConfigParamsStore != nullptr); m_pRemoteConfigParamsStore->Update(&m_tRemoteConfigParams); + + DEBUG_EXIT } void RemoteConfigParams::SetBool(const uint8_t nValue, const uint32_t nMask) { @@ -136,6 +140,7 @@ void RemoteConfigParams::Builder(const struct TRemoteConfigParams *pRemoteConfig if (pRemoteConfigParams != nullptr) { memcpy(&m_tRemoteConfigParams, pRemoteConfigParams, sizeof(struct TRemoteConfigParams)); } else { + assert(m_pRemoteConfigParamsStore != nullptr); m_pRemoteConfigParamsStore->Copy(&m_tRemoteConfigParams); } @@ -155,20 +160,6 @@ void RemoteConfigParams::Builder(const struct TRemoteConfigParams *pRemoteConfig return; } -void RemoteConfigParams::Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { - DEBUG_ENTRY - - if (m_pRemoteConfigParamsStore == nullptr) { - nSize = 0; - DEBUG_EXIT - return; - } - - Builder(nullptr, pBuffer, nLength, nSize); - - return; -} - void RemoteConfigParams::Set(RemoteConfig* pRemoteConfig) { assert(pRemoteConfig != nullptr); diff --git a/lib-remoteconfig/src/remoteconfigstatic.cpp b/lib-remoteconfig/src/remoteconfigstatic.cpp index 905bc99..8323572 100644 --- a/lib-remoteconfig/src/remoteconfigstatic.cpp +++ b/lib-remoteconfig/src/remoteconfigstatic.cpp @@ -45,10 +45,10 @@ const RemoteConfig::Txt RemoteConfig::s_TXT[] = { { &RemoteConfig::HandleGetDisplayTxt, &RemoteConfig::HandleSetDisplayTxt, "display.txt", 11, Store::DISPLAYUDF }, #endif #if defined (NODE_ARTNET) - { &RemoteConfig::HandleGetArtnetTxt, &RemoteConfig::HandleSetArtnetTxt, "artnet.txt", 10, Store::ARTNET }, + { &RemoteConfig::HandleGetArtnetTxt, &RemoteConfig::HandleSetArtnetTxt, "artnet.txt", 10, Store::NODE }, #endif #if defined (NODE_E131) - { &RemoteConfig::HandleGetE131Txt, &RemoteConfig::HandleSetE131Txt, "e131.txt", 8, Store::E131 }, + { &RemoteConfig::HandleGetE131Txt, &RemoteConfig::HandleSetE131Txt, "e131.txt", 8, Store::NODE }, #endif #if defined (NODE_LTC_SMPTE) { &RemoteConfig::HandleGetLtcTxt, &RemoteConfig::HandleSetLtcTxt, "ltc.txt", 7, Store::LTC }, diff --git a/lib-remoteconfig/src/tftp/tftpfileserver.cpp b/lib-remoteconfig/src/tftp/tftpfileserver.cpp index 2e115ea..75d9b54 100644 --- a/lib-remoteconfig/src/tftp/tftpfileserver.cpp +++ b/lib-remoteconfig/src/tftp/tftpfileserver.cpp @@ -56,19 +56,19 @@ void TFTPFileServer::Exit() { } -bool TFTPFileServer::FileOpen(__attribute__((unused)) const char* pFileName, __attribute__((unused)) TFTPMode tMode) { +bool TFTPFileServer::FileOpen(__attribute__((unused)) const char* pFileName, __attribute__((unused)) tftp::Mode tMode) { DEBUG_ENTRY DEBUG_EXIT return false; } -bool TFTPFileServer::FileCreate(const char* pFileName, TFTPMode mode) { +bool TFTPFileServer::FileCreate(const char* pFileName, tftp::Mode mode) { DEBUG_ENTRY assert(pFileName != nullptr); - if (mode != TFTPMode::BINARY) { + if (mode != tftp::Mode::BINARY) { DEBUG_EXIT return false; } diff --git a/udp_send/.settings/language.settings.xml b/udp_send/.settings/language.settings.xml index 11cb7a3..6daeab9 100644 --- a/udp_send/.settings/language.settings.xml +++ b/udp_send/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - +