ZephyrのI2C scannerサンプルを動かしてみる

はじめに

I2Cデバイスを使いたいので、手始めにZephyrのI2C scannerサンプルを動かしてみます。 ターゲットSoCはnRF52840です。

サンプルプロジェクトを確認

|> zephyr/samples/drivers/i2c_scanner

nRF52x系は、overlayする設定ファイルが用意されています。

|> overlay-nrf52.nrf

CONFIG_I2C_NRFX=y
CONFIG_I2C_0=y

今回は、I2C1を使うので、I2C1に変更しておきます。

CONFIG_I2C_NRFX=y
CONFIG_I2C_1=y

ソースコードをざっと確認します。

#include <errno.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <device.h>
#include <i2c.h>

#ifdef ARDUINO_I2C_LABEL
#define I2C_DEV ARDUINO_I2C_LABEL
#else
#define I2C_DEV "I2C_1"
#endif

/**
 * @file This app scans I2C bus for any devices present
 */

void main(void)
{
    struct device *i2c_dev;

    printk("Starting i2c scanner...\n");

    i2c_dev = device_get_binding(I2C_DEV);
    if (!i2c_dev) {
        printk("I2C: Device driver not found.\n");
        return;
    }

    for (u8_t i = 4; i <= 0x77; i++) {
        struct i2c_msg msgs[1];
        u8_t dst;

        /* Send the address to read from */
        msgs[0].buf = &dst;
        msgs[0].len = 0U;
        msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

        if (i2c_transfer(i2c_dev, &msgs[0], 1, i) == 0) {
            printk("0x%2x FOUND\n", i);
        }
    }
}

全アドレス順番にreadしていって、値が読めたら、見つかった判定しています。 まぁこんなもんでしょう。

動作確認

動かしてみましょう。

Starting i2c scanner...
[00:00:10.125,366] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
[00:00:22.562,713] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
[00:00:25.425,384] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
[00:00:29.490,722] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
[00:00:31.948,394] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
[00:00:33.013,885] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
...
[00:01:22.722,534] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
--- 18 messages dropped ---
[00:01:22.725,891] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
...

ありゃ、途中でRTTのメッセージがdropしていますね。 I2Cのアドレスを一通り舐めていて、デバイスが見つからなかった時のエラーが多すぎる、ということなのでしょう。

一応見落としがないようにするため、GDBを使って手動でループを回します。

...
[00:00:14.157,165] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
0x51 FOUND
[00:00:14.360,198] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
...
[00:00:16.207,885] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
0x64 FOUND
[00:00:16.414,978] <err> i2c_nrfx_twi: Error 195952641 occurred for message 0
...

今、繋がっているI2Cデバイスのアドレスは、0x51と0x64なので、OKですね!