Add pico-w5500 example

This commit is contained in:
cpq 2023-01-02 16:24:27 +00:00
parent 311062dc41
commit 0f474e8d2a
10 changed files with 176 additions and 1 deletions

View File

@ -12,7 +12,7 @@ VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
IPV6 ?= 1
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
ASAN_OPTIONS ?= detect_leaks=1
EXAMPLES := $(dir $(wildcard examples/*/Makefile)) $(wildcard examples/stm32/nucleo-*)
EXAMPLES := $(dir $(wildcard examples/*/Makefile)) $(wildcard examples/stm32/nucleo-*) $(wildcard examples/rp2040/*)
PREFIX ?= /usr/local
VERSION ?= $(shell cut -d'"' -f2 src/version.h)
COMMON_CFLAGS ?= $(C_WARN) $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS)

View File

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(example)
pico_sdk_init()
add_executable(example main.c mongoose.c)
target_link_libraries(example pico_stdlib hardware_spi)
pico_add_extra_outputs(example)
# Enable USB output. Comment out in order to use UART
pico_enable_stdio_usb(example 1)
pico_enable_stdio_uart(example 0)
# Mongoose build flags
add_definitions(-DMG_ARCH=MG_ARCH_NEWLIB)
add_definitions(-DMG_ENABLE_MIP=1)
add_definitions(-DMG_ENABLE_CUSTOM_MILLIS=1)

View File

@ -0,0 +1,13 @@
SDK_VERSION ?= 1.4.0
SDK_REPO ?= https://github.com/raspberrypi/pico-sdk
all example build: pico-sdk
test -d build || mkdir build
cd build && cmake .. && make
pico-sdk:
git clone --depth 1 -b $(SDK_VERSION) $(SDK_REPO) $@
cd $@ && git submodule update --init
clean:
rm -rf pico-sdk build

View File

@ -0,0 +1,57 @@
# RP2040 with W5500 Ethernet module
This repository demonstrates how to use RP2040 with W5500 Ethernet module,
to implement networking. In this example, a very simple HTTP server is
implemented. See [other examples](../..) for more functionality.
## RP2040 Pico wiring
The W5500 module uses SPI for communication. The following pins are used
by this example (modify `main.c` if you use a different pinout):
```c
enum { LED = 25, SPI_CS = 17, SPI_CLK = 18, SPI_TX = 19, SPI_RX = 16 };
```
On a breadboard, it might look like this:
![](images/wiring.png)
## Pinout reference
![](images/pinout.png)
## Build and run
Clone Mongoose repo, go to this example, and build it:
```sh
git clone https://github.com/cesanta/mongoose
cd mongoose/examples/ro2040/pico-w5500
make
```
The above will make a firmware in `build/example.uf2`. Reboot your Pico
board in bootloader mode, and copy `example.uf2` to the RPI disk.
Attach serial console. Then, plug in Ethernet cable:
```
$ cu -l /dev/cu.usb* -s 115200
4653 2 main.c:79:main Ethernet: down
520b 2 main.c:79:main Ethernet: down
5dc3 2 main.c:79:main Ethernet: down
6593 1 mongoose.c:6757:onstatechange Link up
659a 3 mongoose.c:6840:tx_dhcp_discover DHCP discover sent
667b 3 mongoose.c:6723:arp_cache_add ARP cache: added 192.168.0.1 @ 90:5c:44:55:19:8b
667d 2 mongoose.c:6749:onstatechange READY, IP: 192.168.0.24
667e 2 mongoose.c:6750:onstatechange GW: 192.168.0.1
6680 2 mongoose.c:6752:onstatechange Lease: 86062 sec
697b 2 main.c:79:main Ethernet: up
7533 2 main.c:79:main Ethernet: up
```
Note the aquired IP address printed. Run a browser, and type that IP address
in the address field. You should see an "ok" message in a browser:
![](images/browser.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

View File

@ -0,0 +1,85 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
#include <stdio.h>
#include <string.h>
#include "hardware/spi.h"
#include "pico/stdlib.h"
#include "mongoose.h"
enum { LED = 25, SPI_CS = 17, SPI_CLK = 18, SPI_TX = 19, SPI_RX = 16 }; // Pins
enum { STATUS_TIMER_MS = 3000, BLINK_TIMER_MS = 250 }; // Timeouts
static void spi_begin(void *spi) {
gpio_put(SPI_CS, 0);
}
static void spi_end(void *spi) {
gpio_put(SPI_CS, 1);
}
static uint8_t spi_txn(void *spi, uint8_t byte) {
uint8_t result = 0;
spi_write_read_blocking(spi0, &byte, &result, 1);
// MG_INFO(("%x -> %x", byte, result));
return result;
}
uint64_t mg_millis(void) {
return to_ms_since_boot(get_absolute_time());
}
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) {
stdio_init_all();
MG_INFO(("Starting ..."));
// Init LED
gpio_init(LED);
gpio_set_dir(LED, GPIO_OUT);
// Init SPI pins
uint r = spi_init(spi0, 500 * 1000);
MG_INFO(("r = %x\n", r));
gpio_set_function(SPI_RX, GPIO_FUNC_SPI); // MISO
gpio_set_function(SPI_TX, GPIO_FUNC_SPI); // MOSI
gpio_set_function(SPI_CLK, GPIO_FUNC_SPI); // CLK
gpio_init(SPI_CS); // CS
gpio_set_dir(SPI_CS, GPIO_OUT); // Set CS it to output
gpio_put(SPI_CS, 1); // And drive CS high (inactive)
// Init Mongoose
struct mip_spi spi = {NULL, spi_begin, spi_end, spi_txn};
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 5},
.driver = &mip_driver_w5500,
.driver_data = &spi};
struct mg_mgr mgr; // Declare event manager
mg_mgr_init(&mgr); // Init event manager
mg_log_set(MG_LL_DEBUG); // Set DEBUG log level
mip_init(&mgr, &mif); // Init TCP/IP stack
mg_http_listen(&mgr, "http://0.0.0.0", fn, NULL); // HTTP listener
bool led_on = false; // Initial LED state
uint64_t status_timer = 0, blink_timer = 0; // Initial timer expirations
// Infinite event manager loop
for (;;) {
if (mg_timer_expired(&blink_timer, BLINK_TIMER_MS, mg_millis())) {
led_on = !led_on; // Flip LED state
if (mip_driver_w5500.up(&mif)) led_on = true; // Always on if Eth up
gpio_put(LED, led_on); // Set LED
}
if (mg_timer_expired(&status_timer, STATUS_TIMER_MS, mg_millis())) {
MG_INFO(("Ethernet: %s", mip_driver_w5500.up(&mif) ? "up" : "down"));
}
mg_mgr_poll(&mgr, 1);
}
return 0;
}

View File

@ -0,0 +1 @@
../../../mongoose.c

View File

@ -0,0 +1 @@
../../../mongoose.h