Compare commits

..

2 Commits

Author SHA1 Message Date
Phil Howard
f31d1468cd CI: i75w build.
Note: 4MB build only.
2025-01-22 14:29:57 +00:00
Phil Howard
84a507e6ac CI: Bump pimoroni-pico to feature/picovector2-and-layers. 2025-01-22 14:28:38 +00:00
86 changed files with 739 additions and 319 deletions

View File

@ -6,34 +6,48 @@ on:
release: release:
types: [created] types: [created]
env:
MICROPYTHON_VERSION: feature/psram-and-wifi
MICROPYTHON_FLAVOUR: pimoroni
PIMORONI_PICO_VERSION: feature/picovector2-and-layers
jobs: jobs:
build: build:
name: MicroPython ${{ matrix.name }} name: ${{ matrix.name }} (${{ matrix.board }})
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
include: include:
- name: rpi_pico2 - name: pico2
- name: rpi_pico2_w board: RPI_PICO2
- name: rpi_pico2b - name: pico2_w
- name: pimoroni_plasma2350 board: RPI_PICO2_W
- name: pimoroni_tiny2350 - name: pico2b_rp2350
- name: pimoroni_pico_plus2 board: RPI_PICO2B
- name: plasma2350
board: PIMORONI_PLASMA2350
- name: tiny2350
board: PIMORONI_TINY2350
- name: pico_plus2_rp2350
board: PIMORONI_PICO_PLUS2
- name: i75w_rp2350
board: PIMORONI_I75W_2350
env: env:
# MicroPython version will be contained in github.event.release.tag_name for releases # MicroPython version will be contained in github.event.release.tag_name for releases
CI_RELEASE_FILENAME: ${{ matrix.name }}-${{ github.event.release.tag_name || github.sha }}-micropython RELEASE_FILE: ${{ matrix.name }}-${{ github.event.release.tag_name || github.sha }}-pimoroni-micropython
CI_PROJECT_ROOT: ${{ github.workspace }}/src-${{ github.sha }} PIMORONI_PICO_DIR: "${{ github.workspace }}/pimoroni-pico"
CI_BUILD_ROOT: ${{ github.workspace }} MICROPY_BOARD_DIR: "${{ github.workspace }}/pimoroni-pico-rp2350-${{ github.sha }}/micropython/board/${{ matrix.BOARD }}"
CI_USE_ENV: 1 USER_C_MODULES: "${{ github.workspace }}/pimoroni-pico-rp2350-${{ github.sha }}/micropython/micropython-pico2.cmake"
TAG_OR_SHA: ${{ github.event.release.tag_name || github.sha }}
MICROPY_BOARD: ${{ matrix.board }}
MICROPY_BOARD_VARIANT: ${{ matrix.variant }}
BOARD_NAME: ${{ matrix.name }}
BUILD_TOOLS: pimoroni-pico-rp2350-${{ github.sha }}/ci/micropython.sh
steps: steps:
- name: Compiler Cache Fixup - name: Compiler Cache
run: |
mkdir -p /home/runner/.ccache
- name: "CCache: Restore saved cache"
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: /home/runner/.ccache path: /home/runner/.ccache
@ -42,61 +56,76 @@ jobs:
ccache-micropython-${{ matrix.name }}-${{ github.ref }} ccache-micropython-${{ matrix.name }}-${{ github.ref }}
ccache-micropython-${{ matrix.name }}- ccache-micropython-${{ matrix.name }}-
- name: "Checkout Project" - uses: actions/checkout@v4
uses: actions/checkout@v4
with: with:
submodules: true submodules: true
path: ${{ env.CI_PROJECT_ROOT }} path: pimoroni-pico-rp2350-${{ github.sha }}
- name: "Install Arm GNU Toolchain (arm-none-eabi-gcc)" - uses: actions/checkout@v4
with:
repository: pimoroni/pimoroni-pico
ref: ${{env.PIMORONI_PICO_VERSION}}
submodules: true
path: pimoroni-pico
- name: Install Arm GNU Toolchain (arm-none-eabi-gcc)
uses: carlosperate/arm-none-eabi-gcc-action@v1 uses: carlosperate/arm-none-eabi-gcc-action@v1
with: with:
release: '13.3.Rel1' release: '13.3.Rel1'
- name: "Prepare tools & dependencies" - name: Install CCache
shell: bash
run: | run: |
source $CI_PROJECT_ROOT/ci/micropython.sh && ci_debug source $BUILD_TOOLS
mkdir -p $CI_BUILD_ROOT apt_install_build_deps
ci_apt_install_build_deps
ci_prepare_all
- name: "MicroPython: Configure" - name: Checkout MicroPython & Submodules
run: |
source $BUILD_TOOLS
micropython_clone
- name: "Py_Decl: Checkout py_decl"
uses: actions/checkout@v4
with:
repository: gadgetoid/py_decl
ref: v0.0.2
path: py_decl
- name: Build MPY Cross
run: |
source $BUILD_TOOLS
micropython_build_mpy_cross
- name: Configure MicroPython
shell: bash shell: bash
run: | run: |
source $CI_PROJECT_ROOT/ci/micropython.sh && ci_debug source $BUILD_TOOLS
micropython_version micropython_version
ci_cmake_configure ${{ matrix.name }} cmake_configure
- name: "MicroPython: Build" - name: Build MicroPython
shell: bash shell: bash
run: | run: |
source $CI_PROJECT_ROOT/ci/micropython.sh && ci_debug source $BUILD_TOOLS
python3 -m venv "$CI_BUILD_ROOT/.dir2uf2" cmake_build
source "$CI_BUILD_ROOT/.dir2uf2/bin/activate"
ci_cmake_build ${{ matrix.name }}
- name: "Artifacts: Upload .uf2" - name: "Py_Decl: Verify UF2"
shell: bash
run: |
python3 py_decl/py_decl.py --to-json --verify build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: Store .uf2 as artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{ env.CI_RELEASE_FILENAME }}.uf2 name: ${{ env.RELEASE_FILE }}.uf2
path: ${{ env.CI_BUILD_ROOT }}/${{ env.CI_RELEASE_FILENAME }}.uf2 path: build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: "Release: Upload .uf2" - name: Upload .uf2
if: github.event_name == 'release' if: github.event_name == 'release'
uses: softprops/action-gh-release@v2 uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
files: ${{ env.CI_BUILD_ROOT }}/${{ env.CI_RELEASE_FILENAME }}.uf2 asset_path: build-${{ matrix.name }}/firmware.uf2
upload_url: ${{ github.event.release.upload_url }}
- name: "Artifacts: Upload .uf2 (With Filesystem)" asset_name: ${{ env.RELEASE_FILE }}.uf2
uses: actions/upload-artifact@v4 asset_content_type: application/octet-stream
with:
if-no-files-found: ignore
name: ${{ env.CI_RELEASE_FILENAME }}-with-filesystem.uf2
path: ${{ env.CI_BUILD_ROOT }}/${{ env.CI_RELEASE_FILENAME }}-with-filesystem.uf2
- name: "Release: Upload .uf2 (With Filesystem)"
if: github.event_name == 'release'
uses: softprops/action-gh-release@v2
with:
files: ${{ env.CI_BUILD_ROOT }}/${{ env.CI_RELEASE_FILENAME }}-with-filesystem.uf2

