<< 2020.10 >>
[日記]
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

2020 年 6 月 22 日 (月)

Arduino Nano Every のクロック

Arduino Nano Every を買った.

IMG_20200620_151928.jpg

Arduino Nano / Nano Every を載せて格安中華 LCD と接続できる基板を作ったので,載せてみた.

IMG_20200620_223939.jpg

I2C に温度センサをつないで,ついでに時刻を表示させてみた.

で,4時間ほど経つと…

IMG_20200621_060332 (36d4e615).jpg

表示時刻が 24 秒も進んでいる.

Nano Every の回路図を見てみると,水晶発振子が無い. マイコン内蔵の発振器を使っていて,クロック周波数が不正確なのだろう. Nano のほうには水晶発振子は乗っているので,Nano Every の非互換の1つと言えるだろう.

データシートを読む

ここで Arduino Nano Every に載ってる ATmega4809 のデータシートを読むと

  • 内蔵発振器の周波数の補正値は,工場出荷時に fuse (ライトワンスのメモリ)に書かれている
  • UART のボーレートジェネレータでの補正値を使った補正例

が載っている.

プログラムを読む

で,ArduinoIDE 側の SDK のソースコードを読んでみると

  • クロック周波数のズレに横断的に対応するようなコードがあるけど,機能していない
  • UART には独自に補正がかかっている
  • tick timer には補正無し

という状況.

強引に補正してみる

というわけで,sketch の setup() 内で強引に補正をかけてみた.

  //
  // millis() speed adjust. for Arduino Nano Every
  //
  extern uint16_t millis_inc, fract_inc;
  if ( ( millis_inc == 1 ) && ( fract_inc == 24 ) ) {
    uint32_t tick_us = millis_inc*1000L + fract_inc;
    int8_t sigrow_val = SIGROW.OSC16ERR5V;

    tick_us = ( tick_us*1024 + ( 1024 + sigrow_val )/2 ) / ( 1024 + sigrow_val );
    // adjust manually
    // tick_us += 1; // faster
    // tick_us -= 1; // slower

    millis_inc = tick_us / 1000;
    fract_inc  = tick_us % 1000;
  }

未補正時の +6 sec/hour の時計の狂いが +3 sec/hour 程度に改善された. さらに手動補正で tick_us -= 1 してみると,1時間経過しても「やや遅れてるな」という程度まで追い込めた.

2020 年 6 月 19 日 (金)

ArduinoIDE 上の ESP32 プログラムの JTAG デバッグ

以前,試しに FusionPCB で作った基板を引っ張り出して組み立てました.

IMG_20200619_083014.jpg

ESP32 DevkitC に JTAG アダプタを接続するゲタです.

19 ピンの足の長い連結ピンソケットが売られてないので,40 ピンの連結ピンソケットの不要な足を刈り込んで使いました.

ESP-IDF 環境での JTAG デバッグは前にネタにしたので,今回は ArduinoIDE 環境でのプログラムのデバッグに挑戦してみます.

環境

PC

Linux PC 上での開発を前提に書きますが,道具立ては Windows でも一緒なので,Windows 上での手順としても参考になると思います.

JTAG アダプタ

Olimex の ARM-USB-TINY-H を使いました. ピンヘッダの配列は ARM JTAG20 というやつです. OpenOCD が対応している ARM JTAG 20 配列のアダプタなら,たぶん他のものでも使えると思います(未確認).

ESP-IDF 環境のインストール

ArduinoIDE 環境にも ESP32 のツールチェーンは入ってますが,ESP32 対応の OpenOCD が無いので,ESP-IDF 環境もインストールします. ツールチェーンが2組インストールされることになってしまうけど,気にしないことにします.

このページを参考にインストールしましょう.

接続

ピンソケットに ESP32 基板を刺し,ピンヘッダに JTAG アダプタを接続します.

IMG_20200619_083125.jpg

サンプルプログラム

ArduinoIDE 上でプログラムを書きます.

スクリーンショット_2020-06-19_08-26-10.png
void setup() {
  // put your setup code here, to run once:
  Serial.begin ( 115200 );
}

void loop() {
  // put your main code here, to run repeatedly:
  for ( int i = 10; i >= 0; --i ) {
    Serial.println ( i );
    delay ( 1000 );
  }
}

カウントダウンを表示するだけのプログラムです.

で,コンパイルする前に

ファイル - 環境設定 - 設定 で「より詳細な情報を表示する」

にチェックを入れておきます. ArduinoIDE の下の画面にコンパイル時のコマンドラインが表示されるようになるので,ELF ファイルがどこに生成されるか確認できます.

コンパイル・書き込みを実行し,シリアルモニタを開いて,ターゲット上でカウントダウンが動いてることを確認します.

