Revamp rp examples

This commit is contained in:
cpq committed 2026-05-22 08:40:58 +01:00
1 parent 948b56a3ec
commit 83ba170b45
142 files changed
+769 -3721

No files matched your search

+11 -29
View File
@@ -209,7 +209,7 @@ jobs:
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/windows_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
arm:
runs-on: ubuntu-latest
strategy:
@@ -325,11 +325,10 @@ jobs:
- path: nxp/rt1020-evk-make-baremetal-builtin
- path: nxp/rt1060-evk-make-baremetal-builtin
- path: nxp/rt1170-evk-make-baremetal-builtin
- path: pico-sdk/pico-w-picosdk-baremetal-builtin
- path: pico-sdk/pico-2-w-picosdk-baremetal-builtin
- path: pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin
- path: pico-sdk/w5500-evb-pico2-picosdk-baremetal-builtin
- path: pico-sdk/w55rp20-evb-pico-picosdk-baremetal-builtin
- path: rp/pico2-w
- path: rp/w5500-evb-pico2
- path: rp/w55rp20-evb-pico
- path: rp/pico-rndis
- path: stm32/nucleo-f429zi-make-baremetal-builtin
- path: stm32/nucleo-f429zi-make-freertos-builtin
- path: stm32/nucleo-f746zg-make-baremetal-builtin
@@ -371,7 +370,7 @@ jobs:
with: { fetch-depth: 2 }
- run: echo # nothing specific to install or do
- run: make -C tutorials/${{ matrix.example.path }} build
generic_examples_arm:
runs-on: ubuntu-latest
strategy:
@@ -397,8 +396,7 @@ jobs:
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
- path: nxp/nxp-twrk65f180m-lwip-freertos
- path: nxp/nxp-twrkv58f220m-lwip-freertos
- path: pico-sdk/rm2-pico-picosdk-baremetal-builtin
- path: pico-sdk/pico-rmii
- path: rp/pico-rmii
- path: stm32/nucleo-f429zi-make-baremetal-builtin-rndis
- path: stm32/rm2-nucleo-f429zi-make-baremetal-builtin
- path: stm32/nucleo-f746zg-make-baremetal-builtin-rndis
@@ -440,9 +438,6 @@ jobs:
- path: nxp/rt1060-evk-make-freertos-builtin
- path: nxp/rt1170-evk-make-freertos-builtin
- path: renesas/ek-ra6m4-make-baremetal-builtin
- path: pico-sdk/pico-rndis-dashboard
- path: pico-sdk/pico-w-picosdk-freertos-lwip
- path: pico-sdk/pico-2-w-picosdk-freertos-lwip
- path: stm32/nucleo-f746zg-make-freertos-tcp
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
name: ${{ matrix.example.path }} ${{ matrix.ssl }}
@@ -458,35 +453,22 @@ jobs:
# fail-fast: false
# matrix:
# example:
# - path:
# - path:
# name: ${{ matrix.example.path }}
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - run: echo # nothing specific to install or do
# - run: make -C tutorials/${{ matrix.example.path }} build
mqtt_dashboard_examples_arm:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example:
- path: pico-sdk/pico-rndis-device
name: ${{ matrix.example.path }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C tutorials/${{ matrix.example.path }} build
# dual_examples:
# runs-on: ubuntu-latest
# strategy:
# fail-fast: false
# matrix:
# example:
# - path:
# - path:
# name: ${{ matrix.example.path }}
# steps:
# - uses: actions/checkout@v4
+3 -3
View File
@@ -21,7 +21,7 @@ jobs:
- name: Cube
run: sudo pip install yq
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
- run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
test_f4:
@@ -62,7 +62,7 @@ jobs:
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_h5:
runs-on: ubuntu-latest
steps:
@@ -140,4 +140,4 @@ jobs:
with: { fetch-depth: 2 }
- name: SDK
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C tutorials/rp/w5500-evb-pico2 test VCON_API_KEY=${{secrets.VCON_API_KEY}}
+5 -45
View File
@@ -168,11 +168,6 @@ jobs:
- path: nxp/rt1020-evk-make-baremetal-builtin
- path: nxp/rt1060-evk-make-baremetal-builtin
- path: nxp/rt1170-evk-make-baremetal-builtin
- path: pico-sdk/pico-w-picosdk-baremetal-builtin
- path: pico-sdk/pico-2-w-picosdk-baremetal-builtin
- path: pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin
- path: pico-sdk/w5500-evb-pico2-picosdk-baremetal-builtin
- path: pico-sdk/w55rp20-evb-pico-picosdk-baremetal-builtin
- path: stm32/nucleo-f429zi-make-baremetal-builtin
- path: stm32/nucleo-f429zi-make-freertos-builtin
- path: stm32/nucleo-f746zg-make-baremetal-builtin
@@ -229,7 +224,7 @@ jobs:
fail-fast: false
matrix:
example:
- path: pico-sdk/rm2-pico-picosdk-baremetal-builtin
- path: rp/pico-rm2
- path: stm32/rm2-nucleo-f429zi-make-baremetal-builtin
- path: stm32/rm2-nucleo-f746zg-make-baremetal-builtin
- path: stm32/nucleo-g031-make-baremetal-builtin
@@ -277,9 +272,10 @@ jobs:
- path: nxp/rt1060-evk-make-freertos-builtin
- path: nxp/rt1170-evk-make-freertos-builtin
- path: renesas/ek-ra6m4-make-baremetal-builtin
- path: pico-sdk/pico-rndis-dashboard
- path: pico-sdk/pico-w-picosdk-freertos-lwip
- path: pico-sdk/pico-2-w-picosdk-freertos-lwip
- path: rp/pico-rndis
- path: rp/pico-w
- path: rp/w55rp20-evb-pico
- path: rp/w5500-evb-pico
- path: stm32/nucleo-f746zg-make-freertos-tcp
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
name: ${{ matrix.example.path }}
@@ -317,26 +313,6 @@ jobs:
# - if: ${{ env.GO == 1 }}
# run: make -C tutorials/${{ matrix.example.path }} build
mqtt_dashboard_examples_arm:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example:
- path: pico-sdk/pico-rndis-device
name: ${{ matrix.example.path }}
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: |
if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-dashboard/device|^tutorials/${{ matrix.example.path }}'; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
run: make -C tutorials/${{ matrix.example.path }} build
cube_examples:
runs-on: ubuntu-latest
@@ -709,19 +685,3 @@ jobs:
# if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
# make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_pico_w5500:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: SDK
# run: |
# if ./test/match_changed_files.sh "^src" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
+5 -5
View File
@@ -1101,7 +1101,7 @@ struct timeval {
#endif
#ifndef MG_SET_WIFI_CONFIG
#define MG_SET_WIFI_CONFIG(data)
#define MG_SET_WIFI_CONFIG(ifp, driver_data)
#endif
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
@@ -3629,7 +3629,7 @@ struct mg_tcpip_driver_cyw_data {
do { \
static struct mg_tcpip_driver_cyw_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
@@ -3706,7 +3706,7 @@ struct mg_tcpip_driver_nxp_wifi_data {
do { \
static struct mg_tcpip_driver_nxp_wifi_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
@@ -3758,7 +3758,7 @@ struct mg_tcpip_driver_pico_w_data {
do { \
static struct mg_tcpip_driver_pico_w_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
@@ -3950,7 +3950,7 @@ struct mg_tcpip_driver_st67w6_data {
do { \
static struct mg_tcpip_driver_st67w6_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
+21 -21
View File
@@ -1,11 +1,12 @@
TOP ?= ../..
# ST_TARGETS = nucleo_h723zg nucleo_f756zg nucleo_h563zi
ST_TARGETS = $(basename $(notdir $(wildcard $(TOP)/tutorials/stm32/*/cubemx/*.ioc)))
RP_TARGETS = pico-w pico-rndis w5500-evb-pico w55rp20-evb-pico
PROJECTS = full
TARGETS = desktop pico2_w $(ST_TARGETS)
TARGETS = desktop $(RP_TARGETS) $(ST_TARGETS)
MX ?= /Applications/STMicroelectronics/STM32CubeMX.app/Contents/MacOs/STM32CubeMX
DIRS = $(foreach P,$(PROJECTS),$(foreach T,$(TARGETS),$(T)_dashboard_$(P)))
DIRS = $(foreach P,$(PROJECTS),$(foreach T,$(TARGETS),$(T)-dashboard-$(P)))
ZIPS = $(foreach D,$(DIRS),$(D).zip)
all:
@@ -15,9 +16,9 @@ dirs: $(DIRS)
zips: $(ZIPS)
DESKTOP_DIRS = $(foreach P,$(PROJECTS),desktop_dashboard_$(P))
DESKTOP_DIRS = $(foreach P,$(PROJECTS),desktop-dashboard-$(P))
$(DESKTOP_DIRS): desktop_dashboard_%:
$(DESKTOP_DIRS): desktop-dashboard-%:
mkdir -p $@ $@/resources
$(MAKE) -C $(TOP)/tutorials/device-dashboard/$* clean
cp $(TOP)/tutorials/device-dashboard/$*/*{c,html,Makefile} $@
@@ -26,23 +27,23 @@ $(DESKTOP_DIRS): desktop_dashboard_%:
cp $(TOP)/resources/*.js $@/resources
sed -i "" "s,../../..,.," $@/Makefile
.PHONY: pico2_w_dashboard_full
pico2_w_dashboard_full pico2_w_dashboard_minimal: pico2_w_dashboard_%:
mkdir -p $@
$(MAKE) -C $(TOP)/tutorials/pico-sdk/pico2_w fullclean
cp $(TOP)/tutorials/pico-sdk/pico2_w/* $@/
cp $(TOP)/{mongoose.c,mongoose.c,LICENSE} $@/
cp $(TOP)/resources/html2c.js $@/
cp $(TOP)/tutorials/device-dashboard/$*/{dashboard.c,dashboard.html} $@/
sed -i '' -e '/mg_http_listen/d' $@/main.c
grep -q 'mg_dash_init' $@/main.c || perl -i -ne 'print; print " mg_dash_init(&mgr);\n" if /mg_mgr_init/' $@/main.c
grep -q 'mg_dash_poll' $@/main.c || perl -i -ne 'print; print " mg_dash_poll(&mgr);\n" if /mg_mgr_poll/' $@/main.c
grep -q 'dashboard.c' $@/CMakeLists.txt || sed -i -e 's,mongoose.c,mongoose.c dashboard.c file_data.c,' $@/CMakeLists.txt
grep -q 'html2c.js' $@/CMakeLists.txt || perl -i -ne 'print "\nadd_custom_command(\n OUTPUT \$${CMAKE_SOURCE_DIR}/file_data.c\n COMMAND node \$${CMAKE_SOURCE_DIR}/html2c.js \$${CMAKE_SOURCE_DIR}/dashboard.html -o \$${CMAKE_SOURCE_DIR}/file_data.c\n DEPENDS \$${CMAKE_SOURCE_DIR}/dashboard.html\n VERBATIM\n)\n\n" if /add_executable/; print;' $@/CMakeLists.txt
define RP_DASHBOARD_RULE
$(1)-dashboard-$(2):
mkdir -p $$@
$(MAKE) -C $(TOP)/tutorials/rp/$(1) clean
cp -r $(TOP)/tutorials/rp/$(1)/* $$@/
cp $(TOP)/{mongoose.c,mongoose.c,LICENSE} $$@/mongoose/
cp $(TOP)/resources/html2c.js $$@/mongoose/
cp $(TOP)/tutorials/device-dashboard/$(2)/{dashboard.c,dashboard.html} $$@/mongoose/
sed -i '' -e '/mg_http_listen/d' $$@/main.c
grep -q 'mg_dash_init' $$@/main.c || perl -i -ne 'print; print " mg_dash_init(&mgr);\n" if /mg_mgr_init/' $$@/main.c
grep -q 'mg_dash_poll' $$@/main.c || perl -i -ne 'print; print " mg_dash_poll(&mgr);\n" if /mg_mgr_poll/' $$@/main.c
grep -q 'dashboard.c' $$@/CMakeLists.txt || sed -i -e 's,mongoose.c,mongoose.c mongoose/dashboard.c mongoose/file_data.c,' $$@/CMakeLists.txt
grep -q 'html2c.js' $$@/CMakeLists.txt || perl -i -ne 'print "add_custom_command(\n OUTPUT \$$$${CMAKE_SOURCE_DIR}/mongoose/file_data.c\n COMMAND node \$$$${CMAKE_SOURCE_DIR}/mongoose/html2c.js \$$$${CMAKE_SOURCE_DIR}/mongoose/dashboard.html -o \$$$${CMAKE_SOURCE_DIR}/mongoose/file_data.c\n DEPENDS \$$$${CMAKE_SOURCE_DIR}/mongoose/dashboard.html\n VERBATIM\n)\n\n" if /add_executable/; print;' $$@/CMakeLists.txt
endef
define ST_DASHBOARD_RULE
$(1)_dashboard_$(2): $(TOP)/tutorials/stm32/$(1)/cubemx/$(1).ioc
$(1)-dashboard-$(2): $(TOP)/tutorials/stm32/$(1)/cubemx/$(1).ioc
mkdir -p $$@
cp $(TOP)/tutorials/stm32/$(1)/cubemx/* $$@ 2>/dev/null || true
echo config load `realpath $$@/$(1).ioc` > gen.mx
@@ -53,6 +54,7 @@ $(1)_dashboard_$(2): $(TOP)/tutorials/stm32/$(1)/cubemx/$(1).ioc
endef
$(foreach T,$(ST_TARGETS), $(foreach P,$(PROJECTS), $(eval $(call ST_DASHBOARD_RULE,$(T),$(P)))))
$(foreach T,$(RP_TARGETS), $(foreach P,$(PROJECTS), $(eval $(call RP_DASHBOARD_RULE,$(T),$(P)))))
%.zip: %
zip -qr $@ $<
@@ -62,5 +64,3 @@ upload: $(ZIPS)
clean:
rm -rf $(DIRS) *.zip
# rm -rf $(DIRS) $(ZIPS) #$(foreach T,$(ST_TARGETS),$(T)_mongoose)
+1 -1
View File
@@ -200,7 +200,7 @@
#endif
#ifndef MG_SET_WIFI_CONFIG
#define MG_SET_WIFI_CONFIG(data)
#define MG_SET_WIFI_CONFIG(ifp, driver_data)
#endif
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
+1 -1
View File
@@ -24,7 +24,7 @@ struct mg_tcpip_driver_cyw_data {
do { \
static struct mg_tcpip_driver_cyw_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
+1 -1
View File
@@ -13,7 +13,7 @@ struct mg_tcpip_driver_nxp_wifi_data {
do { \
static struct mg_tcpip_driver_nxp_wifi_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
+1 -1
View File
@@ -15,7 +15,7 @@ struct mg_tcpip_driver_pico_w_data {
do { \
static struct mg_tcpip_driver_pico_w_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
+1 -1
View File
@@ -14,7 +14,7 @@ struct mg_tcpip_driver_st67w6_data {
do { \
static struct mg_tcpip_driver_st67w6_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
MG_SET_WIFI_CONFIG(&mif_, &driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
+1 -1
View File
@@ -16,7 +16,7 @@ IPV6 ?= 1
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
ASAN_OPTIONS ?= detect_leaks=1
# This does not include ESP32, ESP8266, Microchip; all examples that are directly placed under an OS tutorial. Also, it is needed that way...
TUTORIALS_EMBEDDED := $(dir $(wildcard ../tutorials/infineon/*/Makefile)) $(dir $(wildcard ../tutorials/nxp/*/Makefile)) $(dir $(wildcard ../tutorials/pico-sdk/*/Makefile)) $(dir $(wildcard ../tutorials/renesas/*/Makefile)) $(dir $(wildcard ../tutorials/stm32/*/Makefile)) $(dir $(wildcard ../tutorials/ti/*/Makefile)) $(dir $(wildcard ../tutorials/wch/*/Makefile))
TUTORIALS_EMBEDDED := $(dir $(wildcard ../tutorials/infineon/*/Makefile)) $(dir $(wildcard ../tutorials/nxp/*/Makefile)) $(dir $(wildcard ../tutorials/rp/*/Makefile)) $(dir $(wildcard ../tutorials/renesas/*/Makefile)) $(dir $(wildcard ../tutorials/stm32/*/Makefile)) $(dir $(wildcard ../tutorials/ti/*/Makefile)) $(dir $(wildcard ../tutorials/wch/*/Makefile))
TUTORIALS := ../tutorials/micropython/ $(filter-out $(TUTORIALS_EMBEDDED), $(dir $(wildcard ../tutorials/*/*/Makefile)))
TUTORIALS_QUICK := $(filter-out ../tutorials/micropython/ ../tutorials/tcpip/pcap-driver/, $(TUTORIALS))
TUTORIALS_MAC := $(filter-out ../tutorials/micropython/ ../tutorials/tcpip/pcap-driver/ ../tutorials/tcpip/tap-driver/, $(TUTORIALS))
@@ -24,4 +24,4 @@ wizard:
clean:
sudo rm -rf firmware.* wizard* workspace mcuxpresso .cache .eclipse .p2
test -f firmware.axf && sudo rm -rf firmware.* wizard* workspace mcuxpresso .cache .eclipse .p2 || true
@@ -1,21 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
mongoose.c
)
target_include_directories(firmware PUBLIC
.
)
target_link_libraries(firmware pico_stdlib pico_rand pico_cyw43_driver pico_cyw43_arch_none)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 1) # Route stdio
add_definitions(-DMG_ENABLE_TCPIP_DRIVER_INIT=0)
@@ -1,17 +0,0 @@
CWD = $(realpath $(PWD))
SDK_PATH ?= $(CWD)/pico-sdk
all example:
true
build: build/firmware.uf2
build/firmware.uf2: pico-sdk main.c
mkdir -p build && cd build && PICO_SDK_PATH=$(SDK_PATH) cmake -DPICO_BOARD="pico2_w" -G "Unix Makefiles" .. && make
pico-sdk:
git clone --depth 1 -b 2.1.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init
clean:
rm -rf build pico-sdk
@@ -1,136 +0,0 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
// mif user states
enum {AP, SCANNING, STOPPING_AP, CONNECTING, READY};
static unsigned int state;
static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
// TODO(): should we include this inside ifp ? add an fn_data ?
if (ev == MG_TCPIP_EV_ST_CHG) {
MG_INFO(("State change: %u", *(uint8_t *) ev_data));
}
switch(state) {
case AP: // we are in AP mode, wait for a user connection to trigger a scan or a connection to a network
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("Access Point READY !"));
// simulate user request to scan for networks
bool res = mg_wifi_scan();
MG_INFO(("Starting scan: %s", res ? "OK":"FAIL"));
if (res) state = SCANNING;
}
break;
case SCANNING:
if (ev == MG_TCPIP_EV_WIFI_SCAN_RESULT) {
struct mg_wifi_scan_bss_data *bss = (struct mg_wifi_scan_bss_data *) ev_data;
MG_INFO(("BSS: %.*s (%u) (%M) %d dBm %u", bss->SSID.len, bss->SSID.buf, bss->channel, mg_print_mac, bss->BSSID, (int) bss->RSSI, bss->security));
} else if (ev == MG_TCPIP_EV_WIFI_SCAN_END) {
struct mg_tcpip_driver_pico_w_data *d = (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
MG_INFO(("Wi-Fi scan finished"));
// simulate user selection of a network (1/2: stop AP)
bool res = mg_wifi_ap_stop();
MG_INFO(("Manually stopping AP: %s", res ? "OK":"FAIL"));
if (res) state = STOPPING_AP;
// else we have a hw/fw problem
}
break;
case STOPPING_AP:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_pico_w_data *) ifp->driver_data)->wifi;
wifi->apmode = false;
// simulate user selection of a network (2/2: actual connect)
bool res = mg_wifi_connect(wifi);
MG_INFO(("Manually connecting: %s", res ? "OK":"FAIL"));
if (res) {
state = CONNECTING;
} // else manually start AP as below
}
break;
case CONNECTING:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("READY!"));
state = READY;
// simulate user code disconnection and go back to AP mode (1/2: disconnect)
bool res = mg_wifi_disconnect();
MG_INFO(("Manually disconnecting: %s", res ? "OK":"FAIL"));
} else if (ev == MG_TCPIP_EV_WIFI_CONNECT_ERR) {
MG_ERROR(("Wi-Fi connect failed"));
// manually start AP as below
}
break;
case READY:
// go back to AP mode after a disconnection (simulation 2/2), you could retry
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_pico_w_data *) ifp->driver_data)->wifi;
bool res = mg_wifi_ap_start(wifi);
MG_INFO(("Disconnected"));
MG_INFO(("Manually starting AP: %s", res ? "OK":"FAIL"));
if (res) {
state = AP;
wifi->apmode = true;
}
}
break;
}
}
int main(void) {
// initialize stdio
stdio_init_all();
sleep_ms(4000);
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
// Initialise WiFi creds
struct mg_tcpip_driver_pico_w_data driver_data = {
.wifi.ssid = WIFI_SSID,
.wifi.pass = WIFI_PASS,
.wifi.apssid = "mongoose",
.wifi.appass = "eightchars",
.wifi.apip = MG_IPV4(192, 168, 169, 1),
.wifi.apmask = MG_IPV4(255, 255, 255, 0),
.wifi.security = 0,
.wifi.apsecurity = 0,
.wifi.apchannel = 10,
.wifi.apmode = true
};
state = driver_data.wifi.apmode ? AP : CONNECTING;
// Initialise Mongoose network stack
// 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 = {
.ip = 0,
.driver = &mg_tcpip_driver_pico_w,
.driver_data = &driver_data,
.recv_queue.size = 8192,
.fn = mif_fn
};
mg_tcpip_init(&mgr, &mif);
MG_INFO(("Init done, starting main loop"));
MG_INFO(("Initialising application..."));
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1,28 +0,0 @@
#pragma once
// See https://mongoose.ws/documentation/#build-options
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_OTA MG_OTA_PICOSDK
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_DRIVER_PICO_W 1
// For static IP configuration, define MG_TCPIP_{IP,MASK,GW}
// By default, those are set to zero, meaning that DHCP is used
//
// #define MG_TCPIP_IP MG_IPV4(192, 168, 1, 10)
// #define MG_TCPIP_GW MG_IPV4(192, 168, 1, 1)
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0)
// MAC address is read from OTP by the driver
// Set your Wi-Fi configuration
/* Using a build-time constant:
#define MG_SET_WIFI_CONFIG(data) do { \
((struct mg_tcpip_driver_pico_w_data *)data)->ssid = "this"; \
((struct mg_tcpip_driver_pico_w_data *)data)->pass = "that"; \
} while (0)
*/
// Using a custom function:
extern void main_setconfig(void *data);
#define MG_SET_WIFI_CONFIG(data) main_setconfig(data)
@@ -1,84 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})
@@ -1,35 +0,0 @@
BOARD = pico2-w
IDE = Pico-SDK
RTOS = baremetal
WIZARD_URL ?= http://mongoose.ws/wizard
all build example: firmware.uf2
firmware.uf2: wizard
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
wizard:
hash=$$(curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s -X POST -H "Content-Type: application/json" -d '{"build":{"board":"$(BOARD)","ide":"$(IDE)","rtos":"$(RTOS)"},"http":{"http": true}}' $(WIZARD_URL)/api/hash | jq -r '.hash') \
&& curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s $(WIZARD_URL)/api/zip -o wizard.zip
unzip wizard.zip
cd wizard/mongoose ; rm mongoose.[ch] ; ln -s ../../../../../mongoose.c ; ln -s ../../../../../mongoose.h
flash: firmware.uf2
picotool load $< -f
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/??
# stdio has to be changed from USB to UART in CMakeLists.txt
update: wizard
sed -i -e 's/pico_enable_stdio_usb(firmware 1)/pico_enable_stdio_usb(firmware 0)/' wizard/CMakeLists.txt
(test `grep -c "pico_enable_stdio_uart(firmware 1)" wizard/CMakeLists.txt` -eq 0 && echo "pico_enable_stdio_uart(firmware 1)" >> wizard/CMakeLists.txt) || true
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @firmware.uf2
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=15 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
rm -rf firmware.* wizard* pico-sdk
@@ -1 +0,0 @@
See [Wizard](https://mongoose.ws/wizard/#/output?board=pico2-w&ide=Pico-SDK&rtos=baremetal&file=README.md)
@@ -1,36 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
include(FreeRTOS_Kernel_import.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
mongoose.c
net.c
packed_fs.c
)
target_include_directories(firmware PUBLIC
.
)
target_link_libraries(firmware
pico_stdlib
pico_rand
pico_cyw43_arch_lwip_sys_freertos
FreeRTOS-Kernel-Heap4
)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 1) # Route stdio
pico_enable_stdio_uart(firmware 0) # to USB
# Prevent extreme optimization from breaking OTA
target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)
# Mongoose build flags in mongoose_config.h
# Example build options
add_definitions(-DHTTP_URL="http://0.0.0.0/")
@@ -1,156 +0,0 @@
/*
* FreeRTOS V202111.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_EXAMPLES_COMMON_H
#define FREERTOS_CONFIG_EXAMPLES_COMMON_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
/* Scheduler Related */
#define configUSE_PREEMPTION 1
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES 32
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 512
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
/* Synchronization Related */
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_QUEUE_SETS 1
#define configUSE_TIME_SLICING 1
#define configUSE_NEWLIB_REENTRANT 0
// todo need this for lwip FreeRTOS sys_arch to compile
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
/* System */
#define configSTACK_DEPTH_TYPE uint32_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE (128*1024)
#define configAPPLICATION_ALLOCATED_HEAP 0
/* Hook function related definitions. */
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 1
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH 1024
/* Interrupt nesting behaviour configuration. */
/*
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
*/
#define configNUMBER_OF_CORES 2
/* SMP (configNUMBER_OF_CORES > 1) only */
#define configTICK_CORE 0
#define configRUN_MULTIPLE_PRIORITIES 1
#if configNUMBER_OF_CORES > 1
#define configUSE_CORE_AFFINITY 1
#endif
#define configUSE_PASSIVE_IDLE_HOOK 0
/* Armv8-M */
/* Not currently supported */
#define configENABLE_MPU 0
//#define configSYSTEM_CALL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 512
#define configENABLE_FPU 1
/* Not currently supported */
#define configENABLE_TRUSTZONE 0
#define configRUN_FREERTOS_SECURE_ONLY 1
// see https://www.freertos.org/RTOS-Cortex-M3-M4.html
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
/* RP2xxx specific */
#define configSUPPORT_PICO_SYNC_INTEROP 1
#define configSUPPORT_PICO_TIME_INTEROP 1
#include <assert.h>
/* Define to trap errors during development. */
#define configASSERT(x) assert(x)
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_xQueueGetMutexHolder 1
/* A header file that defines trace macro can be included here. */
#endif /* FREERTOS_CONFIG_H */
@@ -1,91 +0,0 @@
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
# This can be dropped into an external project to help locate the FreeRTOS kernel
# It should be include()ed prior to project(). Alternatively this file may
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
# respectively.
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
endif ()
# first pass we look in old tree; second pass we look in new tree
foreach(SEARCH_PASS RANGE 0 1)
if (SEARCH_PASS)
# ports may be moving to submodule in the future
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC")
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..")
else()
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC")
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
endif()
if(PICO_PLATFORM STREQUAL "rp2040")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040")
else()
if (PICO_PLATFORM STREQUAL "rp2350-riscv")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V")
else()
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ")
endif()
endif()
if (NOT FREERTOS_KERNEL_PATH)
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
endif()
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
break()
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
break()
endif()
endif ()
if (NOT FREERTOS_KERNEL_PATH)
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
# check if FreeRTOS-Kernel exists under directory that included us
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
break()
endif()
endforeach()
if (FREERTOS_KERNEL_PATH)
break()
endif()
endif()
# user must have specified
if (FREERTOS_KERNEL_PATH)
if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
break()
endif()
endif()
endforeach ()
if (NOT FREERTOS_KERNEL_PATH)
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
endif()
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
endif()
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
endif()
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
@@ -1,27 +0,0 @@
RM = rm -rf
MKBUILD = rm -rf build && mkdir -p build # test -d build || mkdir build
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F /S
MKBUILD = if not exist build mkdir build
endif
all example:
true
build: pico-sdk FreeRTOS-Kernel build/firmware.uf2
build/firmware.uf2:
$(MKBUILD)
cd build && cmake -DPICO_BOARD="pico2_w" -G "Unix Makefiles" .. && make
pico-sdk:
#git clone --depth 1 -b 2.1.1 https://github.com/raspberrypi/pico-sdk $@
#cd $@ && git submodule update --init
# Temporary fix until 2.1.1 is released, see #3027
git clone -b develop https://github.com/raspberrypi/pico-sdk $@
cd $@ && git reset --hard --quiet b51fa1b && git submodule update --quiet --init
FreeRTOS-Kernel: # FreeRTOS sources
git clone --depth 1 -b main https://github.com/raspberrypi/FreeRTOS-Kernel $@
clean:
$(RM) pico-sdk build FreeRTOS-Kernel
@@ -1,5 +0,0 @@
# Mongoose on PICO 2 W
See detailed tutorial at https://mongoose.ws/tutorials/rp2040/pico-w/
@@ -1,55 +0,0 @@
#ifndef _LWIPOPTS_H
#define _LWIPOPTS_H
#define TCPIP_THREAD_STACKSIZE 1024
#define DEFAULT_THREAD_STACKSIZE 2048
#define DEFAULT_RAW_RECVMBOX_SIZE 8
#define TCPIP_MBOX_SIZE 16
#define DEFAULT_UDP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
#define DEFAULT_TCP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
#define DEFAULT_ACCEPTMBOX_SIZE TCPIP_MBOX_SIZE
#define LWIP_TIMEVAL_PRIVATE 0
// not necessary, can be done either way
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
#define LWIP_SOCKET 1
#define LWIP_COMPAT_SOCKETS 1
#define LWIP_POSIX_SOCKETS_IO_NAMES 1
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#define MEM_ALIGNMENT 4
#define MEM_SIZE 20000
#define MEMP_NUM_TCP_PCB 10
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 1
#define MEMP_NUM_NETCONN 10
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 0
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#endif
@@ -1,46 +0,0 @@
// Copyright (c) 2024 Cesanta Software Limited
// All rights reserved
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "FreeRTOS.h"
#include <task.h>
#include "mongoose.h"
#include "net.h"
#define WIFI_SSID "yourWiFiSSID"
#define WIFI_PASS "yourWiFiPassword"
static void mongoose(void *args) {
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
mg_log_set(MG_LL_DEBUG); // Set log level
cyw43_arch_init();
cyw43_arch_enable_sta_mode();
cyw43_arch_wifi_connect_blocking(WIFI_SSID, WIFI_PASS, CYW43_AUTH_WPA2_AES_PSK);
MG_INFO(("Initialising application..."));
web_init(&mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 10);
}
(void) args;
}
int main(void) {
// initialize stdio
stdio_init_all();
xTaskCreate(mongoose, "mongoose", 2048, 0, configMAX_PRIORITIES - 1, NULL);
vTaskStartScheduler(); // This blocks
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1,3 +0,0 @@
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_LWIP 1
@@ -1 +0,0 @@
../../http/device-dashboard/net.c
@@ -1 +0,0 @@
../../http/device-dashboard/net.h
@@ -1 +0,0 @@
../../http/device-dashboard/packed_fs.c
@@ -1,84 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})
-1
View File
@@ -1 +0,0 @@
See detailed tutorial (including hardware connections) at https://mongoose.ws/tutorials/rp2040/pico-rmii/
@@ -1,35 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
msc_disk.c
usb_descriptors.c
mongoose.c
net.c
packed_fs.c
pico-sdk/lib/tinyusb/lib/networking/rndis_reports.c)
target_include_directories(firmware PUBLIC
.
pico-sdk/lib/tinyusb/lib/networking)
target_link_libraries(firmware pico_stdlib pico_rand hardware_spi tinyusb_device)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 0) # Route stdio
pico_enable_stdio_uart(firmware 1) # to the UART
# Mongoose build flags in mongoose_config.h
# Example build options
add_definitions(-DHTTP_URL="http://0.0.0.0/")
# Extra build flags (enable if needed)
add_definitions(-DDUAL_CONFIG=0)
# Prevent extreme optimization from breaking OTA
target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)
@@ -1,20 +0,0 @@
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
all example:
true
build build/firmware.uf2: pico-sdk main.c net.c
$(MKBUILD)
cd build && cmake -G "Unix Makefiles" .. && make
pico-sdk:
git clone --depth 1 -b 2.1.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init
clean:
$(RM) pico-sdk build
@@ -1,7 +0,0 @@
# Device Dashboard via RNDIS on an RP2040
Your headless Raspberry Pi Pico-based hardware can also have a device dashboard on a web browser when you connect it to your computer via USB
- See detailed tutorial at https://mongoose.ws/tutorials/rp2040/pico-rndis-dashboard/
Note for Mac users: For this example to run on Mac, please set `DUAL_CONFIG=1` in `CMakeLists.txt` before building; this enables CDC-ECM. Please notice that Windows may not recognize the mass-storage device in that case.
@@ -1,81 +0,0 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "net.h"
#include "pico/stdlib.h"
#include "tusb.h"
static struct mg_tcpip_if *s_ifp;
uint8_t tud_network_mac_address[6] = {2, 2, 0x84, 0x6A, 0x96, 0};
static void blink_cb(void *arg) { // Blink periodically
gpio_put(PICO_DEFAULT_LED_PIN, !gpio_get_out_level(PICO_DEFAULT_LED_PIN));
(void) arg;
}
bool tud_network_recv_cb(const uint8_t *buf, uint16_t len) {
mg_tcpip_qwrite((void *) buf, len, s_ifp);
// MG_INFO(("RECV %hu", len));
// mg_hexdump(buf, len);
tud_network_recv_renew();
return true;
}
void tud_network_init_cb(void) {}
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
// MG_INFO(("SEND %hu", arg));
memcpy(dst, ref, arg);
return arg;
}
static size_t usb_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
if (!tud_ready()) return 0;
while (!tud_network_can_xmit(len)) tud_task();
tud_network_xmit((void *) buf, len);
(void) ifp;
return len;
}
static bool usb_poll(struct mg_tcpip_if *ifp, bool s1) {
(void) ifp;
tud_task();
return s1 ? tud_inited() && tud_ready() && tud_connected() : false;
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_dta) {
if (ev == MG_EV_HTTP_MSG) return mg_http_reply(c, 200, "", "ok\n");
}
int main(void) {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
stdio_init_all();
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, blink_cb, &mgr);
struct mg_tcpip_driver driver = {.tx = usb_tx, .poll = usb_poll};
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 0x77},
.ip = mg_htonl(MG_U32(192, 168, 3, 1)),
.mask = mg_htonl(MG_U32(255, 255, 255, 0)),
.enable_dhcp_server = true,
.driver = &driver,
.recv_queue.size = 4096};
s_ifp = &mif;
mg_tcpip_init(&mgr, &mif);
tusb_init();
MG_INFO(("Initialising application..."));
web_init(&mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1 +0,0 @@
../../http/device-dashboard/net.c
@@ -1 +0,0 @@
../../http/device-dashboard/net.h
@@ -1 +0,0 @@
../../http/device-dashboard/packed_fs.c
@@ -1,29 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
usb_descriptors.c
mongoose.c
net.c
pico-sdk/lib/tinyusb/lib/networking/rndis_reports.c)
target_include_directories(firmware PUBLIC
.
pico-sdk/lib/tinyusb/lib/networking)
target_link_libraries(firmware pico_stdlib pico_rand hardware_spi tinyusb_device)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 0) # Route stdio
pico_enable_stdio_uart(firmware 1) # to the UART
# Prevent extreme optimization from breaking OTA
target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)
# Mongoose build flags in mongoose_config.h
# Example build options
@@ -1,20 +0,0 @@
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
all example:
true
build build/firmware.uf2: pico-sdk main.c net.c
$(MKBUILD)
cd build && cmake -G "Unix Makefiles" .. && make
pico-sdk:
git clone --depth 1 -b 2.1.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init
clean:
$(RM) pico-sdk build
@@ -1,30 +0,0 @@
# Remote MQTT Device on an RP2040
Your headless Raspberry Pi Pico-based hardware can also be a remote gadget when you connect it to your computer via USB
For the USB specifics, see this related tutorial at https://mongoose.ws/tutorials/rp2040/pico-rndis-dashboard/
See this tutorial to control your device: https://mongoose.ws/tutorials/mqtt-dashboard/
For this to work, you need your computer to act as a router (gateway) and NAT for your device.
## Linux setup
Enable "masquerading"; the quick and simple options are:
``` bash
sudo iptables --flush
sudo iptables --table nat --flush
sudo iptables --delete-chain
sudo iptables --table nat --delete-chain
# Do masquerading
sudo iptables -t nat -A POSTROUTING -o yourifc -j MASQUERADE
# enable routing
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
```
Where `yourifc` is the interface that is connected to your network
## MacOS setup
@@ -1,11 +0,0 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
#define LED PICO_DEFAULT_LED_PIN
static inline int gpio_read(uint16_t pin) {
return gpio_get_out_level(pin);
}
static inline void gpio_write(uint16_t pin, bool val) {
gpio_put(pin, val);
}
@@ -1,96 +0,0 @@
// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "net.h"
#include "pico/stdlib.h"
#include "tusb.h"
char *g_firmware_version = "1.0.0";
bool hal_gpio_read(int pin) {
return (pin >= 0 && pin <= 29) ? gpio_get_out_level((uint) pin) : false;
}
bool hal_gpio_write(int pin, bool val) {
if (pin >= 0 && pin <= 29) {
gpio_put((uint) pin, val);
return true;
} else {
return false;
}
}
int hal_led_pin(void) {
return PICO_DEFAULT_LED_PIN;
}
static struct mg_tcpip_if *s_ifp;
uint8_t tud_network_mac_address[6] = {2, 2, 0x84, 0x6A, 0x96, 0};
bool tud_network_recv_cb(const uint8_t *buf, uint16_t len) {
mg_tcpip_qwrite((void *) buf, len, s_ifp);
// MG_INFO(("RECV %hu", len));
// mg_hexdump(buf, len);
tud_network_recv_renew();
return true;
}
void tud_network_init_cb(void) {
}
uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
// MG_INFO(("SEND %hu", arg));
memcpy(dst, ref, arg);
return arg;
}
static size_t usb_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
if (!tud_ready()) return 0;
while (!tud_network_can_xmit(len)) tud_task();
tud_network_xmit((void *) buf, len);
(void) ifp;
return len;
}
static bool usb_poll(struct mg_tcpip_if *ifp, bool s1) {
(void) ifp;
tud_task();
return s1 ? tud_inited() && tud_ready() && tud_connected() : false;
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_dta) {
if (ev == MG_EV_HTTP_MSG) return mg_http_reply(c, 200, "", "ok\n");
}
int main(void) {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
stdio_init_all();
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
struct mg_tcpip_driver driver = {.tx = usb_tx, .poll = usb_poll};
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 0x77},
.ip = mg_htonl(MG_U32(192, 168, 3, 1)),
.mask = mg_htonl(MG_U32(255, 255, 255, 0)),
.enable_dhcp_server = true,
.enable_get_gateway = true,
.driver = &driver,
.recv_queue.size = 4096};
s_ifp = &mif;
mg_tcpip_init(&mgr, &mif);
tusb_init();
MG_INFO(("Initialising application..."));
web_init(&mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1,4 +0,0 @@
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
@@ -1 +0,0 @@
../../mqtt/mqtt-dashboard/device/net.c
@@ -1 +0,0 @@
../../mqtt/mqtt-dashboard/device/net.h
@@ -1,2 +0,0 @@
#pragma once
#define SIZEOF_ETH_HDR 14
@@ -1,9 +0,0 @@
#pragma once
// Windows only supports RNDIS
// Mac only supports CDC-ECM
// Linux supports either RNDIS, CDC-ECM or CDC-NCM
#define CFG_TUD_ECM_RNDIS 1
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
@@ -1,248 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB]
*/
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) )
// String Descriptor Index
enum
{
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_INTERFACE,
STRID_MAC
};
enum
{
ITF_NUM_CDC = 0,
ITF_NUM_CDC_DATA,
ITF_NUM_TOTAL
};
enum
{
#if CFG_TUD_ECM_RNDIS
CONFIG_ID_RNDIS = 0,
CONFIG_ID_ECM = 1,
#else
CONFIG_ID_NCM = 0,
#endif
CONFIG_ID_COUNT
};
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
// Use Interface Association Descriptor (IAD) device class
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0xCafe,
.idProduct = USB_PID,
.bcdDevice = 0x0101,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = CONFIG_ID_COUNT // multiple configurations
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void)
{
return (uint8_t const *) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN)
#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN)
#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_DESC_LEN)
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x83
#else
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#endif
#if CFG_TUD_ECM_RNDIS
static uint8_t const rndis_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE),
};
static uint8_t const ecm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
};
#else
static uint8_t const ncm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
};
#endif
// Configuration array: RNDIS and CDC-ECM
// - Windows only works with RNDIS
// - MacOS only works with CDC-ECM
// - Linux will work on both
static uint8_t const * const configuration_arr[2] =
{
#if CFG_TUD_ECM_RNDIS
[CONFIG_ID_RNDIS] = rndis_configuration,
[CONFIG_ID_ECM ] = ecm_configuration
#else
[CONFIG_ID_NCM ] = ncm_configuration
#endif
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL;
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// array of pointer to string descriptors
static char const* string_desc_arr [] =
{
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer
[STRID_PRODUCT] = "TinyUSB Device", // Product
[STRID_SERIAL] = "123456", // Serial
[STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description
// STRID_MAC index is handled separately
};
static uint16_t _desc_str[32];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
(void) langid;
unsigned int chr_count = 0;
if (STRID_LANGID == index)
{
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
}
else if (STRID_MAC == index)
{
// Convert MAC address into UTF-16
for (unsigned i=0; i<sizeof(tud_network_mac_address); i++)
{
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf];
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
}
}
else
{
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = (uint8_t) strlen(str);
if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1;
// Convert ASCII string into UTF-16
for (unsigned int i=0; i<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
return _desc_str;
}
-7
View File
@@ -1,7 +0,0 @@
# Device Dashboard via RNDIS on an RP2040
Your headless Raspberry Pi Pico-based hardware can also have a device dashboard on a web browser when you connect it to your computer via USB
- See detailed tutorial at https://mongoose.ws/tutorials/rp2040/pico-rndis-dashboard/
Note for Mac users: For this example to run on Mac, please set `DUAL_CONFIG=1` in `CMakeLists.txt` before building; this enables CDC-ECM. Please notice that Windows may not recognize the mass-storage device in that case.
@@ -1,4 +0,0 @@
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
-252
View File
@@ -1,252 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
// Modified by Cesanta Software
#include "tusb.h"
// Some MCU doesn't have enough 8KB SRAM to store the whole disk
enum
{
DISK_BLOCK_NUM = 16, // 8KB is the smallest size that Windows allows to mount
DISK_BLOCK_SIZE = 512
};
#define INDEX_CONTENTS \
"<head><meta http-equiv=\"Refresh\" content=\"0;url=http://192.168.3.1\"></head><body></body>"
// readonly
const uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
{
//------------- Block0: Boot Sector -------------//
// byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
// sector_per_cluster = 1; reserved_sectors = 1;
// fat_num = 1; fat12_root_entry_num = 16;
// sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
// drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
// filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB 0 ";
// FAT magic code at offset 510-511
{
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' ,
'S' , 'B' , ' ' , 'C' , ' ' , ' ' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
// Zero up to 2 last bytes of FAT magic code
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
},
//------------- Block1: FAT12 Table -------------//
{
0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file
},
//------------- Block2: Root Directory -------------//
{
// first entry is volume label
'M' , 'o' , 'n' , 'g' , 'o' , 'o' , 's' , 'e' , ' ' , ' ' , ' ' , 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// second entry is our file
'I' , 'N' , 'D' , 'E' , 'X' , ' ' , ' ' , ' ' , 'H' , 'T' , 'M' , 0x20, 0x00, 0xC6, 0x52, 0x6D,
0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
sizeof(INDEX_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
},
//------------- Block3: file Content -------------//
INDEX_CONTENTS
};
// Invoked to determine max LUN
uint8_t tud_msc_get_maxlun_cb(void)
{
return 1; // single LUN
}
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
{
(void) lun; // use same ID for both LUNs
const char vid[] = "TinyUSB";
const char pid[] = "Mass Storage";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
(void) lun;
return true; // Flash/RAM disks are always ready
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
{
(void) lun;
*block_count = DISK_BLOCK_NUM;
*block_size = DISK_BLOCK_SIZE;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
{
(void) lun;
(void) power_condition;
if ( load_eject )
{
if (start)
{
// load disk storage
}else
{
// unload disk storage
}
}
return true;
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
{
// out of ramdisk
if ( lba >= DISK_BLOCK_NUM ) return -1;
(void) lun;
uint8_t const* addr = msc_disk0[lba] + offset;
memcpy(buffer, addr, bufsize);
return (int32_t) bufsize;
}
bool tud_msc_is_writable_cb (uint8_t lun)
{
(void) lun;
// readonly
return false;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and return number of written bytes
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
{
// out of ramdisk
if ( lba >= DISK_BLOCK_NUM ) return -1;
#if 0
uint8_t* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset;
memcpy(addr, buffer, bufsize);
#else // readonly
(void) lun; (void) lba; (void) offset; (void) buffer;
#endif
return (int32_t) bufsize;
}
// Callback invoked when received an SCSI command not in built-in list below
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 has their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
{
// read10 & write10 has their own callback and MUST not be handled here
void const* response = NULL;
int32_t resplen = 0;
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0])
{
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
// negative means error -> tinyusb could stall and/or response with failed status
resplen = -1;
break;
}
// return resplen must not larger than bufsize
if ( resplen > bufsize ) resplen = bufsize;
if ( response && (resplen > 0) )
{
if(in_xfer)
{
memcpy(buffer, response, (size_t) resplen);
}else
{
// SCSI output
}
}
return resplen;
}
@@ -1,2 +0,0 @@
#pragma once
#define SIZEOF_ETH_HDR 14
@@ -1,12 +0,0 @@
#pragma once
// Windows only supports RNDIS, and apparently doesn't like composite devices with two configurations.
// Mac only supports CDC-ECM, which we present as the second config in a dual configuration device
// Linux supports either RNDIS, CDC-ECM or CDC-NCM
#define CFG_TUD_ECM_RNDIS 1
#define CFG_TUD_MSC 1 // This enables mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512 // Also Add msc_disk.c and descritors
#define CFG_TUD_NCM 0
#define BOARD_DEVICE_RHPORT_NUM 0
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
@@ -1,271 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
// Modified by Cesanta Software
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB]
*/
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) )
// String Descriptor Index
enum
{
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
STRID_INTERFACE,
STRID_MAC
};
enum
{
ITF_NUM_CDC = 0,
ITF_NUM_CDC_DATA,
ITF_NUM_MSC,
ITF_NUM_TOTAL
};
enum
{
#if CFG_TUD_ECM_RNDIS
CONFIG_ID_RNDIS = 0,
#if DUAL_CONFIG
CONFIG_ID_ECM = 1,
#endif
#else
CONFIG_ID_NCM = 0,
#endif
CONFIG_ID_COUNT
};
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
// Use Interface Association Descriptor (IAD) device class
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0xCafe,
.idProduct = USB_PID,
.bcdDevice = 0x0101,
.iManufacturer = STRID_MANUFACTURER,
.iProduct = STRID_PRODUCT,
.iSerialNumber = STRID_SERIAL,
.bNumConfigurations = CONFIG_ID_COUNT // multiple configurations
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void)
{
return (uint8_t const *) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN + TUD_RNDIS_DESC_LEN)
#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN + TUD_CDC_ECM_DESC_LEN)
#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN + TUD_CDC_NCM_DESC_LEN)
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#define EPNUM_MSC_OUT 0x05
#define EPNUM_MSC_IN 0x85
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x83
#define EPNUM_MSC_OUT 0x04
#define EPNUM_MSC_IN 0x85
#else
#define EPNUM_NET_NOTIF 0x81
#define EPNUM_NET_OUT 0x02
#define EPNUM_NET_IN 0x82
#define EPNUM_MSC_OUT 0x03
#define EPNUM_MSC_IN 0x83
#endif
// Interface number, string index, EP Out & EP In address, EP size
# define MSCDESC TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64)
#if CFG_TUD_ECM_RNDIS
static uint8_t const rndis_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE),
MSCDESC
};
#if DUAL_CONFIG
static uint8_t const ecm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
MSCDESC
};
#endif
#else
static uint8_t const ncm_configuration[] =
{
// Config number (index+1), interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100),
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU),
MSCDESC
};
#endif
// Configuration array: RNDIS and CDC-ECM
// - Windows only works with RNDIS
// - MacOS only works with CDC-ECM
// - Linux will work on both
static uint8_t const * const configuration_arr[2] =
{
#if CFG_TUD_ECM_RNDIS
[CONFIG_ID_RNDIS] = rndis_configuration
#if DUAL_CONFIG
, [CONFIG_ID_ECM ] = ecm_configuration
#endif
#else
[CONFIG_ID_NCM ] = ncm_configuration
#endif
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL;
}
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
// array of pointer to string descriptors
static char const* string_desc_arr [] =
{
[STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409)
[STRID_MANUFACTURER] = "TinyUSB", // Manufacturer
[STRID_PRODUCT] = "TinyUSB Device", // Product
[STRID_SERIAL] = "123456", // Serial
[STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description
// STRID_MAC index is handled separately
};
static uint16_t _desc_str[32];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
(void) langid;
unsigned int chr_count = 0;
if (STRID_LANGID == index)
{
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
chr_count = 1;
}
else if (STRID_MAC == index)
{
// Convert MAC address into UTF-16
for (unsigned i=0; i<sizeof(tud_network_mac_address); i++)
{
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf];
_desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf];
}
}
else
{
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = (uint8_t) strlen(str);
if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1;
// Convert ASCII string into UTF-16
for (unsigned int i=0; i<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
return _desc_str;
}
@@ -1,35 +0,0 @@
BOARD = pico-w
IDE = Pico-SDK
RTOS = baremetal
WIZARD_URL ?= http://mongoose.ws/wizard
all build example: firmware.uf2
firmware.uf2: wizard
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
wizard:
hash=$$(curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s -X POST -H "Content-Type: application/json" -d '{"build":{"board":"$(BOARD)","ide":"$(IDE)","rtos":"$(RTOS)"},"http":{"http": true}}' $(WIZARD_URL)/api/hash | jq -r '.hash') \
&& curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s $(WIZARD_URL)/api/zip -o wizard.zip
unzip wizard.zip
cd wizard/mongoose ; rm mongoose.[ch] ; ln -s ../../../../../mongoose.c ; ln -s ../../../../../mongoose.h
flash: firmware.uf2
picotool load $< -f
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/??
# stdio has to be changed from USB to UART in CMakeLists.txt
update: wizard
sed -i -e 's/pico_enable_stdio_usb(firmware 1)/pico_enable_stdio_usb(firmware 0)/' wizard/CMakeLists.txt
(test `grep -c "pico_enable_stdio_uart(firmware 1)" wizard/CMakeLists.txt` -eq 0 && echo "pico_enable_stdio_uart(firmware 1)" >> wizard/CMakeLists.txt) || true
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @firmware.uf2
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=15 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
rm -rf firmware.* wizard* pico-sdk
@@ -1 +0,0 @@
See [Wizard](https://mongoose.ws/wizard/#/output?board=pico-w&ide=Pico-SDK&rtos=baremetal&file=README.md)
@@ -1,36 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
include(FreeRTOS_Kernel_import.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
mongoose.c
net.c
packed_fs.c
)
target_include_directories(firmware PUBLIC
.
)
target_link_libraries(firmware
pico_stdlib
pico_rand
pico_cyw43_arch_lwip_sys_freertos
FreeRTOS-Kernel-Heap4
)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 1) # Route stdio
pico_enable_stdio_uart(firmware 0) # to USB
# Prevent extreme optimization from breaking OTA
target_compile_options(firmware PRIVATE -fno-tree-loop-distribute-patterns)
# Mongoose build flags in mongoose_config.h
# Example build options
add_definitions(-DHTTP_URL="http://0.0.0.0/")
@@ -1,156 +0,0 @@
/*
* FreeRTOS V202111.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_EXAMPLES_COMMON_H
#define FREERTOS_CONFIG_EXAMPLES_COMMON_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
/* Scheduler Related */
#define configUSE_PREEMPTION 1
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES 32
#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 512
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
/* Synchronization Related */
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_QUEUE_SETS 1
#define configUSE_TIME_SLICING 1
#define configUSE_NEWLIB_REENTRANT 0
// todo need this for lwip FreeRTOS sys_arch to compile
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
/* System */
#define configSTACK_DEPTH_TYPE uint32_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE (128*1024)
#define configAPPLICATION_ALLOCATED_HEAP 0
/* Hook function related definitions. */
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 1
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH 1024
/* Interrupt nesting behaviour configuration. */
/*
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
*/
#define configNUMBER_OF_CORES 2
/* SMP (configNUMBER_OF_CORES > 1) only */
#define configTICK_CORE 0
#define configRUN_MULTIPLE_PRIORITIES 1
#if configNUMBER_OF_CORES > 1
#define configUSE_CORE_AFFINITY 1
#endif
#define configUSE_PASSIVE_IDLE_HOOK 0
/* Armv8-M */
/* Not currently supported */
#define configENABLE_MPU 0
//#define configSYSTEM_CALL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 512
#define configENABLE_FPU 1
/* Not currently supported */
#define configENABLE_TRUSTZONE 0
#define configRUN_FREERTOS_SECURE_ONLY 1
// see https://www.freertos.org/RTOS-Cortex-M3-M4.html
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
/* RP2xxx specific */
#define configSUPPORT_PICO_SYNC_INTEROP 1
#define configSUPPORT_PICO_TIME_INTEROP 1
#include <assert.h>
/* Define to trap errors during development. */
#define configASSERT(x) assert(x)
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_xQueueGetMutexHolder 1
/* A header file that defines trace macro can be included here. */
#endif /* FREERTOS_CONFIG_H */
@@ -1,91 +0,0 @@
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
# This can be dropped into an external project to help locate the FreeRTOS kernel
# It should be include()ed prior to project(). Alternatively this file may
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
# respectively.
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
endif ()
# first pass we look in old tree; second pass we look in new tree
foreach(SEARCH_PASS RANGE 0 1)
if (SEARCH_PASS)
# ports may be moving to submodule in the future
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC")
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..")
else()
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC")
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
endif()
if(PICO_PLATFORM STREQUAL "rp2040")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040")
else()
if (PICO_PLATFORM STREQUAL "rp2350-riscv")
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V")
else()
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ")
endif()
endif()
if (NOT FREERTOS_KERNEL_PATH)
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
endif()
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
break()
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
break()
endif()
endif ()
if (NOT FREERTOS_KERNEL_PATH)
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
# check if FreeRTOS-Kernel exists under directory that included us
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
break()
endif()
endforeach()
if (FREERTOS_KERNEL_PATH)
break()
endif()
endif()
# user must have specified
if (FREERTOS_KERNEL_PATH)
if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
break()
endif()
endif()
endforeach ()
if (NOT FREERTOS_KERNEL_PATH)
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
endif()
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
endif()
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
endif()
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
@@ -1,24 +0,0 @@
RM = rm -rf
MKBUILD = rm -rf build && mkdir -p build # test -d build || mkdir build
ifeq ($(OS),Windows_NT)
RM = cmd /C del /Q /F /S
MKBUILD = if not exist build mkdir build
endif
all example:
true
build: pico-sdk FreeRTOS-Kernel build/firmware.uf2
build/firmware.uf2:
$(MKBUILD)
cd build && cmake -DPICO_BOARD="pico_w" -G "Unix Makefiles" .. && make
pico-sdk:
git clone --depth 1 -b 2.0.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init
FreeRTOS-Kernel: # FreeRTOS sources
git clone --depth 1 -b main https://github.com/raspberrypi/FreeRTOS-Kernel $@
clean:
$(RM) pico-sdk build FreeRTOS-Kernel
@@ -1,5 +0,0 @@
# Mongoose on PICO W
See detailed tutorial at https://mongoose.ws/tutorials/rp2040/pico-w/
@@ -1,55 +0,0 @@
#ifndef _LWIPOPTS_H
#define _LWIPOPTS_H
#define TCPIP_THREAD_STACKSIZE 1024
#define DEFAULT_THREAD_STACKSIZE 2048
#define DEFAULT_RAW_RECVMBOX_SIZE 8
#define TCPIP_MBOX_SIZE 16
#define DEFAULT_UDP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
#define DEFAULT_TCP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
#define DEFAULT_ACCEPTMBOX_SIZE TCPIP_MBOX_SIZE
#define LWIP_TIMEVAL_PRIVATE 0
// not necessary, can be done either way
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
#define LWIP_SOCKET 1
#define LWIP_COMPAT_SOCKETS 1
#define LWIP_POSIX_SOCKETS_IO_NAMES 1
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#define MEM_ALIGNMENT 4
#define MEM_SIZE 20000
#define MEMP_NUM_TCP_PCB 10
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 1
#define MEMP_NUM_NETCONN 10
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 0
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#endif
@@ -1,46 +0,0 @@
// Copyright (c) 2024 Cesanta Software Limited
// All rights reserved
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "FreeRTOS.h"
#include <task.h>
#include "mongoose.h"
#include "net.h"
#define WIFI_SSID "yourWiFiSSID"
#define WIFI_PASS "yourWiFiPassword"
static void mongoose(void *args) {
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
mg_log_set(MG_LL_DEBUG); // Set log level
cyw43_arch_init();
cyw43_arch_enable_sta_mode();
cyw43_arch_wifi_connect_blocking(WIFI_SSID, WIFI_PASS, CYW43_AUTH_WPA2_AES_PSK);
MG_INFO(("Initialising application..."));
web_init(&mgr);
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 10);
}
(void) args;
}
int main(void) {
// initialize stdio
stdio_init_all();
xTaskCreate(mongoose, "mongoose", 2048, 0, configMAX_PRIORITIES - 1, NULL);
vTaskStartScheduler(); // This blocks
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1,3 +0,0 @@
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_LWIP 1
@@ -1 +0,0 @@
../../http/device-dashboard/net.c
@@ -1 +0,0 @@
../../http/device-dashboard/net.h
@@ -1 +0,0 @@
../../http/device-dashboard/packed_fs.c
@@ -1,84 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})
-1
View File
@@ -1 +0,0 @@
w5500-evb-pico-picosdk-baremetal-builtin
-12
View File
@@ -1,12 +0,0 @@
# Pico2-W Mongoose example
To build and run,
1. Edit main.c and change WIFI credentials
2. Execute the following
```sh
make build flash
```
3. Run serial console to see the debug output
@@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
mongoose.c
)
target_include_directories(firmware PUBLIC
.
)
target_link_libraries(firmware hardware_pio pico_stdlib pico_rand)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 1) # Route stdio
pico_enable_stdio_uart(firmware 0) # to USB
# Mongoose build flags in mongoose_config.h
# Example build options
@@ -1,20 +0,0 @@
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
all example:
true
build build/firmware.uf2: pico-sdk main.c
$(MKBUILD)
cd build && cmake -G "Unix Makefiles" .. && make
pico-sdk:
git clone --depth 1 -b 2.1.0 https://github.com/raspberrypi/pico-sdk $@
cd $@ && git submodule update --init
clean:
$(RM) pico-sdk build
@@ -1,155 +0,0 @@
// Copyright (c) 2025 Cesanta Software Limited
// All rights reserved
#include "pico/stdlib.h"
#include "hardware/pio.h"
extern void mg_delayms(unsigned int ms);
#define SPIPIO pio0
#define SPISM 0
#define DATAPIN 2
#define CLKPIN 3
#define CSPIN 1
#define PWRPIN 0
#define piospi_wrap_target 0
#define piospi_wrap 6
#define piospi_pio_version 0
#define piospi_offset_rx_ 7u
static const uint16_t piospi_program_instructions[] = {
// .wrap_target
0x80a0, // 0: pull block side 0
0xa027, // 1: mov x, osr side 0
0x6068, // 2: out null, 8 side 0
0x6001, // 3: out pins, 1 side 0
0x1043, // 4: jmp x--, 3 side 1
0xe000, // 5: set pins, 0 side 0
0xc020, // 6: irq wait 0 side 0
// .wrap
0xe080, // 7: set pindirs, 0 side 0
0x6020, // 8: out x, 32 side 0
0x4001, // 9: in pins, 1 side 0
0x1049, // 10: jmp x--, 9 side 1
0xe000, // 11: set pins, 0 side 0
0xe081, // 12: set pindirs, 1 side 0
0xc020, // 13: irq wait 0 side 0
0x0000, // 14: jmp 0 side 0
};
static const struct pio_program piospi_program = {
.instructions = piospi_program_instructions,
.length = 15,
.origin = -1,
.pio_version = 0,
#if PICO_PIO_VERSION > 0
.used_gpio_ranges = 0x0
#endif
};
static inline pio_sm_config piospi_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + piospi_wrap_target, offset + piospi_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
static inline pio_sm_config piospi_init(PIO pio, uint sm, uint addr, uint data, uint clk) {
pio_gpio_init(pio, data);
pio_gpio_init(pio, clk);
pio_sm_set_pins_with_mask(pio, sm, 0, (1 << data) | (1 << clk));
pio_sm_config c = piospi_program_get_default_config(addr);
sm_config_set_out_pins(&c, data, 1);
sm_config_set_in_pins(&c, data);
sm_config_set_set_pins(&c, data, 1);
sm_config_set_sideset_pins(&c, clk);
pio_sm_set_consecutive_pindirs(pio, sm, data, 1, true);
pio_sm_set_consecutive_pindirs(pio, sm, clk, 1, true);
pio_sm_set_pindirs_with_mask(pio, sm, (1 << data) | (1 << clk), (1 << data) | (1 << clk));
sm_config_set_in_shift(&c, false, true, 8); // push bytes, MSB first, auto
#if PICO_RP2040
sm_config_set_clkdiv(&c, 18); // Run at 133/1 = <50MHz (2x data rate)
#else
sm_config_set_clkdiv(&c, 20); // Run at 150/1 = <50MHz (2x data rate)
#endif
return c;
}
static inline void piospi_tx(PIO pio, uint sm, pio_sm_config *c, uint addr, uint data) {
sm_config_set_fifo_join(c, PIO_FIFO_JOIN_TX);
sm_config_set_out_shift(c, false, true, 8); // pull bytes, MSB first, auto
pio_sm_init(pio, sm, addr, c);
}
static inline void piospi_rx(PIO pio, uint sm, pio_sm_config *c, uint addr, uint data) {
sm_config_set_fifo_join(c, PIO_FIFO_JOIN_NONE);
sm_config_set_out_shift(c, false, true, 32); // pull words, MSB first, auto
pio_sm_init(pio, sm, addr + piospi_offset_rx_, c);
}
static inline void piospi_done(PIO pio, uint sm) {
while(!pio_interrupt_get(pio, 0));
pio_sm_set_enabled(pio, sm, false);
pio_interrupt_clear(pio, 0);
}
static pio_sm_config s_piospi_sm_config;
static uint s_piospi_sm_addr;
void piospi_write(uint8_t *data, size_t len) {
size_t initial_len = len;
piospi_tx(SPIPIO, SPISM, &s_piospi_sm_config, s_piospi_sm_addr, DATAPIN);
__compiler_memory_barrier();
pio_sm_put(SPIPIO, SPISM, (len * 8) - 1); // bits to transmit
pio_sm_set_enabled(SPIPIO, SPISM, true);
while (len--) pio_sm_put_blocking(SPIPIO, SPISM, (*data++) << 24);
piospi_done(SPIPIO, SPISM);
}
// Read data block from SPI interface
void piospi_read(uint8_t *data, size_t len) {
piospi_rx(SPIPIO, SPISM, &s_piospi_sm_config, s_piospi_sm_addr, DATAPIN);
__compiler_memory_barrier();
pio_sm_put(SPIPIO, SPISM, (len * 8) - 1); // bits to receive
pio_sm_set_enabled(SPIPIO, SPISM, true);
while (len--) *data++ = pio_sm_get_blocking(SPIPIO, SPISM);
piospi_done(SPIPIO, SPISM);
}
void hwspecific_spi_init(void) {
gpio_init(PWRPIN);
gpio_set_dir(PWRPIN, GPIO_OUT);
gpio_put(PWRPIN, 0);
gpio_init(CSPIN);
gpio_set_dir(CSPIN, GPIO_OUT);
gpio_put(CSPIN, 0);
// init SPI pins so they are idle and stable during power up
gpio_init(DATAPIN);
gpio_set_dir(DATAPIN, GPIO_OUT);
gpio_put(DATAPIN, 0);
gpio_init(CLKPIN);
gpio_set_dir(CLKPIN, GPIO_OUT);
gpio_put(CLKPIN, 0);
mg_delayms(100);
gpio_put(CSPIN, 1);
gpio_put(PWRPIN, 1);
s_piospi_sm_addr = pio_add_program(SPIPIO, &piospi_program);
s_piospi_sm_config = piospi_init(SPIPIO, SPISM, s_piospi_sm_addr, DATAPIN, CLKPIN);
mg_delayms(50);
}
void hwspecific_spi_begin(void *arg) {
gpio_put(CSPIN, 0);
(void) arg;
}
// either write or read, not both
void hwspecific_spi_txn(void *arg, uint8_t *txdata, uint8_t *rxdata, size_t len) {
if (txdata != NULL) piospi_write(txdata, len);
if (rxdata != NULL) piospi_read(rxdata, len);
(void) arg;
}
void hwspecific_spi_end(void *arg) {
gpio_put(CSPIN, 1);
(void) arg;
}
@@ -1,142 +0,0 @@
// Copyright (c) 2025 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "hal.h"
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
static const struct mg_tcpip_spi spi = {NULL, hwspecific_spi_begin, hwspecific_spi_end, hwspecific_spi_txn};
#ifndef CYW43_RESOURCE_ATTRIBUTE
#define CYW43_RESOURCE_ATTRIBUTE
#endif
#include "pico-sdk/lib/cyw43-driver/firmware/w43439A0_7_95_49_00_combined.h"
#include "pico-sdk/lib/cyw43-driver/firmware/wifi_nvram_43439.h"
static const struct mg_tcpip_driver_cyw_firmware fw = {
(const uint8_t *)w43439A0_7_95_49_00_combined, (size_t)CYW43_WIFI_FW_LEN,
(const uint8_t *)wifi_nvram_4343, (size_t)sizeof(wifi_nvram_4343),
(const uint8_t *)(w43439A0_7_95_49_00_combined + sizeof(w43439A0_7_95_49_00_combined) - CYW43_CLM_LEN), (size_t)CYW43_CLM_LEN};
// mif user states
enum {AP, SCANNING, STOPPING_AP, CONNECTING, READY};
static unsigned int state;
static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
// TODO(): should we include this inside ifp ? add an fn_data ?
if (ev == MG_TCPIP_EV_ST_CHG) {
MG_INFO(("State change: %u", *(uint8_t *) ev_data));
}
switch(state) {
case AP: // we are in AP mode, wait for a user connection to trigger a scan or a connection to a network
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("Access Point READY !"));
// simulate user request to scan for networks
bool res = mg_wifi_scan();
MG_INFO(("Starting scan: %s", res ? "OK":"FAIL"));
if (res) state = SCANNING;
}
break;
case SCANNING:
if (ev == MG_TCPIP_EV_WIFI_SCAN_RESULT) {
struct mg_wifi_scan_bss_data *bss = (struct mg_wifi_scan_bss_data *) ev_data;
MG_INFO(("BSS: %.*s (%u) (%M) %d dBm %u", bss->SSID.len, bss->SSID.buf, bss->channel, mg_print_mac, bss->BSSID, (int) bss->RSSI, bss->security));
} else if (ev == MG_TCPIP_EV_WIFI_SCAN_END) {
//struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
MG_INFO(("Wi-Fi scan finished"));
// simulate user selection of a network (1/2: stop AP)
bool res = mg_wifi_ap_stop();
MG_INFO(("Manually stopping AP: %s", res ? "OK":"FAIL"));
if (res) state = STOPPING_AP;
// else we have a hw/fw problem
}
break;
case STOPPING_AP:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_cyw_data *) ifp->driver_data)->wifi;
wifi->apmode = false;
// simulate user selection of a network (2/2: actual connect)
bool res = mg_wifi_connect(wifi);
MG_INFO(("Manually connecting: %s", res ? "OK":"FAIL"));
if (res) {
state = CONNECTING;
} // else manually start AP as below
}
break;
case CONNECTING:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("READY!"));
state = READY;
// simulate user code disconnection and go back to AP mode (1/2: disconnect)
bool res = mg_wifi_disconnect();
MG_INFO(("Manually disconnecting: %s", res ? "OK":"FAIL"));
} else if (ev == MG_TCPIP_EV_WIFI_CONNECT_ERR) {
MG_ERROR(("Wi-Fi connect failed"));
// manually start AP as below
}
break;
case READY:
// go back to AP mode after a disconnection (simulation 2/2), you could retry
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_cyw_data *) ifp->driver_data)->wifi;
bool res = mg_wifi_ap_start(wifi);
MG_INFO(("Disconnected"));
MG_INFO(("Manually starting AP: %s", res ? "OK":"FAIL"));
if (res) {
state = AP;
wifi->apmode = true;
}
}
break;
}
}
static struct mg_tcpip_driver_cyw_data d = {
{WIFI_SSID, WIFI_PASS, "mongoose", "mongoose", 0, 0, 0, 0, 10, true}, (struct mg_tcpip_spi *)&spi, (struct mg_tcpip_driver_cyw_firmware *)&fw, false};
int main(void) {
// initialize stdio
stdio_init_all();
hwspecific_spi_init();
d.wifi.apip = MG_IPV4(192, 168, 169, 1),
d.wifi.apmask = MG_IPV4(255, 255, 255, 0),
state = d.wifi.apmode ? AP : CONNECTING;
struct mg_mgr mgr; // Initialise Mongoose event manager
mg_mgr_init(&mgr); // and attach it to the interface
mg_log_set(MG_LL_DEBUG); // Set log level
// Initialise Mongoose network stack
// 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 = {
.ip = 0,
.driver = (struct mg_tcpip_driver *)&mg_tcpip_driver_cyw,
.driver_data = (struct mg_tcpip_driver_cyw_data*)&d,
.fn = mif_fn,
// .recv_queue.size = 8192
};
mg_tcpip_init(&mgr, &mif);
MG_INFO(("Init done, starting main loop"));
MG_INFO(("Initialising application..."));
MG_INFO(("Starting event loop"));
for (;;) {
mg_mgr_poll(&mgr, 0);
}
return 0;
}
@@ -1 +0,0 @@
../../../mongoose.c
@@ -1 +0,0 @@
../../../mongoose.h
@@ -1,84 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})
@@ -1,24 +0,0 @@
cmake_minimum_required(VERSION 3.13)
include(pico-sdk/pico_sdk_init.cmake)
project(firmware)
pico_sdk_init()
add_executable(firmware
main.c
mongoose.c
)
target_include_directories(firmware PUBLIC
.
)
target_link_libraries(firmware hardware_pio pico_stdlib pico_rand)
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
pico_enable_stdio_usb(firmware 1) # Route stdio
pico_enable_stdio_uart(firmware 0) # to USB
# Mongoose build flags in mongoose_config.h
# Example build options
-155
View File
@@ -1,155 +0,0 @@
// Copyright (c) 2025 Cesanta Software Limited
// All rights reserved
#include "pico/stdlib.h"
#include "hardware/pio.h"
extern void mg_delayms(unsigned int ms);
#define SPIPIO pio0
#define SPISM 0
#define DATAPIN 2
#define CLKPIN 3
#define CSPIN 1
#define PWRPIN 0
#define piospi_wrap_target 0
#define piospi_wrap 6
#define piospi_pio_version 0
#define piospi_offset_rx_ 7u
static const uint16_t piospi_program_instructions[] = {
// .wrap_target
0x80a0, // 0: pull block side 0
0xa027, // 1: mov x, osr side 0
0x6068, // 2: out null, 8 side 0
0x6001, // 3: out pins, 1 side 0
0x1043, // 4: jmp x--, 3 side 1
0xe000, // 5: set pins, 0 side 0
0xc020, // 6: irq wait 0 side 0
// .wrap
0xe080, // 7: set pindirs, 0 side 0
0x6020, // 8: out x, 32 side 0
0x4001, // 9: in pins, 1 side 0
0x1049, // 10: jmp x--, 9 side 1
0xe000, // 11: set pins, 0 side 0
0xe081, // 12: set pindirs, 1 side 0
0xc020, // 13: irq wait 0 side 0
0x0000, // 14: jmp 0 side 0
};
static const struct pio_program piospi_program = {
.instructions = piospi_program_instructions,
.length = 15,
.origin = -1,
.pio_version = 0,
#if PICO_PIO_VERSION > 0
.used_gpio_ranges = 0x0
#endif
};
static inline pio_sm_config piospi_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + piospi_wrap_target, offset + piospi_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
static inline pio_sm_config piospi_init(PIO pio, uint sm, uint addr, uint data, uint clk) {
pio_gpio_init(pio, data);
pio_gpio_init(pio, clk);
pio_sm_set_pins_with_mask(pio, sm, 0, (1 << data) | (1 << clk));
pio_sm_config c = piospi_program_get_default_config(addr);
sm_config_set_out_pins(&c, data, 1);
sm_config_set_in_pins(&c, data);
sm_config_set_set_pins(&c, data, 1);
sm_config_set_sideset_pins(&c, clk);
pio_sm_set_consecutive_pindirs(pio, sm, data, 1, true);
pio_sm_set_consecutive_pindirs(pio, sm, clk, 1, true);
pio_sm_set_pindirs_with_mask(pio, sm, (1 << data) | (1 << clk), (1 << data) | (1 << clk));
sm_config_set_in_shift(&c, false, true, 8); // push bytes, MSB first, auto
#if PICO_RP2040
sm_config_set_clkdiv(&c, 18); // Run at 133/1 = <50MHz (2x data rate)
#else
sm_config_set_clkdiv(&c, 20); // Run at 150/1 = <50MHz (2x data rate)
#endif
return c;
}
static inline void piospi_tx(PIO pio, uint sm, pio_sm_config *c, uint addr, uint data) {
sm_config_set_fifo_join(c, PIO_FIFO_JOIN_TX);
sm_config_set_out_shift(c, false, true, 8); // pull bytes, MSB first, auto
pio_sm_init(pio, sm, addr, c);
}
static inline void piospi_rx(PIO pio, uint sm, pio_sm_config *c, uint addr, uint data) {
sm_config_set_fifo_join(c, PIO_FIFO_JOIN_NONE);
sm_config_set_out_shift(c, false, true, 32); // pull words, MSB first, auto
pio_sm_init(pio, sm, addr + piospi_offset_rx_, c);
}
static inline void piospi_done(PIO pio, uint sm) {
while(!pio_interrupt_get(pio, 0));
pio_sm_set_enabled(pio, sm, false);
pio_interrupt_clear(pio, 0);
}
static pio_sm_config s_piospi_sm_config;
static uint s_piospi_sm_addr;
void piospi_write(uint8_t *data, size_t len) {
size_t initial_len = len;
piospi_tx(SPIPIO, SPISM, &s_piospi_sm_config, s_piospi_sm_addr, DATAPIN);
__compiler_memory_barrier();
pio_sm_put(SPIPIO, SPISM, (len * 8) - 1); // bits to transmit
pio_sm_set_enabled(SPIPIO, SPISM, true);
while (len--) pio_sm_put_blocking(SPIPIO, SPISM, (*data++) << 24);
piospi_done(SPIPIO, SPISM);
}
// Read data block from SPI interface
void piospi_read(uint8_t *data, size_t len) {
piospi_rx(SPIPIO, SPISM, &s_piospi_sm_config, s_piospi_sm_addr, DATAPIN);
__compiler_memory_barrier();
pio_sm_put(SPIPIO, SPISM, (len * 8) - 1); // bits to receive
pio_sm_set_enabled(SPIPIO, SPISM, true);
while (len--) *data++ = pio_sm_get_blocking(SPIPIO, SPISM);
piospi_done(SPIPIO, SPISM);
}
void hwspecific_spi_init(void) {
gpio_init(PWRPIN);
gpio_set_dir(PWRPIN, GPIO_OUT);
gpio_put(PWRPIN, 0);
gpio_init(CSPIN);
gpio_set_dir(CSPIN, GPIO_OUT);
gpio_put(CSPIN, 0);
// init SPI pins so they are idle and stable during power up
gpio_init(DATAPIN);
gpio_set_dir(DATAPIN, GPIO_OUT);
gpio_put(DATAPIN, 0);
gpio_init(CLKPIN);
gpio_set_dir(CLKPIN, GPIO_OUT);
gpio_put(CLKPIN, 0);
mg_delayms(100);
gpio_put(CSPIN, 1);
gpio_put(PWRPIN, 1);
s_piospi_sm_addr = pio_add_program(SPIPIO, &piospi_program);
s_piospi_sm_config = piospi_init(SPIPIO, SPISM, s_piospi_sm_addr, DATAPIN, CLKPIN);
mg_delayms(50);
}
void hwspecific_spi_begin(void *arg) {
gpio_put(CSPIN, 0);
(void) arg;
}
// either write or read, not both
void hwspecific_spi_txn(void *arg, uint8_t *txdata, uint8_t *rxdata, size_t len) {
if (txdata != NULL) piospi_write(txdata, len);
if (rxdata != NULL) piospi_read(rxdata, len);
(void) arg;
}
void hwspecific_spi_end(void *arg) {
gpio_put(CSPIN, 1);
(void) arg;
}
-153
View File
@@ -1,153 +0,0 @@
// Copyright (c) 2025 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
#include "hal.h"
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
static const struct mg_tcpip_spi spi = {NULL, hwspecific_spi_begin, hwspecific_spi_end, hwspecific_spi_txn};
#ifndef CYW43_RESOURCE_ATTRIBUTE
#define CYW43_RESOURCE_ATTRIBUTE
#endif
#include "pico-sdk/lib/cyw43-driver/firmware/w43439A0_7_95_49_00_combined.h"
#include "pico-sdk/lib/cyw43-driver/firmware/wifi_nvram_43439.h"
static const struct mg_tcpip_driver_cyw_firmware fw = {
(const uint8_t *)w43439A0_7_95_49_00_combined, (size_t)CYW43_WIFI_FW_LEN,
(const uint8_t *)wifi_nvram_4343, (size_t)sizeof(wifi_nvram_4343),
(const uint8_t *)(w43439A0_7_95_49_00_combined + sizeof(w43439A0_7_95_49_00_combined) - CYW43_CLM_LEN), (size_t)CYW43_CLM_LEN};
// mif user states
enum {AP, SCANNING, STOPPING_AP, CONNECTING, READY};
static unsigned int state;
static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
// TODO(): should we include this inside ifp ? add an fn_data ?
if (ev == MG_TCPIP_EV_ST_CHG) {
MG_INFO(("State change: %u", *(uint8_t *) ev_data));
}
switch(state) {
case AP: // we are in AP mode, wait for a user connection to trigger a scan or a connection to a network
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("Access Point READY !"));
// simulate user request to scan for networks
bool res = mg_wifi_scan();
MG_INFO(("Starting scan: %s", res ? "OK":"FAIL"));
if (res) state = SCANNING;
}
break;
case SCANNING:
if (ev == MG_TCPIP_EV_WIFI_SCAN_RESULT) {
struct mg_wifi_scan_bss_data *bss = (struct mg_wifi_scan_bss_data *) ev_data;
MG_INFO(("BSS: %.*s (%u) (%M) %d dBm %u", bss->SSID.len, bss->SSID.buf, bss->channel, mg_print_mac, bss->BSSID, (int) bss->RSSI, bss->security));
} else if (ev == MG_TCPIP_EV_WIFI_SCAN_END) {
//struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
MG_INFO(("Wi-Fi scan finished"));
// simulate user selection of a network (1/2: stop AP)
bool res = mg_wifi_ap_stop();
MG_INFO(("Manually stopping AP: %s", res ? "OK":"FAIL"));
if (res) state = STOPPING_AP;
// else we have a hw/fw problem
}
break;
case STOPPING_AP:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_cyw_data *) ifp->driver_data)->wifi;
wifi->apmode = false;
// simulate user selection of a network (2/2: actual connect)
bool res = mg_wifi_connect(wifi);
MG_INFO(("Manually connecting: %s", res ? "OK":"FAIL"));
if (res) {
state = CONNECTING;
} // else manually start AP as below
}
break;
case CONNECTING:
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
MG_INFO(("READY!"));
state = READY;
// simulate user code disconnection and go back to AP mode (1/2: disconnect)
bool res = mg_wifi_disconnect();
MG_INFO(("Manually disconnecting: %s", res ? "OK":"FAIL"));
} else if (ev == MG_TCPIP_EV_WIFI_CONNECT_ERR) {
MG_ERROR(("Wi-Fi connect failed"));
// manually start AP as below
}
break;
case READY:
// go back to AP mode after a disconnection (simulation 2/2), you could retry
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_cyw_data *) ifp->driver_data)->wifi;
bool res = mg_wifi_ap_start(wifi);
MG_INFO(("Disconnected"));
MG_INFO(("Manually starting AP: %s", res ? "OK":"FAIL"));
if (res) {
state = AP;
wifi->apmode = true;
}
}
break;
}
}
static struct mg_tcpip_driver_cyw_data d = {
{WIFI_SSID, WIFI_PASS, "mongoose", "mongoose", 0, 0, 0, 0, 10, true}, (struct mg_tcpip_spi *)&spi, (struct mg_tcpip_driver_cyw_firmware *)&fw, false};
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);
}
}
}
static void driver_init(struct mg_mgr *mgr) {
d.wifi.apip = MG_IPV4(192, 168, 169, 1),
d.wifi.apmask = MG_IPV4(255, 255, 255, 0),
state = d.wifi.apmode ? AP : CONNECTING;
// Initialise Mongoose network stack
// 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 = {
.ip = 0,
.driver = (struct mg_tcpip_driver *)&mg_tcpip_driver_cyw,
.driver_data = (struct mg_tcpip_driver_cyw_data*)&d,
.fn = mif_fn,
// .recv_queue.size = 8192
};
mg_tcpip_init(mgr, &mif);
}
// 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) {
// initialize stdio
stdio_init_all();
hwspecific_spi_init();
run_mongoose();
return 0;
}
@@ -1,5 +0,0 @@
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_DRIVER_CYW 1
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
@@ -1,35 +0,0 @@
BOARD = evb-pico
IDE = Pico-SDK
RTOS = baremetal
WIZARD_URL ?= http://mongoose.ws/wizard
all build example: firmware.uf2
firmware.uf2: wizard
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
wizard:
hash=$$(curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s -X POST -H "Content-Type: application/json" -d '{"build":{"board":"$(BOARD)","ide":"$(IDE)","rtos":"$(RTOS)"},"http":{"http": true}}' $(WIZARD_URL)/api/hash | jq -r '.hash') \
&& curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s $(WIZARD_URL)/api/zip -o wizard.zip
unzip wizard.zip
cd wizard/mongoose ; rm mongoose.[ch] ; ln -s ../../../../../mongoose.c ; ln -s ../../../../../mongoose.h
flash: firmware.uf2
picotool load $< -f
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/3
# stdio has to be changed from USB to UART in CMakeLists.txt
update: wizard
sed -i -e 's/pico_enable_stdio_usb(firmware 1)/pico_enable_stdio_usb(firmware 0)/' wizard/CMakeLists.txt
(test `grep -c "pico_enable_stdio_uart(firmware 1)" wizard/CMakeLists.txt` -eq 0 && echo "pico_enable_stdio_uart(firmware 1)" >> wizard/CMakeLists.txt) || true
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @firmware.uf2
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=15 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
rm -rf firmware.* wizard* pico-sdk
@@ -1,5 +0,0 @@
# RP2040 + W5500 Ethernet chip
- See [Wizard](https://mongoose.ws/wizard/#/output?board=evb-pico&ide=Pico-SDK&rtos=baremetal&file=README.md)
- See detailed tutorial (including hardware connections) at https://mongoose.ws/tutorials/rp2040/pico-w5500/
@@ -1,35 +0,0 @@
BOARD = evb-pico2
IDE = Pico-SDK
RTOS = baremetal
WIZARD_URL ?= http://mongoose.ws/wizard
all build example: firmware.uf2
firmware.uf2: wizard
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
wizard:
hash=$$(curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s -X POST -H "Content-Type: application/json" -d '{"build":{"board":"$(BOARD)","ide":"$(IDE)","rtos":"$(RTOS)"},"http":{"http": true}}' $(WIZARD_URL)/api/hash | jq -r '.hash') \
&& curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s $(WIZARD_URL)/api/zip -o wizard.zip
unzip wizard.zip
cd wizard/mongoose ; rm mongoose.[ch] ; ln -s ../../../../../mongoose.c ; ln -s ../../../../../mongoose.h
flash: firmware.uf2
picotool load $< -f
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/??
# stdio has to be changed from USB to UART in CMakeLists.txt
update: wizard
sed -i -e 's/pico_enable_stdio_usb(firmware 1)/pico_enable_stdio_usb(firmware 0)/' wizard/CMakeLists.txt
(test `grep -c "pico_enable_stdio_uart(firmware 1)" wizard/CMakeLists.txt` -eq 0 && echo "pico_enable_stdio_uart(firmware 1)" >> wizard/CMakeLists.txt) || true
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota?uf2=1 --data-binary @firmware.uf2
test: update
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=15 | tee /tmp/output.txt
grep 'READY, IP:' /tmp/output.txt # Check for network init
clean:
rm -rf firmware.* wizard* pico-sdk
@@ -1,5 +0,0 @@
# RP2350 + W5500 Ethernet chip
- See [Wizard](https://mongoose.ws/wizard/#/output?board=evb-pico2&ide=Pico-SDK&rtos=baremetal&file=README.md)
- See detailed tutorial (including hardware connections) at https://mongoose.ws/tutorials/rp2040/pico-w5500/
@@ -1,40 +0,0 @@
# 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: build/firmware.uf2
build/firmware.uf2: pico_sdk_import.cmake mongoose.c mongoose.h
pico_sdk_import.cmake: $(SDK_PATH)
cp $(SDK_PATH)/external/$@ $@
mongoose.c mongoose.h:
cp ../../../$@ .
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.c mongoose.h
fullclean: clean
$(RM) $(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
@@ -1,22 +0,0 @@
BOARD = evb-pico-w55rp20
IDE = Pico-SDK
RTOS = baremetal
WIZARD_URL ?= http://mongoose.ws/wizard
all build example: firmware.uf2
firmware.uf2: wizard
make -C wizard CFLAGS_EXTRA=$(CFLAGS_EXTRA) && mv wizard/build/firmware.uf2 ./
wizard:
hash=$$(curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s -X POST -H "Content-Type: application/json" -d '{"build":{"board":"$(BOARD)","ide":"$(IDE)","rtos":"$(RTOS)"},"http":{"http": true}}' $(WIZARD_URL)/api/hash | jq -r '.hash') \
&& curl -H 'Cookie: mongoose_wizard_uid=F2PPlAgQCqSthV1g' -s $(WIZARD_URL)/api/zip -o wizard.zip
unzip wizard.zip
cd wizard/mongoose ; rm mongoose.[ch] ; ln -s ../../../../../mongoose.c ; ln -s ../../../../../mongoose.h
flash: firmware.uf2
picotool load $< -f
clean:
rm -rf firmware.* wizard* pico-sdk
@@ -1,48 +0,0 @@
#pragma once
// See https://mongoose.ws/documentation/#build-options
#define MG_ARCH MG_ARCH_PICOSDK
#define MG_OTA MG_OTA_PICOSDK
#define MG_TLS MG_TLS_BUILTIN
#define MG_IO_SIZE 2048
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_DRIVER_W5500 1
// For static IP configuration, define MG_TCPIP_{IP,MASK,GW}
// By default, those are set to zero, meaning that DHCP is used
//
// #define MG_TCPIP_IP MG_IPV4(192, 168, 1, 10)
// #define MG_TCPIP_GW MG_IPV4(192, 168, 1, 1)
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0)
// Set custom MAC address. By default, it is randomly generated
// Using a build-time constant:
// #define MG_SET_MAC_ADDRESS(mac) do { uint8_t buf_[6] = {2,3,4,5,6,7};
// memmove(mac, buf_, sizeof(buf_)); } while (0)
//
// Using custom function:
extern void genmac(unsigned char *mac);
#define MG_SET_MAC_ADDRESS(mac) genmac(mac)
// Hardware specific SPI support
#include <stddef.h>
#include <stdint.h>
extern void spi_begin(void *);
extern void spi_end(void *);
extern void spi_txn(void *spi, uint8_t *tx, uint8_t *rx, size_t len);
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_spi spi_ = {NULL, spi_begin, spi_end, spi_txn}; \
static struct mg_tcpip_if mif_; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_w5500; \
mif_.driver_data = &spi_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: W5500, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
Loaded 100 of 142 files, more files were not shown because too many files have changed in this diff. Show more