39
.gitignore vendored
View File

@ -1,39 +0,0 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
**/build
.vscode
# Apple filesystem cruft
.DS_Store
venv

View File

@ -7,17 +7,15 @@ batteries-included flavour of MicroPython for RP2350 / Pico2 boards.
| Board | MicroPython Flavour | Download Link | Notes | | Board | MicroPython Flavour | Download Link | Notes |
|-------|---------------------|---------------|-------| |-------|---------------------|---------------|-------|
| Pimoroni Pico Plus 2 & 2 W | pimoroni_pico_plus2-vx.x.x | [Download from Releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/latest) | :warning: Experimental: Enables PSRAM | Pimoroni Pico Plus 2 & 2 W | pico_plus2_rp2350 | [pico_plus2_rp2350-v0.0.11-pimoroni-micropython.uf2](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/download/v0.0.11/pico_plus2_rp2350-v0.0.11-pimoroni-micropython.uf2) | :warning: Experimental: Enables PSRAM
| Tiny 2350 | pimoroni_tiny2350-vx.x.x | [Download from Releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/latest) | | Plasma 2350 & Plasma 2350 W | plasma2350 | [plasma2350-v0.0.11-pimoroni-micropython.uf2](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/download/v0.0.11/plasma2350-v0.0.11-pimoroni-micropython.uf2) |
| Raspberry Pi Pico 2 | rpi-pico2-vx.x.x | [Download from Releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/latest) | This gives you the Pimoroni Pico libs on a vanilla Pico 2 | Tiny 2350 | tiny2350 | [tiny2350-v0.0.11-pimoroni-micropython.uf2](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/download/v0.0.11/tiny2350-v0.0.11-pimoroni-micropython.uf2) |
| Raspberry Pi Pico 2 W | rpi-pico2_w-vx.x.x | [Download from Releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/latest) | This gives you the Pimoroni Pico libs on a vanilla Pico 2 W | Raspberry Pi Pico 2 | pico2 | [pico2-v0.0.11-pimoroni-micropython.uf2](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/download/v0.0.11/pico2-v0.0.11-pimoroni-micropython.uf2) | This gives you the Pimoroni Pico libs on a vanilla Pico 2
| Raspberry Pi Pico 2 W | pico2_w | [pico2_w-v0.0.11-pimoroni-micropython.uf2](https://github.com/pimoroni/pimoroni-pico-rp2350/releases/download/v0.0.11/pico2_w-v0.0.11-pimoroni-micropython.uf2) | This gives you the Pimoroni Pico libs on a vanilla Pico 2 W
| PGA2350 | ~ | [https://github.com/pimoroni/pga/](https://github.com/pimoroni/pga/) | See the PGA repo for builds and boilerplate | PGA2350 | ~ | [https://github.com/pimoroni/pga/](https://github.com/pimoroni/pga/) | See the PGA repo for builds and boilerplate
| Pimoroni Explorer | ~ | [https://github.com/pimoroni/explorer](https://github.com/pimoroni/explorer) | See the Explorer repo for builds and examples | Pimoroni Explorer | ~ | [https://github.com/pimoroni/explorer](https://github.com/pimoroni/explorer) | See the Explorer repo for builds and examples
| Inky Frame (Pico 2 W Aboard) | ~ | [https://github.com/pimoroni/inky-frame](https://github.com/pimoroni/inky-frame) | See the Inky Frame repo for builds and examples | Inky Frame (Pico 2 W Aboard) | ~ | [https://github.com/pimoroni/inky-frame](https://github.com/pimoroni/inky-frame) | See the Inky Frame repo for builds and examples
| Pico 2 W Unicorn | ~ | [https://github.com/pimoroni/unicorn](https://github.com/pimoroni/unicorn) | See the Unicorn repo for builds and examples | Pico 2 W Unicorn | ~ | [https://github.com/pimoroni/unicorn](https://github.com/pimoroni/unicorn) | See the Unicorn repo for builds and examples
| Pimoroni Presto | ~ | [https://github.com/pimoroni/presto](https://github.com/pimoroni/presto) | See the Presto repo for builds and examples | Pimoroni Presto | ~ | [https://github.com/pimoroni/presto](https://github.com/pimoroni/presto) | See the Presto repo for builds and examples
| Interstate 75 W (RP2350) | ~ | [https://github.com/pimoroni/interstate75](https://github.com/pimoroni/interstate75) | See the Interstate 75 repo for builds and examples
| Plasma 2350 & Plasma 2350 W | ~ | [https://github.com/pimoroni/plasma](https://github.com/pimoroni/plasma) | See the Plasma repo for builds and examples
| Pimoroni Pico LiPo 2 & 2 XL W | ~ | [https://github.com/pimoroni/pico-lipo](https://github.com/pimoroni/pico-lipo) | See the Pico-LiPo repo for builds and examples
For a list of all releases see [https://github.com/pimoroni/pimoroni-pico-rp2350/releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases). For a list of all releases see [https://github.com/pimoroni/pimoroni-pico-rp2350/releases](https://github.com/pimoroni/pimoroni-pico-rp2350/releases).

View File

@ -1,41 +0,0 @@
# Make sure we get our VirtualEnv Python
set(Python_FIND_VIRTUALENV "FIRST")
set(Python_FIND_UNVERSIONED_NAMES "FIRST")
set(Python_FIND_STRATEGY "LOCATION")
find_package (Python COMPONENTS Interpreter Development)
message("dir2uf2/py_decl: Using Python ${Python_EXECUTABLE}")
MESSAGE("dir2uf2/py_decl: Using pimoroni tools dir ${PIMORONI_TOOLS_DIR}")
if (EXISTS "${PIMORONI_TOOLS_DIR}/py_decl/py_decl.py")
MESSAGE("py_decl: py_decl.py found, will verify uf2.")
add_custom_target("${MICROPY_TARGET}-verify" ALL
COMMAND ${Python_EXECUTABLE} "${PIMORONI_TOOLS_DIR}/py_decl/py_decl.py" --to-json --verify "${CMAKE_CURRENT_BINARY_DIR}/${MICROPY_TARGET}.uf2"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "pydecl: Verifying ${MICROPY_TARGET}.uf2"
DEPENDS ${MICROPY_TARGET}
)
endif()
if(DEFINED PIMORONI_UF2_MANIFEST AND DEFINED PIMORONI_UF2_DIR)
# Convert supplies paths to absolute, for a quieter life
get_filename_component(PIMORONI_UF2_MANIFEST ${PIMORONI_UF2_MANIFEST} REALPATH)
get_filename_component(PIMORONI_UF2_DIR ${PIMORONI_UF2_DIR} REALPATH)
if (EXISTS "${PIMORONI_TOOLS_DIR}/dir2uf2/dir2uf2" AND EXISTS "${PIMORONI_UF2_MANIFEST}" AND EXISTS "${PIMORONI_UF2_DIR}")
MESSAGE("dir2uf2: Using manifest ${PIMORONI_UF2_MANIFEST}.")
MESSAGE("dir2uf2: Using root ${PIMORONI_UF2_DIR}.")
add_custom_target("${MICROPY_TARGET}-with-filesystem.uf2" ALL
COMMAND ${Python_EXECUTABLE} "${PIMORONI_TOOLS_DIR}/dir2uf2/dir2uf2" --fs-compact --sparse --append-to "${MICROPY_TARGET}.uf2" --manifest "${PIMORONI_UF2_MANIFEST}" --filename with-filesystem.uf2 "${PIMORONI_UF2_DIR}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "dir2uf2: Appending filesystem to ${MICROPY_TARGET}.uf2."
DEPENDS ${MICROPY_TARGET}
DEPENDS "${MICROPY_TARGET}-verify"
)
else()
MESSAGE("dir2uf2: Could not find manifest ${PIMORONI_UF2_MANIFEST}")
MESSAGE(" and/or root ${PIMORONI_UF2_DIR}.")
endif()
endif()

View File

@ -1,12 +0,0 @@
# micropython/ports/rp2/../../../
MODULES_PY = "$(PORT_DIR)/../../../pimoroni-pico/micropython/modules_py"
# SD Card
require("sdcard")
freeze(MODULES_PY, "gfx_pack.py")
freeze(MODULES_PY, "pimoroni.py")
freeze(MODULES_PY, "boot.py")
freeze(MODULES_PY, "lte.py")

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,18 +0,0 @@
# cmake file for Raspberry Pi Pico2
set(PICO_BOARD "pico2")
# To change the gpio count for QFN-80
# set(PICO_NUM_GPIOS 48)
# Links micropy_lib_lwip and sets MICROPY_PY_LWIP = 1
# Picked up and expanded upon in mpconfigboard.h
set(MICROPY_PY_LWIP ON)
if (PICO_CYW43_SUPPORTED)
include(enable_cyw43.cmake)
set(PICO_PINS_CSV_NAME pins_cyw43.csv)
endif()
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,16 +0,0 @@
# cmake file for Raspberry Pi Pico 2 W
set(PICO_BOARD "pico2_w")
# To change the gpio count for QFN-80
# set(PICO_NUM_GPIOS 48)
# Links micropy_lib_lwip and sets MICROPY_PY_LWIP = 1
# Picked up and expanded upon in mpconfigboard.h
set(MICROPY_PY_LWIP ON)
include(enable_cyw43.cmake)
# Board specific version of the frozen manifest
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,3 +0,0 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
include(usermod-common)

View File

@ -1,15 +1,5 @@
export TERM=${TERM:="xterm-256color"} export TERM=${TERM:="xterm-256color"}
MICROPYTHON_FLAVOUR="pimoroni"
MICROPYTHON_VERSION="pico2_w_2025_09_19"
PIMORONI_PICO_FLAVOUR="pimoroni"
PIMORONI_PICO_VERSION="431d8ad455371075ed247b10ded769d12136c7aa"
PY_DECL_VERSION="v0.0.3"
DIR2UF2_VERSION="v0.0.9"
function log_success { function log_success {
echo -e "$(tput setaf 2)$1$(tput sgr0)" echo -e "$(tput setaf 2)$1$(tput sgr0)"
} }
@ -22,19 +12,10 @@ function log_warning {
echo -e "$(tput setaf 1)$1$(tput sgr0)" echo -e "$(tput setaf 1)$1$(tput sgr0)"
} }
function ci_pimoroni_pico_clone { function micropython_clone {
log_inform "Using Pimoroni Pico $PIMORONI_PICO_FLAVOUR/$PIMORONI_PICO_VERSION" log_inform "Using MicroPython $MICROPYTHON_VERSION"
git clone https://github.com/$PIMORONI_PICO_FLAVOUR/pimoroni-pico "$CI_BUILD_ROOT/pimoroni-pico" git clone https://github.com/$MICROPYTHON_FLAVOUR/micropython
cd "$CI_BUILD_ROOT/pimoroni-pico" || return 1 cd micropython
git checkout $PIMORONI_PICO_VERSION
git submodule update --init
cd "$CI_BUILD_ROOT"
}
function ci_micropython_clone {
log_inform "Using MicroPython $MICROPYTHON_FLAVOUR/$MICROPYTHON_VERSION"
git clone https://github.com/$MICROPYTHON_FLAVOUR/micropython "$CI_BUILD_ROOT/micropython"
cd "$CI_BUILD_ROOT/micropython" || return 1
git checkout $MICROPYTHON_VERSION git checkout $MICROPYTHON_VERSION
git submodule update --init lib/pico-sdk git submodule update --init lib/pico-sdk
git submodule update --init lib/cyw43-driver git submodule update --init lib/cyw43-driver
@ -43,98 +24,42 @@ function ci_micropython_clone {
git submodule update --init lib/micropython-lib git submodule update --init lib/micropython-lib
git submodule update --init lib/tinyusb git submodule update --init lib/tinyusb
git submodule update --init lib/btstack git submodule update --init lib/btstack
cd "$CI_BUILD_ROOT" cd ../
} }
function ci_tools_clone { function micropython_build_mpy_cross {
mkdir -p "$CI_BUILD_ROOT/tools" cd micropython/mpy-cross
git clone https://github.com/gadgetoid/py_decl -b "$PY_DECL_VERSION" "$CI_BUILD_ROOT/tools/py_decl"
git clone https://github.com/gadgetoid/dir2uf2 -b "$DIR2UF2_VERSION" "$CI_BUILD_ROOT/tools/dir2uf2"
python3 -m pip install littlefs-python==0.12.0
}
function ci_micropython_build_mpy_cross {
cd "$CI_BUILD_ROOT/micropython/mpy-cross" || return 1
ccache --zero-stats || true ccache --zero-stats || true
CROSS_COMPILE="ccache " make CROSS_COMPILE="ccache " USER_C_MODULES= make
ccache --show-stats || true ccache --show-stats || true
cd "$CI_BUILD_ROOT" cd ../../
} }
function ci_apt_install_build_deps { function apt_install_build_deps {
sudo apt update && sudo apt install ccache sudo apt update && sudo apt install ccache
} }
function ci_prepare_all {
ci_tools_clone
ci_micropython_clone
ci_pimoroni_pico_clone
ci_micropython_build_mpy_cross
}
function ci_debug {
log_inform "Project root: $CI_PROJECT_ROOT"
log_inform "Build root: $CI_BUILD_ROOT"
}
function micropython_version { function micropython_version {
BOARD=$1 echo "MICROPY_GIT_TAG=$MICROPYTHON_VERSION, $BOARD_NAME $TAG_OR_SHA" >> $GITHUB_ENV
echo "MICROPY_GIT_TAG=$MICROPYTHON_VERSION, $BOARD $TAG_OR_SHA" >> $GITHUB_ENV
echo "MICROPY_GIT_HASH=$MICROPYTHON_VERSION-$TAG_OR_SHA" >> $GITHUB_ENV echo "MICROPY_GIT_HASH=$MICROPYTHON_VERSION-$TAG_OR_SHA" >> $GITHUB_ENV
} }
function ci_cmake_configure { function cmake_configure {
BOARD=$1 cmake -S micropython/ports/rp2 -B build-$BOARD_NAME \
TOOLS_DIR="$CI_BUILD_ROOT/tools"
MICROPY_BOARD_DIR=$CI_PROJECT_ROOT/boards/$BOARD
if [ ! -f "$MICROPY_BOARD_DIR/mpconfigboard.cmake" ]; then
log_warning "Invalid board: \"$BOARD\". Run with ci_cmake_configure <board_name>."
return 1
fi
BUILD_DIR="$CI_BUILD_ROOT/build-$BOARD"
cmake -S $CI_BUILD_ROOT/micropython/ports/rp2 -B "$BUILD_DIR" \
-DPICOTOOL_FORCE_FETCH_FROM_GIT=1 \
-DPICO_BUILD_DOCS=0 \ -DPICO_BUILD_DOCS=0 \
-DPICO_NO_COPRO_DIS=1 \ -DPICO_NO_COPRO_DIS=1 \
-DPICOTOOL_FETCH_FROM_GIT_PATH="$TOOLS_DIR/picotool" \ -DUSER_C_MODULES=$USER_C_MODULES \
-DPIMORONI_PICO_PATH="$CI_BUILD_ROOT/pimoroni-pico" \ -DMICROPY_BOARD_DIR=$MICROPY_BOARD_DIR \
-DPIMORONI_TOOLS_DIR="$TOOLS_DIR" \ -DMICROPY_BOARD=$MICROPY_BOARD \
-DUSER_C_MODULES="$MICROPY_BOARD_DIR/usermodules.cmake" \ -DMICROPY_BOARD_VARIANT=$MICROPY_BOARD_VARIANT \
-DMICROPY_BOARD_DIR="$MICROPY_BOARD_DIR" \
-DMICROPY_BOARD="$BOARD" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
} }
function ci_cmake_build { function cmake_build {
BOARD=$1
MICROPY_BOARD_DIR=$CI_PROJECT_ROOT/boards/$BOARD
if [ ! -f "$MICROPY_BOARD_DIR/mpconfigboard.cmake" ]; then
log_warning "Invalid board: \"$BOARD\". Run with ci_cmake_build <board_name>."
return 1
fi
BUILD_DIR="$CI_BUILD_ROOT/build-$BOARD"
ccache --zero-stats || true ccache --zero-stats || true
cmake --build $BUILD_DIR -j 2 cmake --build build-$BOARD_NAME -j 2
ccache --show-stats || true ccache --show-stats || true
cd build-$BOARD_NAME
if [ -z ${CI_RELEASE_FILENAME+x} ]; then cp firmware.uf2 $RELEASE_FILE.uf2
CI_RELEASE_FILENAME="$BOARD"
fi
log_inform "Copying .uf2 to $(pwd)/$CI_RELEASE_FILENAME.uf2"
cp "$BUILD_DIR/firmware.uf2" $CI_RELEASE_FILENAME.uf2
if [ -f "$BUILD_DIR/firmware-with-filesystem.uf2" ]; then
log_inform "Copying -with-filesystem .uf2 to $(pwd)/$CI_RELEASE_FILENAME-with-filesystem.uf2"
cp "$BUILD_DIR/firmware-with-filesystem.uf2" $CI_RELEASE_FILENAME-with-filesystem.uf2
fi
} }
if [ -z ${CI_USE_ENV+x} ] || [ -z ${CI_PROJECT_ROOT+x} ] || [ -z ${CI_BUILD_ROOT+x} ]; then
SCRIPT_PATH="$(dirname $0)"
CI_PROJECT_ROOT=$(realpath "$SCRIPT_PATH/..")
CI_BUILD_ROOT=$(pwd)
fi
ci_debug

View File

@ -6,3 +6,5 @@ require("aioble")
include("$(PORT_DIR)/boards/manifest.py") include("$(PORT_DIR)/boards/manifest.py")
include("../manifest_pico2.py") include("../manifest_pico2.py")
freeze("$(BOARD_DIR)/../../modules_py", "lte.py")

View File

@ -0,0 +1,38 @@
# cmake file for Raspberry Pi Pico
set(PICO_BOARD "pimoroni_i75w_2350")
set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR})
set(PICO_PLATFORM "rp2350")
# Board specific version of the frozen manifest
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(MICROPY_C_HEAP_SIZE 4096)
# Links micropy_lib_lwip and sets MICROPY_PY_LWIP = 1
# Picked up and expanded upon in mpconfigboard.h
set(MICROPY_PY_LWIP ON)
# Links cyw43-driver and sets:
# MICROPY_PY_NETWORK_CYW43 = 1,
# MICROPY_PY_SOCKET_DEFAULT_TIMEOUT_MS = 30000
set(MICROPY_PY_NETWORK_CYW43 ON)
# Adds mpbthciport.c
# And sets:
# MICROPY_PY_BLUETOOTH = 1,
# MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS = 1,
# MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE = 1
set(MICROPY_PY_BLUETOOTH ON)
# Links pico_btstack_hci_transport_cyw43
# And sets:
# MICROPY_BLUETOOTH_BTSTACK = 1,
# MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE =
set(MICROPY_BLUETOOTH_BTSTACK ON)
# Sets:
# CYW43_ENABLE_BLUETOOTH = 1,
# MICROPY_PY_BLUETOOTH_CYW43 = 1
set(MICROPY_PY_BLUETOOTH_CYW43 ON)

View File

@ -0,0 +1,26 @@
// Board and hardware specific configuration
#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (2 * 1024 * 1024))
// Set up networking.
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "I75W"
#define MICROPY_HW_BOARD_NAME "Pimoroni i75w RP2350"
// Enable WiFi & PPP
#define MICROPY_PY_NETWORK (1)
#define MICROPY_PY_NETWORK_PPP_LWIP (1)
// CYW43 driver configuration.
#define CYW43_USE_SPI (1)
#define CYW43_LWIP (1)
#define CYW43_GPIO (1)
#define CYW43_SPI_PIO (1)
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
#define MICROPY_HW_PIN_EXT_COUNT CYW43_WL_GPIO_COUNT
int mp_hal_is_pin_reserved(int n);
#define MICROPY_HW_PIN_RESERVED(i) mp_hal_is_pin_reserved(i)

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// -----------------------------------------------------
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
// This header may be included by other board headers as "boards/pico2_w.h"
// pico_cmake_set PICO_PLATFORM=rp2350
// pico_cmake_set PICO_CYW43_SUPPORTED = 1
#ifndef _BOARDS_PICO2_W_H
#define _BOARDS_PICO2_W_H
// For board detection
#define RASPBERRYPI_PICO2_W
// --- RP2350 VARIANT ---
//#define PICO_RP2350A 1
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
// --- LED ---
// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
// no PICO_DEFAULT_WS2812_PIN
// --- I2C ---
#ifndef PICO_DEFAULT_I2C
#define PICO_DEFAULT_I2C 0
#endif
#ifndef PICO_DEFAULT_I2C_SDA_PIN
#define PICO_DEFAULT_I2C_SDA_PIN 4
#endif
#ifndef PICO_DEFAULT_I2C_SCL_PIN
#define PICO_DEFAULT_I2C_SCL_PIN 5
#endif
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
#define PICO_DEFAULT_SPI 0
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
#define PICO_DEFAULT_SPI_SCK_PIN 18
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
#define PICO_DEFAULT_SPI_TX_PIN 19
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
#define PICO_DEFAULT_SPI_RX_PIN 16
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
#define PICO_DEFAULT_SPI_CSN_PIN 17
#endif
// --- FLASH ---
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
// note the SMSP mode pin is on WL_GPIO1
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
#ifndef CYW43_WL_GPIO_LED_PIN
#define CYW43_WL_GPIO_LED_PIN 0
#endif
// If CYW43_WL_GPIO_VBUS_PIN is defined then a CYW43 GPIO has to be used to read VBUS.
// This can be passed to cyw43_arch_gpio_get to determine if the device is battery powered.
// PICO_VBUS_PIN and CYW43_WL_GPIO_VBUS_PIN should not both be defined.
#ifndef CYW43_WL_GPIO_VBUS_PIN
#define CYW43_WL_GPIO_VBUS_PIN 2
#endif
// If CYW43_USES_VSYS_PIN is defined then CYW43 uses the VSYS GPIO (defined by PICO_VSYS_PIN) for other purposes.
// If this is the case, to use the VSYS GPIO it's necessary to ensure CYW43 is not using it.
// This can be achieved by wrapping the use of the VSYS GPIO in cyw43_thread_enter / cyw43_thread_exit.
#ifndef CYW43_USES_VSYS_PIN
#define CYW43_USES_VSYS_PIN 1
#endif
// The GPIO Pin used to monitor VSYS. Typically you would use this with ADC.
// There is an example in adc/read_vsys in pico-examples.
#ifndef PICO_VSYS_PIN
#define PICO_VSYS_PIN 29
#endif
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
// PICO_CONFIG: CYW43_PIN_WL_DYNAMIC, flag to indicate if cyw43 SPI pins can be changed at runtime, type=bool, default=false, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_PIN_WL_DYNAMIC
#define CYW43_PIN_WL_DYNAMIC 0
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_REG_ON, gpio pin to power up the cyw43 chip, type=int, default=23, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
#define CYW43_DEFAULT_PIN_WL_REG_ON 23u
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_OUT, gpio pin for spi data out to the cyw43 chip, type=int, default=24, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
#define CYW43_DEFAULT_PIN_WL_DATA_OUT 24u
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_DATA_IN, gpio pin for spi data in from the cyw43 chip, type=int, default=24, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
#define CYW43_DEFAULT_PIN_WL_DATA_IN 24u
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_HOST_WAKE, gpio (irq) pin for the irq line from the cyw43 chip, type=int, default=24, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 24u
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_CLOCK, gpio pin for the spi clock line to the cyw43 chip, type=int, default=29, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
#define CYW43_DEFAULT_PIN_WL_CLOCK 29u
#endif
// PICO_CONFIG: CYW43_DEFAULT_PIN_WL_CS, gpio pin for the spi chip select to the cyw43 chip, type=int, default=25, advanced=true, group=pico_cyw43_driver
#ifndef CYW43_DEFAULT_PIN_WL_CS
#define CYW43_DEFAULT_PIN_WL_CS 25u
#endif
#endif

View File

@ -0,0 +1,30 @@
GP0,GPIO0
GP1,GPIO1
GP2,GPIO2
GP3,GPIO3
GP4,GPIO4
GP5,GPIO5
GP6,GPIO6
GP7,GPIO7
GP8,GPIO8
GP9,GPIO9
GP10,GPIO10
GP11,GPIO11
GP12,GPIO12
GP13,GPIO13
GP14,GPIO14
GP15,GPIO15
GP16,GPIO16
GP17,GPIO17
GP18,GPIO18
GP19,GPIO19
GP20,GPIO20
GP21,GPIO21
GP22,GPIO22
GP25,GPIO25
GP26,GPIO26
GP27,GPIO27
GP28,GPIO28
WL_GPIO0,EXT_GPIO0
WL_GPIO1,EXT_GPIO1
WL_GPIO2,EXT_GPIO2
1 GP0 GPIO0
2 GP1 GPIO1
3 GP2 GPIO2
4 GP3 GPIO3
5 GP4 GPIO4
6 GP5 GPIO5
7 GP6 GPIO6
8 GP7 GPIO7
9 GP8 GPIO8
10 GP9 GPIO9
11 GP10 GPIO10
12 GP11 GPIO11
13 GP12 GPIO12
14 GP13 GPIO13
15 GP14 GPIO14
16 GP15 GPIO15
17 GP16 GPIO16
18 GP17 GPIO17
19 GP18 GPIO18
20 GP19 GPIO19
21 GP20 GPIO20
22 GP21 GPIO21
23 GP22 GPIO22
24 GP25 GPIO25
25 GP26 GPIO26
26 GP27 GPIO27
27 GP28 GPIO28
28 WL_GPIO0 EXT_GPIO0
29 WL_GPIO1 EXT_GPIO1
30 WL_GPIO2 EXT_GPIO2

View File

@ -6,3 +6,5 @@ require("aioble")
include("$(PORT_DIR)/boards/manifest.py") include("$(PORT_DIR)/boards/manifest.py")
include("../manifest_pico2.py") include("../manifest_pico2.py")
freeze("$(BOARD_DIR)/../../modules_py", "lte.py")

View File

@ -36,4 +36,4 @@ set(MICROPY_BLUETOOTH_BTSTACK ON)
# MICROPY_PY_BLUETOOTH_CYW43 = 1 # MICROPY_PY_BLUETOOTH_CYW43 = 1
set(MICROPY_PY_BLUETOOTH_CYW43 ON) set(MICROPY_PY_BLUETOOTH_CYW43 ON)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -0,0 +1,10 @@
require("bundle-networking")
# Bluetooth
require("aioble")
include("$(PORT_DIR)/boards/manifest.py")
include("../manifest_pico2.py")
freeze("$(BOARD_DIR)/../../modules_py", "lte.py")

View File

@ -35,4 +35,3 @@ set(MICROPY_BLUETOOTH_BTSTACK ON)
# MICROPY_PY_BLUETOOTH_CYW43 = 1 # MICROPY_PY_BLUETOOTH_CYW43 = 1
set(MICROPY_PY_BLUETOOTH_CYW43 ON) set(MICROPY_PY_BLUETOOTH_CYW43 ON)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -6,5 +6,3 @@ set(PICO_PLATFORM "rp2350")
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(MICROPY_C_HEAP_SIZE 4096) set(MICROPY_C_HEAP_SIZE 4096)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -0,0 +1,11 @@
# cmake file for Raspberry Pi Pico2
set(PICO_BOARD "pico2")
# To change the gpio count for QFN-80
# set(PICO_NUM_GPIOS 48)
if (PICO_CYW43_SUPPORTED)
include(enable_cyw43.cmake)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(PICO_PINS_CSV_NAME pins_cyw43.csv)
endif()

View File

@ -2,12 +2,6 @@
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico2" #define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico2"
#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - 1024 * 1024 * 2) #define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - 1024 * 1024 * 2)
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Pico2"
// Enable WiFi & PPP
#define MICROPY_PY_NETWORK (1)
#define MICROPY_PY_NETWORK_PPP_LWIP (1)
#if MICROPY_PY_NETWORK_CYW43 #if MICROPY_PY_NETWORK_CYW43
#include "enable_cyw43.h" #include "enable_cyw43.h"

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// -----------------------------------------------------
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// -----------------------------------------------------
// This header may be included by other board headers as "boards/pico2_w.h"
// pico_cmake_set PICO_PLATFORM=rp2350
// pico_cmake_set PICO_CYW43_SUPPORTED = 1
#ifndef _BOARDS_PICO2_W_H
#define _BOARDS_PICO2_W_H
// For board detection
#define RASPBERRYPI_PICO2_W
// --- RP2350 VARIANT ---
#define PICO_RP2350A 1
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
// --- LED ---
// no PICO_DEFAULT_LED_PIN - LED is on Wireless chip
// no PICO_DEFAULT_WS2812_PIN
// --- I2C ---
#ifndef PICO_DEFAULT_I2C
#define PICO_DEFAULT_I2C 0
#endif
#ifndef PICO_DEFAULT_I2C_SDA_PIN
#define PICO_DEFAULT_I2C_SDA_PIN 4
#endif
#ifndef PICO_DEFAULT_I2C_SCL_PIN
#define PICO_DEFAULT_I2C_SCL_PIN 5
#endif
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
#define PICO_DEFAULT_SPI 0
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
#define PICO_DEFAULT_SPI_SCK_PIN 18
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
#define PICO_DEFAULT_SPI_TX_PIN 19
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
#define PICO_DEFAULT_SPI_RX_PIN 16
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
#define PICO_DEFAULT_SPI_CSN_PIN 17
#endif
// --- FLASH ---
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (4 * 1024 * 1024)
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
#endif
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
// note the SMSP mode pin is on WL_GPIO1
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
#ifndef CYW43_WL_GPIO_LED_PIN
#define CYW43_WL_GPIO_LED_PIN 0
#endif
// If CYW43_WL_GPIO_VBUS_PIN is defined then a CYW43 GPIO has to be used to read VBUS.
// This can be passed to cyw43_arch_gpio_get to determine if the device is battery powered.
// PICO_VBUS_PIN and CYW43_WL_GPIO_VBUS_PIN should not both be defined.
#ifndef CYW43_WL_GPIO_VBUS_PIN
#define CYW43_WL_GPIO_VBUS_PIN 2
#endif
// If CYW43_USES_VSYS_PIN is defined then CYW43 uses the VSYS GPIO (defined by PICO_VSYS_PIN) for other purposes.
// If this is the case, to use the VSYS GPIO it's necessary to ensure CYW43 is not using it.
// This can be achieved by wrapping the use of the VSYS GPIO in cyw43_thread_enter / cyw43_thread_exit.
#ifndef CYW43_USES_VSYS_PIN
#define CYW43_USES_VSYS_PIN 1
#endif
// The GPIO Pin used to monitor VSYS. Typically you would use this with ADC.
// There is an example in adc/read_vsys in pico-examples.
#ifndef PICO_VSYS_PIN
#define PICO_VSYS_PIN 29
#endif
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
#endif

View File

@ -10,5 +10,3 @@ set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(MICROPY_C_HEAP_SIZE 4096) set(MICROPY_C_HEAP_SIZE 4096)
set(PICO_NUM_GPIOS 48) set(PICO_NUM_GPIOS 48)
include(${CMAKE_CURRENT_LIST_DIR}/../common.cmake)

View File

@ -0,0 +1,11 @@
# cmake file for Raspberry Pi Pico 2 W
set(PICO_BOARD "pico2_w")
# To change the gpio count for QFN-80
# set(PICO_NUM_GPIOS 48)
include(enable_cyw43.cmake)
# Board specific version of the frozen manifest
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

View File

@ -4,7 +4,4 @@
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Pico2W" #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Pico2W"
// Enable PPP
#define MICROPY_PY_NETWORK_PPP_LWIP (1)
#include "enable_cyw43.h" #include "enable_cyw43.h"

View File

@ -0,0 +1,9 @@
MODULES_PY = "../../../pimoroni-pico/micropython/modules_py"
# SD Card
require("sdcard")
freeze(MODULES_PY, "gfx_pack.py")
freeze(MODULES_PY, "pimoroni.py")
freeze(MODULES_PY, "boot.py")

View File

@ -0,0 +1,220 @@
from machine import UART, Pin
from network import PPP
from micropython import const
import time
DEFAULT_PIN_RST = 35
DEFAULT_PIN_NETLIGHT = 34
DEFAULT_PIN_RX = 33
DEFAULT_PIN_TX = 32
DEFAULT_UART_ID = 0
DEFAULT_UART_TIMEOUT = const(1)
DEFAULT_UART_TIMEOUT_CHAR = const(1)
DEFAULT_UART_RXBUF = const(1024)
DEFAULT_UART_STARTUP_BAUD = const(115200)
DEFAULT_UART_BAUD = const(460800)
class CellularError(Exception):
def __init__(self, message=None):
self.message = f"CellularError: {message}"
class LTE():
def __init__(self, apn, uart=None, reset_pin=None, netlight_pin=None, netlight_led=None, skip_reset=False):
self._apn = apn
self._reset = reset_pin or Pin(DEFAULT_PIN_RST, Pin.OUT)
self._uart = uart or UART(
DEFAULT_UART_ID,
tx=Pin(DEFAULT_PIN_TX, Pin.OUT),
rx=Pin(DEFAULT_PIN_RX, Pin.OUT))
# Set PPP timeouts and rxbuf
self._uart.init(
timeout=DEFAULT_UART_TIMEOUT,
timeout_char=DEFAULT_UART_TIMEOUT_CHAR,
rxbuf=DEFAULT_UART_RXBUF)
if not skip_reset:
self._reset.value(0)
time.sleep(1.0)
self._reset.value(1)
if netlight_led:
self._led = netlight_led
self._netlight = netlight_pin or Pin(DEFAULT_PIN_NETLIGHT, Pin.IN)
self._netlight.irq(self._netlight_irq)
def _netlight_irq(self, pin):
self._led.value(pin.value())
def ipconfig(self, *args, **kwargs):
if len(args):
return self._ppp.ipconfig(*args)
else:
return self._ppp.ipconfig(**kwargs)
def iccid(self):
try:
return self._send_at_command("AT+CICCID", 1)
except CellularError:
return None
def status(self):
lte_status = self._send_at_command("AT+CEREG?", 1)
gsm_status = self._send_at_command("AT+CGREG?", 1)
return lte_status, gsm_status
def signal_quality(self):
try:
response = self._send_at_command("AT+CSQ", 1)
quality = int(response.split(":")[1].split(",")[0])
db = -113 + (2 * quality) # conversion as per AT command set datasheet
return db
except CellularError:
pass
return None
def stop_ppp(self):
self._ppp.disconnect()
self._send_at_command(f"AT+IPR={DEFAULT_UART_STARTUP_BAUD}")
self._flush_uart()
def start_ppp(self, baudrate=DEFAULT_UART_BAUD, connect=True):
self._wait_ready(poll_time=1.0, timeout=30)
# Switch to a faster baudrate
self._send_at_command(f"AT+IPR={baudrate}")
self._flush_uart()
self._uart.init(
baudrate=baudrate,
timeout=DEFAULT_UART_TIMEOUT,
timeout_char=DEFAULT_UART_TIMEOUT_CHAR,
rxbuf=DEFAULT_UART_RXBUF)
self._wait_ready(poll_time=1.0)
# Connect!
if connect:
self.connect()
# This will just always time out!?
# try:
# self._send_at_command("ATD*99#", timeout=300)
# except CellularError as e:
# print(e)
# Force PPP to use modem's default settings...
self._flush_uart()
self._uart.write("ATD*99#\r")
self._uart.flush()
self._ppp = PPP(self._uart)
self._ppp.connect()
while self._ppp.status() != 4:
time.sleep(1.0)
return self._ppp.ifconfig()
def connect(self, timeout=60):
print(" - setting up cellular uart")
# connect to and flush the uart
# consume any unsolicited messages first, we don't need those
self._flush_uart()
print(" - waiting for cellular module to be ready")
# wait for the cellular module to respond to AT commands
self._wait_ready()
self._send_at_command("ATE0") # disable local echo
self._send_at_command(f"AT+CGDCONT=1,\"IP\",\"{self._apn}\"") # set apn and activate pdp context
# wait for roaming lte connection to be established
giveup = time.time() + timeout
status = None
while status != "+CEREG: 0,5" and status != "+CEREG: 0,1":
status = self._send_at_command("AT+CEREG?", 1)
time.sleep(0.25)
if time.time() > giveup:
raise CellularError("timed out getting network registration")
# disable server and client certification validation
self._send_at_command("AT+CSSLCFG=\"authmode\",0,0")
self._send_at_command("AT+CSSLCFG=\"enableSNI\",0,1")
print(f" - SIM ICCID is {self.iccid()}")
def _wait_ready(self, poll_time=0.25, timeout=10):
giveup = time.time() + timeout
while time.time() <= giveup:
try:
# if __send_at_command doesn't throw an exception then we're good!
self._send_at_command("AT")
return
except CellularError as e:
print(e)
time.sleep(poll_time)
raise CellularError("timed out waiting for AT response")
def _flush_uart(self):
self._uart.flush()
time.sleep(0.25)
while self._uart.any():
self._uart.read(self._uart.any())
time.sleep(0.25)
def _send_at_command(self, command, result_lines=0, timeout=5.0):
# consume any unsolicited messages first, we don't need those
self._flush_uart()
self._uart.write(command + "\r")
self._uart.flush()
status, data = self._read_result(result_lines, timeout=timeout)
print(" -", command, status, data)
if status not in ["OK", "DOWNLOAD"]:
raise CellularError(f"non 'OK' or 'DOWNLOAD' result for command {command}")
if result_lines == 1:
return data[0]
if result_lines > 1:
return data
return None
def _read_result(self, result_lines, timeout=1.0):
status = None
result = []
start = time.ticks_ms()
timeout *= 1000
while len(result) < result_lines or status is None:
if (time.ticks_ms() - start) > timeout:
raise CellularError("cellular module timed out")
line = self._uart.readline()
if line:
line = line.strip()
if line in [b"OK", b"ERROR", b"DOWNLOAD"]:
status = line.decode("ascii")
elif line != b"":
result.append(str(line, "ascii"))
start = time.ticks_ms()
return status, result
def send_text_message(self, recipient, body, timeout=5.0):
self._uart.write("AT+CMGS=\"")
self._uart.write(recipient.encode("ascii"))
self._uart.write(b"\"\r")
time.sleep(0.5)
self._uart.write(body.encode("ascii"))
self._uart.write(b"\x1a\r")
self._uart.flush()
status, _ = self._read_result(1, timeout=timeout)
return status == "OK"