LoginSignup
11
11

More than 3 years have passed since last update.

RaspberryPiPicoにmruby/cでプログラムする(Lチカ)

Last updated at Posted at 2021-02-06

まだタイマーは実装できていない…

準備したもの

RaspberryPiPico
windows10のPC
USB-microUSBケーブル

開発環境の構築

公式のドキュメントを参照
私はwindowsだったので「9.2.Building on MS Windows」を参考にした。
・ARM GCC compiler
・CMake
・Build Tools for Visual Studio 2019
・Python 3.7
・Git
をインストールすればいいらしい。
特に問題は無いはずだが私がつまずいた点だけあげておく。

  1. Visual Studio 2019のインストール時、チェックボックスが公式ドキュメントと異なる。
    日本語ですから…とりあえず↓のようにしておいた。 image.png
  2. Gitのインストール時にvim以外を指定するようにドキュメントに書いてある。
    ドキュメント曰くNotepad++にするようにと画像で示されているが、Notepad++をインストールしていなかったのでインストールした。
  3. [9.2.3. Building "Hello World" from the Command Line]にて
    Windows > Visual Studio2019 > Developer Command Prompを開くように言われているのに無視してそのままcmd.exeで作業していました。 気を付けましょう。cmakeとnmakeができないと思います。

mruby/cを導入

mruby/cmrbcをダウンロードします。(コマンドを使用しないでcode > DownlodeZipでコードを持ってくる男)
 → それぞれ解凍しておく。
mruby/cのzipファイルを解凍すると中にsrcフォルダがあると思うので、そのsrcフォルダをpico-examples/blinkへそのまま入れます。
ちなみに今回はpico-examples/blinkを改造して使っていきます。
pico-examples/blink内にあるCMakeLists.txtを編集しなきゃならないですが、cmakeなんてはじめて触るので雑ですが↓のように編集しました。

CMakeLists.txt
add_compile_options(-D MRBC_NO_TIMER)

add_executable(blink
    blink.c
    src/alloc.c
    src/c_array.c
    src/c_hash.c
    src/c_math.c
    src/c_numeric.c
    src/c_range.c
    src/c_string.c
    src/class.c
    src/console.c
    src/error.c
    src/global.c
    src/keyvalue.c
    src/load.c
    src/mrblib.c
    src/rrt0.c
    src/static.c
    src/symbol.c
    src/value.c
    src/vm.c
        )

# Pull in our pico_stdlib which pulls in commonly used features
target_link_libraries(blink pico_stdlib)

# create map/bin/hex file etc.
pico_add_extra_outputs(blink)

# add url via pico_set_program_url
example_auto_set_url(blink)

pico-examples/blink/src/vm_config.h84行目にあるコメントアウトを外します。

vm_config.h
/* 32it alignment
   If 32-bit alignment is required, enable the following line.
 */
#define MRBC_REQUIRE_32BIT_ALIGNMENT

pico-examples/blink/src内にあるhal_psoc5lpフォルダをhalへリネームします。
そのhalフォルダにあるhal.hを↓のように編集します。

hal.h
#ifndef MRBC_SRC_HAL_H_
#define MRBC_SRC_HAL_H_

#ifdef __cplusplus
extern "C" {
#endif

/***** Feature test switches ************************************************/
/***** System headers *******************************************************/
#include "pico/stdlib.h"


/***** Local headers ********************************************************/
/***** Constant values ******************************************************/
/***** Macros ***************************************************************/
#if !defined(MRBC_TICK_UNIT)
#define MRBC_TICK_UNIT_1_MS   1
#define MRBC_TICK_UNIT_2_MS   2
#define MRBC_TICK_UNIT_4_MS   4
#define MRBC_TICK_UNIT_10_MS 10
// You may be able to reduce power consumption if you configure
// MRBC_TICK_UNIT_2_MS or larger.
#define MRBC_TICK_UNIT MRBC_TICK_UNIT_1_MS
// Substantial timeslice value (millisecond) will be
// MRBC_TICK_UNIT * MRBC_TIMESLICE_TICK_COUNT (+ Jitter).
// MRBC_TIMESLICE_TICK_COUNT must be natural number
// (recommended value is from 1 to 10).
#define MRBC_TIMESLICE_TICK_COUNT 10
#endif

#ifndef MRBC_NO_TIMER
# define hal_init()        ((void)0)
# define hal_enable_irq()  ((void)0)
# define hal_disable_irq() ((void)0)
# define hal_idle_cpu()    (sleep_ms(1), mrbc_tick())
#else // MRBC_NO_TIMER
# define hal_init()        ((void)0)
# define hal_enable_irq()  ((void)0)
# define hal_disable_irq() ((void)0)
# define hal_idle_cpu()    (sleep_ms(1), mrbc_tick())

#endif

/***** Typedefs *************************************************************/
/***** Global variables *****************************************************/
/***** Function prototypes **************************************************/
int hal_write(int fd, const void *buf, int nbytes);
int hal_flush(int fd);


/***** Inline functions *****************************************************/


#ifdef __cplusplus
}
#endif
#endif // ifndef MRBC_HAL_H_

(タイマーの実装はできてないので同じ内容をダミーとして入れておきました)

今回使用するRubyのプログラムを用意します。
保存場所はコンパイラのフォルダ内がいいと思います。201904181318159501cbec95e/mruby-2.0.1-winの下
Lチカしたいので、それらしいプログラムを書いておきます。
led1_writeによってオンボードLEDを制御することにします。
第一引数が1の時LEDがON、0の時OFFとなる予定です。
while文の無限ループ内にsleepも含めてプログラムします。1秒間隔でLEDが点滅する。

