Getting Started with the Raspberry Pi Pico C/C++ SDK and TinyUSB MIDI

I’ve been meaning to take a proper look at the Raspberry Pi Pico C/C++ SDK for quite some time, but have been putting it off.  With good reason it would appear!  But I’ve finally got to the start of being able to build the Tiny USB test MIDI application myself and so have a good template for moving forward now.

This are the “notes to self” for what I had to do to get up and running, and most importantly, which parts of the documentation were key to getting it all working.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

  • Raspberry Pi Pico
  • Linux (Ubuntu) installation or virtual machine

Installation

All these instructions assume a Linux-based host.  I’m using Ubuntu in a virtual machine.  I followed the instructions in the Getting Started with the Raspberry Pi Pico guide.

Notes:

  • I didn’t use the “pico_setup.sh” script described in Chapter 1 of the guide.
  • I followed the instructions in Chapter 2, which helps me understand a little more what is going on:
    • Get the SDK and the examples using GitHub.
    • Install the toolchain using apt.
  • Build the examples as described in Chapter 3, which helps to verify that everything is installed correctly:
    • Create a build directory.
    • set the PICO_SDK_PATH environment variable.
    • run cmake to create the build environment.
    • run make to perform the build.
  • I’ve then skipped chapter 4, 5, and 6 for now.  Console output and debugging will be important so I’ll come back to those later, but I’m not fussed about using Visual Studio.
  • Now I’m ready to create a project with the environment set up ready to go.

First Tiny USB MIDI Project

There is an example Tiny USB project that builds a MIDI USB device, so I thought I’d start with that.  However there is an issue:

  • All of the Tiny USB examples have a slightly odd build configuration, being designed to be built from within Tiny USB which itself lives within the pico-sdk structure.
  • There are some Raspberry Pi Pico USB examples, but they don’t transfer out of the “pico-examples” area and build as stand-alone projects.

So you have to follow the instructions in Chapter 7 of the guide to turn the Tiny USB MIDI example into a Raspberry Pi Pico example into a stand-alone “external” project.  This means doing the following:

  • Create a project area for your new project.  I have everything Pico installed in a pico area, so I’ve created a pico/src area for my own projects.
  • Copy the following files from pico/pico-sdk/lib/tinyusb/examples/device/midi_test/src:
    • main.c, tusb_config.h, usb_descriptors.c
  • Create a file CMakeLists.txt with the following in it:
cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)
project(picomiditest)
pico_sdk_init()
add_executable(picomiditest)
target_sources(picomiditest PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/main.c
    ${CMAKE_CURRENT_LIST_DIR}/usb_descriptors.c
)

# Make sure TinyUSB can find tusb_config.h
target_include_directories(picomiditest PUBLIC
${CMAKE_CURRENT_LIST_DIR})

# In addition to pico_stdlib required for common PicoSDK functionality, add dependency on tinyusb_device
# for TinyUSB device support and tinyusb_board for the additional board support library used by the example
target_link_libraries(picomiditest PUBLIC pico_stdlib tinyusb_device tinyusb_board)

# Uncomment this line to enable fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
#target_compile_definitions(picomidirouter PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)

pico_add_extra_outputs(picomiditest)

This is based on the CMakeLists.txt file from the pico/pico-examples/usb/device/dev_hid_composite/CMakeLists.txt file, but with the extra entries needed, as described in Chapter 7 of the guide, to make it build outside of the pico-examples area.  Basically this means the “include(pico_sdk_import.cmake)” and “pico_sdk_init()” lines.  Without these, nothing will build.  Everywhere you see “picomiditest”, I’m assuming that is the name of the project directory, the project itself and your build output.  I think they might need to all match, but I’m not sure.

Note copy over the pico_sdk_import.cmake file from pico/pico-sdk/external/ and finally create a build directory.

Your project area should now look something like this:

pico/src/picomiditest/
     +--- build
     +--- CMakeLists.txt
     +--- main.c
     +--- pico_sdk_import.cmake
     +--- tusb_config.h
     +--- usb_descriptors.c

Now the following steps are required.

  1. Create the build environment using cmake.
  2. Build the application.
  3. Plug in a Pico with the boot button pressed.
  4. Copy the resulting picomiditest.uf2 file over to a Raspberry Pi Pico.
$ cd pico/src/picomiditest/build
$ export PICO_SDK_PATH=../../../pico-sdk
$ cmake ..
$ make
$ cp picomiditest.uf2 /media/RPI_RP2/
$

If all goes well the Pico will come up blinking the LED and if you fire up a MIDI application you should see a Tiny USB device and if you connect to it as a MIDI input you should start receiving MIDI note messages.

Closing Thoughts

I had an initial go at this a number of weeks back, but got stuck trying to setup the CMakeLists.txt file to allow the build system to find all the bits and pieces.  The crucial missing bit of information for me was the fact that the examples won’t build outside of the examples area due to extra layers of make information.

As I was attempting to work my way through the Getting Started Guide but with my own application, nothing was working.  What I hadn’t realised was that the information I needed I hadn’t got to yet. I hadn’t noticed that Chapter 7 was dedicated to “Creating your own project”.

