Compare commits
@@ -6,11 +6,6 @@ name: Arduino-Pico CI
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
# Consistent style, spelling
|
||||
@@ -75,6 +70,37 @@ jobs:
|
||||
cd ..
|
||||
bash ./tests/build.sh
|
||||
|
||||
# Build all rp2350 examples on linux (core and Arduino IDE)
|
||||
build-rp2350-linux:
|
||||
name: Build RP2350 ${{ matrix.chunk }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
chunk: [0, 1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Linux toolchain
|
||||
id: cache-linux
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketches
|
||||
env:
|
||||
BUILD_PARITY: custom
|
||||
mod: 6
|
||||
rem: ${{ matrix.chunk }}
|
||||
run: |
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build-rp2350.sh
|
||||
|
||||
# Build TinyUSB examples, requires custom build command line
|
||||
build-tinyusb:
|
||||
name: Build TinyUSB Examples
|
||||
@@ -161,11 +187,16 @@ jobs:
|
||||
mod: 500
|
||||
rem: 1
|
||||
run: |
|
||||
brew update
|
||||
brew install bash
|
||||
/usr/bin/env bash --version
|
||||
uname -a
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build.sh
|
||||
/usr/bin/env bash ./tests/build.sh
|
||||
./system/picotool/picotool version
|
||||
otool -L ./system/picotool/picotool
|
||||
|
||||
# Build a few examples with PlatformIO to test if integration works
|
||||
build-platformio:
|
||||
@@ -204,8 +235,9 @@ jobs:
|
||||
pip install --upgrade platformio
|
||||
pio pkg install --global --platform https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
pio pkg install --global --tool symlink://.
|
||||
cp -f /home/runner/work/arduino-pico/arduino-pico/tools/json/*.json /home/runner/.platformio/platforms/raspberrypi/boards/.
|
||||
- name: Build Multicore Example
|
||||
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Multicore/Multicore.ino
|
||||
run: pio ci -v --board=rpipico --board=rpipico2 --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Multicore/Multicore.ino
|
||||
- name: Build Fade Example
|
||||
run: pio ci --board=rpipico --board=adafruit_feather -O "platform_packages=framework-arduinopico@symlink:///home/runner/work/arduino-pico/arduino-pico" libraries/rp2040/examples/Fade/Fade.ino
|
||||
- name: Build TinyUSB Example
|
||||
|
||||
@@ -33,7 +33,6 @@ jobs:
|
||||
# pip install --upgrade platformio
|
||||
- name: Deploy updated JSON
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
BUILD_TYPE: package
|
||||
CI_GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
|
||||
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
|
||||
|
||||
@@ -24,7 +24,6 @@ jobs:
|
||||
python-version: '3.x'
|
||||
- name: Build package JSON
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
BUILD_TYPE: package
|
||||
CI_GITHUB_API_KEY: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
|
||||
@@ -43,3 +43,9 @@
|
||||
[submodule "libraries/AsyncUDP"]
|
||||
path = libraries/AsyncUDP
|
||||
url = https://github.com/earlephilhower/AsyncUDP.git
|
||||
[submodule "cores/rp2040/tlsf"]
|
||||
path = lib/tlsf
|
||||
url = https://github.com/earlephilhower/tlsf.git
|
||||
[submodule "libraries/ESPHost"]
|
||||
path = libraries/ESPHost
|
||||
url = https://github.com/Networking-for-Arduino/ESPHost.git
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Read the Docs configuration file for Sphinx projects
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the OS, Python version and other tools you might need
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.12"
|
||||
jobs:
|
||||
post_create_environment:
|
||||
- python -m pip install sphinx_rtd_theme
|
||||
# You can also specify other tool versions:
|
||||
# nodejs: "20"
|
||||
# rust: "1.70"
|
||||
# golang: "1.20"
|
||||
|
||||
|
||||
# Build documentation in the "docs/" directory with Sphinx
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
|
||||
# builder: "dirhtml"
|
||||
# Fail on all warnings to avoid broken references
|
||||
# fail_on_warning: true
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
# formats:
|
||||
# - pdf
|
||||
# - epub
|
||||
|
||||
# Optional but recommended, declare the Python requirements required
|
||||
# to build your documentation
|
||||
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
# python:
|
||||
# install:
|
||||
# - requirements: docs/requirements.txt
|
||||
@@ -2,9 +2,9 @@
|
||||
[](https://github.com/earlephilhower/arduino-pico/releases)
|
||||
[](https://gitter.im/arduino-pico/community)
|
||||
|
||||
Raspberry Pi Pico Arduino core, for all RP2040 boards
|
||||
Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
|
||||
|
||||
This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosystem. It uses the bare Raspberry Pi Pico SDK and a custom GCC 12.3/Newlib 4.0 toolchain.
|
||||
This is a port of Arduino to the RP2040 (Raspberry Pi Pico processor) and RP2350 (Raspberry Pi Pico 2 processor). It uses the bare Raspberry Pi Pico SDK and a custom GCC 12.3/Newlib 4.0 toolchain.
|
||||
|
||||
# Documentation
|
||||
See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for more detailed usage information.
|
||||
@@ -15,6 +15,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
# Supported Boards
|
||||
* Raspberry Pi Pico
|
||||
* Raspberry Pi Pico W
|
||||
* Raspberry Pi Pico 2
|
||||
* 0xCB Helios
|
||||
* Adafruit Feather RP2040
|
||||
* Adafruit Feather RP2040 SCORPIO
|
||||
@@ -34,10 +35,13 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Breadstick Raspberry
|
||||
* BridgeTek IDM2040-7A
|
||||
* BridgeTek IDM2040-43A
|
||||
* Cytron IRIV IO Controller
|
||||
* Cytron Maker Pi RP2040
|
||||
* Cytron Maker Nano RP2040
|
||||
* Cytron Maker Uno RP2040
|
||||
* DatanoiseTV PicoADK+
|
||||
* Cytron Motion 2350 Pro
|
||||
* Datanoise PicoADK v1
|
||||
* Datanoise PicoADK v2 (RP2350)
|
||||
* Degz Suibo RP2040
|
||||
* DeRuiLab FlyBoard2040 Core
|
||||
* DFRobot Beetle RP2040
|
||||
@@ -54,6 +58,8 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Invector Labs Challenger RP2040 SubGHz
|
||||
* Invector Labs Challenger RP2040 SD/RTC
|
||||
* Invector Labs Challenger RP2040 UWB
|
||||
* Invector Labs Challenger RP2350 BConnect
|
||||
* Invector Labs Challenger RP2350 WiFi/BLE
|
||||
* Invector Labs RPICO32
|
||||
* Melopero Cookie RP2040
|
||||
* Melopero Shake RP2040
|
||||
@@ -63,8 +69,10 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Newsan Archi
|
||||
* nullbits Bit-C PRO
|
||||
* Pimoroni PGA2040
|
||||
* Pimoroni Pico Plus 2
|
||||
* Pimoroni Plasma2040
|
||||
* Pimoroni Tiny2040
|
||||
* Pimoroni Tiny2350
|
||||
* Pintronix PinMax
|
||||
* RAKwireless RAK11300
|
||||
* Redscorp RP2040-Eins
|
||||
@@ -74,8 +82,11 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Seeed XIAO RP2040
|
||||
* Silicognition RP2040-Shim
|
||||
* Solder Party RP2040 Stamp
|
||||
* Solder Party RP2350 Stamp
|
||||
* Solder Party RP2350 Stamp XL
|
||||
* SparkFun MicroMod RP2040
|
||||
* SparkFun ProMicro RP2040
|
||||
* SparkFun ProMicro RP2350
|
||||
* SparkFun Thing Plus RP2040
|
||||
* uPesy RP2040 DevKit
|
||||
* VCC-GND YD-RP2040
|
||||
@@ -90,7 +101,8 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* WIZnet W5100S-EVB-Pico
|
||||
* WIZnet W5500-EVB-Pico
|
||||
* WIZnet WizFi360-EVB-Pico
|
||||
* Generic (configurable flash, I/O pins)
|
||||
* Generic RP2040 (configurable flash, I/O pins)
|
||||
* Generic RP2350 (configurable flash, I/O pins)
|
||||
|
||||
# Features
|
||||
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
|
||||
@@ -98,7 +110,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* Bluetooth Classic and BLE HID master mode (connect to BT keyboard, mouse, or joystick)
|
||||
* Generic Arduino USB Serial, Keyboard, Joystick, and Mouse emulation
|
||||
* WiFi (Pico W, ESP32-based ESPHost, Atmel WINC1500)
|
||||
* Ethernet (Wired W5500, W5100, ENC28J60)
|
||||
* Ethernet (Wired WizNet W6100, WizNet W5500, WizNet W5100, ENC28J60)
|
||||
* HTTP client and server (WebServer)
|
||||
* SSL/TLS/HTTPS
|
||||
* Over-the-Air (OTA) upgrades
|
||||
@@ -113,6 +125,7 @@ Read the [Contributing Guide](https://github.com/earlephilhower/arduino-pico/blo
|
||||
* USB drive mode for data loggers (SingleFileDrive, FatFSUSB)
|
||||
* Peripherals: SPI master/slave, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio input/output, Servo
|
||||
* printf (i.e. debug) output over USB serial
|
||||
* Transparent use of PSRAM globals and heap (RP2350 only)
|
||||
|
||||
The RP2040 PIO state machines (SMs) are used to generate jitter-free:
|
||||
* Servos
|
||||
@@ -185,11 +198,6 @@ cd ../tools
|
||||
python3 ./get.py
|
||||
`````
|
||||
|
||||
# Installing both Arduino and CMake
|
||||
Tom's Hardware presented a very nice writeup on installing `arduino-pico` on both Windows and Linux, available at https://www.tomshardware.com/how-to/program-raspberry-pi-pico-with-arduino-ide
|
||||
|
||||
If you follow Les' step-by-step you will also have a fully functional `CMake`-based environment to build Pico apps on if you outgrow the Arduino ecosystem.
|
||||
|
||||
# Uploading Sketches
|
||||
To upload your first sketch, you will need to hold the BOOTSEL button down while plugging in the Pico to your computer.
|
||||
Then hit the upload button and the sketch should be transferred and start to run.
|
||||
@@ -210,16 +218,18 @@ To install, follow the directions in
|
||||
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/blob/master/README.md
|
||||
|
||||
For detailed usage information, please check the ESP8266 repo documentation (ignore SPIFFS related notes) available at
|
||||
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
|
||||
* https://arduino-pico.readthedocs.io/en/latest/fs.html
|
||||
|
||||
# Uploading Sketches with Picoprobe
|
||||
# Uploading Sketches with Picoprobe/Debugprobe
|
||||
If you have built a Raspberry Pi Picoprobe, you can use OpenOCD to handle your sketch uploads and for debugging with GDB.
|
||||
|
||||
Under Windows a local admin user should be able to access the Picoprobe port automatically, but under Linux `udev` must be told about the device and to allow normal users access.
|
||||
|
||||
To set up user-level access to Picoprobes on Ubuntu (and other OSes which use `udev`):
|
||||
````
|
||||
echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="660", GROUP-"plugdev"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE="660", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000f", MODE="660", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
sudo udevadm control --reload
|
||||
sudo udevadm trigger -w -s usb
|
||||
````
|
||||
@@ -230,28 +240,8 @@ If for some reason the device file does not appear, manually unplug and re-plug
|
||||
|
||||
Once Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.
|
||||
|
||||
# Uploading Sketches with pico-debug
|
||||
[pico-debug](https://github.com/majbthrd/pico-debug/) differs from Picoprobe in that pico-debug is a virtual debug pod that runs side-by-side on the same RP2040 that you run your code on; so, you only need one RP2040 board instead of two. pico-debug also differs from Picoprobe in that pico-debug is standards-based; it uses the CMSIS-DAP protocol, which means even software not specially written for the Raspberry Pi Pico can support it. pico-debug uses OpenOCD to handle your sketch uploads, and debugging can be accomplished with CMSIS-DAP capable debuggers including GDB.
|
||||
|
||||
Under Windows and macOS, any user should be able to access pico-debug automatically, but under Linux `udev` must be told about the device and to allow normal users access.
|
||||
|
||||
To set up group-level access to all CMSIS-DAP adapters on Ubuntu (and other OSes which use `udev`):
|
||||
````
|
||||
echo 'ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-CMSIS-DAP.rules
|
||||
sudo udevadm control --reload
|
||||
sudo udevadm trigger -w -s usb
|
||||
````
|
||||
|
||||
The first line creates a device file in `/dev` that matches all CMSIS-DAP adapters, and it enables read+write permissions for members of the `plugdev` group. The second line causes `udev` to load this new rule. The third line requests the kernel generate "device change" events that will cause our new `udev` rule to run.
|
||||
|
||||
If for some reason the device file does not appear, manually unplug and re-plug the USB connection and check again. The output from `dmesg` can reveal useful diagnostics if the device file remains absent.
|
||||
|
||||
Once CMSIS-DAP permissions are set up properly, then select the board "Raspberry Pi Pico (pico-debug)" in the Tools menu.
|
||||
|
||||
When first connecting the USB port to your PC, you must copy [pico-debug-gimmecache.uf2](https://github.com/majbthrd/pico-debug/releases/) to the Pi Pico to load pico-debug into RAM; after this, upload as normal.
|
||||
|
||||
# Debugging with Picoprobe/pico-debug, OpenOCD, and GDB
|
||||
The installed tools include a version of OpenOCD (in the pqt-openocd directory) and GDB (in the pqt-gcc directory). These may be used to run GDB in an interactive window as documented in the Pico Getting Started manuals from the Raspberry Pi Foundation. For [pico-debug](https://github.com/majbthrd/pico-debug/), replace the raspberrypi-swd and picoprobe example OpenOCD arguments of "-f interface/raspberrypi-swd.cfg -f target/rp2040.cfg" or "-f interface/picoprobe.cfg -f target/rp2040.cfg" respectively in the Pico Getting Started manual with "-f board/pico-debug.cfg".
|
||||
# Debugging with Picoprobe, OpenOCD, and GDB
|
||||
The installed tools include a version of OpenOCD (in the pqt-openocd directory) and GDB (in the pqt-gcc directory). These may be used to run GDB in an interactive window as documented in the Pico Getting Started manuals from the Raspberry Pi Foundation. Use the command line `./system/openocd/bin/openocd -f ./lib/rp2040/picoprobe_cmsis_dap.tcl` or `./system/openocd/bin/openocd -f ./lib/rp2350/picoprobe_cmsis_dap.tcl` from the `git` installation directory.
|
||||
|
||||
# Licensing and Credits
|
||||
* The [Arduino IDE and ArduinoCore-API](https://arduino.cc) are developed and maintained by the Arduino team. The IDE is licensed under GPL.
|
||||
@@ -271,7 +261,8 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
|
||||
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others.
|
||||
* [Xoshiro-cpp](https://github.com/Reputeless/Xoshiro-cpp) is copyright (c) 2020 Ryo Suzuki and distributed under the MIT license.
|
||||
* [FatFS low-level filesystem](http://elm-chan.org/fsw/ff/) code is Copyright (C) 2024, ChaN, all rights reserved.
|
||||
|
||||
* [TLSF memory manager for PSRAM from Espressif fork](https://github.com/espressif/tlsf) of [original](https://github.com/mattconte/tlsf) by Matthew Conte is copyright Matthew Conte and licensed under the MIT license.
|
||||
* [ESPHost library](https://github.com/Networking-for-Arduino/ESPHost) is LGPL licensed by its maintainers.
|
||||
|
||||
-Earle F. Philhower, III
|
||||
earlephilhower@yahoo.com
|
||||
|
||||
+5402
-1601
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
// Padded and checksummed version of: boot2_generic_03h.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.global __boot2_entry_point
|
||||
__boot2_entry_point:
|
||||
.byte 0x00, 0xb5, 0x05, 0x4b, 0x05, 0x48, 0xd8, 0x60, 0x4f, 0xf0, 0x03, 0x00, 0x58, 0x61, 0x4f, 0xf4
|
||||
.byte 0x80, 0x50, 0x18, 0x61, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x40, 0x02, 0x01, 0x00, 0x40
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
@@ -0,0 +1,25 @@
|
||||
// Padded and checksummed version of: boot2_generic_03h.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.global __boot2_entry_point
|
||||
__boot2_entry_point:
|
||||
.byte 0x00, 0xb5, 0x05, 0x4b, 0x05, 0x48, 0xd8, 0x60, 0x4f, 0xf0, 0x03, 0x00, 0x58, 0x61, 0x4f, 0xf4
|
||||
.byte 0x80, 0x50, 0x18, 0x61, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x40, 0x04, 0x01, 0x00, 0x40
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
@@ -0,0 +1,25 @@
|
||||
// Padded and checksummed version of: boot2_w25q080.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.global __boot2_entry_point
|
||||
__boot2_entry_point:
|
||||
.byte 0x00, 0xb5, 0x24, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x13, 0xf5, 0x40, 0x53, 0x02, 0x20, 0x98, 0x60
|
||||
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x13, 0xf5, 0x0d, 0x23, 0x1f, 0x49, 0x19, 0x60, 0x18, 0x68
|
||||
.byte 0x10, 0xf0, 0x02, 0x0f, 0xfb, 0xd1, 0x35, 0x20, 0x00, 0xf0, 0x2c, 0xf8, 0x02, 0x28, 0x14, 0xd0
|
||||
.byte 0x06, 0x20, 0x58, 0x60, 0x00, 0xf0, 0x22, 0xf8, 0x98, 0x68, 0x01, 0x20, 0x58, 0x60, 0x00, 0x20
|
||||
.byte 0x58, 0x60, 0x02, 0x20, 0x58, 0x60, 0x00, 0xf0, 0x19, 0xf8, 0x98, 0x68, 0x98, 0x68, 0x98, 0x68
|
||||
.byte 0x05, 0x20, 0x00, 0xf0, 0x17, 0xf8, 0x40, 0x08, 0xfa, 0xd2, 0x31, 0xf0, 0x01, 0x01, 0x19, 0x60
|
||||
.byte 0x0e, 0x48, 0xd8, 0x60, 0x4a, 0xf2, 0xeb, 0x00, 0x58, 0x61, 0x0d, 0x48, 0x18, 0x61, 0x4f, 0xf0
|
||||
.byte 0xa0, 0x51, 0x09, 0x78, 0x20, 0xf4, 0x80, 0x50, 0x18, 0x61, 0x00, 0xbd, 0x18, 0x68, 0x80, 0x08
|
||||
.byte 0xfc, 0xd2, 0x70, 0x47, 0x00, 0xb5, 0x58, 0x60, 0x58, 0x60, 0xff, 0xf7, 0xf7, 0xff, 0x98, 0x68
|
||||
.byte 0x98, 0x68, 0x00, 0xbd, 0x00, 0x00, 0x04, 0x40, 0x41, 0x00, 0x80, 0x07, 0x02, 0x02, 0x00, 0x40
|
||||
.byte 0xa8, 0x92, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
@@ -0,0 +1,25 @@
|
||||
// Padded and checksummed version of: boot2_w25q080.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.global __boot2_entry_point
|
||||
__boot2_entry_point:
|
||||
.byte 0x00, 0xb5, 0x24, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x13, 0xf5, 0x40, 0x53, 0x02, 0x20, 0x98, 0x60
|
||||
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x13, 0xf5, 0x0d, 0x23, 0x1f, 0x49, 0x19, 0x60, 0x18, 0x68
|
||||
.byte 0x10, 0xf0, 0x02, 0x0f, 0xfb, 0xd1, 0x35, 0x20, 0x00, 0xf0, 0x2c, 0xf8, 0x02, 0x28, 0x14, 0xd0
|
||||
.byte 0x06, 0x20, 0x58, 0x60, 0x00, 0xf0, 0x22, 0xf8, 0x98, 0x68, 0x01, 0x20, 0x58, 0x60, 0x00, 0x20
|
||||
.byte 0x58, 0x60, 0x02, 0x20, 0x58, 0x60, 0x00, 0xf0, 0x19, 0xf8, 0x98, 0x68, 0x98, 0x68, 0x98, 0x68
|
||||
.byte 0x05, 0x20, 0x00, 0xf0, 0x17, 0xf8, 0x40, 0x08, 0xfa, 0xd2, 0x31, 0xf0, 0x01, 0x01, 0x19, 0x60
|
||||
.byte 0x0e, 0x48, 0xd8, 0x60, 0x4a, 0xf2, 0xeb, 0x00, 0x58, 0x61, 0x0d, 0x48, 0x18, 0x61, 0x4f, 0xf0
|
||||
.byte 0xa0, 0x51, 0x09, 0x78, 0x20, 0xf4, 0x80, 0x50, 0x18, 0x61, 0x00, 0xbd, 0x18, 0x68, 0x80, 0x08
|
||||
.byte 0xfc, 0xd2, 0x70, 0x47, 0x00, 0xb5, 0x58, 0x60, 0x58, 0x60, 0xff, 0xf7, 0xf7, 0xff, 0x98, 0x68
|
||||
.byte 0x98, 0x68, 0x00, 0xbd, 0x00, 0x00, 0x04, 0x40, 0x41, 0x00, 0x80, 0x07, 0x04, 0x02, 0x00, 0x40
|
||||
.byte 0xa8, 0x92, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
+21
-3
@@ -30,7 +30,6 @@
|
||||
#include <pins_arduino.h>
|
||||
#include <hardware/gpio.h> // Required for the port*Register macros
|
||||
#include "debug_internal.h"
|
||||
#include <RP2040.h> // CMSIS
|
||||
|
||||
// Try and make the best of the old Arduino abs() macro. When in C++, use
|
||||
// the sane std::abs() call, but for C code use their macro since stdlib abs()
|
||||
@@ -59,6 +58,15 @@ extern "C" {
|
||||
void interrupts();
|
||||
void noInterrupts();
|
||||
|
||||
// Only implemented on some RP2350 boards, not the OG Pico 2
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
void *pmalloc(size_t size);
|
||||
void *pcalloc(size_t count, size_t size);
|
||||
#else
|
||||
[[deprecated("This chip does not have PSRAM, pmalloc will always fail")]] void *pmalloc(size_t size);
|
||||
[[deprecated("This chip does not have PSRAM, pcalloc will always fail")]] void *pcalloc(size_t count, size_t size);
|
||||
#endif
|
||||
|
||||
// AVR compatibility macros...naughty and accesses the HW directly
|
||||
#define digitalPinToPort(pin) (0)
|
||||
#define digitalPinToBitMask(pin) (1UL << (pin))
|
||||
@@ -125,8 +133,8 @@ extern const String emptyString;
|
||||
// Template which will evaluate at *compile time* to a single 32b number
|
||||
// with the specified bits set.
|
||||
template <size_t N>
|
||||
constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
return i < N ? (1L << a[i]) | __bitset(a, i + 1) : 0;
|
||||
constexpr uint64_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
return i < N ? (1LL << a[i]) | __bitset(a, i + 1) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -139,4 +147,14 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
|
||||
#undef stdio_usb_init
|
||||
#define stdio_usb_init(...) static_assert(0, "stdio_usb_init is not supported or needed. Either use Serial.printf() or set the debug port in the IDE to Serial/1/2 and use printf(). See https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1540354673 and https://github.com/earlephilhower/arduino-pico/issues/1433#issuecomment-1546783109")
|
||||
|
||||
// PSRAM decorator
|
||||
#define PSRAM __attribute__((section("\".psram\"")))
|
||||
|
||||
// General GPIO/ADC layout info
|
||||
#ifdef PICO_RP2350B
|
||||
#define __GPIOCNT 48
|
||||
#define __FIRSTANALOGGPIO 40
|
||||
#else
|
||||
#define __GPIOCNT 30
|
||||
#define __FIRSTANALOGGPIO 26
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,9 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
|
||||
|
||||
// Must disable interrupts, as interrupt handlers may be in flash, and we
|
||||
// are about to temporarily disable flash access!
|
||||
noInterrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
noInterrupts();
|
||||
}
|
||||
rp2040.idleOtherCore();
|
||||
|
||||
// Set chip select to Hi-Z
|
||||
@@ -39,7 +41,12 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
|
||||
|
||||
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
|
||||
// Note the button pulls the pin *low* when pressed.
|
||||
bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
|
||||
#if PICO_RP2040
|
||||
#define CS_BIT (1u << 1)
|
||||
#else
|
||||
#define CS_BIT SIO_GPIO_HI_IN_QSPI_CSN_BITS
|
||||
#endif
|
||||
bool button_state = !(sio_hw->gpio_hi_in & CS_BIT);
|
||||
|
||||
// Need to restore the state of chip select, else we are going to have a
|
||||
// bad time when we return to code in flash!
|
||||
@@ -48,7 +55,9 @@ static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
|
||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
interrupts();
|
||||
}
|
||||
|
||||
return button_state;
|
||||
}
|
||||
|
||||
+26
-7
@@ -225,6 +225,21 @@ void File::setTimeCallback(time_t (*cb)(void)) {
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
bool File::stat(FSStat *st) {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
size_t pos = position();
|
||||
seek(0, SeekEnd);
|
||||
st->size = position() - pos;
|
||||
seek(pos, SeekSet);
|
||||
st->blocksize = 0; // Not set here
|
||||
st->ctime = getCreationTime();
|
||||
st->atime = getLastWrite();
|
||||
st->isDir = isDirectory();
|
||||
return true;
|
||||
}
|
||||
|
||||
File Dir::openFile(const char* mode) {
|
||||
if (!_impl) {
|
||||
return File();
|
||||
@@ -366,13 +381,6 @@ bool FS::info(FSInfo& info) {
|
||||
return _impl->info(info);
|
||||
}
|
||||
|
||||
bool FS::info64(FSInfo64& info) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->info64(info);
|
||||
}
|
||||
|
||||
File FS::open(const String& path, const char* mode) {
|
||||
return open(path.c_str(), mode);
|
||||
}
|
||||
@@ -462,6 +470,17 @@ bool FS::rename(const String& pathFrom, const String& pathTo) {
|
||||
return rename(pathFrom.c_str(), pathTo.c_str());
|
||||
}
|
||||
|
||||
bool FS::stat(const char *path, FSStat *st) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->stat(path, st);
|
||||
}
|
||||
|
||||
bool FS::stat(const String& path, FSStat *st) {
|
||||
return stat(path.c_str(), st);
|
||||
}
|
||||
|
||||
time_t FS::getCreationTime() {
|
||||
if (!_impl) {
|
||||
return 0;
|
||||
|
||||
+14
-13
@@ -48,6 +48,14 @@ enum SeekMode {
|
||||
SeekEnd = 2
|
||||
};
|
||||
|
||||
struct FSStat {
|
||||
size_t size;
|
||||
size_t blocksize;
|
||||
time_t ctime;
|
||||
time_t atime;
|
||||
bool isDir;
|
||||
};
|
||||
|
||||
class File : public Stream {
|
||||
public:
|
||||
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) {
|
||||
@@ -119,6 +127,8 @@ public:
|
||||
time_t getCreationTime();
|
||||
void setTimeCallback(time_t (*cb)(void));
|
||||
|
||||
bool stat(FSStat *st);
|
||||
|
||||
protected:
|
||||
FileImplPtr _p;
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
@@ -152,18 +162,8 @@ protected:
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
};
|
||||
|
||||
// Backwards compatible, <4GB filesystem usage
|
||||
struct FSInfo {
|
||||
size_t totalBytes;
|
||||
size_t usedBytes;
|
||||
size_t blockSize;
|
||||
size_t pageSize;
|
||||
size_t maxOpenFiles;
|
||||
size_t maxPathLength;
|
||||
};
|
||||
|
||||
// Support > 4GB filesystems (SD, etc.)
|
||||
struct FSInfo64 {
|
||||
struct FSInfo {
|
||||
uint64_t totalBytes;
|
||||
uint64_t usedBytes;
|
||||
size_t blockSize;
|
||||
@@ -172,7 +172,6 @@ struct FSInfo64 {
|
||||
size_t maxPathLength;
|
||||
};
|
||||
|
||||
|
||||
class FSConfig {
|
||||
public:
|
||||
static constexpr uint32_t FSId = 0x00000000;
|
||||
@@ -201,7 +200,6 @@ public:
|
||||
|
||||
bool format();
|
||||
bool info(FSInfo& info);
|
||||
bool info64(FSInfo64& info);
|
||||
|
||||
File open(const char* path, const char* mode);
|
||||
File open(const String& path, const char* mode);
|
||||
@@ -224,6 +222,9 @@ public:
|
||||
bool rmdir(const char* path);
|
||||
bool rmdir(const String& path);
|
||||
|
||||
bool stat(const char *path, FSStat *st);
|
||||
bool stat(const String& path, FSStat *st);
|
||||
|
||||
// Low-level FS routines, not needed by most applications
|
||||
bool gc();
|
||||
bool check();
|
||||
|
||||
@@ -119,7 +119,6 @@ public:
|
||||
virtual void end() = 0;
|
||||
virtual bool format() = 0;
|
||||
virtual bool info(FSInfo& info) = 0;
|
||||
virtual bool info64(FSInfo64& info) = 0;
|
||||
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0;
|
||||
virtual bool exists(const char* path) = 0;
|
||||
virtual DirImplPtr openDir(const char* path) = 0;
|
||||
@@ -127,6 +126,7 @@ public:
|
||||
virtual bool remove(const char* path) = 0;
|
||||
virtual bool mkdir(const char* path) = 0;
|
||||
virtual bool rmdir(const char* path) = 0;
|
||||
virtual bool stat(const char *path, FSStat *st) = 0;
|
||||
virtual bool gc() {
|
||||
return true; // May not be implemented in all file systems.
|
||||
}
|
||||
|
||||
+75
-18
@@ -21,11 +21,21 @@
|
||||
#include <Arduino.h>
|
||||
#include "PIOProgram.h"
|
||||
#include <map>
|
||||
#include <hardware/claim.h>
|
||||
|
||||
static std::map<const pio_program_t *, int> __pioMap[2];
|
||||
#if defined(PICO_RP2350)
|
||||
#define PIOS pio0, pio1, pio2
|
||||
#define PIOCNT 3
|
||||
#elif defined(PICO_RP2040)
|
||||
#define PIOS pio0, pio1
|
||||
#define PIOCNT 2
|
||||
#endif
|
||||
|
||||
static std::map<const pio_program_t *, int> __pioMap[PIOCNT];
|
||||
static bool __pioAllocated[PIOCNT];
|
||||
static bool __pioHighGPIO[PIOCNT];
|
||||
auto_init_mutex(_pioMutex);
|
||||
|
||||
|
||||
PIOProgram::PIOProgram(const pio_program_t *pgm) {
|
||||
_pgm = pgm;
|
||||
_pio = nullptr;
|
||||
@@ -40,16 +50,30 @@ PIOProgram::~PIOProgram() {
|
||||
}
|
||||
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool PIOProgram::prepare(PIO *pio, int *sm, int *offset) {
|
||||
bool PIOProgram::prepare(PIO *pio, int *sm, int *offset, int start, int cnt) {
|
||||
CoreMutex m(&_pioMutex);
|
||||
PIO pi[2] = { pio0, pio1 };
|
||||
PIO pi[PIOCNT] = { PIOS };
|
||||
|
||||
#if 0
|
||||
uint usm;
|
||||
uint uoff;
|
||||
auto ret = pio_claim_free_sm_and_add_program_for_gpio_range(_pgm, pio, &usm, &uoff, start, cnt, true);
|
||||
*sm = usm;
|
||||
*offset = uoff;
|
||||
DEBUGV("clain %d\n", ret);
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
bool needsHigh = (start + cnt) >= 32;
|
||||
DEBUGV("PIOProgram %p: Searching for high=%d, pins %d-%d\n", _pgm, needsHigh ? 1 : 0, start, start + cnt - 1);
|
||||
|
||||
// If it's already loaded into PIO IRAM, try and allocate in that specific PIO
|
||||
for (int o = 0; o < 2; o++) {
|
||||
for (int o = 0; o < PIOCNT; o++) {
|
||||
auto p = __pioMap[o].find(_pgm);
|
||||
if (p != __pioMap[o].end()) {
|
||||
if ((p != __pioMap[o].end()) && (__pioHighGPIO[o] == needsHigh)) {
|
||||
int idx = pio_claim_unused_sm(pi[o], false);
|
||||
if (idx >= 0) {
|
||||
DEBUGV("PIOProgram %p: Reusing IMEM ON PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
@@ -61,22 +85,55 @@ bool PIOProgram::prepare(PIO *pio, int *sm, int *offset) {
|
||||
}
|
||||
|
||||
// Not in any PIO IRAM, so try and add
|
||||
for (int o = 0; o < 2; o++) {
|
||||
if (pio_can_add_program(pi[o], _pgm)) {
|
||||
int idx = pio_claim_unused_sm(pi[o], false);
|
||||
if (idx >= 0) {
|
||||
int off = pio_add_program(pi[o], _pgm);
|
||||
__pioMap[o].insert({_pgm, off});
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
*sm = idx;
|
||||
*offset = off;
|
||||
return true;
|
||||
for (int o = 0; o < PIOCNT; o++) {
|
||||
if (__pioAllocated[o] && (__pioHighGPIO[o] == needsHigh)) {
|
||||
DEBUGV("PIOProgram: Checking PIO %p\n", pi[o]);
|
||||
if (pio_can_add_program(pi[o], _pgm)) {
|
||||
int idx = pio_claim_unused_sm(pi[o], false);
|
||||
if (idx >= 0) {
|
||||
DEBUGV("PIOProgram %p: Adding IMEM ON PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
|
||||
int off = pio_add_program(pi[o], _pgm);
|
||||
__pioMap[o].insert({_pgm, off});
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
*sm = idx;
|
||||
*offset = off;
|
||||
return true;
|
||||
} else {
|
||||
DEBUGV("PIOProgram: can't claim unused SM\n");
|
||||
}
|
||||
} else {
|
||||
DEBUGV("PIOProgram: can't add program\n");
|
||||
}
|
||||
} else {
|
||||
DEBUGV("PIOProgram: Skipping PIO %p, wrong allocated/needhi\n", pi[o]);
|
||||
}
|
||||
}
|
||||
|
||||
// No existing PIOs can meet, is there an unallocated one we can allocate?
|
||||
PIO p;
|
||||
uint idx;
|
||||
uint off;
|
||||
auto rc = pio_claim_free_sm_and_add_program_for_gpio_range(_pgm, &p, &idx, &off, start, cnt, true);
|
||||
if (rc) {
|
||||
int o = 0;
|
||||
while (p != pi[o]) {
|
||||
o++;
|
||||
}
|
||||
assert(!__pioAllocated[o]);
|
||||
__pioAllocated[o] = true;
|
||||
__pioHighGPIO[o] = needsHigh;
|
||||
DEBUGV("PIOProgram %p: Allocating new PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
|
||||
__pioMap[o].insert({_pgm, off});
|
||||
_pio = pi[o];
|
||||
_sm = idx;
|
||||
*pio = pi[o];
|
||||
*sm = idx;
|
||||
*offset = off;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nope, no room either for SMs or INSNs
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
PIOProgram(const pio_program_t *pgm);
|
||||
~PIOProgram();
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool prepare(PIO *pio, int *sm, int *offset);
|
||||
bool prepare(PIO *pio, int *sm, int *offset, int gpio_start = 0, int gpio_cnt = 1);
|
||||
|
||||
private:
|
||||
const pio_program_t *_pgm;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <hardware/structs/rosc.h>
|
||||
#include <hardware/structs/systick.h>
|
||||
#include <pico/multicore.h>
|
||||
#include <hardware/dma.h>
|
||||
#include <pico/rand.h>
|
||||
#include <pico/util/queue.h>
|
||||
#include <pico/bootrom.h>
|
||||
@@ -59,8 +60,13 @@ public:
|
||||
void registerCore() {
|
||||
if (!__isFreeRTOS) {
|
||||
multicore_fifo_clear_irq();
|
||||
#ifdef PICO_RP2350
|
||||
irq_set_exclusive_handler(SIO_IRQ_FIFO, _irq);
|
||||
irq_set_enabled(SIO_IRQ_FIFO, true);
|
||||
#else
|
||||
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
|
||||
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
|
||||
#endif
|
||||
}
|
||||
// FreeRTOS port.c will handle the IRQ hooking
|
||||
}
|
||||
@@ -242,6 +248,28 @@ public:
|
||||
return &__StackLimit - &__bss_end__;
|
||||
}
|
||||
|
||||
inline int getFreePSRAMHeap() {
|
||||
return getTotalPSRAMHeap() - getUsedPSRAMHeap();
|
||||
}
|
||||
|
||||
inline int getUsedPSRAMHeap() {
|
||||
#if defined(RP2350_PSRAM_CS)
|
||||
extern size_t __psram_total_used();
|
||||
return __psram_total_used();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int getTotalPSRAMHeap() {
|
||||
#if defined(RP2350_PSRAM_CS)
|
||||
extern size_t __psram_total_space();
|
||||
return __psram_total_space();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t getStackPointer() {
|
||||
uint32_t *sp;
|
||||
asm volatile("mov %0, sp" : "=r"(sp));
|
||||
@@ -261,6 +289,15 @@ public:
|
||||
return sp - ref;
|
||||
}
|
||||
|
||||
inline size_t getPSRAMSize() {
|
||||
#if defined(RP2350_PSRAM_CS)
|
||||
extern size_t __psram_size;
|
||||
return __psram_size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void idleOtherCore() {
|
||||
fifo.idleOtherCore();
|
||||
}
|
||||
@@ -311,6 +348,36 @@ public:
|
||||
return id;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
void *memcpyDMA(void *dest, const void *src, size_t n) {
|
||||
// Allocate a DMA channel on 1st call, reuse it every call after
|
||||
if (memcpyDMAChannel < 1) {
|
||||
memcpyDMAChannel = dma_claim_unused_channel(true);
|
||||
dma_channel_config c = dma_channel_get_default_config(memcpyDMAChannel);
|
||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
|
||||
channel_config_set_read_increment(&c, true);
|
||||
channel_config_set_write_increment(&c, true);
|
||||
channel_config_set_irq_quiet(&c, true);
|
||||
dma_channel_set_config(memcpyDMAChannel, &c, false);
|
||||
}
|
||||
// If there's any misalignment or too small, use regular memcpy which can handle it
|
||||
if ((n < 64) || (((uint32_t)dest) | ((uint32_t)src) | n) & 3) {
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
int words = n / 4;
|
||||
dma_channel_set_read_addr(memcpyDMAChannel, src, false);
|
||||
dma_channel_set_write_addr(memcpyDMAChannel, dest, false);
|
||||
dma_channel_set_trans_count(memcpyDMAChannel, words, false);
|
||||
dma_channel_start(memcpyDMAChannel);
|
||||
while (dma_channel_is_busy(memcpyDMAChannel)) {
|
||||
/* busy wait dma */
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
// Multicore comms FIFO
|
||||
_MFIFO fifo;
|
||||
|
||||
@@ -336,4 +403,5 @@ private:
|
||||
PIO _pio;
|
||||
int _sm;
|
||||
PIOProgram *_ccountPgm;
|
||||
int memcpyDMAChannel = -1;
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <pico/usb_reset_interface.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <pico/bootrom.h>
|
||||
#include "sdkoverride/tusb_absmouse.h"
|
||||
#include "sdkoverride/tusb_gamepad16.h"
|
||||
#include <device/usbd_pvt.h>
|
||||
|
||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||
@@ -155,47 +155,6 @@ static uint8_t *GetDescHIDReport(int *len) {
|
||||
return __hid_report;
|
||||
}
|
||||
|
||||
#define TUD_HID_REPORT_DESC_GAMEPAD16(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
/* 16 bit X, Y, Z, Rz, Rx, Ry (min -32767, max 32767 ) */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\
|
||||
HID_LOGICAL_MIN_N ( -32767, 2 ) ,\
|
||||
HID_LOGICAL_MAX_N ( 32767, 2 ) ,\
|
||||
HID_REPORT_COUNT ( 6 ) ,\
|
||||
HID_REPORT_SIZE ( 16 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 8 bit DPad/Hat Button Map */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\
|
||||
HID_LOGICAL_MIN ( 1 ) ,\
|
||||
HID_LOGICAL_MAX ( 8 ) ,\
|
||||
HID_PHYSICAL_MIN ( 0 ) ,\
|
||||
HID_PHYSICAL_MAX_N ( 315, 2 ) ,\
|
||||
HID_REPORT_COUNT ( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 8 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 32 bit Button Map */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
|
||||
HID_USAGE_MIN ( 1 ) ,\
|
||||
HID_USAGE_MAX ( 32 ) ,\
|
||||
HID_LOGICAL_MIN ( 0 ) ,\
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
HID_REPORT_COUNT ( 32 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
HID_COLLECTION_END \
|
||||
|
||||
|
||||
void __SetupDescHIDReport() {
|
||||
//allocate memory for the HID report descriptors. We don't use them, but need the size here.
|
||||
uint8_t desc_hid_report_mouse[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1)) };
|
||||
@@ -607,8 +566,6 @@ usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
|
||||
|
||||
#elif defined NO_USB
|
||||
|
||||
// will ensure backward compatibility with existing code when using pico-debug
|
||||
|
||||
#warning "NO_USB selected. No output to Serial will occur!"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 3
|
||||
#define ARDUINO_PICO_MINOR 9
|
||||
#define ARDUINO_PICO_REVISION 4
|
||||
#define ARDUINO_PICO_VERSION_STR "3.9.4"
|
||||
#define ARDUINO_PICO_MAJOR 4
|
||||
#define ARDUINO_PICO_MINOR 0
|
||||
#define ARDUINO_PICO_REVISION 3
|
||||
#define ARDUINO_PICO_VERSION_STR "4.0.3"
|
||||
|
||||
+42
-27
@@ -33,6 +33,7 @@ static std::map<int, PIOProgram*> _rxMap;
|
||||
// Duplicate a program and replace the first insn with a "set x, repl"
|
||||
static pio_program_t *pio_make_uart_prog(int repl, const pio_program_t *pg) {
|
||||
pio_program_t *p = new pio_program_t;
|
||||
memcpy(p, pg, sizeof(*p));
|
||||
p->length = pg->length;
|
||||
p->origin = pg->origin;
|
||||
uint16_t *insn = (uint16_t *)malloc(p->length * 2);
|
||||
@@ -46,24 +47,22 @@ static pio_program_t *pio_make_uart_prog(int repl, const pio_program_t *pg) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static PIOProgram *_getTxProgram(int bits, bool inverted) {
|
||||
int key = inverted ? -bits : bits;
|
||||
auto f = _txMap.find(key);
|
||||
static PIOProgram *_getTxProgram(int bits) {
|
||||
auto f = _txMap.find(bits);
|
||||
if (f == _txMap.end()) {
|
||||
pio_program_t * p = pio_make_uart_prog(bits, inverted ? &pio_tx_inv_program : &pio_tx_program);
|
||||
_txMap.insert({key, new PIOProgram(p)});
|
||||
f = _txMap.find(key);
|
||||
pio_program_t * p = pio_make_uart_prog(bits, &pio_tx_program);
|
||||
_txMap.insert({bits, new PIOProgram(p)});
|
||||
f = _txMap.find(bits);
|
||||
}
|
||||
return f->second;
|
||||
}
|
||||
|
||||
static PIOProgram *_getRxProgram(int bits, bool inverted) {
|
||||
int key = inverted ? -bits : bits;
|
||||
auto f = _rxMap.find(key);
|
||||
static PIOProgram *_getRxProgram(int bits) {
|
||||
auto f = _rxMap.find(bits);
|
||||
if (f == _rxMap.end()) {
|
||||
pio_program_t * p = pio_make_uart_prog(bits, inverted ? &pio_rx_inv_program : &pio_rx_program);
|
||||
_rxMap.insert({key, new PIOProgram(p)});
|
||||
f = _rxMap.find(key);
|
||||
pio_program_t * p = pio_make_uart_prog(bits, &pio_rx_program);
|
||||
_rxMap.insert({bits, new PIOProgram(p)});
|
||||
f = _rxMap.find(bits);
|
||||
}
|
||||
return f->second;
|
||||
}
|
||||
@@ -80,9 +79,9 @@ static int _parity(int bits, int data) {
|
||||
|
||||
// We need to cache generated SerialPIOs so we can add data to them from
|
||||
// the shared handler
|
||||
static SerialPIO *_pioSP[2][4];
|
||||
static SerialPIO *_pioSP[3][4];
|
||||
static void __not_in_flash_func(_fifoIRQ)() {
|
||||
for (int p = 0; p < 2; p++) {
|
||||
for (int p = 0; p < 3; p++) {
|
||||
for (int sm = 0; sm < 4; sm++) {
|
||||
SerialPIO *s = _pioSP[p][sm];
|
||||
if (s) {
|
||||
@@ -98,7 +97,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
|
||||
return;
|
||||
}
|
||||
while (!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) {
|
||||
uint32_t decode = _rxPIO->rxf[_rxSM] ^ (_rxInverted ? 0xffffffff : 0);
|
||||
uint32_t decode = _rxPIO->rxf[_rxSM];
|
||||
decode >>= 33 - _rxBits;
|
||||
uint32_t val = 0;
|
||||
for (int b = 0; b < _bits + 1; b++) {
|
||||
@@ -140,6 +139,8 @@ SerialPIO::SerialPIO(pin_size_t tx, pin_size_t rx, size_t fifoSize) {
|
||||
_fifoSize = fifoSize + 1; // Always one unused entry
|
||||
_queue = new uint8_t[_fifoSize];
|
||||
mutex_init(&_mutex);
|
||||
_invertTX = false;
|
||||
_invertRX = false;
|
||||
}
|
||||
|
||||
SerialPIO::~SerialPIO() {
|
||||
@@ -147,6 +148,21 @@ SerialPIO::~SerialPIO() {
|
||||
delete[] _queue;
|
||||
}
|
||||
|
||||
static int pio_irq_0(PIO p) {
|
||||
switch (pio_get_index(p)) {
|
||||
case 0:
|
||||
return PIO0_IRQ_0;
|
||||
case 1:
|
||||
return PIO1_IRQ_0;
|
||||
#if defined(PICO_RP2350)
|
||||
case 2:
|
||||
return PIO2_IRQ_0;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
_overflow = false;
|
||||
_baud = baud;
|
||||
@@ -191,9 +207,9 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
|
||||
if (_tx != NOPIN) {
|
||||
_txBits = _bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1/*start bit*/;
|
||||
_txPgm = _getTxProgram(_txBits, _txInverted);
|
||||
_txPgm = _getTxProgram(_txBits);
|
||||
int off;
|
||||
if (!_txPgm->prepare(&_txPIO, &_txSM, &off)) {
|
||||
if (!_txPgm->prepare(&_txPIO, &_txSM, &off, _tx, 1)) {
|
||||
DEBUGCORE("ERROR: Unable to allocate PIO TX UART, out of PIO resources\n");
|
||||
// ERROR, no free slots
|
||||
return;
|
||||
@@ -211,6 +227,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
pio_sm_exec(_txPIO, _txSM, pio_encode_mov(pio_isr, pio_osr));
|
||||
|
||||
// Start running!
|
||||
gpio_set_outover(_tx, _invertTX);
|
||||
pio_sm_set_enabled(_txPIO, _txSM, true);
|
||||
}
|
||||
if (_rx != NOPIN) {
|
||||
@@ -218,9 +235,9 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
_reader = 0;
|
||||
|
||||
_rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1) - 1;
|
||||
_rxPgm = _getRxProgram(_rxBits, _rxInverted);
|
||||
_rxPgm = _getRxProgram(_rxBits);
|
||||
int off;
|
||||
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) {
|
||||
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off, _rx, 1)) {
|
||||
DEBUGCORE("ERROR: Unable to allocate PIO RX UART, out of PIO resources\n");
|
||||
return;
|
||||
}
|
||||
@@ -245,10 +262,11 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
|
||||
case 2: pio_set_irq0_source_enabled(_rxPIO, pis_sm2_rx_fifo_not_empty, true); break;
|
||||
case 3: pio_set_irq0_source_enabled(_rxPIO, pis_sm3_rx_fifo_not_empty, true); break;
|
||||
}
|
||||
auto irqno = pio_get_index(_rxPIO) == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
|
||||
auto irqno = pio_irq_0(_rxPIO);
|
||||
irq_set_exclusive_handler(irqno, _fifoIRQ);
|
||||
irq_set_enabled(irqno, true);
|
||||
|
||||
gpio_set_inover(_rx, _invertRX);
|
||||
pio_sm_set_enabled(_rxPIO, _rxSM, true);
|
||||
}
|
||||
|
||||
@@ -262,6 +280,7 @@ void SerialPIO::end() {
|
||||
if (_tx != NOPIN) {
|
||||
pio_sm_set_enabled(_txPIO, _txSM, false);
|
||||
pio_sm_unclaim(_txPIO, _txSM);
|
||||
gpio_set_outover(_tx, 0);
|
||||
}
|
||||
if (_rx != NOPIN) {
|
||||
pio_sm_set_enabled(_rxPIO, _rxSM, false);
|
||||
@@ -274,9 +293,10 @@ void SerialPIO::end() {
|
||||
used = used || !!_pioSP[pioNum][i];
|
||||
}
|
||||
if (!used) {
|
||||
auto irqno = pioNum == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
|
||||
auto irqno = pio_irq_0(_rxPIO);
|
||||
irq_set_enabled(irqno, false);
|
||||
}
|
||||
gpio_set_inover(_rx, 0);
|
||||
}
|
||||
_running = false;
|
||||
}
|
||||
@@ -348,11 +368,6 @@ void SerialPIO::flush() {
|
||||
delay((1000 * (_txBits + 1)) / _baud);
|
||||
}
|
||||
|
||||
void SerialPIO::setInverted(bool invTx, bool invRx) {
|
||||
_txInverted = invTx;
|
||||
_rxInverted = invRx;
|
||||
}
|
||||
|
||||
size_t SerialPIO::write(uint8_t c) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m || (_tx == NOPIN)) {
|
||||
@@ -371,7 +386,7 @@ size_t SerialPIO::write(uint8_t c) {
|
||||
}
|
||||
val <<= 1; // Start bit = low
|
||||
|
||||
pio_sm_put_blocking(_txPIO, _txSM, _txInverted ? ~val : val);
|
||||
pio_sm_put_blocking(_txPIO, _txSM, val);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,22 @@ public:
|
||||
void begin(unsigned long baud, uint16_t config) override;
|
||||
void end() override;
|
||||
|
||||
void setInverted(bool invTx = true, bool invRx = true);
|
||||
void setInverted(bool invTx = true, bool invRx = true) {
|
||||
setInvertTX(invTx);
|
||||
setInvertRX(invRx);
|
||||
}
|
||||
bool setInvertTX(bool invert = true) {
|
||||
if (!_running) {
|
||||
_invertTX = invert;
|
||||
}
|
||||
return !_running;
|
||||
}
|
||||
bool setInvertRX(bool invert = true) {
|
||||
if (!_running) {
|
||||
_invertRX = invert;
|
||||
}
|
||||
return !_running;
|
||||
}
|
||||
|
||||
virtual int peek() override;
|
||||
virtual int read() override;
|
||||
@@ -65,8 +80,8 @@ protected:
|
||||
int _stop;
|
||||
bool _overflow;
|
||||
mutex_t _mutex;
|
||||
bool _txInverted = false;
|
||||
bool _rxInverted = false;
|
||||
bool _invertTX;
|
||||
bool _invertRX;
|
||||
|
||||
PIOProgram *_txPgm;
|
||||
PIO _txPIO;
|
||||
|
||||
@@ -32,10 +32,16 @@ extern void serialEvent1() __attribute__((weak));
|
||||
extern void serialEvent2() __attribute__((weak));
|
||||
|
||||
bool SerialUART::setRX(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({1, 13, 17, 29}) /* UART0 */,
|
||||
#ifdef PICO_RP2350B
|
||||
constexpr uint64_t valid[2] = { __bitset({1, 13, 17, 29, 33, 45}) /* UART0 */,
|
||||
__bitset({5, 9, 21, 25, 37, 41}) /* UART1 */
|
||||
};
|
||||
#else
|
||||
constexpr uint64_t valid[2] = { __bitset({1, 13, 17, 29}) /* UART0 */,
|
||||
__bitset({5, 9, 21, 25}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
|
||||
#endif
|
||||
if ((!_running) && ((1LL << pin) & valid[uart_get_index(_uart)])) {
|
||||
_rx = pin;
|
||||
return true;
|
||||
}
|
||||
@@ -53,10 +59,16 @@ bool SerialUART::setRX(pin_size_t pin) {
|
||||
}
|
||||
|
||||
bool SerialUART::setTX(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({0, 12, 16, 28}) /* UART0 */,
|
||||
#ifdef PICO_RP2350B
|
||||
constexpr uint64_t valid[2] = { __bitset({0, 12, 16, 28, 32, 44}) /* UART0 */,
|
||||
__bitset({4, 8, 20, 24, 36, 40}) /* UART1 */
|
||||
};
|
||||
#else
|
||||
constexpr uint64_t valid[2] = { __bitset({0, 12, 16, 28}) /* UART0 */,
|
||||
__bitset({4, 8, 20, 24}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
|
||||
#endif
|
||||
if ((!_running) && ((1LL << pin) & valid[uart_get_index(_uart)])) {
|
||||
_tx = pin;
|
||||
return true;
|
||||
}
|
||||
@@ -74,10 +86,16 @@ bool SerialUART::setTX(pin_size_t pin) {
|
||||
}
|
||||
|
||||
bool SerialUART::setRTS(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
|
||||
#ifdef PICO_RP2350B
|
||||
constexpr uint64_t valid[2] = { __bitset({3, 15, 19, 31, 35, 47}) /* UART0 */,
|
||||
__bitset({7, 11, 23, 27, 39, 43}) /* UART1 */
|
||||
};
|
||||
#else
|
||||
constexpr uint64_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
|
||||
__bitset({7, 11, 23, 27}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
|
||||
#endif
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1LL << pin) & valid[uart_get_index(_uart)]))) {
|
||||
_rts = pin;
|
||||
return true;
|
||||
}
|
||||
@@ -95,10 +113,16 @@ bool SerialUART::setRTS(pin_size_t pin) {
|
||||
}
|
||||
|
||||
bool SerialUART::setCTS(pin_size_t pin) {
|
||||
constexpr uint32_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
|
||||
#ifdef PICO_RP2350B
|
||||
constexpr uint64_t valid[2] = { __bitset({2, 14, 18, 30, 34, 46}) /* UART0 */,
|
||||
__bitset({6, 10, 22, 26, 38, 42}) /* UART1 */
|
||||
};
|
||||
#else
|
||||
constexpr uint64_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
|
||||
__bitset({6, 10, 22, 26}) /* UART1 */
|
||||
};
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
|
||||
#endif
|
||||
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1LL << pin) & valid[uart_get_index(_uart)]))) {
|
||||
_cts = pin;
|
||||
return true;
|
||||
}
|
||||
@@ -138,6 +162,9 @@ SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size
|
||||
_cts = cts;
|
||||
mutex_init(&_mutex);
|
||||
mutex_init(&_fifoMutex);
|
||||
_invertTX = false;
|
||||
_invertRX = false;
|
||||
_invertControl = false;
|
||||
}
|
||||
|
||||
static void _uart0IRQ();
|
||||
@@ -154,14 +181,18 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
_fcnTx = gpio_get_function(_tx);
|
||||
_fcnRx = gpio_get_function(_rx);
|
||||
gpio_set_function(_tx, GPIO_FUNC_UART);
|
||||
gpio_set_outover(_tx, _invertTX ? 1 : 0);
|
||||
gpio_set_function(_rx, GPIO_FUNC_UART);
|
||||
gpio_set_inover(_rx, _invertRX ? 1 : 0);
|
||||
if (_rts != UART_PIN_NOT_DEFINED) {
|
||||
_fcnRts = gpio_get_function(_rts);
|
||||
gpio_set_function(_rts, GPIO_FUNC_UART);
|
||||
gpio_set_outover(_rts, _invertControl ? 1 : 0);
|
||||
}
|
||||
if (_cts != UART_PIN_NOT_DEFINED) {
|
||||
_fcnCts = gpio_get_function(_cts);
|
||||
gpio_set_function(_cts, GPIO_FUNC_UART);
|
||||
gpio_set_inover(_cts, _invertControl ? 1 : 0);
|
||||
}
|
||||
|
||||
uart_init(_uart, baud);
|
||||
@@ -246,12 +277,16 @@ void SerialUART::end() {
|
||||
|
||||
// Restore pin functions
|
||||
gpio_set_function(_tx, _fcnTx);
|
||||
gpio_set_outover(_tx, 0);
|
||||
gpio_set_function(_rx, _fcnRx);
|
||||
gpio_set_inover(_rx, 0);
|
||||
if (_rts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_rts, _fcnRts);
|
||||
gpio_set_outover(_rts, 0);
|
||||
}
|
||||
if (_cts != UART_PIN_NOT_DEFINED) {
|
||||
gpio_set_function(_cts, _fcnCts);
|
||||
gpio_set_inover(_cts, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,26 @@ public:
|
||||
ret &= setTX(tx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool setInvertTX(bool invert = true) {
|
||||
if (!_running) {
|
||||
_invertTX = invert;
|
||||
}
|
||||
return !_running;
|
||||
}
|
||||
bool setInvertRX(bool invert = true) {
|
||||
if (!_running) {
|
||||
_invertRX = invert;
|
||||
}
|
||||
return !_running;
|
||||
}
|
||||
bool setInvertControl(bool invert = true) {
|
||||
if (!_running) {
|
||||
_invertControl = invert;
|
||||
}
|
||||
return !_running;
|
||||
}
|
||||
|
||||
bool setFIFOSize(size_t size);
|
||||
bool setPollingMode(bool mode = true);
|
||||
|
||||
@@ -80,12 +100,13 @@ private:
|
||||
uart_inst_t *_uart;
|
||||
pin_size_t _tx, _rx;
|
||||
pin_size_t _rts, _cts;
|
||||
enum gpio_function _fcnTx, _fcnRx, _fcnRts, _fcnCts;
|
||||
gpio_function_t _fcnTx, _fcnRx, _fcnRts, _fcnCts;
|
||||
int _baud;
|
||||
mutex_t _mutex;
|
||||
bool _polling = false;
|
||||
bool _overflow;
|
||||
bool _break;
|
||||
bool _invertTX, _invertRX, _invertControl;
|
||||
|
||||
// Lockless, IRQ-handled circular queue
|
||||
uint32_t _writer;
|
||||
|
||||
@@ -30,10 +30,6 @@ public:
|
||||
}
|
||||
|
||||
~SoftwareSerial() {
|
||||
if (_invert) {
|
||||
gpio_set_outover(_tx, 0);
|
||||
gpio_set_outover(_rx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void begin(unsigned long baud = 115200) override {
|
||||
@@ -41,11 +37,9 @@ public:
|
||||
};
|
||||
|
||||
void begin(unsigned long baud, uint16_t config) override {
|
||||
setInvertTX(_invert);
|
||||
setInvertRX(_invert);
|
||||
SerialPIO::begin(baud, config);
|
||||
if (_invert) {
|
||||
gpio_set_outover(_tx, GPIO_OVERRIDE_INVERT);
|
||||
gpio_set_inover(_rx, GPIO_OVERRIDE_INVERT);
|
||||
}
|
||||
}
|
||||
|
||||
void listen() { /* noop */ }
|
||||
|
||||
@@ -56,7 +56,7 @@ int64_t _stopTonePIO(alarm_id_t id, void *user_data) {
|
||||
}
|
||||
|
||||
void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
if (pin > 29) {
|
||||
if (pin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
newTone = new Tone();
|
||||
newTone->pin = pin;
|
||||
pinMode(pin, OUTPUT);
|
||||
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off)) {
|
||||
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off, pin, 1)) {
|
||||
DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n");
|
||||
// ERROR, no free slots
|
||||
delete newTone;
|
||||
@@ -118,7 +118,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
void noTone(uint8_t pin) {
|
||||
CoreMutex m(&_toneMutex);
|
||||
|
||||
if ((pin > 29) || !m) {
|
||||
if ((pin > __GPIOCNT) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,5 +54,8 @@ extern "C" {
|
||||
|
||||
extern void __freertos_idle_other_core() __attribute__((weak));
|
||||
extern void __freertos_resume_other_core() __attribute__((weak));
|
||||
|
||||
extern void __freertos_task_exit_critical() __attribute__((weak));
|
||||
extern void __freertos_task_enter_critical() __attribute__((weak));
|
||||
}
|
||||
extern SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive = false);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#define ccount_wrap_target 0
|
||||
#define ccount_wrap 1
|
||||
#define ccount_pio_version 0
|
||||
|
||||
static const uint16_t ccount_program_instructions[] = {
|
||||
// .wrap_target
|
||||
@@ -27,6 +28,10 @@ static const struct pio_program ccount_program = {
|
||||
.instructions = ccount_program_instructions,
|
||||
.length = 2,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config ccount_program_get_default_config(uint offset) {
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#ifdef PICO_RP2040
|
||||
#include <pico/cyw43_arch.h>
|
||||
#endif
|
||||
#include <pico/mutex.h>
|
||||
#include <sys/lock.h>
|
||||
#include "_xoshiro.h"
|
||||
@@ -247,19 +249,19 @@ extern "C" {
|
||||
extern void __real_tcp_setprio(struct tcp_pcb *pcb, u8_t prio);
|
||||
void __wrap_tcp_setprio(struct tcp_pcb *pcb, u8_t prio) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_setprio(pcb, prio);
|
||||
__real_tcp_setprio(pcb, prio);
|
||||
}
|
||||
|
||||
extern void __real_tcp_backlog_delayed(struct tcp_pcb* pcb);
|
||||
void __wrap_tcp_backlog_delayed(struct tcp_pcb* pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_backlog_delayed(pcb);
|
||||
__real_tcp_backlog_delayed(pcb);
|
||||
}
|
||||
|
||||
extern void __real_tcp_backlog_accepted(struct tcp_pcb* pcb);
|
||||
void __wrap_tcp_backlog_accepted(struct tcp_pcb* pcb) {
|
||||
LWIPMutex m;
|
||||
return __real_tcp_backlog_accepted(pcb);
|
||||
__real_tcp_backlog_accepted(pcb);
|
||||
}
|
||||
extern struct udp_pcb *__real_udp_new(void);
|
||||
struct udp_pcb *__wrap_udp_new(void) {
|
||||
|
||||
@@ -79,7 +79,7 @@ extern void __loop() {
|
||||
static struct _reent *_impure_ptr1 = nullptr;
|
||||
|
||||
extern "C" int main() {
|
||||
#if F_CPU != 125000000
|
||||
#if (defined(PICO_RP2040) && (F_CPU != 125000000)) || (defined(PICO_RP2350) && (F_CPU != 150000000))
|
||||
set_sys_clock_khz(F_CPU / 1000, true);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -19,11 +19,25 @@
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <malloc.h>
|
||||
#include <reent.h>
|
||||
#include "psram.h"
|
||||
|
||||
extern "C" void *__real_malloc(size_t size);
|
||||
extern "C" void *__real_calloc(size_t count, size_t size);
|
||||
extern "C" void *__real_realloc(void *mem, size_t size);
|
||||
extern "C" void __real_free(void *mem);
|
||||
extern "C" struct mallinfo __real_mallinfo();
|
||||
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
extern "C" {
|
||||
extern uint8_t __psram_start__;
|
||||
extern uint8_t __psram_heap_start__;
|
||||
void __malloc_lock(struct _reent *ptr);
|
||||
void __malloc_unlock(struct _reent *ptr);
|
||||
static void *__ram_start = (void *)0x20000000; // TODO - Is there a SDK exposed variable/macro?
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" void *__wrap_malloc(size_t size) {
|
||||
noInterrupts();
|
||||
@@ -39,15 +53,72 @@ extern "C" void *__wrap_calloc(size_t count, size_t size) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void *__wrap_realloc(void *mem, size_t size) {
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
// Utilize the existing malloc lock infrastructure and interrupt blocking
|
||||
// to work with multicore and FreeRTOS
|
||||
extern "C" void *pmalloc(size_t size) {
|
||||
noInterrupts();
|
||||
void *rc = __real_realloc(mem, size);
|
||||
__malloc_lock(__getreent());
|
||||
auto rc = __psram_malloc(size);
|
||||
__malloc_unlock(__getreent());
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void *pcalloc(size_t count, size_t size) {
|
||||
noInterrupts();
|
||||
__malloc_lock(__getreent());
|
||||
auto rc = __psram_calloc(count, size);
|
||||
__malloc_unlock(__getreent());
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
// No PSRAM, always fail
|
||||
extern "C" void *pmalloc(size_t size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" void *pcalloc(size_t count, size_t size) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" void *__wrap_realloc(void *mem, size_t size) {
|
||||
void *rc;
|
||||
noInterrupts();
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
if (mem && (mem < __ram_start)) {
|
||||
rc = __psram_realloc(mem, size);
|
||||
} else {
|
||||
rc = __real_realloc(mem, size);
|
||||
}
|
||||
#else
|
||||
rc = __real_realloc(mem, size);
|
||||
#endif
|
||||
interrupts();
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern "C" void __wrap_free(void *mem) {
|
||||
noInterrupts();
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
if (mem && (mem < __ram_start)) {
|
||||
__psram_free(mem);
|
||||
} else {
|
||||
__real_free(mem);
|
||||
}
|
||||
#else
|
||||
__real_free(mem);
|
||||
#endif
|
||||
interrupts();
|
||||
}
|
||||
|
||||
extern "C" struct mallinfo __wrap_mallinfo() {
|
||||
noInterrupts();
|
||||
__malloc_lock(__getreent());
|
||||
auto ret = __real_mallinfo();
|
||||
__malloc_unlock(__getreent());
|
||||
interrupts();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -39,35 +39,13 @@ wait_bit:
|
||||
jmp y-- wait_bit
|
||||
jmp x-- bitloop
|
||||
|
||||
|
||||
|
||||
; inverted-logic version (inverts the stop bit)
|
||||
|
||||
.program pio_tx_inv
|
||||
.side_set 1 opt
|
||||
|
||||
|
||||
; We shift out the start and stop bit as part of the FIFO
|
||||
set x, 9
|
||||
|
||||
pull side 0 ; Force stop bit low
|
||||
|
||||
; Send the bits
|
||||
bitloop:
|
||||
out pins, 1
|
||||
mov y, isr ; ISR is loaded by the setup routine with the period-1 count
|
||||
wait_bit:
|
||||
jmp y-- wait_bit
|
||||
jmp x-- bitloop
|
||||
|
||||
|
||||
% c-sdk {
|
||||
|
||||
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
|
||||
// Tell PIO to initially drive output-high on the selected pin, then map PIO
|
||||
// onto that pin with the IO muxes.
|
||||
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_sm_set_set_pins(pio, sm, pin_tx, 1);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_tx, 1, true);
|
||||
pio_gpio_init(pio, pin_tx);
|
||||
|
||||
pio_sm_config c = pio_tx_program_get_default_config(offset);
|
||||
@@ -110,28 +88,6 @@ wait_half:
|
||||
|
||||
push ; Stuff it and wait for next start
|
||||
|
||||
|
||||
.program pio_rx_inv
|
||||
|
||||
; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
|
||||
|
||||
start:
|
||||
set x, 18 ; Preload bit counter...we'll shift in the start bit and stop bit, and each bit will be double-recorded (to be fixed by RP2040 code)
|
||||
wait 1 pin 0 ; Stall until start bit is asserted
|
||||
|
||||
bitloop:
|
||||
; Delay until 1/2 way into the bit time
|
||||
mov y, osr
|
||||
wait_half:
|
||||
jmp y-- wait_half
|
||||
|
||||
; Read in the bit
|
||||
in pins, 1 ; Shift data bit into ISR
|
||||
jmp x-- bitloop ; Loop all bits
|
||||
|
||||
push ; Stuff it and wait for next start
|
||||
|
||||
|
||||
% c-sdk {
|
||||
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
|
||||
+12
-68
@@ -14,6 +14,7 @@
|
||||
|
||||
#define pio_tx_wrap_target 0
|
||||
#define pio_tx_wrap 5
|
||||
#define pio_tx_pio_version 0
|
||||
|
||||
static const uint16_t pio_tx_program_instructions[] = {
|
||||
// .wrap_target
|
||||
@@ -31,6 +32,10 @@ static const struct pio_program pio_tx_program = {
|
||||
.instructions = pio_tx_program_instructions,
|
||||
.length = 6,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_tx_program_get_default_config(uint offset) {
|
||||
@@ -39,45 +44,12 @@ static inline pio_sm_config pio_tx_program_get_default_config(uint offset) {
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------- //
|
||||
// pio_tx_inv //
|
||||
// ---------- //
|
||||
|
||||
#define pio_tx_inv_wrap_target 0
|
||||
#define pio_tx_inv_wrap 5
|
||||
|
||||
static const uint16_t pio_tx_inv_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe029, // 0: set x, 9
|
||||
0x90a0, // 1: pull block side 0
|
||||
0x6001, // 2: out pins, 1
|
||||
0xa046, // 3: mov y, isr
|
||||
0x0084, // 4: jmp y--, 4
|
||||
0x0042, // 5: jmp x--, 2
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_tx_inv_program = {
|
||||
.instructions = pio_tx_inv_program_instructions,
|
||||
.length = 6,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_tx_inv_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_tx_inv_wrap_target, offset + pio_tx_inv_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx) {
|
||||
// Tell PIO to initially drive output-high on the selected pin, then map PIO
|
||||
// onto that pin with the IO muxes.
|
||||
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||||
pio_sm_set_set_pins(pio, sm, pin_tx, 1);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_tx, 1, true);
|
||||
pio_gpio_init(pio, pin_tx);
|
||||
pio_sm_config c = pio_tx_program_get_default_config(offset);
|
||||
// OUT shifts to right, no autopull
|
||||
@@ -100,6 +72,7 @@ static inline void pio_tx_program_init(PIO pio, uint sm, uint offset, uint pin_t
|
||||
|
||||
#define pio_rx_wrap_target 0
|
||||
#define pio_rx_wrap 6
|
||||
#define pio_rx_pio_version 0
|
||||
|
||||
static const uint16_t pio_rx_program_instructions[] = {
|
||||
// .wrap_target
|
||||
@@ -118,6 +91,10 @@ static const struct pio_program pio_rx_program = {
|
||||
.instructions = pio_rx_program_instructions,
|
||||
.length = 7,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_rx_program_get_default_config(uint offset) {
|
||||
@@ -125,39 +102,6 @@ static inline pio_sm_config pio_rx_program_get_default_config(uint offset) {
|
||||
sm_config_set_wrap(&c, offset + pio_rx_wrap_target, offset + pio_rx_wrap);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------- //
|
||||
// pio_rx_inv //
|
||||
// ---------- //
|
||||
|
||||
#define pio_rx_inv_wrap_target 0
|
||||
#define pio_rx_inv_wrap 6
|
||||
|
||||
static const uint16_t pio_rx_inv_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xe032, // 0: set x, 18
|
||||
0x20a0, // 1: wait 1 pin, 0
|
||||
0xa047, // 2: mov y, osr
|
||||
0x0083, // 3: jmp y--, 3
|
||||
0x4001, // 4: in pins, 1
|
||||
0x0042, // 5: jmp x--, 2
|
||||
0x8020, // 6: push block
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program pio_rx_inv_program = {
|
||||
.instructions = pio_rx_inv_program_instructions,
|
||||
.length = 7,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config pio_rx_inv_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + pio_rx_inv_wrap_target, offset + pio_rx_inv_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void pio_rx_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
|
||||
@@ -0,0 +1,437 @@
|
||||
// Originally from https://github.com/sparkfun/sparkfun-pico
|
||||
/**
|
||||
@file sfe_psram.c
|
||||
|
||||
@brief This file contains a function that is used to detect and initialize PSRAM on
|
||||
SparkFun rp2350 boards.
|
||||
*/
|
||||
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 SparkFun Electronics
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// Hacked by Earle Philhower to work with the Arduino-Pico core
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef RP2350_PSRAM_CS
|
||||
|
||||
#include <hardware/address_mapped.h>
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/regs/addressmap.h>
|
||||
#include <hardware/spi.h>
|
||||
#include <hardware/structs/qmi.h>
|
||||
#include <hardware/structs/xip_ctrl.h>
|
||||
#include <pico/runtime_init.h>
|
||||
|
||||
// Include TLSF in this compilation unit
|
||||
#include "../../lib/tlsf/tlsf.c"
|
||||
static tlsf_t _mem_heap = nullptr;
|
||||
static pool_t _mem_psram_pool = nullptr;
|
||||
|
||||
// PSRAM heap minus PSRAM global/static variables from the linker
|
||||
extern "C" {
|
||||
extern uint8_t __psram_start__;
|
||||
extern uint8_t __psram_heap_start__;
|
||||
}
|
||||
|
||||
static bool _bInitalized = false;
|
||||
size_t __psram_size = 0;
|
||||
size_t __psram_heap_size = 0;
|
||||
|
||||
#define PICO_RUNTIME_INIT_PSRAM "11001" // Towards the end, after alarms
|
||||
|
||||
#ifndef RP2350_PSRAM_MAX_SELECT_FS64
|
||||
#define RP2350_PSRAM_MAX_SELECT_FS64 (125'000'000)
|
||||
#endif
|
||||
|
||||
#ifndef RP2350_PSRAM_MIN_DESELECT_FS
|
||||
#define RP2350_PSRAM_MIN_DESELECT_FS (50'000'000)
|
||||
#endif
|
||||
|
||||
#ifndef RP2350_PSRAM_MAX_SCK_HZ
|
||||
#define RP2350_PSRAM_MAX_SCK_HZ (109'000'000)
|
||||
#endif
|
||||
|
||||
#ifndef RP2350_PSRAM_ID
|
||||
#define RP2350_PSRAM_ID (0x5D)
|
||||
#endif
|
||||
|
||||
// DETAILS/
|
||||
//
|
||||
// SparkFun RP2350 boards use the following PSRAM IC:
|
||||
//
|
||||
// apmemory APS6404L-3SQR-ZR
|
||||
// https://www.mouser.com/ProductDetail/AP-Memory/APS6404L-3SQR-ZR?qs=IS%252B4QmGtzzpDOdsCIglviw%3D%3D
|
||||
//
|
||||
// The origin of this logic is from the Circuit Python code that was downloaded from:
|
||||
// https://github.com/raspberrypi/pico-sdk-rp2350/issues/12#issuecomment-2055274428
|
||||
//
|
||||
|
||||
// Details on the PSRAM IC that are used during setup/configuration of PSRAM on SparkFun RP2350 boards.
|
||||
|
||||
// For PSRAM timing calculations - to use int math, we work in femto seconds (fs) (1e-15),
|
||||
// NOTE: This idea is from micro python work on psram..
|
||||
|
||||
#define SFE_SEC_TO_FS 1000000000000000ll
|
||||
|
||||
// max select pulse width = 8us => 8e6 ns => 8000 ns => 8000 * 1e6 fs => 8000e6 fs
|
||||
// Additionally, the MAX select is in units of 64 clock cycles - will use a constant that
|
||||
// takes this into account - so 8000e6 fs / 64 = 125e6 fs
|
||||
|
||||
const uint32_t SFE_PSRAM_MAX_SELECT_FS64 = RP2350_PSRAM_MAX_SELECT_FS64;
|
||||
|
||||
// min deselect pulse width = 50ns => 50 * 1e6 fs => 50e7 fs
|
||||
const uint32_t SFE_PSRAM_MIN_DESELECT_FS = RP2350_PSRAM_MIN_DESELECT_FS;
|
||||
|
||||
// from psram datasheet - max Freq with VDDat 3.3v - SparkFun RP2350 boards run at 3.3v.
|
||||
// If VDD = 3.0 Max Freq is 133 Mhz
|
||||
const uint32_t SFE_PSRAM_MAX_SCK_HZ = RP2350_PSRAM_MAX_SCK_HZ;
|
||||
|
||||
// PSRAM SPI command codes
|
||||
const uint8_t PSRAM_CMD_QUAD_END = 0xF5;
|
||||
const uint8_t PSRAM_CMD_QUAD_ENABLE = 0x35;
|
||||
const uint8_t PSRAM_CMD_READ_ID = 0x9F;
|
||||
const uint8_t PSRAM_CMD_RSTEN = 0x66;
|
||||
const uint8_t PSRAM_CMD_RST = 0x99;
|
||||
const uint8_t PSRAM_CMD_QUAD_READ = 0xEB;
|
||||
const uint8_t PSRAM_CMD_QUAD_WRITE = 0x38;
|
||||
const uint8_t PSRAM_CMD_NOOP = 0xFF;
|
||||
|
||||
const uint8_t PSRAM_ID = RP2350_PSRAM_ID;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// @brief Communicate directly with the PSRAM IC - validate it is present and return the size
|
||||
///
|
||||
/// @return size_t The size of the PSRAM
|
||||
///
|
||||
/// @note This function expects the CS pin set
|
||||
static size_t __no_inline_not_in_flash_func(get_psram_size)(void) {
|
||||
size_t psram_size = 0;
|
||||
uint32_t intr_stash = save_and_disable_interrupts();
|
||||
|
||||
// Try and read the PSRAM ID via direct_csr.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB | QMI_DIRECT_CSR_EN_BITS;
|
||||
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// Exit out of QMI in case we've inited already
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
|
||||
// Transmit the command to exit QPI quad mode - read ID as standard SPI
|
||||
qmi_hw->direct_tx =
|
||||
QMI_DIRECT_TX_OE_BITS | QMI_DIRECT_TX_IWIDTH_VALUE_Q << QMI_DIRECT_TX_IWIDTH_LSB | PSRAM_CMD_QUAD_END;
|
||||
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
(void)qmi_hw->direct_rx;
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
|
||||
// Read the id
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
uint8_t kgd = 0;
|
||||
uint8_t eid = 0;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
qmi_hw->direct_tx = (i == 0 ? PSRAM_CMD_READ_ID : PSRAM_CMD_NOOP);
|
||||
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_TXEMPTY_BITS) == 0) {
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
if (i == 5) {
|
||||
kgd = qmi_hw->direct_rx;
|
||||
} else if (i == 6) {
|
||||
eid = qmi_hw->direct_rx;
|
||||
} else {
|
||||
(void)qmi_hw->direct_rx; // just read and discard
|
||||
}
|
||||
}
|
||||
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
// is this the PSRAM we're looking for obi-wan?
|
||||
if (kgd == PSRAM_ID) {
|
||||
// PSRAM size
|
||||
psram_size = 1024 * 1024; // 1 MiB
|
||||
uint8_t size_id = eid >> 5;
|
||||
if (eid == 0x26 || size_id == 2) {
|
||||
psram_size *= 8;
|
||||
} else if (size_id == 0) {
|
||||
psram_size *= 2;
|
||||
} else if (size_id == 1) {
|
||||
psram_size *= 4;
|
||||
}
|
||||
}
|
||||
restore_interrupts(intr_stash);
|
||||
return psram_size;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
/// @brief Update the PSRAM timing configuration based on system clock
|
||||
///
|
||||
/// @note This function expects interrupts to be enabled on entry
|
||||
|
||||
static void __no_inline_not_in_flash_func(set_psram_timing)(void) {
|
||||
// Get secs / cycle for the system clock - get before disabling interrupts.
|
||||
uint32_t sysHz = (uint32_t)clock_get_hz(clk_sys);
|
||||
|
||||
// Calculate the clock divider - goal to get clock used for PSRAM <= what
|
||||
// the PSRAM IC can handle - which is defined in SFE_PSRAM_MAX_SCK_HZ
|
||||
volatile uint8_t clockDivider = (sysHz + SFE_PSRAM_MAX_SCK_HZ - 1) / SFE_PSRAM_MAX_SCK_HZ;
|
||||
|
||||
uint32_t intr_stash = save_and_disable_interrupts();
|
||||
|
||||
// Get the clock femto seconds per cycle.
|
||||
|
||||
uint32_t fsPerCycle = SFE_SEC_TO_FS / sysHz;
|
||||
|
||||
// the maxSelect value is defined in units of 64 clock cycles
|
||||
// So maxFS / (64 * fsPerCycle) = maxSelect = SFE_PSRAM_MAX_SELECT_FS64/fsPerCycle
|
||||
volatile uint8_t maxSelect = SFE_PSRAM_MAX_SELECT_FS64 / fsPerCycle;
|
||||
|
||||
// minDeselect time - in system clock cycle
|
||||
// Must be higher than 50ns (min deselect time for PSRAM) so add a fsPerCycle - 1 to round up
|
||||
// So minFS/fsPerCycle = minDeselect = SFE_PSRAM_MIN_DESELECT_FS/fsPerCycle
|
||||
|
||||
volatile uint8_t minDeselect = (SFE_PSRAM_MIN_DESELECT_FS + fsPerCycle - 1) / fsPerCycle;
|
||||
|
||||
// printf("Max Select: %d, Min Deselect: %d, clock divider: %d\n", maxSelect, minDeselect, clockDivider);
|
||||
|
||||
qmi_hw->m[1].timing = QMI_M1_TIMING_PAGEBREAK_VALUE_1024 << QMI_M1_TIMING_PAGEBREAK_LSB | // Break between pages.
|
||||
3 << QMI_M1_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles.
|
||||
1 << QMI_M1_TIMING_COOLDOWN_LSB | 1 << QMI_M1_TIMING_RXDELAY_LSB |
|
||||
maxSelect << QMI_M1_TIMING_MAX_SELECT_LSB | minDeselect << QMI_M1_TIMING_MIN_DESELECT_LSB |
|
||||
clockDivider << QMI_M1_TIMING_CLKDIV_LSB;
|
||||
|
||||
restore_interrupts(intr_stash);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// @brief The setup_psram function - note that this is not in flash
|
||||
///
|
||||
///
|
||||
static void __no_inline_not_in_flash_func(runtime_init_setup_psram)(/*uint32_t psram_cs_pin*/) {
|
||||
// Set the PSRAM CS pin in the SDK
|
||||
gpio_set_function(RP2350_PSRAM_CS, GPIO_FUNC_XIP_CS1);
|
||||
|
||||
// start with zero size
|
||||
size_t psram_size = get_psram_size();
|
||||
|
||||
// No PSRAM - no dice
|
||||
if (psram_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t intr_stash = save_and_disable_interrupts();
|
||||
// Enable quad mode.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB | QMI_DIRECT_CSR_EN_BITS;
|
||||
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// RESETEN, RESET and quad enable
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
if (i == 0) {
|
||||
qmi_hw->direct_tx = PSRAM_CMD_RSTEN;
|
||||
} else if (i == 1) {
|
||||
qmi_hw->direct_tx = PSRAM_CMD_RST;
|
||||
} else {
|
||||
qmi_hw->direct_tx = PSRAM_CMD_QUAD_ENABLE;
|
||||
}
|
||||
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
for (size_t j = 0; j < 20; j++) {
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
(void)qmi_hw->direct_rx;
|
||||
}
|
||||
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
// check our interrupts and setup the timing
|
||||
restore_interrupts(intr_stash);
|
||||
set_psram_timing();
|
||||
|
||||
// and now stash interrupts again
|
||||
intr_stash = save_and_disable_interrupts();
|
||||
|
||||
qmi_hw->m[1].rfmt = (QMI_M1_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M1_RFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M1_RFMT_ADDR_WIDTH_VALUE_Q << QMI_M1_RFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M1_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M1_RFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M1_RFMT_DUMMY_WIDTH_VALUE_Q << QMI_M1_RFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M1_RFMT_DUMMY_LEN_VALUE_24 << QMI_M1_RFMT_DUMMY_LEN_LSB |
|
||||
QMI_M1_RFMT_DATA_WIDTH_VALUE_Q << QMI_M1_RFMT_DATA_WIDTH_LSB |
|
||||
QMI_M1_RFMT_PREFIX_LEN_VALUE_8 << QMI_M1_RFMT_PREFIX_LEN_LSB |
|
||||
QMI_M1_RFMT_SUFFIX_LEN_VALUE_NONE << QMI_M1_RFMT_SUFFIX_LEN_LSB);
|
||||
|
||||
qmi_hw->m[1].rcmd = PSRAM_CMD_QUAD_READ << QMI_M1_RCMD_PREFIX_LSB | 0 << QMI_M1_RCMD_SUFFIX_LSB;
|
||||
|
||||
qmi_hw->m[1].wfmt = (QMI_M1_WFMT_PREFIX_WIDTH_VALUE_Q << QMI_M1_WFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M1_WFMT_ADDR_WIDTH_VALUE_Q << QMI_M1_WFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M1_WFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M1_WFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M1_WFMT_DUMMY_WIDTH_VALUE_Q << QMI_M1_WFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M1_WFMT_DUMMY_LEN_VALUE_NONE << QMI_M1_WFMT_DUMMY_LEN_LSB |
|
||||
QMI_M1_WFMT_DATA_WIDTH_VALUE_Q << QMI_M1_WFMT_DATA_WIDTH_LSB |
|
||||
QMI_M1_WFMT_PREFIX_LEN_VALUE_8 << QMI_M1_WFMT_PREFIX_LEN_LSB |
|
||||
QMI_M1_WFMT_SUFFIX_LEN_VALUE_NONE << QMI_M1_WFMT_SUFFIX_LEN_LSB);
|
||||
|
||||
qmi_hw->m[1].wcmd = PSRAM_CMD_QUAD_WRITE << QMI_M1_WCMD_PREFIX_LSB | 0 << QMI_M1_WCMD_SUFFIX_LSB;
|
||||
|
||||
// Mark that we can write to PSRAM.
|
||||
xip_ctrl_hw->ctrl |= XIP_CTRL_WRITABLE_M1_BITS;
|
||||
|
||||
restore_interrupts(intr_stash);
|
||||
|
||||
__psram_size = psram_size;
|
||||
|
||||
uint32_t used_psram_size = &__psram_heap_start__ - &__psram_start__;
|
||||
__psram_heap_size = __psram_size - used_psram_size;
|
||||
}
|
||||
PICO_RUNTIME_INIT_FUNC_RUNTIME(runtime_init_setup_psram, PICO_RUNTIME_INIT_PSRAM);
|
||||
|
||||
// update timing -- used if the system clock/timing was changed.
|
||||
void psram_reinit_timing() {
|
||||
set_psram_timing();
|
||||
}
|
||||
|
||||
static bool __psram_heap_init() {
|
||||
if (_bInitalized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!__psram_heap_size) {
|
||||
return false;
|
||||
}
|
||||
_mem_heap = NULL;
|
||||
_mem_psram_pool = NULL;
|
||||
_mem_heap = tlsf_create_with_pool((void *)&__psram_heap_start__, __psram_heap_size, 16 * 1024 * 1024);
|
||||
if (!_mem_heap) {
|
||||
return false;
|
||||
}
|
||||
_mem_psram_pool = tlsf_get_pool(_mem_heap);
|
||||
if (!_mem_psram_pool) {
|
||||
return false;
|
||||
}
|
||||
_bInitalized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void *__psram_malloc(size_t size) {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return NULL;
|
||||
}
|
||||
return tlsf_malloc(_mem_heap, size);
|
||||
}
|
||||
|
||||
void __psram_free(void *ptr) {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return;
|
||||
}
|
||||
tlsf_free(_mem_heap, ptr);
|
||||
}
|
||||
|
||||
void *__psram_realloc(void *ptr, size_t size) {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return NULL;
|
||||
}
|
||||
return tlsf_realloc(_mem_heap, ptr, size);
|
||||
}
|
||||
|
||||
void *__psram_calloc(size_t num, size_t size) {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr = tlsf_malloc(_mem_heap, num * size);
|
||||
if (ptr) {
|
||||
bzero(ptr, num * size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static bool max_free_walker(void *ptr, size_t size, int used, void *user) {
|
||||
size_t *max_size = (size_t *)user;
|
||||
if (!used && *max_size < size) {
|
||||
*max_size = size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t __psram_largest_free_block() {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return 0;
|
||||
}
|
||||
size_t max_free = 0;
|
||||
if (_mem_psram_pool) {
|
||||
tlsf_walk_pool(_mem_psram_pool, max_free_walker, &max_free);
|
||||
}
|
||||
return max_free;
|
||||
}
|
||||
|
||||
static bool memory_size_walker(void *ptr, size_t size, int used, void *user) {
|
||||
*((size_t *)user) += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t __psram_total_space() {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return 0;
|
||||
}
|
||||
size_t total_size = 0;
|
||||
if (_mem_psram_pool) {
|
||||
tlsf_walk_pool(_mem_psram_pool, memory_size_walker, &total_size);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
static bool memory_used_walker(void *ptr, size_t size, int used, void *user) {
|
||||
if (used) {
|
||||
*((size_t *)user) += size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t __psram_total_used() {
|
||||
if (!__psram_heap_init() || !_mem_heap) {
|
||||
return 0;
|
||||
}
|
||||
size_t total_size = 0;
|
||||
if (_mem_psram_pool) {
|
||||
tlsf_walk_pool(_mem_psram_pool, memory_used_walker, &total_size);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
#endif // RP2350_PSRAM_CS
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
@file sfe_psram.c
|
||||
|
||||
@brief This file contains a function that is used to detect and initialize PSRAM on
|
||||
SparkFun rp2350 boards.
|
||||
*/
|
||||
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 SparkFun Electronics
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void psram_reinit_timing();
|
||||
void *__psram_malloc(size_t size);
|
||||
void __psram_free(void *ptr);
|
||||
void *__psram_realloc(void *ptr, size_t size);
|
||||
void *__psram_calloc(size_t num, size_t size);
|
||||
size_t __psram_largest_free_block();
|
||||
size_t __psram_total_space();
|
||||
size_t __psram_total_used();
|
||||
@@ -49,11 +49,15 @@ static uint32_t pico_flash_bank_get_alignment(void * context) {
|
||||
static void pico_flash_bank_erase(void * context, int bank) {
|
||||
(void)(context);
|
||||
DEBUG_PRINT("erase: bank %d\n", bank);
|
||||
noInterrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
noInterrupts();
|
||||
}
|
||||
rp2040.idleOtherCore();
|
||||
flash_range_erase(PICO_FLASH_BANK_STORAGE_OFFSET + (PICO_FLASH_BANK_SIZE * bank), PICO_FLASH_BANK_SIZE);
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
static void pico_flash_bank_read(void *context, int bank, uint32_t offset, uint8_t *buffer, uint32_t size) {
|
||||
@@ -147,11 +151,15 @@ static void pico_flash_bank_write(void * context, int bank, uint32_t offset, con
|
||||
offset = 0;
|
||||
|
||||
// Now program the entire page
|
||||
noInterrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
noInterrupts();
|
||||
}
|
||||
rp2040.idleOtherCore();
|
||||
flash_range_program(bank_start_pos + (page * FLASH_PAGE_SIZE), page_data, FLASH_PAGE_SIZE);
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
if (!__isFreeRTOS) {
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#if PICO_ENTER_USB_BOOT_ON_EXIT
|
||||
#include "pico/bootrom.h"
|
||||
#endif
|
||||
#include "pico/time.h"
|
||||
#include "pico/runtime_init.h"
|
||||
|
||||
#if LIB_PICO_PRINTF_PICO
|
||||
#include "pico/printf.h"
|
||||
#else
|
||||
#define weak_raw_printf printf
|
||||
#define weak_raw_vprintf vprintf
|
||||
#endif
|
||||
#if LIB_PICO_STDIO
|
||||
#include "pico/stdio.h"
|
||||
#endif
|
||||
|
||||
#if PICO_ENTER_USB_BOOT_ON_EXIT
|
||||
#include "pico/bootrom.h"
|
||||
#endif
|
||||
|
||||
extern char __StackLimit; /* Set by linker. */
|
||||
|
||||
#define STDIO_HANDLE_STDIN 0
|
||||
#define STDIO_HANDLE_STDOUT 1
|
||||
#define STDIO_HANDLE_STDERR 2
|
||||
|
||||
void __attribute__((noreturn)) __weak _exit(__unused int status) {
|
||||
#if PICO_ENTER_USB_BOOT_ON_EXIT
|
||||
reset_usb_boot(0, 0);
|
||||
#else
|
||||
while (1) {
|
||||
__breakpoint();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__weak void *_sbrk(int incr) {
|
||||
extern char end; /* Set by linker. */
|
||||
static char *heap_end;
|
||||
char *prev_heap_end;
|
||||
|
||||
if (heap_end == 0) {
|
||||
heap_end = &end;
|
||||
}
|
||||
|
||||
prev_heap_end = heap_end;
|
||||
char *next_heap_end = heap_end + incr;
|
||||
|
||||
if (__builtin_expect(next_heap_end > (&__StackLimit), false)) {
|
||||
#if PICO_USE_OPTIMISTIC_SBRK
|
||||
if (heap_end == &__StackLimit) {
|
||||
// errno = ENOMEM;
|
||||
return (char *) -1;
|
||||
}
|
||||
next_heap_end = &__StackLimit;
|
||||
#else
|
||||
return (char *) -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
heap_end = next_heap_end;
|
||||
return (void *) prev_heap_end;
|
||||
}
|
||||
#if 0
|
||||
static int64_t epoch_time_us_since_boot;
|
||||
|
||||
__weak int _gettimeofday(struct timeval *__restrict tv, __unused void *__restrict tz) {
|
||||
if (tv) {
|
||||
int64_t us_since_epoch = ((int64_t)to_us_since_boot(get_absolute_time())) - epoch_time_us_since_boot;
|
||||
tv->tv_sec = (time_t)(us_since_epoch / 1000000);
|
||||
tv->tv_usec = (suseconds_t)(us_since_epoch % 1000000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int settimeofday(__unused const struct timeval *tv, __unused const struct timezone *tz) {
|
||||
if (tv) {
|
||||
int64_t us_since_epoch = tv->tv_sec * 1000000 + tv->tv_usec;
|
||||
epoch_time_us_since_boot = (int64_t)to_us_since_boot(get_absolute_time()) - us_since_epoch;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int _times(struct tms *tms) {
|
||||
#if CLOCKS_PER_SEC >= 1000000
|
||||
tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) * (CLOCKS_PER_SEC / 1000000));
|
||||
#else
|
||||
tms->tms_utime = (clock_t)(to_us_since_boot(get_absolute_time()) / (1000000 / CLOCKS_PER_SEC));
|
||||
#endif
|
||||
tms->tms_stime = 0;
|
||||
tms->tms_cutime = 0;
|
||||
tms->tms_cstime = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak pid_t _getpid(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int _kill(__unused pid_t pid, __unused int sig) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _read(int handle, char *buffer, int length) {
|
||||
#if LIB_PICO_STDIO
|
||||
if (handle == STDIO_HANDLE_STDIN) {
|
||||
return stdio_get_until(buffer, length, at_the_end_of_time);
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _write(int handle, char *buffer, int length) {
|
||||
#if LIB_PICO_STDIO
|
||||
if (handle == STDIO_HANDLE_STDOUT || handle == STDIO_HANDLE_STDERR) {
|
||||
stdio_put_string(buffer, length, false, true);
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _open(__unused const char *fn, __unused int oflag, ...) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _close(__unused int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t __attribute__((weak)) _lseek(__unused int fd, __unused off_t pos, __unused int whence) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _fstat(__unused int fd, __unused struct stat *buf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __attribute__((weak)) _isatty(int fd) {
|
||||
return fd == STDIO_HANDLE_STDIN || fd == STDIO_HANDLE_STDOUT || fd == STDIO_HANDLE_STDERR;
|
||||
}
|
||||
|
||||
// exit is not useful... no desire to pull in __call_exitprocs
|
||||
void exit(int status) {
|
||||
_exit(status);
|
||||
}
|
||||
|
||||
// incorrect warning from GCC 6
|
||||
GCC_Pragma("GCC diagnostic push")
|
||||
GCC_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
|
||||
void __weak __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
|
||||
weak_raw_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
|
||||
failedexpr, file, line, func ? ", function: " : "",
|
||||
func ? func : "");
|
||||
|
||||
_exit(1);
|
||||
}
|
||||
GCC_Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
void runtime_init(void) {
|
||||
#ifndef NDEBUG
|
||||
if (__get_current_exception()) {
|
||||
// crap; started in exception handler
|
||||
__breakpoint();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !PICO_RUNTIME_SKIP_INIT_PER_CORE_INSTALL_STACK_GUARD
|
||||
// install core0 stack guard
|
||||
extern char __StackBottom;
|
||||
runtime_init_per_core_install_stack_guard(&__StackBottom);
|
||||
#endif
|
||||
|
||||
// todo maybe we want to do this in the future, but it does stuff like register_tm_clones
|
||||
// which we didn't do in previous SDKs
|
||||
//extern void __libc_init_array(void);
|
||||
//__libc_init_array();
|
||||
|
||||
// ... so instead just do the __preinit_array
|
||||
runtime_run_initializers();
|
||||
// ... and the __init_array
|
||||
extern void (*__init_array_start)(void);
|
||||
extern void (*__init_array_end)(void);
|
||||
for (void (**p)(void) = &__init_array_start; p < &__init_array_end; ++p) {
|
||||
(*p)();
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
Expost absolute mouse HID descriptor and report
|
||||
Taken from @tobozo PR https://github.com/hathach/tinyusb/pull/1363
|
||||
TODO - remove once that PR merged with TinyUSB
|
||||
|
||||
Copyright (c) 2023 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "class/hid/hid_device.h"
|
||||
|
||||
// Absolute Mouse: same as the Standard (relative) Mouse Report but
|
||||
// with int16_t instead of int8_t for X and Y coordinates.
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
|
||||
int16_t x; /**< Current x position of the mouse. */
|
||||
int16_t y; /**< Current y position of the mouse. */
|
||||
int8_t wheel; /**< Current delta wheel movement on the mouse. */
|
||||
int8_t pan; // using AC Pan
|
||||
} hid_abs_mouse_report_t;
|
||||
|
||||
|
||||
// Absolute Mouse Report Descriptor Template
|
||||
#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
|
||||
HID_USAGE_MIN ( 1 ) ,\
|
||||
HID_USAGE_MAX ( 5 ) ,\
|
||||
HID_LOGICAL_MIN ( 0 ) ,\
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
/* Left, Right, Middle, Backward, Forward buttons */ \
|
||||
HID_REPORT_COUNT( 5 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 3 bit padding */ \
|
||||
HID_REPORT_COUNT( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 3 ) ,\
|
||||
HID_INPUT ( HID_CONSTANT ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
/* X, Y absolute position [0, 32767] */ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
|
||||
HID_LOGICAL_MIN ( 0x00 ) ,\
|
||||
HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\
|
||||
HID_REPORT_SIZE ( 16 ) ,\
|
||||
HID_REPORT_COUNT ( 2 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* Vertical wheel scroll [-127, 127] */ \
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
|
||||
HID_LOGICAL_MIN ( 0x81 ) ,\
|
||||
HID_LOGICAL_MAX ( 0x7f ) ,\
|
||||
HID_REPORT_COUNT( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 8 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \
|
||||
/* Horizontal wheel scroll [-127, 127] */ \
|
||||
HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \
|
||||
HID_LOGICAL_MIN ( 0x81 ), \
|
||||
HID_LOGICAL_MAX ( 0x7f ), \
|
||||
HID_REPORT_COUNT( 1 ), \
|
||||
HID_REPORT_SIZE ( 8 ), \
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \
|
||||
HID_COLLECTION_END , \
|
||||
HID_COLLECTION_END \
|
||||
|
||||
|
||||
static inline bool tud_hid_abs_mouse_report(uint8_t report_id,
|
||||
uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
|
||||
hid_abs_mouse_report_t report = {
|
||||
.buttons = buttons,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
};
|
||||
|
||||
return tud_hid_n_report(0, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
16-bit axis gamepad definition
|
||||
Copyright (c) 2024 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "class/hid/hid_device.h"
|
||||
|
||||
#define TUD_HID_REPORT_DESC_GAMEPAD16(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
/* 16 bit X, Y, Z, Rz, Rx, Ry (min -32767, max 32767 ) */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\
|
||||
HID_LOGICAL_MIN_N ( -32767, 2 ) ,\
|
||||
HID_LOGICAL_MAX_N ( 32767, 2 ) ,\
|
||||
HID_REPORT_COUNT ( 6 ) ,\
|
||||
HID_REPORT_SIZE ( 16 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 8 bit DPad/Hat Button Map */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\
|
||||
HID_LOGICAL_MIN ( 1 ) ,\
|
||||
HID_LOGICAL_MAX ( 8 ) ,\
|
||||
HID_PHYSICAL_MIN ( 0 ) ,\
|
||||
HID_PHYSICAL_MAX_N ( 315, 2 ) ,\
|
||||
HID_REPORT_COUNT ( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 8 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
/* 32 bit Button Map */ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
|
||||
HID_USAGE_MIN ( 1 ) ,\
|
||||
HID_USAGE_MAX ( 32 ) ,\
|
||||
HID_LOGICAL_MIN ( 0 ) ,\
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
HID_REPORT_COUNT ( 32 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
HID_COLLECTION_END \
|
||||
|
||||
// HID Gamepad Protocol Report.
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
int16_t x; ///< Delta x movement of left analog-stick
|
||||
int16_t y; ///< Delta y movement of left analog-stick
|
||||
int16_t z; ///< Delta z movement of right analog-joystick
|
||||
int16_t rz; ///< Delta Rz movement of right analog-joystick
|
||||
int16_t rx; ///< Delta Rx movement of analog left trigger
|
||||
int16_t ry; ///< Delta Ry movement of analog right trigger
|
||||
uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat
|
||||
uint32_t buttons; ///< Buttons mask for currently pressed buttons
|
||||
} hid_gamepad16_report_t;
|
||||
@@ -2,6 +2,8 @@
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
@@ -12,6 +14,7 @@
|
||||
|
||||
#define tone2_wrap_target 0
|
||||
#define tone2_wrap 8
|
||||
#define tone2_pio_version 0
|
||||
|
||||
static const uint16_t tone2_program_instructions[] = {
|
||||
// .wrap_target
|
||||
@@ -32,6 +35,10 @@ static const struct pio_program tone2_program = {
|
||||
.instructions = tone2_program_instructions,
|
||||
.length = 9,
|
||||
.origin = -1,
|
||||
.pio_version = 0,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
.used_gpio_ranges = 0x0
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline pio_sm_config tone2_program_get_default_config(uint offset) {
|
||||
|
||||
@@ -30,7 +30,7 @@ void __clearADCPin(pin_size_t p);
|
||||
|
||||
static uint32_t analogScale = 255;
|
||||
static uint32_t analogFreq = 1000;
|
||||
static uint32_t pwmInitted = 0;
|
||||
static uint64_t pwmInitted = 0;
|
||||
static bool scaleInitted = false;
|
||||
static bool adcInitted = false;
|
||||
static uint16_t analogWritePseudoScale = 1;
|
||||
@@ -79,7 +79,7 @@ extern "C" void analogWriteResolution(int res) {
|
||||
extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
CoreMutex m(&_dacMutex);
|
||||
|
||||
if ((pin > 29) || !m) {
|
||||
if ((pin >= __GPIOCNT) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
@@ -101,12 +101,12 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
}
|
||||
scaleInitted = true;
|
||||
}
|
||||
if (!(pwmInitted & (1 << pwm_gpio_to_slice_num(pin)))) {
|
||||
if (!(pwmInitted & (1LL << pwm_gpio_to_slice_num(pin)))) {
|
||||
pwm_config c = pwm_get_default_config();
|
||||
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq));
|
||||
pwm_config_set_wrap(&c, analogScale - 1);
|
||||
pwm_init(pwm_gpio_to_slice_num(pin), &c, true);
|
||||
pwmInitted |= 1 << pwm_gpio_to_slice_num(pin);
|
||||
pwmInitted |= 1LL << pwm_gpio_to_slice_num(pin);
|
||||
}
|
||||
|
||||
val <<= analogWritePseudoScale;
|
||||
@@ -125,17 +125,17 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
auto_init_mutex(_adcMutex);
|
||||
static uint8_t _readBits = 10;
|
||||
static uint8_t _lastADCMux = 0;
|
||||
static uint32_t _adcGPIOInit = 0;
|
||||
static uint64_t _adcGPIOInit = 0;
|
||||
|
||||
void __clearADCPin(pin_size_t p) {
|
||||
_adcGPIOInit &= ~(1 << p);
|
||||
_adcGPIOInit &= ~(1LL << p);
|
||||
}
|
||||
|
||||
extern "C" int analogRead(pin_size_t pin) {
|
||||
CoreMutex m(&_adcMutex);
|
||||
|
||||
pin_size_t maxPin = max(A0, A3);
|
||||
pin_size_t minPin = min(A0, A3);
|
||||
pin_size_t maxPin = __GPIOCNT;
|
||||
pin_size_t minPin = __FIRSTANALOGGPIO;
|
||||
|
||||
if ((pin < minPin) || (pin > maxPin) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal analogRead pin (%d)\n", pin);
|
||||
@@ -145,9 +145,9 @@ extern "C" int analogRead(pin_size_t pin) {
|
||||
adc_init();
|
||||
adcInitted = true;
|
||||
}
|
||||
if (!(_adcGPIOInit & (1 << pin))) {
|
||||
if (!(_adcGPIOInit & (1LL << pin))) {
|
||||
adc_gpio_init(pin);
|
||||
_adcGPIOInit |= 1 << pin;
|
||||
_adcGPIOInit |= 1LL << pin;
|
||||
}
|
||||
if (_lastADCMux != pin) {
|
||||
adc_select_input(pin - minPin);
|
||||
@@ -169,7 +169,7 @@ extern "C" float analogReadTemp(float vref) {
|
||||
_lastADCMux = 0;
|
||||
adc_set_temp_sensor_enabled(true);
|
||||
delay(1); // Allow things to settle. Without this, readings can be erratic
|
||||
adc_select_input(4); // Temperature sensor
|
||||
adc_select_input(__GPIOCNT - __FIRSTANALOGGPIO); // Temperature sensor
|
||||
int v = adc_read();
|
||||
adc_set_temp_sensor_enabled(false);
|
||||
float t = 27.0f - ((v * vref / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet
|
||||
|
||||
@@ -23,10 +23,15 @@
|
||||
|
||||
extern void __clearADCPin(pin_size_t p);
|
||||
|
||||
static PinMode _pm[30];
|
||||
static PinMode _pm[__GPIOCNT];
|
||||
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode")));
|
||||
extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
if (ulPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ulMode) {
|
||||
case INPUT:
|
||||
gpio_init(ulPin);
|
||||
@@ -72,20 +77,16 @@ extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
}
|
||||
_pm[ulPin] = ulMode;
|
||||
|
||||
if ((ulPin >= std::min(A0, A3)) && (ulPin <= std::max(A0, A3))) {
|
||||
if (ulPin >= __FIRSTANALOGGPIO) {
|
||||
__clearADCPin(ulPin);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) __attribute__((weak, alias("__digitalWrite")));
|
||||
extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
if (ulPin > 29) {
|
||||
if (ulPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
}
|
||||
@@ -109,7 +110,7 @@ extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) __attribute__((weak, alias("__digitalRead")));
|
||||
extern "C" PinStatus __digitalRead(pin_size_t ulPin) {
|
||||
if (ulPin > 29) {
|
||||
if (ulPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal pin in digitalRead (%d)\n", ulPin);
|
||||
return LOW;
|
||||
}
|
||||
|
||||
@@ -23,29 +23,40 @@
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <map>
|
||||
#include "_freertos.h"
|
||||
|
||||
|
||||
// Support nested IRQ disable/re-enable
|
||||
#ifndef maxIRQs
|
||||
#define maxIRQs 15
|
||||
#endif
|
||||
static uint32_t _irqStackTop[2] = { 0, 0 };
|
||||
static uint32_t _irqStack[2][maxIRQs];
|
||||
|
||||
extern "C" void interrupts() {
|
||||
auto core = get_core_num();
|
||||
if (!_irqStackTop[core]) {
|
||||
// ERROR
|
||||
return;
|
||||
if (__freeRTOSinitted) {
|
||||
__freertos_task_exit_critical();
|
||||
} else {
|
||||
auto core = get_core_num();
|
||||
if (!_irqStackTop[core]) {
|
||||
// ERROR
|
||||
return;
|
||||
}
|
||||
restore_interrupts(_irqStack[core][--_irqStackTop[core]]);
|
||||
}
|
||||
restore_interrupts(_irqStack[core][--_irqStackTop[core]]);
|
||||
}
|
||||
|
||||
extern "C" void noInterrupts() {
|
||||
auto core = get_core_num();
|
||||
if (_irqStackTop[core] == maxIRQs) {
|
||||
// ERROR
|
||||
panic("IRQ stack overflow");
|
||||
if (__freeRTOSinitted) {
|
||||
__freertos_task_enter_critical();
|
||||
} else {
|
||||
auto core = get_core_num();
|
||||
if (_irqStackTop[core] == maxIRQs) {
|
||||
// ERROR
|
||||
panic("IRQ stack overflow");
|
||||
}
|
||||
_irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
_irqStack[core][_irqStackTop[core]++] = save_and_disable_interrupts();
|
||||
}
|
||||
|
||||
// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeo
|
||||
uint64_t start = time_us_64();
|
||||
uint64_t abort = start + timeout;
|
||||
|
||||
if (pin > 29) {
|
||||
if (pin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pulseIn (%d)\n", pin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
extern "C" uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder) {
|
||||
uint8_t value = 0;
|
||||
uint8_t i;
|
||||
if (dataPin > 29) {
|
||||
if (dataPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal dataPin in shiftIn (%d)\n", dataPin);
|
||||
return 0;
|
||||
}
|
||||
if (clockPin > 29) {
|
||||
if (clockPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal clockPin in shiftIn (%d)\n", clockPin);
|
||||
return 0;
|
||||
}
|
||||
@@ -46,11 +46,11 @@ extern "C" uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bit
|
||||
|
||||
extern "C" void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val) {
|
||||
uint8_t i;
|
||||
if (dataPin > 29) {
|
||||
if (dataPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal dataPin in shiftOut (%d)\n", dataPin);
|
||||
return;
|
||||
}
|
||||
if (clockPin > 29) {
|
||||
if (clockPin >= __GPIOCNT) {
|
||||
DEBUGCORE("ERROR: Illegal clockPin in shiftOut (%d)\n", clockPin);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ Valid values for min and max are `BR_TLS10`, `BR_TLS11`, `BR_TLS12`. Min and ma
|
||||
|
||||
|
||||
ESP32 Compatibility
|
||||
===================
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Simple ESP32 ``WiFiClientSecure`` compatibility is built-in, allow for some sketches to run without any modification.
|
||||
The following methods are implemented:
|
||||
|
||||
|
||||
+20
-20
@@ -1,21 +1,21 @@
|
||||
BOOTSEL Button
|
||||
==============
|
||||
|
||||
The BOOTSEL button on the Pico is not connected to a standard GPIO, so
|
||||
it cannot be read using the usual ``digitalRead`` function. It **can**,
|
||||
however, be read using a special (relatively slow) method.
|
||||
|
||||
The ``BOOTSEL`` object implements a simple way of reading the BOOTSEL
|
||||
button. Simply use the object ``BOOTSEL`` as a boolean (as a conditional
|
||||
in an ``if`` or ``while``, or assigning to a ``bool``):
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
// Print "BEEP" if the BOOTSEL button is pressed
|
||||
if (BOOTSEL) {
|
||||
Serial.println("BEEP!");
|
||||
// Wait until BOOTSEL is released
|
||||
while (BOOTSEL) {
|
||||
delay(1);
|
||||
}
|
||||
BOOTSEL Button
|
||||
==============
|
||||
|
||||
The BOOTSEL button on the Pico is not connected to a standard GPIO, so
|
||||
it cannot be read using the usual ``digitalRead`` function. It **can**,
|
||||
however, be read using a special (relatively slow) method.
|
||||
|
||||
The ``BOOTSEL`` object implements a simple way of reading the BOOTSEL
|
||||
button. Simply use the object ``BOOTSEL`` as a boolean (as a conditional
|
||||
in an ``if`` or ``while``, or assigning to a ``bool``):
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
// Print "BEEP" if the BOOTSEL button is pressed
|
||||
if (BOOTSEL) {
|
||||
Serial.println("BEEP!");
|
||||
// Wait until BOOTSEL is released
|
||||
while (BOOTSEL) {
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'3.9.4'
|
||||
version = u'4.0.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'3.9.4'
|
||||
release = u'4.0.3'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -89,6 +89,43 @@ code that only runs on this core, use the following define.
|
||||
~~~ your changes ~~~
|
||||
#endif
|
||||
|
||||
Identifying RP2040, RP2530A, or RP2350B
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To check if a board is an original RP2040
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(PICO_RP2040)
|
||||
...OG Pico code...
|
||||
#endif
|
||||
|
||||
For RP2350(A or B):
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(PICO_RP2350)
|
||||
...Pico 2 code...
|
||||
#endif
|
||||
|
||||
For only RP2350A variants (using the compile options, not the onboard ID register):
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(PICO_RP2350) && !defined(PICO_RP2350B)
|
||||
...RP2350A only code...
|
||||
#endif
|
||||
|
||||
For only RP2350B variants (again, at compile time as identified by the selected board
|
||||
and not the chip ID register):
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#if defined(PICO_RP2350B)
|
||||
...48-GPIO version code here
|
||||
#endif
|
||||
|
||||
|
||||
Library Architectures
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -98,3 +135,4 @@ not know your new code is compatible here.
|
||||
|
||||
Add ``rp2040`` to ``architectures`` (in ``library.properties``) and
|
||||
``"rp2040"`` to ``platforms[]`` (in ``library.json``) to let the tools know.
|
||||
Note that even the RP2350 is identified as ``rp2040`` for this purpose.
|
||||
|
||||
@@ -6,6 +6,10 @@ Board-Specific Pins
|
||||
The Raspberry Pi Pico RP2040 chip supports up to 30 digital I/O pins,
|
||||
however not all boards provide access to all pins.
|
||||
|
||||
Pin Notation
|
||||
------------
|
||||
When using Analog or Digital I/Os, if you supply an integer it specifies the RP2040 GPIO pin to use. Using Dx or Ax notation (for example, D4 or A3) may be necessary on boards without a direct PCB pin to GPIO mapping.
|
||||
|
||||
Input Modes
|
||||
-----------
|
||||
The Raspberry Pi Pico has 3 Input modes settings for use with `pinMode`: `INPUT`, `INPUT_PULLUP` and `INPUT_PULLDOWN`
|
||||
|
||||
+51
-22
@@ -92,8 +92,9 @@ LittleFS File System Limitations
|
||||
--------------------------------
|
||||
|
||||
The LittleFS implementation for the RP2040 supports filenames of up
|
||||
to 31 characters + terminating zero (i.e. ``char filename[32]``), and
|
||||
as many subdirectories as space permits.
|
||||
to 254 characters + terminating zero (i.e. ``char filename[255]`` or
|
||||
better ``char filename[LFS_NAME_MAX]`` ), and as many subdirectories
|
||||
as space permits.
|
||||
|
||||
Filenames are assumed to be in the root directory if no initial "/" is
|
||||
present.
|
||||
@@ -151,6 +152,48 @@ second SPI port, ``SPI1``. Just use the following call in place of
|
||||
SD.begin(cspin, SPI1);
|
||||
|
||||
|
||||
Using VFS (Virtual File System) for POSIX support
|
||||
-------------------------------------------------
|
||||
The ``VFS`` library enables sketches to use standard POSIX file I/O operations using
|
||||
standard ``FILE *`` operations. Include the ``VFS`` library in your application and
|
||||
add a call to map the ``VFS.root()`` to your filesystem. I.e.:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <VFS.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
void setup() {
|
||||
LittleFS.begin();
|
||||
VFS.root(LittleFS);
|
||||
FILE *fp = fopen("/thisfilelivesonflash.txt", "w");
|
||||
fprintf(fp, "Hello!\n");
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
Multiple filesystems can be ``VFS.map()`` into the VFS namespace under different directory
|
||||
names. For example, the following will make files on ``/sd`` reside on an external\
|
||||
SD card and files on ``/lfs`` live in internal flash.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <VFS.h>
|
||||
#include <LittleFS.h>
|
||||
#include <SDFS.h>
|
||||
|
||||
void setup() {
|
||||
LittleFS.begin();
|
||||
SDFS.begin();
|
||||
VFS.map("/lfs", LittleFS);
|
||||
VFS.map("/sd", SDFS);
|
||||
FILE *onSD = fopen("/sd/thislivesonsd.txt", "wb");
|
||||
....
|
||||
}
|
||||
|
||||
See the examples in the ``VFS`` library for more information.
|
||||
|
||||
|
||||
|
||||
File system object (LittleFS/SD/SDFS/FatFS)
|
||||
-------------------------------------------
|
||||
|
||||
@@ -330,8 +373,8 @@ rename
|
||||
Renames file from ``pathFrom`` to ``pathTo``. Paths must be absolute.
|
||||
Returns *true* if file was renamed successfully.
|
||||
|
||||
info **DEPRECATED**
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
info
|
||||
~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
@@ -340,9 +383,8 @@ info **DEPRECATED**
|
||||
|
||||
Fills `FSInfo structure <#filesystem-information-structure>`__ with
|
||||
information about the file system. Returns ``true`` if successful,
|
||||
``false`` otherwise. Because this cannot report information about
|
||||
filesystemd greater than 4MB, don't use it in new code. Use ``info64``
|
||||
instead which uses 64-bit fields for filesystem sizes.
|
||||
``false`` otherwise. ``ìnfo()`` has been updated to support filesystems
|
||||
greater than 4GB and ``FSInfo64`` and ``info64()`` have been discarded.
|
||||
|
||||
Filesystem information structure
|
||||
--------------------------------
|
||||
@@ -350,8 +392,8 @@ Filesystem information structure
|
||||
.. code:: cpp
|
||||
|
||||
struct FSInfo {
|
||||
size_t totalBytes;
|
||||
size_t usedBytes;
|
||||
uint64_t totalBytes;
|
||||
uint64_t usedBytes;
|
||||
size_t blockSize;
|
||||
size_t pageSize;
|
||||
size_t maxOpenFiles;
|
||||
@@ -366,19 +408,6 @@ block size - ``pageSize`` — filesystem logical page size - ``maxOpenFiles``
|
||||
``maxPathLength`` — max file name length (including one byte for zero
|
||||
termination)
|
||||
|
||||
info64
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
FSInfo64 fsinfo;
|
||||
SDFS.info64(fsinfo);
|
||||
or LittleFS.info64(fsinfo);
|
||||
|
||||
Performs the same operation as ``info`` but allows for reporting greater than
|
||||
4GB for filesystem size/used/etc. Should be used with the SD and SDFS
|
||||
filesystems since most SD cards today are greater than 4GB in size.
|
||||
|
||||
setTimeCallback(time_t (\*cb)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
+10
-6
@@ -2,12 +2,12 @@ Arduino-Pico
|
||||
============
|
||||
|
||||
This is the documentation for the Raspberry Pi Pico Arduino core,
|
||||
Arduino-Pico. Arduino-Pico is a community port of the RP2040
|
||||
(Raspberry Pi Pico processor) to the Arduino ecosystem, intended
|
||||
to make it easier and more fun to use and program the Raspberry Pi
|
||||
Pico / RP2040 based boards.
|
||||
Arduino-Pico. Arduino-Pico is a community port of Arduino to the
|
||||
RP2040 (Raspberry Pi Pico processor) and RP2350 (Raspberry Pi Pico 2
|
||||
processor), intended to make it easier and more fun to use and
|
||||
program the Raspberry Pi Pico / RP2040 / RP2350 based boards.
|
||||
|
||||
This Arduino core uses a custom toolset with GCC 10.3 and Newlib 4.0.0
|
||||
This Arduino core uses a custom toolset with GCC 12.3 and Newlib 4.0.0
|
||||
and doesn't require any system-installed prerequisites.
|
||||
|
||||
For the latest version, always check https://github.com/earlephilhower/arduino-pico
|
||||
@@ -26,7 +26,7 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
||||
|
||||
Pin (Re)Assignment <pins>
|
||||
|
||||
RP2040 Helper <rp2040>
|
||||
RP2040/RP2350 Helper <rp2040>
|
||||
|
||||
Analog I/O <analog>
|
||||
Digital I/O <digital>
|
||||
@@ -44,6 +44,9 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
||||
USB (Arduino and Adafruit_TinyUSB) <usb>
|
||||
Multicore Processing <multicore>
|
||||
|
||||
RP2350 Specific Notes <rp2350>
|
||||
RP2350 PSRAM <psram>
|
||||
|
||||
Bluetooth <bluetooth>
|
||||
Bluetooth HID Master <hidmaster>
|
||||
Bluetooth Audio (A2DP) <a2dp>
|
||||
@@ -70,4 +73,5 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
||||
Ported/Optimized Libraries <libraries>
|
||||
Using Pico-SDK <sdk>
|
||||
|
||||
|
||||
Licenses <license>
|
||||
|
||||
+6
-10
@@ -184,11 +184,9 @@ The first line creates a file with the USB vendor and ID of the Picoprobe and te
|
||||
|
||||
Once Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.
|
||||
|
||||
Uploading Sketches with pico-debug
|
||||
----------------------------------
|
||||
pico-debug differs from Picoprobe in that pico-debug is a virtual debug pod that runs side-by-side on the same RP2040 that you run your code on; so, you only need one RP2040 board instead of two. pico-debug also differs from Picoprobe in that pico-debug is standards-based; it uses the CMSIS-DAP protocol, which means even software not specially written for the Raspberry Pi Pico can support it. pico-debug uses OpenOCD to handle your sketch uploads, and debugging can be accomplished with CMSIS-DAP capable debuggers including GDB.
|
||||
|
||||
Under Windows and macOS, any user should be able to access pico-debug automatically, but under Linux `udev` must be told about the device and to allow normal users access.
|
||||
Uploading Sketches with OpenOCD
|
||||
-------------------------------
|
||||
Under Windows and macOS, any user should be able to access OpenOCD automatically, but under Linux `udev` must be told about the device and to allow normal users access.
|
||||
|
||||
To set up user-level access to all CMSIS-DAP adapters on Ubuntu (and other OSes which use `udev`):
|
||||
|
||||
@@ -199,10 +197,8 @@ To set up user-level access to all CMSIS-DAP adapters on Ubuntu (and other OSes
|
||||
|
||||
The first line creates a file that recognizes all CMSIS-DAP adapters and tells UDEV to give users full access to it. The second causes `udev` to load this new rule. Note that you will need to unplug and re-plug in your device the first time you create this file, to allow udev to make the device node properly.
|
||||
|
||||
Once CMSIS-DAP permissions are set up properly, then select the board "Raspberry Pi Pico (pico-debug)" in the Tools menu.
|
||||
Once CMSIS-DAP permissions are set up properly, then select the Upload Method "Picoprobe/Debugprobe (CMSIS-DAP)" in the Tools menu.
|
||||
|
||||
When first connecting the USB port to your PC, you must copy pico-debug-gimmecache.uf2 to the Pi Pico to load pico-debug into RAM; after this, upload as normal.
|
||||
|
||||
Debugging with Picoprobe/pico-debug, OpenOCD, and GDB
|
||||
Debugging with Picoprobe/Debugprobe, OpenOCD, and GDB
|
||||
-----------------------------------------------------
|
||||
The installed tools include a version of OpenOCD (in the pqt-openocd directory) and GDB (in the pqt-gcc directory). These may be used to run GDB in an interactive window as documented in the Pico Getting Started manuals from the Raspberry Pi Foundation. For pico-debug, replace the raspberrypi-swd and picoprobe example OpenOCD arguments of "-f interface/raspberrypi-swd.cfg -f target/rp2040.cfg" or "-f interface/picoprobe.cfg -f target/rp2040.cfg" respectively in the Pico Getting Started manual with "-f board/pico-debug.cfg".
|
||||
The installed tools include a version of OpenOCD (in the pqt-openocd directory) and GDB (in the pqt-gcc directory). These may be used to run GDB in an interactive window as documented in the Pico Getting Started manuals from the Raspberry Pi Foundation.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
OTA Updates
|
||||
===========
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
|
||||
+6
-1
@@ -23,6 +23,12 @@ For example, to make a transmit-only port on GP16
|
||||
For detailed information about the Serial ports, see the
|
||||
Arduino `Serial Reference <https://www.arduino.cc/reference/en/language/functions/communication/serial/>`_ .
|
||||
|
||||
Inversion
|
||||
---------
|
||||
|
||||
``SoftwareSerial`` and ``SerialPIO`` can both support inverted input and/or outputs via the methods
|
||||
``setInvertRX(bool invert)`` and ``setInvertTX(bool invert)``.
|
||||
|
||||
|
||||
SoftwareSerial Emulation
|
||||
========================
|
||||
@@ -31,7 +37,6 @@ with the Arduino `Software Serial <https://docs.arduino.cc/learn/built-in-librar
|
||||
library. Use the normal ``#include <SoftwareSerial.h>`` to include it. The following
|
||||
differences from the Arduino standard are present:
|
||||
|
||||
* Inverted mode is not supported
|
||||
* All ports are always listening
|
||||
* ``listen`` call is a no-op
|
||||
* ``isListening()`` always returns ``true``
|
||||
|
||||
+380
-400
@@ -1,400 +1,380 @@
|
||||
Using this core with PlatformIO
|
||||
===============================
|
||||
|
||||
What is PlatformIO?
|
||||
-------------------
|
||||
|
||||
`PlatformIO <https://platformio.org/>`__ is a free, open-source build-tool written in Python, which also integrates into VSCode code as an extension.
|
||||
|
||||
PlatformIO significantly simplifies writing embedded software by offering a unified build system, yet being able to create project files for many different IDEs, including VSCode, Eclipse, CLion, etc.
|
||||
Through this, PlatformIO can offer extensive features such as IntelliSense (autocomplete), debugging, unit testing etc., which not available in the standard Arduino IDE.
|
||||
|
||||
The Arduino IDE experience:
|
||||
|
||||
.. image:: images/the_arduinoide_experience.png
|
||||
|
||||
The PlatformIO experience:
|
||||
|
||||
.. image:: images/the_platformio_experience.png
|
||||
|
||||
Refer to the general documentation at https://docs.platformio.org/.
|
||||
|
||||
Especially useful is the `Getting started with VSCode + PlatformIO <https://docs.platformio.org/en/latest/integration/ide/vscode.html#installation>`_, `CLI reference <https://docs.platformio.org/en/latest/core/index.html>`_ and the `platformio.ini options <https://docs.platformio.org/en/latest/projectconf/index.html>`_ page.
|
||||
|
||||
Hereafter it is assumed that you have a basic understanding of PlatformIO in regards to project creation, project file structure and building and uploading PlatformIO projects, through reading the above pages.
|
||||
|
||||
Important steps for Windows users, before installing
|
||||
----------------------------------------------------
|
||||
|
||||
By default, Windows has a limited path length that is not long enough to fully clone the ``Pico-SDK``'s ``tinyusb`` repository, resulting in error messages like the one below while attempting to fetch the repository.
|
||||
|
||||
.. code::
|
||||
|
||||
error: unable to create file '.....' : Filename too long
|
||||
|
||||
To work around this requires performing two steps and rebooting Windows once. These steps will enable longer file paths at the Windows OS and the ``git`` level.
|
||||
|
||||
Step 1: Enabling long paths in git
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Open up a Windows ``cmd`` or ``terminal`` window and execute the following command
|
||||
|
||||
.. code::
|
||||
|
||||
git config --system core.longpaths true
|
||||
|
||||
Step 2: Enabling long paths in the Windows OS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
(taken from https://www.microfocus.com/documentation/filr/filr-4/filr-desktop/t47bx2ogpfz7.html)
|
||||
|
||||
1. Click Window key and type gpedit.msc, then press the Enter key. This launches the Local Group Policy Editor.
|
||||
|
||||
2. Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem.
|
||||
|
||||
3. Double click Enable NTFS/Win32 long paths and close the dialog.
|
||||
|
||||
.. image:: images/longpath.png
|
||||
|
||||
|
||||
Step 3: Reboot the computer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once the two prior stages are complete, please do a full reboot or power cycle so that the new settings will take effect.
|
||||
|
||||
|
||||
Current state of development
|
||||
----------------------------
|
||||
|
||||
At the time of writing, PlatformIO integration for this core is a work-in-progress and not yet merged into mainline PlatformIO. This is subject to change once `this pull request <https://github.com/platformio/platform-raspberrypi/pull/36>`_ is merged.
|
||||
|
||||
If you want to use the PlatformIO integration right now, make sure you first create a standard Raspberry Pi Pico + Arduino project within PlatformIO.
|
||||
This will give you a project with the ``platformio.ini``
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = raspberrypi
|
||||
board = pico
|
||||
framework = arduino
|
||||
|
||||
Here, you need to change the `platform` to take advantage of the features described hereunder and switch to the new core.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
board_build.core = earlephilhower
|
||||
|
||||
When the support for this core has been merged into mainline PlatformIO, this notice will be removed and a standard `platformio.ini` as shown above will work as a base.
|
||||
|
||||
Deprecation warnings
|
||||
---------------------
|
||||
|
||||
Previous versions of this documentation told users to inject the framework and toolchain package into the project by using
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; note that download link for toolchain is specific for OS. see https://github.com/earlephilhower/pico-quick-toolchain/releases.
|
||||
platform_packages =
|
||||
maxgerhardt/framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git
|
||||
maxgerhardt/toolchain-pico@https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.1-a/x86_64-w64-mingw32.arm-none-eabi-7855b0c.210706.zip
|
||||
|
||||
This is now **deprecated** and should not be done anymore. Users should delete these ``platform_packages`` lines and update the platform integration by issuing the command
|
||||
|
||||
.. code:: bash
|
||||
|
||||
pio pkg update -g -p https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
|
||||
in the `PlatformIO CLI <https://docs.platformio.org/en/latest/integration/ide/vscode.html#platformio-core-cli>`_. The same can be achieved by using the VSCode PIO Home -> Platforms -> Updates GUI.
|
||||
|
||||
The toolchain, which was also renamed to ``toolchain-rp2040-earlephilhower`` is downloaded automatically from the registry. The same goes for the ``framework-arduinopico`` toolchain package, which points directly to the Arduino-Pico Github repository.
|
||||
However, users can still select a custom fork or branch of the core if desired so, as detailed in a chapter below.
|
||||
|
||||
Selecting the new core
|
||||
----------------------
|
||||
|
||||
Prerequisite for using this core is to tell PlatformIO to switch to it.
|
||||
There will be board definition files where the Earle-Philhower core will
|
||||
be the default since it's a board that only exists in this core (and not
|
||||
the other https://github.com/arduino/ArduinoCore-mbed). To switch boards
|
||||
for which this is not the default core (which are only
|
||||
``board = pico`` and ``board = nanorp2040connect``), the directive
|
||||
|
||||
.. code:: ini
|
||||
|
||||
board_build.core = earlephilhower
|
||||
|
||||
must be added to the ``platformio.ini``. This controls the `core
|
||||
switching
|
||||
logic <https://github.com/maxgerhardt/platform-raspberrypi/blob/77e0d3a29d1dbf00fd3ec3271104e3bf4820869c/builder/frameworks/arduino/arduino.py#L27-L32>`__.
|
||||
|
||||
When using Arduino-Pico-only boards like ``board = rpipico`` or ``board = adafruit_feather``, this is not needed.
|
||||
|
||||
Flash size
|
||||
----------
|
||||
|
||||
Controlled via specifying the size allocated for the filesystem.
|
||||
Available sketch size is calculated accordingly by using (as in
|
||||
``makeboards.py``) that number and the (constant) EEPROM size (4096
|
||||
bytes) and the total flash size as known to PlatformIO via the board
|
||||
definition file. The expression on the right can involve "b","k","m"
|
||||
(bytes/kilobytes/megabytes) and floating point numbers. This makes it
|
||||
actually more flexible than in the Arduino IDE where there is a finite
|
||||
list of choices. Calculations happen in `the
|
||||
platform <https://github.com/maxgerhardt/platform-raspberrypi/blob/77e0d3a29d1dbf00fd3ec3271104e3bf4820869c/builder/main.py#L118-L184>`__.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; in reference to a board = pico config (2MB flash)
|
||||
; Flash Size: 2MB (Sketch: 1MB, FS:1MB)
|
||||
board_build.filesystem_size = 1m
|
||||
; Flash Size: 2MB (No FS)
|
||||
board_build.filesystem_size = 0m
|
||||
; Flash Size: 2MB (Sketch: 0.5MB, FS:1.5MB)
|
||||
board_build.filesystem_size = 1.5m
|
||||
|
||||
CPU Speed
|
||||
---------
|
||||
|
||||
As for all other PlatformIO platforms, the ``f_cpu`` macro value (which
|
||||
is passed to the core) can be changed as
|
||||
`documented <https://docs.platformio.org/en/latest/boards/raspberrypi/pico.html#configuration>`__
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; 133MHz
|
||||
board_build.f_cpu = 133000000L
|
||||
|
||||
Debug Port
|
||||
----------
|
||||
|
||||
Via
|
||||
`build_flags <https://docs.platformio.org/en/latest/projectconf/section_env_build.html#build-flags>`__
|
||||
as done for many other cores
|
||||
(`example <https://docs.platformio.org/en/latest/platforms/ststm32.html#configuration>`__).
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Debug Port: Serial
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial
|
||||
; Debug Port: Serial 1
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial1
|
||||
; Debug Port: Serial 2
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial2
|
||||
|
||||
Debug Level
|
||||
-----------
|
||||
|
||||
Done again by directly adding the needed `build
|
||||
flags <https://github.com/earlephilhower/arduino-pico/blob/05356da2c5552413a442f742e209c6fa92823666/boards.txt#L104-L114>`__.
|
||||
When wanting to define multiple build flags, they must be accumulated in
|
||||
either a single line or a newline-separated expression.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Debug level: Core
|
||||
build_flags = -DDEBUG_RP2040_CORE
|
||||
; Debug level: SPI
|
||||
build_flags = -DDEBUG_RP2040_SPI
|
||||
; Debug level: Wire
|
||||
build_flags = -DDEBUG_RP2040_WIRE
|
||||
; Debug level: All
|
||||
build_flags = -DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE
|
||||
; Debug level: NDEBUG
|
||||
build_flags = -DNDEBUG
|
||||
|
||||
; example: Debug port on serial 2 and all debug output
|
||||
build_flags = -DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE -DDEBUG_RP2040_PORT=Serial2
|
||||
; equivalent to above
|
||||
build_flags =
|
||||
-DDEBUG_RP2040_WIRE
|
||||
-DDEBUG_RP2040_SPI
|
||||
-DDEBUG_RP2040_CORE
|
||||
-DDEBUG_RP2040_PORT=Serial2
|
||||
|
||||
C++ Exceptions
|
||||
--------------
|
||||
|
||||
Exceptions are disabled by default. To enable them, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable Exceptions
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
|
||||
|
||||
Stack Protector
|
||||
---------------
|
||||
|
||||
To enable GCC's stack protection feature, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable Stack Protector
|
||||
build_flags = -fstack-protector
|
||||
|
||||
|
||||
RTTI
|
||||
----
|
||||
|
||||
RTTI (run-time type information) is disabled by default. To enable it, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable RTTI
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
|
||||
|
||||
USB Stack
|
||||
---------
|
||||
|
||||
Not specifying any special build flags regarding this gives one the
|
||||
default Pico SDK USB stack. To change it, add
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Adafruit TinyUSB
|
||||
build_flags = -DUSE_TINYUSB
|
||||
; No USB stack
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
|
||||
|
||||
Note that the special "No USB" setting is also supported, through the
|
||||
shortcut-define ``PIO_FRAMEWORK_ARDUINO_NO_USB``.
|
||||
|
||||
IP Stack
|
||||
---------
|
||||
|
||||
The lwIP stack can be configured to support only IPv4 (default) or additionally IPv6. To activate IPv6 support, add
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; IPv6
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
|
||||
|
||||
to the ``platformio.ini``.
|
||||
|
||||
Bluetooth Stack
|
||||
---------------
|
||||
|
||||
The Bluetooth Classic (BTC) and Bluetooth Low Energy (BLE) stack can be activated by adding
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; BTC and BLE
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
|
||||
|
||||
to the ``platformio.ini``.
|
||||
|
||||
Selecting a different core version
|
||||
----------------------------------
|
||||
|
||||
If you wish to use a different version of the core, e.g., the latest git
|
||||
``master`` version, you can use a
|
||||
`platform_packages <https://docs.platformio.org/en/latest/projectconf/section_env_platform.html#platform-packages>`__
|
||||
directive to do so. Simply specify that the framework package
|
||||
(``framework-arduinopico``) comes from a different source.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
platform_packages =
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
|
||||
|
||||
Whereas the ``#master`` can also be replaced by a ``#branchname`` or a
|
||||
``#commithash``. If left out, it will pull the default branch, which is ``master``.
|
||||
|
||||
The ``file://`` and ``symlink://`` pseudo-protocols can also be used instead of ``https://`` to point to a
|
||||
local copy of the core (with e.g. some modifications) on disk (`see documentation <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html?#local-folder>`_).
|
||||
|
||||
Note that this can only be done for versions that have the PlatformIO
|
||||
builder script it in, so versions before 1.9.2 are not supported.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
The following example ``platformio.ini`` can be used for a Raspberry Pi Pico
|
||||
and 0.5MByte filesystem.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
; board can use both Arduino cores -- we select Arduino-Pico here
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
|
||||
|
||||
The initial project structure should be generated just creating a new
|
||||
project for the Pico and the Arduino framework, after which the
|
||||
auto-generated ``platformio.ini`` can be adapted per above.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
With recent updates to the toolchain and OpenOCD, debugging firmwares is also possible.
|
||||
|
||||
To specify the debugging adapter, use ``debug_tool`` (`documentation <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html#debug-tool>`_). Supported values are:
|
||||
|
||||
* ``picoprobe``
|
||||
* ``cmsis-dap``
|
||||
* ``jlink``
|
||||
* ``raspberrypi-swd``
|
||||
* ``blackmagic``
|
||||
* ``pico-debug``
|
||||
|
||||
These values can also be used in ``upload_protocol`` if you want PlatformIO to upload the regular firmware through this method, which you likely want.
|
||||
|
||||
Especially the PicoProbe method is convenient when you have two Raspberry Pi Pico boards. One of them can be flashed with the PicoProbe firmware (`documentation <https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html#debugging-using-another-raspberry-pi-pico>`__) and is then connected to the target Raspberry Pi Pico board (see `documentation <https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf>`__ chapter "Picoprobe Wiring"). Remember that on Windows, you have to use `Zadig <https://zadig.akeo.ie/>`_ to also load "WinUSB" drivers for the "Picoprobe (Interface 2)" device so that OpenOCD can speak to it.
|
||||
|
||||
.. note::
|
||||
Newer PicoProbe firmware versions have dropped the proprietary "PicoProbe" USB communication protocol and emulate a **CMSIS-DAP** instead. Meaning, you have to use ``debug_tool = cmsis-dap`` for these newer firmwares, such as those obtained from `raspberrypi/picoprobe <https://github.com/raspberrypi/picoprobe/releases>`__
|
||||
|
||||
With that set up, debugging can be started via the left debugging sidebar and works nicely: Setup breakpoints, inspect the value of variables in the code, step through the code line by line. When a breakpoint is hit or execution is halted, you can even see the execution state both Cortex-M0+ cores of the RP2040.
|
||||
|
||||
.. image:: images/pio_debugging.png
|
||||
|
||||
For further information on customizing debug options, like the initial breakpoint or debugging / SWD speed, consult `the documentation <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html>`_.
|
||||
|
||||
.. note::
|
||||
For the BlackMagicProbe debugging probe (as can be e.g., created by simply flashing a STM32F103C8 "Bluepill" board), you currently have to use the branch ``fix/rp2040-flash-reliability`` (or at least commit ``1d001bc``) **and** use the `official ARM provided toolchain <https://github.com/blackmagic-debug/blackmagic/issues/1364#issuecomment-1503393266>`_.
|
||||
|
||||
You can obtain precompiled binaries from `here <https://github.com/blackmagic-debug/blackmagic/issues/1364#issuecomment-1503372723>`__. A flashing guide is available `here <https://primalcortex.wordpress.com/2017/06/13/building-a-black-magic-debug-probe/>`__. You then have to configure the target serial port ("GDB port") in your project per `documentation <https://docs.platformio.org/en/latest/plus/debug-tools/blackmagic.html#debugging-tool-blackmagic>`__.
|
||||
|
||||
.. note::
|
||||
For the pico-debug (`download <https://github.com/majbthrd/pico-debug/releases>`__) debugging way, *which needs no additional debug probe*, add this snippet to your ``platformio.ini`` and follow the given procedure:
|
||||
|
||||
.. code:: ini
|
||||
|
||||
upload_protocol = pico-debug
|
||||
debug_tool = pico-debug
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
|
||||
|
||||
1. Build your firmware normally
|
||||
2. Plug in the Pico in BOOTSEL mode
|
||||
3. Drag and drop your ``.pio/build/<env>/firmware.uf2`` onto the boot drive
|
||||
4. Unplug and replug your Pico back into BOOTSEL mode for the second time
|
||||
5. Drag and drop the downloaded ``pico-debug-gimmecache.uf2`` file onto the boot drive
|
||||
6. A CMSIS-DAP device should now appear on your computer
|
||||
7. Start debugging via the debug sidebar as normal
|
||||
|
||||
Note the restrictions: The second core cannot be used, the USB port cannot be used (no USB serial, only UART serial), 16KB less RAM is available.
|
||||
|
||||
Filesystem Uploading
|
||||
--------------------
|
||||
|
||||
For the Arduino IDE, `a plugin <https://github.com/earlephilhower/arduino-pico#uploading-filesystem-images>`_ is available that enables a data folder to be packed as a LittleFS filesystem binary and uploaded to the Pico.
|
||||
|
||||
This functionality is also built-in in the PlatformIO integration. Open the `project tasks <https://docs.platformio.org/en/latest/integration/ide/vscode.html#project-tasks>`_ and expand the "Platform" tasks:
|
||||
|
||||
.. image:: images/pio_fs_upload.png
|
||||
|
||||
The files you want to upload should be placed in a folder called ``data`` inside the project. This can be customized `if needed <https://docs.platformio.org/en/latest/projectconf/section_platformio.html#data-dir>`_.
|
||||
|
||||
The task "Build Filesystem Image" will take all files in the data directory and create a ``littlefs.bin`` file from it using the ``mklittlefs`` tool.
|
||||
|
||||
The task "Upload Filesystem Image" will upload the filesystem image to the Pico via the specified ``upload_protocol``.
|
||||
|
||||
.. note::
|
||||
Set the space available for the filesystem in the ``platformio.ini`` using e.g., ``board_build.filesystem_size = 0.5m``, or filesystem creation will fail!
|
||||
Using this core with PlatformIO
|
||||
===============================
|
||||
|
||||
What is PlatformIO?
|
||||
-------------------
|
||||
|
||||
`PlatformIO <https://platformio.org/>`__ is a free, open-source build-tool written in Python, which also integrates into VSCode code as an extension.
|
||||
|
||||
PlatformIO significantly simplifies writing embedded software by offering a unified build system, yet being able to create project files for many different IDEs, including VSCode, Eclipse, CLion, etc.
|
||||
Through this, PlatformIO can offer extensive features such as IntelliSense (autocomplete), debugging, unit testing etc., which not available in the standard Arduino IDE.
|
||||
|
||||
The Arduino IDE experience:
|
||||
|
||||
.. image:: images/the_arduinoide_experience.png
|
||||
|
||||
The PlatformIO experience:
|
||||
|
||||
.. image:: images/the_platformio_experience.png
|
||||
|
||||
Refer to the general documentation at https://docs.platformio.org/.
|
||||
|
||||
Especially useful is the `Getting started with VSCode + PlatformIO <https://docs.platformio.org/en/latest/integration/ide/vscode.html#installation>`_, `CLI reference <https://docs.platformio.org/en/latest/core/index.html>`_ and the `platformio.ini options <https://docs.platformio.org/en/latest/projectconf/index.html>`_ page.
|
||||
|
||||
Hereafter it is assumed that you have a basic understanding of PlatformIO in regards to project creation, project file structure and building and uploading PlatformIO projects, through reading the above pages.
|
||||
|
||||
Important steps for Windows users, before installing
|
||||
----------------------------------------------------
|
||||
|
||||
By default, Windows has a limited path length that is not long enough to fully clone the ``Pico-SDK``'s ``tinyusb`` repository, resulting in error messages like the one below while attempting to fetch the repository.
|
||||
|
||||
.. code::
|
||||
|
||||
error: unable to create file '.....' : Filename too long
|
||||
|
||||
To work around this requires performing two steps and rebooting Windows once. These steps will enable longer file paths at the Windows OS and the ``git`` level.
|
||||
|
||||
Step 1: Enabling long paths in git
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Open up a Windows ``cmd`` or ``terminal`` window and execute the following command
|
||||
|
||||
.. code::
|
||||
|
||||
git config --system core.longpaths true
|
||||
|
||||
Step 2: Enabling long paths in the Windows OS
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
(taken from https://www.microfocus.com/documentation/filr/filr-4/filr-desktop/t47bx2ogpfz7.html)
|
||||
|
||||
1. Click Window key and type gpedit.msc, then press the Enter key. This launches the Local Group Policy Editor.
|
||||
|
||||
2. Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem.
|
||||
|
||||
3. Double click Enable NTFS/Win32 long paths and close the dialog.
|
||||
|
||||
.. image:: images/longpath.png
|
||||
|
||||
|
||||
Step 3: Reboot the computer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once the two prior stages are complete, please do a full reboot or power cycle so that the new settings will take effect.
|
||||
|
||||
|
||||
Current state of development
|
||||
----------------------------
|
||||
|
||||
At the time of writing, PlatformIO integration for this core is a work-in-progress and not yet merged into mainline PlatformIO. This is subject to change once `this pull request <https://github.com/platformio/platform-raspberrypi/pull/36>`_ is merged.
|
||||
|
||||
If you want to use the PlatformIO integration right now, make sure you first create a standard Raspberry Pi Pico + Arduino project within PlatformIO.
|
||||
This will give you a project with the ``platformio.ini``
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = raspberrypi
|
||||
board = pico
|
||||
framework = arduino
|
||||
|
||||
Here, you need to change the `platform` to take advantage of the features described hereunder and switch to the new core.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
board_build.core = earlephilhower
|
||||
|
||||
When the support for this core has been merged into mainline PlatformIO, this notice will be removed and a standard `platformio.ini` as shown above will work as a base.
|
||||
|
||||
Deprecation warnings
|
||||
---------------------
|
||||
|
||||
Previous versions of this documentation told users to inject the framework and toolchain package into the project by using
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; note that download link for toolchain is specific for OS. see https://github.com/earlephilhower/pico-quick-toolchain/releases.
|
||||
platform_packages =
|
||||
maxgerhardt/framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git
|
||||
maxgerhardt/toolchain-pico@https://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.1-a/x86_64-w64-mingw32.arm-none-eabi-7855b0c.210706.zip
|
||||
|
||||
This is now **deprecated** and should not be done anymore. Users should delete these ``platform_packages`` lines and update the platform integration by issuing the command
|
||||
|
||||
.. code:: bash
|
||||
|
||||
pio pkg update -g -p https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
|
||||
in the `PlatformIO CLI <https://docs.platformio.org/en/latest/integration/ide/vscode.html#platformio-core-cli>`_. The same can be achieved by using the VSCode PIO Home -> Platforms -> Updates GUI.
|
||||
|
||||
The toolchain, which was also renamed to ``toolchain-rp2040-earlephilhower`` is downloaded automatically from the registry. The same goes for the ``framework-arduinopico`` toolchain package, which points directly to the Arduino-Pico Github repository.
|
||||
However, users can still select a custom fork or branch of the core if desired so, as detailed in a chapter below.
|
||||
|
||||
Selecting the new core
|
||||
----------------------
|
||||
|
||||
Prerequisite for using this core is to tell PlatformIO to switch to it.
|
||||
There will be board definition files where the Earle-Philhower core will
|
||||
be the default since it's a board that only exists in this core (and not
|
||||
the other https://github.com/arduino/ArduinoCore-mbed). To switch boards
|
||||
for which this is not the default core (which are only
|
||||
``board = pico`` and ``board = nanorp2040connect``), the directive
|
||||
|
||||
.. code:: ini
|
||||
|
||||
board_build.core = earlephilhower
|
||||
|
||||
must be added to the ``platformio.ini``. This controls the `core
|
||||
switching
|
||||
logic <https://github.com/maxgerhardt/platform-raspberrypi/blob/77e0d3a29d1dbf00fd3ec3271104e3bf4820869c/builder/frameworks/arduino/arduino.py#L27-L32>`__.
|
||||
|
||||
When using Arduino-Pico-only boards like ``board = rpipico`` or ``board = adafruit_feather``, this is not needed.
|
||||
|
||||
Flash size
|
||||
----------
|
||||
|
||||
Controlled via specifying the size allocated for the filesystem.
|
||||
Available sketch size is calculated accordingly by using (as in
|
||||
``makeboards.py``) that number and the (constant) EEPROM size (4096
|
||||
bytes) and the total flash size as known to PlatformIO via the board
|
||||
definition file. The expression on the right can involve "b","k","m"
|
||||
(bytes/kilobytes/megabytes) and floating point numbers. This makes it
|
||||
actually more flexible than in the Arduino IDE where there is a finite
|
||||
list of choices. Calculations happen in `the
|
||||
platform <https://github.com/maxgerhardt/platform-raspberrypi/blob/77e0d3a29d1dbf00fd3ec3271104e3bf4820869c/builder/main.py#L118-L184>`__.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; in reference to a board = pico config (2MB flash)
|
||||
; Flash Size: 2MB (Sketch: 1MB, FS:1MB)
|
||||
board_build.filesystem_size = 1m
|
||||
; Flash Size: 2MB (No FS)
|
||||
board_build.filesystem_size = 0m
|
||||
; Flash Size: 2MB (Sketch: 0.5MB, FS:1.5MB)
|
||||
board_build.filesystem_size = 1.5m
|
||||
|
||||
CPU Speed
|
||||
---------
|
||||
|
||||
As for all other PlatformIO platforms, the ``f_cpu`` macro value (which
|
||||
is passed to the core) can be changed as
|
||||
`documented <https://docs.platformio.org/en/latest/boards/raspberrypi/pico.html#configuration>`__
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; 133MHz
|
||||
board_build.f_cpu = 133000000L
|
||||
|
||||
Debug Port
|
||||
----------
|
||||
|
||||
Via
|
||||
`build_flags <https://docs.platformio.org/en/latest/projectconf/section_env_build.html#build-flags>`__
|
||||
as done for many other cores
|
||||
(`example <https://docs.platformio.org/en/latest/platforms/ststm32.html#configuration>`__).
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Debug Port: Serial
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial
|
||||
; Debug Port: Serial 1
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial1
|
||||
; Debug Port: Serial 2
|
||||
build_flags = -DDEBUG_RP2040_PORT=Serial2
|
||||
|
||||
Debug Level
|
||||
-----------
|
||||
|
||||
Done again by directly adding the needed `build
|
||||
flags <https://github.com/earlephilhower/arduino-pico/blob/05356da2c5552413a442f742e209c6fa92823666/boards.txt#L104-L114>`__.
|
||||
When wanting to define multiple build flags, they must be accumulated in
|
||||
either a single line or a newline-separated expression.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Debug level: Core
|
||||
build_flags = -DDEBUG_RP2040_CORE
|
||||
; Debug level: SPI
|
||||
build_flags = -DDEBUG_RP2040_SPI
|
||||
; Debug level: Wire
|
||||
build_flags = -DDEBUG_RP2040_WIRE
|
||||
; Debug level: All
|
||||
build_flags = -DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE
|
||||
; Debug level: NDEBUG
|
||||
build_flags = -DNDEBUG
|
||||
|
||||
; example: Debug port on serial 2 and all debug output
|
||||
build_flags = -DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE -DDEBUG_RP2040_PORT=Serial2
|
||||
; equivalent to above
|
||||
build_flags =
|
||||
-DDEBUG_RP2040_WIRE
|
||||
-DDEBUG_RP2040_SPI
|
||||
-DDEBUG_RP2040_CORE
|
||||
-DDEBUG_RP2040_PORT=Serial2
|
||||
|
||||
C++ Exceptions
|
||||
--------------
|
||||
|
||||
Exceptions are disabled by default. To enable them, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable Exceptions
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
|
||||
|
||||
Stack Protector
|
||||
---------------
|
||||
|
||||
To enable GCC's stack protection feature, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable Stack Protector
|
||||
build_flags = -fstack-protector
|
||||
|
||||
|
||||
RTTI
|
||||
----
|
||||
|
||||
RTTI (run-time type information) is disabled by default. To enable it, use
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Enable RTTI
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
|
||||
|
||||
USB Stack
|
||||
---------
|
||||
|
||||
Not specifying any special build flags regarding this gives one the
|
||||
default Pico SDK USB stack. To change it, add
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; Adafruit TinyUSB
|
||||
build_flags = -DUSE_TINYUSB
|
||||
; No USB stack
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
|
||||
|
||||
Note that the special "No USB" setting is also supported, through the
|
||||
shortcut-define ``PIO_FRAMEWORK_ARDUINO_NO_USB``.
|
||||
|
||||
IP Stack
|
||||
--------
|
||||
|
||||
The lwIP stack can be configured to support only IPv4 (default) or additionally IPv6. To activate IPv6 support, add
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; IPv6
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
|
||||
|
||||
to the ``platformio.ini``.
|
||||
|
||||
Bluetooth Stack
|
||||
---------------
|
||||
|
||||
The Bluetooth Classic (BTC) and Bluetooth Low Energy (BLE) stack can be activated by adding
|
||||
|
||||
.. code:: ini
|
||||
|
||||
; BTC and BLE
|
||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
|
||||
|
||||
to the ``platformio.ini``.
|
||||
|
||||
Selecting a different core version
|
||||
----------------------------------
|
||||
|
||||
If you wish to use a different version of the core, e.g., the latest git
|
||||
``master`` version, you can use a
|
||||
`platform_packages <https://docs.platformio.org/en/latest/projectconf/section_env_platform.html#platform-packages>`__
|
||||
directive to do so. Simply specify that the framework package
|
||||
(``framework-arduinopico``) comes from a different source.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
platform_packages =
|
||||
framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
|
||||
|
||||
Whereas the ``#master`` can also be replaced by a ``#branchname`` or a
|
||||
``#commithash``. If left out, it will pull the default branch, which is ``master``.
|
||||
|
||||
The ``file://`` and ``symlink://`` pseudo-protocols can also be used instead of ``https://`` to point to a
|
||||
local copy of the core (with e.g. some modifications) on disk (`see documentation <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html?#local-folder>`_).
|
||||
|
||||
Note that this can only be done for versions that have the PlatformIO
|
||||
builder script it in, so versions before 1.9.2 are not supported.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
The following example ``platformio.ini`` can be used for a Raspberry Pi Pico
|
||||
and 0.5MByte filesystem.
|
||||
|
||||
.. code:: ini
|
||||
|
||||
[env:pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
; board can use both Arduino cores -- we select Arduino-Pico here
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
|
||||
|
||||
The initial project structure should be generated just creating a new
|
||||
project for the Pico and the Arduino framework, after which the
|
||||
auto-generated ``platformio.ini`` can be adapted per above.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
With recent updates to the toolchain and OpenOCD, debugging firmwares is also possible.
|
||||
|
||||
To specify the debugging adapter, use ``debug_tool`` (`documentation <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html#debug-tool>`_). Supported values are:
|
||||
|
||||
* ``picoprobe``
|
||||
* ``cmsis-dap``
|
||||
* ``jlink``
|
||||
* ``raspberrypi-swd``
|
||||
* ``blackmagic``
|
||||
|
||||
These values can also be used in ``upload_protocol`` if you want PlatformIO to upload the regular firmware through this method, which you likely want.
|
||||
|
||||
Especially the PicoProbe method is convenient when you have two Raspberry Pi Pico boards. One of them can be flashed with the PicoProbe firmware (`documentation <https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html#debugging-using-another-raspberry-pi-pico>`__) and is then connected to the target Raspberry Pi Pico board (see `documentation <https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf>`__ chapter "Picoprobe Wiring"). Remember that on Windows, you have to use `Zadig <https://zadig.akeo.ie/>`_ to also load "WinUSB" drivers for the "Picoprobe (Interface 2)" device so that OpenOCD can speak to it.
|
||||
|
||||
.. note::
|
||||
Newer PicoProbe firmware versions have dropped the proprietary "PicoProbe" USB communication protocol and emulate a **CMSIS-DAP** instead. Meaning, you have to use ``debug_tool = cmsis-dap`` for these newer firmwares, such as those obtained from `raspberrypi/picoprobe <https://github.com/raspberrypi/picoprobe/releases>`__
|
||||
|
||||
With that set up, debugging can be started via the left debugging sidebar and works nicely: Setup breakpoints, inspect the value of variables in the code, step through the code line by line. When a breakpoint is hit or execution is halted, you can even see the execution state both Cortex-M0+ cores of the RP2040.
|
||||
|
||||
.. image:: images/pio_debugging.png
|
||||
|
||||
For further information on customizing debug options, like the initial breakpoint or debugging / SWD speed, consult `the documentation <https://docs.platformio.org/en/latest/projectconf/section_env_debug.html>`_.
|
||||
|
||||
.. note::
|
||||
For the BlackMagicProbe debugging probe (as can be e.g., created by simply flashing a STM32F103C8 "Bluepill" board), you currently have to use the branch ``fix/rp2040-flash-reliability`` (or at least commit ``1d001bc``) **and** use the `official ARM provided toolchain <https://github.com/blackmagic-debug/blackmagic/issues/1364#issuecomment-1503393266>`_.
|
||||
|
||||
You can obtain precompiled binaries from `here <https://github.com/blackmagic-debug/blackmagic/issues/1364#issuecomment-1503372723>`__. A flashing guide is available `here <https://primalcortex.wordpress.com/2017/06/13/building-a-black-magic-debug-probe/>`__. You then have to configure the target serial port ("GDB port") in your project per `documentation <https://docs.platformio.org/en/latest/plus/debug-tools/blackmagic.html#debugging-tool-blackmagic>`__.
|
||||
|
||||
Filesystem Uploading
|
||||
--------------------
|
||||
|
||||
For the Arduino IDE, `a plugin <https://github.com/earlephilhower/arduino-pico#uploading-filesystem-images>`_ is available that enables a data folder to be packed as a LittleFS filesystem binary and uploaded to the Pico.
|
||||
|
||||
This functionality is also built-in in the PlatformIO integration. Open the `project tasks <https://docs.platformio.org/en/latest/integration/ide/vscode.html#project-tasks>`_ and expand the "Platform" tasks:
|
||||
|
||||
.. image:: images/pio_fs_upload.png
|
||||
|
||||
The files you want to upload should be placed in a folder called ``data`` inside the project. This can be customized `if needed <https://docs.platformio.org/en/latest/projectconf/section_platformio.html#data-dir>`_.
|
||||
|
||||
The task "Build Filesystem Image" will take all files in the data directory and create a ``littlefs.bin`` file from it using the ``mklittlefs`` tool.
|
||||
|
||||
The task "Upload Filesystem Image" will upload the filesystem image to the Pico via the specified ``upload_protocol``.
|
||||
|
||||
.. note::
|
||||
Set the space available for the filesystem in the ``platformio.ini`` using e.g., ``board_build.filesystem_size = 0.5m``, or filesystem creation will fail!
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
RP2350 PSRAM Support
|
||||
====================
|
||||
|
||||
The RP2350 chip in the Raspberry Pi Pico 2, and other RP2350 boards,
|
||||
supports an external interface to PSRAM. When a PSRAM chip is attached
|
||||
to the processor (please note that there is none on the Pico 2 board, but
|
||||
iLabs and SparkFun boards, among others, do have it), up to 16 megabytes
|
||||
of additional memory can be used by the chip.
|
||||
|
||||
While this external RAM is slower than the built-in SRAM, it is still
|
||||
able to be used in any place where normal RAM would be used (other than
|
||||
for memory-mapped functions and statically initialized variables).
|
||||
|
||||
When present, PSRAM can be used in two ways: for specific instantiated
|
||||
variables, or through a ``malloc``-like access method. Both can be used
|
||||
in any single application.
|
||||
|
||||
Using PSRAM for regular variables
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similar to ``PROGMEM`` in the original Arduino AVR devices, the variable
|
||||
decorator ``PSRAM`` can be added to map a variable into PSRAM. Simply add
|
||||
``PSRAM`` to an array and it will be mapped into PSRAM:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
...
|
||||
float weights[4000] PSRAM; // Place an array of 4000 floats in PSRAM
|
||||
char samplefile[1'000'000] PSRAM; // Allocate 1M for WAV samples in PSRAM
|
||||
...
|
||||
|
||||
These variables can be used just like normal ones, no special handling is
|
||||
required. For example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
char buff[4 *1024 * 1024]; // 4MB array
|
||||
|
||||
void initBuff() {
|
||||
bzero(buff, sizeof(buff));
|
||||
for (int i = 0; i < 4 *1024 * 1024; i += 4096) {
|
||||
buff[i] = rand();
|
||||
}
|
||||
}
|
||||
|
||||
The only restriction is that these variables may not be initialized statically.
|
||||
The following example will **NOT** work:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
char buff[] = "This is illegal and will not function";
|
||||
|
||||
Using PSRAM for dynamic allocations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
PSRAM can also be used as a heap for dynamica allocations using ``pmalloc`` and
|
||||
``pcalloc``. These calls function exactly like normal ``malloc`` and ``calloc``
|
||||
except they allocate space from PSRAM.
|
||||
|
||||
Simply replace a ``malloc`` or ``calloc`` with ``pmalloc`` or ``pcalloc`` to use
|
||||
the PSRAM heap. Other calls, such as ``free`` and ``realloc`` "just work" and do
|
||||
not need to be modified (they check where the passed-in pointer resides and
|
||||
do the right thing automatically).
|
||||
|
||||
For example, to create and modify large buffer in PSRAM:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
void ex() {
|
||||
int *buff;
|
||||
// Ignoring OOM error conditions in example for brevity
|
||||
buff = (int *)pmalloc(10000 * sizeof(*buff));
|
||||
// Something happened and we need more space, so...
|
||||
buff = (int *)realloc(buff, 20000 * sizeof(*buff)); // buff now has 20K elements
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
buff[i] = i;
|
||||
}
|
||||
// Do some work, now we're done
|
||||
free(buff);
|
||||
}
|
||||
|
||||
C++ objects can be allocated in PSRAM using "placement new" constructors. Note that
|
||||
this will only place immediate object data in PSRAM: if the object creates any other
|
||||
objects via ``new`` *those* objects will be placed in normal RAM unless the object
|
||||
also uses placement new constructors.
|
||||
|
||||
|
||||
|
||||
Checking on PSRAM space
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``rp2040`` helper object has the following calls to return the state of the
|
||||
PSRAM heap with the following calls, similar to the normal RAM heap:
|
||||
|
||||
int rp2040.getPSRAMSize()
|
||||
-------------------------
|
||||
|
||||
Return the total size of the attached PSRAM chip. This is the **RAW** space and
|
||||
does not take into account any allocations for static variables or dynamic
|
||||
allocations. (i.e. it will return 1, 2, 4, 8, or 16MV depending on the chip).
|
||||
|
||||
int rp2040.getTotalPSRAMHeap()
|
||||
------------------------------
|
||||
|
||||
Returns the total PSRAM heap (free and used) available or used for ``pmalloc``
|
||||
allocations.
|
||||
|
||||
int rp2040.getUsedPSRAMHeap()
|
||||
-----------------------------
|
||||
|
||||
Returns the total used bytes (including any overhead) of the PSRAM heap.
|
||||
|
||||
int getFreePSRAMHeap()
|
||||
----------------------
|
||||
|
||||
Returns the total free bytes in the PSRAM heap. (Note that this may include
|
||||
multiple non-contiguous chunks, so this is not always the maximum block size
|
||||
that can be allocated.)
|
||||
@@ -99,3 +99,13 @@ bootloader.
|
||||
void rp2040.rebootToBootloader()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Will reboot the RP2040 into USB UF2 upload mode.
|
||||
|
||||
DMA-based MEMCPY
|
||||
----------------
|
||||
The onboard DMA engines can copy 4-byte aligned quantities faster than the CPU.
|
||||
|
||||
void \*rp2040.memcpyDMA(void \*dest, const void \*src, size_t count);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Uses a DMA engine to transfer data from src to dest in 4-byte chunks without CPU
|
||||
intervention. If any arguments are not 4-byte aligned, or if the count is not a
|
||||
multiple of 4, then it will fall back to CPU-managed memcpy.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
RP2350 Specific Notes
|
||||
=====================
|
||||
|
||||
The RP2350 chip (present on the Raspberry Pi Pico 2 board and many others)
|
||||
is supported by the core with some minor caveats:
|
||||
|
||||
* PSRAM is supported via a new ``pmalloc`` call and ``PSRAM`` variable decorator.
|
||||
* Both RP2350A and RP2350B (48 GPIOs) are supported.
|
||||
* Only ARM mode is available. For RISC-V (Hazard3), please use the raw SDK.
|
||||
|
||||
P2350-E9 Errata ("Increased leakage current on Bank 0 GPIO when pad input is enabled")
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Like all chips, the RP2350-A2 stepping has post-silicon chip errata covering certain
|
||||
bugs found after the chip was manufactured. Probably the most (in)famous and concerning
|
||||
is RP2350-E9 which is noted as resulting in "Increased leakage current on Bank 0 GPIO
|
||||
when pad input is enabled." At a high level, this means that in some cases when an
|
||||
input pin is being driven by a weak (high impedance) input, it may not read properly.
|
||||
|
||||
After discussion with the community and exploration of the issue by many users, this
|
||||
core has decided not to implement any forced workarounds for this issue. Given the
|
||||
physical nature of the problem and how no one specific solution is appropriate for
|
||||
all conditions.
|
||||
|
||||
For more information please read the errata yourself and check the Raspberry Pi Forums
|
||||
for the latest updates.
|
||||
|
||||
@@ -47,6 +47,14 @@ For detailed information about the Serial ports, see the
|
||||
Arduino `Serial Reference <https://www.arduino.cc/reference/en/language/functions/communication/serial/>`_ .
|
||||
|
||||
|
||||
Inversion
|
||||
---------
|
||||
|
||||
``Serial1`` and ``Serial2`` can both support inverted input and/or outputs via the methods
|
||||
``Serial1/2::setInvertRX(bool invert)`` and ``Serial1/2::setInvertTX(bool invert)`` and
|
||||
``Serial1/2::serInvertControl(bool invert)``.
|
||||
|
||||
|
||||
RP2040 Specific SerialUSB methods
|
||||
---------------------------------
|
||||
|
||||
|
||||
@@ -11,3 +11,10 @@ require the use of a PIO machine.
|
||||
See the Arduino standard
|
||||
`Servo documentation <https://www.arduino.cc/reference/en/libraries/servo/>`_
|
||||
for detailed usage instructions. There is also an included ``sweep`` example.
|
||||
|
||||
Pulse Width Defaults
|
||||
--------------------
|
||||
The defaults in the Servo library are conservatively set to avoid damage in the case of over-driving. The pulse widths individual servos, especially the no-name or clones, occasionally need tweaking.
|
||||
|
||||
You can set the min and max servo pulse width in the attach command, with default values used in most Arduino cores of 540/2400:
|
||||
```myServo.attach(D3, 540, 2400)```
|
||||
|
||||
+29
-20
@@ -33,32 +33,41 @@ being performed. For example, a game could send a full screen update out over I
|
||||
processing the next frame without waiting for the first one to be sent over I2C. DMA is used to handle
|
||||
the transfer to/from the I2C hardware freeing the CPU from bit-banging or busy waiting.
|
||||
|
||||
Note that asynchronous operations can not be intersped with normal, synchronous ones. Fully complete an
|
||||
asynchronous operation before attempting to do a normal ``Wire.beginTransaction()`` or ``Wire.requestFrom``.
|
||||
Also, all buffers need to be valid throughout the entire operation. Read data cannot be accessed until
|
||||
the transaction is completed and can't be "peeked" at while the operation is ongoing.
|
||||
Note that asynchronous operations can not be intersped with normal, synchronous ones. Fully complete or
|
||||
abort an asynchronous operation before attempting to do a normal ``Wire.beginTransaction()`` or
|
||||
``Wire.requestFrom``.
|
||||
|
||||
|
||||
bool writeAsync(uint8_t address, const void \*buffer, size_t bytes, bool sendStop)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Begins an I2C asynchronous write transaction. Writes to ``address`` of ``bytes`` from ``buffer`` and
|
||||
at the end will send an I2C stop if ``sendStop`` is ``true``.
|
||||
Check ``finishedAsync()`` to determine when the operation completes and conclude the transaction.
|
||||
This operation needs to allocate a buffer from heap equal to 2x ``bytes`` in size.
|
||||
bool writeReadAsync(uint8_t address, const void \*wbuffer, size_t wbytes, const void \*rbuffer, size_t rbytes, bool sendStop)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Executes a master I2C asynchronous write/read transaction to I2C slave ``address``. First ``wbytes`` from
|
||||
``wbuffer`` are written to the I2C slave, followed by an I2C restart, then ``rbytes`` are read from the
|
||||
I2C slave into ``rbuffer``. The buffers need to be valid throughout the entire asynchronous operation.
|
||||
|
||||
bool readAsync(uint8_t address, void \*buffer, size_t bytes, bool sendStop)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Begins an I2C asynchronous read transaction. Reads from ``address`` for ``bytes`` into ``buffer`` and
|
||||
at the end will send an I2C stop if ``sendStop`` is ``true``.
|
||||
Check ``finishedAsync()`` to determine when the operation completes and conclude the transaction.
|
||||
This operation needs to allocate a buffer from heap equal to 4x ``bytes`` in size.
|
||||
At the end of the transaction an I2C stop is sent if ``sendStop`` is ``true``, and at the beginning of the
|
||||
transaction an I2C start is sent if the previous write/read had ``sendStop`` set to ``true``.
|
||||
|
||||
Check ``finishedAsync()`` to determine when the operation completes, or use ``onFinishedAsync()`` to set a
|
||||
callback.
|
||||
|
||||
Set ``rbytes`` to 0 to do a write-only operation, set ``wbytes`` to 0 to do a read-only operation. Or use:
|
||||
|
||||
``bool writeAsync(uint8_t address, const void \*buffer, size_t bytes, bool sendStop)``
|
||||
|
||||
``bool readAsync(uint8_t address, void \*buffer, size_t bytes, bool sendStop)``
|
||||
|
||||
The first call to an asynchronous write/read operation allocates the required DMA channels and internal
|
||||
buffer. If desired, call ``end()`` to free these resources.
|
||||
|
||||
bool finishedAsync()
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
Call to check if the asynchronous operations is completed and the buffer passed in can be either read or
|
||||
reused. Frees the allocated memory and completes the asynchronous transaction.
|
||||
Call to check if the asynchronous operations is completed.
|
||||
|
||||
void onFinishedAsync(void(*function)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Set a (optional) callback for async operation. The ``function`` will be called when the asynchronous
|
||||
operation finishes.
|
||||
|
||||
void abortAsync()
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Cancels the outstanding asynchronous transaction and frees any allocated memory.
|
||||
|
||||
Cancels any outstanding asynchronous transaction.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Do not edit -- Automatically generated by tools/sdk/ssl/bearssl/Makefile
|
||||
#define BEARSSL_GIT f294aa0
|
||||
#define BEARSSL_GIT c2c9d9d
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@
|
||||
|
||||
// based on PICO_CONFIG_HEADER_FILES:
|
||||
|
||||
#include "../../pico-sdk/src/boards/include/boards/pico.h"
|
||||
#include "../../pico-sdk/src/boards/include/boards/pico_w.h"
|
||||
#include "../../pico-sdk/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h"
|
||||
|
||||
// based on PICO_RP2040_CONFIG_HEADER_FILES:
|
||||
@@ -11,9 +11,9 @@
|
||||
#ifndef _PICO_VERSION_H
|
||||
#define _PICO_VERSION_H
|
||||
|
||||
#define PICO_SDK_VERSION_MAJOR 1
|
||||
#define PICO_SDK_VERSION_MINOR 5
|
||||
#define PICO_SDK_VERSION_REVISION 1
|
||||
#define PICO_SDK_VERSION_STRING "1.5.1"
|
||||
#define PICO_SDK_VERSION_MAJOR 2
|
||||
#define PICO_SDK_VERSION_MINOR 0
|
||||
#define PICO_SDK_VERSION_REVISION 0
|
||||
#define PICO_SDK_VERSION_STRING "2.0.0"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_DEBUG
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_PRINTF_HEXDUMP
|
||||
#define ENABLE_SCO_OVER_HCI
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#endif
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
|
||||
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
|
||||
#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
|
||||
#define MAX_NR_AVDTP_CONNECTIONS 1
|
||||
#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
|
||||
#define MAX_NR_AVRCP_CONNECTIONS 2
|
||||
#define MAX_NR_BNEP_CHANNELS 1
|
||||
#define MAX_NR_BNEP_SERVICES 1
|
||||
#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
|
||||
#define MAX_NR_GATT_CLIENTS 1
|
||||
#define MAX_NR_HCI_CONNECTIONS 2
|
||||
#define MAX_NR_HID_HOST_CONNECTIONS 1
|
||||
#define MAX_NR_HIDS_CLIENTS 1
|
||||
#define MAX_NR_HFP_CONNECTIONS 1
|
||||
#define MAX_NR_L2CAP_CHANNELS 4
|
||||
#define MAX_NR_L2CAP_SERVICES 3
|
||||
#define MAX_NR_RFCOMM_CHANNELS 1
|
||||
#define MAX_NR_RFCOMM_MULTIPLEXERS 1
|
||||
#define MAX_NR_RFCOMM_SERVICES 1
|
||||
#define MAX_NR_SERVICE_RECORD_ITEMS 4
|
||||
#define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||
#define MAX_NR_WHITELIST_ENTRIES 16
|
||||
#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
|
||||
|
||||
// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
|
||||
#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
|
||||
#define MAX_NR_CONTROLLER_SCO_PACKETS 3
|
||||
|
||||
// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
|
||||
#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
|
||||
#define HCI_HOST_ACL_PACKET_LEN 1024
|
||||
#define HCI_HOST_ACL_PACKET_NUM 3
|
||||
#define HCI_HOST_SCO_PACKET_LEN 120
|
||||
#define HCI_HOST_SCO_PACKET_NUM 3
|
||||
|
||||
// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
|
||||
#define NVM_NUM_DEVICE_DB_ENTRIES 16
|
||||
#define NVM_NUM_LINK_KEYS 16
|
||||
|
||||
// We don't give btstack a malloc, so use a fixed-size ATT DB.
|
||||
#define MAX_ATT_DB_SIZE 512
|
||||
|
||||
// BTstack HAL configuration
|
||||
#define HAVE_EMBEDDED_TIME_MS
|
||||
|
||||
// map btstack_assert onto Pico SDK assert()
|
||||
#define HAVE_ASSERT
|
||||
|
||||
// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
|
||||
#define HCI_RESET_RESEND_TIMEOUT_MS 1000
|
||||
|
||||
#define ENABLE_SOFTWARE_AES128
|
||||
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
|
||||
|
||||
#undef HAVE_BTSTACK_STDIN
|
||||
@@ -0,0 +1,10 @@
|
||||
// AUTOGENERATED FROM PICO_CONFIG_HEADER_FILES and then PICO_<PLATFORM>_CONFIG_HEADER_FILES
|
||||
// DO NOT EDIT!
|
||||
|
||||
|
||||
// based on PICO_CONFIG_HEADER_FILES:
|
||||
|
||||
#include "../../pico-sdk/src/boards/include/boards/solderparty_rp2350_stamp_xl.h"
|
||||
#include "../../pico-sdk/src/rp2_common/cmsis/include/cmsis/rename_exceptions.h"
|
||||
|
||||
// based on PICO_RP2350_ARM_S_CONFIG_HEADER_FILES:
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
ota_command.h - OTA stub that copies from LittleFS to flash
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define _OTA_WRITE 1
|
||||
#define _OTA_VERIFY 1
|
||||
|
||||
typedef struct {
|
||||
uint32_t command;
|
||||
union {
|
||||
struct {
|
||||
char filename[64];
|
||||
uint32_t fileOffset;
|
||||
uint32_t fileLength;
|
||||
uint32_t flashAddress; // Normally XIP_BASE
|
||||
} write;
|
||||
};
|
||||
} commandEntry;
|
||||
|
||||
// Must fit within 4K page
|
||||
typedef struct {
|
||||
uint8_t sign[8]; // "Pico OTA"
|
||||
|
||||
// List of operations
|
||||
uint32_t count;
|
||||
commandEntry cmd[8];
|
||||
|
||||
uint32_t crc32; // CRC32 over just the contents of this struct, up until just before this value
|
||||
} OTACmdPage;
|
||||
|
||||
#define _OTA_COMMAND_FILE "otacommand.bin"
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
// ---------------------------------------
|
||||
// THIS FILE IS AUTOGENERATED; DO NOT EDIT
|
||||
// ---------------------------------------
|
||||
|
||||
#ifndef _PICO_VERSION_H
|
||||
#define _PICO_VERSION_H
|
||||
|
||||
#define PICO_SDK_VERSION_MAJOR 2
|
||||
#define PICO_SDK_VERSION_MINOR 0
|
||||
#define PICO_SDK_VERSION_REVISION 0
|
||||
#define PICO_SDK_VERSION_STRING "2.0.0"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#define CFG_TUSB_MCU OPT_MCU_RP2040
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
#define CFG_TUSB_OS OPT_OS_PICO
|
||||
|
||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID (2)
|
||||
#define CFG_TUD_CDC (1)
|
||||
#define CFG_TUD_MSC (1)
|
||||
#define CFG_TUD_MIDI (0)
|
||||
#define CFG_TUD_VENDOR (0)
|
||||
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (256)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (256)
|
||||
|
||||
#define CFG_TUD_MSC_EP_BUFSIZE (64)
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_EP_BUFSIZE (64)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
@@ -13,6 +13,7 @@ Dir KEYWORD1
|
||||
File KEYWORD1
|
||||
timeval KEYWORD1
|
||||
time_t KEYWORD1
|
||||
SoftwareSerial KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
@@ -56,6 +57,14 @@ restart KEYWORD2
|
||||
|
||||
isPicoW KEYWORD2
|
||||
|
||||
pmalloc KEYWORD2
|
||||
pcalloc KEYWORD2
|
||||
getPSRAMSize KEYWORD2
|
||||
getFreePSRAMHeap KEYWORD2
|
||||
getUsedPSRAMHeap KEYWORD2
|
||||
getTotalPSRAMHeap KEYWORD2
|
||||
getTotalPSRAM KEYWORD2
|
||||
|
||||
getChipID KEYWORD2
|
||||
|
||||
hwrand32 KEYWORD2
|
||||
@@ -65,6 +74,9 @@ prepare KEYWORD2
|
||||
SerialPIO KEYWORD2
|
||||
setFIFOSize KEYWORD2
|
||||
setPollingMode KEYWORD2
|
||||
setInvertTX KEYWORD2
|
||||
setInvertRX KEYWORD2
|
||||
setInvertControl KEYWORD2
|
||||
|
||||
digitalWriteFast KEYWORD2
|
||||
digitalReadFast KEYWORD2
|
||||
@@ -92,3 +104,5 @@ OUTPUT_8MA LITERAL1
|
||||
OUTPUT_12MA LITERAL1
|
||||
|
||||
ARDUINO_ARCH_RP2040 LITERAL1
|
||||
|
||||
PSRAM LITERAL1
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
-iwithprefixbefore/cores/rp2040/api/deprecated-avr-comp/
|
||||
-iwithprefixbefore/include/pico_base/
|
||||
-iwithprefixbefore/pico-sdk/lib/tinyusb/src/
|
||||
-iwithprefixbefore/cores/rp2040/api/deprecated-avr-comp
|
||||
|
||||
-iwithprefixbefore/pico-sdk/lib/tinyusb/src
|
||||
-iwithprefixbefore/pico-sdk/src/boards/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/hardware_claim/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_base/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_base_headers/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_binary_info/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_bit_ops/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_divider/include
|
||||
@@ -11,14 +13,13 @@
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_time/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_usb_reset_interface/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_util/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_regs/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_structs/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_stdlib_headers/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_usb_reset_interface_headers/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/cmsis/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/cmsis/stub/CMSIS/Device/RaspberryPi/RP2040/Include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_adc/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_base/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_claim/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_boot_lock/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_clocks/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_divider/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_dma/include
|
||||
@@ -35,29 +36,30 @@
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_resets/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_spi/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_sync/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_sync_spin_lock/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_timer/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_uart/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_vreg/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_watchdog/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_xosc/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_aon_timer/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_async_context/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_bootrom/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_btstack/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_arch/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_driver/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_double/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_float/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_int64_ops/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_lwip/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_multicore/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform_compiler/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform_sections/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform_panic/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_printf/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_runtime/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_runtime_init/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_rand/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_uart/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_unique_id/include
|
||||
-iwithprefixbefore/pico-sdk/lib/cyw43-driver/src
|
||||
-iwithprefixbefore/pico-sdk/lib/lwip/src/include
|
||||
-iwithprefixbefore/pico-sdk/lib/btstack/src
|
||||
-iwithprefixbefore/pico-sdk/lib/btstack/platform/embedded
|
||||
@@ -0,0 +1,69 @@
|
||||
-Wl,--wrap=__getreent
|
||||
|
||||
-Wl,--wrap=malloc
|
||||
-Wl,--wrap=calloc
|
||||
-Wl,--wrap=realloc
|
||||
-Wl,--wrap=free
|
||||
-Wl,--wrap=mallinfo
|
||||
|
||||
-Wl,--wrap=lwip_init
|
||||
|
||||
-Wl,--wrap=pbuf_header
|
||||
-Wl,--wrap=pbuf_free
|
||||
-Wl,--wrap=pbuf_alloc
|
||||
-Wl,--wrap=pbuf_take
|
||||
-Wl,--wrap=pbuf_copy_partial
|
||||
-Wl,--wrap=pbuf_ref
|
||||
-Wl,--wrap=pbuf_get_at
|
||||
-Wl,--wrap=pbuf_get_contiguous
|
||||
-Wl,--wrap=pbuf_cat
|
||||
|
||||
-Wl,--wrap=tcp_arg
|
||||
-Wl,--wrap=tcp_new
|
||||
-Wl,--wrap=tcp_bind
|
||||
-Wl,--wrap=tcp_listen
|
||||
-Wl,--wrap=tcp_listen_with_backlog
|
||||
-Wl,--wrap=tcp_accept
|
||||
-Wl,--wrap=tcp_connect
|
||||
-Wl,--wrap=tcp_write
|
||||
-Wl,--wrap=tcp_sent
|
||||
-Wl,--wrap=tcp_recv
|
||||
-Wl,--wrap=tcp_recved
|
||||
-Wl,--wrap=tcp_poll
|
||||
-Wl,--wrap=tcp_close
|
||||
-Wl,--wrap=tcp_abort
|
||||
-Wl,--wrap=tcp_err
|
||||
-Wl,--wrap=tcp_output
|
||||
-Wl,--wrap=tcp_setprio
|
||||
-Wl,--wrap=tcp_backlog_delayed
|
||||
-Wl,--wrap=tcp_backlog_accepted
|
||||
|
||||
-Wl,--wrap=udp_new
|
||||
-Wl,--wrap=udp_remove
|
||||
-Wl,--wrap=udp_bind
|
||||
-Wl,--wrap=udp_connect
|
||||
-Wl,--wrap=udp_disconnect
|
||||
-Wl,--wrap=udp_send
|
||||
-Wl,--wrap=udp_recv
|
||||
-Wl,--wrap=udp_sendto_if
|
||||
|
||||
-Wl,--wrap=sys_check_timeouts
|
||||
|
||||
-Wl,--wrap=dns_gethostbyname
|
||||
-Wl,--wrap=dns_gethostbyname_addrtype
|
||||
|
||||
-Wl,--wrap=raw_new
|
||||
-Wl,--wrap=raw_recv
|
||||
-Wl,--wrap=raw_bind
|
||||
-Wl,--wrap=raw_sendto
|
||||
-Wl,--wrap=raw_remove
|
||||
|
||||
-Wl,--wrap=netif_add
|
||||
-Wl,--wrap=netif_remove
|
||||
|
||||
-Wl,--wrap=cyw43_cb_process_ethernet
|
||||
-Wl,--wrap=cyw43_cb_tcpip_set_link_up
|
||||
-Wl,--wrap=cyw43_cb_tcpip_set_link_down
|
||||
-Wl,--wrap=cyw43_tcpip_link_status
|
||||
-Wl,--wrap=cyw43_cb_tcpip_init
|
||||
-Wl,--wrap=cyw43_cb_tcpip_deinit
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
source [find board/pico-debug.cfg]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user