Raspberry Pi Picoの環境設定

Raspberry Pi Picoの環境を、Macbook Pro 2019, Mac Os Ventura OS13.5にインストールします。 インストールするのは、CMake, GNU Embedded Toolchain for Arm, Pico SDK, Pico Example の4つです。

インストールは 「Raspberry Pi Picoをセットアップしよう」 を参照しました。

CMakeのインストール

CMakeはこちらのダウンロードサイトからダウンロードします。ページを下へ辿ると macOS 10.13 or laterという項目があります。私は、cmake-3.27.5-macos-universal.dmgを ダウンロードしました。



CMakeのアイコンをApplicationsにコピーします。

CMakeのアプリケーションにPATHを通します。Terminalを開き、以下の行をコピー&ペーストしてください。

> echo export PATH='/Applications/CMake.app/Contents/bin:$PATH' >> ~/.zshrc

GNU Embedded Toolchain for Armのインストール

GNU Embedded Toolchain for Armはこちらのダウンロードサイトからダウンロードします。ページを下へ辿り、gcc-arm-none-eabi-10.3-2021.10-mac.pkg をダウンロードします。

ARMの開発環境へPATHを通します。

  > echo export PATH='/Applications/ARM/bin:$PATH' >> ~/.zshrc
  > echo export PATH='/Applications/ARM/arm-none-eabi/bin:$PATH' >> ~/.zshrc

pico sdkとpico exampleのインストール

まず、picoの作業用のフォルダを作成します。場所はどこでも良いのですが、以下のようにターミナルで作成しました。

  > mkdir ~/pico

pico sdkとpico exampleをgithubからダウンロードします。

  > cd ~/pico
  > git clone https://github.com/raspberrypi/pico-sdk.git --branch master
  > cd pico-sdk
  > git submodule update --init
  > cd ..
  > git clone https://github.com/raspberrypi/pico-examples.git --branch master

pico-exampleをbuildします。まず、buildフォルダをpicoフォルダの下に作成します。 その上で、buildフォルダに移動しcmakeを行います。

  > cd ~/pico
  > mkdir build
  > cd build
  > cmake ../pico-examples

その上でmakeします。

  > make

