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はこちらのダウンロードサイトからダウンロードします。ページを下へ辿ると 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はこちらのダウンロードサイトからダウンロードします。ページを下へ辿り、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の作業用のフォルダを作成します。場所はどこでも良いのですが、以下のようにターミナルで作成しました。
> 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
の順でコマンドを実行します。
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を、そのまま送信するプログラムを作成します。まず、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として認識されています。