Zephyr×Rustのインテグレーションにチャレンジ!⑪~UART Driver 受信編~

はじめに

ZephyrとRustのインテグレーションに挑戦しています。

RustでデバイスDriverを作っていきます。 まずは、QEMUのUARTをターゲットにします。 QEMUのUARTデバイスガバガバで、初期化を行わなくてもデータ送受信ができるので、敷居が低いです。

UART受信

基本は、以前の記事でUART Driverの受信処理を作ったときと同じです。

tomo-wait-for-it-yuki.hatenablog.com

動作確認も、ZephyrのShellが動くかどうか、を見ていきましょう。

実装

まず、APIpoll_inを埋めます。

static UART_API: uart_driver_api = uart_driver_api {
    poll_out: Some(rust_poll_out),
-    poll_in: None,
+    poll_in: Some(rust_poll_in),
    err_check: None,
    configure: None,
    config_get: None,
};

poll_inを実装します。あとでどちゃくそリファクタリングしましょう。 (と言ってもCからのコールバックなので、それほどきれいにできないかもしれませんが)

// Flag register
const FR: u32 = 0x18;
const UARTFR_RXFE: u32 = 0x00000010;

unsafe extern "C" fn rust_poll_in(_dev: *mut device, p_char: *mut cty::c_uchar)
        -> cty::c_int
{
    let flags = *((zephyr::UART_0_BASE_ADDRESS + FR) as  *const u32);
    if (flags & UARTFR_RXFE) != 0 {
        return -1;  // don't have RX data.
    }

    *p_char = *(zephyr::UART_0_BASE_ADDRESS as *mut u32) as cty::c_uchar;
    return 0;
}

Rustの実装はこれだけです!

動作確認

ZephyrのShellをinterrupt drivenを無効化した上で、有効化します。

$ ninja run
 ninja run
[0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-m3
qemu-system-arm: warning: nic stellaris_enet.0 has no peer
***** Booting Zephyr OS 1.13.99 *****
Hello from Rust!

uart:~$ 
  clear    help     history  resize   shell
uart:~$ help
Please press the <Tab> button to see all available commands.
You can also use the <Tab> button to prompt or auto-complete all commands or its subcommands.
You can try to call commands with <-h> or <--help> parameter for more information.

Rustで書いたZephyrのDriverが動いています!感動!