これで、buildフォルダーにExampleをコンパイルした結果が格納されています。 例えば、build/blink/blink.uf2のような.uf2ファイルがpicoボードにインストールできるファイルです。 build フォルダーの下にどのようなuf2ファイルがあるかfindコマンドで調べてみます。

  > cd build
  > find ./ -name '*.uf2'
  .//blink/blink.uf2
  .//pio/clocked_input/pio_clocked_input.uf2
  .//pio/differential_manchester/pio_differential_manchester.uf2
  .//pio/hello_pio/hello_pio.uf2
  .//pio/ws2812/pio_ws2812.uf2
  .//pio/ws2812/pio_ws2812_parallel.uf2
  .//pio/pwm/pio_pwm.uf2
  .//pio/manchester_encoding/pio_manchester_encoding.uf2
  .//pio/i2c/pio_i2c_bus_scan.uf2
  .//pio/uart_tx/pio_uart_tx.uf2
  .//pio/apa102/pio_apa102.uf2
  .//pio/logic_analyser/pio_logic_analyser.uf2
  .//pio/squarewave/pio_squarewave.uf2
  .//pio/spi/pio_spi_flash.uf2
  .//pio/spi/pio_spi_loopback.uf2
  .//pio/st7789_lcd/pio_st7789_lcd.uf2
  .//pio/ir_nec/ir_loopback/pio_ir_loopback.uf2
  .//pio/quadrature_encoder/pio_quadrature_encoder.uf2
  .//pio/pio_blink/pio_blink.uf2
  .//pio/onewire/pio_onewire.uf2
  .//pio/hub75/pio_hub75.uf2
  .//pio/uart_rx/pio_uart_rx_intr.uf2
  .//pio/uart_rx/pio_uart_rx.uf2
  .//pio/addition/pio_addition.uf2
  .//hello_world/usb/hello_usb.uf2
  .//hello_world/serial/hello_serial.uf2
  .//cmake/build_variants/build_variant1.uf2
  .//cmake/build_variants/build_variant2.uf2
  .//picoboard/blinky/picoboard_blinky.uf2
  .//picoboard/button/picoboard_button.uf2
  .//pwm/hello_pwm/hello_pwm.uf2
  .//pwm/led_fade/pwm_led_fade.uf2
  .//pwm/measure_duty_cycle/pwm_measure_duty_cycle.uf2
  .//clocks/hello_gpout/hello_gpout.uf2
  .//clocks/hello_48MHz/hello_48MHz.uf2
  .//clocks/detached_clk_peri/clocks_detached_clk_peri.uf2
  .//clocks/hello_resus/hello_resus.uf2
  .//multicore/multicore_runner/multicore_runner.uf2
  .//multicore/hello_multicore/hello_multicore.uf2
  .//multicore/multicore_fifo_irqs/multicore_fifo_irqs.uf2
  .//multicore/multicore_runner_queue/multicore_runner_queue.uf2
  .//interp/hello_interp/hello_interp.uf2
  .//timer/hello_timer/hello_timer.uf2
  .//timer/timer_lowlevel/timer_lowlevel.uf2
  .//timer/periodic_sampler/periodic_sampler.uf2
  .//i2c/ssd1306_i2c/ssd1306_i2c.uf2
  .//i2c/lcd_1602_i2c/lcd_1602_i2c.uf2
  .//i2c/lis3dh_i2c/lis3dh_i2c.uf2
  .//i2c/ht16k33_i2c/ht16k33_i2c.uf2
  .//i2c/mpu6050_i2c/mpu6050_i2c.uf2
  .//i2c/bmp280_i2c/bmp280_i2c.uf2
  .//i2c/slave_mem_i2c/slave_mem_i2c.uf2
  .//i2c/pcf8523_i2c/pcf8523_i2c.uf2
  .//i2c/bus_scan/i2c_bus_scan.uf2
  .//i2c/mpl3115a2_i2c/mpl3115a2_i2c.uf2
  .//i2c/pa1010d_i2c/pa1010d_i2c.uf2
  .//i2c/mma8451_i2c/mma8451_i2c.uf2
  .//i2c/mcp9808_i2c/mcp9808_i2c.uf2
  .//usb/host/tinyusb_host_examples/cdc_msc_hid/tinyusb_host_cdc_msc_hid.uf2
  .//usb/host/tinyusb_host_examples/hid_controller/tinyusb_host_hid_controller.uf2
  .//usb/host/tinyusb_host_examples/msc_file_explorer/tinyusb_host_msc_file_explorer.uf2
  .//usb/host/tinyusb_host_examples/bare_api/tinyusb_host_bare_api.uf2
  .//usb/host/host_cdc_msc_hid/host_cdc_msc_hid.uf2
  .//usb/device/dev_hid_composite/dev_hid_composite.uf2
  .//usb/device/tinyusb_device_examples/cdc_msc/tinyusb_dev_cdc_msc.uf2
  .//usb/device/tinyusb_device_examples/webusb_serial/tinyusb_dev_webusb_serial.uf2
  .//usb/device/tinyusb_device_examples/hid_multiple_interface/tinyusb_dev_hid_multiple_interface.uf2
  .//usb/device/tinyusb_device_examples/hid_generic_inout/tinyusb_dev_hid_generic_inout.uf2
  .//usb/device/tinyusb_device_examples/msc_dual_lun/tinyusb_dev_msc_dual_lun.uf2
  .//usb/device/tinyusb_device_examples/audio_test/tinyusb_dev_audio_test.uf2
  .//usb/device/tinyusb_device_examples/dfu/tinyusb_dev_dfu.uf2
  .//usb/device/tinyusb_device_examples/midi_test/tinyusb_dev_midi_test.uf2
  .//usb/device/tinyusb_device_examples/audio_4_channel_mic/tinyusb_dev_audio_4_channel_mic.uf2
  .//usb/device/tinyusb_device_examples/usbtmc/tinyusb_dev_usbtmc.uf2
  .//usb/device/tinyusb_device_examples/video_capture/tinyusb_dev_video_capture.uf2
  .//usb/device/tinyusb_device_examples/hid_composite/tinyusb_dev_hid_composite.uf2
  .//usb/device/tinyusb_device_examples/uac2_headset/tinyusb_dev_uac2_headset.uf2
  .//usb/device/tinyusb_device_examples/cdc_dual_ports/tinyusb_dev_cdc_dual_ports.uf2
  .//usb/device/tinyusb_device_examples/board_test/tinyusb_dev_board_test.uf2
  .//usb/device/tinyusb_device_examples/dfu_runtime/tinyusb_dev_dfu_runtime.uf2
  .//usb/device/tinyusb_device_examples/dynamic_configuration/tinyusb_dev_dynamic_configuration.uf2
  .//usb/device/dev_lowlevel/dev_lowlevel.uf2
  .//system/hello_double_tap/hello_double_tap.uf2
  .//system/unique_board_id/unique_board_id.uf2
  .//system/narrow_io_write/narrow_io_write.uf2
  .//flash/cache_perfctr/flash_cache_perfctr.uf2
  .//flash/program/flash_program.uf2
  .//flash/xip_stream/flash_xip_stream.uf2
  .//flash/ssi_dma/flash_ssi_dma.uf2
  .//flash/nuke/flash_nuke.uf2
  .//spi/bme280_spi/bme280_spi.uf2
  .//spi/spi_dma/spi_dma.uf2
  .//spi/max7219_32x8_spi/max7219_32x8_spi.uf2
  .//spi/mpu9250_spi/mpu9250_spi.uf2
  .//spi/max7219_8x7seg_spi/max7219_8x7seg_spi.uf2
  .//spi/spi_master_slave/spi_master/spi_master.uf2
  .//spi/spi_master_slave/spi_slave/spi_slave.uf2
  .//spi/spi_flash/spi_flash.uf2
  .//watchdog/hello_watchdog/hello_watchdog.uf2
  .//adc/joystick_display/joystick_display.uf2
  .//adc/adc_console/adc_console.uf2
  .//adc/microphone_adc/microphone_adc.uf2
  .//adc/onboard_temperature/onboard_temperature.uf2
  .//adc/hello_adc/hello_adc.uf2
  .//adc/read_vsys/read_vsys.uf2
  .//adc/dma_capture/adc_dma_capture.uf2
  .//divider/hello_divider.uf2
  .//rtc/rtc_alarm/rtc_alarm.uf2
  .//rtc/hello_rtc/hello_rtc.uf2
  .//rtc/rtc_alarm_repeat/rtc_alarm_repeat.uf2
  .//dma/channel_irq/dma_channel_irq.uf2
  .//dma/control_blocks/dma_control_blocks.uf2
  .//dma/sniff_crc/sniff_crc.uf2
  .//dma/hello_dma/hello_dma.uf2
  .//gpio/hello_gpio_irq/hello_gpio_irq.uf2
  .//gpio/dht_sensor/dht.uf2
  .//gpio/hello_7segment/hello_7segment.uf2
  .//uart/lcd_uart/lcd_uart.uf2
  .//uart/hello_uart/hello_uart.uf2
  .//uart/uart_advanced/uart_advanced.uf2