Just a small note in the example CMakeList.txt files that they are not “stand alone” would have probably been all I needed.  Oh well, now I know and hopefully this blog may help someone else getting going too.

Having spent some time searching online, I’ve not found anything other than “you’re on your own” messages and posts in response to trying to build Tiny USB examples on the Pico.  Whilst frustrating to get there, in the end all the information you’ll need is around and actually it isn’t too bad!

This is now a good baseline from which I can start building some custom applications.  My starting point will be something for my Pico MIDI Router.

Kevin

8 thoughts on “Getting Started with the Raspberry Pi Pico C/C++ SDK and TinyUSB MIDI

  1. This is very useful, thanks. I would like to be able to invoke tinyusb on core1 of the Pico but from within micropython. I assume it ought to be possible to build an .mpy wrapper to do this, wondered if anyone had tried. Couldn’t find anything via Google.

    Like

  2. Hi, Kevin,

    Have you looked at either of these projects?

    https://github.com/rppicomidi/midi2usbhost
    https://github.com/rppicomidi/midi2usbhub

    With one of those as a starting point, I’m trying to figure out how to get a usb midi host working with a Pico on one of your Pico MIDI Proto Expanders, but I’m a bit confused about how to connect and power everything. All those warnings about not hooking up your expensive gear makes me really nervous!

    I’d appreciate any guidance.

    Thanks.

    Peter

    Like

    1. Haha yes! This is a person after my own heart – I have all the same disclaimers as you know! If you’re using my proto board, I have the same issues – the MIDI OUT isn’t buffered for me either. This is more of an issue of not protecting the Pico: something with an incorrectly wired MIDI connector drawing too much current from the Pico could kill its TX pin (and maybe more) rather than damaging the external equipment.

      So that is the serial side. On the USB side, the key thing about a MIDI host (as opposed to a device) is that the USB device you plug into it has to get its power over USB from the host (Pico) too. To do that with a Pico means powering it with 5V on VBUS. But whatever you plug into its USB port will then get that VBUS voltage directly with no additional circuitry. So basically, make sure you’re using a good 5V power supply to connect to VBUS in the first place – I notice this person wires a USB breakout directly to VBUS and GND, so they seem to be doing the same.

      But if you use a good USB power supply to give you your 5V (and enough current for your MIDI device + the Pico) you should be ok I’d say.

      In the case of using my proto expander, if you’re not using the GPIO expander section for anything else you could build a proto/strip board add-on to connect a USB power connection directly to VBUS/GND there. That would allow you to test it all in isolation and make sure it can power the Pi ok and that the Pi’s USB socket is getting 5V from your additional USB power connection, and that GND really is GND, before plugging anything else in. If you can’t do that, then you’ll have to tap into VBUS somewhere else, possibly even the pads under the Pico as described in that link.

      I can’t guarantee it is the same, but I did something similar in this: https://diyelectromusic.wordpress.com/2022/04/22/raspberry-pi-pico-multi-midi-router-part-3/. In this one the Trinket is the USB host and is powered using 5V from the Pico which itself is powered over USB. In your case you’re replacing the Trinket with a Pico.

      Note when powering the Pico this way as a USB host, do NOT plug it into something like a computer or another USB host. That would get messy pretty quickly I’d imagine.

      Let me know how it goes!

      Kevin

      Like

      1. Ah very nice. BLE MIDI is something still on my todo list. I’ve also got one of those cheap “wireless MIDI” things that you can buy which I think is also BLE so that might be fun to try to work out too…

        Glad its all working – fantastic stuff – jolly well done 🙂

        Kevin

        Like

  3. Hello Friend,

    I have been trying to make my own keyboard device using tinyusb/dev_hid_composite and could not wrangle (mangle?) the CMakeLists.txt to satisfy all the dependencies.

    While I’m not thrilled about it, your method of embedding my project in the pico/src worked almost the first time. I had to add a couple dependencies:

    target_link_libraries(${NAME} PUBLIC pico_stdlib tinyusb_device tinyusb_board pico_multicore pico_unique_id)

    (pico_multicore is likely overkill, but some other StackOverflow had it, and i doubt it hurts).

    I’m pretty stubborn. I REALLY want to do this in my own folder. So as a compromise I did this:

    <code>
    $ cd ~pico
    $ mkdir src
    $ ln -s ~/git/myproject/mytinusb ./src/mytinusb # make a softlink to my code
    </code>

    I want to thank you for your help. This is the only place that had a solution that worked first time.

    Best,

    Greg Smith
    https://drfrancintosh.wordrpress.com

    Like

    1. Glad you got something sorted!

      Note, in my case the pico/src directory is one I created, not one within the Pico SDK… I’ve installed everything Pico related into pico and then all my own projects in a sub-directory called src.

      So I have the following:
      pico/pico-sdk – the main SDK
      pico/pico-examples – the official examples
      pico/pico-extras – additional official extras
      pico/pico-playground – additional official examples for the extras
      pico/src – my own projects

      So that seemed to work for me. I still largely have no clue how CMake works…

      Kevin

      Like

Leave a comment