sample1.rb
while true
    led1_write(1)
    sleep(1)
    led1_write(0)
    sleep(1)
end

sample1.rbを書き終えたらコマンドラインで201904181318159501cbec95e/mruby-2.0.1-winまで移動しましょう。
image.png

移動したらコマンドを打ちますmrbc.exe -E -Bsample1 sample1.rb
すると同じフォルダ内にsample1.cができると思います。↓ sample1[]の中身をコピーしておきましょう。

sample1.c
/* dumped in big endian order.
   use `mrbc -e` option for better performance on little endian CPU. */
#include <stdint.h>
extern const uint8_t sample1[];
const uint8_t
#if defined __GNUC__
__attribute__((aligned(4)))
#elif defined _MSC_VER
__declspec(align(4))
#endif
sample1[] = {
0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x36,0xd1,0x25,0x00,0x00,0x00,0x83,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x65,0x30,0x30,
0x30,0x32,0x00,0x00,0x00,0xe7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x2e,
0x21,0x00,0x23,0x10,0x01,0x07,0x02,0x2e,0x01,0x00,0x01,0x10,0x01,0x07,0x02,0x2e,
0x01,0x01,0x01,0x10,0x01,0x06,0x02,0x2e,0x01,0x00,0x01,0x10,0x01,0x07,0x02,0x2e,
0x01,0x01,0x01,0x11,0x01,0x22,0x01,0x00,0x03,0x0f,0x01,0x37,0x01,0x67,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0a,0x6c,0x65,0x64,0x31,0x5f,0x77,0x72,0x69,
0x74,0x65,0x00,0x00,0x05,0x73,0x6c,0x65,0x65,0x70,0x00,0x45,0x4e,0x44,0x00,0x00,
0x00,0x00,0x08,
};

続いてpico-examples/blink/blink.cを編集していきます。
led1_writeという関数をRubyのプログラムで使えるように追加しておきます。
sample1[]には先ほどRubyプログラムをコンパイルしてできた配列を入れます。

blink.c
#include "pico/stdlib.h"
#include "src/mrubyc.h"
#define MEMORY_SIZE (1024*20)

uint8_t sample1[] = {
0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x36,0xd1,0x25,0x00,0x00,0x00,0x83,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x65,0x30,0x30,
0x30,0x32,0x00,0x00,0x00,0xe7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x2e,
0x21,0x00,0x23,0x10,0x01,0x07,0x02,0x2e,0x01,0x00,0x01,0x10,0x01,0x07,0x02,0x2e,
0x01,0x01,0x01,0x10,0x01,0x06,0x02,0x2e,0x01,0x00,0x01,0x10,0x01,0x07,0x02,0x2e,
0x01,0x01,0x01,0x11,0x01,0x22,0x01,0x00,0x03,0x0f,0x01,0x37,0x01,0x67,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0a,0x6c,0x65,0x64,0x31,0x5f,0x77,0x72,0x69,
0x74,0x65,0x00,0x00,0x05,0x73,0x6c,0x65,0x65,0x70,0x00,0x45,0x4e,0x44,0x00,0x00,
0x00,0x00,0x08,
};
static uint8_t memory_pool[MEMORY_SIZE];

static void c_led1_write(mrb_vm *vm, mrb_value *v, int argc) {
    int set_value = GET_INT_ARG(1);
    gpio_put(25,set_value);
}

int hal_write(int fd, const void *buf, int nbytes) {
    return 0;
}
int hal_flush(int fd) {
    return 0;
}

int main() {
    gpio_init(25);
    gpio_set_dir(25, GPIO_OUT);
    mrbc_init(memory_pool, MEMORY_SIZE);
    mrbc_define_method(0, mrbc_class_object, "led1_write", c_led1_write);
    mrbc_create_task(sample1, 0);
    mrbc_run();
    return 1;
}

プログラムの書き込み

Developer Command Prompを使ってpico-examples/buildへ移動します。
nmakeコマンドを実行。↓のようにビルドがはじまります。

Scanning dependencies of target blink
[  0%] Building C object blink/CMakeFiles/blink.dir/blink.c.obj
[  0%] Building C object blink/CMakeFiles/blink.dir/src/alloc.c.obj
[  0%] Building C object blink/CMakeFiles/blink.dir/src/c_array.c.obj
[  0%] Building C object blink/CMakeFiles/blink.dir/src/c_hash.c.obj
[  0%] Building C object blink/CMakeFiles/blink.dir/src/c_math.c.obj
[  0%] Building C object blink/CMakeFiles/blink.dir/src/c_numeric.c.obj
............

エクスプローラーでpico-examples/build/blinkを開きます↓
image.png
ラズパイpicoをパソコンへ接続します。
すると勝手にエクスプローラが起動します。(一度書き込んだ後はBOOTSELボタンを押しながらパソコンへ接続)
image.png
pico-examples/build/blinkにあるblink.uf2をラズパイpicoのディレクトリにドラッグアンドドロップすれば書き込み完了です。
Lチカが始まります。
動画:pic.twitter.com/D87VRTHXlr

まとめ(感想)

環境構築だけで数時間かかった(´;ω;`)こんなに手のかかったマイコンははじめてです。
現在はタイマーやスリープを実装したいのでドキュメントとにらめっこしています(*´Д`)
スリープのサンプルはあった。
https://github.com/raspberrypi/pico-playground

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11