Compare commits

...
13 Commits
Author SHA1 Message Date
Earle F. Philhower, III f1e77995f5 Look for UF2 drives in additional spots on Linux (#37)
Fixes #28
2021-05-06 20:04:36 -07:00
Earle F. Philhower, III 70a30dc219 Add multicore safety, FIFO, update pico-sdk (#122)
Update pico-sdk to 1.1.2

Add methods to block the opposite core while doing flash updates.
Ensure opposite core is stopped in LittleFS and EEPROM while doing
flash updates.

Update documentation with new calls.
2021-05-06 19:57:21 -07:00
Earle F. Philhower, III 6cf0b30fdf Merge branch 'master' of https://github.com/earlephilhower/arduino-pico 2021-05-06 08:28:35 -07:00
Earle F. Philhower, III a62075d8f1 Add HWSerial redirect
Fixes #120
2021-05-06 08:28:08 -07:00
Oğuzhan Başer 47915df2da PWM functions definitions missing (#114)
* add keywords file

* Add PWM function definitions
2021-04-27 07:11:02 -07:00
Earle F. Philhower, III 1815c45f92 Add multicore support with setup1/loop1 (#113)
Support running code on the second core by adding a setup1() and/or
a loop1() routine to a sketch.  These functions operate exactly like
the normal Arduino ones, and anything they call will be run on
the second core automatically.

Add a simple multicore example.
2021-04-24 11:40:29 -07:00
Earle F. Philhower, III 2d58f08bf2 Update README.md 2021-04-22 10:39:29 -07:00
Earle F. Philhower, III 6e51516d6c Set default pins for peripherals per datasheet (#103)
Using the official Raspberry Pi Pico datasheet and the Adafruit Feather
RP2040 schematic, set the default pins for peripherals to match.

Fixes #92
2021-04-16 10:23:43 -07:00
Earle F. Philhower, III 011ecdb5a6 More multicore safety plumbing, IRQs, analogXXX (#107)
Keep a per-core IRQ stack for noInterrupts since each core has its own
enable/disable.

Make analogRead/analogWrite multicore safe
2021-04-15 17:16:13 -07:00
Earle F. Philhower, III b793ad5533 Make Tone multicore safe (#106)
Add a mutex around the Tone mapping for multicore safety.
2021-04-15 16:21:47 -07:00
Earle F. Philhower, III b5aeb84cb3 Add NOT_AN_INTERRUPT define (#105)
Fix #104
2021-04-15 12:50:35 -07:00
Earle F. Philhower, III d490499c86 Add note about Win7 driver installation (#102)
Fixes #96
2021-04-13 18:11:48 -07:00
Earle F. Philhower, III 9e0e266b4f Add hardware_dma include path (#101)
Fix #100
2021-04-13 15:44:27 -07:00
33 changed files with 535 additions and 116 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ cd ~/Arduino/hardware/pico/rp2040
git submodule update --init
cd pico-sdk
git submodule update --init
cd pico-extras
cd ../pico-extras
git submodule update --init
cd ../tools
python3 ./get.py
+4
View File
@@ -50,6 +50,7 @@ void detachInterrupt(pin_size_t pin);
#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)
@@ -67,6 +68,9 @@ 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);
+1
View File
@@ -33,6 +33,7 @@ public:
_acquired = false;
if (!mutex_try_enter(_mutex, &owner)) {
if (owner == get_core_num()) { // Deadlock!
DEBUGCORE("CoreMutex - Deadlock detected!\n");
return;
}
mutex_enter_blocking(_mutex);
+1
View File
@@ -0,0 +1 @@
#include "api/HardwareSerial.h"
+97 -1
View File
@@ -18,8 +18,96 @@
* 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>
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:
@@ -33,8 +121,16 @@ public:
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
+2 -2
View File
@@ -179,8 +179,8 @@ 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()) {
+1 -4
View File
@@ -18,8 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SERIALUART_H__
#define __SERIALUART_H__
#pragma once
#include <Arduino.h>
#include "api/HardwareSerial.h"
@@ -67,5 +66,3 @@ namespace arduino {
extern void serialEvent1Run(void) __attribute__((weak));
extern void serialEvent2Run(void) __attribute__((weak));
};
#endif
+13 -2
View File
@@ -19,6 +19,7 @@
*/
#include <Arduino.h>
#include "CoreMutex.h"
#include <hardware/gpio.h>
#include <pico/time.h>
#include <map>
@@ -29,9 +30,12 @@ typedef struct {
int sm;
} Tone;
// 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) {
@@ -43,6 +47,11 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
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;
@@ -76,7 +85,9 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
}
void noTone(uint8_t pin) {
if ((pin < 0) || (pin > 29)) {
CoreMutex m(&_toneMutex);
if ((pin < 0) || (pin > 29) || !m) {
DEBUGCORE("ERROR: Illegal pin in tone (%d)\n", pin);
return;
}
+30 -1
View File
@@ -20,6 +20,11 @@
#include <Arduino.h>
#include <pico/stdlib.h>
#include <pico/multicore.h>
RP2040 rp2040;
volatile bool _MFIFO::_otherIdled = false;
extern void setup();
extern void loop();
@@ -29,6 +34,22 @@ extern void loop();
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() {
#if F_CPU != 125000000
set_sys_clock_khz(F_CPU / 1000, true);
@@ -45,8 +66,16 @@ extern "C" int main() {
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();
if (arduino::serialEventRun) {
arduino::serialEventRun();
+16 -2
View File
@@ -19,6 +19,7 @@
*/
#include <Arduino.h>
#include <CoreMutex.h>
#include <hardware/gpio.h>
#include <hardware/pwm.h>
#include <hardware/clocks.h>
@@ -31,6 +32,8 @@ 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;
@@ -68,7 +71,9 @@ extern "C" void analogWriteResolution(int res) {
}
extern "C" void analogWrite(pin_size_t pin, int val) {
if ((pin < 0) || (pin > 29)) {
CoreMutex m(&_dacMutex);
if ((pin < 0) || (pin > 29) || !m) {
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
return;
}
@@ -92,8 +97,12 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
pwm_set_gpio_level(pin, val);
}
auto_init_mutex(_adcMutex);
extern "C" int analogRead(pin_size_t pin) {
if ((pin < A0) || (pin > A3)) {
CoreMutex m(&_adcMutex);
if ((pin < A0) || (pin > A3) || !m) {
DEBUGCORE("ERROR: Illegal analogRead pin (%d)\n", pin);
return 0;
}
@@ -106,6 +115,11 @@ extern "C" int analogRead(pin_size_t pin) {
}
extern "C" float analogReadTemp() {
CoreMutex m(&_adcMutex);
if (!m) {
return 0.0f; // Deadlock
}
if (!adcInitted) {
adc_init();
}
+31 -9
View File
@@ -19,42 +19,59 @@
*/
#include <Arduino.h>
#include <CoreMutex.h>
#include <hardware/gpio.h>
#include <hardware/sync.h>
#include <stack>
#include <map>
// Support nested IRQ disable/re-enable
static std::stack<uint32_t> _irqStack;
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) {
auto irq = _map.find(gpio);
if (irq != _map.end()) {
// Ignore events, only one event per pin supported by Arduino
irq->second(); // Do the callback
// 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;
@@ -72,6 +89,11 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
}
extern "C" void detachInterrupt(pin_size_t pin) {
CoreMutex m(&_irqMutex);
if (!m) {
return;
}
noInterrupts();
auto irq = _map.find(pin);
if (irq != _map.end()) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

+2
View File
@@ -34,6 +34,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
Ported/Optimized Libraries <libraries>
Multicore Processing <multicore>
Using Pico-SDK <sdk>
Licenses <license>
+13
View File
@@ -67,6 +67,19 @@ 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
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
+77
View File
@@ -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 accesses.
**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 softwarae-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.
+18
View File
@@ -0,0 +1,18 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
analogWriteFreq KEYWORD2
analogWriteRange KEYWORD2
analogWriteResolution KEYWORD2
######################################
# Constants (LITERAL1)
#######################################
BIN
View File
Binary file not shown.
+4 -3
View File
@@ -105,11 +105,12 @@ bool EEPROMClass::commit() {
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;
}
+8 -4
View File
@@ -173,10 +173,12 @@ int LittleFSImpl::lfs_flash_prog(const struct lfs_config *c,
lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) {
LittleFSImpl *me = reinterpret_cast<LittleFSImpl*>(c->context);
uint8_t *addr = me->_start + (block * me->_blockSize) + off;
uint32_t save = save_and_disable_interrupts();
noInterrupts();
rp2040.idleOtherCore();
// Serial.printf("WRITE: %p, $d\n", (intptr_t)addr - (intptr_t)XIP_BASE, size);
flash_range_program((intptr_t)addr - (intptr_t)XIP_BASE, (const uint8_t *)buffer, size);
restore_interrupts(save);
rp2040.resumeOtherCore();
interrupts();
return 0;
}
@@ -184,9 +186,11 @@ int LittleFSImpl::lfs_flash_erase(const struct lfs_config *c, lfs_block_t block)
LittleFSImpl *me = reinterpret_cast<LittleFSImpl*>(c->context);
uint8_t *addr = me->_start + (block * me->_blockSize);
// Serial.printf("ERASE: %p, %d\n", (intptr_t)addr - (intptr_t)XIP_BASE, me->_blockSize);
uint32_t save = save_and_disable_interrupts();
noInterrupts();
rp2040.idleOtherCore();
flash_range_erase((intptr_t)addr - (intptr_t)XIP_BASE, me->_blockSize);
restore_interrupts(save);
rp2040.resumeOtherCore();
interrupts();
return 0;
}
+2 -2
View File
@@ -232,5 +232,5 @@ void SPIClassRP2040::setClockDivider(uint8_t uc_div) {
(void) uc_div; // no-op
}
SPIClassRP2040 SPI(spi0, 0, 1, 2, 3);
SPIClassRP2040 SPI1(spi1, 8, 9, 10, 11);
SPIClassRP2040 SPI(spi0, PIN_SPI0_MISO, PIN_SPI0_SS, PIN_SPI0_SCK, PIN_SPI0_MOSI);
SPIClassRP2040 SPI1(spi1, PIN_SPI1_MISO, PIN_SPI1_SS, PIN_SPI1_SCK, PIN_SPI1_MOSI);
+1 -5
View File
@@ -18,8 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SPI_H_INCLUDED
#define _SPI_H_INCLUDED
#pragma once
#include <Arduino.h>
#include <api/HardwareSPI.h>
@@ -79,6 +78,3 @@ private:
extern SPIClassRP2040 SPI;
extern SPIClassRP2040 SPI1;
#endif
+2 -2
View File
@@ -335,5 +335,5 @@ void TwoWire::onRequest(void(*function)(void))
_onRequestCallback = function;
}
TwoWire Wire(i2c0, 0, 1);
TwoWire Wire1(i2c1, 2, 3);
TwoWire Wire(i2c0, PIN_WIRE0_SDA, PIN_WIRE0_SCL);
TwoWire Wire1(i2c1, PIN_WIRE1_SDA, PIN_WIRE1_SCL);
+1 -5
View File
@@ -21,8 +21,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef TwoWire_h
#define TwoWire_h
#pragma once
#include <Arduino.h>
#include "api/HardwareI2C.h"
@@ -105,6 +104,3 @@ private:
extern TwoWire Wire;
extern TwoWire Wire1;
#endif
@@ -11,7 +11,11 @@
void setup() {
Serial.begin(115200);
delay(5000);
Wire.setSDA(0);
Wire.setSCL(1);
Wire.begin();
Wire1.setSDA(2);
Wire1.setSCL(3);
Wire1.begin(0x30);
Wire1.onReceive(recv);
Wire1.onRequest(req);
@@ -0,0 +1,40 @@
// 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
// The normal, core0 setup
void setup() {
Serial.begin();
delay(5000);
}
void loop() {
Serial.printf("C0: Blue leader standing by...\n");
delay(1000);
}
// Running on core1
void setup1() {
delay(5000);
Serial.printf("C1: Red leader standing by...\n");
}
void loop1() {
Serial.printf("C1: Stay on target...\n");
delay(500);
}
+2 -2
View File
@@ -13,7 +13,7 @@
#define PICO_SDK_VERSION_MAJOR 1
#define PICO_SDK_VERSION_MINOR 1
#define PICO_SDK_VERSION_REVISION 0
#define PICO_SDK_VERSION_STRING "1.1.0"
#define PICO_SDK_VERSION_REVISION 2
#define PICO_SDK_VERSION_STRING "1.1.2"
#endif
+1 -1
View File
@@ -39,7 +39,7 @@ compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
compiler.defines={build.led}
compiler.includes="-I{runtime.platform.path}/pico_base/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_unique_id/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_stdlib/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_gpio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_i2c/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_flash/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include" "-I{runtime.platform.path}/pico-examples/build/generated/pico_base" "-I{runtime.platform.path}/pico-sdk/src/boards/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_base/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_structs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_claim/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_sync/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_divider/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_time/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_sync/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_util/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_runtime/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_clocks/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_resets/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_watchdog/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_xosc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pll/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_vreg/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_irq/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_printf/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_bootrom/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_bit_ops/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_divider/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_double/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_int64_ops/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_float/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/lib/tinyusb/src/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_usb/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_spi/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pwm/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_adc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/cores/rp2040/api/deprecated-avr-comp/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/pico-extras/src/rp2_common/pico_audio_i2s/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_audio/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_util_buffer/include"
compiler.includes="-I{runtime.platform.path}/pico_base/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_unique_id/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_stdlib/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_gpio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_i2c/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_flash/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_base/include" "-I{runtime.platform.path}/pico-examples/build/generated/pico_base" "-I{runtime.platform.path}/pico-sdk/src/boards/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_platform/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_base/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_structs/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_claim/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_sync/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_divider/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_time/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_timer/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_sync/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_util/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_runtime/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_clocks/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_resets/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_watchdog/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_xosc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pll/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_vreg/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_irq/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_printf/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_bootrom/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_bit_ops/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_divider/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_double/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_int64_ops/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_float/include" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_dma/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_uart/include" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/lib/tinyusb/src/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_stdio_usb/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_spi/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_pwm/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/hardware_adc/include" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/cores/rp2040/api/deprecated-avr-comp/" "-I{runtime.platform.path}/pico-sdk/src/rp2_common/pico_multicore/include" "-I{runtime.platform.path}/pico-extras/src/rp2_common/pico_audio_i2s/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_audio/include" "-I{runtime.platform.path}/pico-extras/src/common/pico_util_buffer/include"
compiler.flags=-Os -march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections
compiler.wrap=-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
+4
View File
@@ -236,6 +236,10 @@ def get_drives():
drives.append(words[0])
else:
rootpath = "/media"
if not os.path.isdir(rootpath):
rootpath = "/run/media"
if not os.path.isdir(rootpath):
rootpath = "/opt/media"
if sys.platform == "darwin":
rootpath = "/Volumes"
elif sys.platform == "linux":
+38 -5
View File
@@ -1,8 +1,41 @@
#ifndef __rpipico_pins_arduino_h__
#define __rpipico_pins_arduino_h__
#pragma once
#define LED_BUILTIN 13
// Pin definitions taken from:
// https://learn.adafruit.com/assets/100337
// LEDs
#define PIN_LED (13u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
// Not pinned out
#define PIN_SERIAL2_TX (31u)
#define PIN_SERIAL2_RX (31u)
// SPI
#define PIN_SPI0_MISO (20u)
#define PIN_SPI0_MOSI (19u)
#define PIN_SPI0_SCK (18u)
#define PIN_SPI0_SS (17u)
// 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 (2u)
#define PIN_WIRE0_SCL (3u)
// 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"
#endif
+45 -58
View File
@@ -1,63 +1,50 @@
#ifndef __generic_common_h__
#define __generic_common_h__
#pragma once
#include <Arduino.h>
#define PINS_COUNT (30u)
#define NUM_DIGITAL_PINS (30u)
#define NUM_ANALOG_INPUTS (4u)
#define NUM_ANALOG_OUTPUTS (0u)
#define ADC_RESOLUTION (12u)
static const pin_size_t D0 = 0;
static const pin_size_t D1 = 1;
static const pin_size_t D2 = 2;
static const pin_size_t D3 = 3;
static const pin_size_t D4 = 4;
static const pin_size_t D5 = 5;
static const pin_size_t D6 = 6;
static const pin_size_t D7 = 7;
static const pin_size_t D8 = 8;
static const pin_size_t D9 = 9;
static const pin_size_t D10 = 10;
static const pin_size_t D11 = 11;
static const pin_size_t D12 = 12;
static const pin_size_t D13 = 13;
static const pin_size_t D14 = 14;
static const pin_size_t D15 = 15;
static const pin_size_t D16 = 16;
static const pin_size_t D17 = 17;
static const pin_size_t D18 = 18;
static const pin_size_t D19 = 19;
static const pin_size_t D20 = 20;
static const pin_size_t D21 = 21;
static const pin_size_t D22 = 22;
static const pin_size_t D23 = 23;
static const pin_size_t D24 = 24;
static const pin_size_t D25 = 25;
static const pin_size_t D26 = 26;
static const pin_size_t D27 = 27;
static const pin_size_t D28 = 28;
static const pin_size_t D29 = 29;
#define LED_BUILTIN PIN_LED
static const pin_size_t A0 = 26;
static const pin_size_t A1 = 27;
static const pin_size_t A2 = 28;
static const pin_size_t A3 = 29;
static const uint8_t D0 = (0u);
static const uint8_t D1 = (1u);
static const uint8_t D2 = (2u);
static const uint8_t D3 = (3u);
static const uint8_t D4 = (4u);
static const uint8_t D5 = (5u);
static const uint8_t D6 = (6u);
static const uint8_t D7 = (7u);
static const uint8_t D8 = (8u);
static const uint8_t D9 = (9u);
static const uint8_t D10 = (10u);
static const uint8_t D11 = (11u);
static const uint8_t D12 = (12u);
static const uint8_t D13 = (13u);
static const uint8_t D14 = (14u);
static const uint8_t D15 = (15u);
static const uint8_t D16 = (16u);
static const uint8_t D17 = (17u);
static const uint8_t D18 = (18u);
static const uint8_t D19 = (19u);
static const uint8_t D20 = (20u);
static const uint8_t D21 = (21u);
static const uint8_t D22 = (22u);
static const uint8_t D23 = (23u);
static const uint8_t D24 = (24u);
static const uint8_t D25 = (25u);
static const uint8_t D26 = (26u);
static const uint8_t D27 = (27u);
static const uint8_t D28 = (28u);
static const uint8_t D29 = (29u);
static const uint8_t A0 = (26u);
static const uint8_t A1 = (27u);
static const uint8_t A2 = (28u);
static const uint8_t A3 = (29u);
#ifndef PIN_SPI_SS
#define PIN_SPI_SS (1)
#endif
#ifndef PIN_SPI_MOSI
#define PIN_SPI_MOSI (3)
#endif
#ifndef PIN_SPI_MISO
#define PIN_SPI_MISO (0)
#endif
#ifndef PIN_SPI_SCK
#define PIN_SPI_SCK (2)
#endif
static const pin_size_t SS = PIN_SPI_SS;
static const pin_size_t MOSI = PIN_SPI_MOSI;
static const pin_size_t MISO = PIN_SPI_MISO;
static const pin_size_t SCK = PIN_SPI_SCK;
#endif
static const uint8_t SS = PIN_SPI1_SS;
static const uint8_t MOSI = PIN_SPI1_MOSI;
static const uint8_t MISO = PIN_SPI1_MISO;
static const uint8_t SCK = PIN_SPI1_SCK;
+39 -1
View File
@@ -1 +1,39 @@
#include "common.h"
#pragma once
// Pin definitions taken from:
// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf
// LEDs
#define PIN_LED (25u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
#define PIN_SERIAL2_TX (8u)
#define PIN_SERIAL2_RX (9u)
// SPI
#define PIN_SPI0_MISO (16u)
#define PIN_SPI0_MOSI (19u)
#define PIN_SPI0_SCK (18u)
#define PIN_SPI0_SS (17u)
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (15u)
#define PIN_SPI1_SCK (14u)
#define PIN_SPI1_SS (13u)
// Wire
#define PIN_WIRE0_SDA (4u)
#define PIN_WIRE0_SCL (5u)
#define PIN_WIRE1_SDA (26u)
#define PIN_WIRE1_SCL (27u)
#define SERIAL_HOWMANY (3u)
#define SPI_HOWMANY (2u)
#define WIRE_HOWMANY (2u)
#include "../generic/common.h"
+36 -5
View File
@@ -1,8 +1,39 @@
#ifndef __rpipico_pins_arduino_h__
#define __rpipico_pins_arduino_h__
#pragma once
#define LED_BUILTIN 25
// Pin definitions taken from:
// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf
// LEDs
#define PIN_LED (25u)
// Serial
#define PIN_SERIAL1_TX (0u)
#define PIN_SERIAL1_RX (1u)
#define PIN_SERIAL2_TX (8u)
#define PIN_SERIAL2_RX (9u)
// SPI
#define PIN_SPI0_MISO (16u)
#define PIN_SPI0_MOSI (19u)
#define PIN_SPI0_SCK (18u)
#define PIN_SPI0_SS (17u)
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (15u)
#define PIN_SPI1_SCK (14u)
#define PIN_SPI1_SS (13u)
// Wire
#define PIN_WIRE0_SDA (4u)
#define PIN_WIRE0_SCL (5u)
#define PIN_WIRE1_SDA (26u)
#define PIN_WIRE1_SCL (27u)
#define SERIAL_HOWMANY (3u)
#define SPI_HOWMANY (2u)
#define WIRE_HOWMANY (2u)
#include "../generic/common.h"
#endif