2017年9月10日日曜日

STM32/FreeRTOSでLua

 とりあえずSTM32F4のFreeRTOSでLuaのはろーわーるどが動いたのでメモ。

 まずソースファイルをすべて追加する。
 環境によってはコレだけで動くと思う。


 追記:2017/09/11
 僕の環境でmallocが使えるようになりました。ってことでLuaのソースコードそのままで動くようになりました。あとprintfの浮動小数点出力も正常になりました。

 いちおう、mallocじゃなく、FreeRTOSのpvPortMallocを使った方法も残しておきます↓。





 僕の環境だとmallocが使えないので、FreeRTOSのpvPortMallocを使うように書き換える。ただ、LuaはReallocを使ってるので、単純に置き換えることはできない。


 まず、lua_mallocという関数を用意する。

void *lua_malloc(void *ptr, size_t size)
{
 if (ptr && size == 0)
 {
  vPortFree(ptr);
  return (0);
 }

 void *newptr = pvPortMalloc(size);

 if (!newptr)
 {
  vPortFree(ptr);
  return (0);
 }

 if (ptr)
 {
  memcpy(newptr, ptr, size);
  vPortFree(ptr);
 }

 return (newptr);
}

 これはmallocやrealloc、freeを1つの関数で処理するためのもの。
 拡張前のメモリから値を引き継ぐのに、memcpyで新しいサイズの全域をコピーしている。かなり無駄の多い処理だが、拡張前の大きさを調べるのが面倒だったので、今回はこういう感じにした。
 mallocで確保したメモリの初期値は不定でいいので、範囲外からコピーされた値が入っていても問題ない。ただ、バッファオーバーランによる他スレッドのデータを読まれたりとか、そういうことは気にしてない。あと、MMUとかついてると問題かも。でもSTM32F4には無いのでキニシナイ。そもそもMMUがある環境ならこんな面倒なことは(以下略。


 次に、lauxlib.cのl_allocを書き換える。

static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
  (void)ud; (void)osize;  /* not used */
  return lua_malloc(ptr, nsize);
}

 freeとかの処理はlua_mallocでラッパーできてるから、単純に呼び出すだけ。


 あとは、コンソールのコマンドがstrという文字列バッファに入ってるとすれば、以下のような処理になる。

if (!strncmp(str, "lua ", 4))
{
 osDelay(50);

 lua_State *L = luaL_newstate();
 luaL_openlibs(L);

 do
 {
  const char *code = str + 4;

  if (luaL_loadbuffer(L, code, strlen(code), "code"))
  {
   fprintf(stderr, "lua couldn't parse '%s': %s.\n", code, lua_tostring(L, -1));
   lua_pop(L, 1);
   break;
  }

  if (lua_pcall(L, 0, 1, 0))
  {
   fprintf(stderr, "lua couldn't execute '%s': %s.\n", code, lua_tostring(L, -1));
   lua_pop(L, 1);
   break;
  }
 } while (0);

 lua_pop(L, lua_gettop(L));

 lua_close(L);
}

 この例では、コマンドを受けるたびにLuaインタラプタを初期化してコードを実行する。

 "lua print 'hello'"のような文字列が入力されれば、ちゃんとhelloと表示される。"lua print(1+2)"とすれば、3と表示される。"lua print(math.sqrt(2))"とすれば平方根の計算もできるはずだが、ウチの環境だと浮動小数点のprintfが正常に動かないので、動作確認できていない。
 ウチの環境、不具合多いなぁ。


 とりあえず、Luaは動いているようだが、かなり大量のメモリが必用。
 "lua print 'hello world' print(3*5)"という簡単なコードでも、20KiBほどのメモリを使っている。凄まじい。

 ま、まずはLuaの動作確認ができたので良しとする。
 コンパイルやフラッシュへの書き込み無しにコードが動くのは結構楽しい。

1 件のコメント:

  1. ありがとうございます、記事は私を手伝いました!私もLuaとFreeRTOSとSTM32-F7を使ってみるでしたが「メモリが十分ではない」と言った。その上、「#define LUA_32BITS」とluaconf.hに書かなくてはなりませんでした。カナダからこんにちは!

    返信削除