Skip to content

Commit

Permalink
Merge branch 'master' into picoadk-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
DatanoiseTV authored Sep 20, 2024
2 parents d2855a8 + b2ec6ec commit 317d74d
Show file tree
Hide file tree
Showing 104 changed files with 12,039 additions and 717 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,6 @@
[submodule "cores/rp2040/tlsf"]
path = lib/tlsf
url = https://github.com/earlephilhower/tlsf.git
[submodule "libraries/ESPHost"]
path = libraries/ESPHost
url = https://github.com/Networking-for-Arduino/ESPHost.git
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
* [Xoshiro-cpp](https://github.com/Reputeless/Xoshiro-cpp) is copyright (c) 2020 Ryo Suzuki and distributed under the MIT license.
* [FatFS low-level filesystem](http://elm-chan.org/fsw/ff/) code is Copyright (C) 2024, ChaN, all rights reserved.
* [TLSF memory manager for PSRAM from Espressif fork](https://github.com/espressif/tlsf) of [original](https://github.com/mattconte/tlsf) by Matthew Conte is copyright Matthew Conte and licensed under the MIT license.
* [ESPHost library](https://github.com/Networking-for-Arduino/ESPHost) is LGPL licensed by its maintainers.

-Earle F. Philhower, III
[email protected]
1,344 changes: 1,067 additions & 277 deletions boards.txt

Large diffs are not rendered by default.

18 changes: 15 additions & 3 deletions cores/rp2040/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ extern "C" {
void interrupts();
void noInterrupts();

// Only implemented on some RP2350 boards, not the OG Pico 2
#ifdef RP2350_PSRAM_CS
void *pmalloc(size_t size);
void *pcalloc(size_t count, size_t size);
#else
[[deprecated("This chip does not have PSRAM, pmalloc will always fail")]] void *pmalloc(size_t size);
[[deprecated("This chip does not have PSRAM, pcalloc will always fail")]] void *pcalloc(size_t count, size_t size);
#endif


// AVR compatibility macros...naughty and accesses the HW directly
#define digitalPinToPort(pin) (0)
#define digitalPinToBitMask(pin) (1UL << (pin))
Expand Down Expand Up @@ -130,8 +133,8 @@ extern const String emptyString;
// Template which will evaluate at *compile time* to a single 32b number
// with the specified bits set.
template <size_t N>
constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
return i < N ? (1L << a[i]) | __bitset(a, i + 1) : 0;
constexpr uint64_t __bitset(const int (&a)[N], size_t i = 0U) {
return i < N ? (1LL << a[i]) | __bitset(a, i + 1) : 0;
}
#endif

Expand All @@ -146,3 +149,12 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {

// PSRAM decorator
#define PSRAM __attribute__((section("\".psram\"")))

// General GPIO/ADC layout info
#ifdef PICO_RP2350B
#define __GPIOCNT 48
#define __FIRSTANALOGGPIO 40
#else
#define __GPIOCNT 30
#define __FIRSTANALOGGPIO 26
#endif
76 changes: 63 additions & 13 deletions cores/rp2040/PIOProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <Arduino.h>
#include "PIOProgram.h"
#include <map>
#include <hardware/claim.h>

#if defined(PICO_RP2350)
#define PIOS pio0, pio1, pio2
Expand All @@ -31,6 +32,8 @@
#endif

static std::map<const pio_program_t *, int> __pioMap[PIOCNT];
static bool __pioAllocated[PIOCNT];
static bool __pioHighGPIO[PIOCNT];
auto_init_mutex(_pioMutex);

PIOProgram::PIOProgram(const pio_program_t *pgm) {
Expand All @@ -47,16 +50,30 @@ PIOProgram::~PIOProgram() {
}

// Possibly load into a PIO and allocate a SM
bool PIOProgram::prepare(PIO *pio, int *sm, int *offset) {
bool PIOProgram::prepare(PIO *pio, int *sm, int *offset, int start, int cnt) {
CoreMutex m(&_pioMutex);
PIO pi[PIOCNT] = { PIOS };

#if 0
uint usm;
uint uoff;
auto ret = pio_claim_free_sm_and_add_program_for_gpio_range(_pgm, pio, &usm, &uoff, start, cnt, true);
*sm = usm;
*offset = uoff;
DEBUGV("clain %d\n", ret);
return ret;
#endif

bool needsHigh = (start + cnt) >= 32;
DEBUGV("PIOProgram %p: Searching for high=%d, pins %d-%d\n", _pgm, needsHigh ? 1 : 0, start, start + cnt - 1);

// If it's already loaded into PIO IRAM, try and allocate in that specific PIO
for (int o = 0; o < PIOCNT; o++) {
auto p = __pioMap[o].find(_pgm);
if (p != __pioMap[o].end()) {
if ((p != __pioMap[o].end()) && (__pioHighGPIO[o] == needsHigh)) {
int idx = pio_claim_unused_sm(pi[o], false);
if (idx >= 0) {
DEBUGV("PIOProgram %p: Reusing IMEM ON PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
_pio = pi[o];
_sm = idx;
*pio = pi[o];
Expand All @@ -69,19 +86,52 @@ bool PIOProgram::prepare(PIO *pio, int *sm, int *offset) {

// Not in any PIO IRAM, so try and add
for (int o = 0; o < PIOCNT; o++) {
if (pio_can_add_program(pi[o], _pgm)) {
int idx = pio_claim_unused_sm(pi[o], false);
if (idx >= 0) {
int off = pio_add_program(pi[o], _pgm);
__pioMap[o].insert({_pgm, off});
_pio = pi[o];
_sm = idx;
*pio = pi[o];
*sm = idx;
*offset = off;
return true;
if (__pioAllocated[o] && (__pioHighGPIO[o] == needsHigh)) {
DEBUGV("PIOProgram: Checking PIO %p\n", pi[o]);
if (pio_can_add_program(pi[o], _pgm)) {
int idx = pio_claim_unused_sm(pi[o], false);
if (idx >= 0) {
DEBUGV("PIOProgram %p: Adding IMEM ON PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
int off = pio_add_program(pi[o], _pgm);
__pioMap[o].insert({_pgm, off});
_pio = pi[o];
_sm = idx;
*pio = pi[o];
*sm = idx;
*offset = off;
return true;
} else {
DEBUGV("PIOProgram: can't claim unused SM\n");
}
} else {
DEBUGV("PIOProgram: can't add program\n");
}
} else {
DEBUGV("PIOProgram: Skipping PIO %p, wrong allocated/needhi\n", pi[o]);
}
}

// No existing PIOs can meet, is there an unallocated one we can allocate?
PIO p;
uint idx;
uint off;
auto rc = pio_claim_free_sm_and_add_program_for_gpio_range(_pgm, &p, &idx, &off, start, cnt, true);
if (rc) {
int o = 0;
while (p != pi[o]) {
o++;
}
assert(!__pioAllocated[o]);
__pioAllocated[o] = true;
__pioHighGPIO[o] = needsHigh;
DEBUGV("PIOProgram %p: Allocating new PIO %p(high=%d) for pins %d-%d\n", _pgm, pi[o], __pioHighGPIO[o] ? 1 : 0, start, start + cnt - 1);
__pioMap[o].insert({_pgm, off});
_pio = pi[o];
_sm = idx;
*pio = pi[o];
*sm = idx;
*offset = off;
return true;
}

// Nope, no room either for SMs or INSNs
Expand Down
2 changes: 1 addition & 1 deletion cores/rp2040/PIOProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class PIOProgram {
PIOProgram(const pio_program_t *pgm);
~PIOProgram();
// Possibly load into a PIO and allocate a SM
bool prepare(PIO *pio, int *sm, int *offset);
bool prepare(PIO *pio, int *sm, int *offset, int gpio_start = 0, int gpio_cnt = 1);

private:
const pio_program_t *_pgm;
Expand Down
6 changes: 3 additions & 3 deletions cores/rp2040/RP2040Support.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class RP2040 {
}

inline int getUsedPSRAMHeap() {
#if defined(PICO_RP2350)
#if defined(RP2350_PSRAM_CS)
extern size_t __psram_total_used();
return __psram_total_used();
#else
Expand All @@ -262,7 +262,7 @@ class RP2040 {
}

inline int getTotalPSRAMHeap() {
#if defined(PICO_RP2350)
#if defined(RP2350_PSRAM_CS)
extern size_t __psram_total_space();
return __psram_total_space();
#else
Expand Down Expand Up @@ -290,7 +290,7 @@ class RP2040 {
}

inline size_t getPSRAMSize() {
#if defined(PICO_RP2350)
#if defined(RP2350_PSRAM_CS)
extern size_t __psram_size;
return __psram_size;
#else
Expand Down
4 changes: 2 additions & 2 deletions cores/rp2040/RP2040Version.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#define ARDUINO_PICO_MAJOR 4
#define ARDUINO_PICO_MINOR 0
#define ARDUINO_PICO_REVISION 1
#define ARDUINO_PICO_VERSION_STR "4.0.1"
#define ARDUINO_PICO_REVISION 2
#define ARDUINO_PICO_VERSION_STR "4.0.2"
28 changes: 22 additions & 6 deletions cores/rp2040/SerialPIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static std::map<int, PIOProgram*> _rxMap;
// Duplicate a program and replace the first insn with a "set x, repl"
static pio_program_t *pio_make_uart_prog(int repl, const pio_program_t *pg) {
pio_program_t *p = new pio_program_t;
memcpy(p, pg, sizeof(*p));
p->length = pg->length;
p->origin = pg->origin;
uint16_t *insn = (uint16_t *)malloc(p->length * 2);
Expand Down Expand Up @@ -78,9 +79,9 @@ static int _parity(int bits, int data) {

// We need to cache generated SerialPIOs so we can add data to them from
// the shared handler
static SerialPIO *_pioSP[2][4];
static SerialPIO *_pioSP[3][4];
static void __not_in_flash_func(_fifoIRQ)() {
for (int p = 0; p < 2; p++) {
for (int p = 0; p < 3; p++) {
for (int sm = 0; sm < 4; sm++) {
SerialPIO *s = _pioSP[p][sm];
if (s) {
Expand Down Expand Up @@ -147,6 +148,21 @@ SerialPIO::~SerialPIO() {
delete[] _queue;
}

static int pio_irq_0(PIO p) {
switch (pio_get_index(p)) {
case 0:
return PIO0_IRQ_0;
case 1:
return PIO1_IRQ_0;
#if defined(PICO_RP2350)
case 2:
return PIO2_IRQ_0;
#endif
default:
return -1;
}
}

void SerialPIO::begin(unsigned long baud, uint16_t config) {
_overflow = false;
_baud = baud;
Expand Down Expand Up @@ -193,7 +209,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
_txBits = _bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1/*start bit*/;
_txPgm = _getTxProgram(_txBits);
int off;
if (!_txPgm->prepare(&_txPIO, &_txSM, &off)) {
if (!_txPgm->prepare(&_txPIO, &_txSM, &off, _tx, 1)) {
DEBUGCORE("ERROR: Unable to allocate PIO TX UART, out of PIO resources\n");
// ERROR, no free slots
return;
Expand Down Expand Up @@ -221,7 +237,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
_rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1) - 1;
_rxPgm = _getRxProgram(_rxBits);
int off;
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) {
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off, _rx, 1)) {
DEBUGCORE("ERROR: Unable to allocate PIO RX UART, out of PIO resources\n");
return;
}
Expand All @@ -246,7 +262,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
case 2: pio_set_irq0_source_enabled(_rxPIO, pis_sm2_rx_fifo_not_empty, true); break;
case 3: pio_set_irq0_source_enabled(_rxPIO, pis_sm3_rx_fifo_not_empty, true); break;
}
auto irqno = pio_get_index(_rxPIO) == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
auto irqno = pio_irq_0(_rxPIO);
irq_set_exclusive_handler(irqno, _fifoIRQ);
irq_set_enabled(irqno, true);

Expand Down Expand Up @@ -277,7 +293,7 @@ void SerialPIO::end() {
used = used || !!_pioSP[pioNum][i];
}
if (!used) {
auto irqno = pioNum == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
auto irqno = pio_irq_0(_rxPIO);
irq_set_enabled(irqno, false);
}
gpio_set_inover(_rx, 0);
Expand Down
40 changes: 32 additions & 8 deletions cores/rp2040/SerialUART.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ extern void serialEvent1() __attribute__((weak));
extern void serialEvent2() __attribute__((weak));

bool SerialUART::setRX(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({1, 13, 17, 29}) /* UART0 */,
#ifdef PICO_RP2350B
constexpr uint64_t valid[2] = { __bitset({1, 13, 17, 29, 33, 45}) /* UART0 */,
__bitset({5, 9, 21, 25, 37, 41}) /* UART1 */
};
#else
constexpr uint64_t valid[2] = { __bitset({1, 13, 17, 29}) /* UART0 */,
__bitset({5, 9, 21, 25}) /* UART1 */
};
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
#endif
if ((!_running) && ((1LL << pin) & valid[uart_get_index(_uart)])) {
_rx = pin;
return true;
}
Expand All @@ -53,10 +59,16 @@ bool SerialUART::setRX(pin_size_t pin) {
}

bool SerialUART::setTX(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({0, 12, 16, 28}) /* UART0 */,
#ifdef PICO_RP2350B
constexpr uint64_t valid[2] = { __bitset({0, 12, 16, 28, 32, 44}) /* UART0 */,
__bitset({4, 8, 20, 24, 36, 40}) /* UART1 */
};
#else
constexpr uint64_t valid[2] = { __bitset({0, 12, 16, 28}) /* UART0 */,
__bitset({4, 8, 20, 24}) /* UART1 */
};
if ((!_running) && ((1 << pin) & valid[uart_get_index(_uart)])) {
#endif
if ((!_running) && ((1LL << pin) & valid[uart_get_index(_uart)])) {
_tx = pin;
return true;
}
Expand All @@ -74,10 +86,16 @@ bool SerialUART::setTX(pin_size_t pin) {
}

bool SerialUART::setRTS(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
#ifdef PICO_RP2350B
constexpr uint64_t valid[2] = { __bitset({3, 15, 19, 31, 35, 47}) /* UART0 */,
__bitset({7, 11, 23, 27, 39, 43}) /* UART1 */
};
#else
constexpr uint64_t valid[2] = { __bitset({3, 15, 19}) /* UART0 */,
__bitset({7, 11, 23, 27}) /* UART1 */
};
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
#endif
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1LL << pin) & valid[uart_get_index(_uart)]))) {
_rts = pin;
return true;
}
Expand All @@ -95,10 +113,16 @@ bool SerialUART::setRTS(pin_size_t pin) {
}

bool SerialUART::setCTS(pin_size_t pin) {
constexpr uint32_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
#ifdef PICO_RP2350B
constexpr uint64_t valid[2] = { __bitset({2, 14, 18, 30, 34, 46}) /* UART0 */,
__bitset({6, 10, 22, 26, 38, 42}) /* UART1 */
};
#else
constexpr uint64_t valid[2] = { __bitset({2, 14, 18}) /* UART0 */,
__bitset({6, 10, 22, 26}) /* UART1 */
};
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1 << pin) & valid[uart_get_index(_uart)]))) {
#endif
if ((!_running) && ((pin == UART_PIN_NOT_DEFINED) || ((1LL << pin) & valid[uart_get_index(_uart)]))) {
_cts = pin;
return true;
}
Expand Down
6 changes: 3 additions & 3 deletions cores/rp2040/Tone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int64_t _stopTonePIO(alarm_id_t id, void *user_data) {
}

void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
if (pin > 29) {
if (pin >= __GPIOCNT) {
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
return;
}
Expand All @@ -81,7 +81,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
newTone = new Tone();
newTone->pin = pin;
pinMode(pin, OUTPUT);
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off)) {
if (!_tone2Pgm.prepare(&newTone->pio, &newTone->sm, &newTone->off, pin, 1)) {
DEBUGCORE("ERROR: tone unable to start, out of PIO resources\n");
// ERROR, no free slots
delete newTone;
Expand Down Expand Up @@ -118,7 +118,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
void noTone(uint8_t pin) {
CoreMutex m(&_toneMutex);

if ((pin > 29) || !m) {
if ((pin > __GPIOCNT) || !m) {
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
return;
}
Expand Down
Loading

0 comments on commit 317d74d

Please sign in to comment.