mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-08 16:11:18 +00:00
Revamp rp examples
This commit is contained in:
1 parent
948b56a3ec
commit
83ba170b45
142 files changed
+769
-3721
No files matched your search
@@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
# If you will set board type here, do it BEFORE including the SDK
|
||||
# set(PICO_BOARD pico2)
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(firmware)
|
||||
pico_sdk_init()
|
||||
|
||||
add_executable(firmware main.c driver_rp2040_rmii.c mongoose/mongoose.c)
|
||||
target_include_directories(firmware PRIVATE . mongoose)
|
||||
|
||||
target_link_libraries(firmware hardware_pio hardware_dma pico_stdlib pico_rand)
|
||||
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
|
||||
pico_enable_stdio_usb(firmware 1) # Route stdio to USB
|
||||
|
||||
# Prevent extreme optimization from breaking OTA
|
||||
target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)
|
||||
@@ -0,0 +1,37 @@
|
||||
# Environment setup: https://mongoose.ws/docs/getting-started/build-environment/
|
||||
|
||||
CWD ?= $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
SDK_PATH ?= $(CWD)/pico-sdk
|
||||
RM = rm -rf
|
||||
MKBUILD = test -d build || mkdir build
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
RM = cmd /C del /Q /F /S
|
||||
MKBUILD = if not exist build mkdir build
|
||||
endif
|
||||
|
||||
.PHONY: build
|
||||
|
||||
all build example: build/firmware.uf2
|
||||
|
||||
build/firmware.uf2: pico_sdk_import.cmake mongoose/mongoose.c mongoose/mongoose.h
|
||||
|
||||
pico_sdk_import.cmake: $(SDK_PATH)
|
||||
cp $(SDK_PATH)/external/$@ $@
|
||||
|
||||
mongoose/mongoose.c mongoose/mongoose.h:
|
||||
cp ../../../$(notdir $@) $@
|
||||
|
||||
build/firmware.uf2: $(SDK_PATH) $(wildcard *.[ch]) CMakeLists.txt Makefile
|
||||
$(MKBUILD)
|
||||
cd build && PICO_SDK_PATH=$(SDK_PATH) cmake -G "Unix Makefiles" .. && make
|
||||
|
||||
flash: build/firmware.uf2
|
||||
picotool load $< -f
|
||||
|
||||
clean:
|
||||
$(RM) build pico_sdk_import.cmake mongoose/mongoose.c mongoose/mongoose.h $(SDK_PATH)
|
||||
|
||||
$(SDK_PATH):
|
||||
git clone -c advice.detachedHead=false --quiet --depth 1 -b 2.1.1 https://github.com/raspberrypi/pico-sdk $@
|
||||
cd $@ && git submodule update --quiet --init
|
||||
@@ -0,0 +1,28 @@
|
||||
# RP2040 / RP2350 Mongoose example
|
||||
|
||||
This example can be built for both RP2040 and RP2350 targets.
|
||||
|
||||
## Set target board
|
||||
|
||||
By default, it builds for RP2040 target. If you want to change the target
|
||||
board, edit `CMakeKists.txt` and set the board, for example:
|
||||
|
||||
```cmake
|
||||
set(PICO_BOARD pico2_w)
|
||||
```
|
||||
|
||||
## Edit WiFi credentials
|
||||
|
||||
For WiFi examples, edit `wifi.c` and set WiFi network name and password.
|
||||
|
||||
## Build and run
|
||||
|
||||
Make sure you have `picotool` installed. Then run:
|
||||
|
||||
```sh
|
||||
make build flash
|
||||
```
|
||||
|
||||
Start serial console to see the debug output.
|
||||
|
||||
See detailed documentation at https://mongoose.ws/docs/guides/rp-tcpip-stack/
|
||||
@@ -0,0 +1,337 @@
|
||||
// Copyright (c) 2022 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/pio.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "driver_rp2040_rmii.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define RXSM 0
|
||||
#define TXSM 1
|
||||
#define SMITXSM 2
|
||||
#define SMIRXSM 0 // pio1
|
||||
|
||||
static uint smi_wr_addr, smi_rd_addr;
|
||||
static int dma_rx;
|
||||
static int dma_tx;
|
||||
|
||||
static dma_channel_config dmacfg_rx;
|
||||
static dma_channel_config dmacfg_tx;
|
||||
|
||||
// Max frame size with VLAN tag + CRC and excluding preamble
|
||||
#define ETH_PKT_SIZE 1522
|
||||
|
||||
static uint8_t s_rxbuf[2][ETH_PKT_SIZE]; // ping-pong buffer
|
||||
static uint8_t s_txbuf[ETH_PKT_SIZE];
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
|
||||
#define rmii_tx_wrap_target 0
|
||||
#define rmii_tx_wrap 7
|
||||
|
||||
static const uint16_t rmii_tx_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe000, // 0: set pins, 0 side 0
|
||||
0x80a0, // 1: pull block side 0
|
||||
0xe03d, // 2: set x, 29 side 0
|
||||
0xf101, // 3: set pins, 1 side 1 [1]
|
||||
0x1144, // 4: jmp x--, 4 side 1 [1]
|
||||
0xf103, // 5: set pins, 3 side 1 [1]
|
||||
0x7002, // 6: out pins, 2 side 1
|
||||
0x10e6, // 7: jmp !osre, 6 side 1
|
||||
// .wrap
|
||||
};
|
||||
|
||||
static const struct pio_program rmii_tx_program = {
|
||||
.instructions = rmii_tx_program_instructions,
|
||||
.length = 8,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config rmii_tx_program_get_default_config(uint addr) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, addr + rmii_tx_wrap_target, addr + rmii_tx_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void rmii_tx_init(PIO pio, uint sm, uint addr, uint gpio) {
|
||||
pio_sm_config c = rmii_tx_program_get_default_config(addr);
|
||||
pio_gpio_init(pio, gpio);
|
||||
pio_gpio_init(pio, gpio + 1);
|
||||
pio_gpio_init(pio, gpio + 2);
|
||||
sm_config_set_out_pins(&c, gpio, 2);
|
||||
sm_config_set_set_pins(&c, gpio, 2);
|
||||
sm_config_set_sideset_pins(&c, gpio + 2);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 3, true);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
sm_config_set_out_shift(&c, true, true, 8); // pull bytes, LSB first, auto
|
||||
sm_config_set_clkdiv(&c,
|
||||
5); // Run at 50/5 = 10MHz (2x 2-bit nibble data rate)
|
||||
pio_sm_init(pio, sm, addr, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#define rmii_rx_wrap_target 0
|
||||
#define rmii_rx_wrap 10
|
||||
|
||||
static const uint16_t rmii_rx_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x2122, // 0: wait 0 pin, 2 [1]
|
||||
0x21a2, // 1: wait 1 pin, 2 [1]
|
||||
0x21a0, // 2: wait 1 pin, 0 [1]
|
||||
0x2121, // 3: wait 0 pin, 1 [1]
|
||||
0x21a1, // 4: wait 1 pin, 1 [1]
|
||||
0x4002, // 5: in pins, 2
|
||||
0x00c5, // 6: jmp pin, 5
|
||||
0x4002, // 7: in pins, 2
|
||||
0x00c5, // 8: jmp pin, 5
|
||||
0xa0c3, // 9: mov isr, null
|
||||
0xc020, // 10: irq wait 0
|
||||
// .wrap
|
||||
};
|
||||
|
||||
static const struct pio_program rmii_rx_program = {
|
||||
.instructions = rmii_rx_program_instructions,
|
||||
.length = 11,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config rmii_rx_program_get_default_config(uint addr) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, addr + rmii_rx_wrap_target, addr + rmii_rx_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void rmii_rx_init(PIO pio, uint sm, uint addr, uint gpio) {
|
||||
pio_sm_config c = rmii_rx_program_get_default_config(addr);
|
||||
pio_gpio_init(pio, gpio);
|
||||
pio_gpio_init(pio, gpio + 1);
|
||||
pio_gpio_init(pio, gpio + 2);
|
||||
sm_config_set_in_pins(&c, gpio);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 3, false);
|
||||
sm_config_set_jmp_pin(&c, gpio + 2);
|
||||
sm_config_set_in_shift(&c, true, true, 8); // push bytes, LSB first, auto
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
sm_config_set_clkdiv(&c,
|
||||
5); // Run at 50/5 = 10MHz (2x 2-bit nibble data rate)
|
||||
pio_sm_init(pio, sm, addr, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
#define smi_wr_wrap_target 0
|
||||
#define smi_wr_wrap 4
|
||||
|
||||
static const uint16_t smi_wr_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe03f, // 0: set x, 31 side 0
|
||||
0xe101, // 1: set pins, 1 side 0 [1]
|
||||
0x1141, // 2: jmp x--, 1 side 1 [1]
|
||||
0x6101, // 3: out pins, 1 side 0 [1]
|
||||
0x1103, // 4: jmp 3 side 1 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
static const struct pio_program smi_wr_program = {
|
||||
.instructions = smi_wr_program_instructions,
|
||||
.length = 5,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config smi_wr_program_get_default_config(uint addr) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, addr + smi_wr_wrap_target, addr + smi_wr_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
#define smi_rd_wrap_target 13
|
||||
#define smi_rd_wrap 13
|
||||
|
||||
static const uint16_t smi_rd_program_instructions[] = {
|
||||
0xe03f, // 0: set x, 31 side 0
|
||||
0xe101, // 1: set pins, 1 side 0 [1]
|
||||
0x1141, // 2: jmp x--, 1 side 1 [1]
|
||||
0xf02d, // 3: set x, 13 side 1
|
||||
0x6101, // 4: out pins, 1 side 0 [1]
|
||||
0x1144, // 5: jmp x--, 4 side 1 [1]
|
||||
0xe180, // 6: set pindirs, 0 side 0 [1]
|
||||
0xf101, // 7: set pins, 1 side 1 [1]
|
||||
0xa142, // 8: nop side 0 [1]
|
||||
0xf12f, // 9: set x, 15 side 1 [1]
|
||||
0xa042, // 10: nop side 0
|
||||
0x4001, // 11: in pins, 1 side 0
|
||||
0x114a, // 12: jmp x--, 10 side 1 [1]
|
||||
// .wrap_target
|
||||
0xf081, // 13: set pindirs, 1 side 1
|
||||
// .wrap
|
||||
};
|
||||
|
||||
static const struct pio_program smi_rd_program = {
|
||||
.instructions = smi_rd_program_instructions,
|
||||
.length = 14,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config smi_rd_program_get_default_config(uint addr) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, addr + smi_rd_wrap_target, addr + smi_rd_wrap);
|
||||
sm_config_set_sideset(&c, 1, false, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void smi_wr_init(PIO pio, uint sm, uint addr, uint gpio) {
|
||||
pio_gpio_init(pio, gpio);
|
||||
pio_gpio_init(pio, gpio + 1);
|
||||
pio_sm_config c = smi_wr_program_get_default_config(addr);
|
||||
sm_config_set_out_pins(&c, gpio, 1);
|
||||
sm_config_set_set_pins(&c, gpio, 1);
|
||||
sm_config_set_sideset_pins(&c, gpio + 1);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 2, true);
|
||||
sm_config_set_out_shift(&c, false, true,
|
||||
16); // pull half-words, MSB first, auto
|
||||
sm_config_set_clkdiv(&c, 6); // Run at 50/6 = <10MHz (4x data rate)
|
||||
pio_sm_init(pio, sm, addr, &c);
|
||||
}
|
||||
|
||||
static inline void smi_rd_init(PIO pio, uint sm, uint addr, uint gpio) {
|
||||
pio_gpio_init(pio, gpio);
|
||||
pio_gpio_init(pio, gpio + 1);
|
||||
pio_sm_config c = smi_rd_program_get_default_config(addr);
|
||||
sm_config_set_in_pins(&c, gpio);
|
||||
sm_config_set_out_pins(&c, gpio, 1);
|
||||
sm_config_set_set_pins(&c, gpio, 1);
|
||||
sm_config_set_sideset_pins(&c, gpio + 1);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 2, true);
|
||||
sm_config_set_out_shift(&c, false, true,
|
||||
16); // pull half-words, MSB first, auto
|
||||
sm_config_set_in_shift(&c, false, true,
|
||||
16); // push half-words, MSB first, auto
|
||||
sm_config_set_clkdiv(&c, 6); // Run at 50/6 = <10MHz (4x data rate)
|
||||
pio_sm_init(pio, sm, addr, &c);
|
||||
}
|
||||
|
||||
static void eth_write_phy(int addr, int reg, int val, uint8_t gpio) {
|
||||
uint16_t op = 0x5002 | (addr << 7) | (reg << 2); // b0101aaaaarrrrr10
|
||||
smi_wr_init(pio0, SMITXSM, smi_wr_addr, gpio);
|
||||
pio_sm_put(pio0, SMITXSM, op << 16);
|
||||
pio_sm_put(pio0, SMITXSM, (uint16_t) val << 16);
|
||||
pio_sm_set_enabled(pio0, SMITXSM, true);
|
||||
}
|
||||
|
||||
static uint16_t eth_read_phy(uint addr, uint reg, uint8_t gpio) {
|
||||
uint16_t op = 0x6000 | (addr << 7) | (reg << 2); // b0110aaaaarrrrr00
|
||||
smi_rd_init(pio1, SMIRXSM, smi_rd_addr, gpio);
|
||||
pio_sm_put(pio1, SMIRXSM, op << 16);
|
||||
pio_sm_set_enabled(pio1, SMIRXSM, true);
|
||||
uint16_t val = (uint16_t) pio_sm_get_blocking(pio1, SMIRXSM);
|
||||
pio_sm_set_enabled(pio1, SMIRXSM, false);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void rx_irq(void);
|
||||
|
||||
static bool mg_tcpip_driver_rp2040_rmii_init(struct mg_tcpip_if *ifp) {
|
||||
struct mg_tcpip_driver_rp2040_rmii_data *d =
|
||||
(struct mg_tcpip_driver_rp2040_rmii_data *) ifp->driver_data;
|
||||
uint rx_sm_addr, tx_sm_addr;
|
||||
s_ifp = ifp;
|
||||
rx_sm_addr = pio_add_program(pio0, &rmii_rx_program);
|
||||
tx_sm_addr = pio_add_program(pio0, &rmii_tx_program);
|
||||
smi_wr_addr = pio_add_program(pio0, &smi_wr_program);
|
||||
smi_rd_addr = pio_add_program(pio1, &smi_rd_program);
|
||||
|
||||
dma_tx = dma_claim_unused_channel(true);
|
||||
dmacfg_tx = dma_channel_get_default_config(dma_tx);
|
||||
channel_config_set_read_increment(&dmacfg_tx, true); // read from memory
|
||||
channel_config_set_write_increment(&dmacfg_tx, false); // write to FIFO
|
||||
channel_config_set_dreq(&dmacfg_tx, pio_get_dreq(pio0, TXSM, true));
|
||||
channel_config_set_transfer_data_size(&dmacfg_tx,
|
||||
DMA_SIZE_8); // transfer bytes
|
||||
rmii_tx_init(pio0, TXSM, tx_sm_addr, d->tx0);
|
||||
|
||||
eth_write_phy(d->phy_addr, 4, 0x61,
|
||||
d->mdio); // Auto Negotiation Advertisement Register: enable
|
||||
// only 10BASE-T full and half duplex (two-pair), use
|
||||
// IEEE 802.3 format
|
||||
sleep_us(31); // give some time for PIO to work (64 bits @2.5MHz = 25.6 us)
|
||||
eth_write_phy(d->phy_addr, 0, 0x1000,
|
||||
d->mdio); // Basic Control Register: enable Auto-Negotiation
|
||||
sleep_us(31);
|
||||
|
||||
dma_rx = dma_claim_unused_channel(true);
|
||||
dmacfg_rx = dma_channel_get_default_config(dma_rx);
|
||||
channel_config_set_read_increment(&dmacfg_rx, false); // read from FIFO
|
||||
channel_config_set_write_increment(&dmacfg_rx,
|
||||
true); // write to memory, increment
|
||||
channel_config_set_dreq(&dmacfg_rx, pio_get_dreq(pio0, RXSM, false));
|
||||
channel_config_set_transfer_data_size(&dmacfg_rx,
|
||||
DMA_SIZE_8); // transfer bytes
|
||||
dma_channel_configure(dma_rx, &dmacfg_rx, s_rxbuf[0],
|
||||
((uint8_t *) &pio0->rxf[RXSM]) + 3, ETH_PKT_SIZE, true);
|
||||
pio_set_irq0_source_enabled(pio0, pis_interrupt0,
|
||||
true); // enable SM0 on PIO0_IRQ_0
|
||||
irq_set_exclusive_handler(7, rx_irq); // set handler for PIO0_IRQ_0
|
||||
irq_set_enabled(7, true); // enable it
|
||||
rmii_rx_init(pio0, RXSM, rx_sm_addr, d->rx0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t mg_tcpip_driver_rp2040_rmii_tx(const void *buf, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
dma_channel_wait_for_finish_blocking(dma_tx);
|
||||
memset(s_txbuf, 0, 60); // pre-pad
|
||||
memcpy(s_txbuf, buf, len);
|
||||
if (len < 60) len = 60; // pad
|
||||
uint32_t crc = mg_crc32(0, s_txbuf, len); // host is little-endian
|
||||
memcpy(s_txbuf + len, (uint8_t *) &crc, 4);
|
||||
len += 4;
|
||||
sleep_us(10); // enforce IFG in case software has been lightning fast...
|
||||
dma_channel_configure(dma_tx, &dmacfg_tx, ((uint8_t *) &pio0->txf[TXSM]) + 3,
|
||||
s_txbuf, len, true);
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32_t s_rxno;
|
||||
|
||||
// The max amount of time we should keep the PIO state machine stopped is the
|
||||
// IFG time (10us) and that includes irq latency
|
||||
static void rx_irq(void) {
|
||||
dma_channel_hw_t *hw = dma_channel_hw_addr(dma_rx);
|
||||
uint32_t rxno =
|
||||
(s_rxno + 1) &
|
||||
1; // 2 buffers, switch to the available one as fast as possible
|
||||
size_t len = ETH_PKT_SIZE - hw->transfer_count;
|
||||
dma_channel_abort(dma_rx);
|
||||
dma_channel_set_write_addr(dma_rx, s_rxbuf[rxno], true); // restart DMA
|
||||
pio_interrupt_clear(pio0,
|
||||
0); // ACK PIO IRQ so the state machine resumes receiving
|
||||
// NOTE(scaprile) Here we could check addressing to avoid queuing frames not
|
||||
// for us. The max amount of time we can linger here is what it takes for the
|
||||
// other buffer to fill (<8us) and that includes irq chaining
|
||||
if (len >= 64 && len <= ETH_PKT_SIZE)
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
|
||||
s_rxno = rxno;
|
||||
}
|
||||
|
||||
static bool mg_tcpip_driver_rp2040_rmii_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
if (!s1) return false;
|
||||
struct mg_tcpip_driver_rp2040_rmii_data *d =
|
||||
(struct mg_tcpip_driver_rp2040_rmii_data *) ifp->driver_data;
|
||||
uint32_t bsr =
|
||||
eth_read_phy(d->phy_addr, 1, d->mdio); // Basic Status Register
|
||||
return (bsr & (1 << 2)) ? 1 : 0; // check Link Status flag
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_rp2040_rmii = {
|
||||
mg_tcpip_driver_rp2040_rmii_init,
|
||||
mg_tcpip_driver_rp2040_rmii_tx,
|
||||
NULL,
|
||||
mg_tcpip_driver_rp2040_rmii_poll,
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
struct mg_tcpip_driver_rp2040_rmii_data {
|
||||
uint8_t rx0; // RX0, RX1, CRS_DV; consecutive GPIO pins
|
||||
uint8_t tx0; // TX0, TX1, TX-EN; consecutive GPIO pins
|
||||
uint8_t mdio; // MDIO, MDC; consecutive GPIO pins
|
||||
uint8_t phy_addr; // PHY address
|
||||
};
|
||||
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_rp2040_rmii;
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2022 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "driver_rp2040_rmii.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define CLKREFPIN 20 // either 20 or 22
|
||||
|
||||
static void driver_init(struct mg_mgr *mgr) {
|
||||
MG_INFO(("Init TCP/IP"));
|
||||
// Initialise Mongoose network stack and specific driver
|
||||
// Set consecutive GPIOs for RMII (tx and rx) and SMI function groups
|
||||
struct mg_tcpip_driver_rp2040_rmii_data driver_data = {
|
||||
// see driver_rp2040_rmii.h
|
||||
.rx0 = 6, // 6, 7, 8 : RX0, RX1, CRS_DV
|
||||
.tx0 = 10, // 10, 11, 12 : TX0, TX1, TX-EN
|
||||
.mdio = 14, // 14, 15 : MDIO, MDC
|
||||
.phy_addr = 1 // check your hardware, LAN8722 is 0 or 1
|
||||
};
|
||||
// Specify MAC address, either set use_dhcp or enter a static config.
|
||||
// For static configuration, specify IP/mask/GW in network byte order
|
||||
struct mg_tcpip_if mif = {
|
||||
.mac = {2, 0, 1, 2, 3, 5},
|
||||
.ip = 0,
|
||||
.enable_mac_check = true,
|
||||
.enable_fcs_check = true,
|
||||
.driver = &mg_tcpip_driver_rp2040_rmii,
|
||||
.driver_data = &driver_data,
|
||||
};
|
||||
mg_tcpip_init(mgr, &mif);
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) { // New HTTP request received
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
uint64_t tick = to_ms_since_boot(get_absolute_time());
|
||||
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
|
||||
mg_http_reply(c, 200, "", "{%m:%llu}\n", MG_ESC("tick"), tick);
|
||||
} else {
|
||||
mg_http_reply(c, 200, "", "Hi from Mongoose, tick %llu\n", tick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In an RTOS environment, give this task 8 KB of stack space.
|
||||
static void run_mongoose(void) {
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr);
|
||||
driver_init(&mgr);
|
||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||
MG_INFO(("Hardware initialised, starting firmware..."));
|
||||
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// use the RMII reference clock (50MHz) as our system clock
|
||||
clock_configure_gpin(clk_sys, CLKREFPIN, 50 * MHZ, 50 * MHZ);
|
||||
sleep_ms(100);
|
||||
stdio_init_all();
|
||||
run_mongoose();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#define MG_ARCH MG_ARCH_PICOSDK
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
|
||||
Reference in new issue
Block a user