新しい開発用のフォルダ

例えば、MyAppというフォルダを作ったとします。ディレクトリはどこでも良いです。 このフォルダには以下のファイルが入っているものとします。

MyApp
 |- MyApp.cpp
 |- MyApp.h
 |- CMakeLists.txt

このとき、cmakeを実行するためにCMakeLists.txtは以下のように記載します。

  cmake_minimum_required(VERSION 3.12)

  # Pull in SDK (must be before project)
  include($ENV{PICO_EXAMPLE_PATH}/pico_sdk_import.cmake)
  include($ENV{PICO_EXAMPLE_PATH}/pico_extras_import_optional.cmake)
  
  # Initialize the SDK
  pico_sdk_init()
  
  set(Proj "MyApp")
  project (${Proj})
  
  add_executable(${Proj}
          MyApp.c
          MyApp.h
          )
  
  # pull in common dependencies
  target_link_libraries(${Proj} pico_stdlib)
  
  # create map/bin/hex file etc.
  pico_add_extra_outputs(${Proj} )
  
  # compile option
  add_compile_options(-Wall -g3 -O0)

これでいずれかにbuildフォルダを作成し、cmake、その後makeをすればuf2ファイルができます。 例えば、MyAppの下にbuildを作ったとすると

 MyApp
 |- MyApp.cpp
 |- MyApp.h
 |- CMakeLists.txt
 |- build
