Raspberry Pi Pico Arduino core, for all RP2040 boards

Arduino-Pico Join the chat at https://gitter.im/arduino-pico/community

Raspberry Pi Pico Arduino core, for all RP2040 boards

This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosystem.

It uses a custom toolset with GCC 10.2 and Newlib 4.0.0, not depending on system-installed prerequisites. https://github.com/earlephilhower/pico-quick-toolchain

There is automated discovery of boards in bootloader mode, so they show up in the IDE, and the upload command works using the Microsoft UF2 tool (included).

Installing via Arduino Boards Manager

Windows Users: Please do not use the Windows Store version of the actual Arduino application because it has issues detecting attached Pico boards. Use the "Windows ZIP" or plain "Windows" executable (EXE) download direct from https://arduino.cc. and allow it to install any device drivers it suggests. Otherwise the Pico board may not be detected. Also, if trying out the 2.0 beta Arduino please install the release 1.8 version beforehand to ensure needed device drivers are present. (See #20 for more details.)

Open up the Arduino IDE and go to File->Preferences.

In the dialog that pops up, enter the following URL in the "Additional Boards Manager URLs" field:

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

image

Hit OK to close the dialog.

Go to Tools->Boards->Board Manager in the IDE

Type "pico" in the search box and select "Add":

image

Installing via GIT

To install via GIT (for latest and greatest versions):

mkdir -p ~/Arduino/hardware/pico
git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/rp2040
cd ~/Arduino/hardware/pico/rp2040
git submodule init
git submodule update
cd pico-sdk
git submodule init
git submodule update
cd ../tools
python3 ./get.py

Installing both Arduino and CMake

Tom's Hardware presented a very nice writeup on installing arduino-pico on both Windows and Linux, available at https://www.tomshardware.com/how-to/program-raspberry-pi-pico-with-arduino-ide

If you follow Les' step-by-step you will also have a fully functional CMake-based environment to build Pico apps on if you outgrow the Arduino ecosystem.

Uploading Sketches

To upload your first sketch, you will need to hold the BOOTSEL button down while plugging in the Pico to your computer. Then hit the upload button and the sketch should be transferred and start to run.

After the first upload, this should not be necessary as the arduino-pico core has auto-reset support. Select the appropriate serial port shown in the Arduino Tools->Port->Serial Port menu once (this setting will stick and does not need to be touched for multiple uploads). This selection allows the auto-reset tool to identify the proper device to reset. Them hit the upload button and your sketch should upload and run.

In some cases the Pico will encounter a hard hang and its USB port will not respond to the auto-reset request. Should this happen, just follow the initial procedure of holding the BOOTSEL button down while plugging in the Pico to enter the ROM bootloader.

Uploading with Picoprobe

If you have built a Raspberry Pi Picoprobe, you can use OpenOCD to handle your sketch uploads and for debugging with GDB.

Under Windows a local admin user should be able to access the Picoprobe port automatically, but under Linux udev must be told about the device and to allow normal users access.

To set up user-level access to Picoprobes on Ubuntu (and other OSes which use udev):

echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", GROUP="users", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
sudo udevadm control --reload

The first line creates a file with the USB vendor and ID of the Picoprobe and tells UDEV to give users full access to it. The second causes udev to load this new rule. Note that you will need to unplug and re-plug in your device the first time you create this file, to allow udev to make the device node properly.

Once Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.

Debugging with Picoprobe, OpenOCD, and GDB

The installed tools include a version of OpenOCD (in the pqt-openocd directory) and GDB (in the pqt-gcc directory). These may be used to run GDB in an interactive window as documented in the Pico Getting Started manuals from the Raspberry Pi Foundation.

Status of Port

