Compare commits
@@ -0,0 +1,182 @@
|
||||
# Run whenever a PR is generated or updated.
|
||||
|
||||
|
||||
name: Arduino-Pico CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
# Me no spell so good
|
||||
code-spell:
|
||||
name: Check spelling
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Run codespell
|
||||
uses: codespell-project/actions-codespell@master
|
||||
with:
|
||||
skip: ./pico-extras,./ArduinoCore-API,./libraries/SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst
|
||||
ignore_words_list: ser,DOUT
|
||||
|
||||
# Consistent style
|
||||
astyle:
|
||||
name: Style, Boards, Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: false
|
||||
- name: Check package references
|
||||
run: |
|
||||
./tests/ci/pkgrefs_test.sh
|
||||
- name: Check boards.txt was not edited after makeboards.py
|
||||
run: |
|
||||
./tools/makeboards.py > boards.txt
|
||||
- name: Run astyle on all code/examples
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install astyle
|
||||
./tests/restyle.sh
|
||||
# If anything changed, GIT should return an error and fail the test
|
||||
git diff --exit-code
|
||||
|
||||
# Build all examples on linux (core and Arduino IDE)
|
||||
build-linux:
|
||||
name: Build ${{ matrix.chunk }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
chunk: [0, 1, 2, 3]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Linux toolchain
|
||||
id: cache-linux
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketches
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
BUILD_PARITY: custom
|
||||
mod: 4
|
||||
rem: ${{ matrix.chunk }}
|
||||
run: |
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ../pico-extras
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build.sh
|
||||
|
||||
# Build TinyUSB examples, requires custom build command line
|
||||
build-tinyusb:
|
||||
name: Build TinyUSB Examples
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Linux toolchain
|
||||
id: cache-linux
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketches
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
BUILD_PARITY: custom
|
||||
run: |
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ../pico-extras
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build-tinyusb.sh
|
||||
|
||||
# Single build under Windows to ensure the Win toolchain is good.
|
||||
build-windows:
|
||||
name: Windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Windows toolchain
|
||||
id: cache-windows
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketch
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
WINDOWS: 1
|
||||
BUILD_PARITY: custom
|
||||
mod: 500
|
||||
rem: 1
|
||||
run: |
|
||||
# Windows has python3 already installed, but it's called "python".
|
||||
# Copy python.exe to the proper name so scripts "just work".
|
||||
try { Get-Command python3 } catch { copy (get-command python).source (get-command python).source.Replace("python.exe", "python3.exe") }
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ../pico-extras
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build.sh
|
||||
|
||||
|
||||
# Single build under macOS to ensure the Mac toolchain is good.
|
||||
build-mac:
|
||||
name: Mac
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Cache Mac toolchain
|
||||
id: cache-mac
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./tools/dist
|
||||
key: ${{ runner.os }}-${{ hashFiles('package/package_pico_index.template.json', 'tests/common.sh') }}
|
||||
- name: Build Sketch
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
MACOSX: 1
|
||||
BUILD_PARITY: custom
|
||||
mod: 500
|
||||
rem: 1
|
||||
run: |
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd ../pico-extras
|
||||
git submodule update --init
|
||||
cd ..
|
||||
bash ./tests/build.sh
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
.DS_Store
|
||||
system
|
||||
tools/dist
|
||||
cores/rp2040/api
|
||||
+19
-1
@@ -1,9 +1,27 @@
|
||||
[submodule "ArduinoCore-API"]
|
||||
path = ArduinoCore-API
|
||||
url = https://github.com/arduino/ArduinoCore-API.git
|
||||
url = https://github.com/earlephilhower/ArduinoCore-API.git
|
||||
[submodule "pico-sdk"]
|
||||
path = pico-sdk
|
||||
url = https://github.com/raspberrypi/pico-sdk.git
|
||||
[submodule "system/pyserial"]
|
||||
path = tools/pyserial
|
||||
url = https://github.com/pyserial/pyserial.git
|
||||
[submodule "libraries/LittleFS/lib/littlefs"]
|
||||
path = libraries/LittleFS/lib/littlefs
|
||||
url = https://github.com/littlefs-project/littlefs.git
|
||||
[submodule "libraries/SdFat"]
|
||||
path = libraries/SdFat
|
||||
url = https://github.com/earlephilhower/ESP8266SdFat.git
|
||||
[submodule "pico-extras"]
|
||||
path = pico-extras
|
||||
url = https://github.com/raspberrypi/pico-extras.git
|
||||
[submodule "libraries/Keyboard"]
|
||||
path = libraries/Keyboard
|
||||
url = https://github.com/earlephilhower/Keyboard
|
||||
[submodule "libraries/Mouse"]
|
||||
path = libraries/Mouse
|
||||
url = https://github.com/earlephilhower/Mouse
|
||||
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
|
||||
path = libraries/Adafruit_TinyUSB_Arduino
|
||||
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
|
||||
|
||||
+1
-1
Submodule ArduinoCore-API updated: 2af4a9c721...9da5373517
@@ -1,18 +1,34 @@
|
||||
# Arduino-Pico
|
||||
# Arduino-Pico [](https://gitter.im/arduino-pico/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Raspberry Pi Pico Arduino core, for all RP2040 boards
|
||||
|
||||
This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosystem.
|
||||
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 10.2/Newlib 4.0 toolchain.
|
||||
|
||||
It uses a custom toolset with GCC 10.2 and Newlib 4.0.0, not depending on system-installed prerequisites. https://github.com/earlephilhower/pico-quick-toolchain
|
||||
# Documentation
|
||||
See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for more detailed usage information.
|
||||
|
||||
There is automated discovery of boards in bootloader mode, so they show up in the IDE, and the upload command works using the Microsoft UF2 tool (included).
|
||||
# Supported Boards
|
||||
* Raspberry Pi Pico
|
||||
* Adafruit Feather RP2040
|
||||
* Adafruit ItsyBitsy RP2040
|
||||
* Adafruit QTPy RP2040
|
||||
* Adafruit STEMMA Friend RP2040
|
||||
* Adafruit Trinkey RP2040 QT
|
||||
* Generic (configurable flash, I/O pins)
|
||||
|
||||
# Installing via Arduino Boards Manager
|
||||
**Windows Users**: Please do not use the Windows Store version of the actual Arduino application
|
||||
because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows"
|
||||
executable (EXE) download direct from https://arduino.cc. and allow it to install any device
|
||||
drivers it suggests. Otherwise the Pico board may not be detected. Also, if trying out the
|
||||
2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers
|
||||
are present. (See #20 for more details.)
|
||||
|
||||
Open up the Arduino IDE and go to File->Preferences.
|
||||
|
||||
In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field:
|
||||
|
||||
https://github.com/earlephilhower/arduino-pico/releases/download/0.9.0/package_rp2040_index.json
|
||||
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||

|
||||
|
||||
@@ -30,34 +46,94 @@ To install via GIT (for latest and greatest versions):
|
||||
mkdir -p ~/Arduino/hardware/pico
|
||||
git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/rp2040
|
||||
cd ~/Arduino/hardware/pico/rp2040
|
||||
git submodule init
|
||||
git submodule update
|
||||
git submodule update --init
|
||||
cd pico-sdk
|
||||
git submodule init
|
||||
git submodule update
|
||||
git submodule update --init
|
||||
cd ../pico-extras
|
||||
git submodule update --init
|
||||
cd ../tools
|
||||
python3 ./get.py
|
||||
`````
|
||||
|
||||
# Status of Port
|
||||
Lots of things are working now!
|
||||
* digitalWrite/Read (basic sanity tested)
|
||||
* shiftIn/Out (tested using Nokia5110 https://github.com/ionpan/Nokia5110)
|
||||
* SPI (tested using SdFat 2.0 https://github.com/greiman/SdFat ... note that the Pico voltage regulator can't reliably supply enough power for a SD Card so use external power, and adjust the `USE_SIMPLE_LITTLE_ENDIAN` define in `src/sdfat.h` to 0)
|
||||
* analogWrite/PWM (tested using Fade.ino)
|
||||
* tone/noTone (using IRQ generated waveform)
|
||||
* Wire/I2C (tested using DS3231 https://github.com/rodan/ds3231)
|
||||
* EEPROM (tested examples)
|
||||
* USB Serial(ACM) w/automatic reboot-to-UF2 upload)
|
||||
* Hardware UART
|
||||
* Servo (basic waveform testing, disables/re-enables without any short pulses)
|
||||
# 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.
|
||||
|
||||
After the first upload, this should not be necessary as the `arduino-pico` core has auto-reset support.
|
||||
Select the appropriate serial port shown in the Arduino Tools->Port->Serial Port menu once (this setting will stick and does not need to be
|
||||
touched for multiple uploads). This selection allows the auto-reset tool to identify the proper device to reset.
|
||||
Them hit the upload button and your sketch should upload and run.
|
||||
|
||||
In some cases the Pico will encounter a hard hang and its USB port will not respond to the auto-reset request. Should this happen, just
|
||||
follow the initial procedure of holding the BOOTSEL button down while plugging in the Pico to enter the ROM bootloader.
|
||||
|
||||
# Uploading Filesystem Images
|
||||
The onboard flash filesystem for the Pico, LittleFS, lets you upload a filesystem image from the sketch directory for your sketch to use. Download the needed plugin from
|
||||
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases
|
||||
|
||||
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
|
||||
|
||||
# Uploading Sketches with Picoprobe
|
||||
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", GROUP="users", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
sudo udevadm control --reload
|
||||
````
|
||||
|
||||
The first line creates a file with the USB vendor and ID of the Picoprobe 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 Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.
|
||||
|
||||
# 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.
|
||||
|
||||
# Features
|
||||
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
|
||||
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
|
||||
* Filesystems (LittleFS and SD/SDFS)
|
||||
* Multicore support (setup1() and loop1())
|
||||
* Overclocking and underclocking from the menus
|
||||
* digitalWrite/Read, shiftIn/Out, tone, analogWrite(PWM)/Read, temperature
|
||||
* Peripherals: SPI master, Wire(I2C) master/slave, dual UART, emulated EEPROM, I2S audio output, Servo
|
||||
* printf (i.e. debug) output over USB serial
|
||||
|
||||
The RP2040 PIO state machines (SMs) are used to generate jitter-free:
|
||||
* Servos
|
||||
* Tones
|
||||
* I2S Output
|
||||
|
||||
# Tutorials from Across the Web
|
||||
Here are some links to coverage and additional tutorials for using `arduino-pico`
|
||||
* The File:: class is taken from the ESP8266. See https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
|
||||
* Arduino Support for the Pi Pico available! And how fast is the Pico? - https://youtu.be/-XHh17cuH5E
|
||||
* Pre-release Adafruit QT Py RP2040 - https://www.youtube.com/watch?v=sfC1msqXX0I
|
||||
* Adafruit Feather RP2040 running LCD + TMP117 - https://www.youtube.com/watch?v=fKDeqZiIwHg
|
||||
* Demonstration of Servos and I2C in Korean - https://cafe.naver.com/arduinoshield/1201
|
||||
|
||||
# Contributing
|
||||
If you want to contribute or have bugfixes, drop me a note at <earlephilhower@yahoo.com> or open an issue/PR here.
|
||||
|
||||
# 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.
|
||||
* The [RP2040 GCC-based toolchain](https://github.com/earlephilhower/pico-quick-toolchain) is licensed under under the GPL.
|
||||
* The [Pico-SDK](https://github.com/raspberrypi/pico-sdk) and [Pico-Extras](https://github.com/raspberrypi/pico-extras) are by Raspberry Pi (Trading) Ltd and licensed under the BSD 3-Clause license.
|
||||
* [Arduino-Pico](https://github.com/earlephilhower/arduino-pico) core files are licensed under the LGPL.
|
||||
* [LittleFS](https://github.com/ARMmbed/littlefs) library written by ARM Limited and released under the [BSD 3-clause license](https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md).
|
||||
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
|
||||
* Some filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||
|
||||
-Earle F. Philhower, III
|
||||
earlephilhower@yahoo.com
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_generic_03h.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x0c, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61, 0x0a, 0x49, 0x19, 0x60
|
||||
.byte 0x0a, 0x49, 0x0b, 0x48, 0x01, 0x60, 0x00, 0x21, 0x59, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc
|
||||
.byte 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x07, 0x48, 0x07, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3
|
||||
.byte 0x08, 0x88, 0x08, 0x47, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x1f, 0x00, 0x18, 0x02, 0x00, 0x03
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 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, 0xea, 0x22, 0x4c, 0x5d
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_generic_03h.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x0c, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x0a, 0x49, 0x19, 0x60
|
||||
.byte 0x0a, 0x49, 0x0b, 0x48, 0x01, 0x60, 0x00, 0x21, 0x59, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc
|
||||
.byte 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x07, 0x48, 0x07, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3
|
||||
.byte 0x08, 0x88, 0x08, 0x47, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x1f, 0x00, 0x18, 0x02, 0x00, 0x03
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 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, 0x2c, 0xec, 0x21, 0x0d
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_is25lp080.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61, 0x29, 0x49, 0x19, 0x60
|
||||
.byte 0x01, 0x21, 0x99, 0x60, 0x28, 0x48, 0x00, 0xf0, 0x42, 0xf8, 0x28, 0x4a, 0x90, 0x42, 0x12, 0xd0
|
||||
.byte 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x32, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20
|
||||
.byte 0x1a, 0x66, 0x00, 0xf0, 0x2b, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x1f, 0x48, 0x00, 0xf0, 0x2f, 0xf8
|
||||
.byte 0x01, 0x21, 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1d, 0x49, 0x19, 0x60, 0x00, 0x21
|
||||
.byte 0x59, 0x60, 0x1c, 0x49, 0x1c, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66
|
||||
.byte 0xa0, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x17, 0x49, 0x16, 0x48
|
||||
.byte 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x14, 0x48
|
||||
.byte 0x14, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a
|
||||
.byte 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5
|
||||
.byte 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0
|
||||
.byte 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 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, 0xee, 0xfd, 0x2e, 0xe2
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_is25lp080.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x29, 0x49, 0x19, 0x60
|
||||
.byte 0x01, 0x21, 0x99, 0x60, 0x28, 0x48, 0x00, 0xf0, 0x42, 0xf8, 0x28, 0x4a, 0x90, 0x42, 0x12, 0xd0
|
||||
.byte 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x32, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20
|
||||
.byte 0x1a, 0x66, 0x00, 0xf0, 0x2b, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x1f, 0x48, 0x00, 0xf0, 0x2f, 0xf8
|
||||
.byte 0x01, 0x21, 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1d, 0x49, 0x19, 0x60, 0x00, 0x21
|
||||
.byte 0x59, 0x60, 0x1c, 0x49, 0x1c, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66
|
||||
.byte 0xa0, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x17, 0x49, 0x16, 0x48
|
||||
.byte 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x14, 0x48
|
||||
.byte 0x14, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a
|
||||
.byte 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5
|
||||
.byte 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0
|
||||
.byte 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 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, 0x28, 0x33, 0x43, 0xb2
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_w25q080.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60
|
||||
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61
|
||||
.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20
|
||||
.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0
|
||||
.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0
|
||||
.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21
|
||||
.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60
|
||||
.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21
|
||||
.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60
|
||||
.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49
|
||||
.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20
|
||||
.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66
|
||||
.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40
|
||||
.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_w25q080.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60
|
||||
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61
|
||||
.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20
|
||||
.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0
|
||||
.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0
|
||||
.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21
|
||||
.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60
|
||||
.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21
|
||||
.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60
|
||||
.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49
|
||||
.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20
|
||||
.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66
|
||||
.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40
|
||||
.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0b, 0x8f, 0xd5
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_w25x10cl.2.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x14, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61, 0x12, 0x49, 0x19, 0x60
|
||||
.byte 0x00, 0x21, 0x59, 0x60, 0x11, 0x49, 0x12, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xbb, 0x21
|
||||
.byte 0x19, 0x66, 0x02, 0x21, 0x19, 0x66, 0x08, 0x21, 0x98, 0x6a, 0x08, 0x42, 0xfc, 0xd0, 0x00, 0x21
|
||||
.byte 0x99, 0x60, 0x0c, 0x49, 0x0a, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28
|
||||
.byte 0x00, 0xd0, 0x00, 0x47, 0x08, 0x48, 0x09, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88
|
||||
.byte 0x08, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x3f, 0x00, 0x1d, 0x12, 0x00, 0x00
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x1e, 0x10, 0x00, 0x20, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.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, 0xba, 0x4f, 0x3e, 0xca
|
||||
@@ -0,0 +1,23 @@
|
||||
// Padded and checksummed version of: boot2_w25x10cl.4.bin
|
||||
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
.section .boot2, "ax"
|
||||
|
||||
.byte 0x00, 0xb5, 0x14, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x12, 0x49, 0x19, 0x60
|
||||
.byte 0x00, 0x21, 0x59, 0x60, 0x11, 0x49, 0x12, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xbb, 0x21
|
||||
.byte 0x19, 0x66, 0x02, 0x21, 0x19, 0x66, 0x08, 0x21, 0x98, 0x6a, 0x08, 0x42, 0xfc, 0xd0, 0x00, 0x21
|
||||
.byte 0x99, 0x60, 0x0c, 0x49, 0x0a, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28
|
||||
.byte 0x00, 0xd0, 0x00, 0x47, 0x08, 0x48, 0x09, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88
|
||||
.byte 0x08, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x3f, 0x00, 0x1d, 0x12, 0x00, 0x00
|
||||
.byte 0xf4, 0x00, 0x00, 0x18, 0x1e, 0x10, 0x00, 0x20, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0
|
||||
.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, 0x7c, 0x81, 0x53, 0x9a
|
||||
@@ -1,20 +0,0 @@
|
||||
// Padded and checksummed version of: /home/earle/src/pico/pico-examples/build/pico_sdk/src/rp2_common/boot_stage2/bs2_default.bin
|
||||
|
||||
.section .boot2, "a"
|
||||
|
||||
.byte 0x00, 0xb5, 0x2f, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60
|
||||
.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61
|
||||
.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x28, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20
|
||||
.byte 0x00, 0xf0, 0x3e, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0
|
||||
.byte 0x2e, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0
|
||||
.byte 0x26, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x29, 0xf8, 0x01, 0x21
|
||||
.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x18, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60
|
||||
.byte 0x17, 0x49, 0x18, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21
|
||||
.byte 0x19, 0x66, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x13, 0x49, 0x11, 0x48, 0x01, 0x60
|
||||
.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd1, 0x10, 0x48, 0x00, 0x47, 0x03, 0xb5
|
||||
.byte 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd
|
||||
.byte 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd
|
||||
.byte 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00
|
||||
.byte 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x01, 0x01, 0x00, 0x10
|
||||
.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, 0x3e, 0x27, 0x2a, 0x60
|
||||
+1949
-28
File diff suppressed because it is too large
Load Diff
+86
-21
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* Arduino header for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Arduino header for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
@@ -24,17 +24,58 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
// Wacky deprecated AVR compatibility functions
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
#include "api/ArduinoAPI.h"
|
||||
|
||||
#include <pins_arduino.h>
|
||||
|
||||
|
||||
// Required for the port*Register macros
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "debug_internal.h"
|
||||
|
||||
// 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()
|
||||
// is int but their macro "works" for everything (with potential side effects)
|
||||
#ifdef abs
|
||||
#undef abs
|
||||
#endif // abs
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
using std::abs;
|
||||
#else
|
||||
#define abs(x) ((x)>0?(x):-(x))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// For compatibility to many platforms and libraries
|
||||
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
|
||||
|
||||
// Disable/re-enable all interrupts. Safely handles nested disables
|
||||
void interrupts();
|
||||
void noInterrupts();
|
||||
|
||||
// GPIO change/value interrupts
|
||||
void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode);
|
||||
void detachInterrupt(pin_size_t pin);
|
||||
|
||||
// AVR compatibility macros...naughty and accesses the HW directly
|
||||
#define digitalPinToPort(pin) (0)
|
||||
#define digitalPinToBitMask(pin) (1UL << (pin))
|
||||
#define digitalPinToTimer(pin) (0)
|
||||
#define digitalPinToInterrupt(pin) (pin)
|
||||
#define NOT_AN_INTERRUPT (-1)
|
||||
#define portOutputRegister(port) ((volatile uint32_t*) sio_hw->gpio_out)
|
||||
#define portInputRegister(port) ((volatile uint32_t*) sio_hw->gpio_in)
|
||||
#define portModeRegister(port) ((volatile uint32_t*) sio_hw->gpio_oe)
|
||||
|
||||
// IO config
|
||||
void pinMode(pin_size_t pinNumber, PinMode pinMode);
|
||||
|
||||
// SIO (GPIO)
|
||||
@@ -43,23 +84,47 @@ PinStatus digitalRead(pin_size_t pinNumber);
|
||||
|
||||
// ADC
|
||||
int analogRead(pin_size_t pinNumber);
|
||||
float analogReadTemp(); // Returns core temp in Centigrade
|
||||
|
||||
// PWM
|
||||
void analogWrite(pin_size_t pinNumber, int value);
|
||||
void analogWriteFreq(uint32_t freq);
|
||||
void analogWriteRange(uint32_t range);
|
||||
void analogWriteResolution(int res);
|
||||
|
||||
// Timing
|
||||
void delay(unsigned long);
|
||||
void delayMicroseconds(unsigned int us);
|
||||
unsigned long millis();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Ancient AVR defines
|
||||
#define HAVE_HWSERIAL0
|
||||
#define HAVE_HWSERIAL1
|
||||
#define HAVE_HWSERIAL2
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
// Needed for declaring Serial
|
||||
#include "Adafruit_USBD_CDC.h"
|
||||
#else
|
||||
#include "SerialUSB.h"
|
||||
#endif
|
||||
|
||||
#include "SerialUART.h"
|
||||
#include "RP2040.h"
|
||||
#include "Bootsel.h"
|
||||
|
||||
// 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "hardware/structs/ioqspi.h"
|
||||
#include "hardware/structs/sio.h"
|
||||
|
||||
// This example blinks the Pico LED when the BOOTSEL button is pressed.
|
||||
//
|
||||
// Picoboard has a button attached to the flash CS pin, which the bootrom
|
||||
// checks, and jumps straight to the USB bootcode if the button is pressed
|
||||
// (pulling flash CS low). We can check this pin in by jumping to some code in
|
||||
// SRAM (so that the XIP interface is not required), floating the flash CS
|
||||
// pin, and observing whether it is pulled low.
|
||||
//
|
||||
// This doesn't work if others are trying to access flash at the same time,
|
||||
// e.g. XIP streamer, or the other core.
|
||||
|
||||
static bool __no_inline_not_in_flash_func(get_bootsel_button)() {
|
||||
const uint CS_PIN_INDEX = 1;
|
||||
|
||||
// Must disable interrupts, as interrupt handlers may be in flash, and we
|
||||
// are about to temporarily disable flash access!
|
||||
noInterrupts();
|
||||
rp2040.idleOtherCore();
|
||||
|
||||
// Set chip select to Hi-Z
|
||||
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
||||
GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||
|
||||
// Note we can't call into any sleep functions in flash right now
|
||||
for (volatile int i = 0; i < 1000; ++i);
|
||||
|
||||
// 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));
|
||||
|
||||
// Need to restore the state of chip select, else we are going to have a
|
||||
// bad time when we return to code in flash!
|
||||
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
|
||||
GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||
|
||||
interrupts();
|
||||
rp2040.resumeOtherCore();
|
||||
|
||||
return button_state;
|
||||
}
|
||||
|
||||
__Bootsel::operator bool() {
|
||||
return get_bootsel_button();
|
||||
}
|
||||
|
||||
__Bootsel BOOTSEL;
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Simple BOOTSEL reader object
|
||||
|
||||
Copyright (c) 2021 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
|
||||
|
||||
class __Bootsel {
|
||||
public:
|
||||
__Bootsel() { }
|
||||
operator bool();
|
||||
};
|
||||
|
||||
extern __Bootsel BOOTSEL;
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Client.h"
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
CoreMutex for the Raspberry Pi Pico RP2040
|
||||
|
||||
Implements a deadlock-safe multicore mutex for sharing things like the
|
||||
USB or UARTs.
|
||||
|
||||
Copyright (c) 2021 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 "pico/mutex.h"
|
||||
|
||||
class CoreMutex {
|
||||
public:
|
||||
CoreMutex(mutex_t *mutex) {
|
||||
uint32_t owner;
|
||||
_mutex = mutex;
|
||||
_acquired = false;
|
||||
if (!mutex_try_enter(_mutex, &owner)) {
|
||||
if (owner == get_core_num()) { // Deadlock!
|
||||
DEBUGCORE("CoreMutex - Deadlock detected!\n");
|
||||
return;
|
||||
}
|
||||
mutex_enter_blocking(_mutex);
|
||||
}
|
||||
_acquired = true;
|
||||
}
|
||||
|
||||
~CoreMutex() {
|
||||
if (_acquired) {
|
||||
mutex_exit(_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
operator bool() {
|
||||
return _acquired;
|
||||
}
|
||||
|
||||
private:
|
||||
mutex_t *_mutex;
|
||||
bool _acquired;
|
||||
};
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
FS.cpp - file system wrapper
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#include "FS.h"
|
||||
#include "FSImpl.h"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
static bool sflags(const char* mode, OpenMode& om, AccessMode& am);
|
||||
|
||||
size_t File::write(uint8_t c) {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->write(&c, 1);
|
||||
}
|
||||
|
||||
size_t File::write(const uint8_t *buf, size_t size) {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->write(buf, size);
|
||||
}
|
||||
|
||||
int File::available() {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->size() - _p->position();
|
||||
}
|
||||
|
||||
int File::availableForWrite() {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->availableForWrite();
|
||||
}
|
||||
|
||||
|
||||
int File::read() {
|
||||
if (!_p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t result;
|
||||
if (_p->read(&result, 1) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int File::read(uint8_t* buf, size_t size) {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->read(buf, size);
|
||||
}
|
||||
|
||||
int File::peek() {
|
||||
if (!_p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t curPos = _p->position();
|
||||
int result = read();
|
||||
seek(curPos, SeekSet);
|
||||
return result;
|
||||
}
|
||||
|
||||
void File::flush() {
|
||||
if (!_p) {
|
||||
return;
|
||||
}
|
||||
|
||||
_p->flush();
|
||||
}
|
||||
|
||||
bool File::seek(uint32_t pos, SeekMode mode) {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->seek(pos, mode);
|
||||
}
|
||||
|
||||
size_t File::position() const {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->position();
|
||||
}
|
||||
|
||||
size_t File::size() const {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->size();
|
||||
}
|
||||
|
||||
void File::close() {
|
||||
if (_p) {
|
||||
_p->close();
|
||||
_p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
File::operator bool() const {
|
||||
return !!_p;
|
||||
}
|
||||
|
||||
bool File::truncate(uint32_t size) {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->truncate(size);
|
||||
}
|
||||
|
||||
const char* File::name() const {
|
||||
if (!_p) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _p->name();
|
||||
}
|
||||
|
||||
const char* File::fullName() const {
|
||||
if (!_p) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _p->fullName();
|
||||
}
|
||||
|
||||
bool File::isFile() const {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->isFile();
|
||||
}
|
||||
|
||||
bool File::isDirectory() const {
|
||||
if (!_p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _p->isDirectory();
|
||||
}
|
||||
|
||||
void File::rewindDirectory() {
|
||||
if (!_fakeDir) {
|
||||
_fakeDir = std::make_shared<Dir>(_baseFS->openDir(fullName()));
|
||||
} else {
|
||||
_fakeDir->rewind();
|
||||
}
|
||||
}
|
||||
|
||||
File File::openNextFile() {
|
||||
if (!_fakeDir) {
|
||||
_fakeDir = std::make_shared<Dir>(_baseFS->openDir(fullName()));
|
||||
}
|
||||
_fakeDir->next();
|
||||
return _fakeDir->openFile("r");
|
||||
}
|
||||
|
||||
String File::readString() {
|
||||
String ret;
|
||||
ret.reserve(size() - position());
|
||||
char temp[256 + 1];
|
||||
int countRead = readBytes(temp, sizeof(temp) - 1);
|
||||
while (countRead > 0) {
|
||||
temp[countRead] = 0;
|
||||
ret += temp;
|
||||
countRead = readBytes(temp, sizeof(temp) - 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_t File::getLastWrite() {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->getLastWrite();
|
||||
}
|
||||
|
||||
time_t File::getCreationTime() {
|
||||
if (!_p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _p->getCreationTime();
|
||||
}
|
||||
|
||||
void File::setTimeCallback(time_t (*cb)(void)) {
|
||||
if (!_p) {
|
||||
return;
|
||||
}
|
||||
_p->setTimeCallback(cb);
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
File Dir::openFile(const char* mode) {
|
||||
if (!_impl) {
|
||||
return File();
|
||||
}
|
||||
|
||||
OpenMode om;
|
||||
AccessMode am;
|
||||
if (!sflags(mode, om, am)) {
|
||||
DEBUGV("Dir::openFile: invalid mode `%s`\r\n", mode);
|
||||
return File();
|
||||
}
|
||||
|
||||
File f(_impl->openFile(om, am), _baseFS);
|
||||
f.setTimeCallback(_timeCallback);
|
||||
return f;
|
||||
}
|
||||
|
||||
String Dir::fileName() {
|
||||
if (!_impl) {
|
||||
return String();
|
||||
}
|
||||
|
||||
return _impl->fileName();
|
||||
}
|
||||
|
||||
time_t Dir::fileTime() {
|
||||
if (!_impl) {
|
||||
return 0;
|
||||
}
|
||||
return _impl->fileTime();
|
||||
}
|
||||
|
||||
time_t Dir::fileCreationTime() {
|
||||
if (!_impl) {
|
||||
return 0;
|
||||
}
|
||||
return _impl->fileCreationTime();
|
||||
}
|
||||
|
||||
size_t Dir::fileSize() {
|
||||
if (!_impl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _impl->fileSize();
|
||||
}
|
||||
|
||||
bool Dir::isFile() const {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _impl->isFile();
|
||||
}
|
||||
|
||||
bool Dir::isDirectory() const {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _impl->isDirectory();
|
||||
}
|
||||
|
||||
bool Dir::next() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _impl->next();
|
||||
}
|
||||
|
||||
bool Dir::rewind() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _impl->rewind();
|
||||
}
|
||||
|
||||
void Dir::setTimeCallback(time_t (*cb)(void)) {
|
||||
if (!_impl) {
|
||||
return;
|
||||
}
|
||||
_impl->setTimeCallback(cb);
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
|
||||
bool FS::setConfig(const FSConfig &cfg) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _impl->setConfig(cfg);
|
||||
}
|
||||
|
||||
bool FS::begin() {
|
||||
if (!_impl) {
|
||||
DEBUGV("#error: FS: no implementation");
|
||||
return false;
|
||||
}
|
||||
_impl->setTimeCallback(_timeCallback);
|
||||
bool ret = _impl->begin();
|
||||
DEBUGV("%s\n", ret ? "" : "#error: FS could not start");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FS::end() {
|
||||
if (_impl) {
|
||||
_impl->end();
|
||||
}
|
||||
}
|
||||
|
||||
bool FS::gc() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->gc();
|
||||
}
|
||||
|
||||
bool FS::check() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->check();
|
||||
}
|
||||
|
||||
bool FS::format() {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->format();
|
||||
}
|
||||
|
||||
bool FS::info(FSInfo& info) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
File FS::open(const char* path, const char* mode) {
|
||||
if (!_impl) {
|
||||
return File();
|
||||
}
|
||||
|
||||
OpenMode om;
|
||||
AccessMode am;
|
||||
if (!sflags(mode, om, am)) {
|
||||
DEBUGV("FS::open: invalid mode `%s`\r\n", mode);
|
||||
return File();
|
||||
}
|
||||
File f(_impl->open(path, om, am), this);
|
||||
f.setTimeCallback(_timeCallback);
|
||||
return f;
|
||||
}
|
||||
|
||||
bool FS::exists(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->exists(path);
|
||||
}
|
||||
|
||||
bool FS::exists(const String& path) {
|
||||
return exists(path.c_str());
|
||||
}
|
||||
|
||||
Dir FS::openDir(const char* path) {
|
||||
if (!_impl) {
|
||||
return Dir();
|
||||
}
|
||||
DirImplPtr p = _impl->openDir(path);
|
||||
Dir d(p, this);
|
||||
d.setTimeCallback(_timeCallback);
|
||||
return d;
|
||||
}
|
||||
|
||||
Dir FS::openDir(const String& path) {
|
||||
return openDir(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::remove(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->remove(path);
|
||||
}
|
||||
|
||||
bool FS::remove(const String& path) {
|
||||
return remove(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::rmdir(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->rmdir(path);
|
||||
}
|
||||
|
||||
bool FS::rmdir(const String& path) {
|
||||
return rmdir(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::mkdir(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->mkdir(path);
|
||||
}
|
||||
|
||||
bool FS::mkdir(const String& path) {
|
||||
return mkdir(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::rename(const char* pathFrom, const char* pathTo) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->rename(pathFrom, pathTo);
|
||||
}
|
||||
|
||||
bool FS::rename(const String& pathFrom, const String& pathTo) {
|
||||
return rename(pathFrom.c_str(), pathTo.c_str());
|
||||
}
|
||||
|
||||
time_t FS::getCreationTime() {
|
||||
if (!_impl) {
|
||||
return 0;
|
||||
}
|
||||
return _impl->getCreationTime();
|
||||
}
|
||||
|
||||
void FS::setTimeCallback(time_t (*cb)(void)) {
|
||||
if (!_impl) {
|
||||
return;
|
||||
}
|
||||
_impl->setTimeCallback(cb);
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
|
||||
static bool sflags(const char* mode, OpenMode& om, AccessMode& am) {
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
am = AM_READ;
|
||||
om = OM_DEFAULT;
|
||||
break;
|
||||
case 'w':
|
||||
am = AM_WRITE;
|
||||
om = (OpenMode)(OM_CREATE | OM_TRUNCATE);
|
||||
break;
|
||||
case 'a':
|
||||
am = AM_WRITE;
|
||||
om = (OpenMode)(OM_CREATE | OM_APPEND);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (mode[1]) {
|
||||
case '+':
|
||||
am = (AccessMode)(AM_WRITE | AM_READ);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(FS_FREESTANDING_FUNCTIONS)
|
||||
|
||||
/*
|
||||
TODO: move these functions to public API:
|
||||
*/
|
||||
File open(const char* path, const char* mode);
|
||||
File open(String& path, const char* mode);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
Dir openDir(String& path);
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint);
|
||||
/*
|
||||
*/
|
||||
|
||||
|
||||
struct MountEntry {
|
||||
FSImplPtr fs;
|
||||
String path;
|
||||
MountEntry* next;
|
||||
};
|
||||
|
||||
static MountEntry* s_mounted = nullptr;
|
||||
|
||||
template<>
|
||||
bool mount<FS>(FS& fs, const char* mountPoint) {
|
||||
FSImplPtr p = fs._impl;
|
||||
if (!p || !p->mount()) {
|
||||
DEBUGV("FSImpl mount failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
!make sure mountPoint has trailing '/' here
|
||||
|
||||
MountEntry* entry = new MountEntry;
|
||||
entry->fs = p;
|
||||
entry->path = mountPoint;
|
||||
entry->next = s_mounted;
|
||||
s_mounted = entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
iterate over MountEntries and look for the ones which match the path
|
||||
*/
|
||||
File open(const char* path, const char* mode) {
|
||||
OpenMode om;
|
||||
AccessMode am;
|
||||
if (!sflags(mode, om, am)) {
|
||||
DEBUGV("open: invalid mode `%s`\r\n", mode);
|
||||
return File();
|
||||
}
|
||||
|
||||
for (MountEntry* entry = s_mounted; entry; entry = entry->next) {
|
||||
size_t offset = entry->path.length();
|
||||
if (strstr(path, entry->path.c_str())) {
|
||||
File result = entry->fs->open(path + offset);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return File();
|
||||
}
|
||||
|
||||
File open(const String& path, const char* mode) {
|
||||
return FS::open(path.c_str(), mode);
|
||||
}
|
||||
|
||||
Dir openDir(const String& path) {
|
||||
return openDir(path.c_str());
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
FS.h - file system wrapper
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef FS_H
|
||||
#define FS_H
|
||||
|
||||
#include <memory>
|
||||
#include <Arduino.h>
|
||||
#include <../include/time.h> // See issue #6714
|
||||
|
||||
class SDClass;
|
||||
|
||||
namespace fs {
|
||||
|
||||
class File;
|
||||
class Dir;
|
||||
class FS;
|
||||
|
||||
class FileImpl;
|
||||
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
||||
class FSImpl;
|
||||
typedef std::shared_ptr<FSImpl> FSImplPtr;
|
||||
class DirImpl;
|
||||
typedef std::shared_ptr<DirImpl> DirImplPtr;
|
||||
|
||||
template <typename Tfs>
|
||||
bool mount(Tfs& fs, const char* mountPoint);
|
||||
|
||||
enum SeekMode {
|
||||
SeekSet = 0,
|
||||
SeekCur = 1,
|
||||
SeekEnd = 2
|
||||
};
|
||||
|
||||
class File : public Stream {
|
||||
public:
|
||||
File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { }
|
||||
|
||||
// Print methods:
|
||||
size_t write(uint8_t) override;
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
int availableForWrite() override;
|
||||
|
||||
// Stream methods:
|
||||
int available() override;
|
||||
int read() override;
|
||||
int peek() override;
|
||||
void flush() override;
|
||||
size_t readBytes(char *buffer, size_t length) {
|
||||
return read((uint8_t*)buffer, length);
|
||||
}
|
||||
int read(uint8_t* buf, size_t size);
|
||||
bool seek(uint32_t pos, SeekMode mode);
|
||||
bool seek(uint32_t pos) {
|
||||
return seek(pos, SeekSet);
|
||||
}
|
||||
size_t position() const;
|
||||
size_t size() const;
|
||||
virtual ssize_t streamRemaining() {
|
||||
return (ssize_t)size() - (ssize_t)position();
|
||||
}
|
||||
void close();
|
||||
operator bool() const;
|
||||
const char* name() const;
|
||||
const char* fullName() const; // Includes path
|
||||
bool truncate(uint32_t size);
|
||||
|
||||
bool isFile() const;
|
||||
bool isDirectory() const;
|
||||
|
||||
// Arduino "class SD" methods for compatibility
|
||||
//TODO use stream::send / check read(buf,size) result
|
||||
template<typename T> size_t write(T &src) {
|
||||
uint8_t obuf[256];
|
||||
size_t doneLen = 0;
|
||||
size_t sentLen;
|
||||
int i;
|
||||
|
||||
while (src.available() > sizeof(obuf)) {
|
||||
src.read(obuf, sizeof(obuf));
|
||||
sentLen = write(obuf, sizeof(obuf));
|
||||
doneLen = doneLen + sentLen;
|
||||
if (sentLen != sizeof(obuf)) {
|
||||
return doneLen;
|
||||
}
|
||||
}
|
||||
|
||||
size_t leftLen = src.available();
|
||||
src.read(obuf, leftLen);
|
||||
sentLen = write(obuf, leftLen);
|
||||
doneLen = doneLen + sentLen;
|
||||
return doneLen;
|
||||
}
|
||||
using Print::write;
|
||||
|
||||
void rewindDirectory();
|
||||
File openNextFile();
|
||||
|
||||
String readString();
|
||||
|
||||
time_t getLastWrite();
|
||||
time_t getCreationTime();
|
||||
void setTimeCallback(time_t (*cb)(void));
|
||||
|
||||
protected:
|
||||
FileImplPtr _p;
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
|
||||
// Arduino SD class emulation
|
||||
std::shared_ptr<Dir> _fakeDir;
|
||||
FS *_baseFS;
|
||||
};
|
||||
|
||||
class Dir {
|
||||
public:
|
||||
Dir(DirImplPtr impl = DirImplPtr(), FS *baseFS = nullptr): _impl(impl), _baseFS(baseFS) { }
|
||||
|
||||
File openFile(const char* mode);
|
||||
|
||||
String fileName();
|
||||
size_t fileSize();
|
||||
time_t fileTime();
|
||||
time_t fileCreationTime();
|
||||
bool isFile() const;
|
||||
bool isDirectory() const;
|
||||
|
||||
bool next();
|
||||
bool rewind();
|
||||
|
||||
void setTimeCallback(time_t (*cb)(void));
|
||||
|
||||
protected:
|
||||
DirImplPtr _impl;
|
||||
FS *_baseFS;
|
||||
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 {
|
||||
uint64_t totalBytes;
|
||||
uint64_t usedBytes;
|
||||
size_t blockSize;
|
||||
size_t pageSize;
|
||||
size_t maxOpenFiles;
|
||||
size_t maxPathLength;
|
||||
};
|
||||
|
||||
|
||||
class FSConfig {
|
||||
public:
|
||||
static constexpr uint32_t FSId = 0x00000000;
|
||||
|
||||
FSConfig(uint32_t type = FSId, bool autoFormat = true) : _type(type), _autoFormat(autoFormat) { }
|
||||
|
||||
FSConfig setAutoFormat(bool val = true) {
|
||||
_autoFormat = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t _type;
|
||||
bool _autoFormat;
|
||||
};
|
||||
|
||||
class SPIFFSConfig : public FSConfig {
|
||||
public:
|
||||
static constexpr uint32_t FSId = 0x53504946;
|
||||
SPIFFSConfig(bool autoFormat = true) : FSConfig(FSId, autoFormat) { }
|
||||
|
||||
// Inherit _type and _autoFormat
|
||||
// nothing yet, enableTime TBD when SPIFFS has metadate
|
||||
};
|
||||
|
||||
class FS {
|
||||
public:
|
||||
FS(FSImplPtr impl) : _impl(impl) {
|
||||
_timeCallback = _defaultTimeCB;
|
||||
}
|
||||
|
||||
bool setConfig(const FSConfig &cfg);
|
||||
|
||||
bool begin();
|
||||
void end();
|
||||
|
||||
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);
|
||||
|
||||
bool exists(const char* path);
|
||||
bool exists(const String& path);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
Dir openDir(const String& path);
|
||||
|
||||
bool remove(const char* path);
|
||||
bool remove(const String& path);
|
||||
|
||||
bool rename(const char* pathFrom, const char* pathTo);
|
||||
bool rename(const String& pathFrom, const String& pathTo);
|
||||
|
||||
bool mkdir(const char* path);
|
||||
bool mkdir(const String& path);
|
||||
|
||||
bool rmdir(const char* path);
|
||||
bool rmdir(const String& path);
|
||||
|
||||
// Low-level FS routines, not needed by most applications
|
||||
bool gc();
|
||||
bool check();
|
||||
|
||||
time_t getCreationTime();
|
||||
|
||||
void setTimeCallback(time_t (*cb)(void));
|
||||
|
||||
friend class ::SDClass; // More of a frenemy, but SD needs internal implementation to get private FAT bits
|
||||
protected:
|
||||
FSImplPtr _impl;
|
||||
FSImplPtr getImpl() {
|
||||
return _impl;
|
||||
}
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
static time_t _defaultTimeCB(void) {
|
||||
return time(NULL);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace fs
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void close_all_fs(void);
|
||||
void littlefs_request_end(void);
|
||||
void spiffs_request_end(void);
|
||||
}
|
||||
|
||||
#ifndef FS_NO_GLOBALS
|
||||
using fs::FS;
|
||||
using fs::File;
|
||||
using fs::Dir;
|
||||
using fs::SeekMode;
|
||||
using fs::SeekSet;
|
||||
using fs::SeekCur;
|
||||
using fs::SeekEnd;
|
||||
using fs::FSInfo;
|
||||
using fs::FSConfig;
|
||||
using fs::SPIFFSConfig;
|
||||
#endif //FS_NO_GLOBALS
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPIFFS)
|
||||
extern fs::FS SPIFFS __attribute__((deprecated("SPIFFS has been deprecated. Please consider moving to LittleFS or other filesystems.")));
|
||||
#endif
|
||||
|
||||
#endif //FS_H
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
FSImpl.h - base file system interface
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
*/
|
||||
#ifndef FSIMPL_H
|
||||
#define FSIMPL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <FS.h>
|
||||
|
||||
namespace fs {
|
||||
|
||||
class FileImpl {
|
||||
public:
|
||||
virtual ~FileImpl() { }
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
virtual int read(uint8_t* buf, size_t size) = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual bool seek(uint32_t pos, SeekMode mode) = 0;
|
||||
virtual size_t position() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
virtual int availableForWrite() {
|
||||
return 0;
|
||||
}
|
||||
virtual bool truncate(uint32_t size) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual const char* name() const = 0;
|
||||
virtual const char* fullName() const = 0;
|
||||
virtual bool isFile() const = 0;
|
||||
virtual bool isDirectory() const = 0;
|
||||
|
||||
// Filesystems *may* support a timestamp per-file, so allow the user to override with
|
||||
// their own callback for *this specific* file (as opposed to the FSImpl call of the
|
||||
// same name. The default implementation simply returns time(null)
|
||||
virtual void setTimeCallback(time_t (*cb)(void)) {
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
// Return the last written time for a file. Undefined when called on a writable file
|
||||
// as the FS is allowed to return either the time of the last write() operation or the
|
||||
// time present in the filesystem metadata (often the last time the file was closed)
|
||||
virtual time_t getLastWrite() {
|
||||
return 0; // Default is to not support timestamps
|
||||
}
|
||||
// Same for creation time.
|
||||
virtual time_t getCreationTime() {
|
||||
return 0; // Default is to not support timestamps
|
||||
}
|
||||
|
||||
protected:
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
};
|
||||
|
||||
enum OpenMode {
|
||||
OM_DEFAULT = 0,
|
||||
OM_CREATE = 1,
|
||||
OM_APPEND = 2,
|
||||
OM_TRUNCATE = 4
|
||||
};
|
||||
|
||||
enum AccessMode {
|
||||
AM_READ = 1,
|
||||
AM_WRITE = 2,
|
||||
AM_RW = AM_READ | AM_WRITE
|
||||
};
|
||||
|
||||
class DirImpl {
|
||||
public:
|
||||
virtual ~DirImpl() { }
|
||||
virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0;
|
||||
virtual const char* fileName() = 0;
|
||||
virtual size_t fileSize() = 0;
|
||||
// Return the last written time for a file. Undefined when called on a writable file
|
||||
// as the FS is allowed to return either the time of the last write() operation or the
|
||||
// time present in the filesystem metadata (often the last time the file was closed)
|
||||
virtual time_t fileTime() {
|
||||
return 0; // By default, FS doesn't report file times
|
||||
}
|
||||
virtual time_t fileCreationTime() {
|
||||
return 0; // By default, FS doesn't report file times
|
||||
}
|
||||
virtual bool isFile() const = 0;
|
||||
virtual bool isDirectory() const = 0;
|
||||
virtual bool next() = 0;
|
||||
virtual bool rewind() = 0;
|
||||
|
||||
// Filesystems *may* support a timestamp per-file, so allow the user to override with
|
||||
// their own callback for *this specific* file (as opposed to the FSImpl call of the
|
||||
// same name. The default implementation simply returns time(null)
|
||||
virtual void setTimeCallback(time_t (*cb)(void)) {
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
protected:
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
};
|
||||
|
||||
class FSImpl {
|
||||
public:
|
||||
virtual ~FSImpl() { }
|
||||
virtual bool setConfig(const FSConfig &cfg) = 0;
|
||||
virtual bool begin() = 0;
|
||||
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;
|
||||
virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
|
||||
virtual bool remove(const char* path) = 0;
|
||||
virtual bool mkdir(const char* path) = 0;
|
||||
virtual bool rmdir(const char* path) = 0;
|
||||
virtual bool gc() {
|
||||
return true; // May not be implemented in all file systems.
|
||||
}
|
||||
virtual bool check() {
|
||||
return true; // May not be implemented in all file systems.
|
||||
}
|
||||
virtual time_t getCreationTime() {
|
||||
return 0; // May not be implemented in all file systems.
|
||||
}
|
||||
|
||||
// Filesystems *may* support a timestamp per-file, so allow the user to override with
|
||||
// their own callback for all files on this FS. The default implementation simply
|
||||
// returns the present time as reported by time(null)
|
||||
virtual void setTimeCallback(time_t (*cb)(void)) {
|
||||
_timeCallback = cb;
|
||||
}
|
||||
|
||||
protected:
|
||||
time_t (*_timeCallback)(void) = nullptr;
|
||||
};
|
||||
|
||||
} // namespace fs
|
||||
|
||||
#endif //FSIMPL_H
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/HardwareSerial.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/IPAddress.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Interrupts.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Printable.h"
|
||||
+137
-25
@@ -1,55 +1,167 @@
|
||||
/*
|
||||
* RP2040 utility class
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
RP2040 utility class
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <hardware/pio.h>
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <hardware/pio.h>
|
||||
#include <pico/multicore.h>
|
||||
#include <pico/util/queue.h>
|
||||
#include <CoreMutex.h>
|
||||
|
||||
class _MFIFO {
|
||||
public:
|
||||
_MFIFO() { /* noop */ };
|
||||
~_MFIFO() { /* noop */ };
|
||||
|
||||
void begin(int cores) {
|
||||
constexpr int FIFOCNT = 8;
|
||||
if (cores == 1) {
|
||||
_multicore = false;
|
||||
return;
|
||||
}
|
||||
mutex_init(&_idleMutex);
|
||||
queue_init(&_queue[0], sizeof(uint32_t), FIFOCNT);
|
||||
queue_init(&_queue[1], sizeof(uint32_t), FIFOCNT);
|
||||
_multicore = true;
|
||||
}
|
||||
|
||||
void registerCore() {
|
||||
multicore_fifo_clear_irq();
|
||||
irq_set_exclusive_handler(SIO_IRQ_PROC0 + get_core_num(), _irq);
|
||||
irq_set_enabled(SIO_IRQ_PROC0 + get_core_num(), true);
|
||||
}
|
||||
|
||||
void push(uint32_t val) {
|
||||
while (!push_nb(val)) { /* noop */ }
|
||||
}
|
||||
|
||||
bool push_nb(uint32_t val) {
|
||||
// Push to the other FIFO
|
||||
return queue_try_add(&_queue[get_core_num() ^ 1], &val);
|
||||
}
|
||||
|
||||
uint32_t pop() {
|
||||
uint32_t ret;
|
||||
while (!pop_nb(&ret)) { /* noop */ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool pop_nb(uint32_t *val) {
|
||||
// Pop from my own FIFO
|
||||
return queue_try_remove(&_queue[get_core_num()], val);
|
||||
}
|
||||
|
||||
int available() {
|
||||
return queue_get_level(&_queue[get_core_num()]);
|
||||
}
|
||||
|
||||
void idleOtherCore() {
|
||||
if (!_multicore) {
|
||||
return;
|
||||
}
|
||||
mutex_enter_blocking(&_idleMutex);
|
||||
_otherIdled = false;
|
||||
multicore_fifo_push_blocking(_GOTOSLEEP);
|
||||
while (!_otherIdled) { /* noop */ }
|
||||
}
|
||||
|
||||
void resumeOtherCore() {
|
||||
if (!_multicore) {
|
||||
return;
|
||||
}
|
||||
mutex_exit(&_idleMutex);
|
||||
_otherIdled = false;
|
||||
// Other core will exit busy-loop and return to operation
|
||||
// once otherIdled == false.
|
||||
}
|
||||
|
||||
private:
|
||||
static void __no_inline_not_in_flash_func(_irq)() {
|
||||
multicore_fifo_clear_irq();
|
||||
noInterrupts(); // We need total control, can't run anything
|
||||
while (multicore_fifo_rvalid()) {
|
||||
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
|
||||
_otherIdled = true;
|
||||
while (_otherIdled) { /* noop */ }
|
||||
break;
|
||||
}
|
||||
}
|
||||
interrupts();
|
||||
}
|
||||
bool _multicore = false;
|
||||
|
||||
mutex_t _idleMutex;
|
||||
static volatile bool _otherIdled;
|
||||
queue_t _queue[2];
|
||||
|
||||
static constexpr int _GOTOSLEEP = 0x66666666;
|
||||
};
|
||||
|
||||
class RP2040 {
|
||||
public:
|
||||
// Convert from microseconds to PIO clock cycles
|
||||
static int usToPIOCycles(int us) {
|
||||
// Parenthesis needed to guarantee order of operations to avoid 32bit overflow
|
||||
return (us * ( clock_get_hz(clk_sys) / 1000000 ));
|
||||
return (us * (clock_get_hz(clk_sys) / 1000000));
|
||||
}
|
||||
|
||||
// Get current clock frequency
|
||||
static int f_cpu() {
|
||||
return clock_get_hz(clk_sys);
|
||||
}
|
||||
|
||||
void idleOtherCore() {
|
||||
fifo.idleOtherCore();
|
||||
}
|
||||
void resumeOtherCore() {
|
||||
fifo.resumeOtherCore();
|
||||
}
|
||||
|
||||
// Multicore comms FIFO
|
||||
_MFIFO fifo;
|
||||
};
|
||||
|
||||
extern RP2040 rp2040;
|
||||
|
||||
// Wrapper class for PIO programs, abstracting common operations out
|
||||
// TODO - Make dualcore safe
|
||||
// TODO - Add unload/destructor
|
||||
class PIOProgram {
|
||||
public:
|
||||
PIOProgram(const pio_program_t *pgm) { _pgm = pgm; }
|
||||
PIOProgram(const pio_program_t *pgm) {
|
||||
_pgm = pgm;
|
||||
}
|
||||
|
||||
// Possibly load into a PIO and allocate a SM
|
||||
bool prepare(PIO *pio, int *sm, int *offset) {
|
||||
extern mutex_t _pioMutex;
|
||||
CoreMutex m(&_pioMutex);
|
||||
// Is there an open slot to run in, first?
|
||||
if (!_findFreeSM(pio, sm)) return false;
|
||||
// Is it loaded on that PIO?
|
||||
if (!_findFreeSM(pio, sm)) {
|
||||
return false;
|
||||
}
|
||||
// Is it loaded on that PIO?
|
||||
if (_offset[pio_get_index(*pio)] < 0) {
|
||||
// Nope, need to load it
|
||||
if (!pio_can_add_program(*pio, _pgm)) return false;
|
||||
if (!pio_can_add_program(*pio, _pgm)) {
|
||||
return false;
|
||||
}
|
||||
_offset[pio_get_index(*pio)] = pio_add_program(*pio, _pgm);
|
||||
}
|
||||
// Here it's guaranteed loaded, return values
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
Shared USB for the Raspberry Pi Pico RP2040
|
||||
Allows for multiple endpoints to share the USB controller
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#ifndef USE_TINYUSB
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "CoreMutex.h"
|
||||
#include "RP2040USB.h"
|
||||
|
||||
#include "tusb.h"
|
||||
#include "class/hid/hid_device.h"
|
||||
#include "class/audio/audio.h"
|
||||
#include "class/midi/midi.h"
|
||||
#include "pico/time.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "pico/mutex.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||
// have multiple cores updating the TUSB state in parallel
|
||||
mutex_t __usb_mutex;
|
||||
|
||||
// USB processing will be a periodic timer task
|
||||
#define USB_TASK_INTERVAL 1000
|
||||
#define USB_TASK_IRQ 31
|
||||
|
||||
// USB VID/PID (note that PID can change depending on the add'l interfaces)
|
||||
#define USBD_VID (0x2E8A) // Raspberry Pi
|
||||
|
||||
#ifdef SERIALUSB_PID
|
||||
#define USBD_PID (SERIALUSB_PID)
|
||||
#else
|
||||
#define USBD_PID (0x000a) // Raspberry Pi Pico SDK CDC
|
||||
#endif
|
||||
|
||||
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
|
||||
#define USBD_MAX_POWER_MA (250)
|
||||
|
||||
#define USBD_ITF_CDC (0) // needs 2 interfaces
|
||||
#define USBD_ITF_MAX (2)
|
||||
|
||||
#define USBD_CDC_EP_CMD (0x81)
|
||||
#define USBD_CDC_EP_OUT (0x02)
|
||||
#define USBD_CDC_EP_IN (0x82)
|
||||
#define USBD_CDC_CMD_MAX_SIZE (8)
|
||||
#define USBD_CDC_IN_OUT_MAX_SIZE (64)
|
||||
|
||||
#define USBD_STR_0 (0x00)
|
||||
#define USBD_STR_MANUF (0x01)
|
||||
#define USBD_STR_PRODUCT (0x02)
|
||||
#define USBD_STR_SERIAL (0x03)
|
||||
#define USBD_STR_CDC (0x04)
|
||||
|
||||
|
||||
#define EPNUM_HID 0x83
|
||||
|
||||
#define EPNUM_MIDI 0x01
|
||||
|
||||
|
||||
const uint8_t *tud_descriptor_device_cb(void) {
|
||||
static tusb_desc_device_t usbd_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_CDC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = USBD_VID,
|
||||
.idProduct = USBD_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUF,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallMIDI) {
|
||||
// Can use as-is, this is the default USB case
|
||||
return (const uint8_t *)&usbd_desc_device;
|
||||
}
|
||||
// Need a multi-endpoint config which will require changing the PID to help Windows not barf
|
||||
if (__USBInstallKeyboard) {
|
||||
usbd_desc_device.idProduct |= 0x8000;
|
||||
}
|
||||
if (__USBInstallMouse) {
|
||||
usbd_desc_device.idProduct |= 0x4000;
|
||||
}
|
||||
if (__USBInstallMIDI) {
|
||||
usbd_desc_device.idProduct |= 0x2000;
|
||||
}
|
||||
// Set the device class to 0 to indicate multiple device classes
|
||||
usbd_desc_device.bDeviceClass = 0;
|
||||
usbd_desc_device.bDeviceSubClass = 0;
|
||||
usbd_desc_device.bDeviceProtocol = 0;
|
||||
return (const uint8_t *)&usbd_desc_device;
|
||||
}
|
||||
|
||||
int __USBGetKeyboardReportID() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __USBGetMouseReportID() {
|
||||
return __USBInstallKeyboard ? 2 : 1;
|
||||
}
|
||||
|
||||
static uint8_t *GetDescHIDReport(int *len) {
|
||||
if (__USBInstallKeyboard && __USBInstallMouse) {
|
||||
static uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1)),
|
||||
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(2))
|
||||
};
|
||||
if (len) {
|
||||
*len = sizeof(desc_hid_report);
|
||||
}
|
||||
return desc_hid_report;
|
||||
} else if (__USBInstallKeyboard && ! __USBInstallMouse) {
|
||||
static uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(1))
|
||||
};
|
||||
if (len) {
|
||||
*len = sizeof(desc_hid_report);
|
||||
}
|
||||
return desc_hid_report;
|
||||
} else { // if (!__USBInstallKeyboard && __USBInstallMouse) {
|
||||
static uint8_t desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(1))
|
||||
};
|
||||
if (len) {
|
||||
*len = sizeof(desc_hid_report);
|
||||
}
|
||||
return desc_hid_report;
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_hid_descriptor_report_cb(void) {
|
||||
return GetDescHIDReport(nullptr);
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
|
||||
(void)index;
|
||||
static uint8_t *usbd_desc_cfg;
|
||||
|
||||
if (!usbd_desc_cfg) {
|
||||
bool hasHID = __USBInstallKeyboard || __USBInstallMouse;
|
||||
|
||||
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0);
|
||||
|
||||
static uint8_t cdc_desc[TUD_CDC_DESC_LEN] = {
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE)
|
||||
};
|
||||
|
||||
int hid_report_len;
|
||||
GetDescHIDReport(&hid_report_len);
|
||||
uint8_t hid_itf = __USBInstallSerial ? 2 : 0;
|
||||
static uint8_t hid_desc[TUD_HID_DESC_LEN] = {
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
TUD_HID_DESCRIPTOR(hid_itf, 0, HID_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||
};
|
||||
|
||||
uint8_t midi_itf = hid_itf + (hasHID ? 1 : 0);
|
||||
static uint8_t midi_desc[TUD_MIDI_DESC_LEN] = {
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(midi_itf, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
|
||||
};
|
||||
|
||||
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMIDI ? sizeof(midi_desc) : 0);
|
||||
|
||||
static uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, interface_count, USBD_STR_0, usbd_desc_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA)
|
||||
};
|
||||
|
||||
// Combine to one descriptor
|
||||
usbd_desc_cfg = (uint8_t *)malloc(usbd_desc_len);
|
||||
bzero(usbd_desc_cfg, usbd_desc_len);
|
||||
uint8_t *ptr = usbd_desc_cfg;
|
||||
memcpy(ptr, tud_cfg_desc, sizeof(tud_cfg_desc));
|
||||
ptr += sizeof(tud_cfg_desc);
|
||||
if (__USBInstallSerial) {
|
||||
memcpy(ptr, cdc_desc, sizeof(cdc_desc));
|
||||
ptr += sizeof(cdc_desc);
|
||||
}
|
||||
if (hasHID) {
|
||||
memcpy(ptr, hid_desc, sizeof(hid_desc));
|
||||
ptr += sizeof(hid_desc);
|
||||
}
|
||||
if (__USBInstallMIDI) {
|
||||
memcpy(ptr, midi_desc, sizeof(midi_desc));
|
||||
}
|
||||
}
|
||||
return usbd_desc_cfg;
|
||||
}
|
||||
|
||||
const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
(void) langid;
|
||||
#define DESC_STR_MAX (20)
|
||||
static uint16_t desc_str[DESC_STR_MAX];
|
||||
|
||||
static char idString[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1];
|
||||
|
||||
static const char *const usbd_desc_str[] = {
|
||||
[USBD_STR_0] = "",
|
||||
[USBD_STR_MANUF] = "Raspberry Pi",
|
||||
[USBD_STR_PRODUCT] = "PicoArduino",
|
||||
[USBD_STR_SERIAL] = idString,
|
||||
[USBD_STR_CDC] = "Board CDC",
|
||||
};
|
||||
|
||||
if (!idString[0]) {
|
||||
// Get ID string into human readable serial number on the first pass
|
||||
pico_unique_board_id_t id;
|
||||
pico_get_unique_board_id(&id);
|
||||
idString[0] = 0;
|
||||
for (auto i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; i++) {
|
||||
char hx[3];
|
||||
sprintf(hx, "%02X", id.id[i]);
|
||||
strcat(idString, hx);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t len;
|
||||
if (index == 0) {
|
||||
desc_str[1] = 0x0409; // supported language is English
|
||||
len = 1;
|
||||
} else {
|
||||
if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
|
||||
return NULL;
|
||||
}
|
||||
const char *str = usbd_desc_str[index];
|
||||
for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
|
||||
desc_str[1 + len] = str[len];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2);
|
||||
|
||||
return desc_str;
|
||||
}
|
||||
|
||||
|
||||
static void usb_irq() {
|
||||
// if the mutex is already owned, then we are in user code
|
||||
// in this file which will do a tud_task itself, so we'll just do nothing
|
||||
// until the next tick; we won't starve
|
||||
if (mutex_try_enter(&__usb_mutex, NULL)) {
|
||||
tud_task();
|
||||
mutex_exit(&__usb_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
|
||||
irq_set_pending(USB_TASK_IRQ);
|
||||
return USB_TASK_INTERVAL;
|
||||
}
|
||||
|
||||
void __USBStart() {
|
||||
if (tusb_inited()) {
|
||||
// Already called
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_init(&__usb_mutex);
|
||||
tusb_init();
|
||||
|
||||
irq_set_exclusive_handler(USB_TASK_IRQ, usb_irq);
|
||||
irq_set_enabled(USB_TASK_IRQ, true);
|
||||
|
||||
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
// Invoked when received GET_REPORT control request
|
||||
// Application must fill buffer report's content and return its length.
|
||||
// Return zero will cause the stack to STALL request
|
||||
uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
|
||||
// TODO not Implemented
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) reqlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invoked when received SET_REPORT control request or
|
||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||
void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
|
||||
// TODO set LED based on CAPLOCK, NUMLOCK etc...
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Shared USB for the Raspberry Pi Pico RP2040
|
||||
Allows for multiple endpoints to share the USB controller
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include "pico/mutex.h"
|
||||
|
||||
// Weak function definitions for each type of endpoint
|
||||
extern void __USBInstallSerial() __attribute__((weak));
|
||||
extern void __USBInstallKeyboard() __attribute__((weak));
|
||||
extern void __USBInstallMouse() __attribute__((weak));
|
||||
extern void __USBInstallMIDI() __attribute__((weak));
|
||||
|
||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||
// have multiple cores updating the TUSB state in parallel
|
||||
extern mutex_t __usb_mutex;
|
||||
|
||||
// HID report ID inquiry (report ID will vary depending on the number/type of other HID)
|
||||
int __USBGetKeyboardReportID();
|
||||
int __USBGetMouseReportID();
|
||||
|
||||
// Called by main() to init the USB HW/SW.
|
||||
void __USBStart();
|
||||
+102
-54
@@ -1,47 +1,74 @@
|
||||
/*
|
||||
* Serial-over-UART for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Serial-over-UART for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include "SerialUART.h"
|
||||
#include "CoreMutex.h"
|
||||
#include <hardware/uart.h>
|
||||
#include <hardware/gpio.h>
|
||||
|
||||
bool SerialUART::setPinout(pin_size_t tx, pin_size_t rx) {
|
||||
const uint32_t uart_tx[2] = { 0b000010001000000000001000100000, 0b100000000000100010000000000010 };
|
||||
const uint32_t uart_rx[2] = { 0b000001000100000000000100010000, 0b010000000000010001000000000001 };
|
||||
if ( ((1 << tx) & uart_tx[uart_get_index(_uart)]) &&
|
||||
((1 << rx) & uart_rx[uart_get_index(_uart)]) ) {
|
||||
if (_running) {
|
||||
pinMode(_tx, INPUT);
|
||||
pinMode(_rx, INPUT);
|
||||
}
|
||||
_tx = tx;
|
||||
// SerialEvent functions are weak, so when the user doesn't define them,
|
||||
// the linker just sets their address to 0 (which is checked below).
|
||||
// The Serialx_available is just a wrapper around Serialx.available(),
|
||||
// but we can refer to it weakly so we don't pull in the entire
|
||||
// HardwareSerial instance if the user doesn't also refer to it.
|
||||
extern void serialEvent1() __attribute__((weak));
|
||||
extern void serialEvent2() __attribute__((weak));
|
||||
|
||||
bool SerialUART::setRX(pin_size_t rx) {
|
||||
constexpr uint32_t valid[2] = { __bitset({1, 13, 17, 29}) /* UART0 */,
|
||||
__bitset({5, 9, 21, 25}) /* UART1 */
|
||||
};
|
||||
if (_running) {
|
||||
DEBUGCORE("ERROR: SerialUART setRX while running\n");
|
||||
return false;
|
||||
} else if ((1 << rx) & valid[uart_get_index(_uart)]) {
|
||||
_rx = rx;
|
||||
if (_running) {
|
||||
gpio_set_function(_tx, GPIO_FUNC_UART);
|
||||
gpio_set_function(_rx, GPIO_FUNC_UART);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
DEBUGCORE("ERROR: SerialUART setRX illegal pin (%d)\n", rx);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SerialUART::setTX(pin_size_t tx) {
|
||||
constexpr uint32_t valid[2] = { __bitset({0, 12, 16, 28}) /* UART0 */,
|
||||
__bitset({4, 8, 20, 24}) /* UART1 */
|
||||
};
|
||||
if (_running) {
|
||||
DEBUGCORE("ERROR: SerialUART setTX while running\n");
|
||||
return false;
|
||||
} else if ((1 << tx) & valid[uart_get_index(_uart)]) {
|
||||
_tx = tx;
|
||||
return true;
|
||||
} else {
|
||||
DEBUGCORE("ERROR: SerialUART setTX illegal pin (%d)\n", tx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) {
|
||||
_uart = uart;
|
||||
_tx = tx;
|
||||
_rx = rx;
|
||||
mutex_init(&_mutex);
|
||||
}
|
||||
|
||||
void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
_baud = baud;
|
||||
@@ -49,19 +76,19 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
int bits, stop;
|
||||
uart_parity_t parity;
|
||||
switch (config & SERIAL_PARITY_MASK) {
|
||||
case SERIAL_PARITY_EVEN: parity = UART_PARITY_EVEN; break;
|
||||
case SERIAL_PARITY_ODD: parity = UART_PARITY_ODD; break;
|
||||
default: parity = UART_PARITY_NONE; break;
|
||||
case SERIAL_PARITY_EVEN: parity = UART_PARITY_EVEN; break;
|
||||
case SERIAL_PARITY_ODD: parity = UART_PARITY_ODD; break;
|
||||
default: parity = UART_PARITY_NONE; break;
|
||||
}
|
||||
switch ( config & SERIAL_STOP_BIT_MASK) {
|
||||
case SERIAL_STOP_BIT_1: stop = 1; break;
|
||||
default: stop = 2; break;
|
||||
switch (config & SERIAL_STOP_BIT_MASK) {
|
||||
case SERIAL_STOP_BIT_1: stop = 1; break;
|
||||
default: stop = 2; break;
|
||||
}
|
||||
switch (config & SERIAL_DATA_MASK) {
|
||||
case SERIAL_DATA_5: bits = 5; break;
|
||||
case SERIAL_DATA_6: bits = 6; break;
|
||||
case SERIAL_DATA_7: bits = 7; break;
|
||||
default: bits = 8; break;
|
||||
case SERIAL_DATA_5: bits = 5; break;
|
||||
case SERIAL_DATA_6: bits = 6; break;
|
||||
case SERIAL_DATA_7: bits = 7; break;
|
||||
default: bits = 8; break;
|
||||
}
|
||||
uart_set_format(_uart, bits, stop, parity);
|
||||
gpio_set_function(_tx, GPIO_FUNC_UART);
|
||||
@@ -71,12 +98,16 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
|
||||
}
|
||||
|
||||
void SerialUART::end() {
|
||||
if (!_running) {
|
||||
return;
|
||||
}
|
||||
uart_deinit(_uart);
|
||||
_running = false;
|
||||
}
|
||||
|
||||
int SerialUART::peek() {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return -1;
|
||||
}
|
||||
if (_peek >= 0) {
|
||||
@@ -87,7 +118,8 @@ int SerialUART::peek() {
|
||||
}
|
||||
|
||||
int SerialUART::read() {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return -1;
|
||||
}
|
||||
if (_peek >= 0) {
|
||||
@@ -99,28 +131,32 @@ int SerialUART::read() {
|
||||
}
|
||||
|
||||
int SerialUART::available() {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
return (uart_is_readable(_uart)) ? 1 : 0;
|
||||
}
|
||||
|
||||
int SerialUART::availableForWrite() {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
return (uart_is_writable(_uart)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void SerialUART::flush() {
|
||||
// TODO, must be smarter way. Now, just sleep long enough to guarantee a full FIFO goes out (very conservative)
|
||||
//int us_per_bit = 1 + (1000000 / _baud);
|
||||
//delayMicroseconds(us_per_bit * 32 * 8);
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return;
|
||||
}
|
||||
uart_default_tx_wait_blocking();
|
||||
}
|
||||
|
||||
size_t SerialUART::write(uint8_t c) {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
uart_putc_raw(_uart, c);
|
||||
@@ -128,7 +164,8 @@ size_t SerialUART::write(uint8_t c) {
|
||||
}
|
||||
|
||||
size_t SerialUART::write(const uint8_t *p, size_t len) {
|
||||
if (!_running) {
|
||||
CoreMutex m(&_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
size_t cnt = len;
|
||||
@@ -144,6 +181,17 @@ SerialUART::operator bool() {
|
||||
return _running;
|
||||
}
|
||||
|
||||
SerialUART Serial1(uart0, 0, 1);
|
||||
SerialUART Serial2(uart1, 4, 5);
|
||||
SerialUART Serial1(uart0, PIN_SERIAL1_TX, PIN_SERIAL1_RX);
|
||||
SerialUART Serial2(uart1, PIN_SERIAL2_TX, PIN_SERIAL2_RX);
|
||||
|
||||
void arduino::serialEvent1Run(void) {
|
||||
if (serialEvent1 && Serial1.available()) {
|
||||
serialEvent1();
|
||||
}
|
||||
}
|
||||
|
||||
void arduino::serialEvent2Run(void) {
|
||||
if (serialEvent2 && Serial2.available()) {
|
||||
serialEvent2();
|
||||
}
|
||||
}
|
||||
|
||||
+38
-48
@@ -1,39 +1,48 @@
|
||||
/*
|
||||
* Serial-over-UART for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Serial-over-UART for the Raspberry Pi Pico RP2040
|
||||
|
||||
#ifndef __SERIALUART_H__
|
||||
#define __SERIALUART_H__
|
||||
Copyright (c) 2021 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 <Arduino.h>
|
||||
#include "api/HardwareSerial.h"
|
||||
#include <stdarg.h>
|
||||
#include "CoreMutex.h"
|
||||
|
||||
extern "C" typedef struct uart_inst uart_inst_t;
|
||||
|
||||
class SerialUART : public HardwareSerial {
|
||||
public:
|
||||
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) { _uart = uart; _tx = tx; _rx = rx; }
|
||||
|
||||
bool setPinout(pin_size_t tx, pin_size_t rx);
|
||||
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx);
|
||||
|
||||
void begin(unsigned long baud = 115200) override { begin(baud, SERIAL_8N1); };
|
||||
// Select the pinout. Call before .begin()
|
||||
bool setRX(pin_size_t pin);
|
||||
bool setTX(pin_size_t pin);
|
||||
bool setPinout(pin_size_t tx, pin_size_t rx) {
|
||||
bool ret = setRX(rx);
|
||||
ret &= setTX(tx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void begin(unsigned long baud = 115200) override {
|
||||
begin(baud, SERIAL_8N1);
|
||||
};
|
||||
void begin(unsigned long baud, uint16_t config) override;
|
||||
void end() override;
|
||||
|
||||
@@ -47,38 +56,19 @@ public:
|
||||
using Print::write;
|
||||
operator bool() override;
|
||||
|
||||
// By all rights, this should be in Print.h...
|
||||
size_t printf(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = write((const uint8_t*) buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
private:
|
||||
bool _running = false;
|
||||
uart_inst_t *_uart;
|
||||
pin_size_t _tx, _rx;
|
||||
int _baud;
|
||||
int _peek;
|
||||
mutex_t _mutex;
|
||||
};
|
||||
|
||||
extern SerialUART Serial1; // HW UART 0
|
||||
extern SerialUART Serial2; // HW UART 1
|
||||
|
||||
#endif
|
||||
namespace arduino {
|
||||
extern void serialEvent1Run(void) __attribute__((weak));
|
||||
extern void serialEvent2Run(void) __attribute__((weak));
|
||||
};
|
||||
|
||||
+116
-208
@@ -1,149 +1,53 @@
|
||||
/*
|
||||
* Serial-Over-USB for the Raspberry Pi Pico RP2040
|
||||
* Implements an ACM which will reboot into UF2 mode on a 1200bps DTR toggle.
|
||||
* Much of this was modified from the Raspberry Pi Pico SDK stdio_usb.c file.
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Serial-Over-USB for the Raspberry Pi Pico RP2040
|
||||
Implements an ACM which will reboot into UF2 mode on a 1200bps DTR toggle.
|
||||
Much of this was modified from the Raspberry Pi Pico SDK stdio_usb.c file.
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#ifndef USE_TINYUSB
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "CoreMutex.h"
|
||||
|
||||
#include "tusb.h"
|
||||
#include "pico/time.h"
|
||||
#include "pico/binary_info.h"
|
||||
extern "C" {
|
||||
#include "pico/bootrom.h"
|
||||
}
|
||||
#include "pico/bootrom.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "pico/mutex.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
#define PICO_STDIO_USB_TASK_INTERVAL_US 1000
|
||||
#define PICO_STDIO_USB_LOW_PRIORITY_IRQ 31
|
||||
#ifndef DISABLE_USB_SERIAL
|
||||
// Ensure we are installed in the USB chain
|
||||
void __USBInstallSerial() { /* noop */ }
|
||||
#endif
|
||||
|
||||
#define USBD_VID (0x2E8A) // Raspberry Pi
|
||||
#define USBD_PID (0x000a) // Raspberry Pi Pico SDK CDC
|
||||
// SerialEvent functions are weak, so when the user doesn't define them,
|
||||
// the linker just sets their address to 0 (which is checked below).
|
||||
// The Serialx_available is just a wrapper around Serialx.available(),
|
||||
// but we can refer to it weakly so we don't pull in the entire
|
||||
// HardwareSerial instance if the user doesn't also refer to it.
|
||||
extern void serialEvent() __attribute__((weak));
|
||||
|
||||
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
|
||||
#define USBD_MAX_POWER_MA (250)
|
||||
|
||||
#define USBD_ITF_CDC (0) // needs 2 interfaces
|
||||
#define USBD_ITF_MAX (2)
|
||||
|
||||
#define USBD_CDC_EP_CMD (0x81)
|
||||
#define USBD_CDC_EP_OUT (0x02)
|
||||
#define USBD_CDC_EP_IN (0x82)
|
||||
#define USBD_CDC_CMD_MAX_SIZE (8)
|
||||
#define USBD_CDC_IN_OUT_MAX_SIZE (64)
|
||||
|
||||
#define USBD_STR_0 (0x00)
|
||||
#define USBD_STR_MANUF (0x01)
|
||||
#define USBD_STR_PRODUCT (0x02)
|
||||
#define USBD_STR_SERIAL (0x03)
|
||||
#define USBD_STR_CDC (0x04)
|
||||
|
||||
// Note: descriptors returned from callbacks must exist long enough for transfer to complete
|
||||
|
||||
static const tusb_desc_device_t usbd_desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.idVendor = USBD_VID,
|
||||
.idProduct = USBD_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
.iManufacturer = USBD_STR_MANUF,
|
||||
.iProduct = USBD_STR_PRODUCT,
|
||||
.iSerialNumber = USBD_STR_SERIAL,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
|
||||
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
|
||||
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
|
||||
};
|
||||
|
||||
static char _idString[PICO_UNIQUE_BOARD_ID_SIZE_BYTES * 2 + 1];
|
||||
|
||||
static const char *const usbd_desc_str[] = {
|
||||
[USBD_STR_0] = "",
|
||||
[USBD_STR_MANUF] = "Raspberry Pi",
|
||||
[USBD_STR_PRODUCT] = "PicoArduino",
|
||||
[USBD_STR_SERIAL] = _idString,
|
||||
[USBD_STR_CDC] = "Board CDC",
|
||||
};
|
||||
|
||||
const uint8_t *tud_descriptor_device_cb(void) {
|
||||
return (const uint8_t *)&usbd_desc_device;
|
||||
}
|
||||
|
||||
const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
|
||||
(void)index;
|
||||
return usbd_desc_cfg;
|
||||
}
|
||||
|
||||
const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
#define DESC_STR_MAX (20)
|
||||
static uint16_t desc_str[DESC_STR_MAX];
|
||||
|
||||
uint8_t len;
|
||||
if (index == 0) {
|
||||
desc_str[1] = 0x0409; // supported language is English
|
||||
len = 1;
|
||||
} else {
|
||||
if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
|
||||
return NULL;
|
||||
}
|
||||
const char *str = usbd_desc_str[index];
|
||||
for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
|
||||
desc_str[1 + len] = str[len];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2);
|
||||
|
||||
return desc_str;
|
||||
}
|
||||
|
||||
static mutex_t usb_mutex;
|
||||
|
||||
static void low_priority_worker_irq() {
|
||||
// if the mutex is already owned, then we are in user code
|
||||
// in this file which will do a tud_task itself, so we'll just do nothing
|
||||
// until the next tick; we won't starve
|
||||
if (mutex_try_enter(&usb_mutex, NULL)) {
|
||||
tud_task();
|
||||
mutex_exit(&usb_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
|
||||
irq_set_pending(PICO_STDIO_USB_LOW_PRIORITY_IRQ);
|
||||
return PICO_STDIO_USB_TASK_INTERVAL_US;
|
||||
}
|
||||
extern mutex_t __usb_mutex;
|
||||
|
||||
void SerialUSB::begin(unsigned long baud) {
|
||||
(void) baud; //ignored
|
||||
@@ -152,24 +56,6 @@ void SerialUSB::begin(unsigned long baud) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get ID string into human readable serial number
|
||||
pico_unique_board_id_t id;
|
||||
pico_get_unique_board_id(&id);
|
||||
_idString[0] = 0;
|
||||
for (auto i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; i++) {
|
||||
char hx[3];
|
||||
sprintf(hx, "%02X", id.id[i]);
|
||||
strcat(_idString, hx);
|
||||
}
|
||||
|
||||
tusb_init();
|
||||
|
||||
irq_set_exclusive_handler(PICO_STDIO_USB_LOW_PRIORITY_IRQ, low_priority_worker_irq);
|
||||
irq_set_enabled(PICO_STDIO_USB_LOW_PRIORITY_IRQ, true);
|
||||
|
||||
mutex_init(&usb_mutex);
|
||||
add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
|
||||
|
||||
_running = true;
|
||||
}
|
||||
|
||||
@@ -178,90 +64,103 @@ void SerialUSB::end() {
|
||||
}
|
||||
|
||||
int SerialUSB::peek() {
|
||||
uint8_t c;
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return -1; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
auto ret = tud_cdc_peek(0, &c) ? (int) c : -1;
|
||||
mutex_exit(&usb_mutex);
|
||||
return ret;
|
||||
|
||||
uint8_t c;
|
||||
return tud_cdc_peek(0, &c) ? (int) c : -1;
|
||||
}
|
||||
|
||||
int SerialUSB::read() {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return -1; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tud_cdc_connected() && tud_cdc_available()) {
|
||||
int ch = tud_cdc_read_char();
|
||||
mutex_exit(&usb_mutex);
|
||||
return ch;
|
||||
return tud_cdc_read_char();
|
||||
}
|
||||
mutex_exit(&usb_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SerialUSB::available() {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return 0; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
auto ret = tud_cdc_available();
|
||||
mutex_exit(&usb_mutex);
|
||||
return ret;
|
||||
|
||||
return tud_cdc_available();
|
||||
}
|
||||
|
||||
int SerialUSB::availableForWrite() {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return 0; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
auto ret = tud_cdc_write_available();
|
||||
mutex_exit(&usb_mutex);
|
||||
return ret;
|
||||
|
||||
return tud_cdc_write_available();
|
||||
}
|
||||
|
||||
void SerialUSB::flush() {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return;
|
||||
}
|
||||
|
||||
tud_cdc_write_flush();
|
||||
mutex_exit(&usb_mutex);
|
||||
}
|
||||
|
||||
size_t SerialUSB::write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
size_t SerialUSB::write(const uint8_t *p, size_t len) {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return 0; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
|
||||
size_t SerialUSB::write(const uint8_t *buf, size_t length) {
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return 0;
|
||||
}
|
||||
size_t remain = len;
|
||||
while (remain && tud_cdc_connected()) {
|
||||
size_t cnt = tud_cdc_write(p, remain);
|
||||
p += cnt;
|
||||
remain -= cnt;
|
||||
tud_task();
|
||||
tud_cdc_write_flush();
|
||||
|
||||
static uint64_t last_avail_time;
|
||||
int i = 0;
|
||||
if (tud_cdc_connected()) {
|
||||
for (size_t i = 0; i < length;) {
|
||||
int n = length - i;
|
||||
int avail = tud_cdc_write_available();
|
||||
if (n > avail) {
|
||||
n = avail;
|
||||
}
|
||||
if (n) {
|
||||
int n2 = tud_cdc_write(buf + i, n);
|
||||
tud_task();
|
||||
tud_cdc_write_flush();
|
||||
i += n2;
|
||||
last_avail_time = time_us_64();
|
||||
} else {
|
||||
tud_task();
|
||||
tud_cdc_write_flush();
|
||||
if (!tud_cdc_connected() ||
|
||||
(!tud_cdc_write_available() && time_us_64() > last_avail_time + 1000000 /* 1 second */)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// reset our timeout
|
||||
last_avail_time = 0;
|
||||
}
|
||||
mutex_exit(&usb_mutex);
|
||||
return len - remain;
|
||||
return i;
|
||||
}
|
||||
|
||||
SerialUSB::operator bool() {
|
||||
uint32_t owner;
|
||||
if (!mutex_try_enter(&usb_mutex, &owner)) {
|
||||
if (owner == get_core_num()) return -1; // would deadlock otherwise
|
||||
mutex_enter_blocking(&usb_mutex);
|
||||
CoreMutex m(&__usb_mutex);
|
||||
if (!_running || !m) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tud_task();
|
||||
auto ret = tud_cdc_connected();
|
||||
mutex_exit(&usb_mutex);
|
||||
return ret;
|
||||
return tud_cdc_connected();
|
||||
}
|
||||
|
||||
|
||||
@@ -270,21 +169,30 @@ static bool _rts = false;
|
||||
static int _bps = 115200;
|
||||
static void CheckSerialReset() {
|
||||
if ((_bps == 1200) && (!_dtr)) {
|
||||
reset_usb_boot(0,0);
|
||||
while (1); // WDT will fire here
|
||||
reset_usb_boot(0, 0);
|
||||
while (1); // WDT will fire here
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
|
||||
(void) itf;
|
||||
_dtr = dtr ? true : false;
|
||||
_rts = rts ? true : false;
|
||||
CheckSerialReset();
|
||||
}
|
||||
|
||||
extern "C" void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) {
|
||||
(void) itf;
|
||||
_bps = p_line_coding->bit_rate;
|
||||
CheckSerialReset();
|
||||
}
|
||||
|
||||
|
||||
SerialUSB Serial;
|
||||
|
||||
void arduino::serialEventRun(void) {
|
||||
if (serialEvent && Serial.available()) {
|
||||
serialEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+26
-43
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* Serial-over-USB for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Serial-over-USB for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#ifndef __SERIALUSB_H__
|
||||
#define __SERIALUSB_H__
|
||||
@@ -29,7 +29,10 @@ class SerialUSB : public HardwareSerial {
|
||||
public:
|
||||
SerialUSB() { }
|
||||
void begin(unsigned long baud = 115200) override;
|
||||
void begin(unsigned long baud, uint16_t config) override { begin(baud); };
|
||||
void begin(unsigned long baud, uint16_t config) override {
|
||||
(void) config;
|
||||
begin(baud);
|
||||
};
|
||||
void end() override;
|
||||
|
||||
virtual int peek() override;
|
||||
@@ -42,34 +45,14 @@ public:
|
||||
using Print::write;
|
||||
operator bool() override;
|
||||
|
||||
// By all rights, this should be in Print.h...
|
||||
size_t printf(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = write((const uint8_t*) buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _running = false;
|
||||
};
|
||||
|
||||
extern SerialUSB Serial;
|
||||
|
||||
namespace arduino {
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Server.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Stream.h"
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018, hathach for Adafruit
|
||||
|
||||
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
|
||||
//--------------------------------------------------------------------
|
||||
#ifdef USE_TINYUSB
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
#else
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE
|
||||
#endif
|
||||
|
||||
//#ifndef CFG_TUSB_MCU
|
||||
// #define CFG_TUSB_MCU OPT_MCU_RP2040
|
||||
//#endif
|
||||
#define CFG_TUSB_OS OPT_OS_PICO
|
||||
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
//#if CFG_TUSB_DEBUG
|
||||
// #define tu_printf serial1_printf
|
||||
// extern int serial1_printf(const char *__restrict __format, ...);
|
||||
//#endif
|
||||
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#define CFG_TUD_ENDOINT0_SIZE 64
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_CDC 1
|
||||
#define CFG_TUD_MSC 1
|
||||
#define CFG_TUD_HID 1
|
||||
#define CFG_TUD_MIDI 1
|
||||
#define CFG_TUD_VENDOR 1
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 256
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 256
|
||||
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE 512
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_BUFSIZE 64
|
||||
|
||||
// MIDI FIFO size of TX and RX
|
||||
#define CFG_TUD_MIDI_RX_BUFSIZE 128
|
||||
#define CFG_TUD_MIDI_TX_BUFSIZE 128
|
||||
|
||||
// Vendor FIFO size of TX and RX
|
||||
#define CFG_TUD_VENDOR_RX_BUFSIZE 64
|
||||
#define CFG_TUD_VENDOR_TX_BUFSIZE 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
+46
-28
@@ -1,24 +1,25 @@
|
||||
/*
|
||||
* Tone for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Tone for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "CoreMutex.h"
|
||||
#include <hardware/gpio.h>
|
||||
#include <pico/time.h>
|
||||
#include <map>
|
||||
@@ -29,17 +30,30 @@ typedef struct {
|
||||
int sm;
|
||||
} Tone;
|
||||
|
||||
#include "tone.pio.h"
|
||||
PIOProgram _tonePgm(&tone_program);
|
||||
// Keep std::map safe for multicore use
|
||||
auto_init_mutex(_toneMutex);
|
||||
|
||||
|
||||
#include "tone.pio.h"
|
||||
static PIOProgram _tonePgm(&tone_program);
|
||||
static std::map<pin_size_t, Tone *> _toneMap;
|
||||
|
||||
void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
DEBUGCORE("TONE: tone(%d, %d, %d)\n", pin, frequency, duration);
|
||||
if (pin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
if (!frequency) {
|
||||
noTone(pin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure only 1 core can start or stop at a time
|
||||
CoreMutex m(&_toneMutex);
|
||||
if (!m) {
|
||||
return; // Weird deadlock case
|
||||
}
|
||||
|
||||
int us = 1000000 / frequency / 2;
|
||||
if (us < 5) {
|
||||
us = 5;
|
||||
@@ -50,15 +64,15 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
if (entry != _toneMap.end()) {
|
||||
noTone(pin);
|
||||
}
|
||||
DEBUGCORE("TONE: phaseUS=%d, phaseCnt=%d\n", us, phases);
|
||||
|
||||
auto newTone = new Tone();
|
||||
newTone->pin = pin;
|
||||
pinMode(pin, OUTPUT);
|
||||
int off;
|
||||
if (!_tonePgm.prepare(&newTone->pio, &newTone->sm, &off)) {
|
||||
DEBUGCORE("TONE: Unable to start, out of PIO resources\n");
|
||||
DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n");
|
||||
// ERROR, no free slots
|
||||
delete newTone;
|
||||
delete newTone;
|
||||
return;
|
||||
}
|
||||
tone_program_init(newTone->pio, newTone->sm, off, pin);
|
||||
@@ -69,17 +83,21 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
|
||||
pio_sm_set_enabled(newTone->pio, newTone->sm, true);
|
||||
pio_sm_put_blocking(newTone->pio, newTone->sm, phases);
|
||||
|
||||
DEBUGCORE("TONE: Began on pio=%p, sm=%d\n", newTone->pio, newTone->sm);
|
||||
_toneMap.insert({pin, newTone});
|
||||
}
|
||||
|
||||
void noTone(uint8_t pin) {
|
||||
DEBUGCORE("NOTONE: noTone(%d)\n", pin);
|
||||
CoreMutex m(&_toneMutex);
|
||||
|
||||
if ((pin > 29) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
auto entry = _toneMap.find(pin);
|
||||
if (entry != _toneMap.end()) {
|
||||
DEBUGCORE("NOTONE: Disabling PIO tone generator pio=%p, sm=%d\n", entry->second->pio, entry->second->sm);
|
||||
pio_sm_set_enabled(entry->second->pio, entry->second->sm, false);
|
||||
pio_sm_unclaim(entry->second->pio, entry->second->sm);
|
||||
pio_sm_unclaim(entry->second->pio, entry->second->sm);
|
||||
delete entry->second;
|
||||
_toneMap.erase(entry);
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, LOW);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "api/Udp.h"
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right 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
|
||||
*/
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdint.h"
|
||||
|
||||
void randomSeed(uint32_t dwSeed) {
|
||||
if (dwSeed != 0) {
|
||||
srand(dwSeed) ;
|
||||
}
|
||||
}
|
||||
|
||||
long random(long howbig) {
|
||||
if (howbig == 0) {
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
return rand() % howbig;
|
||||
}
|
||||
|
||||
long random(long howsmall, long howbig) {
|
||||
if (howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
|
||||
long diff = howbig - howsmall;
|
||||
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../ArduinoCore-API/api/
|
||||
@@ -1,46 +1,46 @@
|
||||
/*
|
||||
* Core debug macros header for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Core debug macros header for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#if !defined(DEBUG_RP2040_PORT)
|
||||
#define DEBUGV(...) do { } while(0)
|
||||
#define DEBUGCORE(...) do { } while(0)
|
||||
#define DEBUGWIRE(...) do { } while(0)
|
||||
#define DEBUGSPI(...) do { } while(0)
|
||||
#define DEBUGV(...) do { } while(0)
|
||||
#define DEBUGCORE(...) do { } while(0)
|
||||
#define DEBUGWIRE(...) do { } while(0)
|
||||
#define DEBUGSPI(...) do { } while(0)
|
||||
#else
|
||||
#define DEBUGV(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#define DEBUGV(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
|
||||
#if defined(DEBUG_RP2040_CORE)
|
||||
#define DEBUGCORE(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGCORE(...) do { } while(0)
|
||||
#endif
|
||||
#if defined(DEBUG_RP2040_CORE)
|
||||
#define DEBUGCORE(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGCORE(...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_RP2040_WIRE)
|
||||
#define DEBUGWIRE(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGWIRE(...) do { } while(0)
|
||||
#endif
|
||||
#if defined(DEBUG_RP2040_WIRE)
|
||||
#define DEBUGWIRE(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGWIRE(...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_RP2040_SPI)
|
||||
#define DEBUGSPI(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGSPI(...) do { } while(0)
|
||||
#endif
|
||||
#if defined(DEBUG_RP2040_SPI)
|
||||
#define DEBUGSPI(fmt, ...) do { DEBUG_RP2040_PORT.printf(fmt, ## __VA_ARGS__); DEBUG_RP2040_PORT.flush(); } while (0)
|
||||
#else
|
||||
#define DEBUGSPI(...) do { } while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+49
-39
@@ -1,52 +1,62 @@
|
||||
/*
|
||||
* delay() for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
delay() for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <pico.h>
|
||||
#include <pico/time.h>
|
||||
|
||||
extern "C" void delay( unsigned long ms )
|
||||
#ifdef USE_TINYUSB
|
||||
#include "Adafruit_TinyUSB_API.h"
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
if (!ms) {
|
||||
return;
|
||||
|
||||
void delay(unsigned long ms) {
|
||||
if (!ms) {
|
||||
return;
|
||||
}
|
||||
|
||||
sleep_ms(ms);
|
||||
}
|
||||
|
||||
sleep_ms(ms);
|
||||
}
|
||||
|
||||
extern "C" void delayMicroseconds( unsigned int usec )
|
||||
{
|
||||
if (!usec) {
|
||||
return;
|
||||
void delayMicroseconds(unsigned int usec) {
|
||||
if (!usec) {
|
||||
return;
|
||||
}
|
||||
sleep_us(usec);
|
||||
}
|
||||
sleep_us(usec);
|
||||
}
|
||||
|
||||
extern "C" void yield() {
|
||||
// NOOP
|
||||
}
|
||||
void yield() {
|
||||
#ifdef USE_TINYUSB
|
||||
TinyUSB_Device_Task();
|
||||
TinyUSB_Device_FlushCDC();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" uint32_t millis() {
|
||||
return to_ms_since_boot(get_absolute_time());
|
||||
}
|
||||
|
||||
extern "C" uint32_t micros() {
|
||||
return to_us_since_boot(get_absolute_time());
|
||||
}
|
||||
uint32_t millis() {
|
||||
return to_ms_since_boot(get_absolute_time());
|
||||
}
|
||||
|
||||
uint32_t micros() {
|
||||
return to_us_since_boot(get_absolute_time());
|
||||
}
|
||||
|
||||
} // extern C
|
||||
|
||||
+94
-142
@@ -1,155 +1,107 @@
|
||||
/*
|
||||
* Main handler for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Main handler for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RP2040USB.h"
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
|
||||
RP2040 rp2040;
|
||||
|
||||
volatile bool _MFIFO::_otherIdled = false;
|
||||
mutex_t _pioMutex;
|
||||
|
||||
|
||||
extern void setup();
|
||||
extern void loop();
|
||||
|
||||
|
||||
// Weak empty variant initialization. May be redefined by variant files.
|
||||
void initVariant() __attribute__((weak));
|
||||
void initVariant() { }
|
||||
|
||||
|
||||
// Optional 2nd core setup and loop
|
||||
extern void setup1() __attribute__((weak));
|
||||
extern void loop1() __attribute__((weak));
|
||||
static void main1() {
|
||||
rp2040.fifo.registerCore();
|
||||
if (setup1) {
|
||||
setup1();
|
||||
}
|
||||
while (true) {
|
||||
if (loop1) {
|
||||
loop1();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int main() {
|
||||
Serial.begin();
|
||||
#if F_CPU != 125000000
|
||||
set_sys_clock_khz(F_CPU / 1000, true);
|
||||
#endif
|
||||
|
||||
mutex_init(&_pioMutex);
|
||||
initVariant();
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
TinyUSB_Device_Init(0);
|
||||
|
||||
#else
|
||||
__USBStart();
|
||||
|
||||
#ifndef DISABLE_USB_SERIAL
|
||||
// Enable serial port for reset/upload always
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined DEBUG_RP2040_PORT
|
||||
DEBUG_RP2040_PORT.begin();
|
||||
#endif
|
||||
|
||||
if (setup1 || loop1) {
|
||||
rp2040.fifo.begin(2);
|
||||
multicore_launch_core1(main1);
|
||||
} else {
|
||||
rp2040.fifo.begin(1);
|
||||
}
|
||||
rp2040.fifo.registerCore();
|
||||
|
||||
setup();
|
||||
while (1) {
|
||||
while (true) {
|
||||
loop();
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
yield();
|
||||
#endif
|
||||
|
||||
if (arduino::serialEventRun) {
|
||||
arduino::serialEventRun();
|
||||
}
|
||||
if (arduino::serialEvent1Run) {
|
||||
arduino::serialEvent1Run();
|
||||
}
|
||||
if (arduino::serialEvent2Run) {
|
||||
arduino::serialEvent2Run();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* NEWLIB syscall overloads, so we can ::print() and ::getc() using our objects */
|
||||
/* Placed here to ensure this compilation unit will be present when it's time */
|
||||
/* to link newlib.a. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <_syslist.h>
|
||||
#include <sys/times.h>
|
||||
#include <bits/stdc++.h>
|
||||
#undef errno
|
||||
|
||||
|
||||
// TODO - check the fd, create a VFS, etc.
|
||||
|
||||
extern "C" int errno;
|
||||
|
||||
extern "C" ssize_t _write(int fd, const void *buf, size_t count) {
|
||||
return Serial.write((const char *)buf, count);
|
||||
}
|
||||
|
||||
extern "C" int _chown (const char *path, uid_t owner, gid_t group) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _close (int fildes) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _execve (char *name, char **argv, char **env) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _fork (void) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _fstat (int fildes, struct stat *st) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _getpid (void) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timeval;
|
||||
|
||||
extern "C" int _gettimeofday (struct timeval *ptimeval, void *ptimezone)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _isatty (int file) {
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int _kill (int pid, int sig) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _link (char *existing, char *newlink) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _lseek (int file, int ptr, int dir) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _open (char *file, int flags, int mode) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _read (int file, char *ptr, int len)
|
||||
{
|
||||
// return Serial.read(ptr, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _readlink (const char *path, char *buf, size_t bufsize) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _stat (const char *file, struct stat *st) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _symlink (const char *path1, const char *path2) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" clock_t _times (struct tms *buf) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _unlink (char *name) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _wait (int *status) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" void __sync_synchronize() { /* noop */ }
|
||||
|
||||
+21
-18
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* Millis() for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
Millis() for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <pico/time.h>
|
||||
|
||||
@@ -24,3 +24,6 @@ extern "C" unsigned long millis() {
|
||||
return to_ms_since_boot(get_absolute_time());
|
||||
}
|
||||
|
||||
extern "C" unsigned long micros() {
|
||||
return time_us_32();
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include <avr/pgmspace.h>
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
NEWLIB syscall implementations
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <_syslist.h>
|
||||
#include <sys/times.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
|
||||
#undef errno
|
||||
|
||||
|
||||
// TODO - check the fd, create a VFS, etc.
|
||||
|
||||
extern "C" int errno;
|
||||
|
||||
extern "C" ssize_t _write(int fd, const void *buf, size_t count) {
|
||||
#if defined DEBUG_RP2040_PORT
|
||||
(void) fd;
|
||||
return DEBUG_RP2040_PORT.write((const char *)buf, count);
|
||||
#else
|
||||
(void) fd;
|
||||
(void) buf;
|
||||
(void) count;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" int _chown(const char *path, uid_t owner, gid_t group) {
|
||||
(void) path;
|
||||
(void) owner;
|
||||
(void) group;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _close(int fd) {
|
||||
(void) fd;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _execve(char *name, char **argv, char **env) {
|
||||
(void) name;
|
||||
(void) argv;
|
||||
(void) env;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _fork(void) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _fstat(int fd, struct stat *st) {
|
||||
(void) fd;
|
||||
(void) st;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _getpid(void) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int64_t __timedelta_us = 0.0;
|
||||
|
||||
extern "C" int _gettimeofday(struct timeval *tv, void *tz) {
|
||||
(void) tz;
|
||||
uint64_t now_us = to_us_since_boot(get_absolute_time()) + __timedelta_us;
|
||||
if (tv) {
|
||||
tv->tv_sec = now_us / 1000000L;
|
||||
tv->tv_usec = now_us % 1000000L;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int settimeofday(const struct timeval *tv, const struct timezone *tz) {
|
||||
(void) tz;
|
||||
uint64_t now_us = to_us_since_boot(get_absolute_time());
|
||||
if (tv) {
|
||||
uint64_t newnow_us;
|
||||
newnow_us = tv->tv_sec * 1000000L;
|
||||
newnow_us += tv->tv_usec;
|
||||
__timedelta_us = newnow_us - now_us;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int _isatty(int file) {
|
||||
(void) file;
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int _kill(int pid, int sig) {
|
||||
(void) pid;
|
||||
(void) sig;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _link(char *existing, char *newlink) {
|
||||
(void) existing;
|
||||
(void) newlink;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _lseek(int file, int ptr, int dir) {
|
||||
(void) file;
|
||||
(void) ptr;
|
||||
(void) dir;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _open(char *file, int flags, int mode) {
|
||||
(void) file;
|
||||
(void) flags;
|
||||
(void) mode;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _read(int file, char *ptr, int len) {
|
||||
(void) file;
|
||||
(void) ptr;
|
||||
(void) len;
|
||||
// return Serial.read(ptr, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _readlink(const char *path, char *buf, size_t bufsize) {
|
||||
(void) path;
|
||||
(void) buf;
|
||||
(void) bufsize;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _stat(const char *file, struct stat *st) {
|
||||
(void) file;
|
||||
(void) st;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _symlink(const char *path1, const char *path2) {
|
||||
(void) path1;
|
||||
(void) path2;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" clock_t _times(struct tms *buf) {
|
||||
(void) buf;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _unlink(char *name) {
|
||||
(void) name;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int _wait(int *status) {
|
||||
(void) status;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
stdlib_noniso.h - nonstandard (but useful) conversion functions
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
Copyright (c) 2021 David Gauchard. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
// ulltoa() is slower than std::to_char() (1.6 times)
|
||||
// but is smaller by ~800B/flash and ~250B/rodata
|
||||
|
||||
// ulltoa fills str backwards and can return a pointer different from str
|
||||
extern "C" char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix) {
|
||||
str += --slen;
|
||||
*str = 0;
|
||||
do {
|
||||
auto mod = val % radix;
|
||||
val /= radix;
|
||||
*--str = mod + ((mod > 9) ? ('a' - 10) : '0');
|
||||
} while (--slen && val);
|
||||
return val ? nullptr : str;
|
||||
}
|
||||
|
||||
// lltoa fills str backwards and can return a pointer different from str
|
||||
extern "C" char* lltoa(long long val, char* str, int slen, unsigned int radix) {
|
||||
bool neg;
|
||||
if (val < 0) {
|
||||
val = -val;
|
||||
neg = true;
|
||||
} else {
|
||||
neg = false;
|
||||
}
|
||||
char* ret = ulltoa(val, str, slen, radix);
|
||||
if (neg) {
|
||||
if (ret == str || ret == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
*--ret = '-';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" char* ltoa(long value, char* result, int base) {
|
||||
return itoa((int)value, result, base);
|
||||
}
|
||||
|
||||
extern "C" char* ultoa(unsigned long value, char* result, int base) {
|
||||
return utoa((unsigned int)value, result, base);
|
||||
}
|
||||
|
||||
extern "C" char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
|
||||
bool negative = false;
|
||||
|
||||
if (isnan(number)) {
|
||||
strcpy(s, "nan");
|
||||
return s;
|
||||
}
|
||||
if (isinf(number)) {
|
||||
strcpy(s, "inf");
|
||||
return s;
|
||||
}
|
||||
|
||||
char* out = s;
|
||||
|
||||
int fillme = width; // how many cells to fill for the integer part
|
||||
if (prec > 0) {
|
||||
fillme -= (prec + 1);
|
||||
}
|
||||
|
||||
// Handle negative numbers
|
||||
if (number < 0.0) {
|
||||
negative = true;
|
||||
fillme--;
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
// I optimized out most of the divisions
|
||||
double rounding = 2.0;
|
||||
for (uint8_t i = 0; i < prec; ++i) {
|
||||
rounding *= 10.0;
|
||||
}
|
||||
rounding = 1.0 / rounding;
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Figure out how big our number really is
|
||||
double tenpow = 1.0;
|
||||
int digitcount = 1;
|
||||
double nextpow;
|
||||
while (number >= (nextpow = (10.0 * tenpow))) {
|
||||
tenpow = nextpow;
|
||||
digitcount++;
|
||||
}
|
||||
|
||||
// minimal compensation for possible lack of precision (#7087 addition)
|
||||
number *= 1 + std::numeric_limits<decltype(number)>::epsilon();
|
||||
|
||||
number /= tenpow;
|
||||
fillme -= digitcount;
|
||||
|
||||
// Pad unused cells with spaces
|
||||
while (fillme-- > 0) {
|
||||
*out++ = ' ';
|
||||
}
|
||||
|
||||
// Handle negative sign
|
||||
if (negative) {
|
||||
*out++ = '-';
|
||||
}
|
||||
|
||||
// Print the digits, and if necessary, the decimal point
|
||||
digitcount += prec;
|
||||
int8_t digit = 0;
|
||||
while (digitcount-- > 0) {
|
||||
digit = (int8_t)number;
|
||||
if (digit > 9) {
|
||||
digit = 9; // insurance
|
||||
}
|
||||
*out++ = (char)('0' | digit);
|
||||
if ((digitcount == prec) && (prec > 0)) {
|
||||
*out++ = '.';
|
||||
}
|
||||
number -= digit;
|
||||
number *= 10.0;
|
||||
}
|
||||
|
||||
// make sure the string is terminated
|
||||
*out = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
strrstr (static)
|
||||
|
||||
Backwards search for p_pcPattern in p_pcString
|
||||
Based on: https://stackoverflow.com/a/1634398/2778898
|
||||
|
||||
*/
|
||||
extern "C" const char* strrstr(const char*__restrict p_pcString,
|
||||
const char*__restrict p_pcPattern) {
|
||||
const char* pcResult = 0;
|
||||
|
||||
size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0);
|
||||
size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0);
|
||||
|
||||
if ((stStringLength) &&
|
||||
(stPatternLength) &&
|
||||
(stPatternLength <= stStringLength)) {
|
||||
// Pattern is shorter or has the same length than the string
|
||||
for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) {
|
||||
if (0 == strncmp(s, p_pcPattern, stPatternLength)) {
|
||||
pcResult = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pcResult;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
stdlib_noniso.h - nonstandard (but useful) conversion functions
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef STDLIB_NONISO_H
|
||||
#define STDLIB_NONISO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int atoi(const char *s);
|
||||
|
||||
long atol(const char* s);
|
||||
|
||||
double atof(const char* s);
|
||||
|
||||
char* itoa(int val, char *s, int radix);
|
||||
|
||||
char* ltoa(long val, char *s, int radix);
|
||||
|
||||
char* lltoa(long long val, char* str, int slen, unsigned int radix);
|
||||
|
||||
char* utoa(unsigned int val, char *s, int radix);
|
||||
|
||||
char* ultoa(unsigned long val, char *s, int radix);
|
||||
|
||||
char* ulltoa(unsigned long long val, char* str, int slen, unsigned int radix);
|
||||
|
||||
char* dtostrf(double val, signed char width, unsigned char prec, char *s);
|
||||
|
||||
void reverse(char* begin, char* end);
|
||||
|
||||
const char* strrstr(const char*__restrict p_pcString,
|
||||
const char*__restrict p_pcPattern);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
+15
-15
@@ -14,16 +14,16 @@
|
||||
#define tone_wrap 7
|
||||
|
||||
static const uint16_t tone_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x80a0, // 0: pull block
|
||||
0xa027, // 1: mov x, osr
|
||||
0xb846, // 2: mov y, isr side 1
|
||||
0x0083, // 3: jmp y--, 3
|
||||
0x0045, // 4: jmp x--, 5
|
||||
0xb046, // 5: mov y, isr side 0
|
||||
0x0086, // 6: jmp y--, 6
|
||||
0x0042, // 7: jmp x--, 2
|
||||
// .wrap
|
||||
// .wrap_target
|
||||
0x80a0, // 0: pull block
|
||||
0xa027, // 1: mov x, osr
|
||||
0xb846, // 2: mov y, isr side 1
|
||||
0x0083, // 3: jmp y--, 3
|
||||
0x0045, // 4: jmp x--, 5
|
||||
0xb046, // 5: mov y, isr side 0
|
||||
0x0086, // 6: jmp y--, 6
|
||||
0x0042, // 7: jmp x--, 2
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
@@ -41,11 +41,11 @@ static inline pio_sm_config tone_program_get_default_config(uint offset) {
|
||||
}
|
||||
|
||||
static inline void tone_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
pio_sm_config c = tone_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
pio_sm_config c = tone_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,42 +1,47 @@
|
||||
/*
|
||||
* PWM and analogRead for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
PWM and analogRead for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <CoreMutex.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/pwm.h>
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/pll.h>
|
||||
#include <hardware/adc.h>
|
||||
|
||||
static int32_t analogScale = 255;
|
||||
static uint32_t analogMap = 0;
|
||||
static uint32_t analogScale = 255;
|
||||
static uint16_t analogFreq = 1000;
|
||||
static bool pwmInitted = false;
|
||||
static bool adcInitted = false;
|
||||
|
||||
auto_init_mutex(_dacMutex);
|
||||
|
||||
extern "C" void analogWriteFreq(uint32_t freq) {
|
||||
if (freq == analogFreq) {
|
||||
return;
|
||||
}
|
||||
if (freq < 100) {
|
||||
DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq);
|
||||
analogFreq = 100;
|
||||
} else if (freq > 60000) {
|
||||
DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq);
|
||||
analogFreq = 60000;
|
||||
} else {
|
||||
analogFreq = freq;
|
||||
@@ -51,29 +56,39 @@ extern "C" void analogWriteRange(uint32_t range) {
|
||||
if ((range >= 15) && (range <= 65535)) {
|
||||
analogScale = range;
|
||||
pwmInitted = false;
|
||||
}
|
||||
} else {
|
||||
DEBUGCORE("ERROR: analogWriteRange out of range (%d)\n", range);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void analogWriteResolution(int res) {
|
||||
if ((res >= 4) && (res <= 16)) {
|
||||
analogWriteRange((1 << res) - 1);
|
||||
} else {
|
||||
DEBUGCORE("ERROR: analogWriteResolution out of range (%d)\n", res);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
CoreMutex m(&_dacMutex);
|
||||
|
||||
if ((pin > 29) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
|
||||
return;
|
||||
}
|
||||
if (!pwmInitted) {
|
||||
pwm_config c = pwm_get_default_config();
|
||||
pwm_config_set_clkdiv( &c, clock_get_hz(clk_sys) / 1.0 * (analogScale * analogFreq) );
|
||||
pwm_config_set_wrap( &c, analogScale );
|
||||
for (int i=0; i<30; i++) {
|
||||
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (float)(analogScale * analogFreq));
|
||||
pwm_config_set_wrap(&c, analogScale);
|
||||
for (int i = 0; i < 30; i++) {
|
||||
pwm_init(pwm_gpio_to_slice_num(i), &c, true);
|
||||
}
|
||||
pwmInitted = true;
|
||||
}
|
||||
|
||||
|
||||
if (val < 0) {
|
||||
val = 0;
|
||||
} else if (val > analogScale) {
|
||||
} else if ((uint32_t)val > analogScale) {
|
||||
val = analogScale;
|
||||
}
|
||||
|
||||
@@ -81,15 +96,37 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
|
||||
pwm_set_gpio_level(pin, val);
|
||||
}
|
||||
|
||||
extern "C" int analogRead(pin_size_t pinNumber) {
|
||||
if ((pinNumber < A0) || (pinNumber > A3)) {
|
||||
auto_init_mutex(_adcMutex);
|
||||
|
||||
extern "C" int analogRead(pin_size_t pin) {
|
||||
CoreMutex m(&_adcMutex);
|
||||
|
||||
if ((pin < A0) || (pin > A3) || !m) {
|
||||
DEBUGCORE("ERROR: Illegal analogRead pin (%d)\n", pin);
|
||||
return 0;
|
||||
}
|
||||
static bool adcInitted = false;
|
||||
if (!adcInitted) {
|
||||
adc_init();
|
||||
}
|
||||
adc_gpio_init(pinNumber);
|
||||
adc_select_input(pinNumber - A0);
|
||||
adc_gpio_init(pin);
|
||||
adc_select_input(pin - A0);
|
||||
return adc_read();
|
||||
}
|
||||
|
||||
extern "C" float analogReadTemp() {
|
||||
CoreMutex m(&_adcMutex);
|
||||
|
||||
if (!m) {
|
||||
return 0.0f; // Deadlock
|
||||
}
|
||||
if (!adcInitted) {
|
||||
adc_init();
|
||||
}
|
||||
adc_set_temp_sensor_enabled(true);
|
||||
delay(1); // Allow things to settle. Without this, readings can be erratic
|
||||
adc_select_input(4); // Temperature sensor
|
||||
int v = adc_read();
|
||||
adc_set_temp_sensor_enabled(false);
|
||||
float t = 27.0f - ((v * 3.3f / 4096.0f) - 0.706f) / 0.001721f; // From the datasheet
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1,66 +1,89 @@
|
||||
/*
|
||||
* pinMode and digitalRead/Write for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
pinMode and digitalRead/Write for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <hardware/gpio.h>
|
||||
|
||||
extern "C" void pinMode( pin_size_t ulPin, PinMode ulMode ) {
|
||||
static PinMode _pm[30];
|
||||
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
switch (ulMode) {
|
||||
case INPUT:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
gpio_pull_up(ulPin);
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
gpio_pull_down(ulPin);
|
||||
break;
|
||||
case OUTPUT:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, true);
|
||||
break;
|
||||
default:
|
||||
// Error
|
||||
break;
|
||||
case INPUT:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
gpio_pull_up(ulPin);
|
||||
gpio_put(ulPin, 0);
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
gpio_pull_down(ulPin);
|
||||
gpio_put(ulPin, 1);
|
||||
break;
|
||||
case OUTPUT:
|
||||
gpio_init(ulPin);
|
||||
gpio_set_dir(ulPin, true);
|
||||
break;
|
||||
default:
|
||||
DEBUGCORE("ERROR: Illegal pinMode mode (%d)\n", ulMode);
|
||||
// Error
|
||||
return;
|
||||
}
|
||||
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
}
|
||||
_pm[ulPin] = ulMode;
|
||||
}
|
||||
|
||||
extern "C" void digitalWrite( pin_size_t ulPin, PinStatus ulVal ) {
|
||||
if (!gpio_is_dir_out(ulPin)) {
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
}
|
||||
if (_pm[ulPin] == INPUT_PULLDOWN) {
|
||||
if (ulVal == LOW) {
|
||||
gpio_pull_down(ulPin);
|
||||
gpio_set_dir(ulPin, false);
|
||||
} else {
|
||||
gpio_pull_up(ulPin);
|
||||
gpio_set_dir(ulPin, true);
|
||||
}
|
||||
} else if (_pm[ulPin] == INPUT_PULLUP) {
|
||||
if (ulVal == HIGH) {
|
||||
gpio_set_dir(ulPin, false);
|
||||
} else {
|
||||
gpio_set_dir(ulPin, true);
|
||||
}
|
||||
} else {
|
||||
gpio_put(ulPin, ulVal == LOW ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" PinStatus digitalRead( pin_size_t ulPin )
|
||||
{
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in digitalRead (%d)\n", ulPin);
|
||||
return LOW;
|
||||
}
|
||||
return gpio_get(ulPin) ? HIGH : LOW;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,105 @@
|
||||
/*
|
||||
* wiring_private for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
wiring_private for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <CoreMutex.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
std::stack<uint32_t> irqStack;
|
||||
// Support nested IRQ disable/re-enable
|
||||
static std::stack<uint32_t> _irqStack[2];
|
||||
|
||||
extern "C" void interrupts() {
|
||||
if (irqStack.empty()) {
|
||||
if (_irqStack[get_core_num()].empty()) {
|
||||
// ERROR
|
||||
return;
|
||||
}
|
||||
restore_interrupts(irqStack.top());
|
||||
irqStack.pop();
|
||||
auto oldIrqs = _irqStack[get_core_num()].top();
|
||||
_irqStack[get_core_num()].pop();
|
||||
restore_interrupts(oldIrqs);
|
||||
}
|
||||
|
||||
extern "C" void noInterrupts() {
|
||||
irqStack.push(save_and_disable_interrupts());
|
||||
_irqStack[get_core_num()].push(save_and_disable_interrupts());
|
||||
}
|
||||
|
||||
// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
|
||||
// dispatch to the real callback manually
|
||||
auto_init_mutex(_irqMutex);
|
||||
static std::map<pin_size_t, voidFuncPtr> _map;
|
||||
|
||||
void _gpioInterruptDispatcher(uint gpio, uint32_t events) {
|
||||
(void) events;
|
||||
// Only need to lock around the std::map check, not the whole IRQ callback
|
||||
voidFuncPtr cb = nullptr;
|
||||
{
|
||||
CoreMutex m(&_irqMutex);
|
||||
if (m) {
|
||||
auto irq = _map.find(gpio);
|
||||
if (irq != _map.end()) {
|
||||
cb = irq->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cb) {
|
||||
cb(); // Do the callback
|
||||
} else {
|
||||
// ERROR, but we're in an IRQ so do nothing
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus mode) {
|
||||
CoreMutex m(&_irqMutex);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t events;
|
||||
switch (mode) {
|
||||
case LOW: events = 1; break;
|
||||
case HIGH: events = 2; break;
|
||||
case FALLING: events = 4; break;
|
||||
case RISING: events = 8; break;
|
||||
case CHANGE: events = 4 | 8; break;
|
||||
default: return; // ERROR
|
||||
}
|
||||
noInterrupts();
|
||||
detachInterrupt(pin);
|
||||
_map.insert({pin, callback});
|
||||
gpio_set_irq_enabled_with_callback(pin, events, true, _gpioInterruptDispatcher);
|
||||
interrupts();
|
||||
}
|
||||
|
||||
extern "C" void detachInterrupt(pin_size_t pin) {
|
||||
CoreMutex m(&_irqMutex);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
noInterrupts();
|
||||
auto irq = _map.find(pin);
|
||||
if (irq != _map.end()) {
|
||||
gpio_set_irq_enabled(pin, 0x0f /* all */, false);
|
||||
_map.erase(pin);
|
||||
}
|
||||
interrupts();
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/* dummy */
|
||||
@@ -1,50 +1,59 @@
|
||||
/*
|
||||
* pulseIn for the Raspberry Pi Pico RP2040
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
pulseIn for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <hardware/timer.h>
|
||||
#include <hardware/gpio.h>
|
||||
|
||||
extern "C" unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||
{
|
||||
extern "C" unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) {
|
||||
uint64_t start = time_us_64();
|
||||
uint64_t abort = start + timeout;
|
||||
|
||||
if (pin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pulseIn (%d)\n", pin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait for deassert, if needed
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort) );
|
||||
if (time_us_64() >= abort) return 0;
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort));
|
||||
if (time_us_64() >= abort) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait for assert
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort) );
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort));
|
||||
uint64_t begin = time_us_64();
|
||||
if (begin >= abort) return 0;
|
||||
if (begin >= abort) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait for deassert
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort) );
|
||||
while ((!!gpio_get(pin) != !state) && (time_us_64() < abort));
|
||||
uint64_t end = time_us_64();
|
||||
if (end >= abort) return 0;
|
||||
if (end >= abort) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return end - begin;
|
||||
}
|
||||
|
||||
extern "C" unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
|
||||
{
|
||||
extern "C" unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) {
|
||||
return pulseIn(pin, state, timeout);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* wiring_shift.c - shiftOut() function
|
||||
* Part of Arduino - http://www.arduino.cc/
|
||||
*
|
||||
* Copyright (c) 2005-2006 David A. Mellis
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
wiring_shift.c - shiftOut() function
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2005-2006 David A. Mellis
|
||||
|
||||
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., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
@@ -24,26 +24,44 @@
|
||||
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) {
|
||||
DEBUGCORE("ERROR: Illegal dataPin in shiftIn (%d)\n", dataPin);
|
||||
return 0;
|
||||
}
|
||||
if (clockPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal clockPin in shiftIn (%d)\n", clockPin);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
digitalWrite(clockPin, HIGH);
|
||||
if (bitOrder == LSBFIRST)
|
||||
value |= digitalRead(dataPin) << i;
|
||||
else
|
||||
value |= digitalRead(dataPin) << (7 - i);
|
||||
digitalWrite(clockPin, LOW);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
if (bitOrder == LSBFIRST) {
|
||||
value |= digitalRead(dataPin) << i;
|
||||
} else {
|
||||
value |= digitalRead(dataPin) << (7 - i);
|
||||
}
|
||||
digitalWrite(clockPin, LOW);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
extern "C" void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val) {
|
||||
uint8_t i;
|
||||
if (dataPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal dataPin in shiftOut (%d)\n", dataPin);
|
||||
return;
|
||||
}
|
||||
if (clockPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal clockPin in shiftOut (%d)\n", clockPin);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (bitOrder == LSBFIRST)
|
||||
if (bitOrder == LSBFIRST) {
|
||||
digitalWrite(dataPin, !!(val & (1 << i)));
|
||||
else
|
||||
} else {
|
||||
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
|
||||
|
||||
}
|
||||
|
||||
digitalWrite(clockPin, HIGH);
|
||||
digitalWrite(clockPin, LOW);
|
||||
digitalWrite(clockPin, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = Arduino-Pico
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,48 @@
|
||||
Analog I/O
|
||||
==========
|
||||
|
||||
Analog Input
|
||||
------------
|
||||
For analog inputs, the RP2040 device has a 12-bit, 4-channel ADC +
|
||||
temperature sensor available on a fixed set of pins (A0...A3).
|
||||
The standard Arduino calls can be used to read their values (with
|
||||
3.3V nominally reading as 4095).
|
||||
|
||||
int analogRead(pin_size_t pin = A0..A3)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns a value from 0...4095 correspionding to the ADC reading
|
||||
of the specific pin.
|
||||
|
||||
float analogReadTemp()
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the temperature, in Celsius, of the onboard thermal sensor.
|
||||
This reading is not exceedingly accurate and of relatively low
|
||||
resolution, so it is not a replacement for an external temperature
|
||||
sensor in many cases.
|
||||
|
||||
Analog Outputs
|
||||
--------------
|
||||
The RP2040 does not have any onboard DACs, so analog outputs are
|
||||
simulated using the standard method of using pulse width modulation
|
||||
(PWM) using the RP20400's hardware PWM units.
|
||||
|
||||
While up to 16 PWM channels can be generated, they are not independent
|
||||
and there are significant restrictions as to allowed pins in parallel.
|
||||
See the `RP2040 datasheet <https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_ for full details.
|
||||
|
||||
void analogWriteFreq(uint32_t freq)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the master PWM frequency used (i.e. how often the PWM output cycles).
|
||||
From 100Hz to 60KHz are supported.
|
||||
|
||||
void analogWriteRange(uint32_t range) and analogWriteResolution(int res)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
These calls set the maximum PWM value (i.e. writing this value will result in
|
||||
a PWM duty cycle of 100%)/ either explicitly (range) or as a power-of-two
|
||||
(res). A range of 16 to 65535 is supported.
|
||||
|
||||
void analogWrite(pin_size_t pin, int val)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Writes a PWM value to a specific pin. The PWM machine is enabled and set to
|
||||
the requested frequency and scale, and the output is generated. This will
|
||||
continue until a ``digitalWrite`` or other digital output is performed.
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Arduino-Pico documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Apr 3 15:02:21 2021.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Arduino-Pico'
|
||||
copyright = u'2021, Earle F. Philhower, III'
|
||||
author = u'Earle F. Philhower, III'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'1.0.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'1.0.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# This is required for the alabaster theme
|
||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||
html_sidebars = {
|
||||
'**': [
|
||||
'relations.html', # needs 'show_related': True theme option to display
|
||||
'searchbox.html',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Arduino-Picodoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'Arduino-Pico.tex', u'Arduino-Pico Documentation',
|
||||
u'Earle F. Philhower, III', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'arduino-pico', u'Arduino-Pico Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'Arduino-Pico', u'Arduino-Pico Documentation',
|
||||
author, 'Arduino-Pico', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
Digital I/O
|
||||
===========
|
||||
|
||||
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.
|
||||
|
||||
Tone/noTone
|
||||
-----------
|
||||
Simple square wave tone generation is possible for up to 8 channels using
|
||||
Arduino standard ``tone`` calls. Because these use the PIO to generate the
|
||||
waveform, they must share resources with other calls such as ``I2S`` or
|
||||
``Servo`` objects.
|
||||
@@ -0,0 +1,58 @@
|
||||
EEPROM Library
|
||||
==============
|
||||
|
||||
While the Raspberry Pi Pico RP2040 does not come with an EEPROM onboard, we
|
||||
simulate one by using a single 4K chunk of flash at the end of flash space.
|
||||
|
||||
**Note that this is a simulated EEPROM and will only support the number of
|
||||
writes as the onboard flash chip, not the 100,000 or so of a real EEPROM.**
|
||||
Therefore, do not frequently update the EEPROM or you may prematurely wear
|
||||
out the flash.
|
||||
|
||||
EEPROM Class API
|
||||
----------------
|
||||
|
||||
EEPROM.begin(size=256...4096)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Call before the first use of the EEPROM data for read or write. It makes a
|
||||
copy of the emulated EEPROM sector in RAM to allow random update and access.
|
||||
|
||||
EEPROM.read(addr), EEPROM[addr]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the data at a specific offset in the EEPROM. See `EEPROM.get` later
|
||||
for a more
|
||||
|
||||
EEPROM.write(addr, data), EEPROM[addr] = data
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Writes a byte of data at the offset specified. Not persisted to flash until
|
||||
``EEPROM.commit()`` is called.
|
||||
|
||||
EEPROM.commit()
|
||||
~~~~~~~~~~~~~~~
|
||||
Writes the updated data to flash, so next reboot it will be readable.
|
||||
|
||||
EEPROM.end()
|
||||
~~~~~~~~~~~~
|
||||
``EEPROM.commit()`` and frees all memory used. Need to call `EEPROM.begin()`
|
||||
before the EEPROM can be used again.
|
||||
|
||||
EEPROM.get(addr, val)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Copies the (potentially multi-byte) data in EEPROM at the specific byte
|
||||
offset into the returned value. Useful for reading structures from EEPROM.
|
||||
|
||||
EEPROM.put(addr, val)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Copies the (potentially multi-byte) value into EEPROM a the byte offset
|
||||
supplied. Useful for storing ``struct`` in EEPROM. Note that any pointers
|
||||
inside a written structure will not be valid, and that most C++ objects
|
||||
like ``String`` cannot be written to EEPROM this way because of it.
|
||||
|
||||
EEPROM.length()
|
||||
~~~~~~~~~~~~~~~
|
||||
Returns the length of the EEPROM (i.e. the value specified in
|
||||
``EEPROM.begin()`` ).
|
||||
|
||||
EEPROM Examples
|
||||
---------------
|
||||
Three EEPROM `examples<https://github.com/earlephilhower/arduino-pico/tree/master/libraries/EEPROM>`_ are included.
|
||||
+574
@@ -0,0 +1,574 @@
|
||||
File Systems
|
||||
============
|
||||
|
||||
The Arduino-Pico core supports using some of the onboard flash as a file
|
||||
system, useful for storing configuration data, output strings, logging,
|
||||
and more. It also supports using SD cards as another (FAT32) filesystem,
|
||||
with an API that's compatible with the onboard flash file system.
|
||||
|
||||
|
||||
Flash Layout
|
||||
------------
|
||||
|
||||
Even though file system is stored on the same flash chip as the program,
|
||||
programming new sketch will not modify file system contents (or EEPROM
|
||||
data).
|
||||
|
||||
The following diagram shows the flash layout used in Arduino-Pico:
|
||||
|
||||
::
|
||||
|
||||
|---------------------|-------------|----|
|
||||
^ ^ ^
|
||||
Sketch File system EEPROM
|
||||
|
||||
The file system size is configurable via the IDE menus, rom 64k up to 15MB
|
||||
(assuming you have an RP2040 boad with that much flash)
|
||||
|
||||
**Note:** to use any of file system functions in the sketch, add the
|
||||
following include to the sketch:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include "LittleFS.h" // LittleFS is declared
|
||||
// #include <SDFS.h>
|
||||
// #include <SD.h>
|
||||
|
||||
|
||||
Compatible Filesystem APIs
|
||||
--------------------------
|
||||
|
||||
LittleFS is an onboard filesystem that sets asidesome program flash for
|
||||
use as a filesystem without requiring any external hardware.
|
||||
|
||||
SDFS is a filesystem for SD cards, based on [SdFat 2.0](https://github.com/earlephilhower/ESP8266SdFat).
|
||||
It supports FAT16 and FAT32 formatted cards, and requires an external
|
||||
SD card reader.
|
||||
|
||||
SD is the Arduino supported, somewhat old and limited SD card filesystem.
|
||||
It is recommended to use SDFS for new applications instead of SD.
|
||||
|
||||
All three of these filesystems can open and manipulate ``File`` and ``Dir``
|
||||
objects with the same code because the implement a common end-user
|
||||
filesystem API.
|
||||
|
||||
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.
|
||||
|
||||
Filenames are assumed to be in the root directory if no initial "/" is
|
||||
present.
|
||||
|
||||
Opening files in subdirectories requires specifying the complete path to
|
||||
the file (i.e. ``LittleFS.open("/sub/dir/file.txt", "r");``). Subdirectories
|
||||
are automatically created when you attempt to create a file in a
|
||||
subdirectory, and when the last file in a subdirectory is removed the
|
||||
subdirectory itself is automatically deleted.
|
||||
|
||||
Uploading Files to the LittleFS File System
|
||||
-------------------------------------------
|
||||
|
||||
*PicoLittleFS* is a tool which integrates into the Arduino IDE. It adds a
|
||||
menu item to **Tools** menu for uploading the contents of sketch data
|
||||
directory into a new LittleFS flash file system.
|
||||
|
||||
- Download the tool: https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases
|
||||
- In your Arduino sketchbook directory, create ``tools`` directory if
|
||||
it doesn't exist yet.
|
||||
- Unpack the tool into ``tools`` directory (the path will look like
|
||||
``<home_dir>/Arduino/tools/PicoLittleFS/tool/picolittlefs.jar``)
|
||||
If upgrading, overwrite the existing JAR file with the newer version.
|
||||
- Restart Arduino IDE.
|
||||
- Open a sketch (or create a new one and save it).
|
||||
- Go to sketch directory (choose Sketch > Show Sketch Folder).
|
||||
- Create a directory named ``data`` and any files you want in the file
|
||||
system there.
|
||||
- Make sure you have selected a board, port, and closed Serial Monitor.
|
||||
- Double check theSerial Monitor is closed. Uploads will fail if the Serial
|
||||
Monitor has control of the serial port.
|
||||
- Select ``Tools > Pico LittleFS Data Upload``. This should start
|
||||
uploading the files into the flash file system.
|
||||
|
||||
SD Library Information
|
||||
----------------------
|
||||
The included ``SD`` library is the Arduino standard one. Please refer to
|
||||
the [Arduino SD reference](https://www.arduino.cc/en/reference/SD) for
|
||||
more information.
|
||||
|
||||
|
||||
File system object (LittleFS/SD/SDFS)
|
||||
--------------------------------------------
|
||||
|
||||
setConfig
|
||||
~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
LittleFSConfig cfg;
|
||||
cfg.setAutoFormat(false);
|
||||
LittleFS.setConfig(cfg);
|
||||
|
||||
SDFSConfig c2;
|
||||
c2.setCSPin(12);
|
||||
SDFS.setConfig(c2);
|
||||
|
||||
This method allows you to configure the parameters of a filesystem
|
||||
before mounting. All filesystems have their own ``*Config`` (i.e.
|
||||
``SDFSConfig`` or ``LittleFSConfig`` with their custom set of options.
|
||||
All filesystems allow explicitly enabling/disabling formatting when
|
||||
mounts fail. If you do not call this ``setConfig`` method before
|
||||
perforing ``begin()``, you will get the filesystem's default
|
||||
behavior and configuration. By default, SPIFFS will autoformat the
|
||||
filesystem if it cannot mount it, while SDFS will not.
|
||||
|
||||
begin
|
||||
~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.begin()
|
||||
or LittleFS.begin()
|
||||
|
||||
This method mounts file system. It must be called before any
|
||||
other FS APIs are used. Returns *true* if file system was mounted
|
||||
successfully, false otherwise. With no options it will format SPIFFS
|
||||
if it is unable to mount it on the first try.
|
||||
|
||||
Note that LittleFS will automatically format the filesystem
|
||||
if one is not detected. This is configurable via ``setConfig``
|
||||
|
||||
end
|
||||
~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.end()
|
||||
or LittleFS.end()
|
||||
|
||||
This method unmounts the file system.
|
||||
|
||||
format
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.format()
|
||||
or LittleFS.format()
|
||||
|
||||
Formats the file system. May be called either before or after calling
|
||||
``begin``. Returns *true* if formatting was successful.
|
||||
|
||||
open
|
||||
~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.open(path, mode)
|
||||
or LittleFS.open(path, mode)
|
||||
|
||||
Opens a file. ``path`` should be an absolute path starting with a slash
|
||||
(e.g. ``/dir/filename.txt``). ``mode`` is a string specifying access
|
||||
mode. It can be one of "r", "w", "a", "r+", "w+", "a+". Meaning of these
|
||||
modes is the same as for ``fopen`` C function.
|
||||
|
||||
::
|
||||
|
||||
r Open text file for reading. The stream is positioned at the
|
||||
beginning of the file.
|
||||
|
||||
r+ Open for reading and writing. The stream is positioned at the
|
||||
beginning of the file.
|
||||
|
||||
w Truncate file to zero length or create text file for writing.
|
||||
The stream is positioned at the beginning of the file.
|
||||
|
||||
w+ Open for reading and writing. The file is created if it does
|
||||
not exist, otherwise it is truncated. The stream is
|
||||
positioned at the beginning of the file.
|
||||
|
||||
a Open for appending (writing at end of file). The file is
|
||||
created if it does not exist. The stream is positioned at the
|
||||
end of the file.
|
||||
|
||||
a+ Open for reading and appending (writing at end of file). The
|
||||
file is created if it does not exist. The initial file
|
||||
position for reading is at the beginning of the file, but
|
||||
output is always appended to the end of the file.
|
||||
|
||||
Returns *File* object. To check whether the file was opened
|
||||
successfully, use the boolean operator.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
File f = LittleFS.open("/f.txt", "w");
|
||||
if (!f) {
|
||||
Serial.println("file open failed");
|
||||
}
|
||||
|
||||
exists
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.exists(path)
|
||||
or LittleFS.exists(path)
|
||||
|
||||
Returns *true* if a file with given path exists, *false* otherwise.
|
||||
|
||||
mkdir
|
||||
~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.mkdir(path)
|
||||
or LittleFS.mkdir(path)
|
||||
|
||||
Returns *true* if the directory creation succeeded, *false* otherwise.
|
||||
|
||||
rmdir
|
||||
~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.rmdir(path)
|
||||
or LittleFS.rmdir(path)
|
||||
|
||||
Returns *true* if the directory was successfully removed, *false* otherwise.
|
||||
|
||||
|
||||
openDir
|
||||
~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.openDir(path)
|
||||
or LittleFS.openDir(path)
|
||||
|
||||
Opens a directory given its absolute path. Returns a *Dir* object.
|
||||
Please note the previous discussion on the difference in behavior between
|
||||
LittleFS and SPIFFS for this call.
|
||||
|
||||
remove
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.remove(path)
|
||||
or LittleFS.remove(path)
|
||||
|
||||
Deletes the file given its absolute path. Returns *true* if file was
|
||||
deleted successfully.
|
||||
|
||||
rename
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
SDFS.rename(pathFrom, pathTo)
|
||||
or LittleFS.rename(pathFrom, pathTo)
|
||||
|
||||
Renames file from ``pathFrom`` to ``pathTo``. Paths must be absolute.
|
||||
Returns *true* if file was renamed successfully.
|
||||
|
||||
info **DEPRECATED**
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
FSInfo fs_info;
|
||||
or LittleFS.info(fs_info);
|
||||
|
||||
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.
|
||||
|
||||
Filesystem information structure
|
||||
--------------------------------
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
struct FSInfo {
|
||||
size_t totalBytes;
|
||||
size_t usedBytes;
|
||||
size_t blockSize;
|
||||
size_t pageSize;
|
||||
size_t maxOpenFiles;
|
||||
size_t maxPathLength;
|
||||
};
|
||||
|
||||
This is the structure which may be filled using FS::info method. -
|
||||
``totalBytes`` — total size of useful data on the file system -
|
||||
``usedBytes`` — number of bytes used by files - ``blockSize`` — filesystem
|
||||
block size - ``pageSize`` — filesystem logical page size - ``maxOpenFiles``
|
||||
— max number of files which may be open simultaneously -
|
||||
``maxPathLength`` — max file name length (including one byte for zero
|
||||
termination)
|
||||
|
||||
info64
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
FSInfo64 fsinfo;
|
||||
SDFS.info(fsinfo);
|
||||
or LittleFS(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))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
time_t myTimeCallback() {
|
||||
return 1455451200; // UNIX timestamp
|
||||
}
|
||||
void setup () {
|
||||
LittleFS.setTimeCallback(myTimeCallback);
|
||||
...
|
||||
// Any files will now be made with Pris' incept date
|
||||
}
|
||||
|
||||
|
||||
The SD, SDFS, and LittleFS filesystems support a file timestamp, updated when the file is
|
||||
opened for writing. By default, the Pico will use the internal time returned from
|
||||
``time(NULL)`` (i.e. local time, not UTC, to conform to the existing FAT filesystem), but this
|
||||
can be overridden to GMT or any other standard you'd like by using ``setTimeCallback()``.
|
||||
If your app sets the system time using NTP before file operations, then
|
||||
you should not need to use this function. However, if you need to set a specific time
|
||||
for a file, or the system clock isn't correct and you need to read the time from an external
|
||||
RTC or use a fixed time, this call allows you do to so.
|
||||
|
||||
In general use, with a functioning ``time()`` call, user applications should not need
|
||||
to use this function.
|
||||
|
||||
Directory object (Dir)
|
||||
----------------------
|
||||
|
||||
The purpose of *Dir* object is to iterate over files inside a directory.
|
||||
It provides multiple access methods.
|
||||
|
||||
The following example shows how it should be used:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
Dir dir = LittleFS.openDir("/data");
|
||||
// or Dir dir = LittleFS.openDir("/data");
|
||||
while (dir.next()) {
|
||||
Serial.print(dir.fileName());
|
||||
if(dir.fileSize()) {
|
||||
File f = dir.openFile("r");
|
||||
Serial.println(f.size());
|
||||
}
|
||||
}
|
||||
|
||||
next
|
||||
~~~~
|
||||
|
||||
Returns true while there are files in the directory to
|
||||
iterate over. It must be called before calling ``fileName()``, ``fileSize()``,
|
||||
and ``openFile()`` functions.
|
||||
|
||||
fileName
|
||||
~~~~~~~~~
|
||||
|
||||
Returns the name of the current file pointed to
|
||||
by the internal iterator.
|
||||
|
||||
fileSize
|
||||
~~~~~~~~
|
||||
|
||||
Returns the size of the current file pointed to
|
||||
by the internal iterator.
|
||||
|
||||
fileTime
|
||||
~~~~~~~~
|
||||
|
||||
Returns the time_t write time of the current file pointed
|
||||
to by the internal iterator.
|
||||
|
||||
fileCreationTime
|
||||
~~~~~~~~~~~~~~~~
|
||||
Returns the time_t creation time of the current file
|
||||
pointed to by the internal iterator.
|
||||
|
||||
isFile
|
||||
~~~~~~
|
||||
|
||||
Returns *true* if the current file pointed to by
|
||||
the internal iterator is a File.
|
||||
|
||||
isDirectory
|
||||
~~~~~~~~~~~
|
||||
|
||||
Returns *true* if the current file pointed to by
|
||||
the internal iterator is a Directory.
|
||||
|
||||
openFile
|
||||
~~~~~~~~
|
||||
|
||||
This method takes *mode* argument which has the same meaning as
|
||||
for ``SDFS/LittleFS.open()`` function.
|
||||
|
||||
rewind
|
||||
~~~~~~
|
||||
|
||||
Resets the internal pointer to the start of the directory.
|
||||
|
||||
setTimeCallback(time_t (\*cb)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sets the time callback for any files accessed from this Dir object via openNextFile.
|
||||
Note that the SD and SDFS filesystems only support a filesystem-wide callback and
|
||||
calls to ``Dir::setTimeCallback`` may produce unexpected behavior.
|
||||
|
||||
File object
|
||||
-----------
|
||||
|
||||
``SDFS/LittleFS.open()`` and ``dir.openFile()`` functions return a *File* object.
|
||||
This object supports all the functions of *Stream*, so you can use
|
||||
``readBytes``, ``findUntil``, ``parseInt``, ``println``, and all other
|
||||
*Stream* methods.
|
||||
|
||||
There are also some functions which are specific to *File* object.
|
||||
|
||||
seek
|
||||
~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
file.seek(offset, mode)
|
||||
|
||||
This function behaves like ``fseek`` C function. Depending on the value
|
||||
of ``mode``, it moves current position in a file as follows:
|
||||
|
||||
- if ``mode`` is ``SeekSet``, position is set to ``offset`` bytes from
|
||||
the beginning.
|
||||
- if ``mode`` is ``SeekCur``, current position is moved by ``offset``
|
||||
bytes.
|
||||
- if ``mode`` is ``SeekEnd``, position is set to ``offset`` bytes from
|
||||
the end of the file.
|
||||
|
||||
Returns *true* if position was set successfully.
|
||||
|
||||
position
|
||||
~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
file.position()
|
||||
|
||||
Returns the current position inside the file, in bytes.
|
||||
|
||||
size
|
||||
~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
file.size()
|
||||
|
||||
Returns file size, in bytes.
|
||||
|
||||
name
|
||||
~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
String name = file.name();
|
||||
|
||||
Returns short (no-path) file name, as ``const char*``. Convert it to *String* for
|
||||
storage.
|
||||
|
||||
fullName
|
||||
~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
// Filesystem:
|
||||
// testdir/
|
||||
// file1
|
||||
Dir d = LittleFS.openDir("testdir/");
|
||||
File f = d.openFile("r");
|
||||
// f.name() == "file1", f.fullName() == "testdir/file1"
|
||||
|
||||
Returns the full path file name as a ``const char*``.
|
||||
|
||||
getLastWrite
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Returns the file last write time, and only valid for files opened in read-only
|
||||
mode. If a file is opened for writing, the returned time may be indeterminate.
|
||||
|
||||
getCreationTime
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Returns the file creation time, if available.
|
||||
|
||||
isFile
|
||||
~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
bool amIAFile = file.isFile();
|
||||
|
||||
Returns *true* if this File points to a real file.
|
||||
|
||||
isDirectory
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
bool amIADir = file.isDir();
|
||||
|
||||
Returns *true* if this File points to a directory (used for emulation
|
||||
of the SD.* interfaces with the ``openNextFile`` method).
|
||||
|
||||
close
|
||||
~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
file.close()
|
||||
|
||||
Close the file. No other operations should be performed on *File* object
|
||||
after ``close`` function was called.
|
||||
|
||||
openNextFile (compatibiity method, not recommended for new code)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
File root = LittleFS.open("/");
|
||||
File file1 = root.openNextFile();
|
||||
File file2 = root.openNextFile();
|
||||
|
||||
Opens the next file in the directory pointed to by the File. Only valid
|
||||
when ``File.isDirectory() == true``.
|
||||
|
||||
rewindDirectory (compatibiity method, not recommended for new code)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
File root = LittleFS.open("/");
|
||||
File file1 = root.openNextFile();
|
||||
file1.close();
|
||||
root.rewindDirectory();
|
||||
file1 = root.openNextFile(); // Opens first file in dir again
|
||||
|
||||
Resets the ``openNextFile`` pointer to the top of the directory. Only
|
||||
valid when ``File.isDirectory() == true``.
|
||||
|
||||
setTimeCallback(time_t (\*cb)(void))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sets the time callback for this specific file. Note that the SD and
|
||||
SDFS filesystems only support a filesystem-wide callback and calls to
|
||||
``Dir::setTimeCallback`` may produce unexpected behavior.
|
||||
@@ -0,0 +1,15 @@
|
||||
Getting Help and Contributing
|
||||
=============================
|
||||
|
||||
This is a community supported project and has multiple ways to get assistance.
|
||||
Posting complete details, in a polite and organized way will get the best
|
||||
response.
|
||||
|
||||
For bugs in the Core, or to submit patches, please use the
|
||||
`GitHub Issues <https://github.com/earlephilhower/arduino-pico/issues>`_ or
|
||||
`GitHub Pull Requests <https://github.com/earlephilhower/arduino-pico/pulls>`_
|
||||
|
||||
For general questions/discussions use either
|
||||
`GitHub Discussions <https://github.com/earlephilhower/arduino-pico/discussions>`_
|
||||
or live-chat with `gitter.im <https://gitter.im/arduino-pico/community>`_
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
I2S (Digital Audio) Output Library
|
||||
==================================
|
||||
|
||||
While the RP2040 chip on the Raspberry Pi Pico does not include a hardware
|
||||
I2S device, it is possible to use the PIO (Programmable I/O) state machines
|
||||
to implement one dynamically.
|
||||
|
||||
This I2S library uses the ``pico-extras`` I2S audio library and wraps it in
|
||||
an Arduino I2S library. It supports 16 bits/sample and frequencies of up
|
||||
to 48kHZ, with configurable BCLK, LRCLK(always pin "BCLK + 1"), and DOUT pins.
|
||||
|
||||
**Note:** This I2S device takes over the entire PIO1 (second) unit and adjusts
|
||||
its clock frequency to meet the I2S needs. That means when only 4 Tones
|
||||
or only 4 Servos may be used when the I2S device is used.
|
||||
|
||||
I2S Class API
|
||||
-------------
|
||||
|
||||
bool setBCLK(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the BCLK pin of the I2S device. The LRCLK/word clock will be ``pin + 1``
|
||||
due to limitations of the PIO state machines. Call this before ``I2S.begin()``
|
||||
Default BCLK = 26, LRCLK = 27
|
||||
|
||||
bool setDOUT(pin_size_t pin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Sets the DOUT pin of the I2S device. Any pin may be used. Default DOUT = 28
|
||||
Call before ``I2S.begin()``
|
||||
|
||||
bool begin(long sampleRate)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Start the I2S device up with the given sample rate. The pins selected above
|
||||
will be turned to output and the I2S will begin to drive silence frames (all
|
||||
zero) out.
|
||||
|
||||
void end()
|
||||
~~~~~~~~~~
|
||||
Stops the I2S device. **Note, at present the memory allocated for I2S buffers
|
||||
is not freed leading to a memory leak when ``end()`` is called. This is due
|
||||
to the state of the ``pico-extras`` release which this code uses.**
|
||||
|
||||
void flush()
|
||||
~~~~~~~~~~~~
|
||||
Sends any partial frames in memory to the I2S output device. They may NOT play
|
||||
immediately. Potential use case for this call would be when the frequency of
|
||||
the output will be changing.
|
||||
|
||||
size_t write(uint8_t)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Provided for compatibility, but not very useful. Writes a sample from 0...255
|
||||
to the I2S buffer. See ``write(int16_t)`` for a better one
|
||||
|
||||
size_t write(const uint8_t \*buffer, size_t size)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Transfers number of bytes from an application buffer to the I2S output buffer.
|
||||
Be aware that ``size`` is in *bytes** and not samples. Size must be a multiple
|
||||
of **4 bytes** (i.e. one left/right sample). Will not block, so check
|
||||
the return value to find out how many bytes were actually written.
|
||||
|
||||
int availableForWrite()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Returns the number of **32-bit L/R samples** that can be written without
|
||||
potentially blocking.
|
||||
|
||||
bool setFrequency(int newFreq)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Adjusts the I2S output frequency. When changing frequency while I2S output
|
||||
is underway, be sure to use ``I2S.flush()`` before changing the frequency to
|
||||
ensure the older data is played at the right frequency.
|
||||
|
||||
size_t write(int16_t)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Writes a single 16-bit left or right sample to the I2S output buffer. The
|
||||
user is required to ensure that an even number of samples is written (i.e.
|
||||
left and right) over the application lifetime. The application also needs
|
||||
to track which sample is next to be written (right/left). For this reason,
|
||||
the ``write(void *b, size_t lrsamples)`` call may be easier and faster to use.
|
||||
|
||||
size_t write(const void \*buffer, size_t lrsamples)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Writes up to size left+right packed samples to the I2S device. Non-blocking,
|
||||
will writefrom 0...size samples and return that count. Be sure your app
|
||||
handles partial writes (i.e. by ``yield()`` ing and then retrying to write the
|
||||
remaining data.)
|
||||
|
||||
The ``onTransmit`` callback is not supported.
|
||||
|
||||
See the `ESP8266Audio <https://github.com/earlephilhower/ESP8266Audio>`_ library
|
||||
for a working example, or look at the included sample tone generator.
|
||||
@@ -0,0 +1,36 @@
|
||||
IDE Menus
|
||||
=========
|
||||
|
||||
Model
|
||||
-----
|
||||
Use the boards menu to select your model of RP2040 board. There will be two
|
||||
options: `Boardname` and `Boardname (Picoprobe)`. If you want to use a
|
||||
Picoprobe to upload your sketches and not the default automatic UF2 upload,
|
||||
use the `(Picoprobe)` option, otherwise use the normal name. No functional
|
||||
or code changes are done because of this.
|
||||
|
||||
There is also a `Generic` board which allows you to individually select
|
||||
things such as flash size or boot2 flash type. Use this if your board isn't
|
||||
yet fully supported and isn't working with the normal `Raspberry Pi Pico`
|
||||
option.
|
||||
|
||||
Flash Size
|
||||
----------
|
||||
Arduino-Pico supports onboard filesystems which will set aside some of the
|
||||
flash on your board for the filesystem, shrinking the maximum code size
|
||||
allowed. Use this menu to select the desired ratio of filesystem to sketch.
|
||||
|
||||
CPU Speed
|
||||
---------
|
||||
While it is unsupported, the Raspberry Pi Pico RP2040 can often run much
|
||||
faster than the stock 125MHz. Use the `CPU Speed` menu to select a
|
||||
desired over or underclock speed. **If the sketch fails at the higher
|
||||
speed, hold the BOOTSEL while plugging it in to enter update mode and try
|
||||
a lower overclock.**
|
||||
|
||||
Debug Port and Debug Level
|
||||
--------------------------
|
||||
Debug messages from `printf` and the Core can be printed to a Serial port
|
||||
to allow for easier debugging. Select the desired port and verbosity.
|
||||
Selecting a port for debug output does not stop a sketch from using it
|
||||
for normal operations.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -1 +1,4 @@
|
||||
## Welcome to Arduino-Pico
|
||||
|
||||
Please go to [https://arduino-pico.readthedocs.io/en/latest/](https://arduino-pico.readthedocs.io/en/latest/) for the
|
||||
latest documentation.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
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.
|
||||
|
||||
This Arduino core uses a custom toolset with GCC 10.2 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
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
Getting Help and Contributing <help>
|
||||
Installation <install>
|
||||
IDE Menus <ide>
|
||||
|
||||
Pin (Re)Assignment <pins>
|
||||
|
||||
Analog I/O <analog>
|
||||
Digital I/O <digital>
|
||||
EEPROM <eeprom>
|
||||
I2S Audio <i2s>
|
||||
Serial USB and UARTs <serial>
|
||||
Servo <servo>
|
||||
SPI <spi>
|
||||
Wire(I2C) <wire>
|
||||
File Systems (SD, SDFS, LittleFS) <fs>
|
||||
USB (Arduino and Adafruit_TinyUSB) <usb>
|
||||
Multicore Processing <multicore>
|
||||
|
||||
Ported/Optimized Libraries <libraries>
|
||||
Using Pico-SDK <sdk>
|
||||
|
||||
Licenses <license>
|
||||
@@ -0,0 +1,140 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
The Arduino-Pico core can be installed using the Arduino IDE Boards Manager
|
||||
or using `git`. If you want to simply write programs for your RP2040 board,
|
||||
the Boards Manager installation will suffice, but if you want to try the
|
||||
latest pre-release versions and submit improvements, you will need the `git`
|
||||
instllation.
|
||||
|
||||
Installing via Arduino Boards Manager
|
||||
-------------------------------------
|
||||
**Note for Windows Users**: Please do not use the Windows Store version of
|
||||
the actual Arduino application because it has issues detecting attached Pico
|
||||
boards. Use the "Windows ZIP" or plain "Windows" executable (EXE) download
|
||||
direct from https://arduino.cc. and allow it to install any device drivers
|
||||
it suggests. Otherwise the Pico board may not be detected. Also, if trying
|
||||
out the 2.0 beta Arduino please install the release 1.8 version beforehand
|
||||
to ensure needed device drivers are present.
|
||||
|
||||
1. Open up the Arduino IDE and go to File->Preferences.
|
||||
2. In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
.. image:: images/install1.png
|
||||
|
||||
3. Hit OK to close the dialog.
|
||||
4. Go to Tools->Boards->Board Manager in the IDE
|
||||
5. Type "pico" in the search box and select "Add":
|
||||
|
||||
.. image:: images/install2.png
|
||||
|
||||
Installing via GIT
|
||||
------------------
|
||||
To install via GIT (for latest and greatest versions):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mkdir -p ~/Arduino/hardware/pico
|
||||
git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/rp2040
|
||||
cd ~/Arduino/hardware/pico/rp2040
|
||||
git submodule update --init
|
||||
cd pico-sdk
|
||||
git submodule update --init
|
||||
cd pico-extras
|
||||
git submodule update --init
|
||||
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 `Tom's Hardware <https://www.tomshardware.com/how-to/program-raspberry-pi-pico-with-arduino-ide>`_ .
|
||||
|
||||
If you follow their 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.
|
||||
|
||||
After the first upload, this should not be necessary as the `arduino-pico` core has auto-reset support.
|
||||
Select the appropriate serial port shown in the Arduino Tools->Port->Serial Port menu once (this setting will stick and does not need to be
|
||||
touched for multiple uploads). This selection allows the auto-reset tool to identify the proper device to reset.
|
||||
Them hit the upload button and your sketch should upload and run.
|
||||
|
||||
In some cases the Pico will encounter a hard hang and its USB port will not respond to the auto-reset request. Should this happen, just
|
||||
follow the initial procedure of holding the BOOTSEL button down while plugging in the Pico to enter the ROM bootloader.
|
||||
|
||||
Windows 7 Driver Notes
|
||||
----------------------
|
||||
|
||||
Windows 10, Linux, and Mac will all support the Pico CDC/ACM USB serial port
|
||||
automatically. However, Windows 7 may not include the proper driver and
|
||||
therefore no detect the Pico for automatic uploads or the Serial Monitor.
|
||||
|
||||
For Windows 7, if this occurs, you can use `Zadig <https://zadig.akeo.ie/>`
|
||||
to install the appropriate driver. Select the USB ID of ``2E8A`` and use
|
||||
the ``USB Serial (CDC)`` driver.
|
||||
|
||||
.. image:: images/install_driver_old_win.png
|
||||
|
||||
Windows 7 Installation Problems
|
||||
-------------------------------
|
||||
|
||||
When running MalwareBytes antivirus (or others) the scanner may lock the compiler or other toolchain executables, causing installation or build failures. (Thanks to @Andy2No)
|
||||
|
||||
Symptoms include:
|
||||
|
||||
*Access denied during update in the boards manager - affects the .exe files, because MalwareBytes has locked them.
|
||||
* Access denied during compilation, to one of the .exe files - same reason.
|
||||
* Can't delete the .exe files - they're locked by MalwareBytes.
|
||||
|
||||
A workaround is possible, involving setting the toolchain as an "excluded directory" and reinstalling.
|
||||
|
||||
1. In MalwareBytes Settings, click the Exclusions tab. Add an exclusion for the equivalent of this folder path:
|
||||
|
||||
``C:\Users{YOUR_USERNAME_HERE}\AppData\Local\Arduino15\packages\rp2040\tools\pqt-gcc\1.1.0-a-81a1771``
|
||||
|
||||
2. Reboot to unlock the files.
|
||||
|
||||
3. Do the boards manager installation / upgrade again.
|
||||
|
||||
4. Set the board type, e.g. to Raspberry Pi Pico and check it can compile.
|
||||
|
||||
|
||||
Uploading Filesystem Images
|
||||
---------------------------
|
||||
The onboard flash filesystem for the Pico, LittleFS, lets you upload a filesystem image from the sketch directory for your sketch to use. Download the needed plugin from
|
||||
|
||||
* https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases
|
||||
|
||||
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 repo documentation available at
|
||||
|
||||
* https://arduino-pico.readthedocs.io/en/latest/fs.html
|
||||
|
||||
Uploading Sketches with Picoprobe
|
||||
---------------------------------
|
||||
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`):
|
||||
|
||||
.. code::
|
||||
|
||||
echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", GROUP="users", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
sudo udevadm control --reload
|
||||
|
||||
The first line creates a file with the USB vendor and ID of the Picoprobe 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 Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,13 @@
|
||||
Libraries Ported/Optimized for the RP2040
|
||||
=========================================
|
||||
|
||||
Most Arduino libraries that work on modern 32-bit CPU based Arduino boards
|
||||
will run fine using Arduino-Pico.
|
||||
|
||||
The following libraries have undergone additional porting and optimizations
|
||||
specifically for the RP2040 and you should consider using them instead of
|
||||
the generic versions available in the Library Manager
|
||||
|
||||
* `Adafruit GFX Library <https://github.com/Bodmer/Adafruit-GFX-Library>`_ by @Bodmer, 2-20x faster than the standard version on the Pico
|
||||
* `Adafruit ILI9341 Library <https://github.com/Bodmer/Adafruit_ILI9341>`_ again by @Bodmer
|
||||
* `ESP8266Audio <https://github.com/earlephilhower/ESP8266Audio>`_ ported to use the included ``I2S`` library
|
||||
@@ -0,0 +1,14 @@
|
||||
Licensing and Credits
|
||||
=====================
|
||||
|
||||
Arduino-Pico is licensed under the LGPL license as detailed in the included README.
|
||||
|
||||
In addition, it contains code from additional open source projects:
|
||||
|
||||
* The `Arduino IDE and ArduinoCore-API <https://arduino.cc>`_ are developed and maintained by the Arduino team. The IDE is licensed under GPL.
|
||||
* The `RP2040 GCC-based toolchain <https://github.com/earlephilhower/pico-quick-toolchain>`_ is licensed under under the GPL.
|
||||
* The `Pico-SDK <https://github.com/raspberrypi/pico-sdk>`_ and `Pico-Extras <https://github.com/raspberrypi/pico-extras>`_ are by Raspberry Pi (Trading) Ltd. and licensed under the BSD 3-Clause license.
|
||||
* `Arduino-Pico <https://github.com/earlephilhower/arduino-pico>`_ core files are licenses under the LGPL.
|
||||
* `LittleFS <https://github.com/ARMmbed/littlefs>`_ library written by ARM Limited and released under the `BSD 3-clause license <https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md>`_ .
|
||||
* `UF2CONV.PY <https://github.com/microsoft/uf2>`_ is by Microsoft Corporatio and licensed under the MIT license.
|
||||
* Some filesystem code taken from the `ESP8266 Arduino Core <https://github.com/esp8266/Arduino>`_ and licensed under the LGPL.
|
||||
@@ -0,0 +1,36 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SPHINXPROJ=Arduino-Pico
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,77 @@
|
||||
Multicore Processing
|
||||
====================
|
||||
|
||||
The RP2040 chip has 2 cores that can run independently of each other, sharing
|
||||
peripherals and memory with each other. Arduino code will normally execute
|
||||
only on core 0, with the 2nd core sitting idle in a low power state.
|
||||
|
||||
By adding a ``setup1()`` and ``loop1()`` function to your sketch you can make
|
||||
use of the second core. Anything called from within the ``setup1()`` or
|
||||
``loop1()`` routines will execute on the second core.
|
||||
|
||||
``setup()`` and ``setup1()`` will be called at the same time, and the ``loop()``
|
||||
or ``loop1()`` will be started as soon as the core's ``setup()`` completes (i.e.
|
||||
not necessarily simultaneously!).
|
||||
|
||||
See the ``Multicore.ino`` example in the ``rp2040`` example directory for a
|
||||
quick introduction.
|
||||
|
||||
Pausing Cores
|
||||
-------------
|
||||
|
||||
Sometimes an application needs to pause the other core on chip (i.e. it is
|
||||
writing to flash or needs to stop processing while some other event occurs).
|
||||
|
||||
void rp2040.idleOtherCore()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sends a message to stop the other core (i.e. when called from core 0 it
|
||||
pauses core 1, and vice versa). Waits for the other core to acknowledge
|
||||
before returning.
|
||||
|
||||
The other core will have its interrupts disabled and be busy-waiting in
|
||||
an RAM-based routine, so flash and other peripherals can be accessed.
|
||||
|
||||
**NOTE** If you idle core 0 too long, then the USB port can become frozen.
|
||||
This is because core 0 manages the USB and needs to service IRQs in a
|
||||
timely manner (which it can't do when idled).
|
||||
|
||||
void rp2040.resumeOtherCore()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Resumes processing in the other core, where it left off.
|
||||
|
||||
Communicating Between Cores
|
||||
---------------------------
|
||||
|
||||
The RP2040 provides a hardware FIFO for communicating between cores, but it
|
||||
is used exclusively for the idle/resume calls described above. Instead, please
|
||||
use the following functions to access a software-managed, multicore safe
|
||||
FIFO.
|
||||
|
||||
void rp2040.fifo.push(uint32_t)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pushes a value to the other core. Will block if the FIFO is full.
|
||||
|
||||
bool rp2040.fifo.push_nb(uint32_t)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pushes a value to the other core. If the FIFO is full, returns ``false``
|
||||
immediately and doesn't block. If the push is successful, returns ``true``.
|
||||
|
||||
uint32_t rp2040.fifo.pop()
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Reads a value from this core's FIFO. Blocks until one is available.
|
||||
|
||||
bool rp2040.fifo.pop_nb(uint32_t *dest)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Reads a value from this core's FIFO and places it in dest. Will return
|
||||
``true`` if successful, or ``false`` if the pop would block.
|
||||
|
||||
int rp2040.fifo.available()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Returns the number of values available in this core's FIFO.
|
||||
@@ -0,0 +1,60 @@
|
||||
Pin Assignments
|
||||
===============
|
||||
|
||||
The Raspberry Pi Pico has an incredibly flexible I/O configuration and most
|
||||
built-in peripherals (except for the ADC) can be used on multiple sets of
|
||||
pins. Note, however, that not all peripherals can use all I/Os. Refer to
|
||||
the RP2040 datasheet or an online pinout diagram for more details.
|
||||
|
||||
Additional methods have been added to allow you to select a peripheral's
|
||||
I/O pins **before calling ::begin**. This is especially helpful when
|
||||
using third party libraries: the library doesn't need to be modified,
|
||||
only your own code in `setup()` is needed to adjust pinouts.
|
||||
|
||||
I2S
|
||||
---
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
::setBCLK(pin)
|
||||
::setDOUT(pin)
|
||||
|
||||
Serial1 (UART0), Serial2 (UART1)
|
||||
--------------------------------
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
::setRX(pin)
|
||||
::setTX(pin)
|
||||
|
||||
SPI (SPI0), SPI1 (SPI1)
|
||||
-----------------------
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
::setSCK(pin)
|
||||
::setRX(pin)
|
||||
::setTX(pin)
|
||||
|
||||
Wire (I2C0), Wire1 (I2C1)
|
||||
-------------------------
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
::setSDA(pin)
|
||||
::setSCL(pin)
|
||||
|
||||
|
||||
For example, because the `SD` library uses the `SPI` library, we can make
|
||||
it use a non-default pinout with a simple call
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
void setup() {
|
||||
SPI.setRX(4);
|
||||
SPI.setTX(7);
|
||||
SPI.setSCK(6);
|
||||
SPI.setCS(5);
|
||||
SD.begin(5);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
Using the Raspberry Pi Pico SDK (PICO-SDK)
|
||||
==========================================
|
||||
|
||||
Included SDK
|
||||
------------
|
||||
A complete copy of the `Raspberry Pi Pico SDK <https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-c-sdk.pdf>`_
|
||||
is included with the Arduino core, and all functions in the core are available
|
||||
inside the standard link libraries.
|
||||
|
||||
For simple programs wishing to call these functions, simply include the
|
||||
appropriate header as shown below
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
void setup() {
|
||||
const uint LED_PIN = 25;
|
||||
gpio_init(LED_PIN);
|
||||
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||
while (true) {
|
||||
gpio_put(LED_PIN, 1);
|
||||
sleep_ms(250);
|
||||
gpio_put(LED_PIN, 0);
|
||||
sleep_ms(250);
|
||||
}
|
||||
}
|
||||
void loop() {}
|
||||
|
||||
**Note:** When you call SDK functions in your own app, the core and
|
||||
libraries are not aware of any changes to the Pico you perform. So,
|
||||
you may break the functionality of certain libraries in doing so.
|
||||
|
||||
Multicore (CORE1) Processing
|
||||
----------------------------
|
||||
**Warning:** While you may spawn multicore applications on CORE1
|
||||
using the SDK, the Arduino core may have issues running properly with
|
||||
them. In particular, anything involving flash writes (i.e. EEPROM,
|
||||
filesystems) will probably crash due to CORE1 attempting to read from
|
||||
flash while CORE0 is writing to it.
|
||||
@@ -0,0 +1,28 @@
|
||||
Serial Ports (USB and UART)
|
||||
===========================
|
||||
|
||||
The Arduino-Pico core implements a software-based Serial-over-USB port
|
||||
using the USB ACM-CDC model to support a wide variety of operating
|
||||
systems.
|
||||
|
||||
``Serial`` is the USB serial port, and while ``Serial.begin()`` does allow
|
||||
specifying a baud rate, this rate is ignored since it is USB-based.
|
||||
(Also be aware that this USB ``Serial`` port is responsible for resetting
|
||||
the RP2040 during the upload process, following the Arduino standard
|
||||
of 1200bps = reset to bootloader).
|
||||
|
||||
The RP2040 provides two hardware-based UARTS with configurable
|
||||
pin selection.
|
||||
|
||||
``Serial1`` is ``UART0``, and ``Serial2`` is ``UART1``.
|
||||
|
||||
Configure their pins using the ``setXXX`` calls prior to calling ``begin()``
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
Serial1.setRX(pin);
|
||||
Serial1.setTX(pin);
|
||||
Serial1.begin(baud);
|
||||
|
||||
For detailed information about the Serial ports, see the
|
||||
Arduino `Serial Reference <https://www.arduino.cc/reference/en/language/functions/communication/serial/>`_ .
|
||||
@@ -0,0 +1,13 @@
|
||||
Servo Library
|
||||
=============
|
||||
|
||||
A hardware-based servo controller is provided using the ``Servo`` library.
|
||||
It utilizes the PIO state machines and generates the appropriate servo
|
||||
control pulses, glitch-free and jitter-free (within crystal limits).
|
||||
|
||||
Up to 8 Servos can be controlled in parallel assuming no other tasks
|
||||
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.
|
||||
@@ -0,0 +1,24 @@
|
||||
SPI (Serial Peripheral Interface)
|
||||
=================================
|
||||
|
||||
The RP2040 has two hardware SPI interfaces, ``spi0 (SPI)`` and ``spi1 (SPI1)``.
|
||||
These interfaces are supported by the ``SPI`` library in master mode.
|
||||
|
||||
SPI pinouts can be set **before SPI.begin()** using the following calls:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
bool setRX(pin_size_t pin);
|
||||
bool setCS(pin_size_t pin);
|
||||
bool setSCK(pin_size_t pin);
|
||||
bool setTX(pin_size_t pin);
|
||||
|
||||
Note that the ``CS`` pin can be hardware or software controlled by the sketch.
|
||||
When software controlled, the ``setCS()`` call is ignored.
|
||||
|
||||
The Arduino `SPI documentation <https://www.arduino.cc/en/reference/SPI>`_ gives
|
||||
a detailed overview of the library, except for the following RP2040-specific
|
||||
changes:
|
||||
|
||||
* ``SPI.begin(bool hwCS)`` can take an options ``hwCS`` parameter. By passing in ``true`` for ``hwCS`` the sketch does not need to worry about asserting and deasserting the ``CS`` pin between transactions. The default is ``false`` and requires the sketch to handle the CS pin itself, as is the standard way in Arduino.
|
||||
* The interrupt calls (``usingInterrupt``, ``notUsingInterrupt``, ``attachInterrupt``, and ``detachInterrpt``) are not implemented.
|
||||
@@ -0,0 +1,48 @@
|
||||
USB (Arduino and Adafruit_TinyUSB)
|
||||
==================================
|
||||
|
||||
Two USB stacks are present in the core. Users can choose the simpler
|
||||
Pico-SDK version or the more powerful Adafruit TinyUSB library.
|
||||
Use the ``Tools->USB Stack`` menu to select between the two.
|
||||
|
||||
Pico SDK USB Support
|
||||
--------------------
|
||||
This is the default mode and automatically includes a USB-based
|
||||
serial port, ``Serial`` as well as supporting automatic reset-to-upload
|
||||
from the IDE.
|
||||
|
||||
The Arduino-Pico core includes ported versions of the basic Arduino
|
||||
``Keyboard`` and ``Mouse`` libraries. These libraries allow you to
|
||||
emulate a keyboard or mouse with the Pico in your sketches.
|
||||
|
||||
See the examples and Arduino Reference at
|
||||
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
|
||||
and
|
||||
https://www.arduino.cc/reference/en/language/functions/usb/mouse
|
||||
|
||||
Adafruit TinyUSB Arduino Support
|
||||
--------------------------------
|
||||
Examples are provided in the Adafruit_TinyUSB_Arduino for the more
|
||||
advanced USB stack.
|
||||
|
||||
To use Serial with TinyUSB, you must include the TinyUSB header in your
|
||||
sketch to avoid a compile error.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <Adafruit_TinyUSB.h>
|
||||
|
||||
If you need to be compatible with the
|
||||
other USB stack, you can use an ifdef:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#ifdef USE_TINYUSB
|
||||
#include <Adafruit_TinyUSB.h>
|
||||
#endif
|
||||
|
||||
Also, this stack requires sketches to manually call
|
||||
``Serial.begin(115200)`` to enable the USB serial port and automatic
|
||||
sketch upload from the IDE. If a sketch is run without this command
|
||||
in ``setup()``, the user will need to use the standard "hold BOOTSEL
|
||||
and plug in USB" method to enter program upload mode.
|
||||
@@ -0,0 +1,26 @@
|
||||
Wire (I2C Master and Slave)
|
||||
===========================
|
||||
|
||||
The RP2040 has two I2C devices, ``i2c0 (Wire)`` and ``i2c1 (Wire1)``.
|
||||
|
||||
The default pins for `Wire` and `Wire1` vary depending on which board you're using.
|
||||
(Here are the pinout diagrams for `Pico <https://datasheets.raspberrypi.org/pico/Pico-R3-A4-Pinout.pdf>`_
|
||||
and `Adafruit Feather <https://learn.adafruit.com/assets/100740>`_.)
|
||||
|
||||
You may change these pins **before calling Wire.begin() or Wire1.begin()** using:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
bool setSDA(pin_size_t sda);
|
||||
bool setSCL(pin_size_t scl);
|
||||
|
||||
Be sure to use pins labeled ``I2C0`` for Wire and ``I2C1`` for Wire1 on the pinout
|
||||
diagram for your board, or it won't work.
|
||||
|
||||
Other than that, the API is compatible with the Arduino standard.
|
||||
Both master and slave operation are supported.
|
||||
|
||||
Master transmissions are buffered (up to 128 bytes) and only performed
|
||||
on ``endTransmission``, as is standard with modern Arduino Wire implementations.
|
||||
|
||||
For more detailed information, check the `Arduino Wire documentation <https://www.arduino.cc/en/reference/wire>`_ .
|
||||
@@ -0,0 +1,20 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
setup1 KEYWORD2
|
||||
loop2 KEYWORD2
|
||||
analogWriteFreq KEYWORD2
|
||||
analogWriteRange KEYWORD2
|
||||
analogWriteResolution KEYWORD2
|
||||
|
||||
######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
Binary file not shown.
@@ -23,12 +23,15 @@
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2044k /* 2048 - 4K for EEPROM */
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = __FLASH_LENGTH__
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
PROVIDE ( _EEPROM_start = 0x101FF000 );
|
||||
PROVIDE ( _EEPROM_start = __EEPROM_START__ );
|
||||
PROVIDE ( _FS_start = __FS_START__ );
|
||||
PROVIDE ( _FS_end = __FS_END__ );
|
||||
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
@@ -36,7 +39,7 @@ SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Pico SDK
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
@@ -60,12 +63,11 @@ SECTIONS
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
@@ -247,6 +249,8 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#define _PICO_VERSION_H
|
||||
|
||||
#define PICO_SDK_VERSION_MAJOR 1
|
||||
#define PICO_SDK_VERSION_MINOR 0
|
||||
#define PICO_SDK_VERSION_REVISION 0
|
||||
#define PICO_SDK_VERSION_STRING "1.0.0"
|
||||
#define PICO_SDK_VERSION_MINOR 1
|
||||
#define PICO_SDK_VERSION_REVISION 2
|
||||
#define PICO_SDK_VERSION_STRING "1.1.2"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
-iwithprefixbefore/cores/rp2040/api/deprecated-avr-comp/
|
||||
-iwithprefixbefore/lib/pico_base/
|
||||
-iwithprefixbefore/pico-examples/build/generated/pico_base
|
||||
-iwithprefixbefore/pico-extras/src/common/pico_audio/include
|
||||
-iwithprefixbefore/pico-extras/src/common/pico_util_buffer/include
|
||||
-iwithprefixbefore/pico-extras/src/rp2_common/pico_audio_i2s/include
|
||||
-iwithprefixbefore/pico-sdk/lib/tinyusb/src/
|
||||
-iwithprefixbefore/pico-sdk/src/boards/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_base/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_base/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
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_stdlib/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_sync/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_time/include
|
||||
-iwithprefixbefore/pico-sdk/src/common/pico_util/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_regs/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_regs/include/
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_regs/include/
|
||||
-iwithprefixbefore/pico-sdk/src/rp2040/hardware_structs/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_clocks/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_divider/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_dma/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_flash/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_gpio/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_i2c/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_irq/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_pio/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_pll/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_pwm/include
|
||||
-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_timer/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_bootrom/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_double/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_multicore/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/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_stdio/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_uart/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_usb/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_unique_id/include
|
||||
@@ -0,0 +1,149 @@
|
||||
-Wl,--wrap=acos
|
||||
-Wl,--wrap=acosf
|
||||
-Wl,--wrap=acosh
|
||||
-Wl,--wrap=acoshf
|
||||
-Wl,--wrap=__aeabi_cdcmpeq
|
||||
-Wl,--wrap=__aeabi_cdcmple
|
||||
-Wl,--wrap=__aeabi_cdrcmple
|
||||
-Wl,--wrap=__aeabi_cfcmpeq
|
||||
-Wl,--wrap=__aeabi_cfcmple
|
||||
-Wl,--wrap=__aeabi_cfrcmple
|
||||
-Wl,--wrap=__aeabi_d2f
|
||||
-Wl,--wrap=__aeabi_d2iz
|
||||
-Wl,--wrap=__aeabi_d2lz
|
||||
-Wl,--wrap=__aeabi_d2uiz
|
||||
-Wl,--wrap=__aeabi_d2ulz
|
||||
-Wl,--wrap=__aeabi_dadd
|
||||
-Wl,--wrap=__aeabi_dcmpeq
|
||||
-Wl,--wrap=__aeabi_dcmpge
|
||||
-Wl,--wrap=__aeabi_dcmpgt
|
||||
-Wl,--wrap=__aeabi_dcmple
|
||||
-Wl,--wrap=__aeabi_dcmplt
|
||||
-Wl,--wrap=__aeabi_dcmpun
|
||||
-Wl,--wrap=__aeabi_ddiv
|
||||
-Wl,--wrap=__aeabi_dmul
|
||||
-Wl,--wrap=__aeabi_drsub
|
||||
-Wl,--wrap=__aeabi_dsub
|
||||
-Wl,--wrap=__aeabi_f2d
|
||||
-Wl,--wrap=__aeabi_f2iz
|
||||
-Wl,--wrap=__aeabi_f2lz
|
||||
-Wl,--wrap=__aeabi_f2uiz
|
||||
-Wl,--wrap=__aeabi_f2ulz
|
||||
-Wl,--wrap=__aeabi_fadd
|
||||
-Wl,--wrap=__aeabi_fcmpeq
|
||||
-Wl,--wrap=__aeabi_fcmpge
|
||||
-Wl,--wrap=__aeabi_fcmpgt
|
||||
-Wl,--wrap=__aeabi_fcmple
|
||||
-Wl,--wrap=__aeabi_fcmplt
|
||||
-Wl,--wrap=__aeabi_fcmpun
|
||||
-Wl,--wrap=__aeabi_fdiv
|
||||
-Wl,--wrap=__aeabi_fmul
|
||||
-Wl,--wrap=__aeabi_frsub
|
||||
-Wl,--wrap=__aeabi_fsub
|
||||
-Wl,--wrap=__aeabi_i2d
|
||||
-Wl,--wrap=__aeabi_i2f
|
||||
-Wl,--wrap=__aeabi_idiv
|
||||
-Wl,--wrap=__aeabi_idivmod
|
||||
-Wl,--wrap=__aeabi_l2d
|
||||
-Wl,--wrap=__aeabi_l2f
|
||||
-Wl,--wrap=__aeabi_ldivmod
|
||||
-Wl,--wrap=__aeabi_lmul
|
||||
-Wl,--wrap=__aeabi_memcpy
|
||||
-Wl,--wrap=__aeabi_memcpy4
|
||||
-Wl,--wrap=__aeabi_memcpy8
|
||||
-Wl,--wrap=__aeabi_memset
|
||||
-Wl,--wrap=__aeabi_memset4
|
||||
-Wl,--wrap=__aeabi_memset8
|
||||
-Wl,--wrap=__aeabi_ui2d
|
||||
-Wl,--wrap=__aeabi_ui2f
|
||||
-Wl,--wrap=__aeabi_uidiv
|
||||
-Wl,--wrap=__aeabi_uidivmod
|
||||
-Wl,--wrap=__aeabi_ul2d
|
||||
-Wl,--wrap=__aeabi_ul2f
|
||||
-Wl,--wrap=__aeabi_uldivmod
|
||||
-Wl,--wrap=asin
|
||||
-Wl,--wrap=asinf
|
||||
-Wl,--wrap=asinh
|
||||
-Wl,--wrap=asinhf
|
||||
-Wl,--wrap=atan
|
||||
-Wl,--wrap=atan2
|
||||
-Wl,--wrap=atan2f
|
||||
-Wl,--wrap=atanf
|
||||
-Wl,--wrap=atanh
|
||||
-Wl,--wrap=atanhf
|
||||
-Wl,--wrap=calloc
|
||||
-Wl,--wrap=cbrt
|
||||
-Wl,--wrap=cbrtf
|
||||
-Wl,--wrap=ceil
|
||||
-Wl,--wrap=ceilf
|
||||
-Wl,--wrap=__clz
|
||||
-Wl,--wrap=__clzdi2
|
||||
-Wl,--wrap=__clzl
|
||||
-Wl,--wrap=__clzll
|
||||
-Wl,--wrap=__clzsi2
|
||||
-Wl,--wrap=copysign
|
||||
-Wl,--wrap=copysignf
|
||||
-Wl,--wrap=cos
|
||||
-Wl,--wrap=cosf
|
||||
-Wl,--wrap=cosh
|
||||
-Wl,--wrap=coshf
|
||||
-Wl,--wrap=__ctzdi2
|
||||
-Wl,--wrap=__ctzsi2
|
||||
-Wl,--wrap=drem
|
||||
-Wl,--wrap=dremf
|
||||
-Wl,--wrap=exp
|
||||
-Wl,--wrap=exp10
|
||||
-Wl,--wrap=exp10f
|
||||
-Wl,--wrap=exp2
|
||||
-Wl,--wrap=exp2f
|
||||
-Wl,--wrap=expf
|
||||
-Wl,--wrap=expm1
|
||||
-Wl,--wrap=expm1f
|
||||
-Wl,--wrap=floor
|
||||
-Wl,--wrap=floorf
|
||||
-Wl,--wrap=fma
|
||||
-Wl,--wrap=fmaf
|
||||
-Wl,--wrap=fmod
|
||||
-Wl,--wrap=fmodf
|
||||
-Wl,--wrap=free
|
||||
-Wl,--wrap=hypot
|
||||
-Wl,--wrap=hypotf
|
||||
-Wl,--wrap=ldexp
|
||||
-Wl,--wrap=ldexpf
|
||||
-Wl,--wrap=log
|
||||
-Wl,--wrap=log10
|
||||
-Wl,--wrap=log10f
|
||||
-Wl,--wrap=log1p
|
||||
-Wl,--wrap=log1pf
|
||||
-Wl,--wrap=log2
|
||||
-Wl,--wrap=log2f
|
||||
-Wl,--wrap=logf
|
||||
-Wl,--wrap=malloc
|
||||
-Wl,--wrap=memcpy
|
||||
-Wl,--wrap=memset
|
||||
-Wl,--wrap=__popcountdi2
|
||||
-Wl,--wrap=__popcountsi2
|
||||
-Wl,--wrap=pow
|
||||
-Wl,--wrap=powf
|
||||
-Wl,--wrap=powint
|
||||
-Wl,--wrap=powintf
|
||||
-Wl,--wrap=remainder
|
||||
-Wl,--wrap=remainderf
|
||||
-Wl,--wrap=remquo
|
||||
-Wl,--wrap=remquof
|
||||
-Wl,--wrap=round
|
||||
-Wl,--wrap=roundf
|
||||
-Wl,--wrap=sin
|
||||
-Wl,--wrap=sincos
|
||||
-Wl,--wrap=sincosf
|
||||
-Wl,--wrap=sinf
|
||||
-Wl,--wrap=sinh
|
||||
-Wl,--wrap=sinhf
|
||||
-Wl,--wrap=sqrt
|
||||
-Wl,--wrap=sqrtf
|
||||
-Wl,--wrap=tan
|
||||
-Wl,--wrap=tanf
|
||||
-Wl,--wrap=tanh
|
||||
-Wl,--wrap=tanhf
|
||||
-Wl,--wrap=trunc
|
||||
-Wl,--wrap=truncf
|
||||
Submodule
+1
Submodule libraries/Adafruit_TinyUSB_Arduino added at d26aa1bbd2
+33
-33
@@ -1,38 +1,34 @@
|
||||
/*
|
||||
* EEPROM.cpp - RP2040 EEPROM emulation
|
||||
* Copyright (c) 2021 Earle F. Philhower III. All rights reserved.
|
||||
*
|
||||
* Based on ESP8266 EEPROM library, which is
|
||||
* Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
EEPROM.cpp - RP2040 EEPROM emulation
|
||||
Copyright (c) 2021 Earle F. Philhower III. All rights reserved.
|
||||
|
||||
Based on ESP8266 EEPROM library, which is
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "EEPROM.h"
|
||||
extern "C" {
|
||||
// This header is missing the "ifdef cplusplus extern C" bit
|
||||
#include <hardware/flash.h>
|
||||
}
|
||||
#include <hardware/sync.h>
|
||||
|
||||
extern "C" uint8_t _EEPROM_start;
|
||||
|
||||
EEPROMClass::EEPROMClass(void)
|
||||
: _sector(&_EEPROM_start)
|
||||
{
|
||||
: _sector(&_EEPROM_start) {
|
||||
}
|
||||
|
||||
void EEPROMClass::begin(size_t size) {
|
||||
@@ -40,13 +36,13 @@ void EEPROMClass::begin(size_t size) {
|
||||
size = 4096;
|
||||
}
|
||||
|
||||
size = (size + 255) & (~255); // Flash writes limited to 256 byte boundaries
|
||||
_size = (size + 255) & (~255); // Flash writes limited to 256 byte boundaries
|
||||
|
||||
// In case begin() is called a 2nd+ time, don't reallocate if size is the same
|
||||
if (_data && size != _size) {
|
||||
delete[] _data;
|
||||
_data = new uint8_t[size];
|
||||
} else if(!_data) {
|
||||
} else if (!_data) {
|
||||
_data = new uint8_t[size];
|
||||
}
|
||||
|
||||
@@ -63,7 +59,7 @@ bool EEPROMClass::end() {
|
||||
}
|
||||
|
||||
retval = commit();
|
||||
if (_data) {
|
||||
if (_data) {
|
||||
delete[] _data;
|
||||
}
|
||||
_data = 0;
|
||||
@@ -101,18 +97,22 @@ void EEPROMClass::write(int const address, uint8_t const value) {
|
||||
}
|
||||
|
||||
bool EEPROMClass::commit() {
|
||||
if (!_size)
|
||||
if (!_size) {
|
||||
return false;
|
||||
if (!_dirty)
|
||||
}
|
||||
if (!_dirty) {
|
||||
return true;
|
||||
if (!_data)
|
||||
}
|
||||
if (!_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO - this only stops IRQs on 1 core, need to do it on both
|
||||
uint32_t save = save_and_disable_interrupts();
|
||||
noInterrupts();
|
||||
rp2040.idleOtherCore();
|
||||
flash_range_erase((intptr_t)_sector - (intptr_t)XIP_BASE, 4096);
|
||||
flash_range_program((intptr_t)_sector - (intptr_t)XIP_BASE, _data, _size);
|
||||
restore_interrupts(save);
|
||||
rp2040.resumeOtherCore();
|
||||
interrupts();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+56
-48
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
EEPROM.cpp - RPI2040 EEPROM emulation
|
||||
/*
|
||||
EEPROM.cpp - RPI2040 EEPROM emulation
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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.
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef EEPROM_h
|
||||
@@ -28,48 +28,56 @@
|
||||
|
||||
class EEPROMClass {
|
||||
public:
|
||||
EEPROMClass(void);
|
||||
EEPROMClass(void);
|
||||
|
||||
void begin(size_t size);
|
||||
uint8_t read(int const address);
|
||||
void write(int const address, uint8_t const val);
|
||||
bool commit();
|
||||
bool end();
|
||||
void begin(size_t size);
|
||||
uint8_t read(int const address);
|
||||
void write(int const address, uint8_t const val);
|
||||
bool commit();
|
||||
bool end();
|
||||
|
||||
uint8_t * getDataPtr();
|
||||
uint8_t const * getConstDataPtr() const;
|
||||
uint8_t * getDataPtr();
|
||||
uint8_t const * getConstDataPtr() const;
|
||||
|
||||
template<typename T>
|
||||
T &get(int const address, T &t) {
|
||||
if (address < 0 || address + sizeof(T) > _size)
|
||||
return t;
|
||||
template<typename T>
|
||||
T &get(int const address, T &t) {
|
||||
if (address < 0 || address + sizeof(T) > _size) {
|
||||
return t;
|
||||
}
|
||||
|
||||
memcpy((uint8_t*) &t, _data + address, sizeof(T));
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T &put(int const address, const T &t) {
|
||||
if (address < 0 || address + sizeof(T) > _size)
|
||||
return t;
|
||||
if (memcmp(_data + address, (const uint8_t*)&t, sizeof(T)) != 0) {
|
||||
_dirty = true;
|
||||
memcpy(_data + address, (const uint8_t*)&t, sizeof(T));
|
||||
memcpy((uint8_t*) &t, _data + address, sizeof(T));
|
||||
return t;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
template<typename T>
|
||||
const T &put(int const address, const T &t) {
|
||||
if (address < 0 || address + sizeof(T) > _size) {
|
||||
return t;
|
||||
}
|
||||
if (memcmp(_data + address, (const uint8_t*)&t, sizeof(T)) != 0) {
|
||||
_dirty = true;
|
||||
memcpy(_data + address, (const uint8_t*)&t, sizeof(T));
|
||||
}
|
||||
|
||||
size_t length() {return _size;}
|
||||
return t;
|
||||
}
|
||||
|
||||
uint8_t& operator[](int const address) {return getDataPtr()[address];}
|
||||
uint8_t const & operator[](int const address) const {return getConstDataPtr()[address];}
|
||||
size_t length() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
uint8_t& operator[](int const address) {
|
||||
return getDataPtr()[address];
|
||||
}
|
||||
uint8_t const & operator[](int const address) const {
|
||||
return getConstDataPtr()[address];
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t* _sector;
|
||||
uint8_t* _data = nullptr;
|
||||
size_t _size = 0;
|
||||
bool _dirty = false;
|
||||
uint8_t* _sector;
|
||||
uint8_t* _data = nullptr;
|
||||
size_t _size = 0;
|
||||
bool _dirty = false;
|
||||
};
|
||||
|
||||
extern EEPROMClass EEPROM;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
This example generates a square wave based tone at a specified frequency
|
||||
and sample rate. Then outputs the data using the I2S interface to a
|
||||
MAX08357 I2S Amp Breakout board.
|
||||
|
||||
created 17 November 2016
|
||||
by Sandeep Mistry
|
||||
modified for ESP8266 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
const int frequency = 440; // frequency of square wave in Hz
|
||||
const int amplitude = 500; // amplitude of square wave
|
||||
const int sampleRate = 8000; // sample rate in Hz
|
||||
|
||||
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
|
||||
|
||||
short sample = amplitude; // current sample value
|
||||
int count = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("I2S simple tone");
|
||||
|
||||
// start I2S at the sample rate with 16-bits per sample
|
||||
if (!I2S.begin(sampleRate)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
while (1); // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (count % halfWavelength == 0) {
|
||||
// invert the sample every half wavelength count multiple to generate square wave
|
||||
sample = -1 * sample;
|
||||
}
|
||||
|
||||
// write the same sample twice, once for left and once for the right channel
|
||||
I2S.write(sample);
|
||||
I2S.write(sample);
|
||||
|
||||
// increment the counter for the next sample
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map I2S
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
I2S KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
end KEYWORD2
|
||||
|
||||
onReceive KEYWORD2
|
||||
onTransmit KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
I2S_PHILIPS_MODE LITERAL1
|
||||
@@ -0,0 +1,9 @@
|
||||
name=I2S
|
||||
version=1.0
|
||||
author=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
sentence=Enables the communication with devices that use the Inter-IC Sound (I2S) Bus. Specific implementation for RP2040, based off of pico-extras samples.
|
||||
paragraph=
|
||||
category=Communication
|
||||
url=http://www.arduino.cc/en/Reference/I2S
|
||||
architectures=rp2040
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
I2S Master library for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "I2S.h"
|
||||
|
||||
I2SClass::I2SClass() {
|
||||
_running = false;
|
||||
_pool = nullptr;
|
||||
_curBuff = nullptr;
|
||||
_bps = 0;
|
||||
_writtenHalf = false;
|
||||
_pinBCLK = 26;
|
||||
_pinDOUT = 28;
|
||||
}
|
||||
|
||||
bool I2SClass::setBCLK(pin_size_t pin) {
|
||||
if (_running || (pin > 28)) {
|
||||
return false;
|
||||
}
|
||||
_pinBCLK = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2SClass::setDOUT(pin_size_t pin) {
|
||||
if (_running || (pin > 29)) {
|
||||
return false;
|
||||
}
|
||||
_pinDOUT = pin;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2SClass::begin(long sampleRate) {
|
||||
if (_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bzero(&_audio_format, sizeof(_audio_format));
|
||||
_audio_format.sample_freq = (uint32_t)sampleRate;
|
||||
_audio_format.format = AUDIO_BUFFER_FORMAT_PCM_S16;
|
||||
_audio_format.channel_count = 2;
|
||||
|
||||
bzero(&_producer_format, sizeof(_producer_format));
|
||||
_producer_format.format = &_audio_format;
|
||||
_producer_format.sample_stride = 4;
|
||||
|
||||
if (!_pool) {
|
||||
_pool = audio_new_producer_pool(&_producer_format, 3, 256);
|
||||
}
|
||||
|
||||
bzero(&_config, sizeof(_config));
|
||||
_config.data_pin = _pinDOUT;
|
||||
_config.clock_pin_base = _pinBCLK;
|
||||
_config.dma_channel = 0;
|
||||
_config.pio_sm = 1;
|
||||
|
||||
if (!audio_i2s_setup(&_audio_format, &_config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!audio_i2s_connect(_pool)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_i2s_set_enabled(true);
|
||||
|
||||
_curBuff = take_audio_buffer(_pool, true);
|
||||
_curBuff->sample_count = 0;
|
||||
|
||||
_bps = 16;
|
||||
_freq = sampleRate;
|
||||
_running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void I2SClass::end() {
|
||||
if (_running) {
|
||||
audio_i2s_set_enabled(false);
|
||||
if (_curBuff) {
|
||||
release_audio_buffer(_pool, _curBuff);
|
||||
_curBuff = nullptr;
|
||||
}
|
||||
}
|
||||
_running = false;
|
||||
_bps = 0;
|
||||
_freq = 0;
|
||||
_writtenHalf = false;
|
||||
}
|
||||
|
||||
int I2SClass::availableForWrite() {
|
||||
if (!_running) {
|
||||
return 0;
|
||||
}
|
||||
// Can we get a whole new buffer to work with?
|
||||
if (!_curBuff) {
|
||||
_curBuff = take_audio_buffer(_pool, false);
|
||||
_curBuff->sample_count = 0;
|
||||
}
|
||||
if (!_curBuff) {
|
||||
return false;
|
||||
}
|
||||
return _curBuff->max_sample_count - _curBuff->sample_count;
|
||||
}
|
||||
|
||||
void I2SClass::flush() {
|
||||
if (!_curBuff || !_curBuff->sample_count) {
|
||||
return;
|
||||
}
|
||||
_audio_format.sample_freq = _freq;
|
||||
give_audio_buffer(_pool, _curBuff);
|
||||
_curBuff = nullptr;
|
||||
}
|
||||
|
||||
bool I2SClass::setFrequency(int newFreq) {
|
||||
if (newFreq != _freq) {
|
||||
flush();
|
||||
_freq = newFreq;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t I2SClass::write(uint8_t s) {
|
||||
return write((int16_t)s);
|
||||
}
|
||||
|
||||
size_t I2SClass::write(const uint8_t *buffer, size_t size) {
|
||||
return write((const void *)buffer, size);
|
||||
}
|
||||
|
||||
size_t I2SClass::write(int16_t s) {
|
||||
if (!_running) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Because our HW really wants 32b writes, store any 16b writes until another
|
||||
// 16b write comes in and then send the combined write down.
|
||||
if (_bps == 16) {
|
||||
if (_writtenHalf) {
|
||||
_writtenData <<= 16;
|
||||
_writtenData |= 0xffff & s;
|
||||
_writtenHalf = false;
|
||||
if (!_curBuff) {
|
||||
_curBuff = take_audio_buffer(_pool, true);
|
||||
_curBuff->sample_count = 0;
|
||||
}
|
||||
int32_t *samples = (int32_t *)_curBuff->buffer->bytes;
|
||||
samples[_curBuff->sample_count++] = _writtenData;
|
||||
if (_curBuff->sample_count == _curBuff->max_sample_count) {
|
||||
_audio_format.sample_freq = _freq;
|
||||
give_audio_buffer(_pool, _curBuff);
|
||||
_curBuff = nullptr;
|
||||
}
|
||||
} else {
|
||||
_writtenHalf = true;
|
||||
_writtenData = s & 0xffff;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Mostly non-blocking
|
||||
size_t I2SClass::write(const void *buffer, size_t size) {
|
||||
if (!_running) {
|
||||
return 0;
|
||||
}
|
||||
// We have no choice here because we need to write at least 1 byte...
|
||||
if (!_curBuff) {
|
||||
_curBuff = take_audio_buffer(_pool, true);
|
||||
_curBuff->sample_count = 0;
|
||||
}
|
||||
|
||||
int32_t *inSamples = (int32_t *)buffer;
|
||||
int written = 0;
|
||||
int wantToWrite = size / 4;
|
||||
while (wantToWrite) {
|
||||
if (!_curBuff) {
|
||||
_curBuff = take_audio_buffer(_pool, false);
|
||||
if (_curBuff) {
|
||||
_curBuff->sample_count = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int avail = _curBuff->max_sample_count - _curBuff->sample_count;
|
||||
int writeSize = (avail > wantToWrite) ? wantToWrite : avail;
|
||||
int32_t *samples = (int32_t *)_curBuff->buffer->bytes;
|
||||
memcpy(samples + _curBuff->sample_count, inSamples, writeSize * 4);
|
||||
_curBuff->sample_count += writeSize;
|
||||
inSamples += writeSize;
|
||||
written += writeSize;
|
||||
wantToWrite -= writeSize;
|
||||
if (_curBuff->sample_count == _curBuff->max_sample_count) {
|
||||
_audio_format.sample_freq = _freq;
|
||||
give_audio_buffer(_pool, _curBuff);
|
||||
_curBuff = nullptr;
|
||||
}
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
I2SClass I2S;
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
I2S Master library for the Raspberry Pi Pico RP2040
|
||||
|
||||
Copyright (c) 2021 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 <Arduino.h>
|
||||
#include "pico/audio_i2s.h"
|
||||
|
||||
class I2SClass : public Stream {
|
||||
public:
|
||||
I2SClass();
|
||||
|
||||
// Only 16 bitsPerSample are allowed by the PIO code. Only write, no read.
|
||||
bool setBCLK(pin_size_t pin);
|
||||
bool setDOUT(pin_size_t pin);
|
||||
bool begin(long sampleRate);
|
||||
void end();
|
||||
|
||||
// from Stream
|
||||
virtual int available() override {
|
||||
return -1;
|
||||
}
|
||||
virtual int read() override {
|
||||
return -1;
|
||||
}
|
||||
virtual int peek() override {
|
||||
return -1;
|
||||
}
|
||||
virtual void flush() override;
|
||||
|
||||
// from Print (see notes on write() methods below)
|
||||
virtual size_t write(uint8_t) override;
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) override;
|
||||
virtual int availableForWrite() override;
|
||||
|
||||
bool setFrequency(int newFreq);
|
||||
|
||||
// Write a single L:R sample to the I2S device. Blocking until write succeeds
|
||||
size_t write(int16_t);
|
||||
// Write up to size samples to the I2S device. Non-blocking, will write
|
||||
// from 0...size samples and return that count. Be sure your app handles
|
||||
// partial writes (i.e. by yield()ing and then retrying to write the
|
||||
// remaining data.
|
||||
size_t write(const void *buffer, size_t lrsamples);
|
||||
|
||||
// Note that these callback are called from **INTERRUPT CONTEXT** and hence
|
||||
// must be both stored in IRAM and not perform anything that's not legal in
|
||||
// an interrupt
|
||||
//void onTransmit(void(*)(void)); -- Not yet implemented, need to edit pico-extra to get callback
|
||||
//void onReceive(void(*)(void)); -- no I2S input yet
|
||||
|
||||
private:
|
||||
pin_size_t _pinBCLK;
|
||||
pin_size_t _pinDOUT;
|
||||
int _bps;
|
||||
int _freq;
|
||||
bool _running;
|
||||
|
||||
// Audio format/pool config
|
||||
audio_format_t _audio_format;
|
||||
audio_buffer_format_t _producer_format;
|
||||
audio_i2s_config_t _config;
|
||||
|
||||
// We manage our own buffer pool here...
|
||||
audio_buffer_pool_t *_pool;
|
||||
audio_buffer_t *_curBuff;
|
||||
|
||||
// Support for ::write(x) on 16b quantities
|
||||
uint32_t _writtenData;
|
||||
bool _writtenHalf;
|
||||
};
|
||||
|
||||
extern I2SClass I2S;
|
||||
Submodule
+1
Submodule libraries/Keyboard added at dcc1a556bf
@@ -0,0 +1,56 @@
|
||||
// Released to the public domain
|
||||
//
|
||||
// This sketch will read an uploaded file and increment a counter file
|
||||
// each time the sketch is booted.
|
||||
|
||||
// Be sure to install the Pico LittleFS Data Upload extension for the
|
||||
// Arduino IDE from:
|
||||
// https://github.com/earlephilhower/arduino-pico-littlefs-plugin/
|
||||
// The latest release is available from:
|
||||
// https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases
|
||||
|
||||
// Before running:
|
||||
// 1) Select Tools->Flash Size->(some size with a FS/filesystem)
|
||||
// 2) Use the Tools->Pico Sketch Data Upload tool to transfer the contents of
|
||||
// the sketch data directory to the Pico
|
||||
|
||||
#include <LittleFS.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
LittleFS.begin();
|
||||
char buff[32];
|
||||
int cnt = 1;
|
||||
File f = LittleFS.open("counts.txt", "r");
|
||||
if (f) {
|
||||
bzero(buff, 32);
|
||||
if (f.read((uint8_t *)buff, 31)) {
|
||||
sscanf(buff, "%d", &cnt);
|
||||
Serial.printf("I have been run %d times\n", cnt);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
|
||||
cnt++;
|
||||
sprintf(buff, "%d\n", cnt);
|
||||
f = LittleFS.open("counts.txt", "w");
|
||||
if (f) {
|
||||
f.write(buff, strlen(buff));
|
||||
f.close();
|
||||
}
|
||||
|
||||
Serial.println("---------------");
|
||||
File i = LittleFS.open("file1.txt", "r");
|
||||
if (i) {
|
||||
while (i.available()) {
|
||||
Serial.write(i.read());
|
||||
}
|
||||
Serial.println("---------------");
|
||||
i.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Hello!
|
||||
|
||||
Welcome to the Raspberry Pi Pico using arduino-pico!
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user