> mkdir build
> cd build
> cmake ..
> make

の順でコマンドを実行します。


MIDIを扱う

USB-MIDIでMIDIを扱うサンプルプログラムは以下のフォルダーにあります。

~/pico/pico-sdk/lib/tinyusb/examples/device/midi_test

uf2ファイルは、上で行ったmakeの結果以下のフォルダーにあります。

  ~/pico/build/usb/device/tinyusb_device_examples/midi_test

このmidi_test.uf2ファイルをpicoにインストールすると、連続してNote On, Note OffのMIDIが出力されます。

MIDI Through

受信したMIDIを、そのまま送信するプログラムを作成します。まず、midi_thrフォルターを作成します。 このフォルダーには、新たに作成するmain.cとmidi_testからusb_config.hとusb_discriptor.Cを以下のディレクトリからコピーします。 さらにpico_exampleからpico_sdk_import.cmakeをコピーします。

  ~/pico/pico-sdk/lib/tinyusb/examples/device/midi_test

以下のプロフラムをmain.cとしてmidi_thrフォルダーに保存します。

#include "bsp/board.h"
#include "tusb.h"

/*------------- MAIN -------------*/
int main(void)
{
  uint8_t packet[4];
  board_init();

  // init device stack on configured roothub port
  tud_init(BOARD_TUD_RHPORT);

  while (1)
  {
    tud_task();                       // tinyusb device task
    while ( tud_midi_available() ){
      tud_midi_packet_read(packet);   // receive MIDI packet
      tud_midi_packet_write(packet);  // send MIDI packet
    }
  }
  return 0;
}

CMakeLists.txtを以下のように作成します。

  cmake_minimum_required(VERSION 3.5)
  set(FAMILY rp2040) 
  
  include(pico_sdk_import.cmake)
  include($ENV{PICO_SDK_PATH}/lib/tinyusb/hw/bsp/family_support.cmake)
  
  family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
  family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
  
  project(${PROJECT})
  set(CMAKE_C_STANDARD 11)
  set(CMAKE_CXX_STANDARD 17)
  set(PICO_EXAMPLE_PATH $ENV{PICO_EXAMPLE_PATH})
  
  add_executable(${PROJECT})
  
  target_sources(${PROJECT} PUBLIC
          ${CMAKE_CURRENT_SOURCE_DIR}/main.c
          ${CMAKE_CURRENT_SOURCE_DIR}/usb_descriptors.c
  )
  
  target_include_directories(${PROJECT} PUBLIC
          ${CMAKE_CURRENT_SOURCE_DIR}
  )
  
  family_configure_device_example(${PROJECT})

midi_thrフォルダーは以下のようになります。

midi_thr
  |- CMakeLists.txt
  |- main.c
  |- usb_descriptors.c
  |- tusb_config.h
  |- pico_sdk_import.cmake

buildフォルダーを作成し、makeします。

> mkdir build
> cd build
> cmake ..
> make

buildフォルダーの中にmidi_thr.uf2ができているはずです。これをpicoにインストールします。 Send and Receive MIDIで確認すると、 TinyUSB Deviceとして認識されています。