OpenOCD の起動

OpenOCD を起動します.

$ cd ~/espressif/tools/openocd-esp32/v0.10.0-esp32-20200420/openocd-esp32
$ bin/openocd -f share/openocd/scripts/interface/ftdi/olimex-arm-usb-tiny-h.cfg \
        -f share/openocd/scripts/board/esp-wroom-32.cfg \
        -c 'adapter_khz 1000' -c 'gdb_port 3333'
Open On-Chip Debugger  v0.10.0-esp32-20200420 (2020-04-20-16:15)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
WARNING: boards/esp-wroom-32.cfg is deprecated, and may be removed in a future release.
Info : Configured 2 cores
adapter speed: 1000 kHz

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 1000 kHz
Info : JTAG tap: esp32.cpu0 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : JTAG tap: esp32.cpu1 tap/device found: 0x120034e5 (mfg: 0x272 (Tensilica), part: 0x2003, ver: 0x1)
Info : esp32: Debug controller 0 was reset.
Info : esp32: Core 0 was reset.
Info : esp32: Debug controller 1 was reset.
Info : esp32: Core 1 was reset.
Info : cpu0: Detected debug stubs @ 3ffc0c64
Info : Listening on port 3333 for gdb connections

GDB の起動

gdb は,ArduinoIDE のツールチェーンにも ESP-IDF のツールチェーンにも含まれています. ESP-IDF ツールチェーンのほうがパスが通ってるので,こちらを使いました.

で,今回は gdb のフロントエンドに gdbgui というものを使いました. web ブラウザ上にに表示してくれます.

$ gdbgui -g xtensa-esp32-elf-gdb /tmp/arduino_build_795862/sketch_jun19a.ino.elf

もちろん,普通に gdb を起動しても問題ありません.

スクリーンショット_2020-06-19_08-25-40.png

起動したら以下のコマンドを打ち込みます.

(gdb) target remote localhost:3333
(gdb) mon reset halt
(gdb) hb loop
(gdb) c

あとは,変数の内容を確認したり,ステップ実行したりと,セルフ開発時の gdb と同じような感覚で使えます. ただし,ブレークポイントを仕掛けるときは,b ではなく hb コマンドを使います. ターゲット CPU 内部のデバッグ回路を使用したハードウェアブレークポイントコマンドです. ESP32 ではフラッシュ ROM 上のプログラムを RAM 上にロードせずに実行しているので,trap 命令を埋め込めないためです.

2020 年 6 月 18 日 (木)

Arduino で printf() を使いたい

という話を目にしたので,ちょろりと書いてみた.

コード

以下のコードを sketch の void setup() の前にコピペするだけです.

size_t devprintf ( Print *dev, const char *fmt, ... )
{
  va_list ap;
  char buf[80];

  va_start ( ap, fmt );
  vsnprintf ( buf, sizeof(buf), fmt, ap );
  va_end ( ap );

  return dev->print ( buf );
}

長さも長さなので,著作権うんぬんは特に主張しません. 改変・再配布は自由にどうぞ.

使用例

シリアル出力と LCD に秒数を表示し続けるプログラムです.

#include <LiquidCrystal.h>

size_t devprintf ( Print *dev, const char *fmt, ... )
{
  va_list ap;
  char buf[80];

  va_start ( ap, fmt );
  vsnprintf ( buf, sizeof(buf), fmt, ap );
  va_end ( ap );

  return dev->print ( buf );
}

LiquidCrystal lcd ( 2, 3, 4, 5, 6, 7, 8 );

void setup() {
  Serial.begin(115200);
  lcd.begin ( 16, 2 );
}

void loop() {
   unsigned s = millis() / 1000;
    
   devprintf ( &Serial, "%05u sec.\r\n", s );
   
   lcd.setCursor ( 0, 0 );
   devprintf ( &lcd, "%05u sec.", s );
    
   delay ( 1000 );
}

使っているのは loop() 内に2箇所あって

devprintf ( &Serial, "%05u sec.\r\n", s );

devprintf ( &lcd, "%05u sec.", s );

です.

シリアル出力だけでなくて,標準ライブラリを使った LCD 出力にも使えます. ちなみに LCD は,こんなものを使いました.

実行すると,シリアルからはこんな↓出力が

スクリーンショット_2020-06-18_11-29-39.png

LCD にはこんな↓出力が表示されます.

IMG_20200618_105429.jpg

RSS

http://jr0bak.homelinux.net/~imai/pukiwiki/pukiwiki.php?cmd=rss&ver=1.0 で RSS を取得できますが,Wiki 全体の RSS になってしまいます. 細かいことは気にしないでね.

リンク

この日記へのリンクはご自由にどうぞ.


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-05-05 (火) 06:10:37 (4190d)