Relatively stable and very functional, but bug reports and PRs always accepted.

  • digitalWrite/Read
  • shiftIn/Out
  • SPI master (tested using SdFat 2.0 https://github.com/greiman/SdFat ... note that the Pico voltage regulator can't reliably supply enough power for a SD Card so use external power, and adjust the USE_SIMPLE_LITTLE_ENDIAN define in src/sdfat.h to 0)
  • analogWrite/PWM
  • tone/noTone
  • Wire/I2C Master and Slave (tested using DS3231 https://github.com/rodan/ds3231)
  • EEPROM
  • USB Serial(ACM) w/automatic reboot-to-UF2 upload)
  • Hardware UART
  • Servo
  • Overclocking and underclocking from the menus
  • printf (i.e. debug) output over USB serial

The RP2040 PIO state machines (SMs) are used to generate jitter-free:

  • Servos
  • Tones

Todo

Some major features I want to add are:

  • Installable filesystem support (SD, LittleFS, etc.)
  • Updated debug infrastructure
  • I2S port from pico-extras

Tutorials from Across the Web

Here are some links to coverage and additional tutorials for using arduino-pico

Contributing

If you want to contribute or have bugfixes, drop me a note at [email protected] or open an issue/PR here.

-Earle F. Philhower, III [email protected]

Owner
Comments
  • Adafruit_ILI9341 does not compile

    Adafruit_ILI9341 does not compile

    Hi,

    I use Adafruit_ILI9341 to drive a 9341 LCD display in my Data General Nova simulator.

    https://github.com/marcelvanherk/nova1200-restoration (folder teensy_nova)

    I have successfully compiled this for the pico with your platform (with a few changes) but:

    #include "Adafruit_ILI9341.h"

    (latest version as well as dependencies) reports:

    C:\Users\marcel\Documents\Arduino\libraries\Adafruit_ILI9341\Adafruit_ILI9341.cpp:53:10: fatal error: wiring_private.h: No such file or directory 53 | #include "wiring_private.h" | ^~~~~~~~~~~~~~~~~~ compilation terminated.

    could this be made to work on the pico?

    Marcel

  • Multicore crash with printf(%f)

    Multicore crash with printf(%f)

    Hi,

    i just switched over from the mbed Arduino core for the RP2040 because I'm pretty disappointed with how the code is written and maintained. Multicore is practically impossible to do there.

    I ran into a very weird behaviour with Printing to SerialUSB from both cores. I use propper Mutex and the weird thing is: it works when I use const char* or format but not when I call it with a const String&. then it just freezes after the first print

    here the code that easily reproduced the problem:

    
    #include "Arduino.h"
    
    
    mutex_t MUTEX_PRINT;
    
    //#define LOGFUNC Log // DOES WORK
    //#define LOGFUNC Log2 // DOES WORK
    #define LOGFUNC Log3 // DOES NOT WORK
    //#define LOGFUNC Log4 // DOES NOT WORK
    
    
    
    #include <stdarg.h>
    extern void Log(const char* format, ...) __attribute__((format(printf, 1, 2)));
    void Log(const char* format, ...)
    {
    	mutex_enter_blocking(&MUTEX_PRINT);
    
    	char loc_buf[64];
    	char* temp = loc_buf;
    	va_list arg;
    	va_list copy;
    	va_start(arg, format);
    	va_copy(copy, arg);
    	int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
    	va_end(copy);
    	if (len < 0) {
    		va_end(arg);
    		return;
    	};
    	if (len >= sizeof(loc_buf)) {
    		temp = (char*)malloc(len + 1);
    		if (temp == NULL) {
    			va_end(arg);
    			return;
    		}
    		len = vsnprintf(temp, len + 1, format, arg);
    	}
    	va_end(arg);
    
    	
    	Serial.print("[");
    	Serial.print(millis());
    	Serial.print("] ");
    	Serial.println(temp);
    
    	
    
    	if (temp != loc_buf) {
    		free(temp);
    	}
    
    	mutex_exit(&MUTEX_PRINT);
    }
    
    void Log2(const char* msg)
    {
    	mutex_enter_blocking(&MUTEX_PRINT);
    	
    	Serial.print("[");
    	Serial.print(millis());
    	Serial.print("] ");
    	Serial.println(msg);
    	
    	mutex_exit(&MUTEX_PRINT);
    }
    
    
    void Log3(const String& msg)
    {
    	mutex_enter_blocking(&MUTEX_PRINT);
    	
    	Serial.print("[");
    	Serial.print(millis());
    	Serial.print("] ");
    	Serial.println(msg);
    	
    	mutex_exit(&MUTEX_PRINT);
    }
    
    
    void Log4(const String& msg)
    {
    	Log2(msg.c_str());
    }
    
    
    
    
    /*****************************************************/
    
    
    static bool start_done = false;
    
    void jtask0()
    {
    	mutex_init(&MUTEX_PRINT);
    	start_done = true;
    	
    	uint32_t loopcount = 0;
    	while(true)
    	{
    		loopcount++;
    
    		LOGFUNC("main0: loop");
    
    		delay(100);
    	}
    }
    
    void jtask1() 
    {
    	while(!start_done);
    
    	uint32_t loopcount = 0;
    	while(true)
    	{
    		loopcount++;
    		
    		LOGFUNC("main1: loop");
    
    		delay(100);
    	}
    }
    
    
    void setup() {
    	Serial.begin(115200);
    
    	while (!Serial.available()) 
    	{
    		Serial.print(".");
    		delay(1000);
    	}
    	while(Serial.available())
    		Serial.read();
    }
    
    void setup1() {
    	
    }
    
    void loop() {
    	jtask0();
    }
    
    void loop1() {
    	jtask1();
    }
    
    
    

    Could somebody try this? you can just switch between the Print Functions with the defines at the top.

    I'm trying to figure this out for half a day now and I can't I think I'm going crazy x]

    Thx

    Here the output of the working Prints:

    
    ..[9034] main0: loop
    [9034] main1: loop
    [9134] main0: loop
    [9134] main1: loop
    [9234] main0: loop
    [9234] main1: loop
    [9334] main0: loop
    [9334] main1: loop
    [9435] main0: loop
    [9435] main1: loop
    [9535] main0: loop
    [9535] main1: loop
    [9635] main0: loop
    [9635] main1: loop
    [9735] main0: loop
    [9735] main1: loop
    [9835] main0: loop
    [9835] main1: loop
    [9935] main0: loop
    [9935] main1: loop
    [10035] main0: loop
    [10035] main1: loop
    [10135] main0: loop
    [10135] main1: loop
    [10235] main0: loop
    
    

    and the not working

    
    ..[7003] main1: loop
    [7003] main1: loop
    [7103] main0: loop
    
    >>> DEADLOCK HERE <<< 
    
    

    Im using PlatformIO with this config

    
    [env:PICO_ALT_CORE]
    platform = https://github.com/maxgerhardt/platform-raspberrypi.git
    board = pico
    framework = arduino
    board_build.core = earlephilhower
    board_build.filesystem_size = 0.5m
    ; note that download link for toolchain is specific for OS. see https://github.com/earlephilhower/pico-quick-toolchain/releases.
    platform_packages =
        maxgerhardt/[email protected]://github.com/earlephilhower/arduino-pico.git
        maxgerhardt/[email protected]://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.1-a/x86_64-w64-mingw32.arm-none-eabi-7855b0c.210706.zip
    
    
  • Intermittent i2c errors, byte count incorrect and missing bytes in onReceive interrupt handler

    Intermittent i2c errors, byte count incorrect and missing bytes in onReceive interrupt handler

    I am posting this issue here first as I am using Arduino-Pico, but this could well be an issue in the underlying Pico SDK or even a hardware issue. I am going to do further testing but I will describe what I have tried so far below.

    This is a bit long winded, mainly because writing it out is a good way for me to make sure I have covered everything I can think of and has helped me reach the conclusion that there must actually be an issue here somewhere.

    Ok, so I have noticed some strange behaviour when sending data from one Pico to another using the i2c interface. I am sending 2 arrays of data from one pico to the other, the first array is 84 bytes long and the second is 48 bytes long, I understand that the wire library implementation for the Pico uses a 128 byte transmit buffer so this is within the buffer size.

    The format of the data I am sending isn't really relevant, but it helped me spot the issue. The data I am sending is 2 arrays of 32bit float values, the first array is 21 floats which equals 84 bytes and the second array is 12 floats which equals 48 bytes. For each float array I send each group of 4 bytes sequentially using the write function until all the values have been placed in the buffer before calling endTransmission to send the data. The sequence I use for each array is like this: beginTransmission(slave_address); write(byte1); write(byte2); write(byte3); write(byte4); write(byte1); …. Rest-of-bytes … endTransmission(); So basically I am sending 2 separate i2c bus transmissions, the first one being 84 bytes followed immediately by another of 48 bytes.

    On the receiving pico i check the expected size of the data as reported in the onReceive interrupt then depending on the size i then copy the bytes into one of 2 correctly sized byte arrays for later processing in the main loop.

    In the main loop I convert the bytes from each array back into 2 arrays of floats so that I have the original float arrays, the first one being 21 floats = 84 bytes. And the second one being 12 floats = 48 bytes. I am using i2c1 (Wire1) on both Pico’s as this makes the pins better suit my requirements and layout.

    When testing I started to notice that the second array on the receiving side was not being populated sometimes, digging further I found that this was because the onReceive interrupt sometimes only reported 47 bytes for the second transmission rather than 48 bytes, resulting in the transmission being ignored by the routine inside the onReceive interrupt . To see what was missing I modified the code so it filled the second array even if the received bytes was less then the expected value of 48. What I found was that on the occasions when only 47 bytes was reported, all of the floats were corrupted, being way off value, close to their max values. This indicates that the missing data was at the start of the i2c transmission which messed up the expected boundaries of the 4 byte groups which make up every float value.

    So far I had mainly been using serial print debugging for this issue so used some more spare pins as debug signal outputs and connected up the scope to find out what was ging on. On the receiving side I setup one of the new debug pins to output a low pulse when the bytes received was less than expected for the second i2c transmission.

    ScreenImg-31 The purple trace is the i2c clock, Blue SDA, yellow low pulse is the error marker from the debug pin, green is the data processing and error detection code running.

    The pair of transmissions are here, rather than sending the second immediately after the first, in this trace they are separated by a 1mS gap which is one of the things I tried changing later. ScreenImg-30

    By trigging off the debug pin I was able to determine from measuring the clock pulses for the address and data transfers that the correct number of bytes was being sent on the wire despite what was being reported in the onReceive interrupt. I also had some serial debugging on the sending Pic to report any errors from the endTransmission call, for which none were ever reported.

    The error rate was high, around 50% of the second transmissions reported 47 bytes rather than 48. I was using an i2c clock of 1MHz (fast mode plus) as stated in the documentation as the fastest supported speed. I had also changed the pull up resistors from 4.7k to 1k to help shape the pulses, this also increased the actual clock speed as I was only getting around 700KHz (presumably due to clock stretching), with 1k pull-ups I am getting 868KHz. The 1k pull-ups made no difference to the error rate, but the rising edge slope was now better.

    ScreenImg-29

    I was sending the pair of transmissions at a frequency of 50Hz, so at 20 mS intervals, this left plenty space between each pair of i2c transmissions and I could confirm via use of debug output pulses that everything had finished its work well before the next onReceive interrupt. Some of the processing work was being done in core1 using loop1() so I eliminated this and ran everything in core0, commenting out loop1(), this made no difference.

    On the scope I noticed that there was quite a delay between the end of the clock pulse block and the start of the onReceive interrupt (around 220uS). This meant that the next i2c transmission was arriving before the interrupt had fired. This resulted in a short break in the SCL pulses during the interrupt handling, I thought maybe this was the issue, but why was it only intermittent?

    To rule this out, on the transmitting side, I added a 500uS delay between the first and second transmissions to see what difference it would make, this made the error rate drop to around 10%. I was able to confirm on the scope that all processing related to the first transmission was complete before the second transmission started, but the missing data was still occurring. I then increased this to 600uS just for the heck of it to create a larger gap and found the error rate dropped further to around 5%.

    Having previously had issues with random interrupt firing delays on pins when using the USB-UART serial comms on a Pico, due to that also using interrupts, I wondered if the USB-UART serial communications on the receiving side was having an effect as there was some serial debugging output being done in between the first and second transmission blocks. Previously this would have overlapped with the reception of the second transmission until I added the 500uS delay on the transmitter. I moved this serial debug output code completely outside of the pair of transmission receptions so that it occurred in the dead 20ms space between each pair of transmissions, this further reduced the error rate to around 3%

    Stage 2:

    So far I have been able to confirm that the transmitting side was working correctly and the scope showed the correct number of clock pulses. Having spent a whole bunch of time debugging this issue and making a mess of the code branch with all the extra debugging stuff I decided to create a test harness project for this with a dedicated sketch for each pico.

    The test harness I created to debug this issue is here on my GitHub account: https://github.com/chrisckc/TestHarness-I2C

    For the test harness created 2 sequential float arrays (1.1, 1.2, 1.3 etc.) of the same sizes I was using in my project. I dumped them out on the serial port as their respective byte arrays in hex and binary format to aid debugging on the scope. I used a lower 10Hz frequency for transmission of the 2 arrays and decoded them back into floats on the receiving side as before. This time I also allowed for missing data in the first transmission to be processed I had purely been focusing on what was going on in the second transmission so far. I also maintained the delay between the first and second transmissions, increasing it to 1000uS

    The only real differences I noticed with the new test code was that I sometimes had 2 missing bytes rather than 1 missing, also the missing byte(s) are at the end rather than at the beginning as only the last float value was corrupted.

    My test code has confirmed that the issue is still there, and is also occurring in the first transmission, but only at a round half the error rate of the second transmission. I also used the protocol decoder on my scope to check the bytes against the hex values that I output over serial debugging. By triggering off a low pulse from a debug pin indicating missing data I was able to confirm that all of the the bytes were indeed correct and present, despite what the onReceive interrupt reported.

    The 48 bytes transmitted in the second transmission are as follows, separated by dashes and comma for clarity: ( float1byte1-float1byte2-float1byte3-float1byte4,float2byte1-float2byte2-float2byte3-float2byte4, .... ) 66-66-46-40,CD-CC-4C-40,33-33-53-40,9A-99-59-40,00-00-60-40,66-66-66-40,CD-CC-6C-40,33-33-73-40,9A-99-79-40,00-00-80-40,33-33-83-40,66-66-86-40

    Here is the protocol decoder output from the wire: ScreenImg-26 In the above scope image, an error has been detected on the second transmission of the pair, the yellow trace low pulse is the error marker, purple is i2c clock and blue is i2c SDA, green is the marker for the code which processes to data and also generates the yellow pulse if there is an error. As can be seen, the protocol decoder has decoded the data, showing the data in the second transmission. The last byte is 0x40 which is clearly visible in the blue trace. The interrupt handler only reported 47 bytes for this transmission and the decoded float value array had a corrupted last value due to the 0x40 not being received.

    Ok, so now armed with the test harness and having confirmed that the correct bytes are always being sent, regardless of an error being detected at the receiver, I tried the following:

    1. Reduced the transmission rate (the gap between each pair of transmissions), to 1Hz, errors still occurred around same percentage, I changed it back to 10Hz for the rest of the changes below.

    2. Reduced the i2c clock to 400KHz (actually about 365KHz as measured), errors were now down to around 0.5 to 1%

    3. Changed some serial debug output so that it occurred in-between the first and second transmission blocks as it was originally, errors now increased to around 1 to 2%

    4. Reduced the i2c clock further to 100KHz (actually about 95 KHz as measured), errors were now down to around 0.007% and I had to leave it running for a while to get a decent amount of failures to generate the average failure percentage.

    The circuit that I originally encountered this issue on is built on a protoboard with soldered wires, the connections between the i2c pins on each pico are very short (around 15mm) however there is an ADC connected to the transmitting Pico which is also being clocked by it using the Pico’s internal 12MHz clock output on a pin. The receiving pico was actually a PicoW and I also wanted to rule that out of the picture, even though there was no Wifi code being used at this stage.

    Stage 3:

    To rule out my hardware configuration I rebuilt a simple version on a breadboard using 2 brand new Pico’s (no PicoW involved here) this time the i2c wires are bit longer at around 50mm due to the breadboard layout constraints. As before I connected the VBUS pins together so that the USB connected to one of the Pico’s also powers the other Pico. Obviously the ground pins are also connected together.

    Breadboard test setup: 20221111_192715

    My actual project prototyping hardware which I originally encountered this issue on: 20221112_195312

    Results were the same on the breadboard setup, the issue still existed with the failure rates around the same percentages.

    I then connected the VSYS pins of each Pico together and powered VSYS from 4 NiMH cells in series, around 5v. I used VSYS rather than VBUS to take advantage of the diode to avoid back-powering the USB bus on the laptop when connecting it to the USB port on the Pico.

    I left it running with nothing else connected, no USB cable, no scope, no test wires sticking out of the breadboard etc. After some time had passed I connected the USB cable to the receiving Pico to check the serial output and found many errors had built up, at around the same rate as when i was powering from USB and had the scope connected. I left this running over night and it accumulated around 12,000 errors across both the first and second transmissions in the pair.

    Minimal battery operated setup: 20221112_160808

    The reason for the above test was to rule out any noisy USB power issues, although seeing as the 3.3v reg on the Pico is a buck-boost converter this was unlikely to make any difference, and sure enough did not.

    Next steps:

    Having so far not determined if this is a hardware or software issue, my next steps will be as follows:

    1. Attempt to read the expected number of bytes inside the onReceive interrupt rather than what is supplied by the interrupt handler function, Although this would not account for data missing at the start of the transmission as observed initially.

    2. Bypass the Arduino Wire API and make use of the underlying Pico SDK directly, while also having a good look at the Wire API implementation.

    3. Swap out just the receiving Pico for a different dev board, say a Teensy4

    4. Swap out just the transmitting Pico for a different dev board, say a Teensy4

    5. As I am currently using i2c1 on both of the Pico’s (Wire1) change the code and pins to use i2c0 (Wire)

    6. Go back to the 2 Pico’s and power them both from an external 3.3v linear reg, bypassing the switching regulator.

    7. Play around with the amount of data being sent in each transmission so see what difference it makes.

  • Add Pico W WiFi support

    Add Pico W WiFi support

    Add support for the WiFi chip on the Pico W board.

    Works well enough for experimental use

    To Do: [X] Update LWIP options (now it is the default example one [X] Add WiFi class [X] Add WiFi client class [X] Add support classes (DNS, etc.) [X] Add WiFi server class [X] Add AP mode [X] Examples [X] Docs (such as they are...)

    • USB interrupt now no longer hard coded (conflicted with the WiFi IRQ).
    • Add in Pico W board to makeboards.py
    • Add in GPIO and variant support
    • Initialize WiFi in the Variant
    • Use manual LWIP, fix size accounting
    • Remove the SDK WiFi overrides
    • Pulling in work done in the ESP8266 core.
    • Make IPAddress support IPv6
    • Build LWIP with IPv4 and IPv6 support
    • Use proper MAC
    • Avoid cyw_warn crash. Make macro to a comment while building
    • Add WiFiServer
    • Add WiFiUdp
    • Move LWIP-specific support files to LWIP_Ethernet
    • Add WiFi::ping (ICMP ping)
    • Move ICMP echo (ping) to LWIPIntfDev
    • Move hostByName to LwipIntfDev
    • Add AP Mode

    Eventually... Fixes #666 Fixed #665

  • After flashing the pico, no life sign from the board

    After flashing the pico, no life sign from the board

    Hi everyone,

    i'm using a RP2040-Zero from waveshare https://www.waveshare.com/product/raspberry-pi/boards-kits/raspberry-pi-pico-cat/rp2040-zero.htm.

    If i try to upload the code, even a simple "hello word" over serialUSB, nothing happens after the flashing is completed. It's like the board is not able boot or something because if i connect it over USB windows does not detect it and the code seems not running (tried to change a pin digital output to see if was something only related to the serialUSB but no changes there).

    If i use platformio indicated platform (raspberry) even if it is missing a lot of key stuff that are present in the arduino-pico, the board is detected overt serial and i get the "hello word" print. So the board is ok and working from the hw point of view.

    What am i doing wrong?

    This is my platformio.ini file

    [env:pico] platform = https://github.com/maxgerhardt/platform-raspberrypi.git board = pico framework = arduino board_build.core = earlephilhower

    thanks in advance

  • EEPROM.commit() hangs apparently due to rp2040.idleOtherCore() / rp2040.resumeOtherCore()

    EEPROM.commit() hangs apparently due to rp2040.idleOtherCore() / rp2040.resumeOtherCore()

    I am having a problem with EEPROM.commit() hanging randomly. Sometimes it works, mostly it doesn't. Be aware that I am also using FreeRTOS and using the PlatformIO environment. See example code below.

    In the following code I use EEPROM.end(), but the failure is happening within EEPROM.commit() (called within end())

    I have tried various things including running saveConfig() in a separate task running at highest priority, placing vTaskDelay() between calls to EEPROM methods and stepping through/over using the debugger (via picoprobe). Note: it runs fine if I step through it. So maybe there's a timing issue.

    I finally tried editing EEPROMClass::commit() to; ... 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); // rp2040.resumeOtherCore(); interrupts(); ...

    Success! So it seems the problem is in idleOtherCore() / resumeOtherCore() Thankfully I have no tasks running on the other core - maybe I should, to keep this happy?


    #define EEPROM_SIZE 255 #define EEPROM_ADDRESS 0

    typedef long signed int MotorPosition_t;

    struct Config { short configured; MotorPosition_t motorPosition; MotorPosition_t openedPosition; };

    void saveConfig(MotorPosition_t motorPosition, MotorPosition_t openedPosition) { Config config; config.configured = ConfigMagicNumber; config.motorPosition = motorPosition; config.openedPosition = openedPosition;

    EEPROM.begin(EEPROM_SIZE); EEPROM.put(EEPROM_ADDRESS , config); EEPROM.end(); }

  • USB Device not detected by host when using platformIO

    USB Device not detected by host when using platformIO

    Issue : Device is not detected by Host computer after uploading from platform io

    What I have tried

    • Many of the Adafruit TinyUSB library examples (HID,MIDI,.. none did work)
    • Compiling on 3 different computers (didn't help)
    • Including libraries or not in the platformio.ini file

    what works :

    • When compiled on PIO : The rest of the code seems to run fine, just not the USB part
    • When compiled on Arduino IDE : USB comunication works fine (everything works)

    Example code :

    #include <Arduino.h>
    #include <Adafruit_TinyUSB.h>
    #include <MIDI.h>
    
    Adafruit_USBD_MIDI usb_midi;
    MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI_USB);
    
    void setup(void) {
      TinyUSB_Device_Init(0);
    
      MIDI_USB.begin(MIDI_CHANNEL_OMNI);
      while( !TinyUSBDevice.mounted() ) delay(1); // obviously hangs there if not commented
    }
    
    void loop(){
    //device should be detected at this point
    };
    

    platformio.ini file :

    [env:pico_W64]
    platform = https://github.com/maxgerhardt/platform-raspberrypi.git
    board = pico
    framework = arduino
    board_build.core = earlephilhower
    board_build.filesystem_size = 0m
    platform_packages = 
    	maxgerhardt/[email protected]://github.com/earlephilhower/arduino-pico.git
    	maxgerhardt/[email protected]://github.com/earlephilhower/pico-quick-toolchain/releases/download/1.3.3-a/x86_64-w64-mingw32.arm-none-eabi-ed6d983.220212.zip
    build_flags = -DUSE_TINYUSB
    lib_deps = 
    	adafruit/Adafruit TinyUSB [email protected]^1.9.4; tried with and without
    

    Nalco

  • Default pins for Serial/SPI/I2C not set properly

    Default pins for Serial/SPI/I2C not set properly

    I was having issues getting any i2c sensor to work so after a lot of testing and searching i came across this issue witch is unrelated but did help me https://github.com/earlephilhower/arduino-pico/issues/38#issuecomment-808835731 the tester that was pointed out also did not work.

    no i saw that PICO_DEFAULT_I2C_SCL_PIN and PICO_DEFAULT_I2C_SDA_PIN ar defined but when correctly connected it does not work.

    i fixed this by setting the pins at the beginring of my program Wire.setSCL(PICO_DEFAULT_I2C_SCL_PIN);//gp5 Wire.setSDA(PICO_DEFAULT_I2C_SDA_PIN);//gp4

    now i don't know if this is an issue but seeing that they are defined you would expect it to use them if not explicitly told to use different pins right? I figured i would let you know.

  • ModuleNotFoundError: No module named 'encodings'

    ModuleNotFoundError: No module named 'encodings'

    Just (re)installed this onto my Windows machine. Latest v2.6.3.

    No matter what board I choose, I always get the following Python error

    Fatal Python error: initfsencoding: unable to load the file system codec
    ModuleNotFoundError: No module named 'encodings'
    
    Current thread 0x000030b4 (most recent call first):
    exit status -1073740791
    Error compiling for board Generic RP2040.
    

    Edit: Downgrading to 2.6.1 'fixes it' and works

  • XIAO RP2040 failed @ Wire.write (I2C)

    XIAO RP2040 failed @ Wire.write (I2C)

    Discussed in https://github.com/earlephilhower/arduino-pico/discussions/591

    Originally posted by numeru55 May 23, 2022 Using both

    rp2040:rp2040    2.0.2   2.0.2  Raspberry Pi Pico/RP2040                  
    Seeeduino:rp2040 2.7.2   2.7.2  Seeed XIAO RP2040  
    

    I2C scan is OK for both core:

        Wire.beginTransmission(0x40);
        byte error = Wire.endTransmission();
    

    But Wire.write() is ignore only for earlephihower:

        Wire.beginTransmission(0x40);
        Wire.write(byte(0));
        byte error = Wire.endTransmission();
    

    Seeed core : address byte and 0 are transmitted normally earlephihower: nothing is transmitted on I2C line. Why?

  • No more able to program my RP2040

    No more able to program my RP2040

    Hello,

    First of all a big thank you for your work.

    i'm actually no more able to program my RP2040. Can not be sure at 100% but seems to be since the update a few day ago.

    "Resetting COM10 Converting to uf2, output size: 114176, start address: 0x2000 Unable to build drive list Une erreur est survenue lors du transfert du croquis " if using the "Mbed version" it's ok but no more with yours. tried with 2 different board ans same result.

    Any advice on what to check ?

    regards

    Jean-Francois

  • Including WiFi support breaks an already working sketch

    Including WiFi support breaks an already working sketch

    I'm working on a sketch which collect samples of a signal and process them after some pre-defined time, the processing is somewhat complex but it works Ok. Adding Wifi support to be able to sync the clock using NTP make the operation unstable, it even hang after some 45 seconds or so.

    The ADC collection segment follows, setup_adc() is called once whilst collect_adc() is called every 160 mSecs or so.

    void setup_adc() {
      adc_gpio_init(ADC0 + ADC_CHANNEL);
      adc_init();
      adc_select_input(ADC_CHANNEL);
      adc_fifo_setup(
        true,    // Write each completed conversion to the sample FIFO
        true,    // Enable DMA data request (DREQ)
        1,       // DREQ (and IRQ) asserted when at least 1 sample present
        false,   // We won't see the ERR bit because of 8 bit reads; disable.
        false     // Shift each sample to 8 bits when pushing to FIFO
      );
      adc_set_clkdiv(CLOCK_DIV);
      sleep_ms(200);
      dma_chan = dma_claim_unused_channel(true);
      cfg = dma_channel_get_default_config(dma_chan);
      channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16);
      channel_config_set_read_increment(&cfg, false);
      channel_config_set_write_increment(&cfg, true);
      channel_config_set_dreq(&cfg, DREQ_ADC);
    
    }
    void collect_adc() {
    
      adc_fifo_drain();
      adc_irq_set_enabled(false);
      adc_run(false);
          
      dma_channel_configure(dma_chan, &cfg,
          fresh_signal,    // dst
          &adc_hw->fifo,  // src
          CAPTURE_DEPTH,          // transfer count
          true            // start immediately
          );
      adc_irq_set_enabled(true);
      adc_run(true);
    }
    

    The processing of the samples is complex but straightforward codewise

        collect_adc();
        tstart = time_us_32();
        while (true) {
          if (flag_first) {
            dma_channel_wait_for_finish_blocking(dma_chan);
            flag_first = false;
            break;
          }
            for (int i = 0; i < nfft; i++) {
                old_signal[i] -= DC_BIAS;
            }
            adc_error = inc_extract_power(dma_chan, old_signal,false);
            if (adc_error != 0x00) {
               break;
            }
           while (dma_channel_is_busy(dma_chan));
           break;
        } //true, pseudo infinite loop
      } //whole reception cycle
    

    As said the above code works ok.

    Then I added the following lines

    int setup_wifi() {
      WiFi.begin("MyISPSSID", "mipassword");
      delay(1000);
    
      uint32_t t = time_us_32();
      
      while (WiFi.status() != WL_CONNECTED) {
        if (time_us_32() - t > wifi_tout * 1000000) {
          return WiFi.status();
        }
      }
      char ipstr[16];
      sprintf(ipstr,"%s",IpAddress2String(WiFi.localIP()).c_str());
      delay(1000);
      return 0;
    }
    

    The sketch works, the connection is made to the WiFi AP succesfully, the data collection cycle operates for some 30 secs correctly and then the whole sketch hangs.

    Probably the above isn't enough to profile the possible reason, but I would like to understand if the WiFi implementation has some interaction or dependency with the ADC operation, or the DMA reading of ADC samples or requires some periodic call somewhere to operate or some interrupt handling jeopardizes the working.

    Thanks in advance, Pedro

  • Feature request: Add TDM mode for I2S

    Feature request: Add TDM mode for I2S

    Codecs (with more than 2 channels use TDM (Time Domain Multiplex) to provide up to 8 Channels of Inputs or Outputs per I2S port. For instance, the CS42448 Codec has 6 Inputs and 8 Inputs which can be used using one single I2S interface.

    Adding TDM support would add a big range of new possibilities.

  • Feature request: Add MCLK support to I2S

    Feature request: Add MCLK support to I2S

    Some I2S codecs require a MCLK signal which is 64/128/256*fs. This signal needs to be aligned with the bit clock (BCLK). Adding master MCLK support would extend the support to many more widely available codecs (like the WM8731).

  • C++ extension configuration issues when developing with Arduino Extension in VSCode

    C++ extension configuration issues when developing with Arduino Extension in VSCode

    Hi Earle! This is not is more of a general issue that I am having when developing code for Raspberry Pi Pico in VSCode. In the first line of my code, I get squiggle errors that mention this: image

    I have an auto-configured c_cpp_properties.json that auto configures when I compile the code, getting rid of any changes I make to the include path list. I wanted to know if it is something that you can look into, or it's more of an "Arduino has to take care of it" thing. Also, is there a "good" configuration file that exists?

  • Add BSSID connection possibility, use it for WiFiMulti

    Add BSSID connection possibility, use it for WiFiMulti

    Unfortunately the Pico-SDK's CYW43 driver does not allow requesting a specific BSSID

    So as far as I understand a issue should be opened in pico-sdk, right?

    Originally posted by @deival1980 in https://github.com/earlephilhower/arduino-pico/issues/944#issuecomment-1299295309

built-in CMSIS-DAP debugger tailored especially for the RP2040 “Raspberry Pi Pico”

RP2040 has two ARM Cortex-M0+ cores, and the second core normally remains dormant. pico-debug runs on one core in a RP2040 and provides a USB CMSIS-DAP interface to debug the other core. No hardware is added; it is as if there were a virtual debug pod built-in.

Dec 30, 2022
Enable LoRaWAN communications on your Raspberry Pi Pico or any RP2040 based board. 📡

pico-lorawan Enable LoRaWAN communications on your Raspberry Pi Pico or any RP2040 based board using a Semtech SX1276 radio module. Based on the Semte

Dec 30, 2022
#PICOmputer - World first Raspberry RP2040 PICO - QWERTY & IPS devkit
#PICOmputer - World first Raspberry RP2040 PICO - QWERTY & IPS devkit

PICOmputer #PICOmputer - World first Raspberry RP2040 PICO - QWERTY & IPS devkit https://www.pcbway.com/project/shareproject/_PICOmputer____World_firs

Dec 30, 2022
Capture audio from a microphone on your Raspberry Pi Pico or any RP2040 based board. 🎤

pico-microphone Capture audio from a microphone on your Raspberry Pi Pico or any RP2040 based board. ?? Hardware RP2040 board Raspberry Pi Pico Microp

Dec 27, 2022
USB host implementation using PIO of raspberry pi pico (RP2040).

Pico-PIO-USB USB host implementation using PIO of raspberry pi pico (RP2040). You can add additional USB port to RP2040. ?? This library is WIP. API m

Dec 30, 2022
This is a set of utilities that allow you to read, write or erase SPI flash chips using a Raspberry Pi Pico (RP2040) chip.

Pico SPI Utilities This is a set of utilities that allow you to read, write or erase SPI flash chips using a Raspberry Pi Pico (RP2040) chip. While th

Aug 7, 2022
Tetris on a Raspberry Pi Pico mounted on a Pimoroni Pico Explorer

PicoTetris Classic Tetris game running on a Raspberry Pi Pico microcontroller. Pico C port by Richard Birkby Original JavaScript implementation - Jake

Dec 3, 2022
Breakout game for Raspberry Pi Pico with Pimoroni Pico Display pack
Breakout game for Raspberry Pi Pico with Pimoroni Pico Display pack

breakout_rpi_pico Breakout game for Raspberry Pi Pico with Pimoroni Pico Display pack Prebuilt binary (breakout.uf2) is here. To build your own binary

Oct 15, 2022
Pico-uart-bridge - Raspberry Pi Pico UART-USB bridge

Raspberry Pi Pico USB-UART Bridge This program bridges the Raspberry Pi Pico HW UARTs to two independent USB CDC serial devices in order to behave lik

Dec 23, 2022
Digital rain animation gif with glow squeezed into a raspberry pi pico and pimoroni pico-display
Digital rain animation gif with glow squeezed into a raspberry pi pico and pimoroni pico-display

pico-display-matrix Digital rain animation gif with glow squeezed into a raspberry pi pico and pimoroni pico-display or how to actually use all Flash

Sep 10, 2022
A C library for RP2040-powered boards to control LCDs via the I2C protocol

picoi2clcd A C library to control I2C LCD displays using the Rapsberry Pi Pico (or really any board using the RP2040 microcontroller). License All of

Oct 16, 2021
Prueba del Raspberry PI PICO con un display Raspberry PI TFT 3.5"

Raspberry-PI-PICO-display-RPI35 Prueba del Raspberry PI PICO con un display Raspberry PI TFT 3.5" Con ayuda de la libreria https://github.com/khoih-pr

Nov 10, 2021
Arduino core for GD32 devices, community developed, based on original GigaDevice's core
Arduino core for GD32 devices, community developed, based on original GigaDevice's core

GD32 Arduino Core (New) This is a Arduino core is based off of the original GigaDevice core that was provided by the company in early June 2021 (see h

Dec 24, 2022
Internet of things created using arduino IoT cloud, consisting of esp and arduino boards

Internet of things created using arduino IoT cloud, consisting of esp and arduino boards. Goal of the project is to create a 3D printed RFID protected (with PIN) lock, including surveillance.

Sep 1, 2022
Using a RP2040 Pico as a basic logic analyzer, exporting CSV data to read in sigrok / Pulseview

rp2040-logic-analyzer This project modified the PIO logic analyzer example that that was part of the Raspberry Pi Pico examples. The example now allow

Dec 29, 2022
I add my Pi Pico (RP2040) stuff here.

Pico Stuff I add my Pi Pico (RP2040) stuff here. There are complete apps and libraries for sensors or complicated tasks. Libraries BMP180: Header-only

Jan 8, 2023
uSDR implementation based on a RP2040 Pi Pico

uSDR-pico A uSDR implementation based on a RP2040 Pi Pico. This code is experimental, intended to investigate how the HW and SDK work with an applicat

Jan 7, 2023
This is some utility functions/classes for having a nice way to communicate with a pico board RP2040

PicoScreenTerminal This is some utility functions/classes for having a nice way to communicate with a pico board RP2040 How to build First follow the

Nov 15, 2021
RPi Pico/RP2040 firmware for the Scoppy Oscilloscope

scoppy-pico RPi Pico/RP2040 firmware for the Scoppy Oscilloscope Installation and getting started instructions Scoppy Android app - Play Store Scoppy

Dec 20, 2022