Compare commits

...
23 Commits
Author SHA1 Message Date
Earle F. Philhower, III 541e23d663 Update to major version 2.0.0 2022-04-27 12:10:55 -07:00
Earle F. Philhower, III 65fe176795 Make default CPU speed 133MHz (#557)
The chip supports 133MHz and the other Pico core already defaults to
the higher speed, so make 133 the default.

It can still be changed through the menus and will stay at 125 unless
pre-existing users change it so they will see no difference.
2022-04-27 11:31:21 -07:00
Earle F. Philhower, III cfc91804c8 Fix memory corruption introducted in FreeRTOS port (#556)
To remove compiler warning the valid core macro was modified to only check
that the core passed in was < # of total cores.  Unfortunately there are
parts of the FreeRTOS code where the passed in core # is -1.  The upstream
catches this and returns FALSE, but my hacked version returned TRUE.  This
caused interesting memory corruption errors and crashes when the
current task block[-1] was updated.

Undo the change and fix the 1 spot where a warning happens instead.

Undo the forced compiler -O0 for port.c, it was only masking the fault.
2022-04-27 09:42:15 -07:00
Earle F. Philhower, III 88d213a30b Additional FreeRTOS adjustments (#555)
Use low power WFE when idle.

Set PORT.C to built `-O0` always because it seems to occasinally end
up with interrupts disabled in task code, causing the SYSTICK never to
fire and killing task switching.

No need for dynamic exceptions.  We don't move the execbase.
2022-04-27 03:53:07 -07:00
Earle F. Philhower, III 189b796499 More FreeRTOS ISR work 2022-04-25 19:11:38 -07:00
Earle F. Philhower, III af7f430227 Change the RTD theme (#554)
Alabaster is not my favorite, try something with colors...
2022-04-25 18:03:07 -07:00
Andy2No 797abb5a7f Update SimpleTone.ino (#552)
Adds code to define which pins are used, moving them from the defaults, which are the same as the only three analogue input pins, and adding comments to explain how to change them.

The original didn't give any clues about which pins were used, which isn't ideal for a beginner - it was necessary to look at the code for the library, to work that out.

The new code redundantly defines a pWS pin number (as pBCLK+1), which isn't used in the example, but is meant as a reminder to the person using it, of how to wire up WS.
2022-04-25 12:21:34 -07:00
Earle F. Philhower, III ffff21a936 Update FreeRTOS library to avoid random crashes (#553) 2022-04-25 12:10:48 -07:00
Earle F. Philhower, III 781fb3ab48 Update docs, increase max analogWriteFreq to 1MHz (#551) 2022-04-25 08:23:50 -07:00
Earle F. Philhower, III bda630e419 Add FreeRTOS support thanks to @hfellner (#533)
Using all the work from @hfellner and others, add FreeRTOS
SMP support.

Allow idling cores through the FreeRTOS FIFO queue to
allow for file system and EEPROM support.

Make delay a weak function so FreeRTOS can override.

Add cycle count support under FreeRTOS using a PIO SM.

Use a task-based approach for handling the USB periodic work
instead of the IRQ-based one in the main core.

Set 8 prio levels so it fits in 3 bits nicely (0..7).
2022-04-24 20:59:57 -07:00
Earle F. Philhower, III 9afdc48ddd Add SoftwareSerial wrapper around SerialPIO (#548)
I receive mails weekly asking how to use `SoftwareSerial` on this core.
Avoid the issue by including a simple wrapper class around `SerialPIO`
which gives the proper class name and constructor parameters.

Note that inverted mode is not supported.
2022-04-24 15:07:55 -07:00
Earle F. Philhower, III 3ee031abc9 Add ::overflow() return to SerialUART/SerialPIO (#547)
Matching the Arduino SoftwareSerial API
2022-04-24 14:44:23 -07:00
Earle F. Philhower, III d1f9bce083 Document the Generic RP2040 option (#546)
Fixes #522
2022-04-24 11:04:17 -07:00
Earle F. Philhower, III 670957487a Update version 2022-04-22 12:55:08 -07:00
Earle F. Philhower, III 1c0133704e Update to LittleFS 2.5 (#545) 2022-04-22 12:22:27 -07:00
Earle F. Philhower, III 5927d4ee2b Fix SerialPIO sampling, avoid reading random garbage (#544)
Adjust the 1/2 bit time to match the number of extra cycles in the actual
PIO loop.

Throw out the entire start bit, which results in sampling the data at the
midpoint and not the starting time of a bit (which was causing random
failures on read data).

Tested at 300bps all the way to 2,000,000bps using a loopback connection.

Fixes #360
2022-04-21 19:48:30 -07:00
Earle F. Philhower, III 5dee051a7a Update version 2022-04-17 14:40:27 -07:00
Earle F. Philhower, III 561110231d Add SparkFun Thing Plus RP2040 (#540) 2022-04-17 14:39:28 -07:00
Earle F. Philhower, III eff908385e Add Seeed XAIO RP2040 support (#538)
Fixes #537
2022-04-16 10:52:06 -07:00
Jean-Luc Béchennec 784a6ed5ad Added the ability to set pad current via pinMode: OUTPUT_2MA, OUTPUT_… (#532) 2022-04-10 13:33:19 -07:00
Earle F. Philhower, III da2d08a27b Update keywords.txt 2022-04-09 11:27:01 -07:00
Earle F. Philhower, III 061b38f0b8 Add RTS/CTS to Arduino Nano Connect Serial2(NINA) (#525)
Fixes #524
2022-03-30 14:12:24 -07:00
Arya11111 9971bda9cb Modify DFRobot pins_arduino.h file. (#521) 2022-03-29 07:17:00 -07:00
76 changed files with 2783 additions and 457 deletions
+5 -5
View File
@@ -20,7 +20,7 @@ jobs:
- name: Run codespell
uses: codespell-project/actions-codespell@master
with:
skip: ./pico-extras,./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api
skip: ./pico-extras,./ArduinoCore-API,./libraries/ESP8266SdFat,./libraries/Adafruit_TinyUSB_Arduino,./libraries/LittleFS/lib,./tools/pyserial,./pico-sdk,./.github,./docs/i2s.rst,./cores/rp2040/api,./libraries/FreeRTOS
ignore_words_list: ser,DOUT
# Consistent style
@@ -46,10 +46,10 @@ jobs:
./tests/restyle.sh
# If anything changed, GIT should return an error and fail the test
git diff --exit-code
- name: Check Arduino API copy is clean
run: |
git submodule update --init ./ArduinoCore-API
diff -r ./cores/rp2040/api ./ArduinoCore-API/api
# - name: Check Arduino API copy is clean
# run: |
# git submodule update --init ./ArduinoCore-API
# diff -r ./cores/rp2040/api ./ArduinoCore-API/api
# Build all examples on linux (core and Arduino IDE)
build-linux:
+3
View File
@@ -25,3 +25,6 @@
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
[submodule "libraries/FreeRTOS/lib/FreeRTOS-Kernel"]
path = libraries/FreeRTOS/lib/FreeRTOS-Kernel
url = https://github.com/earlephilhower/FreeRTOS-Kernel.git
+4 -1
View File
@@ -18,7 +18,7 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m
* Adafruit QTPy RP2040
* Adafruit STEMMA Friend RP2040
* Adafruit Trinkey RP2040 QT
* Arduino Nano RP2040 Connect (preliminary)
* Arduino Nano RP2040 Connect
* Cytron Maker Pi RP2040
* Cytron Maker Nano RP2040
* DeRuiLab FlyBoard2040 Core
@@ -29,8 +29,10 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m
* Invector Labs Challenger RP2040 LoRa
* Invector Labs RPICO32
* Melopero Shake RP2040
* Seeed XIAO RP2040
* Solder Party RP2040 Stamp
* SparkFun ProMicro RP2040
* SparkFun Thing Plus RP2040
* uPesy RP2040 DevKit
* WIZnet W5100S-EVB-Pico
* Generic (configurable flash, I/O pins)
@@ -171,6 +173,7 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
* [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.
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
-Earle F. Philhower, III
earlephilhower@yahoo.com
+1298 -288
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -79,6 +79,9 @@ void analogWriteFreq(uint32_t freq);
void analogWriteRange(uint32_t range);
void analogWriteResolution(int res);
// FreeRTOS potential calls
extern bool __isFreeRTOS;
#ifdef __cplusplus
} // extern "C"
#endif
+116 -89
View File
@@ -25,7 +25,11 @@
#include <hardware/structs/systick.h>
#include <pico/multicore.h>
#include <pico/util/queue.h>
#include <CoreMutex.h>
#include "CoreMutex.h"
#include "ccount.pio.h"
extern "C" volatile bool __otherCoreIdled;
class _MFIFO {
public:
@@ -45,9 +49,12 @@ public:
}
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);
if (!__isFreeRTOS) {
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);
}
// FreeRTOS port.c will handle the IRQ hooking
}
void push(uint32_t val) {
@@ -79,9 +86,9 @@ public:
return;
}
mutex_enter_blocking(&_idleMutex);
_otherIdled = false;
__otherCoreIdled = false;
multicore_fifo_push_blocking(_GOTOSLEEP);
while (!_otherIdled) { /* noop */ }
while (!__otherCoreIdled) { /* noop */ }
}
void resumeOtherCore() {
@@ -89,9 +96,9 @@ public:
return;
}
mutex_exit(&_idleMutex);
_otherIdled = false;
__otherCoreIdled = false;
// Other core will exit busy-loop and return to operation
// once otherIdled == false.
// once __otherCoreIdled == false.
}
void clear() {
@@ -108,98 +115,31 @@ public:
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;
if (!__isFreeRTOS) {
multicore_fifo_clear_irq();
noInterrupts(); // We need total control, can't run anything
while (multicore_fifo_rvalid()) {
if (_GOTOSLEEP == multicore_fifo_pop_blocking()) {
__otherCoreIdled = true;
while (__otherCoreIdled) { /* noop */ }
break;
}
}
interrupts();
}
interrupts();
}
bool _multicore = false;
mutex_t _idleMutex;
static volatile bool _otherIdled;
queue_t _queue[2];
static constexpr int _GOTOSLEEP = 0x66666666;
static constexpr uint32_t _GOTOSLEEP = 0xC0DED02E;
};
class RP2040;
extern RP2040 rp2040;
extern "C" void main1();
class RP2040 {
public:
RP2040() {
_epoch = 0;
// Enable SYSTICK exception
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
systick_hw->csr = 0x7;
systick_hw->rvr = 0x00FFFFFF;
}
~RP2040() { /* noop */ }
// 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));
}
// Get current clock frequency
static int f_cpu() {
return clock_get_hz(clk_sys);
}
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
volatile uint64_t _epoch = 0;
inline uint32_t getCycleCount() {
uint32_t epoch;
uint32_t ctr;
do {
epoch = (uint32_t)_epoch;
ctr = systick_hw->cvr;
} while (epoch != (uint32_t)_epoch);
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
}
inline uint64_t getCycleCount64() {
uint64_t epoch;
uint64_t ctr;
do {
epoch = _epoch;
ctr = systick_hw->cvr;
} while (epoch != _epoch);
return epoch + (1LL << 24) - ctr;
}
void idleOtherCore() {
fifo.idleOtherCore();
}
void resumeOtherCore() {
fifo.resumeOtherCore();
}
void restartCore1() {
multicore_reset_core1();
fifo.clear();
multicore_launch_core1(main1);
}
// Multicore comms FIFO
_MFIFO fifo;
private:
static void _SystickHandler() {
rp2040._epoch += 1LL << 24;
}
};
class PIOProgram;
// Wrapper class for PIO programs, abstracting common operations out
// TODO - Add unload/destructor
@@ -255,3 +195,90 @@ private:
const pio_program_t *_pgm;
};
class RP2040 {
public:
RP2040() { /* noop */ }
~RP2040() { /* noop */ }
void begin() {
_epoch = 0;
if (!__isFreeRTOS) {
// Enable SYSTICK exception
exception_set_exclusive_handler(SYSTICK_EXCEPTION, _SystickHandler);
systick_hw->csr = 0x7;
systick_hw->rvr = 0x00FFFFFF;
} else {
int off = 0;
_ccountPgm = new PIOProgram(&ccount_program);
_ccountPgm->prepare(&_pio, &_sm, &off);
ccount_program_init(_pio, _sm, off);
pio_sm_set_enabled(_pio, _sm, true);
}
}
// 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));
}
// Get current clock frequency
static int f_cpu() {
return clock_get_hz(clk_sys);
}
// Get CPU cycle count. Needs to do magic to extens 24b HW to something longer
volatile uint64_t _epoch = 0;
inline uint32_t getCycleCount() {
if (!__isFreeRTOS) {
uint32_t epoch;
uint32_t ctr;
do {
epoch = (uint32_t)_epoch;
ctr = systick_hw->cvr;
} while (epoch != (uint32_t)_epoch);
return epoch + (1 << 24) - ctr; /* CTR counts down from 1<<24-1 */
} else {
return ccount_read(_pio, _sm);
}
}
inline uint64_t getCycleCount64() {
if (!__isFreeRTOS) {
uint64_t epoch;
uint64_t ctr;
do {
epoch = _epoch;
ctr = systick_hw->cvr;
} while (epoch != _epoch);
return epoch + (1LL << 24) - ctr;
} else {
return ccount_read(_pio, _sm);
}
}
void idleOtherCore() {
fifo.idleOtherCore();
}
void resumeOtherCore() {
fifo.resumeOtherCore();
}
void restartCore1() {
multicore_reset_core1();
fifo.clear();
multicore_launch_core1(main1);
}
// Multicore comms FIFO
_MFIFO fifo;
private:
static void _SystickHandler() {
rp2040._epoch += 1LL << 24;
}
PIO _pio;
int _sm;
PIOProgram *_ccountPgm;
};
+2
View File
@@ -287,6 +287,8 @@ static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
return USB_TASK_INTERVAL;
}
void __USBStart() __attribute__((weak));
void __USBStart() {
if (tusb_inited()) {
// Already called
+4 -4
View File
@@ -1,5 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 1
#define ARDUINO_PICO_MINOR 13
#define ARDUINO_PICO_REVISION 1
#define ARDUINO_PICO_VERSION_STR "1.13.1"
#define ARDUINO_PICO_MAJOR 2
#define ARDUINO_PICO_MINOR 0
#define ARDUINO_PICO_REVISION 0
#define ARDUINO_PICO_VERSION_STR "2.0.0"
+15 -3
View File
@@ -97,7 +97,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
}
while (!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) {
uint32_t decode = _rxPIO->rxf[_rxSM];
decode >>= 32 - _rxBits;
decode >>= 33 - _rxBits;
uint32_t val = 0;
for (int b = 0; b < _bits + 1; b++) {
val |= (decode & (1 << (b * 2))) ? 1 << b : 0;
@@ -127,7 +127,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances
_writer = next_writer;
} else {
// TODO: Overflow
_overflow = true;
}
}
}
@@ -146,6 +146,7 @@ SerialPIO::~SerialPIO() {
}
void SerialPIO::begin(unsigned long baud, uint16_t config) {
_overflow = false;
_baud = baud;
switch (config & SERIAL_PARITY_MASK) {
case SERIAL_PARITY_EVEN:
@@ -229,7 +230,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
pio_sm_clear_fifos(_rxPIO, _rxSM); // Remove any existing data
// Put phase divider into OSR w/o using add'l program memory
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 2);
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 5 /* insns in PIO halfbit loop */);
pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false));
// Join the TX FIFO to the RX one now that we don't need it
@@ -289,6 +290,17 @@ int SerialPIO::read() {
return -1;
}
bool SerialPIO::overflow() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
return false;
}
bool hold = _overflow;
_overflow = false;
return hold;
}
int SerialPIO::available() {
CoreMutex m(&_mutex);
if (!_running || !m || (_rx == NOPIN)) {
+2
View File
@@ -47,6 +47,7 @@ public:
virtual int availableForWrite() override;
virtual void flush() override;
virtual size_t write(uint8_t c) override;
bool overflow();
using Print::write;
operator bool() override;
@@ -60,6 +61,7 @@ private:
int _bits;
uart_parity_t _parity;
int _stop;
bool _overflow;
mutex_t _mutex;
PIOProgram *_txPgm;
+24 -4
View File
@@ -114,12 +114,12 @@ bool SerialUART::setFIFOSize(size_t size) {
return true;
}
SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) {
SerialUART::SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size_t rts, pin_size_t cts) {
_uart = uart;
_tx = tx;
_rx = rx;
_rts = UART_PIN_NOT_DEFINED;
_cts = UART_PIN_NOT_DEFINED;
_rts = rts;
_cts = cts;
mutex_init(&_mutex);
mutex_init(&_fifoMutex);
}
@@ -131,6 +131,7 @@ void SerialUART::begin(unsigned long baud, uint16_t config) {
if (_running) {
end();
}
_overflow = false;
_queue = new uint8_t[_fifoSize];
_baud = baud;
uart_init(_uart, baud);
@@ -271,6 +272,16 @@ int SerialUART::read() {
return -1;
}
bool SerialUART::overflow() {
CoreMutex m(&_mutex);
if (!_running || !m) {
return false;
}
bool hold = _overflow;
_overflow = false;
return hold;
}
int SerialUART::available() {
CoreMutex m(&_mutex);
if (!_running || !m) {
@@ -339,8 +350,17 @@ SerialUART::operator bool() {
return _running;
}
#if defined(PIN_SERIAL1_RTS)
SerialUART Serial1(uart0, PIN_SERIAL1_TX, PIN_SERIAL1_RX, PIN_SERIAL1_RTS, PIN_SERIAL1_CTS);
#else
SerialUART Serial1(uart0, PIN_SERIAL1_TX, PIN_SERIAL1_RX);
#endif
#if defined(PIN_SERIAL2_RTS)
SerialUART Serial2(uart1, PIN_SERIAL2_TX, PIN_SERIAL2_RX, PIN_SERIAL2_RTS, PIN_SERIAL2_CTS);
#else
SerialUART Serial2(uart1, PIN_SERIAL2_TX, PIN_SERIAL2_RX);
#endif
void arduino::serialEvent1Run(void) {
if (serialEvent1 && Serial1.available()) {
@@ -378,7 +398,7 @@ void __not_in_flash_func(SerialUART::_handleIRQ)(bool inIRQ) {
// Avoid using division or mod because the HW divider could be in use
_writer = next_writer;
} else {
// TODO: Overflow
_overflow = true;
}
}
if (inIRQ) {
+3 -1
View File
@@ -31,7 +31,7 @@ extern "C" typedef struct uart_inst uart_inst_t;
#define UART_PIN_NOT_DEFINED (255u)
class SerialUART : public HardwareSerial {
public:
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx);
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx, pin_size_t rts = UART_PIN_NOT_DEFINED, pin_size_t cts = UART_PIN_NOT_DEFINED);
// Select the pinout. Call before .begin()
bool setRX(pin_size_t pin);
@@ -60,6 +60,7 @@ public:
virtual size_t write(uint8_t c) override;
virtual size_t write(const uint8_t *p, size_t len) override;
using Print::write;
bool overflow();
operator bool() override;
// Not to be called by users, only from the IRQ handler. In public so that the C-language IQR callback can access it
@@ -73,6 +74,7 @@ private:
int _baud;
mutex_t _mutex;
bool _polling = false;
bool _overflow;
// Lockless, IRQ-handled circular queue
uint32_t _writer;
+37
View File
@@ -0,0 +1,37 @@
/*
SoftwareSerial wrapper for SerialPIO
Copyright (c) 2022 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 "SerialPIO.h"
class SoftwareSerial : public SerialPIO {
public:
// Note the rx/tx pins are swapped in PIO vs SWSerial
SoftwareSerial(pin_size_t rx, pin_size_t tx, bool invert = true) : SerialPIO(tx, rx) {
if (invert) {
panic("SoftwareSerial inverted operation not supported\n");
}
}
void listen() { /* noop */ }
bool isListening() {
return true;
}
};
+4
View File
@@ -20,6 +20,10 @@ typedef enum {
OUTPUT = 0x1,
INPUT_PULLUP = 0x2,
INPUT_PULLDOWN = 0x3,
OUTPUT_2MA = 0x4,
OUTPUT_4MA = 0x5,
OUTPUT_8MA = 0x6,
OUTPUT_12MA = 0x7,
} PinMode;
typedef enum {
+62
View File
@@ -0,0 +1,62 @@
; Cycle Count for the Raspberry Pi Pico RP2040
;
; Copyright (c) 2022 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
; Cycle count is stored in {-y, -x}
.program ccount
cnt:
jmp x-- cnt
epoch:
jmp y-- cnt
% c-sdk {
static inline void ccount_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = ccount_program_get_default_config(offset);
pio_sm_init(pio, sm, offset, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, 0));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
}
static inline uint64_t ccount_read(PIO pio, uint sm) {
static uint64_t extra = 0;
// Guard against having the epoch rollover while we're reading the time.
// If epoch2 != epoch1, we looped in middle and get new LSW
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
extra += 8;
uint32_t y1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t y2 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x2 = -((int)pio_sm_get_blocking(pio, sm));
uint64_t val;
if (y2 != y1) {
val = ((((uint64_t)y2) << 32LL) | x2) + y2 /* adjust for missed cycle every epoch increment */;
} else {
val = ((((uint64_t)y1) << 32LL) | x1) + y1 /* adjust for missed cycle every epoch increment */;
}
return val + extra;
}
%}
+71
View File
@@ -0,0 +1,71 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
#pragma once
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// ------ //
// ccount //
// ------ //
#define ccount_wrap_target 0
#define ccount_wrap 1
static const uint16_t ccount_program_instructions[] = {
// .wrap_target
0x0040, // 0: jmp x--, 0
0x0080, // 1: jmp y--, 0
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program ccount_program = {
.instructions = ccount_program_instructions,
.length = 2,
.origin = -1,
};
static inline pio_sm_config ccount_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + ccount_wrap_target, offset + ccount_wrap);
return c;
}
static inline void ccount_program_init(PIO pio, uint sm, uint offset) {
pio_sm_config c = ccount_program_get_default_config(offset);
pio_sm_init(pio, sm, offset, &c);
pio_sm_exec(pio, sm, pio_encode_set(pio_x, 0));
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
}
static inline uint64_t ccount_read(PIO pio, uint sm) {
static uint64_t extra = 0;
// Guard against having the epoch rollover while we're reading the time.
// If epoch2 != epoch1, we looped in middle and get new LSW
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_y));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
pio_sm_exec(pio, sm, pio_encode_mov(pio_isr, pio_x));
pio_sm_exec(pio, sm, pio_encode_push(false, false));
extra += 8;
uint32_t y1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x1 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t y2 = -((int)pio_sm_get_blocking(pio, sm));
uint32_t x2 = -((int)pio_sm_get_blocking(pio, sm));
uint64_t val;
if (y2 != y1) {
val = ((((uint64_t)y2) << 32LL) | x2) + y2 /* adjust for missed cycle every epoch increment */;
} else {
val = ((((uint64_t)y1) << 32LL) | x1) + y1 /* adjust for missed cycle every epoch increment */;
}
return val + extra;
}
#endif
+3
View File
@@ -25,6 +25,9 @@
#include "Adafruit_TinyUSB_API.h"
#endif
extern "C" void delay(unsigned long ms) __attribute__((weak));
extern "C" void yield() __attribute__((weak));
extern "C"
{
+61 -28
View File
@@ -24,20 +24,24 @@
#include <pico/multicore.h>
RP2040 rp2040;
extern "C" {
volatile bool __otherCoreIdled = false;
};
volatile bool _MFIFO::_otherIdled = false;
mutex_t _pioMutex;
extern void setup();
extern void loop();
// FreeRTOS potential includes
extern void initFreeRTOS() __attribute__((weak));
extern void startFreeRTOS() __attribute__((weak));
bool __isFreeRTOS;
// 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));
@@ -53,14 +57,40 @@ extern "C" void main1() {
}
}
extern void __loop() {
#ifdef USE_TINYUSB
yield();
#endif
if (arduino::serialEventRun) {
arduino::serialEventRun();
}
if (arduino::serialEvent1Run) {
arduino::serialEvent1Run();
}
if (arduino::serialEvent2Run) {
arduino::serialEvent2Run();
}
}
extern "C" int main() {
#if F_CPU != 125000000
set_sys_clock_khz(F_CPU / 1000, true);
#endif
// Let rest of core know if we're using FreeRTOS
__isFreeRTOS = initFreeRTOS ? true : false;
mutex_init(&_pioMutex);
rp2040.begin();
initVariant();
if (__isFreeRTOS) {
initFreeRTOS();
}
#ifndef NO_USB
#ifdef USE_TINYUSB
TinyUSB_Device_Init(0);
@@ -69,43 +99,46 @@ extern "C" int main() {
__USBStart();
#ifndef DISABLE_USB_SERIAL
// Enable serial port for reset/upload always
Serial.begin(115200);
if (!__isFreeRTOS) {
// Enable serial port for reset/upload always
Serial.begin(115200);
}
#endif
#endif
#endif
#if defined DEBUG_RP2040_PORT
DEBUG_RP2040_PORT.begin(115200);
if (!__isFreeRTOS) {
DEBUG_RP2040_PORT.begin(115200);
}
#endif
#ifndef NO_USB
if (setup1 || loop1) {
rp2040.fifo.begin(2);
multicore_launch_core1(main1);
} else {
rp2040.fifo.begin(1);
if (!__isFreeRTOS) {
if (setup1 || loop1) {
rp2040.fifo.begin(2);
multicore_launch_core1(main1);
} else {
rp2040.fifo.begin(1);
}
rp2040.fifo.registerCore();
}
rp2040.fifo.registerCore();
#endif
setup();
while (true) {
loop();
#ifdef USE_TINYUSB
yield();
#endif
if (arduino::serialEventRun) {
arduino::serialEventRun();
}
if (arduino::serialEvent1Run) {
arduino::serialEvent1Run();
}
if (arduino::serialEvent2Run) {
arduino::serialEvent2Run();
if (!__isFreeRTOS) {
setup();
while (true) {
loop();
__loop();
}
} else {
rp2040.fifo.begin(2);
startFreeRTOS();
}
return 0;
}
extern "C" unsigned long ulMainGetRunTimeCounterValue() {
return rp2040.getCycleCount64();
}
+3 -3
View File
@@ -27,7 +27,7 @@
#include <hardware/adc.h>
static uint32_t analogScale = 255;
static uint16_t analogFreq = 1000;
static uint32_t analogFreq = 1000;
static bool pwmInitted = false;
static bool adcInitted = false;
static uint16_t analogWritePseudoScale = 1;
@@ -42,9 +42,9 @@ extern "C" void analogWriteFreq(uint32_t freq) {
if (freq < 100) {
DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq);
analogFreq = 100;
} else if (freq > 60000) {
} else if (freq > 1000000) {
DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq);
analogFreq = 60000;
analogFreq = 1000000;
} else {
analogFreq = freq;
}
+17
View File
@@ -43,7 +43,24 @@ extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
gpio_put(ulPin, 1);
break;
case OUTPUT:
case OUTPUT_4MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_4MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_2MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_2MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_8MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_8MA);
gpio_set_dir(ulPin, true);
break;
case OUTPUT_12MA:
gpio_init(ulPin);
gpio_set_drive_strength(ulPin, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_dir(ulPin, true);
break;
default:
+12 -1
View File
@@ -30,10 +30,21 @@ 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.
Analog Output Restrictions
--------------------------
The PWM generator source clock restricts the legal combinations of
frequency and ranges. For example, at 1MHz only about 6 bits of range
are possible. When you define an ``analogWriteFreq`` and ``analogWriteRange``
that can't be fulfilled by the hardware, the frequency will be preserved
but the accuracy (range) will be reduced automatically. Your code will
still send in the range you specify, but the core itself will transparently
map it into the allowable PWN range.
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.
From 100Hz to 1MHz are supported.
void analogWriteRange(uint32_t range) and analogWriteResolution(int res)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+4 -4
View File
@@ -19,7 +19,7 @@
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
import sphinx_rtd_theme
# -- General configuration ------------------------------------------------
@@ -30,7 +30,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = ['sphinx_rtd_theme']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -46,7 +46,7 @@ master_doc = 'index'
# General information about the project.
project = u'Arduino-Pico'
copyright = u'2021, Earle F. Philhower, III'
copyright = u'2022, Earle F. Philhower, III'
author = u'Earle F. Philhower, III'
# The version info for the project you're documenting, acts as replacement for
@@ -82,7 +82,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'sphinx_rtd_theme'
# 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
+49
View File
@@ -0,0 +1,49 @@
FreeRTOS SMP
============
The SMP (multicore) port of FreeRTOS is included with the core. This allows complex
task operations and real preemptive multithreading in your sketches. While the
``setup1`` and ``loop1`` way of multitasking is simplest for most folks, FreeRTOS
is much more powerful.
Enabling FreeRTOS
-----------------
To enable FreeRTOS, simply add
.. code:: c++
#include <FreeRTOS.h>
to your sketch and it will be included and enabled automatically.
Configuration and Predefined Tasks
----------------------------------
FreeRTOS is configured with 8 priority levels (0 through 7) and a process for
``setup()/loop()``, ``setup1()/loop1()``, and the USB port will be created. The task
quantum is 1 millisecond (i.e. 1,000 switches per second).
``setup()`` and ``loop()`` are assigned to only run on core 0, while ``setup1()`` and ``loop1()``
only run in core 1 in this mode, the same as the default multithreading mode.
You can launch and manage additional processes using the standard FreeRTOS routines.
``delay()`` and ``yield()`` free the CPU for other tasks, while ``delayMicroseconds()`` does not.
Caveats
-------
While the core now supports FreeRTOS, most (probably all) Arduino libraries were not written
to support preemptive multithreading. This means that all calls to a particular library should
be made from a single task.
In particular, the ``LittleFS`` and ``SDFS`` libraries can not be called from different
threads. Do all ``File`` operations from a single thread or else undefined behavior
(aka strange crashes or data corruption) can occur.
More Information
----------------
For full FreeRTOS documentation look at `FreeRTOS.org <https://freertos.org/index.html>`__
and `FreeRTOS SMP support <https://freertos.org/symmetric-multiprocessing-introduction.html>`__.
+37
View File
@@ -34,3 +34,40 @@ 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.
Generic RP2040 Support
----------------------
If your RP2040 board isn't in the menus you can still use it with the
IDE bu using the `Board->Generic RP2040` menu option. You will need to
then set the flash size (see above) and tell the IDE how to communicate
with the flash chip using the `Tools->Boot Stage 2` menu.
Boot Stage 2 Options for Generic RP2040
---------------------------------------
The Arduino Pico needs to set up its internal flash interface to talk to
whatever flash chip is in the system. While all flash chips support a
basic (and slow) 1-bit operation using common timings, each different
brand (and sometimes model) of flash chip require custom timings to work
in QSPI (4-bit) mode. The `Boot Stage 2` menu lets you select from
the supported timings.
The options with `/2` in them divide the system clock by 2 to drive the
bus. Options with `/4` divide the clock by 4 and so are slower but more
compatible.
If you can't match a chip name in the menu to your flash chip, a simple
test can be run to determine which is correct. Simpily load the `Blink`
example, select the first option in the `Boot Stage 2` menu, and upload.
If that works, note it and continue. Iterate through the options and
note which ones work. If an option doesn't work, unplug the chip and
hold the BOOTSEL button down while re-inserting it to enter the ROM
uploader mode. (The CPU and flash will not be harmed if the test fails.)
If one of the custom bootloaders (not `Generic SPI /2 or /4`) worked, use
that option to get best performance. If none worked other than the
`Generic SPI /2 or /4` then use that. The `/2` options of all models
is preferred as it is faster, but some boards do require `/4` on the
custom chip interfaces.
When in doubt, `Generic SPI /4` should work with any flash chip but is
slow.
+2
View File
@@ -37,6 +37,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
USB (Arduino and Adafruit_TinyUSB) <usb>
Multicore Processing <multicore>
FreeRTOS SMP (multicore) <freertos>
Ported/Optimized Libraries <libraries>
Using Pico-SDK <sdk>
+5
View File
@@ -60,3 +60,8 @@ it use a non-default pinout with a simple call
SPI.setCS(5);
SD.begin(5);
}
Pad Strength
============
The Raspberry Pi Pico has the ability to set the current that a pin (actually the pad associated with it) is capable of supplying. The current can be set to values of 2mA, 4mA, 8mA and 12mA. By default, on a reset, the setting is 4mA. A `pinMode(x, OUTPUT)`, where `x` is the pin number, is also the default setting. 4 settings have been added for use with `pinMode`: `OUTPUT_2MA`, `OUTPUT_4MA`, which has the same behavior as `OUTPUT`, `OUTPUT_8MA` and `OUTPUT_12MA`.
+10
View File
@@ -21,3 +21,13 @@ For example, to make a transmit-only port on GP16
For detailed information about the Serial ports, see the
Arduino `Serial Reference <https://www.arduino.cc/reference/en/language/functions/communication/serial/>`_ .
SoftwareSerial Emulation
========================
A ``SoftwareSerial`` wrapper is included to provide plug-and-play compatibility
with the Arduino `Software Serial <https://docs.arduino.cc/learn/built-in-libraries/software-serial>`_
library. Use the normal ``#include <SoftwareSerial.h>`` to include it. The following
differences from the Arduino standard are present:
* Inverted mode is not supported
* All ports are always listening. The ``listen`` call is a no-op, and ``isListening()`` always returns ``true`` .
+6 -1
View File
@@ -11,7 +11,7 @@
#######################################
setup1 KEYWORD2
loop2 KEYWORD2
loop1 KEYWORD2
analogWriteFreq KEYWORD2
analogWriteRange KEYWORD2
@@ -36,3 +36,8 @@ prepare KEYWORD2
SerialPIO KEYWORD2
setFIFOSize KEYWORD2
setPollingMode KEYWORD2
OUTPUT_2MA LITERAL1
OUTPUT_4MA LITERAL1
OUTPUT_8MA LITERAL1
OUTPUT_12MA LITERAL1
@@ -0,0 +1,81 @@
// Demonstrates a simple use of the setup1()/loop1() functions
// for a multiprocessor run.
// Will output something like, where C0 is running on core 0 and
// C1 is on core 1, in parallel.
// 11:23:07.507 -> C0: Blue leader standing by...
// 11:23:07.507 -> C1: Red leader standing by...
// 11:23:07.507 -> C1: Stay on target...
// 11:23:08.008 -> C1: Stay on target...
// 11:23:08.505 -> C0: Blue leader standing by...
// 11:23:08.505 -> C1: Stay on target...
// 11:23:09.007 -> C1: Stay on target...
// 11:23:09.511 -> C0: Blue leader standing by...
// 11:23:09.511 -> C1: Stay on target...
// 11:23:10.015 -> C1: Stay on target...
// Released to the public domain
#include <FreeRTOS.h>
#include <task.h>
#include <map>
#include <EEPROM.h>
std::map<eTaskState, const char *> eTaskStateName { {eReady, "Ready"}, { eRunning, "Running" }, {eBlocked, "Blocked"}, {eSuspended, "Suspended"}, {eDeleted, "Deleted"} };
void ps() {
int tasks = uxTaskGetNumberOfTasks();
TaskStatus_t *pxTaskStatusArray = new TaskStatus_t[tasks];
unsigned long runtime;
tasks = uxTaskGetSystemState( pxTaskStatusArray, tasks, &runtime );
Serial.printf("# Tasks: %d\n", tasks);
Serial.println("ID, NAME, STATE, PRIO, CYCLES");
for (int i=0; i < tasks; i++) {
Serial.printf("%d: %-16s %-10s %d %lu\n", i, pxTaskStatusArray[i].pcTaskName, eTaskStateName[pxTaskStatusArray[i].eCurrentState], pxTaskStatusArray[i].uxCurrentPriority, pxTaskStatusArray[i].ulRunTimeCounter);
}
delete[] pxTaskStatusArray;
}
void blink(void *param) {
(void) param;
pinMode(LED_BUILTIN, OUTPUT);
while (true) {
digitalWrite(LED_BUILTIN, LOW);
delay(750);
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
}
}
void setup() {
Serial.begin(115200);
xTaskCreate(blink, "BLINK", 128, nullptr, 1, nullptr);
delay(5000);
}
volatile int val= 0;
void loop() {
Serial.printf("C0: Blue leader standing by...\n");
ps();
Serial.printf("val: %d\n", val);
delay(1000);
}
// Running on core1
void setup1() {
delay(5000);
Serial.printf("C1: Red leader standing by...\n");
}
void loop1() {
static int x = 0;
Serial.printf("C1: Stay on target...\n");
val++;
if (++x < 10) {
EEPROM.begin(512);
EEPROM.write(0,x);
EEPROM.commit();
}
delay(1000);
}
+60
View File
@@ -0,0 +1,60 @@
# Syntax Coloring Map For FreeRTOS
# https://arduino.github.io/arduino-cli/library-specification/#keywords
# Formatted by a single true tab (not spaces)
# Datatypes (KEYWORD1)
StackType_t KEYWORD1
BaseType_t KEYWORD1
UBaseType_t KEYWORD1
TickType_t KEYWORD1
TaskHandle_t KEYWORD1
QueueHandle_t KEYWORD1
TimerHandle_t KEYWORD1
SemaphoreHandle_t KEYWORD1
StreamBufferHandle_t KEYWORD1
MessageBufferHandle_t KEYWORD1
EventGroupHandle_t KEYWORD1
# Methods and Functions (KEYWORD2)
xSemaphoreCreateMutex KEYWORD2
xSemaphoreCreateBinary KEYWORD2
xSemaphoreTake KEYWORD2
xSemaphoreTakeFromISR KEYWORD2
xSemaphoreGive KEYWORD2
xSemaphoreGiveFromISR KEYWORD2
xTaskCreate KEYWORD2
vTaskDelete KEYWORD2
vTaskDelay KEYWORD2
xTaskDelayUntil KEYWORD2
xQueueCreate KEYWORD2
xQueueSend KEYWORD2
xQueueReceive KEYWORD2
pcTaskGetName KEYWORD2
ulTaskNotifyTake KEYWORD2
vTaskNotifyGiveFromISR KEYWORD2
taskYIELD KEYWORD2
vTaskSuspend KEYWORD2
vTaskResume KEYWORD2
xTaskResumeFromISR KEYWORD2
xTaskGetTickCount KEYWORD2
xTaskGetTickCountFromISR KEYWORD2
uxTaskGetNumberOfTasks KEYWORD2
uxTaskGetStackHighWaterMark KEYWORD2
# Instances (KEYWORD2)
# Structures (KEYWORD3)
TaskParameters_t KEYWORD3
TaskStatus_t KEYWORD3
ListItem_t KEYWORD3
MiniListItem_t KEYWORD3
HeapStats_t KEYWORD3
# Constants (LITERAL1)
portUSE_WDTO LITERAL1
portTICK_PERIOD_MS LITERAL1
configTICK_RATE_HZ LITERAL1
configCPU_CLOCK_HZ LITERAL1
configMAX_PRIORITIES LITERAL1
configMINIMAL_STACK_SIZE LITERAL1
+10
View File
@@ -0,0 +1,10 @@
name=FreeRTOS
version=1.0.0
author=Graham Sanderson <info@freertos.org>
maintainer=Graham Sanderson <info@freertos.org>
sentence=<h3>FreeRTOS Real Time Operating System implemented for RP2040.</h3>
paragraph=Taken from the official FreeRTOS SMP branch.
category=Timing
url=https://github.com/FreeRTOS/FreeRTOS-Kernel
architectures=rp2040
license=MIT
+39
View File
@@ -0,0 +1,39 @@
**ATTENTION**
Please be aware that this library was copied from the original Arduino AVR FreeRTOS library and may still contain files from that library that have no meaning in the context of this package, i.e. the licensing and code of conduct file! Each file retains the license and copyright from where it was taken (FreeRTOS repository or AVR FreeRTOS library, respectively.)
______
This is a copy of the RP2040 port of the FreeRTOS SMP branch, packaged as an Arduino library.
It has been created to provide access to FreeRTOS capabilities, with full compatibility to the Arduino environment.
It does this by keeping hands off almost everything, and only touching the minimum of hardware to be successful.
## General
FreeRTOS has a multitude of configuration options, which can be specified from within the FreeRTOSConfig.h file.
To keep commonality with all of the Arduino hardware options, some sensible defaults have been selected.
System ticks are 1ms, which means that Tasks can only be scheduled to run up to 1000 times per second.
Stack for the `loop()` function has been set at 256 bytes. This can be configured by adjusting the `configMINIMAL_STACK_SIZE` parameter. If you have stack overflow issues, just increase it.
Users should prefer to allocate larger structures, arrays, or buffers using `pvPortMalloc()`, rather than defining them locally on the stack.
Memory for the heap is allocated by the normal `malloc()` function, wrapped by `pvPortMalloc()`.
This option has been selected because it is automatically adjusted to use the capabilities of each device.
Other heap allocation schemes are supported by FreeRTOS, and they can used with additional configuration.
## Errors
* Stack Overflow: If any stack (for the `loop()` or) for any Task overflows, there will be a slow LED blink, with 4 second cycle.
* Heap Overflow: If any Task tries to allocate memory and that allocation fails, there will be a fast LED blink, with 100 millisecond cycle.
## Files & Configuration
* `RP2040_FreeRTOS.h` : Must always be `#include` first. It references other configuration files, and sets defaults where necessary.
* `FreeRTOSConfig.h` : Contains a multitude of API and environment configurations.
* `variantHooks.cpp` : Contains the RP2040 specific configurations for this port of FreeRTOS.
* `heap_3.c` : Contains the heap allocation scheme based on `malloc()`. Other schemes are available, but depend on user configuration for specific MCU choice.
## Sources / Credits ✨
This library is built on the efforts of the authors of the FreeRTOS SMP port for the RP2040, using the original Arduino FreeRTOS library as a template for the library package and the Arduino specific behavior.
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/FreeRTOS.h"
+122
View File
@@ -0,0 +1,122 @@
/* Cores */
#define configNUM_CORES 2
#define configUSE_CORE_AFFINITY 1
#define configRUN_MULTIPLE_PRIORITIES 1
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_MINIMAL_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( ( unsigned long ) F_CPU )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 8 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 164 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_QUEUE_SETS 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION 0
/* Run time stats related definitions. */
void vMainConfigureTimerForRunTimeStats( void );
unsigned long ulMainGetRunTimeCounterValue( void );
#define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() //vMainConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulMainGetRunTimeCounterValue()
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 1
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH ( 80 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
/* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human
readable ASCII form. See the notes in the implementation of vTaskList() within
FreeRTOS/Source/tasks.c for limitations. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configUSE_MUTEXES 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configCHECK_FOR_STACK_OVERFLOW 2
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* Cortex-M specific definitions. */
#undef __NVIC_PRIO_BITS
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 3 /* 8 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
extern void rtosFatalError(void);
#define configASSERT( x ) \
if( ( x ) == 0 ) { portDISABLE_INTERRUPTS(); rtosFatalError(); }
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
//#define xPortPendSVHandler PendSV_Handler
//#define xPortSysTickHandler SysTick_Handler
//#define vPortSVCHandler SVC_Handler
/* The size of the global output buffer that is available for use when there
are multiple command interpreters running at once (for example, one on a UART
and one on TCP/IP). This is done to prevent an output buffer being defined by
each implementation - which would waste RAM. In this case, there is only one
command interpreter running. */
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2048
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 0
#define configSUPPORT_PICO_SYNC_INTEROP 1
#define configSUPPORT_PICO_TIME_INTEROP 1
#include "rp2040_config.h"
//#include "task.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/StackMacros.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/atomic.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/croutine.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/croutine.h"
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/deprecated_definitions.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/event_groups.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/event_groups.h"
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/freertos_sdk_config.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/MemMang/heap_3.c"
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/idle_task_static_memory.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/list.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/list.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/message_buffer.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/mpu_prototypes.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/mpu_wrappers.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/port.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/portable.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/portmacro.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/projdefs.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/queue.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/queue.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/semphr.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/stack_macros.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/stream_buffer.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/stream_buffer.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/task.h"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/tasks.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/timers.c"
+1
View File
@@ -0,0 +1 @@
#include "../lib/FreeRTOS-Kernel/include/timers.h"
+419
View File
@@ -0,0 +1,419 @@
/*
* Copyright (C) 2021 Phillip Stevens All Rights Reserved.
* Modifications by Earle F. Philhower, III, for Arduino-Pico
*
* 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.
*
*
* This file is NOT part of the FreeRTOS distribution.
*
*/
#include <stdlib.h>
/* Arduino Core includes */
#include <Arduino.h>
#include <RP2040USB.h>
#include "tusb.h"
#define USB_TASK_IRQ 31
/* Raspberry PI Pico includes */
#include <pico.h>
#include <pico/time.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
/*-----------------------------------------------------------*/
void initFreeRTOS(void)
{
}
extern void setup() __attribute__((weak));
extern void loop() __attribute__((weak));
extern void setup1() __attribute__((weak));
extern void loop1() __attribute__((weak));
// Idle functions (USB, events, ...) from the core
extern void __loop();
volatile bool __usbInitted = false;
static void __core0(void *params)
{
(void) params;
#ifndef NO_USB
while (!__usbInitted) {
delay(1);
}
#endif
if (setup) {
setup();
}
if (loop) {
while (1) {
loop();
__loop();
}
} else {
while (1) {
__loop();
}
}
}
static void __core1(void *params)
{
(void) params;
#ifndef NO_USB
while (!__usbInitted) {
delay(1);
}
#endif
if (setup1) {
setup1();
}
if (loop1) {
while (1) {
loop1();
}
} else {
while (1) {
vTaskDelay(1000);
}
}
}
extern "C" void delay(unsigned long ms) {
vTaskDelay(ms / portTICK_PERIOD_MS);
}
extern "C" void yield() {
taskYIELD();
}
extern mutex_t __usb_mutex;
static TaskHandle_t __usbTask;
static void __usb(void *param);
void startFreeRTOS(void)
{
TaskHandle_t c0;
xTaskCreate(__core0, "CORE0", 1024, 0, configMAX_PRIORITIES / 2, &c0);
vTaskCoreAffinitySet( c0, 1 << 0 );
if (setup1 || loop1) {
TaskHandle_t c1;
xTaskCreate(__core1, "CORE1", 1024, 0, configMAX_PRIORITIES / 2, &c1);
vTaskCoreAffinitySet( c1, 1 << 1 );
}
// Initialise and run the freeRTOS scheduler. Execution should never return here.
vTaskStartScheduler();
while (true) {
/* noop */
}
}
/*-----------------------------------------------------------*/
void prvDisableInterrupts()
{
portDISABLE_INTERRUPTS();
}
void prvEnableInterrupts()
{
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
#if ( configUSE_IDLE_HOOK == 1 )
/*
* Call the user defined loop() function from within the idle task.
* This allows the application designer to add background functionality
* without the overhead of a separate task.
*
* NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.
*
*/
extern "C"
void vApplicationIdleHook( void ) __attribute__((weak));
void vApplicationIdleHook( void )
{
__wfe(); // Low power idle if nothing to do...
}
#endif /* configUSE_IDLE_HOOK == 1 */
/*-----------------------------------------------------------*/
#if ( configUSE_MINIMAL_IDLE_HOOK == 1 )
/*
* Call the user defined minimalIdle() function from within the idle task.
* This allows the application designer to add background functionality
* without the overhead of a separate task.
*
* NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.
*
*/
void minimalIdle( void ) __attribute__((weak));
void minimalIdle() {} //Empty minimalIdle function
extern "C"
void vApplicationMinimalIdleHook( void ) __attribute__((weak));
void vApplicationMinimalIdleHook( void )
{
minimalIdle();
}
#endif /* configUSE_MINIMAL_IDLE_HOOK == 1 */
/*-----------------------------------------------------------*/
#if ( configUSE_TICK_HOOK == 1 )
/*
* Call the user defined minimalIdle() function from within the idle task.
* This allows the application designer to add background functionality
* without the overhead of a separate task.
*
* NOTE: vApplicationMinimalIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.
*
*/
void tick( void ) __attribute__((weak));
void tick() {} //Empty minimalIdle function
extern "C"
void vApplicationTickHook( void ) __attribute__((weak));
void vApplicationTickHook( void )
{
tick();
}
#endif /* configUSE_TICK_HOOK == 1 */
/*-----------------------------------------------------------*/
#if ( configUSE_MALLOC_FAILED_HOOK == 1 || configCHECK_FOR_STACK_OVERFLOW >= 1 || configDEFAULT_ASSERT == 1 )
/**
* Private function to enable board led to use it in application hooks
*/
void prvSetMainLedOn( void )
{
gpio_init(LED_BUILTIN);
gpio_set_dir(LED_BUILTIN, true);
gpio_put(LED_BUILTIN, true);
}
/**
* Private function to blink board led to use it in application hooks
*/
void prvBlinkMainLed( void )
{
gpio_put(LED_BUILTIN, !gpio_get(LED_BUILTIN));
}
#endif
/*---------------------------------------------------------------------------*\
Usage:
called on fatal error (interrupts disabled already)
\*---------------------------------------------------------------------------*/
extern "C"
void rtosFatalError(void)
{
prvSetMainLedOn(); // Main LED on.
for(;;)
{
// Main LED slow flash
sleep_ms(100);
prvBlinkMainLed();
sleep_ms(2000);
prvBlinkMainLed();
}
}
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
/*---------------------------------------------------------------------------*\
Usage:
called by task system when a malloc failure is noticed
Description:
Malloc failure handler -- Shut down all interrupts, send serious complaint
to command port. FAST Blink on main LED.
Arguments:
pxTask - pointer to task handle
pcTaskName - pointer to task name
Results:
<none>
Notes:
This routine will never return.
This routine is referenced in the task.c file of FreeRTOS as an extern.
\*---------------------------------------------------------------------------*/
extern "C"
void vApplicationMallocFailedHook( void ) __attribute__((weak));
void vApplicationMallocFailedHook( void )
{
prvSetMainLedOn(); // Main LED on.
for(;;)
{
sleep_ms(50);
prvBlinkMainLed(); // Main LED fast blink.
}
}
#endif /* configUSE_MALLOC_FAILED_HOOK == 1 */
/*-----------------------------------------------------------*/
#if ( configCHECK_FOR_STACK_OVERFLOW >= 1 )
extern "C"
void vApplicationStackOverflowHook( TaskHandle_t xTask,
char * pcTaskName ) __attribute__((weak));
void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__((unused)),
char * pcTaskName __attribute__((unused)) )
{
prvSetMainLedOn(); // Main LED on.
for(;;)
{
sleep_ms(2000);
prvBlinkMainLed(); // Main LED slow blink.
}
}
#endif /* configCHECK_FOR_STACK_OVERFLOW >= 1 */
/*-----------------------------------------------------------*/
#if ( configSUPPORT_STATIC_ALLOCATION >= 1 )
extern "C"
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
configSTACK_DEPTH_TYPE * pulIdleTaskStackSize ) __attribute__((weak));
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
configSTACK_DEPTH_TYPE * pulIdleTaskStackSize )
{
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
#if ( configUSE_TIMERS >= 1 )
extern "C"
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
configSTACK_DEPTH_TYPE * pulTimerTaskStackSize ) __attribute__((weak));
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
configSTACK_DEPTH_TYPE * pulTimerTaskStackSize )
{
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif /* configUSE_TIMERS >= 1 */
#endif /* configSUPPORT_STATIC_ALLOCATION >= 1 */
/**
* configASSERT default implementation
*/
#if configDEFAULT_ASSERT == 1
extern "C"
void vApplicationAssertHook() {
taskDISABLE_INTERRUPTS(); // Disable task interrupts
prvSetMainLedOn(); // Main LED on.
for(;;)
{
sleep_ms(100);
prvBlinkMainLed(); // Led off.
sleep_ms(2000);
prvBlinkMainLed(); // Led on.
sleep_ms(100);
prvBlinkMainLed(); // Led off
sleep_ms(100);
prvBlinkMainLed(); // Led on.
}
}
#endif
static void __usb_irq() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR( __usbTask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
static void __usb(void *param)
{
(void) param;
tusb_init();
irq_set_exclusive_handler(USB_TASK_IRQ, __usb_irq);
irq_set_enabled(USB_TASK_IRQ, true);
Serial.begin(115200);
__usbInitted = true;
while (true) {
if (mutex_try_enter(&__usb_mutex, NULL)) {
tud_task();
mutex_exit(&__usb_mutex);
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
void __USBStart()
{
mutex_init(&__usb_mutex);
// Make highest prio and locked to core 0
xTaskCreate(__usb, "USB", 256, 0, configMAX_PRIORITIES - 1, &__usbTask);
vTaskCoreAffinitySet( __usbTask, 1 << 0 );
}
@@ -6,28 +6,59 @@
created 17 November 2016
by Sandeep Mistry
modified for ESP8266 by Earle F. Philhower, III <earlephilhower@yahoo.com>
Only 16 bitsPerSample are allowed by the PIO code. Only write, no read.
bool setBCLK(pin_size_t pin); // Must be 28 or less. Default is 26
// This assigns two adjacent pins - the pin after this one (one greater) is the WS (word select) signal,
// which toggles before the sample for each channel is sent
bool setDOUT(pin_size_t pin); // Must be 29 or less. Default is 28
*/
#include <I2S.h>
// GPIO pin numbers
//define pBCLK 26
#define pBCLK 20
#define pWS (pBCLK+1)
//define pDOUT 28
#define pDOUT 22
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 sampleRate = 8000; // sample rate in Hz
const int sampleRate = 16000; // minimum for UDA1334A
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
short sample = amplitude; // current sample value
int count = 0;
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 1);
Serial.begin(9600);
Serial.println("I2S simple tone");
I2S.setBCLK(pBCLK); // Must be 28 or less. Default is 26
// This assigns two adjacent pins - the pin after this one (one greater) is the WS (word select) signal,
// which toggles before the sample for each channel is sent
I2S.setDOUT(pDOUT); // Must be 29 or less. Default is 28
// 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() {
@@ -43,4 +74,3 @@ void loop() {
// increment the counter for the next sample
count++;
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "framework-arduinopico",
"version": "1.11301.0",
"version": "1.20000.0",
"description": "Arduino Wiring-based Framework (RPi Pico RP2040)",
"keywords": [
"framework",
+6
View File
@@ -71,12 +71,18 @@
{
"name": "Invector Labs RPICO32"
},
{
"name": "Seeed XIAO RP2040"
},
{
"name": "Solder Party RP2040 Stamp"
},
{
"name": "SparkFun ProMicro RP2040"
},
{
"name": "SparkFun Thing Plus RP2040"
},
{
"name": "Melopero Shake RP2040"
},
+1 -1
View File
@@ -20,7 +20,7 @@
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=Raspberry Pi RP2040 Boards
version=1.13.1
version=2.0.0
runtime.tools.pqt-gcc.path={runtime.platform.path}/system/arm-none-eabi
runtime.tools.pqt-python3.path={runtime.platform.path}/system/python3
+5 -3
View File
@@ -32,7 +32,7 @@ def BuildDebugLevel(name):
print("%s.menu.dbglvl.%s.build.debug_level=%s" % (name, l[0], l[1]))
def BuildFreq(name):
for f in [ 125, 50, 100, 133, 150, 175, 200, 225, 250, 275, 300]:
for f in [ 133, 50, 100, 125, 150, 175, 200, 225, 250, 275, 300]:
warn = ""
if f > 133: warn = " (Overclock)"
print("%s.menu.freq.%s=%s MHz%s" % (name, f, f, warn))
@@ -225,7 +225,6 @@ BuildGlobalMenuList()
# Raspberry Pi
MakeBoard("rpipico", "Raspberry Pi", "Pico", "0x2e8a", "0x000a", 250, "RASPBERRY_PI_PICO", 2, "boot2_w25q080_2_padded_checksum")
# Adafruit
MakeBoard("adafruit_feather", "Adafruit", "Feather RP2040", "0x239a", "0x80f1", 250, "ADAFRUIT_FEATHER_RP2040", 8, "boot2_w25x10cl_4_padded_checksum")
MakeBoard("adafruit_itsybitsy", "Adafruit", "ItsyBitsy RP2040", "0x239a", "0x80fd", 250, "ADAFRUIT_ITSYBITSY_RP2040", 8, "boot2_w25q080_2_padded_checksum")
@@ -263,10 +262,14 @@ MakeBoard("solderparty_rp2040_stamp", "Solder Party", "RP2040 Stamp", "0x1209",
# SparkFun
MakeBoard("sparkfun_promicrorp2040", "SparkFun", "ProMicro RP2040", "0x1b4f", "0x0026", 250, "SPARKFUN_PROMICRO_RP2040", 16, "boot2_generic_03h_4_padded_checksum")
MakeBoard("sparkfun_thingplusrp2040", "SparkFun", "Thing Plus RP2040", "0x1b4f", "0x0026", 250, "SPARKFUN_THINGPLUS_RP2040", 16, "boot2_w25q080_2_padded_checksum")
# Upesy
MakeBoard("upesy_rp2040_devkit", "uPesy", "RP2040 DevKit", "0x2e8a", "0x1007", 250, "UPESY_RP2040_DEVKIT", 2, "boot2_w25q080_2_padded_checksum")
# Seeed
MakeBoard("seeed_xiao_rp2040", "Seeed", "XAIO RP2040", "0x2e8a", "0x000a", 250, "SEEED_XAIO_RP2040", 2, "boot2_w25q080_2_padded_checksum")
# WIZnet
MakeBoard("wiznet_5100s_evb_pico", "WIZnet", "W5100S-EVB-Pico", "0x2e8a", "0x1008", 250, "WIZNET_5100S_EVB_PICO", 2, "boot2_w25q080_2_padded_checksum")
@@ -274,5 +277,4 @@ MakeBoard("wiznet_5100s_evb_pico", "WIZnet", "W5100S-EVB-Pico", "0x2e8a", "0x100
MakeBoard("generic", "Generic", "RP2040", "0x2e8a", "0xf00a", 250, "GENERIC_RP2040", 16, "boot2_generic_03h_4_padded_checksum")
sys.stdout.close()
+4 -2
View File
@@ -47,8 +47,10 @@ static const uint8_t A3 = (29u);
#define PIN_SERIAL1_TX (D1)
#define PIN_SERIAL1_RX (D0)
#define PIN_SERIAL2_TX (D25)
#define PIN_SERIAL2_RX (D26)
#define PIN_SERIAL2_TX (D25)
#define PIN_SERIAL2_RX (D26)
#define PIN_SERIAL2_CTS (D27)
#define PIN_SERIAL2_RTS (D28)
// SPI
#define PIN_SPI0_MISO (D12)
+19 -14
View File
@@ -4,19 +4,19 @@
// https://www.dfrobot.com
// Not pinned out
#define PIN_LED (31u)
#define PIN_LED (13u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// UART0
#define PIN_SERIAL1_TX (28u)
#define PIN_SERIAL1_RX (29u)
// Not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// UART1
#define PIN_SERIAL2_TX (4u)
#define PIN_SERIAL2_RX (5u)
// SPI
#define PIN_SPI0_MISO (0u)
#define PIN_SPI0_MISO (0u)
#define PIN_SPI0_MOSI (3u)
#define PIN_SPI0_SCK (2u)
#define PIN_SPI0_SS (1u)
@@ -28,13 +28,18 @@
#define PIN_SPI1_SS (31u)
// Wire
#define PIN_WIRE0_SDA (31u)
#define PIN_WIRE0_SCL (31u)
#define PIN_WIRE1_SDA (26u)
#define PIN_WIRE1_SCL (27u)
#define PIN_WIRE0_SDA (4u)
#define PIN_WIRE0_SCL (5u)
#define PIN_WIRE1_SDA (2u)
#define PIN_WIRE1_SCL (3u)
#define SERIAL_HOWMANY (2u)
#define SERIAL_HOWMANY (3u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#define WIRE_HOWMANY (2u)
#define __PIN_A0 (29u)
#define __PIN_A1 (28u)
#define __PIN_A2 (31u)
#define __PIN_A3 (31u)
#include "../generic/common.h"
+48
View File
@@ -0,0 +1,48 @@
#pragma once
// Pin definitions taken from:
// https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html
// LEDs
#define PIN_LED (17u)
#define PIN_LED_R (17u)
#define PIN_LED_G (16u)
#define PIN_LED_B (25u)
// NeoPixel
#define PIN_NEOPIXEL (12u)
#define NEOPIXEL_POWER (11u)
// Serial1
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// Serial2 not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (4u)
#define PIN_SPI0_MOSI (3u)
#define PIN_SPI0_SCK (2u)
#define PIN_SPI0_SS (31u) // not pinned out
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
// Wire
#define PIN_WIRE0_SDA (6u)
#define PIN_WIRE0_SCL (7u)
// Wire1 not pinned out
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"
@@ -0,0 +1,40 @@
#pragma once
// Taken from schematic at https://cdn.sparkfun.com/assets/e/2/7/6/b/ProMicroRP2040_Graphical_Datasheet.pdf
// LEDs
#define PIN_LED (25u)
#define PIN_NEOPIXEL (8u)
#define NUM_NEOPIXEL (1)
// UARTs
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (4u)
#define PIN_SPI0_MOSI (3u)
#define PIN_SPI0_SCK (2u)
#define PIN_SPI0_SS (31u)
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (15u)
#define PIN_SPI1_SCK (14u)
#define PIN_SPI1_SS (9u)
// Wire
#define PIN_WIRE0_SDA (16u)
#define PIN_WIRE0_SCL (17u)
#define PIN_WIRE1_SDA (6u)
#define PIN_WIRE1_SCL (7u)
#define SERIAL_HOWMANY (3u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"