Flashing a PicoW from Debian

I’m building this firmware for the Pico https://github.com/rosmo-robot/linorobot2_hardware_ESP32_Pico/tree/master/firmware

It builds OK but won’t find the pico to flash.

If plugged in via USB it pops open a finder window and I can drag uf2 files to it OK.

I’m sure it’s simple but I can’t figure it out.

sam@debian:~$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 010: ID 138a:0097 Validity Sensors, Inc. 
Bus 001 Device 004: ID 04ca:7067 Lite-On Technology Corp. Integrated Camera
Bus 001 Device 003: ID 8087:0a2b Intel Corp. Bluetooth wireless interface
Bus 001 Device 011: ID 1199:9079 Sierra Wireless, Inc. EM7455
Bus 001 Device 028: ID 2e8a:0003 Raspberry Pi RP2 Boot
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
sam@debian:~$ sudo dmesg | grep tty
[    0.110455] printk: console [tty0] enabled
[    4.731385] systemd[1]: Created slice system-getty.slice - Slice /system/getty.
[29035.428387] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[29183.404586] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[29245.286535] cdc_acm 1-2:1.0: ttyACM1: USB ACM device
[30471.157899] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[30471.863162] cdc_acm 1-2:1.0: ttyACM2: USB ACM device
[30536.352324] cdc_acm 1-2:1.0: ttyACM3: USB ACM device
[34830.455923] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[35031.463474] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
sam@debian:~$ sudo setserial -g /dev/ttyS[0123]
/dev/ttyS0, UART: unknown, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: unknown, Port: 0x02f8, IRQ: 3
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3

I have
upload_port = /dev/tty0
but I’ve also tried tty1, tty2, tty3

ttyS* are hardware COM ports (e.g. on the motherboard).

The pico will show up as one of the ttyACM* devices. Funny enough you have seem to have 0 to 3 in there.

I’d just suggest:

  1. Execute sudo dmesg -w
  2. Disconnect the Pico
  3. Reconnect the Pico
  4. The logs should say what ttyACM was added.

For example

[  174.611724] usb 1-2: new full-speed USB device number 4 using xhci_hcd
[  174.921500] usb 1-2: New USB device found, idVendor=2e8a, idProduct=000a, bcdDevice= 1.00
[  174.921506] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  174.921508] usb 1-2: Product: Pico
[  174.921510] usb 1-2: Manufacturer: Raspberry Pi
[  174.921512] usb 1-2: SerialNumber: E66038B7133C5D30
[  174.926732] usb-storage 1-2:1.2: USB Mass Storage device detected
[  174.927043] scsi host3: usb-storage 1-2:1.2
[  174.970245] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[  174.970295] usbcore: registered new interface driver cdc_acm
[  174.970297] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
1 Like
4830.449950] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[34830.449957] usb 1-2: Product: Pico
[34830.449962] usb 1-2: Manufacturer: Raspberry Pi
[34830.449966] usb 1-2: SerialNumber: E6614C775B35AF32
[34830.455923] cdc_acm 1-2:1.0: ttyACM0: USB ACM device

But when I upload

Building .pio/build/pico/firmware.bin
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, jlink, mbed, pico-debug, picoprobe, picotool, raspberrypi-swd
CURRENT: upload_protocol = mbed
Trying to reset Pico into bootloader mode...
Forcing reset using 1200bps open/close on port /dev/ttyACM0
Looking for upload disk...
Using manually specified: /dev/ttyACM0
Uploading .pio/build/pico/firmware.bin
*** [upload] /dev/ttyACM0/firmware.uf2: No such file or directory
============================================================================ [FAILED] Took 80.65 seconds ============================================================================

 *  The terminal process "platformio 'run', '--target', 'upload'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

It does pop up a file browser window showing the pi as it fails.

No. When it has

it wants an upload disk and assumes the Pico is in BOOTSEL mode. You’d have to mount the drive (or just double click on the USB stick icon in the desktop environment) and give it the full path, e.g., /media/max/RPI-RP2 on my VM (which is a mount of /dev/sdb1 as it appears in the dmesg log).

$ mount
/dev/sdb1 on /media/max/RPI-RP2 type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)

The serial port is only available when an Arduino firmware is loaded and running (it creates it, it is not available in BOOTSEL mode) and is used to reboot the device into bootloader mode so that picotool / rp2040load can work with the USB device via libusb. This method is used when upload_protocol = picotool is set (or no upload_protocol is explicitly set, since it’s the default).

So, you’re mismatching the expected upload_port arguments for upload_protocol = mbed / picotool respectively.

1 Like

Great, so it worked with

upload_port = /media/sam/RPI-RP2

Thanks.

Follow up question, which pins should I expect to find SDA/ SCL on?

/*
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
It won't work with v1.x motor shields! Only for the v2's with built in PWM
control

For use with the Adafruit Motor Shield v2
---->	http://www.adafruit.com/products/1438
*/

#include <Adafruit_MotorShield.h>
#include <Wire.h>
#include "Adafruit_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
//Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x40);

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Adafruit Motorshield v2 - DC Motor test!");

  if (!AFMS.begin()) {         // create with the default frequency 1.6KHz
  // if (!AFMS.begin(1000)) {  // OR with a different frequency, say 1KHz
    Serial.println("Could not find Motor Shield. Check wiring.");
    while (1);
  }
  Serial.println("Motor Shield found.");

  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}

void loop() {
  uint8_t i;

  Serial.print("tick");

  myMotor->run(FORWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tock");

  myMotor->run(BACKWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tech");
  myMotor->run(RELEASE);
  delay(1000);
}

At whichever pins the variant declares them to be by default. For example for board = rpipicow, that as GP4, GP5.

As per documentation, those can be changed to any other pins that are also support by that I2C peripheral (pinout).

1 Like