Nuttxをnucleo-g474上で動作させるようにする作業をやっている所なのですが、今のところ、DMAは動作しませんが、GPIOとADCとSPI(SPISDにてsd cardをmount, RW)はとりあえず動いたよ確認できたので、今度はI2Cの動作を確認するために、NuttxのシステムアプリであるI2CTOOLを動作させることにしました。その前にまず、I2Cデバイスが必要なのですが、手元に適当なものがなかったので、Arduino Uno R3をi2cスレーブにしてみました。
さらに、動作確認のためすでにサポートされているNucleo-F446REでI2CTOOL(i2cマスターのスキャンツール)を動かしてみたのですが、以下の様な結果となりました。
1. SDA/SCLへのプルアップがないと動作しない。(NuttxのソースコードではGPIOはGPIO_OPENDRAIN)
2. Arduinoのスキャンツール(マスター)を動作させないと、I2CTOOLではスキャンできない。
2. マスターのNucleo-64のSDAとSCLは5Vを3.3KΩでプルアップしたところ、I2CTOOLにてスキャンに成功。
3. USB給電のないArduinoがバス上に接続されていると、スキャンに失敗する。
給電されていないArduinoがあるとスキャンできない点以外はおおむねOKかなという結果でした。
参考までに、Arduino I2C スレーブのコードは以下の通りです。
boards/arm/stm32/nucleo-f446re/include/board.h
#include <Wire.h>
byte b=0;
void setup() {
Wire.begin(0xf);// Slave ID #f
pinMode(SDA, INPUT);
pinMode(SCL, INPUT);
Wire.onRequest(requestEvent);
}
void loop() {
}
void requestEvent() {
Wire.write(b++);
}
なお、今回はArduinoのIOが5Vなので、SDA/SCLへはNucleo側の5Vを3.3KΩでプルアップした結果ですが、プルアップがないと動作しないところから察するに、プルアップ抵抗値の設定などをきちんとしないといけない様子です。が、とりあえず本稿では、備忘録としてNuttx/I2CTOOLの設定を以下に記述したいとおもいます。
まず、i2ctoolの呼び出しコードを設定します。
boards/arm/stm32/nucleo-f446re/src/stm32_appinit.c
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: board_i2c_register
*
* Description:
* Register one I2C drivers for the I2C tool.
*
****************************************************************************/
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
static void board_i2c_register(int bus)
{
struct i2c_master_s *i2c;
int ret;
i2c = stm32_i2cbus_initialize(bus);
if (i2c == NULL)
{
syslog(LOG_ERR, "ERROR: Failed to get I2C%d interface\n", bus);
}
else
{
ret = i2c_register(i2c, bus);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: Failed to register I2C%d driver: %d\n",
bus, ret);
stm32_i2cbus_uninitialize(i2c);
}
}
}
#endif
/****************************************************************************
* Name: board_i2ctool
*
* Description:
* Register I2C drivers for the I2C tool.
*
****************************************************************************/
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
static void board_i2ctool(void)
{
#ifdef CONFIG_STM32_I2C1
board_i2c_register(1);
#endif
#ifdef CONFIG_STM32_I2C2
board_i2c_register(2);
#endif
#ifdef CONFIG_STM32_I2C3
board_i2c_register(3);
#endif
}
#endif
// 中略
int board_app_initialize(uintptr_t arg)
{
// 中略
#if defined(CONFIG_I2C) && defined(CONFIG_SYSTEM_I2CTOOL)
board_i2ctool();
#endif
// 中略
}
次に、SDA/SCLピンの定義ですが、今回はNucleo-F446REのARDUINO互換のピンを使う設定を行います。使用するピンは以下の通りです。
D14 I2C1_SDA PB9 D15 I2C1_SCL PB8Nuttx側で、上記のピンをI2C1として使う場合、以下の設定をします。
boards/arm/stm32/nucleo-f446re/include/board.h
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2 #define GPIO_I2C1_SDA GPIO_I2C1_SDA_2なお、Nucleo-G474REでは、定義が異なり、以下の様になります。 boards/arm/stm32/nucleo-g474re/include/board.h
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_3 #define GPIO_I2C1_SDA GPIO_I2C1_SDA_3続いて、Nuttx build configurationです。今回はnshをベースにしていますので、make distcleanした後、
tools/configure.sh nucleo-f446re/nsh make menuconfigとします。設定は以下の通りです。(参考までに、make menuconfig後、/を入力するとサーチモードになるのでコンフィグ項目を検索できます。)
CONFIG_STM32_I2C1 [=y] CONFIG_I2C_DRIVER [=y] CONFIG_SYSTEM_I2CTOOL [=y] CONFIG_NSH_ARCHINIT [=y] CONFIG_BOARD_LATE_INITIALIZE [=y] CONFIG_BUILTIN [=y] CONFIG_NSH_BUILTIN_APPS [=y]ちなみに、g474の方は、以下の設定が必要でした。
CONFIG_STM32_I2CTIMEOMS=1000 CONFIG_STM32_I2CTIMEOTICKS=1000g474でもfrequency は100000または200000で、スキャンできました。スキャンに成功すると以下の様になります。
nsh> i2c dev -b1 -f 100000 0x00 0x7f
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- 06 -- -- -- -- 0b -- -- -- 0f
今回は以上です。それでは。
コメント
コメントを投稿