From b5213c13dd2aeab65dbd9ef0f2db5ae6cc3ec95c Mon Sep 17 00:00:00 2001 From: robert Date: Wed, 2 Aug 2023 07:46:06 -0400 Subject: [PATCH 1/6] SAME54 Ethernet driver --- examples/microchip/same54/Makefile | 56 +++++ examples/microchip/same54/hal.h | 178 ++++++++++++++ examples/microchip/same54/link.ld | 25 ++ examples/microchip/same54/main.c | 77 ++++++ examples/microchip/same54/mongoose.c | 1 + examples/microchip/same54/mongoose.h | 1 + examples/microchip/same54/net.c | 1 + examples/microchip/same54/net.h | 1 + examples/microchip/same54/packed_fs.c | 1 + examples/microchip/same54/startup.c | 332 ++++++++++++++++++++++++++ examples/microchip/same54/syscalls.c | 89 +++++++ mongoose.c | 286 ++++++++++++++++++++++ mongoose.h | 12 + src/tcpip/driver_same54.c | 282 ++++++++++++++++++++++ src/tcpip/driver_same54.h | 11 + src/tcpip/tcpip.h | 1 + 16 files changed, 1354 insertions(+) create mode 100644 examples/microchip/same54/Makefile create mode 100644 examples/microchip/same54/hal.h create mode 100644 examples/microchip/same54/link.ld create mode 100644 examples/microchip/same54/main.c create mode 120000 examples/microchip/same54/mongoose.c create mode 120000 examples/microchip/same54/mongoose.h create mode 120000 examples/microchip/same54/net.c create mode 120000 examples/microchip/same54/net.h create mode 120000 examples/microchip/same54/packed_fs.c create mode 100644 examples/microchip/same54/startup.c create mode 100644 examples/microchip/same54/syscalls.c create mode 100644 src/tcpip/driver_same54.c create mode 100644 src/tcpip/driver_same54.h diff --git a/examples/microchip/same54/Makefile b/examples/microchip/same54/Makefile new file mode 100644 index 00000000..646661ae --- /dev/null +++ b/examples/microchip/same54/Makefile @@ -0,0 +1,56 @@ +CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion +CFLAGS += -Wformat-truncation -fno-common -Wconversion +CFLAGS += -g -O2 -ffunction-sections -fdata-sections +CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include +CFLAGS += -D__SAME54P20A__ -Icmsis_sam/include #-Icmsis_sam/xc32/include +#CFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 +CFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16 +LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map + +SOURCES = main.c syscalls.c startup.c +#SOURCES += cmsis_sam/xc32/ATSAME54P20A/startup_atsame54p20a.c + +SOURCES += mongoose.c net.c packed_fs.c +CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 +CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA) + +VCON_API_KEY=IBrJL5K4arSGMiAXbUKWdG6I2gM + +ifeq ($(OS),Windows_NT) + RM = cmd /C del /Q /F +else + RM = rm -rf +endif + +build: firmware.bin + +firmware.elf: cmsis_core cmsis_sam hal.h link.ld Makefile $(SOURCES) + arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@ + +firmware.bin: firmware.elf + arm-none-eabi-objcopy -O binary $< $@ + +flash: firmware.bin + bossac -p /dev/cu.usb* -w -v -b $< + +cmsis_core: + git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@ + +cmsis_sam: + curl -sL https://packs.download.microchip.com/Microchip.SAME54_DFP.3.8.234.pack -o $@.zip + mkdir $@ && cd $@ && unzip ../$@.zip +# git clone --depth 1 -b master https://github.com/modm-io/cmsis-header-sam $@ + +clean: + $(RM) firmware.* cmsis_* *.zip + +# Automated test via https://vcon.io/automated-firmware-tests/. Set VCON_API_KEY and update DEVICE_URL +DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/9 +fota: CFLAGS += -DUART_DEBUG=USART1 +fota: firmware.bin + curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$< +test: fota + curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt + egrep '^tick:.*CPU 180 MHz' /tmp/output.txt +watch: fota + curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=999 diff --git a/examples/microchip/same54/hal.h b/examples/microchip/same54/hal.h new file mode 100644 index 00000000..eebe6bd4 --- /dev/null +++ b/examples/microchip/same54/hal.h @@ -0,0 +1,178 @@ +// Copyright (c) 2022 Cesanta Software Limited +// SPDX-License-Identifier: MIT +// +// https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM-D5x-E5x-Family-Data-Sheet-DS60001507.pdf +// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf + +#ifndef LED_PIN +#define LED_PIN PIN('C', 18) +#endif + +#ifndef BUTTON_PIN +#define BUTTON_PIN PIN('B', 31) +#endif + +#ifndef UART_DEBUG +#define UART_DEBUG USART1 +#endif + +#pragma once +#include + +#include +#include +#include +#include + +#define BIT(x) (1UL << (x)) +#define SETBITS(R, CLEARMASK, SETMASK) (R) = ((R) & ~(CLEARMASK)) | (SETMASK) +#define PIN(bank, num) ((((bank) - 'A') << 8) | (num)) +#define PINNO(pin) (pin & 255) +#define PINBANK(pin) (pin >> 8) + +static inline void spin(volatile uint32_t count) { + while (count--) (void) 0; +} + +static inline uint32_t clock_sys_freq(void) { + return 48000000U; +} + +enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG }; +enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN }; +enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_HIGH, GPIO_SPEED_INSANE }; +enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN }; +#define GPIO(N) ((port_group_registers_t *) (PORT_BASE_ADDRESS + 0x80 * (N))) +typedef port_group_registers_t GPIO_TypeDef; +static inline GPIO_TypeDef *gpio_bank(uint16_t pin) { + return GPIO(PINBANK(pin)); +} +static inline void gpio_toggle(uint16_t pin) { + gpio_bank(pin)->PORT_OUTTGL = BIT(PINNO(pin)); +} +static inline bool gpio_read(uint16_t pin) { + return gpio_bank(pin)->PORT_IN & BIT(PINNO(pin)); +} +static inline void gpio_write(uint16_t pin, bool val) { + GPIO_TypeDef *gpio = gpio_bank(pin); + if (val) { + gpio->PORT_OUTSET = BIT(PINNO(pin)); + } else { + gpio->PORT_OUTCLR = BIT(PINNO(pin)); + } +} +static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type, + uint8_t speed, uint8_t pull, uint8_t af) { + (void) type, (void) speed, (void) pull, (void) af; + GPIO_TypeDef *gpio = gpio_bank(pin); + uint32_t mask = BIT(PINNO(pin)); + MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; + if (mode == GPIO_MODE_INPUT) { + gpio->PORT_DIRCLR = mask; + } else { + gpio->PORT_DIRSET = mask; + } +} +static inline void gpio_input(uint16_t pin) { + gpio_init(pin, GPIO_MODE_INPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, + GPIO_PULL_NONE, 0); +} +static inline void gpio_output(uint16_t pin) { + gpio_init(pin, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, + GPIO_PULL_NONE, 0); +} + +typedef sercom_usart_int_registers_t USART_TypeDef; +#define USART1 ((USART_TypeDef *) SERCOM0_BASE_ADDRESS) +#define USART2 ((USART_TypeDef *) SERCOM1_BASE_ADDRESS) +#define USART3 ((USART_TypeDef *) SERCOM2_BASE_ADDRESS) +static inline bool uart_init(USART_TypeDef *uart, unsigned long baud) { + uint16_t rx = 0, tx = 0; // Pins + uint8_t rx_mux = 0, tx_mux = 0; + if (uart == USART1) { + MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM0_Msk; + GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_CORE] = + GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN_Msk; + GCLK_REGS->GCLK_PCHCTRL[SERCOM0_GCLK_ID_SLOW] = + GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN_Msk; + tx = PIN('A', 4), rx = PIN('A', 5); + rx_mux = MUX_PA05D_SERCOM0_PAD1, tx_mux = MUX_PA04D_SERCOM0_PAD0; + } else if (uart == USART2) { + MCLK_REGS->MCLK_APBAMASK |= MCLK_APBAMASK_SERCOM1_Msk; + tx = PIN('C', 27), rx = PIN('C', 28); + } else if (uart == USART3) { + MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_SERCOM2_Msk; + tx = PIN('A', 9), rx = PIN('A', 8); + } else { + return false; + } + gpio_bank(rx)->PORT_WRCONFIG = + PORT_WRCONFIG_PMUX(rx_mux) | PORT_WRCONFIG_WRPMUX(1) | + PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(rx)); + gpio_bank(tx)->PORT_WRCONFIG = + PORT_WRCONFIG_PMUX(tx_mux) | PORT_WRCONFIG_WRPMUX(1) | + PORT_WRCONFIG_PMUXEN(1) | PORT_WRCONFIG_WRPINCFG(1) | BIT(PINNO(tx)); + uart->SERCOM_CTRLA = SERCOM_USART_INT_CTRLA_DORD(1) | + SERCOM_USART_INT_CTRLA_MODE(1 /* INT_CLK */) | + SERCOM_USART_INT_CTRLA_RXPO(1 /* PAD1 */) | + SERCOM_USART_INT_CTRLA_TXPO(0 /* PAD0 */) | + SERCOM_USART_INT_CTRLA_SAMPR(1); + uart->SERCOM_BAUD = (uint16_t) (clock_sys_freq() / (16 * baud)); + uart->SERCOM_CTRLB = SERCOM_USART_INT_CTRLB_RXEN(1) | + SERCOM_USART_INT_CTRLB_TXEN(1) | + SERCOM_USART_INT_CTRLB_CHSIZE(0); + while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_CTRLB_Msk) spin(1); + uart->SERCOM_CTRLA |= SERCOM_USART_INT_CTRLA_ENABLE(1); + while (uart->SERCOM_SYNCBUSY & SERCOM_USART_INT_SYNCBUSY_ENABLE_Msk) spin(1); + return true; +} +static inline void uart_write_byte(USART_TypeDef *uart, uint8_t byte) { + while (!(uart->SERCOM_INTFLAG & SERCOM_USART_INT_INTFLAG_DRE_Msk)) spin(1); + uart->SERCOM_DATA = byte; +} +static inline void uart_write_buf(USART_TypeDef *uart, char *buf, size_t len) { + while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++); +} +static inline bool uart_read_ready(USART_TypeDef *uart) { + return (uart->SERCOM_INTFLAG & SERCOM_USART_EXT_INTFLAG_RXC_Msk); +} +static inline uint8_t uart_read_byte(USART_TypeDef *uart) { + return (uint8_t) (uart->SERCOM_DATA & 255U); +} + +static inline void rng_init(void) { + MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_TRNG_Msk; + TRNG_REGS->TRNG_CTRLA = TRNG_CTRLA_ENABLE_Msk; +} +static inline uint32_t rng_read(void) { + while ((TRNG_REGS->TRNG_INTFLAG & TRNG_INTFLAG_DATARDY_Msk) == 0) spin(1); + return TRNG_REGS->TRNG_DATA; +} + +#define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 39.1 + +// Helper macro for MAC generation +#define GENERATE_LOCALLY_ADMINISTERED_MAC() \ + { \ + 2, UUID[0] ^ UUID[1], UUID[2] ^ UUID[3], UUID[4] ^ UUID[5], \ + UUID[6] ^ UUID[7] ^ UUID[8], UUID[9] ^ UUID[10] ^ UUID[11] \ + } + +static inline bool timer_expired(volatile uint64_t *t, uint64_t prd, + uint64_t now) { + if (now + prd < *t) *t = 0; // Time wrapped? Reset timer + if (*t == 0) *t = now + prd; // Firt poll? Set expiration + if (*t > now) return false; // Not expired yet, return + *t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time + return true; // Expired, return true +} + +static inline void clock_init(void) { + SCB->CPACR |= (15U << 20); // Enable FPU + SysTick_Config(clock_sys_freq() / 1000); // Sys tick every 1ms +} + +static inline void gpio_set_irq_handler(uint16_t pin, void (*fn)(void *), + void *arg) { + (void) pin, (void) fn, (void) arg; +} diff --git a/examples/microchip/same54/link.ld b/examples/microchip/same54/link.ld new file mode 100644 index 00000000..f66bbb90 --- /dev/null +++ b/examples/microchip/same54/link.ld @@ -0,0 +1,25 @@ +ENTRY(Reset_Handler); +MEMORY { + flash(rx) : ORIGIN = 0x00000000, LENGTH = 1024k + sram(rwx) : ORIGIN = 0x20000000, LENGTH = 256k +} +_estack = ORIGIN(sram) + LENGTH(sram); + +SECTIONS { + .vectors : { FILL(256) KEEP(*(.vectors)) } > flash + .text : { *(.text*) } > flash + .rodata : { *(.rodata*) } > flash + + .data : { + _sdata = .; + *(.first_data) + *(.data SORT(.data.*)) + _edata = .; + } > sram AT > flash + _sidata = LOADADDR(.data); + + .bss : { _sbss = .; *(.bss SORT(.bss.*) COMMON) _ebss = .; } > sram + + . = ALIGN(8); + _end = .; +} diff --git a/examples/microchip/same54/main.c b/examples/microchip/same54/main.c new file mode 100644 index 00000000..2bf7a697 --- /dev/null +++ b/examples/microchip/same54/main.c @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2022-2023 Cesanta Software Limited +// SPDX-License-Identifier: MIT + +#include "hal.h" +#include "mongoose.h" +#include "net.h" + +#define BLINK_PERIOD_MS 500 // LED blinking period in millis +#define LOG_PERIOD_MS 1000 // Info log period in millis + +void SystemInit(void) { // Called automatically by startup code + clock_init(); +} + +static volatile uint64_t s_ticks; // Milliseconds since boot +void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms + s_ticks++; +} + +uint64_t mg_millis(void) { // Let Mongoose use our uptime function + return s_ticks; // Return number of milliseconds since boot +} + +void mg_random(void *buf, size_t len) { // Use on-board RNG + for (size_t n = 0; n < len; n += sizeof(uint32_t)) { + uint32_t r = rng_read(); + memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r)); + } +} + +static void timer_fn(void *arg) { + struct mg_tcpip_if *ifp = arg; // show network stats + const char *names[] = {"down", "up", "req", "ready"}; + MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", + names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent, + ifp->ndrop, ifp->nerr)); +} + +int main(void) { + gpio_input(BUTTON_PIN); + gpio_output(LED_PIN); + uart_init(UART_DEBUG, 115200); + rng_init(); + + MG_INFO(("Starting, CPU freq %g MHz", (double) clock_sys_freq() / 1000000)); + + struct mg_mgr mgr; // Initialise + mg_mgr_init(&mgr); // Mongoose event manager + mg_log_set(MG_LL_DEBUG); // Set log level + + // Initialise Mongoose network stack + struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 4}; + struct mg_tcpip_if mif = {.mac = {0x02, 0x14, 0x30, 0x00, 0x1a, 0x00}, + // Uncomment below for static configuration: + // .ip = mg_htonl(MG_U32(192, 168, 0, 223)), + // .mask = mg_htonl(MG_U32(255, 255, 255, 0)), + // .gw = mg_htonl(MG_U32(192, 168, 0, 1)), + .driver = &mg_tcpip_driver_same54, + .driver_data = &driver_data}; + mg_tcpip_init(&mgr, &mif); + mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif); + + MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac)); + while (mif.state != MG_TCPIP_STATE_READY) { + mg_mgr_poll(&mgr, 0); + } + + MG_INFO(("Initialising application...")); + web_init(&mgr); + + MG_INFO(("Starting event loop")); + for (;;) { + mg_mgr_poll(&mgr, 0); + } + + return 0; +} \ No newline at end of file diff --git a/examples/microchip/same54/mongoose.c b/examples/microchip/same54/mongoose.c new file mode 120000 index 00000000..5e522bbc --- /dev/null +++ b/examples/microchip/same54/mongoose.c @@ -0,0 +1 @@ +../../../mongoose.c \ No newline at end of file diff --git a/examples/microchip/same54/mongoose.h b/examples/microchip/same54/mongoose.h new file mode 120000 index 00000000..ee4ac823 --- /dev/null +++ b/examples/microchip/same54/mongoose.h @@ -0,0 +1 @@ +../../../mongoose.h \ No newline at end of file diff --git a/examples/microchip/same54/net.c b/examples/microchip/same54/net.c new file mode 120000 index 00000000..fe0e6f06 --- /dev/null +++ b/examples/microchip/same54/net.c @@ -0,0 +1 @@ +../../device-dashboard/net.c \ No newline at end of file diff --git a/examples/microchip/same54/net.h b/examples/microchip/same54/net.h new file mode 120000 index 00000000..9de896ef --- /dev/null +++ b/examples/microchip/same54/net.h @@ -0,0 +1 @@ +../../device-dashboard/net.h \ No newline at end of file diff --git a/examples/microchip/same54/packed_fs.c b/examples/microchip/same54/packed_fs.c new file mode 120000 index 00000000..e06bf092 --- /dev/null +++ b/examples/microchip/same54/packed_fs.c @@ -0,0 +1 @@ +../../device-dashboard/packed_fs.c \ No newline at end of file diff --git a/examples/microchip/same54/startup.c b/examples/microchip/same54/startup.c new file mode 100644 index 00000000..28ef30e2 --- /dev/null +++ b/examples/microchip/same54/startup.c @@ -0,0 +1,332 @@ +// SPDX-FileCopyrightText: 2022-2023 Cesanta Software Limited +// SPDX-License-Identifier: MIT + +#include "hal.h" + +void Reset_Handler(void); // Defined below +void Dummy_Handler(void); // Defined below +void SysTick_Handler(void); // Defined in main.c +void SystemInit(void); // Defined in main.c, called by reset handler +void _estack(void); // Defined in link.ld + +#define WEAK_ALIAS __attribute__((weak, alias("Default_Handler"))) + +WEAK_ALIAS void NMI_Handler(void); +WEAK_ALIAS void HardFault_Handler(void); +WEAK_ALIAS void MemoryManagement_Handler(void); +WEAK_ALIAS void BusFault_Handler(void); +WEAK_ALIAS void UsageFault_Handler(void); +WEAK_ALIAS void SVCall_Handler(void); +WEAK_ALIAS void DebugMonitor_Handler(void); +WEAK_ALIAS void PendSV_Handler(void); +WEAK_ALIAS void SysTick_Handler(void); + +WEAK_ALIAS void PM_Handler(void); +WEAK_ALIAS void MCLK_Handler(void); +WEAK_ALIAS void OSCCTRL_XOSC0_Handler(void); +WEAK_ALIAS void OSCCTRL_XOSC1_Handler(void); +WEAK_ALIAS void OSCCTRL_DFLL_Handler(void); +WEAK_ALIAS void OSCCTRL_DPLL0_Handler(void); +WEAK_ALIAS void OSCCTRL_DPLL1_Handler(void); +WEAK_ALIAS void OSC32KCTRL_Handler(void); +WEAK_ALIAS void SUPC_OTHER_Handler(void); +WEAK_ALIAS void SUPC_BODDET_Handler(void); +WEAK_ALIAS void WDT_Handler(void); +WEAK_ALIAS void RTC_Handler(void); +WEAK_ALIAS void EIC_EXTINT_0_Handler(void); +WEAK_ALIAS void EIC_EXTINT_1_Handler(void); +WEAK_ALIAS void EIC_EXTINT_2_Handler(void); +WEAK_ALIAS void EIC_EXTINT_3_Handler(void); +WEAK_ALIAS void EIC_EXTINT_4_Handler(void); +WEAK_ALIAS void EIC_EXTINT_5_Handler(void); +WEAK_ALIAS void EIC_EXTINT_6_Handler(void); +WEAK_ALIAS void EIC_EXTINT_7_Handler(void); +WEAK_ALIAS void EIC_EXTINT_8_Handler(void); +WEAK_ALIAS void EIC_EXTINT_9_Handler(void); +WEAK_ALIAS void EIC_EXTINT_10_Handler(void); +WEAK_ALIAS void EIC_EXTINT_11_Handler(void); +WEAK_ALIAS void EIC_EXTINT_12_Handler(void); +WEAK_ALIAS void EIC_EXTINT_13_Handler(void); +WEAK_ALIAS void EIC_EXTINT_14_Handler(void); +WEAK_ALIAS void EIC_EXTINT_15_Handler(void); +WEAK_ALIAS void FREQM_Handler(void); +WEAK_ALIAS void NVMCTRL_0_Handler(void); +WEAK_ALIAS void NVMCTRL_1_Handler(void); +WEAK_ALIAS void DMAC_0_Handler(void); +WEAK_ALIAS void DMAC_1_Handler(void); +WEAK_ALIAS void DMAC_2_Handler(void); +WEAK_ALIAS void DMAC_3_Handler(void); +WEAK_ALIAS void DMAC_OTHER_Handler(void); +WEAK_ALIAS void EVSYS_0_Handler(void); +WEAK_ALIAS void EVSYS_1_Handler(void); +WEAK_ALIAS void EVSYS_2_Handler(void); +WEAK_ALIAS void EVSYS_3_Handler(void); +WEAK_ALIAS void EVSYS_OTHER_Handler(void); +WEAK_ALIAS void PAC_Handler(void); +WEAK_ALIAS void RAMECC_Handler(void); +WEAK_ALIAS void SERCOM0_0_Handler(void); +WEAK_ALIAS void SERCOM0_1_Handler(void); +WEAK_ALIAS void SERCOM0_2_Handler(void); +WEAK_ALIAS void SERCOM0_OTHER_Handler(void); +WEAK_ALIAS void SERCOM1_0_Handler(void); +WEAK_ALIAS void SERCOM1_1_Handler(void); +WEAK_ALIAS void SERCOM1_2_Handler(void); +WEAK_ALIAS void SERCOM1_OTHER_Handler(void); +WEAK_ALIAS void SERCOM2_0_Handler(void); +WEAK_ALIAS void SERCOM2_1_Handler(void); +WEAK_ALIAS void SERCOM2_2_Handler(void); +WEAK_ALIAS void SERCOM2_OTHER_Handler(void); +WEAK_ALIAS void SERCOM3_0_Handler(void); +WEAK_ALIAS void SERCOM3_1_Handler(void); +WEAK_ALIAS void SERCOM3_2_Handler(void); +WEAK_ALIAS void SERCOM3_OTHER_Handler(void); +WEAK_ALIAS void SERCOM4_0_Handler(void); +WEAK_ALIAS void SERCOM4_1_Handler(void); +WEAK_ALIAS void SERCOM4_2_Handler(void); +WEAK_ALIAS void SERCOM4_OTHER_Handler(void); +WEAK_ALIAS void SERCOM5_0_Handler(void); +WEAK_ALIAS void SERCOM5_1_Handler(void); +WEAK_ALIAS void SERCOM5_2_Handler(void); +WEAK_ALIAS void SERCOM5_OTHER_Handler(void); +WEAK_ALIAS void SERCOM6_0_Handler(void); +WEAK_ALIAS void SERCOM6_1_Handler(void); +WEAK_ALIAS void SERCOM6_2_Handler(void); +WEAK_ALIAS void SERCOM6_OTHER_Handler(void); +WEAK_ALIAS void SERCOM7_0_Handler(void); +WEAK_ALIAS void SERCOM7_1_Handler(void); +WEAK_ALIAS void SERCOM7_2_Handler(void); +WEAK_ALIAS void SERCOM7_OTHER_Handler(void); +WEAK_ALIAS void CAN0_Handler(void); +WEAK_ALIAS void CAN1_Handler(void); +WEAK_ALIAS void USB_OTHER_Handler(void); +WEAK_ALIAS void USB_SOF_HSOF_Handler(void); +WEAK_ALIAS void USB_TRCPT0_Handler(void); +WEAK_ALIAS void USB_TRCPT1_Handler(void); +WEAK_ALIAS void GMAC_Handler(void); +WEAK_ALIAS void TCC0_OTHER_Handler(void); +WEAK_ALIAS void TCC0_MC0_Handler(void); +WEAK_ALIAS void TCC0_MC1_Handler(void); +WEAK_ALIAS void TCC0_MC2_Handler(void); +WEAK_ALIAS void TCC0_MC3_Handler(void); +WEAK_ALIAS void TCC0_MC4_Handler(void); +WEAK_ALIAS void TCC0_MC5_Handler(void); +WEAK_ALIAS void TCC1_OTHER_Handler(void); +WEAK_ALIAS void TCC1_MC0_Handler(void); +WEAK_ALIAS void TCC1_MC1_Handler(void); +WEAK_ALIAS void TCC1_MC2_Handler(void); +WEAK_ALIAS void TCC1_MC3_Handler(void); +WEAK_ALIAS void TCC2_OTHER_Handler(void); +WEAK_ALIAS void TCC2_MC0_Handler(void); +WEAK_ALIAS void TCC2_MC1_Handler(void); +WEAK_ALIAS void TCC2_MC2_Handler(void); +WEAK_ALIAS void TCC3_OTHER_Handler(void); +WEAK_ALIAS void TCC3_MC0_Handler(void); +WEAK_ALIAS void TCC3_MC1_Handler(void); +WEAK_ALIAS void TCC4_OTHER_Handler(void); +WEAK_ALIAS void TCC4_MC0_Handler(void); +WEAK_ALIAS void TCC4_MC1_Handler(void); +WEAK_ALIAS void TC0_Handler(void); +WEAK_ALIAS void TC1_Handler(void); +WEAK_ALIAS void TC2_Handler(void); +WEAK_ALIAS void TC3_Handler(void); +WEAK_ALIAS void TC4_Handler(void); +WEAK_ALIAS void TC5_Handler(void); +WEAK_ALIAS void TC6_Handler(void); +WEAK_ALIAS void TC7_Handler(void); +WEAK_ALIAS void PDEC_OTHER_Handler(void); +WEAK_ALIAS void PDEC_MC0_Handler(void); +WEAK_ALIAS void PDEC_MC1_Handler(void); +WEAK_ALIAS void ADC0_OTHER_Handler(void); +WEAK_ALIAS void ADC0_RESRDY_Handler(void); +WEAK_ALIAS void ADC1_OTHER_Handler(void); +WEAK_ALIAS void ADC1_RESRDY_Handler(void); +WEAK_ALIAS void AC_Handler(void); +WEAK_ALIAS void DAC_OTHER_Handler(void); +WEAK_ALIAS void DAC_EMPTY_0_Handler(void); +WEAK_ALIAS void DAC_EMPTY_1_Handler(void); +WEAK_ALIAS void DAC_RESRDY_0_Handler(void); +WEAK_ALIAS void DAC_RESRDY_1_Handler(void); +WEAK_ALIAS void I2S_Handler(void); +WEAK_ALIAS void PCC_Handler(void); +WEAK_ALIAS void AES_Handler(void); +WEAK_ALIAS void TRNG_Handler(void); +WEAK_ALIAS void ICM_Handler(void); +WEAK_ALIAS void PUKCC_Handler(void); +WEAK_ALIAS void QSPI_Handler(void); +WEAK_ALIAS void SDHC0_Handler(void); +WEAK_ALIAS void SDHC1_Handler(void); + +__attribute__((section(".vectors"))) void (*const tab[16 + 138])(void) = { + _estack, + Reset_Handler, + NMI_Handler, + HardFault_Handler, + MemoryManagement_Handler, + BusFault_Handler, + UsageFault_Handler, + NULL, + NULL, + NULL, + NULL, + SVCall_Handler, + DebugMonitor_Handler, + NULL, + PendSV_Handler, + SysTick_Handler, + PM_Handler, // 0 Power + MCLK_Handler, // 1 Main + OSCCTRL_XOSC0_Handler, // 2 Oscillators + OSCCTRL_XOSC1_Handler, // 3 Oscillators + OSCCTRL_DFLL_Handler, // 4 Oscillators + OSCCTRL_DPLL0_Handler, // 5 Oscillators + OSCCTRL_DPLL1_Handler, // 6 Oscillators + OSC32KCTRL_Handler, // 7 32kHz + SUPC_OTHER_Handler, // 8 Supply + SUPC_BODDET_Handler, // 9 Supply + WDT_Handler, // 10 Watchdog + RTC_Handler, // 11 Real-Time + EIC_EXTINT_0_Handler, // 12 External + EIC_EXTINT_1_Handler, // 13 External + EIC_EXTINT_2_Handler, // 14 External + EIC_EXTINT_3_Handler, // 15 External + EIC_EXTINT_4_Handler, // 16 External + EIC_EXTINT_5_Handler, // 17 External + EIC_EXTINT_6_Handler, // 18 External + EIC_EXTINT_7_Handler, // 19 External + EIC_EXTINT_8_Handler, // 20 External + EIC_EXTINT_9_Handler, // 21 External + EIC_EXTINT_10_Handler, // 22 External + EIC_EXTINT_11_Handler, // 23 External + EIC_EXTINT_12_Handler, // 24 External + EIC_EXTINT_13_Handler, // 25 External + EIC_EXTINT_14_Handler, // 26 External + EIC_EXTINT_15_Handler, // 27 External + FREQM_Handler, // 28 Frequency + NVMCTRL_0_Handler, // 29 Non-Volatile + NVMCTRL_1_Handler, // 30 Non-Volatile + DMAC_0_Handler, // 31 Direct + DMAC_1_Handler, // 32 Direct + DMAC_2_Handler, // 33 Direct + DMAC_3_Handler, // 34 Direct + DMAC_OTHER_Handler, // 35 Direct + EVSYS_0_Handler, // 36 Event + EVSYS_1_Handler, // 37 Event + EVSYS_2_Handler, // 38 Event + EVSYS_3_Handler, // 39 Event + EVSYS_OTHER_Handler, // 40 Event + PAC_Handler, // 41 Peripheral + 0, // 42 Reserved + 0, // 43 Reserved + 0, // 44 Reserved + RAMECC_Handler, // 45 RAM + SERCOM0_0_Handler, // 46 Serial + SERCOM0_1_Handler, // 47 Serial + SERCOM0_2_Handler, // 48 Serial + SERCOM0_OTHER_Handler, // 49 Serial + SERCOM1_0_Handler, // 50 Serial + SERCOM1_1_Handler, // 51 Serial + SERCOM1_2_Handler, // 52 Serial + SERCOM1_OTHER_Handler, // 53 Serial + SERCOM2_0_Handler, // 54 Serial + SERCOM2_1_Handler, // 55 Serial + SERCOM2_2_Handler, // 56 Serial + SERCOM2_OTHER_Handler, // 57 Serial + SERCOM3_0_Handler, // 58 Serial + SERCOM3_1_Handler, // 59 Serial + SERCOM3_2_Handler, // 60 Serial + SERCOM3_OTHER_Handler, // 61 Serial + SERCOM4_0_Handler, // 62 Serial + SERCOM4_1_Handler, // 63 Serial + SERCOM4_2_Handler, // 64 Serial + SERCOM4_OTHER_Handler, // 65 Serial + SERCOM5_0_Handler, // 66 Serial + SERCOM5_1_Handler, // 67 Serial + SERCOM5_2_Handler, // 68 Serial + SERCOM5_OTHER_Handler, // 69 Serial + SERCOM6_0_Handler, // 70 Serial + SERCOM6_1_Handler, // 71 Serial + SERCOM6_2_Handler, // 72 Serial + SERCOM6_OTHER_Handler, // 73 Serial + SERCOM7_0_Handler, // 74 Serial + SERCOM7_1_Handler, // 75 Serial + SERCOM7_2_Handler, // 76 Serial + SERCOM7_OTHER_Handler, // 77 Serial + CAN0_Handler, // 78 Control + CAN1_Handler, // 79 Control + USB_OTHER_Handler, // 80 Universal + USB_SOF_HSOF_Handler, // 81 Universal + USB_TRCPT0_Handler, // 82 Universal + USB_TRCPT1_Handler, // 83 Universal + GMAC_Handler, // 84 Ethernet + TCC0_OTHER_Handler, // 85 Timer + TCC0_MC0_Handler, // 86 Timer + TCC0_MC1_Handler, // 87 Timer + TCC0_MC2_Handler, // 88 Timer + TCC0_MC3_Handler, // 89 Timer + TCC0_MC4_Handler, // 90 Timer + TCC0_MC5_Handler, // 91 Timer + TCC1_OTHER_Handler, // 92 Timer + TCC1_MC0_Handler, // 93 Timer + TCC1_MC1_Handler, // 94 Timer + TCC1_MC2_Handler, // 95 Timer + TCC1_MC3_Handler, // 96 Timer + TCC2_OTHER_Handler, // 97 Timer + TCC2_MC0_Handler, // 98 Timer + TCC2_MC1_Handler, // 99 Timer + TCC2_MC2_Handler, // 100 Timer + TCC3_OTHER_Handler, // 101 Timer + TCC3_MC0_Handler, // 102 Timer + TCC3_MC1_Handler, // 103 Timer + TCC4_OTHER_Handler, // 104 Timer + TCC4_MC0_Handler, // 105 Timer + TCC4_MC1_Handler, // 106 Timer + TC0_Handler, // 107 Basic + TC1_Handler, // 108 Basic + TC2_Handler, // 109 Basic + TC3_Handler, // 110 Basic + TC4_Handler, // 111 Basic + TC5_Handler, // 112 Basic + TC6_Handler, // 113 Basic + TC7_Handler, // 114 Basic + PDEC_OTHER_Handler, // 115 Quadrature + PDEC_MC0_Handler, // 116 Quadrature + PDEC_MC1_Handler, // 117 Quadrature + ADC0_OTHER_Handler, // 118 Analog + ADC0_RESRDY_Handler, // 119 Analog + ADC1_OTHER_Handler, // 120 Analog + ADC1_RESRDY_Handler, // 121 Analog + AC_Handler, // 122 Analog + DAC_OTHER_Handler, // 123 Digital-to-Analog + DAC_EMPTY_0_Handler, // 124 Digital-to-Analog + DAC_EMPTY_1_Handler, // 125 Digital-to-Analog + DAC_RESRDY_0_Handler, // 126 Digital-to-Analog + DAC_RESRDY_1_Handler, // 127 Digital-to-Analog + I2S_Handler, // 128 Inter-IC + PCC_Handler, // 129 Parallel + AES_Handler, // 130 Advanced + TRNG_Handler, // 131 True + ICM_Handler, // 132 Integrity + PUKCC_Handler, // 133 PUblic-Key + QSPI_Handler, // 134 Quad + SDHC0_Handler, // 135 SD/MMC + SDHC1_Handler // 136 SD/MMC +}; + +__attribute__((naked, noreturn)) void Reset_Handler(void) { + // Clear BSS section, and copy data section from flash to RAM + extern long _sbss, _ebss, _sdata, _edata, _sidata; + for (long *src = &_sbss; src < &_ebss; src++) *src = 0; + for (long *src = &_sdata, *dst = &_sidata; src < &_edata;) *src++ = *dst++; + + SCB->VTOR = (uint32_t) &tab; + SystemInit(); + + // Call main() + extern void main(void); + main(); + for (;;) (void) 0; // Infinite loop +} + +void Default_Handler(void) { + for (;;) (void) 0; +} diff --git a/examples/microchip/same54/syscalls.c b/examples/microchip/same54/syscalls.c new file mode 100644 index 00000000..fbf0b74b --- /dev/null +++ b/examples/microchip/same54/syscalls.c @@ -0,0 +1,89 @@ +// Copyright (c) 2022 Cesanta Software Limited +// All rights reserved + +#include + +#include "hal.h" + +int _fstat(int fd, struct stat *st) { + if (fd < 0) return -1; + st->st_mode = S_IFCHR; + return 0; +} + +void *_sbrk(int incr) { + extern char _end; + static unsigned char *heap = NULL; + unsigned char *prev_heap; + if (heap == NULL) heap = (unsigned char *) &_end; + prev_heap = heap; + heap += incr; + return prev_heap; +} + +int _open(const char *path) { + (void) path; + return -1; +} + +int _close(int fd) { + (void) fd; + return -1; +} + +int _isatty(int fd) { + (void) fd; + return 1; +} + +int _lseek(int fd, int ptr, int dir) { + (void) fd, (void) ptr, (void) dir; + return 0; +} + +void _exit(int status) { + (void) status; + for (;;) asm volatile("BKPT #0"); +} + +void _kill(int pid, int sig) { + (void) pid, (void) sig; +} + +int _getpid(void) { + return -1; +} + +int _write(int fd, char *ptr, int len) { + (void) fd, (void) ptr, (void) len; + if (fd == 1) uart_write_buf(UART_DEBUG, ptr, (size_t) len); + return -1; +} + +int _read(int fd, char *ptr, int len) { + (void) fd, (void) ptr, (void) len; + return -1; +} + +int _link(const char *a, const char *b) { + (void) a, (void) b; + return -1; +} + +int _unlink(const char *a) { + (void) a; + return -1; +} + +int _stat(const char *path, struct stat *st) { + (void) path, (void) st; + return -1; +} + +int mkdir(const char *path, mode_t mode) { + (void) path, (void) mode; + return -1; +} + +void _init(void) { +} diff --git a/mongoose.c b/mongoose.c index c33171cc..5f71ecc7 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6858,6 +6858,292 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { #endif +#ifdef MG_ENABLE_LINES +#line 1 "src/tcpip/driver_same54.c" +#endif + + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 + +#undef BIT +#define BIT(x) ((uint32_t) 1 << (x)) +#define ETH_PKT_SIZE 1536 // Max frame size +#define GMAC_DESC_CNT 4 // Descriptors count +#define GMAC_DS 2 // Descriptor size (words) + +static uint8_t s_rxbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers +static uint8_t s_txbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers +static uint32_t s_rxdesc[GMAC_DESC_CNT][GMAC_DS]; // RX descriptors +static uint32_t s_txdesc[GMAC_DESC_CNT][GMAC_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor + +static struct mg_tcpip_if *s_ifp; // MIP interface +enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1}; + +static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the read op is complete + return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value +} + +static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete +} + +static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { + struct mg_tcpip_driver_same54_data *d = + (struct mg_tcpip_driver_same54_data *) ifp->driver_data; + s_ifp = ifp; + + // enabling GMAC bus clocks + MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC(1); + MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC(1); + + GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_RXEN_Msk; // Disable receive circuit + GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_TXEN_Msk; // Disable transmit circuit + + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_TXPBMS(1); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_RXBMS(2); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_FBLDO(4); + + // Init RX descriptors + for (int i = 0; i < GMAC_DESC_CNT; i++) { + s_rxdesc[i][0] = ((uint32_t) s_rxbuf[i]) & 0xfffffffc; // Point to data buffer (bits [31:2]) + s_rxdesc[i][1] = 0; + } + s_rxdesc[GMAC_DESC_CNT - 1][0] |= BIT(1); // Marking last rx descriptor + + // Init TX descriptors + for (int i = 0; i < GMAC_DESC_CNT; i++) { + s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer + s_txdesc[i][1] = BIT(31); // Setting the OWN bit + } + s_txdesc[GMAC_DESC_CNT - 1][1] |= BIT(30); // Marking last tx descriptor + + // let the controller know about the descriptor addresses + GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; + GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; + + // GPIO pin configuration + MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; // //enable bus clock for PORT + uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15), + PIN('A', 17), PIN('A', 18), PIN('A', 19), + PIN('C', 11), PIN('C', 12), PIN('C', 20)}; + + uint32_t pin_fns[] = { + MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0, MUX_PA14L_GMAC_GTXCK, + MUX_PA15L_GMAC_GRXER, MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0, + MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC, MUX_PC12L_GMAC_GMDIO, + MUX_PC20L_GMAC_GRXDV + }; + + for (uint32_t i = 0; i < sizeof(pins) / sizeof(uint16_t); i++) { + uint8_t group = (uint8_t) (pins[i] >> 8); + uint8_t pin_no = (uint8_t) pins[i]; + PORT_REGS->GROUP[group].PORT_PINCFG[pin_no] |= PORT_PINCFG_PMUXEN_Msk; + if (pin_no % 2) + PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXO(pin_fns[i]); + else + PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXE(pin_fns[i]); + } + + PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk; + + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // RMII operation mode + + // Resetting the PHY + /*uint64_t start = mg_millis(), now = start; + PORT_REGS->GROUP[2].PORT_DIRSET = PORT_PC21; + PORT_REGS->GROUP[2].PORT_OUTCLR = PORT_PC21; + for (; now - start < 10000; now = mg_millis()); + PORT_REGS->GROUP[2].PORT_OUTSET = PORT_PC21; + for (start = mg_millis(), now = start; now - start < 10000; now = mg_millis());*/ + + // Clock advanced configuration +#if 0 + uint8_t mdc_clk_div = 5; + + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + mdc_clk_div = crs[i]; + break; + } + } + +#endif + + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(5); // set the MDC clock + GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; //enable management port + + // configure MAC + GMAC_REGS->SA[0].GMAC_SAT = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; + GMAC_REGS->SA[0].GMAC_SAB = (uint32_t) (ifp->mac[3] << 24) | + ((uint32_t) ifp->mac[2] << 16) | + ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; + + //Configure the receive filter + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk; + + //GMAC_REGS->GMAC_IER = GMAC_IER_RCOMP(1); // Enable the receive interrupt + GMAC_REGS->GMAC_IER = 0x3ffcfcff; // Enabling all interrupts + NVIC_EnableIRQ(GMAC_IRQn); + + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk; // Enable transmit circuit + GMAC_REGS->GMAC_NCR |= GMAC_NCR_RXEN_Msk ; // Enable receive circuit + + return true; +} + +static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, + struct mg_tcpip_if *ifp) { + //MG_INFO(("DMAC_CTRL: 0x%x", DMAC_REGS->DMAC_CTRL)); + MG_INFO(("GMAC_TSR: 0x%x", GMAC_REGS->GMAC_TSR)); + GMAC_REGS->GMAC_TSR |= 0x21; + uint32_t rsr = GMAC_REGS->GMAC_RSR; + MG_INFO(("GMAC_RSR: 0x%x", rsr)); + GMAC_REGS->GMAC_RSR = rsr; + if (len > sizeof(s_txbuf[s_txno])) { + MG_ERROR(("Frame too big, %ld", (long) len)); + len = 0; // Frame is too big + } else if (!(s_txdesc[s_txno][1] & BIT(31))) { + ifp->nerr++; + MG_ERROR(("No free descriptors")); + len = 0; // All descriptors are busy, fail + } else { + memcpy(s_txbuf[s_txno], buf, len); // Copy data + if (++s_txno >= GMAC_DESC_CNT) { + s_txdesc[GMAC_DESC_CNT - 1][1] = (len & (BIT(14) - 1)) | BIT(15)| BIT(30); + s_txno = 0; + MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", GMAC_DESC_CNT - 1, s_txdesc[GMAC_DESC_CNT - 1][1])); + } else { + s_txdesc[s_txno - 1][1] = (len & (BIT(14) - 1)) | BIT(15); + MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", s_txno - 1, s_txdesc[s_txno - 1][1])); + } + } + __DSB(); // Ensure descriptors have been written + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission + return len; +} + +static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { + uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); + //MG_INFO(("BSR: 0x%x", bsr)); + bool up = bsr & BIT(2) ? 1 : 0; + (void) ifp; + return up; +} + +void GMAC_Handler(void); +void GMAC_Handler(void) { + MG_INFO(("Entering GMAC IRQ HANDLER")); + uint32_t isr = GMAC_REGS->GMAC_ISR; + MG_INFO(("isr: 0x%x", isr)); + if (/*GMAC_REGS->GMAC_ISR*/ isr & GMAC_ISR_RCOMP_Msk) { + int frame_start = -1; + int frame_end = -1; + + // find the start of the frame + for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (!(s_rxdesc[desc_index][0] & 1)) break; + if (s_rxdesc[desc_index][1] & BIT(14)) + frame_start = desc_index; + } + + // if frame start not found, then clear the own bit + if (frame_start == -1) { + for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (!(s_rxdesc[desc_index][0] & 1)) { + break; + } else { + s_rxdesc[desc_index][0] &= ~(BIT(0)); + } + } + return; + } + + // find the end of the frame + for (int i = frame_start; i < GMAC_DESC_CNT + frame_start; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (s_rxdesc[desc_index][1] & BIT(15)) + frame_end = desc_index; + } + + // clear all used buffers until you reach start of frame + for (int i = 0; i < GMAC_DESC_CNT; i++) { + int desc_index = (i + s_rxno) % GMAC_DESC_CNT; + if (s_rxno == frame_start) break; + if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; + s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit + } + + // from start of frame to end of frame you copy into queue + size_t offset = 0, len; + for (int i = 0; i < GMAC_DESC_CNT; i++) { + int desc_index = (i + s_rxno) % GMAC_DESC_CNT; + if (desc_index == frame_start) + offset = (GMAC_REGS->GMAC_NCFGR & GMAC_NCFGR_RXBUFO_Msk) >> GMAC_NCFGR_RXBUFO_Pos; + else + offset = 0; + len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); + mg_tcpip_qwrite(s_rxbuf[s_rxno] + offset, len, s_ifp); + s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit + if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; + if (desc_index == frame_end) break; + } + } +} + +struct mg_tcpip_driver mg_tcpip_driver_same54 = {mg_tcpip_driver_same54_init, + mg_tcpip_driver_same54_tx, NULL, + mg_tcpip_driver_same54_up}; +#endif + #ifdef MG_ENABLE_LINES #line 1 "src/tcpip/driver_stm32.c" #endif diff --git a/mongoose.h b/mongoose.h index 29e6f077..6f1ee6f2 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1696,6 +1696,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; +extern struct mg_tcpip_driver mg_tcpip_driver_same54; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi { @@ -1722,6 +1723,17 @@ struct mg_tcpip_driver_imxrt1020_data { }; +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 + +#include "hal.h" // keep this include + +struct mg_tcpip_driver_same54_data { + int mdc_cr; +}; + +#endif + + struct mg_tcpip_driver_stm32_data { // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz // HCLK range DIVIDER mdc_cr VALUE diff --git a/src/tcpip/driver_same54.c b/src/tcpip/driver_same54.c new file mode 100644 index 00000000..d423cdcb --- /dev/null +++ b/src/tcpip/driver_same54.c @@ -0,0 +1,282 @@ +#include "tcpip.h" + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 + +#undef BIT +#define BIT(x) ((uint32_t) 1 << (x)) +#define ETH_PKT_SIZE 1536 // Max frame size +#define GMAC_DESC_CNT 4 // Descriptors count +#define GMAC_DS 2 // Descriptor size (words) + +static uint8_t s_rxbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers +static uint8_t s_txbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers +static uint32_t s_rxdesc[GMAC_DESC_CNT][GMAC_DS]; // RX descriptors +static uint32_t s_txdesc[GMAC_DESC_CNT][GMAC_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor + +static struct mg_tcpip_if *s_ifp; // MIP interface +enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1}; + +static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the read op is complete + return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value +} + +static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete +} + +static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { + struct mg_tcpip_driver_same54_data *d = + (struct mg_tcpip_driver_same54_data *) ifp->driver_data; + s_ifp = ifp; + + // enabling GMAC bus clocks + MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC(1); + MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC(1); + + GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_RXEN_Msk; // Disable receive circuit + GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_TXEN_Msk; // Disable transmit circuit + + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_TXPBMS(1); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_RXBMS(2); + GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_FBLDO(4); + + // Init RX descriptors + for (int i = 0; i < GMAC_DESC_CNT; i++) { + s_rxdesc[i][0] = ((uint32_t) s_rxbuf[i]) & 0xfffffffc; // Point to data buffer (bits [31:2]) + s_rxdesc[i][1] = 0; + } + s_rxdesc[GMAC_DESC_CNT - 1][0] |= BIT(1); // Marking last rx descriptor + + // Init TX descriptors + for (int i = 0; i < GMAC_DESC_CNT; i++) { + s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer + s_txdesc[i][1] = BIT(31); // Setting the OWN bit + } + s_txdesc[GMAC_DESC_CNT - 1][1] |= BIT(30); // Marking last tx descriptor + + // let the controller know about the descriptor addresses + GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; + GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; + + // GPIO pin configuration + MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; // //enable bus clock for PORT + uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15), + PIN('A', 17), PIN('A', 18), PIN('A', 19), + PIN('C', 11), PIN('C', 12), PIN('C', 20)}; + + uint32_t pin_fns[] = { + MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0, MUX_PA14L_GMAC_GTXCK, + MUX_PA15L_GMAC_GRXER, MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0, + MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC, MUX_PC12L_GMAC_GMDIO, + MUX_PC20L_GMAC_GRXDV + }; + + for (uint32_t i = 0; i < sizeof(pins) / sizeof(uint16_t); i++) { + uint8_t group = (uint8_t) (pins[i] >> 8); + uint8_t pin_no = (uint8_t) pins[i]; + PORT_REGS->GROUP[group].PORT_PINCFG[pin_no] |= PORT_PINCFG_PMUXEN_Msk; + if (pin_no % 2) + PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXO(pin_fns[i]); + else + PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXE(pin_fns[i]); + } + + PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk; + + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // RMII operation mode + + // Resetting the PHY + /*uint64_t start = mg_millis(), now = start; + PORT_REGS->GROUP[2].PORT_DIRSET = PORT_PC21; + PORT_REGS->GROUP[2].PORT_OUTCLR = PORT_PC21; + for (; now - start < 10000; now = mg_millis()); + PORT_REGS->GROUP[2].PORT_OUTSET = PORT_PC21; + for (start = mg_millis(), now = start; now - start < 10000; now = mg_millis());*/ + + // Clock advanced configuration +#if 0 + uint8_t mdc_clk_div = 5; + + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + mdc_clk_div = crs[i]; + break; + } + } + +#endif + + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(5); // set the MDC clock + GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; //enable management port + + // configure MAC + GMAC_REGS->SA[0].GMAC_SAT = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; + GMAC_REGS->SA[0].GMAC_SAB = (uint32_t) (ifp->mac[3] << 24) | + ((uint32_t) ifp->mac[2] << 16) | + ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; + + //Configure the receive filter + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk; + + //GMAC_REGS->GMAC_IER = GMAC_IER_RCOMP(1); // Enable the receive interrupt + GMAC_REGS->GMAC_IER = 0x3ffcfcff; // Enabling all interrupts + NVIC_EnableIRQ(GMAC_IRQn); + + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk; // Enable transmit circuit + GMAC_REGS->GMAC_NCR |= GMAC_NCR_RXEN_Msk ; // Enable receive circuit + + return true; +} + +static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, + struct mg_tcpip_if *ifp) { + //MG_INFO(("DMAC_CTRL: 0x%x", DMAC_REGS->DMAC_CTRL)); + MG_INFO(("GMAC_TSR: 0x%x", GMAC_REGS->GMAC_TSR)); + GMAC_REGS->GMAC_TSR |= 0x21; + uint32_t rsr = GMAC_REGS->GMAC_RSR; + MG_INFO(("GMAC_RSR: 0x%x", rsr)); + GMAC_REGS->GMAC_RSR = rsr; + if (len > sizeof(s_txbuf[s_txno])) { + MG_ERROR(("Frame too big, %ld", (long) len)); + len = 0; // Frame is too big + } else if (!(s_txdesc[s_txno][1] & BIT(31))) { + ifp->nerr++; + MG_ERROR(("No free descriptors")); + len = 0; // All descriptors are busy, fail + } else { + memcpy(s_txbuf[s_txno], buf, len); // Copy data + if (++s_txno >= GMAC_DESC_CNT) { + s_txdesc[GMAC_DESC_CNT - 1][1] = (len & (BIT(14) - 1)) | BIT(15)| BIT(30); + s_txno = 0; + MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", GMAC_DESC_CNT - 1, s_txdesc[GMAC_DESC_CNT - 1][1])); + } else { + s_txdesc[s_txno - 1][1] = (len & (BIT(14) - 1)) | BIT(15); + MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", s_txno - 1, s_txdesc[s_txno - 1][1])); + } + } + __DSB(); // Ensure descriptors have been written + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission + return len; +} + +static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { + uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); + //MG_INFO(("BSR: 0x%x", bsr)); + bool up = bsr & BIT(2) ? 1 : 0; + (void) ifp; + return up; +} + +void GMAC_Handler(void); +void GMAC_Handler(void) { + MG_INFO(("Entering GMAC IRQ HANDLER")); + uint32_t isr = GMAC_REGS->GMAC_ISR; + MG_INFO(("isr: 0x%x", isr)); + if (/*GMAC_REGS->GMAC_ISR*/ isr & GMAC_ISR_RCOMP_Msk) { + int frame_start = -1; + int frame_end = -1; + + // find the start of the frame + for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (!(s_rxdesc[desc_index][0] & 1)) break; + if (s_rxdesc[desc_index][1] & BIT(14)) + frame_start = desc_index; + } + + // if frame start not found, then clear the own bit + if (frame_start == -1) { + for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (!(s_rxdesc[desc_index][0] & 1)) { + break; + } else { + s_rxdesc[desc_index][0] &= ~(BIT(0)); + } + } + return; + } + + // find the end of the frame + for (int i = frame_start; i < GMAC_DESC_CNT + frame_start; i++) { + int desc_index = i % GMAC_DESC_CNT; + if (s_rxdesc[desc_index][1] & BIT(15)) + frame_end = desc_index; + } + + // clear all used buffers until you reach start of frame + for (int i = 0; i < GMAC_DESC_CNT; i++) { + int desc_index = (i + s_rxno) % GMAC_DESC_CNT; + if (s_rxno == frame_start) break; + if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; + s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit + } + + // from start of frame to end of frame you copy into queue + size_t offset = 0, len; + for (int i = 0; i < GMAC_DESC_CNT; i++) { + int desc_index = (i + s_rxno) % GMAC_DESC_CNT; + if (desc_index == frame_start) + offset = (GMAC_REGS->GMAC_NCFGR & GMAC_NCFGR_RXBUFO_Msk) >> GMAC_NCFGR_RXBUFO_Pos; + else + offset = 0; + len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); + mg_tcpip_qwrite(s_rxbuf[s_rxno] + offset, len, s_ifp); + s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit + if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; + if (desc_index == frame_end) break; + } + } +} + +struct mg_tcpip_driver mg_tcpip_driver_same54 = {mg_tcpip_driver_same54_init, + mg_tcpip_driver_same54_tx, NULL, + mg_tcpip_driver_same54_up}; +#endif diff --git a/src/tcpip/driver_same54.h b/src/tcpip/driver_same54.h new file mode 100644 index 00000000..c5552dbb --- /dev/null +++ b/src/tcpip/driver_same54.h @@ -0,0 +1,11 @@ +#pragma once + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 + +#include "hal.h" // keep this include + +struct mg_tcpip_driver_same54_data { + int mdc_cr; +}; + +#endif diff --git a/src/tcpip/tcpip.h b/src/tcpip/tcpip.h index c7aed964..ec60a288 100644 --- a/src/tcpip/tcpip.h +++ b/src/tcpip/tcpip.h @@ -54,6 +54,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; +extern struct mg_tcpip_driver mg_tcpip_driver_same54; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi { From cea7fcdb37dbfe2466540fdf59e74723f39ea267 Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 20 Jul 2023 14:36:10 +0100 Subject: [PATCH 2/6] AVR build fixes --- .../Core/Inc/mongoose_custom.h | 1 + .../Core/Inc/mongoose_custom.h | 1 + .../nucleo-f429zi-cube-freertos-lwip/Core/Inc/mongoose_custom.h | 1 + .../Core/Inc/mongoose_custom.h | 1 + .../Core/Inc/mongoose_custom.h | 1 + .../nucleo-f746zg-cube-freertos-lwip/Core/Inc/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-baremetal/mongoose_custom.h | 1 + .../stm32/nucleo-f746zg-keil-freertos-lwip/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-freertos-tcp/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-freertos/mongoose_custom.h | 1 + .../nucleo-f746zg-keil-freertos_cmsis2-lwip/mongoose_custom.h | 1 + .../stm32/nucleo-f746zg-keil-freertos_cmsis2/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-rtx-mdk/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-rtx/mongoose_custom.h | 1 + examples/stm32/nucleo-f746zg-keil-rtx5-mdk/mongoose_custom.h | 1 + 15 files changed, 15 insertions(+) diff --git a/examples/stm32/nucleo-f429zi-cube-baremetal-builtin/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f429zi-cube-baremetal-builtin/Core/Inc/mongoose_custom.h index 37217804..632e9721 100644 --- a/examples/stm32/nucleo-f429zi-cube-baremetal-builtin/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f429zi-cube-baremetal-builtin/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32H 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f429zi-cube-freertos-builtin/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f429zi-cube-freertos-builtin/Core/Inc/mongoose_custom.h index 4c3dab86..d9b2f8c7 100644 --- a/examples/stm32/nucleo-f429zi-cube-freertos-builtin/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f429zi-cube-freertos-builtin/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_STMPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_STMPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_STMPACK_NET == 2 diff --git a/examples/stm32/nucleo-f429zi-cube-freertos-lwip/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f429zi-cube-freertos-lwip/Core/Inc/mongoose_custom.h index f4238f40..96a2532d 100644 --- a/examples/stm32/nucleo-f429zi-cube-freertos-lwip/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f429zi-cube-freertos-lwip/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_STMPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_STMPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_STMPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-cube-baremetal-builtin/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f746zg-cube-baremetal-builtin/Core/Inc/mongoose_custom.h index 37217804..d8355cb6 100644 --- a/examples/stm32/nucleo-f746zg-cube-baremetal-builtin/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-cube-baremetal-builtin/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-cube-freertos-builtin/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f746zg-cube-freertos-builtin/Core/Inc/mongoose_custom.h index 4c3dab86..5c4a6d8f 100644 --- a/examples/stm32/nucleo-f746zg-cube-freertos-builtin/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-cube-freertos-builtin/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_STMPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32H 1 #elif MG_STMPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_STMPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-cube-freertos-lwip/Core/Inc/mongoose_custom.h b/examples/stm32/nucleo-f746zg-cube-freertos-lwip/Core/Inc/mongoose_custom.h index f4238f40..96a2532d 100644 --- a/examples/stm32/nucleo-f746zg-cube-freertos-lwip/Core/Inc/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-cube-freertos-lwip/Core/Inc/mongoose_custom.h @@ -17,6 +17,7 @@ // Translate to Mongoose macros #if MG_STMPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_STMPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_STMPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-baremetal/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-baremetal/mongoose_custom.h index f9f29417..b5a7eb79 100644 --- a/examples/stm32/nucleo-f746zg-keil-baremetal/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-baremetal/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-freertos-lwip/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-freertos-lwip/mongoose_custom.h index b8e0019f..2d842ea3 100644 --- a/examples/stm32/nucleo-f746zg-keil-freertos-lwip/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-freertos-lwip/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-freertos-tcp/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-freertos-tcp/mongoose_custom.h index 35353103..3429a559 100644 --- a/examples/stm32/nucleo-f746zg-keil-freertos-tcp/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-freertos-tcp/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-freertos/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-freertos/mongoose_custom.h index c64de147..3a9aaaf0 100644 --- a/examples/stm32/nucleo-f746zg-keil-freertos/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-freertos/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2-lwip/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2-lwip/mongoose_custom.h index eb12e4be..fe746ae8 100644 --- a/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2-lwip/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2-lwip/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2/mongoose_custom.h index 5307c6bd..1dab0fba 100644 --- a/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-freertos_cmsis2/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-rtx-mdk/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-rtx-mdk/mongoose_custom.h index 2fddc3ba..b7fba70d 100644 --- a/examples/stm32/nucleo-f746zg-keil-rtx-mdk/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-rtx-mdk/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-rtx/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-rtx/mongoose_custom.h index 8ee2b06c..49fbd67c 100644 --- a/examples/stm32/nucleo-f746zg-keil-rtx/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-rtx/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 diff --git a/examples/stm32/nucleo-f746zg-keil-rtx5-mdk/mongoose_custom.h b/examples/stm32/nucleo-f746zg-keil-rtx5-mdk/mongoose_custom.h index 9221a987..1797b73d 100644 --- a/examples/stm32/nucleo-f746zg-keil-rtx5-mdk/mongoose_custom.h +++ b/examples/stm32/nucleo-f746zg-keil-rtx5-mdk/mongoose_custom.h @@ -65,6 +65,7 @@ #endif #if MG_CMSISPACK_NET == 0 #define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_DRIVER_STM32 1 #elif MG_CMSISPACK_NET == 1 #define MG_ENABLE_LWIP 1 #elif MG_CMSISPACK_NET == 2 From f5943fe591212d5d6b702368f1ea04e3c2bf212f Mon Sep 17 00:00:00 2001 From: cpq Date: Mon, 24 Jul 2023 12:05:51 +0100 Subject: [PATCH 3/6] Add tls_builtin.c --- mongoose.c | 174 +++++++++++++++++++++++++++++++++++++++++++++- mongoose.h | 2 +- src/net.c | 6 +- src/tls.h | 2 +- src/tls_builtin.c | 164 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 src/tls_builtin.c diff --git a/mongoose.c b/mongoose.c index 5f71ecc7..a84d6bd3 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3616,7 +3616,7 @@ static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { for (i = 2; i < 6; i++) { if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false; } - //struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); + // struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false; memcpy(&ipv4, addr->ip, sizeof(ipv4)); memset(addr->ip, 0, sizeof(addr->ip)); @@ -3659,7 +3659,7 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2); memset(&addr->ip[dc], 0, 14 - n); } - + addr->is_ip6 = true; return true; } @@ -3713,7 +3713,7 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, c->is_client = true; c->fn_data = fn_data; MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); - mg_call(c, MG_EV_OPEN, NULL); + mg_call(c, MG_EV_OPEN, (void *) url); mg_resolve(c, url); if (mg_url_is_ssl(url)) { struct mg_str host = mg_url_host(url); @@ -5494,6 +5494,174 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) { } } +#ifdef MG_ENABLE_LINES +#line 1 "src/tls_builtin.c" +#endif + + +#if MG_TLS == MG_TLS_BUILTIN +struct tls_data { + struct mg_iobuf send; + struct mg_iobuf recv; +}; + +#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) +#define TLS_HDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes len + +static inline bool mg_is_big_endian(void) { + int v = 1; + return *(unsigned char *) &v == 1; +} +static inline uint16_t mg_swap16(uint16_t v) { + return (uint16_t) ((v << 8U) | (v >> 8U)); +} +static inline uint32_t mg_swap32(uint32_t v) { + return (v >> 24) | (v >> 8 & 0xff00) | (v << 8 & 0xff0000) | (v << 24); +} +static inline uint64_t mg_swap64(uint64_t v) { + return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | mg_swap32(v >> 32); +} +static inline uint16_t mg_be16(uint16_t v) { + return mg_is_big_endian() ? mg_swap16(v) : v; +} +static inline uint32_t mg_be32(uint32_t v) { + return mg_is_big_endian() ? mg_swap32(v) : v; +} + +static inline void add8(struct mg_iobuf *io, uint8_t data) { + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} +static inline void add16(struct mg_iobuf *io, uint16_t data) { + data = mg_htons(data); + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} +static inline void add32(struct mg_iobuf *io, uint32_t data) { + data = mg_htonl(data); + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} + +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct tls_data *tls = (struct tls_data *) calloc(1, sizeof(struct tls_data)); + if (tls != NULL) { + tls->send.align = tls->recv.align = MG_IO_SIZE; + c->tls = tls; + c->is_tls = c->is_tls_hs = 1; + } else { + mg_error(c, "tls oom"); + } + (void) hostname; +} +void mg_tls_free(struct mg_connection *c) { + struct tls_data *tls = c->tls; + if (tls != NULL) { + mg_iobuf_free(&tls->send); + mg_iobuf_free(&tls->recv); + } + free(c->tls); + c->tls = NULL; +} +long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { + (void) c, (void) buf, (void) len; + // MG_INFO(("BBBBBBBB")); + return -1; +} +long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { + (void) c, (void) buf, (void) len; + char tmp[8192]; + long n = mg_io_recv(c, tmp, sizeof(tmp)); + if (n > 0) mg_hexdump(tmp, n); + MG_INFO(("AAAAAAAA")); + return -1; + // struct mg_tls *tls = (struct mg_tls *) c->tls; + // long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len); + // if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) + // return MG_IO_WAIT; + // if (n <= 0) return MG_IO_ERR; + // return n; +} +size_t mg_tls_pending(struct mg_connection *c) { + (void) c; + return 0; +} +void mg_tls_handshake(struct mg_connection *c) { + struct tls_data *tls = c->tls; + struct mg_iobuf *rio = &tls->recv; + struct mg_iobuf *wio = &tls->send; + // Pull data from TCP + for (;;) { + mg_iobuf_resize(rio, rio->len + 1); + long n = mg_io_recv(c, &rio->buf[rio->len], rio->size - rio->len); + if (n > 0) { + rio->len += n; + } else if (n == MG_IO_WAIT) { + break; + } else { + mg_error(c, "IO err"); + return; + } + } + // Look if we've pulled everything + if (rio->len < TLS_HDR_SIZE) return; + uint8_t record_type = rio->buf[0]; + uint16_t record_len = MG_LOAD_BE16(rio->buf + 3); + uint16_t record_version = MG_LOAD_BE16(rio->buf + 1); + if (record_type != 22) { + mg_error(c, "no 22"); + return; + } + if (rio->len < TLS_HDR_SIZE + record_len) return; + // Got full hello + // struct tls_hello *hello = (struct tls_hello *) (hdr + 1); + MG_INFO(("CT=%d V=%hx L=%hu", record_type, record_version, record_len)); + mg_hexdump(rio->buf, rio->len); + + // Send response. Server Hello + size_t ofs = wio->len; + add8(wio, 22), add16(wio, 0x303), add16(wio, 0); // Layer: type, ver, len + add8(wio, 2), add8(wio, 0), add16(wio, 0), add16(wio, 0x304); // Hello + mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random + mg_random(wio->buf + wio->len - 32, 32); // bytes + add8(wio, 0); // Session ID + add16(wio, 0x1301); // Cipher: TLS_AES_128_GCM_SHA256 + add8(wio, 0); // Compression method: 0 + add16(wio, 46); // Extensions length + add16(wio, 43), add16(wio, 2), add16(wio, 0x304); // extension: TLS 1.3 + add16(wio, 51), add16(wio, 36), add16(wio, 29), add16(wio, 32); // keyshare + mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random + mg_random(wio->buf + wio->len - 32, 32); // bytes + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + *(uint16_t *) &wio->buf[ofs + 7] = mg_be16(wio->len - ofs - 9); + + // Change cipher. Cipher's payload is an encypted app data + // ofs = wio->len; + add8(wio, 20), add16(wio, 0x303); // Layer: type, version + add16(wio, 1), add8(wio, 1); + + ofs = wio->len; // Application data + add8(wio, 23), add16(wio, 0x303), add16(wio, 5); // Layer: type, version + // mg_iobuf_add(wio, wio->len, "\x01\x02\x03\x04\x05", 5); + add8(wio, 22); // handshake message + add8(wio, 8); // encrypted extensions + add8(wio, 0), add16(wio, 2), add16(wio, 0); // empty 2 bytes + add8(wio, 11); // certificate message + add8(wio, 0), add16(wio, 4), add32(wio, 0x1020304); // len + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + + mg_io_send(c, wio->buf, wio->len); + wio->len = 0; + + rio->len = 0; + c->is_tls_hs = 0; + mg_error(c, "doh"); +} +void mg_tls_ctx_free(struct mg_mgr *mgr) { + mgr->tls_ctx = NULL; +} +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + (void) opts, (void) mgr; +} +#endif + #ifdef MG_ENABLE_LINES #line 1 "src/tls_dummy.c" #endif diff --git a/mongoose.h b/mongoose.h index 6f1ee6f2..d251d22e 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1326,7 +1326,7 @@ void mg_http_serve_ssi(struct mg_connection *c, const char *root, #define MG_TLS_CUSTOM 4 // Custom implementation #ifndef MG_TLS -#define MG_TLS MG_TLS_NONE +#define MG_TLS MG_TLS_BUILTIN #endif diff --git a/src/net.c b/src/net.c index 6c7d4b5f..45b60904 100644 --- a/src/net.c +++ b/src/net.c @@ -65,7 +65,7 @@ static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { for (i = 2; i < 6; i++) { if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false; } - //struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); + // struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false; memcpy(&ipv4, addr->ip, sizeof(ipv4)); memset(addr->ip, 0, sizeof(addr->ip)); @@ -108,7 +108,7 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2); memset(&addr->ip[dc], 0, 14 - n); } - + addr->is_ip6 = true; return true; } @@ -162,7 +162,7 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url, c->is_client = true; c->fn_data = fn_data; MG_DEBUG(("%lu %p %s", c->id, c->fd, url)); - mg_call(c, MG_EV_OPEN, NULL); + mg_call(c, MG_EV_OPEN, (void *) url); mg_resolve(c, url); if (mg_url_is_ssl(url)) { struct mg_str host = mg_url_host(url); diff --git a/src/tls.h b/src/tls.h index 97128d94..9ce371af 100644 --- a/src/tls.h +++ b/src/tls.h @@ -7,7 +7,7 @@ #define MG_TLS_CUSTOM 4 // Custom implementation #ifndef MG_TLS -#define MG_TLS MG_TLS_NONE +#define MG_TLS MG_TLS_BUILTIN #endif #include "net.h" diff --git a/src/tls_builtin.c b/src/tls_builtin.c new file mode 100644 index 00000000..0c53b708 --- /dev/null +++ b/src/tls_builtin.c @@ -0,0 +1,164 @@ +#include "tls.h" + +#if MG_TLS == MG_TLS_BUILTIN +struct tls_data { + struct mg_iobuf send; + struct mg_iobuf recv; +}; + +#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) +#define TLS_HDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes len + +static inline bool mg_is_big_endian(void) { + int v = 1; + return *(unsigned char *) &v == 1; +} +static inline uint16_t mg_swap16(uint16_t v) { + return (uint16_t) ((v << 8U) | (v >> 8U)); +} +static inline uint32_t mg_swap32(uint32_t v) { + return (v >> 24) | (v >> 8 & 0xff00) | (v << 8 & 0xff0000) | (v << 24); +} +static inline uint64_t mg_swap64(uint64_t v) { + return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | mg_swap32(v >> 32); +} +static inline uint16_t mg_be16(uint16_t v) { + return mg_is_big_endian() ? mg_swap16(v) : v; +} +static inline uint32_t mg_be32(uint32_t v) { + return mg_is_big_endian() ? mg_swap32(v) : v; +} + +static inline void add8(struct mg_iobuf *io, uint8_t data) { + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} +static inline void add16(struct mg_iobuf *io, uint16_t data) { + data = mg_htons(data); + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} +static inline void add32(struct mg_iobuf *io, uint32_t data) { + data = mg_htonl(data); + mg_iobuf_add(io, io->len, &data, sizeof(data)); +} + +void mg_tls_init(struct mg_connection *c, struct mg_str hostname) { + struct tls_data *tls = (struct tls_data *) calloc(1, sizeof(struct tls_data)); + if (tls != NULL) { + tls->send.align = tls->recv.align = MG_IO_SIZE; + c->tls = tls; + c->is_tls = c->is_tls_hs = 1; + } else { + mg_error(c, "tls oom"); + } + (void) hostname; +} +void mg_tls_free(struct mg_connection *c) { + struct tls_data *tls = c->tls; + if (tls != NULL) { + mg_iobuf_free(&tls->send); + mg_iobuf_free(&tls->recv); + } + free(c->tls); + c->tls = NULL; +} +long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { + (void) c, (void) buf, (void) len; + // MG_INFO(("BBBBBBBB")); + return -1; +} +long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { + (void) c, (void) buf, (void) len; + char tmp[8192]; + long n = mg_io_recv(c, tmp, sizeof(tmp)); + if (n > 0) mg_hexdump(tmp, n); + MG_INFO(("AAAAAAAA")); + return -1; + // struct mg_tls *tls = (struct mg_tls *) c->tls; + // long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len); + // if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) + // return MG_IO_WAIT; + // if (n <= 0) return MG_IO_ERR; + // return n; +} +size_t mg_tls_pending(struct mg_connection *c) { + (void) c; + return 0; +} +void mg_tls_handshake(struct mg_connection *c) { + struct tls_data *tls = c->tls; + struct mg_iobuf *rio = &tls->recv; + struct mg_iobuf *wio = &tls->send; + // Pull data from TCP + for (;;) { + mg_iobuf_resize(rio, rio->len + 1); + long n = mg_io_recv(c, &rio->buf[rio->len], rio->size - rio->len); + if (n > 0) { + rio->len += n; + } else if (n == MG_IO_WAIT) { + break; + } else { + mg_error(c, "IO err"); + return; + } + } + // Look if we've pulled everything + if (rio->len < TLS_HDR_SIZE) return; + uint8_t record_type = rio->buf[0]; + uint16_t record_len = MG_LOAD_BE16(rio->buf + 3); + uint16_t record_version = MG_LOAD_BE16(rio->buf + 1); + if (record_type != 22) { + mg_error(c, "no 22"); + return; + } + if (rio->len < TLS_HDR_SIZE + record_len) return; + // Got full hello + // struct tls_hello *hello = (struct tls_hello *) (hdr + 1); + MG_INFO(("CT=%d V=%hx L=%hu", record_type, record_version, record_len)); + mg_hexdump(rio->buf, rio->len); + + // Send response. Server Hello + size_t ofs = wio->len; + add8(wio, 22), add16(wio, 0x303), add16(wio, 0); // Layer: type, ver, len + add8(wio, 2), add8(wio, 0), add16(wio, 0), add16(wio, 0x304); // Hello + mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random + mg_random(wio->buf + wio->len - 32, 32); // bytes + add8(wio, 0); // Session ID + add16(wio, 0x1301); // Cipher: TLS_AES_128_GCM_SHA256 + add8(wio, 0); // Compression method: 0 + add16(wio, 46); // Extensions length + add16(wio, 43), add16(wio, 2), add16(wio, 0x304); // extension: TLS 1.3 + add16(wio, 51), add16(wio, 36), add16(wio, 29), add16(wio, 32); // keyshare + mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random + mg_random(wio->buf + wio->len - 32, 32); // bytes + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + *(uint16_t *) &wio->buf[ofs + 7] = mg_be16(wio->len - ofs - 9); + + // Change cipher. Cipher's payload is an encypted app data + // ofs = wio->len; + add8(wio, 20), add16(wio, 0x303); // Layer: type, version + add16(wio, 1), add8(wio, 1); + + ofs = wio->len; // Application data + add8(wio, 23), add16(wio, 0x303), add16(wio, 5); // Layer: type, version + // mg_iobuf_add(wio, wio->len, "\x01\x02\x03\x04\x05", 5); + add8(wio, 22); // handshake message + add8(wio, 8); // encrypted extensions + add8(wio, 0), add16(wio, 2), add16(wio, 0); // empty 2 bytes + add8(wio, 11); // certificate message + add8(wio, 0), add16(wio, 4), add32(wio, 0x1020304); // len + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + + mg_io_send(c, wio->buf, wio->len); + wio->len = 0; + + rio->len = 0; + c->is_tls_hs = 0; + mg_error(c, "doh"); +} +void mg_tls_ctx_free(struct mg_mgr *mgr) { + mgr->tls_ctx = NULL; +} +void mg_tls_ctx_init(struct mg_mgr *mgr, const struct mg_tls_opts *opts) { + (void) opts, (void) mgr; +} +#endif From 8005a5e687b1909c5489f0ba0fb1f3eb6709b6e6 Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 3 Aug 2023 09:31:04 +0100 Subject: [PATCH 4/6] Changes --- examples/microchip/same54/Makefile | 2 +- examples/microchip/same54/hal.h | 36 ++++ examples/microchip/same54/main.c | 18 +- mongoose.c | 319 +++++++++-------------------- mongoose.h | 4 +- src/tcpip/driver_same54.c | 300 +++++++++------------------ src/tcpip/driver_same54.h | 2 - src/tcpip/tcpip.c | 4 +- src/tls.h | 2 +- src/tls_builtin.c | 15 +- 10 files changed, 255 insertions(+), 447 deletions(-) diff --git a/examples/microchip/same54/Makefile b/examples/microchip/same54/Makefile index 646661ae..e9ec2448 100644 --- a/examples/microchip/same54/Makefile +++ b/examples/microchip/same54/Makefile @@ -11,7 +11,7 @@ SOURCES = main.c syscalls.c startup.c #SOURCES += cmsis_sam/xc32/ATSAME54P20A/startup_atsame54p20a.c SOURCES += mongoose.c net.c packed_fs.c -CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 +CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_LINES=1 CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA) VCON_API_KEY=IBrJL5K4arSGMiAXbUKWdG6I2gM diff --git a/examples/microchip/same54/hal.h b/examples/microchip/same54/hal.h index eebe6bd4..80a24f7a 100644 --- a/examples/microchip/same54/hal.h +++ b/examples/microchip/same54/hal.h @@ -176,3 +176,39 @@ static inline void gpio_set_irq_handler(uint16_t pin, void (*fn)(void *), void *arg) { (void) pin, (void) fn, (void) arg; } + +static inline void ethernet_init(void) { + uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15), + PIN('A', 17), PIN('A', 18), PIN('A', 19), PIN('C', 11), + PIN('C', 12), PIN('C', 20)}; + uint32_t af[] = {MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0, + MUX_PA14L_GMAC_GTXCK, MUX_PA15L_GMAC_GRXER, + MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0, + MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC, + MUX_PC12L_GMAC_GMDIO, MUX_PC20L_GMAC_GRXDV}; + + MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; + + for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) { + int bank = PINBANK(pins[i]), no = PINNO(pins[i]); + PORT_REGS->GROUP[bank].PORT_PINCFG[no] |= PORT_PINCFG_PMUXEN_Msk; + volatile uint8_t *m = &PORT_REGS->GROUP[bank].PORT_PMUX[no / 2], v = m[0]; + if (no & 1) { + m[0] = (uint8_t) (v & ~0xf0) | PORT_PMUX_PMUXO(af[i]); + } else { + m[0] = (uint8_t) (v & ~0x0f) | PORT_PMUX_PMUXE(af[i]); + } + } + + PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk; + PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk; + + // Reset PHY + uint16_t phy_pin = PIN('C', 21); + gpio_output(phy_pin); + gpio_write(phy_pin, false); + spin(999); + gpio_write(phy_pin, true); + spin(999); +} diff --git a/examples/microchip/same54/main.c b/examples/microchip/same54/main.c index 2bf7a697..d6d1d9b2 100644 --- a/examples/microchip/same54/main.c +++ b/examples/microchip/same54/main.c @@ -10,6 +10,7 @@ void SystemInit(void) { // Called automatically by startup code clock_init(); + rng_init(); } static volatile uint64_t s_ticks; // Milliseconds since boot @@ -36,11 +37,15 @@ static void timer_fn(void *arg) { ifp->ndrop, ifp->nerr)); } +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n"); + } + int main(void) { gpio_input(BUTTON_PIN); gpio_output(LED_PIN); uart_init(UART_DEBUG, 115200); - rng_init(); + ethernet_init(); MG_INFO(("Starting, CPU freq %g MHz", (double) clock_sys_freq() / 1000000)); @@ -49,8 +54,8 @@ int main(void) { mg_log_set(MG_LL_DEBUG); // Set log level // Initialise Mongoose network stack - struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 4}; - struct mg_tcpip_if mif = {.mac = {0x02, 0x14, 0x30, 0x00, 0x1a, 0x00}, + struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 5}; + struct mg_tcpip_if mif = {.mac = {2, 3, 4, 5, 6, 7}, // Uncomment below for static configuration: // .ip = mg_htonl(MG_U32(192, 168, 0, 223)), // .mask = mg_htonl(MG_U32(255, 255, 255, 0)), @@ -58,7 +63,7 @@ int main(void) { .driver = &mg_tcpip_driver_same54, .driver_data = &driver_data}; mg_tcpip_init(&mgr, &mif); - mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif); + mg_timer_add(&mgr, LOG_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif); MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac)); while (mif.state != MG_TCPIP_STATE_READY) { @@ -66,7 +71,8 @@ int main(void) { } MG_INFO(("Initialising application...")); - web_init(&mgr); + mg_http_listen(&mgr, "http://0.0.0.0", fn, NULL); + //web_init(&mgr); MG_INFO(("Starting event loop")); for (;;) { @@ -74,4 +80,4 @@ int main(void) { } return 0; -} \ No newline at end of file +} diff --git a/mongoose.c b/mongoose.c index a84d6bd3..6f8472e6 100644 --- a/mongoose.c +++ b/mongoose.c @@ -5519,7 +5519,8 @@ static inline uint32_t mg_swap32(uint32_t v) { return (v >> 24) | (v >> 8 & 0xff00) | (v << 8 & 0xff0000) | (v << 24); } static inline uint64_t mg_swap64(uint64_t v) { - return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | mg_swap32(v >> 32); + return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | + mg_swap32((uint32_t) (v >> 32)); } static inline uint16_t mg_be16(uint16_t v) { return mg_is_big_endian() ? mg_swap16(v) : v; @@ -5569,7 +5570,7 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { (void) c, (void) buf, (void) len; char tmp[8192]; long n = mg_io_recv(c, tmp, sizeof(tmp)); - if (n > 0) mg_hexdump(tmp, n); + if (n > 0) mg_hexdump(tmp, (size_t) n); MG_INFO(("AAAAAAAA")); return -1; // struct mg_tls *tls = (struct mg_tls *) c->tls; @@ -5592,7 +5593,7 @@ void mg_tls_handshake(struct mg_connection *c) { mg_iobuf_resize(rio, rio->len + 1); long n = mg_io_recv(c, &rio->buf[rio->len], rio->size - rio->len); if (n > 0) { - rio->len += n; + rio->len += (size_t) n; } else if (n == MG_IO_WAIT) { break; } else { @@ -5609,7 +5610,7 @@ void mg_tls_handshake(struct mg_connection *c) { mg_error(c, "no 22"); return; } - if (rio->len < TLS_HDR_SIZE + record_len) return; + if (rio->len < (size_t) TLS_HDR_SIZE + record_len) return; // Got full hello // struct tls_hello *hello = (struct tls_hello *) (hdr + 1); MG_INFO(("CT=%d V=%hx L=%hu", record_type, record_version, record_len)); @@ -5629,8 +5630,8 @@ void mg_tls_handshake(struct mg_connection *c) { add16(wio, 51), add16(wio, 36), add16(wio, 29), add16(wio, 32); // keyshare mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random mg_random(wio->buf + wio->len - 32, 32); // bytes - *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); - *(uint16_t *) &wio->buf[ofs + 7] = mg_be16(wio->len - ofs - 9); + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16((uint16_t) (wio->len - ofs - 5)); + *(uint16_t *) &wio->buf[ofs + 7] = mg_be16((uint16_t) (wio->len - ofs - 9)); // Change cipher. Cipher's payload is an encypted app data // ofs = wio->len; @@ -5645,7 +5646,7 @@ void mg_tls_handshake(struct mg_connection *c) { add8(wio, 0), add16(wio, 2), add16(wio, 0); // empty 2 bytes add8(wio, 11); // certificate message add8(wio, 0), add16(wio, 4), add32(wio, 0x1020304); // len - *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16((uint16_t)(wio->len - ofs - 5)); mg_io_send(c, wio->buf, wio->len); wio->len = 0; @@ -7031,215 +7032,131 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { #endif -#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \ + MG_ENABLE_DRIVER_SAME54 + +#include #undef BIT #define BIT(x) ((uint32_t) 1 << (x)) #define ETH_PKT_SIZE 1536 // Max frame size -#define GMAC_DESC_CNT 4 // Descriptors count -#define GMAC_DS 2 // Descriptor size (words) +#define ETH_DESC_CNT 4 // Descriptors count +#define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers -static uint8_t s_txbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers -static uint32_t s_rxdesc[GMAC_DESC_CNT][GMAC_DS]; // RX descriptors -static uint32_t s_txdesc[GMAC_DESC_CNT][GMAC_DS]; // TX descriptors -static uint8_t s_txno; // Current TX descriptor -static uint8_t s_rxno; // Current RX descriptor +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors +static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface -enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1}; +enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { - GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation - GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address - GMAC_MAN_REGA(reg); // Setting the register - while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the read op is complete - return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | + GMAC_MAN_OP(2) | // Setting the read operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0; + return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value } +#if 0 static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete } +#endif static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; s_ifp = ifp; - // enabling GMAC bus clocks - MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC(1); - MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC(1); - - GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_RXEN_Msk; // Disable receive circuit - GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_TXEN_Msk; // Disable transmit circuit - - GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_TXPBMS(1); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_RXBMS(2); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_FBLDO(4); - - // Init RX descriptors - for (int i = 0; i < GMAC_DESC_CNT; i++) { - s_rxdesc[i][0] = ((uint32_t) s_rxbuf[i]) & 0xfffffffc; // Point to data buffer (bits [31:2]) - s_rxdesc[i][1] = 0; - } - s_rxdesc[GMAC_DESC_CNT - 1][0] |= BIT(1); // Marking last rx descriptor + MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; + MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX + GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO // Init TX descriptors - for (int i = 0; i < GMAC_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer - s_txdesc[i][1] = BIT(31); // Setting the OWN bit + s_txdesc[i][1] = BIT(31); // OWN bit } - s_txdesc[GMAC_DESC_CNT - 1][1] |= BIT(30); // Marking last tx descriptor + s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // let the controller know about the descriptor addresses - GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; - GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; - - // GPIO pin configuration - MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; // //enable bus clock for PORT - uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15), - PIN('A', 17), PIN('A', 18), PIN('A', 19), - PIN('C', 11), PIN('C', 12), PIN('C', 20)}; - - uint32_t pin_fns[] = { - MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0, MUX_PA14L_GMAC_GTXCK, - MUX_PA15L_GMAC_GRXER, MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0, - MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC, MUX_PC12L_GMAC_GMDIO, - MUX_PC20L_GMAC_GRXDV - }; - - for (uint32_t i = 0; i < sizeof(pins) / sizeof(uint16_t); i++) { - uint8_t group = (uint8_t) (pins[i] >> 8); - uint8_t pin_no = (uint8_t) pins[i]; - PORT_REGS->GROUP[group].PORT_PINCFG[pin_no] |= PORT_PINCFG_PMUXEN_Msk; - if (pin_no % 2) - PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXO(pin_fns[i]); - else - PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXE(pin_fns[i]); + // Init RX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk; - PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk; - PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk; + GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses + GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // RMII operation mode + // Select RMII operation mode + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; - // Resetting the PHY - /*uint64_t start = mg_millis(), now = start; - PORT_REGS->GROUP[2].PORT_DIRSET = PORT_PC21; - PORT_REGS->GROUP[2].PORT_OUTCLR = PORT_PC21; - for (; now - start < 10000; now = mg_millis()); - PORT_REGS->GROUP[2].PORT_OUTSET = PORT_PC21; - for (start = mg_millis(), now = start; now - start < 10000; now = mg_millis());*/ + // Configure the receive filter + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | + GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - // Clock advanced configuration -#if 0 - uint8_t mdc_clk_div = 5; + // Clear transmit status register + GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | + GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | + GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | + GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - // get MCLK from GCLK_GENERATOR 0 - uint32_t div = 512; - uint32_t mclk; - if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) - div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); - switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { - case GCLK_GENCTRL_SRC_XOSC0_Val: - mclk = 32000000UL; /* 32MHz */ - break; - case GCLK_GENCTRL_SRC_XOSC1_Val: - mclk = 32000000UL; /* 32MHz */ - break; - case GCLK_GENCTRL_SRC_OSCULP32K_Val: - mclk = 32000UL; - break; - case GCLK_GENCTRL_SRC_XOSC32K_Val: - mclk = 32000UL; - break; - case GCLK_GENCTRL_SRC_DFLL_Val: - mclk = 48000000UL; /* 48MHz */ - break; - case GCLK_GENCTRL_SRC_DPLL0_Val: - mclk = 200000000UL; /* 200MHz */ - break; - case GCLK_GENCTRL_SRC_DPLL1_Val: - mclk = 200000000UL; /* 200MHz */ - break; - default: - mclk = 200000000UL; /* 200MHz */ - } + // Clear receive status register + GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | + GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - mclk /= div; + // First disable all GMAC interrupts + GMAC_REGS->GMAC_IDR = ~0U; - uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values - uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers - for (int i = 0; i < 6; i++) { - if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { - mdc_clk_div = crs[i]; - break; - } - } + // Only the desired ones are enabled + GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | + GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | + GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | + GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; -#endif + // Enable the GMAC to transmit and receive data + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(5); // set the MDC clock - GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; //enable management port - - // configure MAC - GMAC_REGS->SA[0].GMAC_SAT = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; - GMAC_REGS->SA[0].GMAC_SAB = (uint32_t) (ifp->mac[3] << 24) | - ((uint32_t) ifp->mac[2] << 16) | - ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - - //Configure the receive filter - GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk; - - //GMAC_REGS->GMAC_IER = GMAC_IER_RCOMP(1); // Enable the receive interrupt - GMAC_REGS->GMAC_IER = 0x3ffcfcff; // Enabling all interrupts NVIC_EnableIRQ(GMAC_IRQn); - GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk; // Enable transmit circuit - GMAC_REGS->GMAC_NCR |= GMAC_NCR_RXEN_Msk ; // Enable receive circuit - return true; } static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, - struct mg_tcpip_if *ifp) { - //MG_INFO(("DMAC_CTRL: 0x%x", DMAC_REGS->DMAC_CTRL)); - MG_INFO(("GMAC_TSR: 0x%x", GMAC_REGS->GMAC_TSR)); - GMAC_REGS->GMAC_TSR |= 0x21; - uint32_t rsr = GMAC_REGS->GMAC_RSR; - MG_INFO(("GMAC_RSR: 0x%x", rsr)); - GMAC_REGS->GMAC_RSR = rsr; + struct mg_tcpip_if *ifp) { if (len > sizeof(s_txbuf[s_txno])) { MG_ERROR(("Frame too big, %ld", (long) len)); len = 0; // Frame is too big - } else if (!(s_txdesc[s_txno][1] & BIT(31))) { + } else if ((s_txdesc[s_txno][1] & BIT(31)) == 0) { ifp->nerr++; MG_ERROR(("No free descriptors")); len = 0; // All descriptors are busy, fail } else { - memcpy(s_txbuf[s_txno], buf, len); // Copy data - if (++s_txno >= GMAC_DESC_CNT) { - s_txdesc[GMAC_DESC_CNT - 1][1] = (len & (BIT(14) - 1)) | BIT(15)| BIT(30); - s_txno = 0; - MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", GMAC_DESC_CNT - 1, s_txdesc[GMAC_DESC_CNT - 1][1])); - } else { - s_txdesc[s_txno - 1][1] = (len & (BIT(14) - 1)) | BIT(15); - MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", s_txno - 1, s_txdesc[s_txno - 1][1])); - } + uint32_t status = len | BIT(15); // Frame length, last chunk + if (s_txno == ETH_DESC_CNT - 1) status |= BIT(30); // wrap + memcpy(s_txbuf[s_txno], buf, len); // Copy data + s_txdesc[s_txno][1] = status; + if (++s_txno >= ETH_DESC_CNT) s_txno = 0; } __DSB(); // Ensure descriptors have been written - GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission return len; } static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - //MG_INFO(("BSR: 0x%x", bsr)); + // MG_INFO(("BSR: 0x%x", bsr)); bool up = bsr & BIT(2) ? 1 : 0; (void) ifp; return up; @@ -7247,69 +7164,37 @@ static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { void GMAC_Handler(void); void GMAC_Handler(void) { - MG_INFO(("Entering GMAC IRQ HANDLER")); uint32_t isr = GMAC_REGS->GMAC_ISR; - MG_INFO(("isr: 0x%x", isr)); - if (/*GMAC_REGS->GMAC_ISR*/ isr & GMAC_ISR_RCOMP_Msk) { - int frame_start = -1; - int frame_end = -1; - - // find the start of the frame - for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (!(s_rxdesc[desc_index][0] & 1)) break; - if (s_rxdesc[desc_index][1] & BIT(14)) - frame_start = desc_index; - } - - // if frame start not found, then clear the own bit - if (frame_start == -1) { - for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (!(s_rxdesc[desc_index][0] & 1)) { - break; - } else { - s_rxdesc[desc_index][0] &= ~(BIT(0)); - } + uint32_t rsr = GMAC_REGS->GMAC_RSR; + uint32_t tsr = GMAC_REGS->GMAC_TSR; + // MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & BIT(1)) { + if (rsr & BIT(1)) { + for (int i = 0; i < 10; i++) { + if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; + uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); + s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown + if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; } - return; - } - - // find the end of the frame - for (int i = frame_start; i < GMAC_DESC_CNT + frame_start; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (s_rxdesc[desc_index][1] & BIT(15)) - frame_end = desc_index; - } - - // clear all used buffers until you reach start of frame - for (int i = 0; i < GMAC_DESC_CNT; i++) { - int desc_index = (i + s_rxno) % GMAC_DESC_CNT; - if (s_rxno == frame_start) break; - if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; - s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit - } - - // from start of frame to end of frame you copy into queue - size_t offset = 0, len; - for (int i = 0; i < GMAC_DESC_CNT; i++) { - int desc_index = (i + s_rxno) % GMAC_DESC_CNT; - if (desc_index == frame_start) - offset = (GMAC_REGS->GMAC_NCFGR & GMAC_NCFGR_RXBUFO_Msk) >> GMAC_NCFGR_RXBUFO_Pos; - else - offset = 0; - len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); - mg_tcpip_qwrite(s_rxbuf[s_rxno] + offset, len, s_ifp); - s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit - if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; - if (desc_index == frame_end) break; } } + + if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | + GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | + GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { + GMAC_REGS->GMAC_TSR = tsr; + MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); + } + + GMAC_REGS->GMAC_RSR = rsr; + GMAC_REGS->GMAC_TSR = tsr; } -struct mg_tcpip_driver mg_tcpip_driver_same54 = {mg_tcpip_driver_same54_init, - mg_tcpip_driver_same54_tx, NULL, - mg_tcpip_driver_same54_up}; +struct mg_tcpip_driver mg_tcpip_driver_same54 = { + mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL, + mg_tcpip_driver_same54_up}; #endif #ifdef MG_ENABLE_LINES @@ -8971,8 +8856,8 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { mkpay(&pkt, pkt.ip + 1); rx_ip(ifp, &pkt); } else { - MG_DEBUG((" Unknown eth type %x", mg_htons(pkt.eth->type))); - mg_hexdump(buf, len >= 16 ? 16 : len); + MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type))); + mg_hexdump(buf, len >= 32 ? 32 : len); } } diff --git a/mongoose.h b/mongoose.h index d251d22e..2ad6f32c 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1326,7 +1326,7 @@ void mg_http_serve_ssi(struct mg_connection *c, const char *root, #define MG_TLS_CUSTOM 4 // Custom implementation #ifndef MG_TLS -#define MG_TLS MG_TLS_BUILTIN +#define MG_TLS MG_TLS_NONE #endif @@ -1725,8 +1725,6 @@ struct mg_tcpip_driver_imxrt1020_data { #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 -#include "hal.h" // keep this include - struct mg_tcpip_driver_same54_data { int mdc_cr; }; diff --git a/src/tcpip/driver_same54.c b/src/tcpip/driver_same54.c index d423cdcb..de995555 100644 --- a/src/tcpip/driver_same54.c +++ b/src/tcpip/driver_same54.c @@ -1,214 +1,130 @@ #include "tcpip.h" -#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \ + MG_ENABLE_DRIVER_SAME54 + +#include #undef BIT #define BIT(x) ((uint32_t) 1 << (x)) #define ETH_PKT_SIZE 1536 // Max frame size -#define GMAC_DESC_CNT 4 // Descriptors count -#define GMAC_DS 2 // Descriptor size (words) +#define ETH_DESC_CNT 4 // Descriptors count +#define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers -static uint8_t s_txbuf[GMAC_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers -static uint32_t s_rxdesc[GMAC_DESC_CNT][GMAC_DS]; // RX descriptors -static uint32_t s_txdesc[GMAC_DESC_CNT][GMAC_DS]; // TX descriptors -static uint8_t s_txno; // Current TX descriptor -static uint8_t s_rxno; // Current RX descriptor +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors +static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface -enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1}; +enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { - GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation - GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address - GMAC_MAN_REGA(reg); // Setting the register - while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the read op is complete - return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value + GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | + GMAC_MAN_OP(2) | // Setting the read operation + GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address + GMAC_MAN_REGA(reg); // Setting the register + while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0; + return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value } +#if 0 static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete } +#endif static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; s_ifp = ifp; - // enabling GMAC bus clocks - MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC(1); - MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC(1); - - GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_RXEN_Msk; // Disable receive circuit - GMAC_REGS->GMAC_NCR &= ~GMAC_NCR_TXEN_Msk; // Disable transmit circuit - - GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_TXPBMS(1); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_RXBMS(2); - GMAC_REGS->GMAC_DCFGR |= GMAC_DCFGR_FBLDO(4); - - // Init RX descriptors - for (int i = 0; i < GMAC_DESC_CNT; i++) { - s_rxdesc[i][0] = ((uint32_t) s_rxbuf[i]) & 0xfffffffc; // Point to data buffer (bits [31:2]) - s_rxdesc[i][1] = 0; - } - s_rxdesc[GMAC_DESC_CNT - 1][0] |= BIT(1); // Marking last rx descriptor + MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; + MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX + GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO // Init TX descriptors - for (int i = 0; i < GMAC_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer - s_txdesc[i][1] = BIT(31); // Setting the OWN bit + s_txdesc[i][1] = BIT(31); // OWN bit } - s_txdesc[GMAC_DESC_CNT - 1][1] |= BIT(30); // Marking last tx descriptor + s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // let the controller know about the descriptor addresses - GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; - GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; - - // GPIO pin configuration - MCLK_REGS->MCLK_APBBMASK |= MCLK_APBBMASK_PORT_Msk; // //enable bus clock for PORT - uint16_t pins[] = {PIN('A', 12), PIN('A', 13), PIN('A', 14), PIN('A', 15), - PIN('A', 17), PIN('A', 18), PIN('A', 19), - PIN('C', 11), PIN('C', 12), PIN('C', 20)}; - - uint32_t pin_fns[] = { - MUX_PA12L_GMAC_GRX1, MUX_PA13L_GMAC_GRX0, MUX_PA14L_GMAC_GTXCK, - MUX_PA15L_GMAC_GRXER, MUX_PA17L_GMAC_GTXEN, MUX_PA18L_GMAC_GTX0, - MUX_PA19L_GMAC_GTX1, MUX_PC11L_GMAC_GMDC, MUX_PC12L_GMAC_GMDIO, - MUX_PC20L_GMAC_GRXDV - }; - - for (uint32_t i = 0; i < sizeof(pins) / sizeof(uint16_t); i++) { - uint8_t group = (uint8_t) (pins[i] >> 8); - uint8_t pin_no = (uint8_t) pins[i]; - PORT_REGS->GROUP[group].PORT_PINCFG[pin_no] |= PORT_PINCFG_PMUXEN_Msk; - if (pin_no % 2) - PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXO(pin_fns[i]); - else - PORT_REGS->GROUP[group].PORT_PMUX[pin_no / 2] |= (uint8_t) PORT_PMUX_PMUXE(pin_fns[i]); + // Init RX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - PORT_REGS->GROUP[0].PORT_PINCFG[17] |= PORT_PINCFG_DRVSTR_Msk; - PORT_REGS->GROUP[0].PORT_PINCFG[18] |= PORT_PINCFG_DRVSTR_Msk; - PORT_REGS->GROUP[0].PORT_PINCFG[19] |= PORT_PINCFG_DRVSTR_Msk; + GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses + GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // RMII operation mode + // Select RMII operation mode + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; - // Resetting the PHY - /*uint64_t start = mg_millis(), now = start; - PORT_REGS->GROUP[2].PORT_DIRSET = PORT_PC21; - PORT_REGS->GROUP[2].PORT_OUTCLR = PORT_PC21; - for (; now - start < 10000; now = mg_millis()); - PORT_REGS->GROUP[2].PORT_OUTSET = PORT_PC21; - for (start = mg_millis(), now = start; now - start < 10000; now = mg_millis());*/ + // Configure the receive filter + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | + GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - // Clock advanced configuration -#if 0 - uint8_t mdc_clk_div = 5; + // Clear transmit status register + GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | + GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | + GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | + GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - // get MCLK from GCLK_GENERATOR 0 - uint32_t div = 512; - uint32_t mclk; - if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) - div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); - switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { - case GCLK_GENCTRL_SRC_XOSC0_Val: - mclk = 32000000UL; /* 32MHz */ - break; - case GCLK_GENCTRL_SRC_XOSC1_Val: - mclk = 32000000UL; /* 32MHz */ - break; - case GCLK_GENCTRL_SRC_OSCULP32K_Val: - mclk = 32000UL; - break; - case GCLK_GENCTRL_SRC_XOSC32K_Val: - mclk = 32000UL; - break; - case GCLK_GENCTRL_SRC_DFLL_Val: - mclk = 48000000UL; /* 48MHz */ - break; - case GCLK_GENCTRL_SRC_DPLL0_Val: - mclk = 200000000UL; /* 200MHz */ - break; - case GCLK_GENCTRL_SRC_DPLL1_Val: - mclk = 200000000UL; /* 200MHz */ - break; - default: - mclk = 200000000UL; /* 200MHz */ - } + // Clear receive status register + GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | + GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - mclk /= div; + // First disable all GMAC interrupts + GMAC_REGS->GMAC_IDR = ~0U; - uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values - uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers - for (int i = 0; i < 6; i++) { - if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { - mdc_clk_div = crs[i]; - break; - } - } + // Only the desired ones are enabled + GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | + GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | + GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | + GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; -#endif + // Enable the GMAC to transmit and receive data + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(5); // set the MDC clock - GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; //enable management port - - // configure MAC - GMAC_REGS->SA[0].GMAC_SAT = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; - GMAC_REGS->SA[0].GMAC_SAB = (uint32_t) (ifp->mac[3] << 24) | - ((uint32_t) ifp->mac[2] << 16) | - ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; - - //Configure the receive filter - GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk; - - //GMAC_REGS->GMAC_IER = GMAC_IER_RCOMP(1); // Enable the receive interrupt - GMAC_REGS->GMAC_IER = 0x3ffcfcff; // Enabling all interrupts NVIC_EnableIRQ(GMAC_IRQn); - GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk; // Enable transmit circuit - GMAC_REGS->GMAC_NCR |= GMAC_NCR_RXEN_Msk ; // Enable receive circuit - return true; } static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, - struct mg_tcpip_if *ifp) { - //MG_INFO(("DMAC_CTRL: 0x%x", DMAC_REGS->DMAC_CTRL)); - MG_INFO(("GMAC_TSR: 0x%x", GMAC_REGS->GMAC_TSR)); - GMAC_REGS->GMAC_TSR |= 0x21; - uint32_t rsr = GMAC_REGS->GMAC_RSR; - MG_INFO(("GMAC_RSR: 0x%x", rsr)); - GMAC_REGS->GMAC_RSR = rsr; + struct mg_tcpip_if *ifp) { if (len > sizeof(s_txbuf[s_txno])) { MG_ERROR(("Frame too big, %ld", (long) len)); len = 0; // Frame is too big - } else if (!(s_txdesc[s_txno][1] & BIT(31))) { + } else if ((s_txdesc[s_txno][1] & BIT(31)) == 0) { ifp->nerr++; MG_ERROR(("No free descriptors")); len = 0; // All descriptors are busy, fail } else { - memcpy(s_txbuf[s_txno], buf, len); // Copy data - if (++s_txno >= GMAC_DESC_CNT) { - s_txdesc[GMAC_DESC_CNT - 1][1] = (len & (BIT(14) - 1)) | BIT(15)| BIT(30); - s_txno = 0; - MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", GMAC_DESC_CNT - 1, s_txdesc[GMAC_DESC_CNT - 1][1])); - } else { - s_txdesc[s_txno - 1][1] = (len & (BIT(14) - 1)) | BIT(15); - MG_INFO(("s_tx_no: %d, tx_desc.status: 0x%x", s_txno - 1, s_txdesc[s_txno - 1][1])); - } + uint32_t status = len | BIT(15); // Frame length, last chunk + if (s_txno == ETH_DESC_CNT - 1) status |= BIT(30); // wrap + memcpy(s_txbuf[s_txno], buf, len); // Copy data + s_txdesc[s_txno][1] = status; + if (++s_txno >= ETH_DESC_CNT) s_txno = 0; } __DSB(); // Ensure descriptors have been written - GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission + GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission return len; } static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - //MG_INFO(("BSR: 0x%x", bsr)); + // MG_INFO(("BSR: 0x%x", bsr)); bool up = bsr & BIT(2) ? 1 : 0; (void) ifp; return up; @@ -216,67 +132,35 @@ static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { void GMAC_Handler(void); void GMAC_Handler(void) { - MG_INFO(("Entering GMAC IRQ HANDLER")); uint32_t isr = GMAC_REGS->GMAC_ISR; - MG_INFO(("isr: 0x%x", isr)); - if (/*GMAC_REGS->GMAC_ISR*/ isr & GMAC_ISR_RCOMP_Msk) { - int frame_start = -1; - int frame_end = -1; - - // find the start of the frame - for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (!(s_rxdesc[desc_index][0] & 1)) break; - if (s_rxdesc[desc_index][1] & BIT(14)) - frame_start = desc_index; - } - - // if frame start not found, then clear the own bit - if (frame_start == -1) { - for (int i = s_rxno; i < GMAC_DESC_CNT + s_rxno; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (!(s_rxdesc[desc_index][0] & 1)) { - break; - } else { - s_rxdesc[desc_index][0] &= ~(BIT(0)); - } + uint32_t rsr = GMAC_REGS->GMAC_RSR; + uint32_t tsr = GMAC_REGS->GMAC_TSR; + // MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & BIT(1)) { + if (rsr & BIT(1)) { + for (int i = 0; i < 10; i++) { + if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; + uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); + s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown + if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; } - return; - } - - // find the end of the frame - for (int i = frame_start; i < GMAC_DESC_CNT + frame_start; i++) { - int desc_index = i % GMAC_DESC_CNT; - if (s_rxdesc[desc_index][1] & BIT(15)) - frame_end = desc_index; - } - - // clear all used buffers until you reach start of frame - for (int i = 0; i < GMAC_DESC_CNT; i++) { - int desc_index = (i + s_rxno) % GMAC_DESC_CNT; - if (s_rxno == frame_start) break; - if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; - s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit - } - - // from start of frame to end of frame you copy into queue - size_t offset = 0, len; - for (int i = 0; i < GMAC_DESC_CNT; i++) { - int desc_index = (i + s_rxno) % GMAC_DESC_CNT; - if (desc_index == frame_start) - offset = (GMAC_REGS->GMAC_NCFGR & GMAC_NCFGR_RXBUFO_Msk) >> GMAC_NCFGR_RXBUFO_Pos; - else - offset = 0; - len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); - mg_tcpip_qwrite(s_rxbuf[s_rxno] + offset, len, s_ifp); - s_rxdesc[desc_index][0] &= ~(BIT(0)); // Clearing the OWN bit - if (++s_rxno >= GMAC_DESC_CNT) s_rxno = 0; - if (desc_index == frame_end) break; } } + + if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | + GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | + GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { + GMAC_REGS->GMAC_TSR = tsr; + MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); + } + + GMAC_REGS->GMAC_RSR = rsr; + GMAC_REGS->GMAC_TSR = tsr; } -struct mg_tcpip_driver mg_tcpip_driver_same54 = {mg_tcpip_driver_same54_init, - mg_tcpip_driver_same54_tx, NULL, - mg_tcpip_driver_same54_up}; +struct mg_tcpip_driver mg_tcpip_driver_same54 = { + mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL, + mg_tcpip_driver_same54_up}; #endif diff --git a/src/tcpip/driver_same54.h b/src/tcpip/driver_same54.h index c5552dbb..4e92adb6 100644 --- a/src/tcpip/driver_same54.h +++ b/src/tcpip/driver_same54.h @@ -2,8 +2,6 @@ #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 -#include "hal.h" // keep this include - struct mg_tcpip_driver_same54_data { int mdc_cr; }; diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index 52a8c139..bfdc1d65 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -794,8 +794,8 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { mkpay(&pkt, pkt.ip + 1); rx_ip(ifp, &pkt); } else { - MG_DEBUG((" Unknown eth type %x", mg_htons(pkt.eth->type))); - mg_hexdump(buf, len >= 16 ? 16 : len); + MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type))); + mg_hexdump(buf, len >= 32 ? 32 : len); } } diff --git a/src/tls.h b/src/tls.h index 9ce371af..97128d94 100644 --- a/src/tls.h +++ b/src/tls.h @@ -7,7 +7,7 @@ #define MG_TLS_CUSTOM 4 // Custom implementation #ifndef MG_TLS -#define MG_TLS MG_TLS_BUILTIN +#define MG_TLS MG_TLS_NONE #endif #include "net.h" diff --git a/src/tls_builtin.c b/src/tls_builtin.c index 0c53b708..eebe5a48 100644 --- a/src/tls_builtin.c +++ b/src/tls_builtin.c @@ -20,7 +20,8 @@ static inline uint32_t mg_swap32(uint32_t v) { return (v >> 24) | (v >> 8 & 0xff00) | (v << 8 & 0xff0000) | (v << 24); } static inline uint64_t mg_swap64(uint64_t v) { - return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | mg_swap32(v >> 32); + return (((uint64_t) mg_swap32((uint32_t) v)) << 32) | + mg_swap32((uint32_t) (v >> 32)); } static inline uint16_t mg_be16(uint16_t v) { return mg_is_big_endian() ? mg_swap16(v) : v; @@ -70,7 +71,7 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { (void) c, (void) buf, (void) len; char tmp[8192]; long n = mg_io_recv(c, tmp, sizeof(tmp)); - if (n > 0) mg_hexdump(tmp, n); + if (n > 0) mg_hexdump(tmp, (size_t) n); MG_INFO(("AAAAAAAA")); return -1; // struct mg_tls *tls = (struct mg_tls *) c->tls; @@ -93,7 +94,7 @@ void mg_tls_handshake(struct mg_connection *c) { mg_iobuf_resize(rio, rio->len + 1); long n = mg_io_recv(c, &rio->buf[rio->len], rio->size - rio->len); if (n > 0) { - rio->len += n; + rio->len += (size_t) n; } else if (n == MG_IO_WAIT) { break; } else { @@ -110,7 +111,7 @@ void mg_tls_handshake(struct mg_connection *c) { mg_error(c, "no 22"); return; } - if (rio->len < TLS_HDR_SIZE + record_len) return; + if (rio->len < (size_t) TLS_HDR_SIZE + record_len) return; // Got full hello // struct tls_hello *hello = (struct tls_hello *) (hdr + 1); MG_INFO(("CT=%d V=%hx L=%hu", record_type, record_version, record_len)); @@ -130,8 +131,8 @@ void mg_tls_handshake(struct mg_connection *c) { add16(wio, 51), add16(wio, 36), add16(wio, 29), add16(wio, 32); // keyshare mg_iobuf_add(wio, wio->len, NULL, 32); // 32 random mg_random(wio->buf + wio->len - 32, 32); // bytes - *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); - *(uint16_t *) &wio->buf[ofs + 7] = mg_be16(wio->len - ofs - 9); + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16((uint16_t) (wio->len - ofs - 5)); + *(uint16_t *) &wio->buf[ofs + 7] = mg_be16((uint16_t) (wio->len - ofs - 9)); // Change cipher. Cipher's payload is an encypted app data // ofs = wio->len; @@ -146,7 +147,7 @@ void mg_tls_handshake(struct mg_connection *c) { add8(wio, 0), add16(wio, 2), add16(wio, 0); // empty 2 bytes add8(wio, 11); // certificate message add8(wio, 0), add16(wio, 4), add32(wio, 0x1020304); // len - *(uint16_t *) &wio->buf[ofs + 3] = mg_be16(wio->len - ofs - 5); + *(uint16_t *) &wio->buf[ofs + 3] = mg_be16((uint16_t)(wio->len - ofs - 5)); mg_io_send(c, wio->buf, wio->len); wio->len = 0; From 519d4b0286de05c5e7d2f6ec49ce3a9a609ee1a6 Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 3 Aug 2023 09:32:02 +0100 Subject: [PATCH 5/6] Changes --- src/tcpip/driver_same54.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tcpip/driver_same54.c b/src/tcpip/driver_same54.c index de995555..33b6f13d 100644 --- a/src/tcpip/driver_same54.c +++ b/src/tcpip/driver_same54.c @@ -135,7 +135,7 @@ void GMAC_Handler(void) { uint32_t isr = GMAC_REGS->GMAC_ISR; uint32_t rsr = GMAC_REGS->GMAC_RSR; uint32_t tsr = GMAC_REGS->GMAC_TSR; - // MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); if (isr & BIT(1)) { if (rsr & BIT(1)) { for (int i = 0; i < 10; i++) { From 70fc71c6f706c3abd3690f06996b3f7c937d12ff Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 3 Aug 2023 09:49:57 +0100 Subject: [PATCH 6/6] Changes --- examples/device-dashboard/net.c | 8 +- examples/microchip/same54/Makefile | 2 +- examples/microchip/same54/hal.h | 21 +++-- examples/microchip/same54/main.c | 7 +- mongoose.c | 122 ++++++++++++++++++++--------- src/tcpip/driver_same54.c | 121 +++++++++++++++++++--------- src/tcpip/tcpip.c | 1 + 7 files changed, 194 insertions(+), 88 deletions(-) diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index 10816c5b..455c74af 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -56,14 +56,14 @@ uint64_t mg_now(void) { int ui_event_next(int no, struct ui_event *e) { if (no < 0 || no >= MAX_EVENTS_NO) return 0; - srand(no); + srand((unsigned) no); e->type = (uint8_t) rand() % 4; e->prio = (uint8_t) rand() % 3; e->timestamp = - (unsigned long) (mg_now() - 86400 * 1000 /* one day back */ + + (unsigned long) ((int64_t) mg_now() - 86400 * 1000 /* one day back */ + no * 300 * 1000 /* 5 mins between alerts */ + 1000 * (rand() % 300) /* randomize event time */) / - 1000; + 1000UL; mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no); return no + 1; @@ -163,7 +163,7 @@ static void handle_stats_get(struct mg_connection *c) { static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) { size_t len = 0; struct ui_event ev; - int pageno = va_arg(*ap, unsigned); + int pageno = va_arg(*ap, int); int no = (pageno - 1) * EVENTS_PER_PAGE; int end = no + EVENTS_PER_PAGE; diff --git a/examples/microchip/same54/Makefile b/examples/microchip/same54/Makefile index e9ec2448..9dfe63c6 100644 --- a/examples/microchip/same54/Makefile +++ b/examples/microchip/same54/Makefile @@ -11,7 +11,7 @@ SOURCES = main.c syscalls.c startup.c #SOURCES += cmsis_sam/xc32/ATSAME54P20A/startup_atsame54p20a.c SOURCES += mongoose.c net.c packed_fs.c -CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_LINES=1 +CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 #-DMG_ENABLE_LINES=1 CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA) VCON_API_KEY=IBrJL5K4arSGMiAXbUKWdG6I2gM diff --git a/examples/microchip/same54/hal.h b/examples/microchip/same54/hal.h index 80a24f7a..226548b8 100644 --- a/examples/microchip/same54/hal.h +++ b/examples/microchip/same54/hal.h @@ -149,13 +149,18 @@ static inline uint32_t rng_read(void) { return TRNG_REGS->TRNG_DATA; } -#define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 39.1 +#define UID_BASE_W0 0x008061FC // Word 0 location of the 128-bit chip ID +#define UID_BASE_W1_3 0x00806010 // Words 1-3 location of the 128-bit chip ID -// Helper macro for MAC generation -#define GENERATE_LOCALLY_ADMINISTERED_MAC() \ - { \ - 2, UUID[0] ^ UUID[1], UUID[2] ^ UUID[3], UUID[4] ^ UUID[5], \ - UUID[6] ^ UUID[7] ^ UUID[8], UUID[9] ^ UUID[10] ^ UUID[11] \ +#define UUID(n) ((n >= 0 && n <= 3) ? \ + (((uint8_t *) UID_BASE_W0)[n]) : \ + (((uint8_t *) UID_BASE_W1_3)[n - 4])) + +#define GENERATE_LOCALLY_ADMINISTERED_MAC() \ + { \ + 2, UUID(0) ^ UUID(1) ^ UUID(2), UUID(3) ^ UUID(4) ^ UUID(5), \ + UUID(6) ^ UUID(7) ^ UUID(8), UUID(9) ^ UUID(10) ^ UUID(11), \ + UUID(12) ^ UUID(13) ^ UUID(14) ^ UUID(15) \ } static inline bool timer_expired(volatile uint64_t *t, uint64_t prd, @@ -194,9 +199,9 @@ static inline void ethernet_init(void) { PORT_REGS->GROUP[bank].PORT_PINCFG[no] |= PORT_PINCFG_PMUXEN_Msk; volatile uint8_t *m = &PORT_REGS->GROUP[bank].PORT_PMUX[no / 2], v = m[0]; if (no & 1) { - m[0] = (uint8_t) (v & ~0xf0) | PORT_PMUX_PMUXO(af[i]); + m[0] = (uint8_t) ((v & ~0xf0) | PORT_PMUX_PMUXO(af[i])); } else { - m[0] = (uint8_t) (v & ~0x0f) | PORT_PMUX_PMUXE(af[i]); + m[0] = (uint8_t) ((v & ~0x0f) | PORT_PMUX_PMUXE(af[i])); } } diff --git a/examples/microchip/same54/main.c b/examples/microchip/same54/main.c index d6d1d9b2..08390285 100644 --- a/examples/microchip/same54/main.c +++ b/examples/microchip/same54/main.c @@ -39,7 +39,8 @@ static void timer_fn(void *arg) { static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n"); - } + (void) ev_data, (void) fn_data; +} int main(void) { gpio_input(BUTTON_PIN); @@ -55,7 +56,7 @@ int main(void) { // Initialise Mongoose network stack struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 5}; - struct mg_tcpip_if mif = {.mac = {2, 3, 4, 5, 6, 7}, + struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC()/*{2, 3, 4, 5, 6, 7}*/, // Uncomment below for static configuration: // .ip = mg_htonl(MG_U32(192, 168, 0, 223)), // .mask = mg_htonl(MG_U32(255, 255, 255, 0)), @@ -72,7 +73,7 @@ int main(void) { MG_INFO(("Initialising application...")); mg_http_listen(&mgr, "http://0.0.0.0", fn, NULL); - //web_init(&mgr); + // web_init(&mgr); MG_INFO(("Starting event loop")); for (;;) { diff --git a/mongoose.c b/mongoose.c index 6f8472e6..9a799837 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7043,8 +7043,8 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { #define ETH_DESC_CNT 4 // Descriptors count #define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); -static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors static uint8_t s_txno; // Current TX descriptor @@ -7053,6 +7053,10 @@ static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; +#define PHY_BCR_DUPLEX_MODE_Msk BIT(8) +#define PHY_BCR_SPEED_Msk BIT(13) +#define PHY_BSR_LINK_STATUS_Msk BIT(2) + static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation @@ -7071,6 +7075,56 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { } #endif +int get_clock_rate(struct mg_tcpip_driver_same54_data *d) { + if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) { + return d->mdc_cr; + } else { + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) { + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + if (div == 0) div = 1; + } + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + return crs[i]; + } + } + + return 5; + } +} + static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; @@ -7078,56 +7132,45 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO - // Init TX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer s_txdesc[i][1] = BIT(31); // OWN bit } s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // Init RX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { - s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer - s_rxdesc[i][1] = 0; // Clear status + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536 + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } - s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - // Select RMII operation mode - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; + GMAC_REGS->SA[0].GMAC_SAB = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); - // Configure the receive filter + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | - GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - - // Clear transmit status register + GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk; GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - - // Clear receive status register GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - - // First disable all GMAC interrupts - GMAC_REGS->GMAC_IDR = ~0U; - - // Only the desired ones are enabled + GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; - - // Enable the GMAC to transmit and receive data GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - NVIC_EnableIRQ(GMAC_IRQn); return true; @@ -7156,9 +7199,16 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - // MG_INFO(("BSR: 0x%x", bsr)); - bool up = bsr & BIT(2) ? 1 : 0; - (void) ifp; + bool up = bsr & PHY_BSR_LINK_STATUS_Msk ? 1 : 0; + + // If PHY is ready, update NCFGR accordingly + if (ifp->state == MG_TCPIP_STATE_DOWN && up) { + uint16_t bcr = eth_read_phy(PHY_ADDR, PHY_BCR); + bool fd = bcr & PHY_BCR_DUPLEX_MODE_Msk ? 1 : 0; + bool spd = bcr & PHY_BCR_SPEED_Msk ? 1 : 0; + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd); + } + return up; } @@ -7167,12 +7217,12 @@ void GMAC_Handler(void) { uint32_t isr = GMAC_REGS->GMAC_ISR; uint32_t rsr = GMAC_REGS->GMAC_RSR; uint32_t tsr = GMAC_REGS->GMAC_TSR; - // MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); - if (isr & BIT(1)) { - if (rsr & BIT(1)) { - for (int i = 0; i < 10; i++) { + //MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & GMAC_ISR_RCOMP_Msk) { + if (rsr & GMAC_ISR_RCOMP_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; - uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; @@ -7183,8 +7233,7 @@ void GMAC_Handler(void) { if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { - GMAC_REGS->GMAC_TSR = tsr; - MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + // MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); } @@ -8824,6 +8873,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { pkt.raw.ptr = (char *) buf; pkt.raw.len = len; pkt.eth = (struct eth *) buf; + //mg_hexdump(buf, len > 16 ? 16: len); if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (ifp->enable_mac_check && memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && diff --git a/src/tcpip/driver_same54.c b/src/tcpip/driver_same54.c index 33b6f13d..2b49197a 100644 --- a/src/tcpip/driver_same54.c +++ b/src/tcpip/driver_same54.c @@ -11,8 +11,8 @@ #define ETH_DESC_CNT 4 // Descriptors count #define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); -static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors static uint8_t s_txno; // Current TX descriptor @@ -21,6 +21,10 @@ static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; +#define PHY_BCR_DUPLEX_MODE_Msk BIT(8) +#define PHY_BCR_SPEED_Msk BIT(13) +#define PHY_BSR_LINK_STATUS_Msk BIT(2) + static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation @@ -39,6 +43,56 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { } #endif +int get_clock_rate(struct mg_tcpip_driver_same54_data *d) { + if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) { + return d->mdc_cr; + } else { + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) { + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + if (div == 0) div = 1; + } + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + return crs[i]; + } + } + + return 5; + } +} + static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; @@ -46,56 +100,45 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO - // Init TX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer s_txdesc[i][1] = BIT(31); // OWN bit } s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // Init RX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { - s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer - s_rxdesc[i][1] = 0; // Clear status + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536 + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } - s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - // Select RMII operation mode - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; + GMAC_REGS->SA[0].GMAC_SAB = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); - // Configure the receive filter + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | - GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - - // Clear transmit status register + GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk; GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - - // Clear receive status register GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - - // First disable all GMAC interrupts - GMAC_REGS->GMAC_IDR = ~0U; - - // Only the desired ones are enabled + GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; - - // Enable the GMAC to transmit and receive data GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - NVIC_EnableIRQ(GMAC_IRQn); return true; @@ -124,9 +167,16 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - // MG_INFO(("BSR: 0x%x", bsr)); - bool up = bsr & BIT(2) ? 1 : 0; - (void) ifp; + bool up = bsr & PHY_BSR_LINK_STATUS_Msk ? 1 : 0; + + // If PHY is ready, update NCFGR accordingly + if (ifp->state == MG_TCPIP_STATE_DOWN && up) { + uint16_t bcr = eth_read_phy(PHY_ADDR, PHY_BCR); + bool fd = bcr & PHY_BCR_DUPLEX_MODE_Msk ? 1 : 0; + bool spd = bcr & PHY_BCR_SPEED_Msk ? 1 : 0; + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd); + } + return up; } @@ -135,12 +185,12 @@ void GMAC_Handler(void) { uint32_t isr = GMAC_REGS->GMAC_ISR; uint32_t rsr = GMAC_REGS->GMAC_RSR; uint32_t tsr = GMAC_REGS->GMAC_TSR; - MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); - if (isr & BIT(1)) { - if (rsr & BIT(1)) { - for (int i = 0; i < 10; i++) { + //MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & GMAC_ISR_RCOMP_Msk) { + if (rsr & GMAC_ISR_RCOMP_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; - uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; @@ -151,8 +201,7 @@ void GMAC_Handler(void) { if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { - GMAC_REGS->GMAC_TSR = tsr; - MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + // MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); } diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index bfdc1d65..a0078f87 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -762,6 +762,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { pkt.raw.ptr = (char *) buf; pkt.raw.len = len; pkt.eth = (struct eth *) buf; + //mg_hexdump(buf, len > 16 ? 16: len); if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (ifp->enable_mac_check && memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&