ラベル Arduino の投稿を表示しています。 すべての投稿を表示
ラベル Arduino の投稿を表示しています。 すべての投稿を表示

2021年4月30日金曜日

ESP32 is rebooting eternal by "rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)" on terminal

ESP32 or NodeMCU or other espressif ESP32 family devices are repeat reboot and output "rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)" on terminal.

ESP32でArduino IDEからプログラムを書き込むと、

"rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)"

と繰り返しターミナルで出力し続け、再起動を繰り返すときの対処方法。

■目次 / Table of contents


■環境 / Environment

ESP32-WROOM-3/DEVKITV1

Windows (and All host OS)

Arduino 1.8.13 +ESP32 Dev Module

以下のモジュールも同様の症状が報告されています
The same symptoms have been reported in the following modules.

    NodeMCU-32S
    ESP32-CAM


■症状 / symptoms

ArduinoIDE上での書き込みは正常に終了する。
Writing process is complete from Arduino IDE.

動作しているはずなのにスケッチが動いていない。
Maybe working but Sketch is not working. 

ESP32のLEDがずっと点滅し続ける。
The indicator led on ESP32 is blinking eternal.

ESP32をUSBでPCに接続しターミナルでボーレート115200にて接続すると、次のようなメッセージを表示し続ける。
Following messages are logging on terminal that connected in 115200bps.


<rebooting eternally with rest:03x (SW_RESET)>

rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6360
entry 0x400806b4
ets Jun 8 2016 00:22:57

:繰り返し/repeat


ちなみにターミナル上での正常な出力結果は次のようになります。
Following messages are displayed in normal running on terminal.

<Normally messages>

I⸮⸮⸮oets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6360
entry 0x400806b4


■処置 / treatment

Arduinoのフラッシュメモリの書き込み速度を
80MHz->40MHz
にする
Slowdown "Flash Frequency" to 40MHz from 80MHz on Arduino IDE.
 [Tool]-[Flash Frequency]-[40MHz]


Select 40MHz from 80MHz on Arduino IDE


インターネット上で対処方法がいくつか掲載されていますが、いずれも症状は改善しませんでした。今回原因だったのはフラッシュメモリへの書き込み速度が高速すぎたためだったようです。Arduinoからの書き込み自体は問題なく正常に動作したかのようなメッセージが表示されますが、実際には起動できませんでした。
This problem is caused by TOO FAST writing speed. But on Arduino IDE, All writing procedure is normally finished and verify is normally complete too!
   
Normally finished messages
C:\Users\Owner\AppData\Local\Temp\arduino_build_931094/ESP32LEDTest.ino.partitions.bin 
esptool.py v3.0-dev
Serial port COM10
Connecting......
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 24:6f:28:16:ba:d0
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 512000
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 5957.9 kbit/s)...
Hash of data verified.
Compressed 18656 bytes to 12053...
Writing at 0x00001000... (100 %)
Wrote 18656 bytes (12053 compressed) at 0x00001000 in 0.3 seconds (effective 563.2 kbit/s)...
Hash of data verified.
Compressed 198944 bytes to 102964...
Writing at 0x00010000... (14 %)
Writing at 0x00014000... (28 %)
Writing at 0x00018000... (42 %)
Writing at 0x0001c000... (57 %)
Writing at 0x00020000... (71 %)
Writing at 0x00024000... (85 %)
Writing at 0x00028000... (100 %)
Wrote 198944 bytes (102964 compressed) at 0x00010000 in 2.2 seconds (effective 712.7 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 128...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.0 seconds (effective 1890.5 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...





■その他の症状1 / Other symptoms2

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)

Bluetooth やWifiを使用した時、上記メッセージが表示される。
Above messages are displayed when you use onboard peripherals like bluetooth and  wifi.
<rebooting eternally with rst:0x10 (RTCWDT_RTC_RESET)>
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
ets Jun  8 2016 00:22:57
と表示が出る。Panic…と表示が出る。

電源が足りていないかもしれません。私の場合、LEDの点滅は問題なく動作するのに、Bluetoothを使うとこのメッセージが出ました。
Led blinking test is normal. But Bluetooth device is used then not working. 

結局、WindowsPCのUSB type-Bから給電していたところ電源容量が足らず、電力不足から電圧低下、動作不安定となり、再起動していたみたいでした。
In the end, Power supply is not insufficient from PC's USB-B port.

電源を別系統から給電するように回路を変更したところ正常動作しました。
This problem solved by add other power supply from AC switching power supply.

■その他の症状2/ Other symptoms2

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT):0x10 

<WiFi.h>を使用した時、上記メッセージが表示される。
Above messages are displayed when you use onboard peripherals like wifi.
エラーメッセージが表示されず正常動作するときもある。
Occasionally run as normal.

<rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT):0x10>
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1324
load:0x40078000,len:7788
ho 0 tail 12 room 4
load:0x40080400,len:6448
entry 0x400806e8
assertion "false && "item should have been present in cache"" failed: file "/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/nvs_flash/src/nvs_item_hash_list.cpp", line 85, function: void nvs::HashList::erase(size_t)
abort() was called at PC 0x400ec2af on core 0

Backtrace: 0x400881d4:0x3ffcfba0 0x400882d3:0x3ffcfbc0 0x400ec2af:0x3ffcfbe0 0x400f5d2c:0x3ffcfc10 0x400f63e6:0x3ffcfc30 0x400f6715:0x3ffcfc80 0x400f57dc:0x3ffcfce0 0x400f5336:0x3ffcfd30 0x400f53cf:0x3ffcfd50 0x400f541a:0x3ffcfd70 0x400e6318:0x3ffcfd90 0x4012d993:0x3ffcfdb0 0x400edc5e:0x3ffcfde0

Rebooting...

バグのようですが、フラッシュメモリ内のデータを参照しているところが初期化されていないか、書き込めていないようです。
フラッシュメモリをクリアすることで治りました。
Maybe bug of Arduino C compiler for ESP32.
Let's try to Clear Flash Memory.


フラッシュメモリをクリアするにはesptool.exeを実行します。
Run esptool.exe for clear in Flash Memory.

esptool.exe  --chip esp32  --port COM7  --baud 921600 erase_flash

You need to replace port number of your environment.


追加 その他の症状2/ Other sysmtoms2 2023.06.30

2019年6月20日木曜日

ArduinoIDEでCとアセンブリ同時出力したい

この記事は以下の環境の話です。
  Arduino UNO/Nano/Mega
  AVR 328P
  ArduinoIDE 1.8.9 (非WindowsStore版)
  Windows 10 Pro/Home Version 1903

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

Arduino Uno Rev3
価格:3234円(税込、送料別) (2019/6/26時点)


■アセンブリ出力が欲しい

~発端~
ArduinoIDEでプログラムを作成していると、switch-caseで10個ぐらい分岐したときに8つ目以降で分岐できないものが出てきたりして、原因を掴むためにアセンブリ出力がどうしても欲しくなった。(アセンブリ時点で分岐項目がなくなっていたのでバグのようだった)
その後、カウンターで時計のプログラムを書いているとどうしても時間がずれてくる。出力された機械語がどうなっているかでクロック消費量が違ってくるのでそこも考慮してプログラムを書かないと正確な時計にならない。

というわけで、
 Cとアセンブラ同時出力があればいろいろわかって便利がいいぞ!
となりまして、いろいろネットをさまよっていると、これまたいろいろ方法があるわけで。Evernoteに保存していたネットの情報をもとにもう一度その手順を追おうとしてももう手元の情報だけで手順がわからない。
ほんと開発メモは大事ですね。

次のコードのアセンブリを出力したいと思います。

[echo.ino]
int lamp = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial.write(inByte);
    digitalWrite(LED_BUILTIN, (lamp ++) & 1);   // turn the LED on or off
  }
}

【手順0】中間ファイルを出力させる preferences.txt

いずれの方法でも、ビルド時に出力される中間ファイルを入手できなければなにもできません。
デフォルトの保存場所は
C:\Documents and Settings\<ユーザー名>\Local Settings\Temp\build*.tmp
だったりしますが、出力先を指定しておくと便利です。
中間ファイルの出力先の変更は、環境設定を変更しなければなりません。この環境設定はArduinoIDEの中にはなく、設定ファイル[preferences.txt]に記載されています。このファイルの保存場所は次の所になります。

[preferences.txt]の場所
%UserProfile%\AppData\Local\Arduino15\preferences.txt

ユーザーがOwnerならば
C:\Users\Owner\AppData\Local\Arduino15\preferences.txt
あたりになります。

ArduinoIDEを終了してから編集します。
次の行を追加します。
[preferences.txt]
build.path=%UserProfile%\Arduino\build

もともと build.path=... は存在しないので、最終行でもいいので追加します。

ArduinoIDEでなにかスケッチをビルドすると
%UserProfile%\Arduino\build
内にファイルが出力されます。

スケッチのあるフォルダに出力する方法もあったようですが。
[preferences.txt]
build.path=build

参考にしたホームページには、上記のような記述でスケッチのフォルダ内にbuildフォルダを作成し保存する。とあったのですが、私の環境ではコンパイラの存在する場所のbuildフォルダに出力しようとし、動作しませんでした。どうもビルド時の動作を見ると、このbuildフォルダにスケッチフォルダの中身全てをコピーしてから作業するようで、スケッチフォルダにいろいろファイルを作成しているとビルド動作が遅くなります。
ただ、今後のアップデートでは、この記述でも動作するかもしれません。

【方法1】avr-objdump -S を使ってアセンブリを出力する


中間ファイルの出力先にelfファイルが出力されています。avr-objdumpを使うことで、このelfファイルからCのソースコード付きアセンブリを出力できます。
スイッチに-Sをつけてアセンブリを出力します。

avr-objdump -S [スケッチ名.ino.elf]  > [出力ファイル名]

実際のコマンドは次のようになります。
インストール環境によりパスは変わると思います。

C:/Program Files (x86)/Arduino/hardware/tools/avr/bin/avr-objdump -S echo.ino.elf > echo.ino.S

実際に出力されたアセンブリはこちら。
[echo.ino.S]
echo.ino.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0: 0c 94 5d 00 jmp 0xba ; 0xba <__ctors_end>
   4: 0c 94 85 00 jmp 0x10a ; 0x10a <__bad_interrupt>
   8: 0c 94 85 00 jmp 0x10a ; 0x10a <__bad_interrupt>
 :
   :
void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  if (Serial.available()) {
 5a8: 84 e1        ldi r24, 0x14 ; 20
 5aa: 91 e0        ldi r25, 0x01 ; 1
 5ac: 0e 94 e6 00 call 0x1cc ; 0x1cc <_ZN14HardwareSerial9availableEv>
 5b0: 89 2b        or r24, r25
 5b2: 09 f4        brne .+2      ; 0x5b6 <main+0x140>
 5b4: 58 c0        rjmp .+176    ; 0x666 <main+0x1f0>
    int inByte = Serial.read();
 5b6: 84 e1        ldi r24, 0x14 ; 20
 5b8: 91 e0        ldi r25, 0x01 ; 1
 5ba: 0e 94 c4 00 call 0x188 ; 0x188 <_ZN14HardwareSerial4readEv>
    virtual void flush(void);
    virtual size_t write(uint8_t);
    inline size_t write(unsigned long n) { return write((uint8_t)n); }
    inline size_t write(long n) { return write((uint8_t)n); }
    inline size_t write(unsigned int n) { return write((uint8_t)n); }
    inline size_t write(int n) { return write((uint8_t)n); }
 5be: 68 2f        mov r22, r24
 5c0: 84 e1        ldi r24, 0x14 ; 20
 5c2: 91 e0        ldi r25, 0x01 ; 1
 5c4: 0e 94 1e 01 call 0x23c ; 0x23c <_ZN14HardwareSerial5writeEh>
    Serial.write(inByte);
    digitalWrite(LED_BUILTIN, (lamp ++) & 1);   // turn the LED on or off
 5c8: 20 91 12 01 lds r18, 0x0112 ; 0x800112 <__data_end>
 5cc: 30 91 13 01 lds r19, 0x0113 ; 0x800113 <__data_end+0x1>
 5d0: c9 01        movw r24, r18
 5d2: 01 96        adiw r24, 0x01 ; 1
 5d4: 90 93 13 01 sts 0x0113, r25 ; 0x800113 <__data_end+0x1>
 5d8: 80 93 12 01 sts 0x0112, r24 ; 0x800112 <__data_end>
 5dc: f7 01        movw r30, r14
 5de: 84 91        lpm r24, Z
uint8_t bit = digitalPinToBitMask(pin);
 5e0: fe 01        movw r30, r28
 5e2: 94 91        lpm r25, Z
uint8_t port = digitalPinToPort(pin);
 5e4: f8 01        movw r30, r16
 5e6: 44 91        lpm r20, Z
volatile uint8_t *out;

if (port == NOT_A_PIN) return;
 5e8: 44 23        and r20, r20
 5ea: 09 f4        brne .+2      ; 0x5ee <main+0x178>
 5ec: 3c c0        rjmp .+120    ; 0x666 <main+0x1f0>

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
 5ee: 88 23        and r24, r24
 5f0: 39 f1        breq .+78      ; 0x640 <main+0x1ca>
//

これこれ!非常に読みやすいですね。
参考にしたのは以下のページです。ありがとうございました。



以下、Cのソースコードは一緒に出てきませんがアセンブリを出力する他の方法です。

【方法2】Cコンパイラからアセンブリを直接出力させる

もっと簡単な方法で出力できたような気がするのですが、Cコンパイラの出力からアセンブリを直接出力させる方法です。面倒くさいですがいろいろ応用ができそうなのでここに書いておきます。

以下スケッチファイルを[echo.ino]として説明します。
次のようにオプションを指定してビルドするとアセンブリを出力できます。

"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -S -g  -Os -std=gnu++11  -Wno-error=narrowing  -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.cpp" -o "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.S"

このコマンドでbuildフォルダにアセンブリファイルを出力します。

このコマンドはビルドオプション"-S -g Os -o -std=gnu++11  -Wno-error=narrowing"が必須になります。また、MCUの種類、速度、ArduinoNo等を指定していますが、このあたりは環境が違うと異なってくるパラメーターです。このパラメーターを取得するにはArduinoIDEよりコンパイルオプションを表示させて流用すると楽です。

ArduinoIDE>ファイル>環境設定
  より詳細な情報を表示する[v]コンパイル

上記画面のコンパイルにチェックをいれてビルドします。

ビルドすると出力窓にコンパイルオプション付きのコマンドが出力されていきますので、それをすべてコピーし、メモ帳などに貼り付けて[スケッチ名.ino.cpp]を探します。この場合ですと、[echo.ino.cpp]を探します。

"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR  "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.cpp" -o null

オプション追加 -S
出力先追加 -o "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.S"
上記オレンジ部分のオプション削除

"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -S -g  -Os -std=gnu++11  -Wno-error=narrowing  -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.cpp" -o "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.S"

でビルドすると先の項目【中間ファイルを出力する】で設定した
[preferences.txt]
build.path=%UserProfile%\Arduino\build

パスにecho.ino.Sが出力されていると思います。
出力結果
[echo.ino.S]
 .file "echo.ino.cpp" __SP_H__ = 0x3e __SP_L__ = 0x3d __SREG__ = 0x3f __tmp_reg__ = 0 __zero_reg__ = 1 ; GNU C++11 (GCC) version 5.4.0 (avr) ; compiled by GNU C version 4.8.2, GMP version 5.0.2, MPFR version 3.0.0, MPC version 0.9       :
      :
  .text .Ltext0: .cfi_sections .debug_frame .global setup .type setup, @function setup: .LFB112: .file 1 "C:\\Users\\Owner\\Arduino\\echo\\echo.ino" .loc 1 3 0 .cfi_startproc /* prologue: function */ /* frame size = 0 */ /* stack size = 0 */ .L__stack_usage = 0 .LVL0: .LBB4: .LBB5: .file 2 "c:\\program files (x86)\\arduino\\hardware\\arduino\\avr\\cores\\arduino\\HardwareSerial.h" .loc 2 121 0 ldi r18,lo8(6) ; , ldi r20,lo8(-128) ; , ldi r21,lo8(37) ; , ldi r22,0 ; ldi r23,0 ; ldi r24,lo8(Serial) ; , ldi r25,hi8(Serial) ; , call _ZN14HardwareSerial5beginEmh ; .LVL1: .LBE5: .LBE4: .loc 1 5 0 ldi r22,lo8(1) ; , ldi r24,lo8(13) ; , jmp pinMode ; .LVL2: .cfi_endproc .LFE112: .size setup, .-setup .global loop .type loop, @function loop: .LFB113: .loc 1 7 0 .cfi_startproc /* prologue: function */ /* frame size = 0 */ /* stack size = 0 */ .L__stack_usage = 0 .LBB10: .loc 1 8 0 ldi r24,lo8(Serial) ; , ldi r25,hi8(Serial) ; , call _ZN14HardwareSerial9availableEv ; .LVL3: or r24,r25 ; breq .L2 ; , .LBB11: .loc 1 9 0 ldi r24,lo8(Serial) ; , ldi r25,hi8(Serial) ; , call _ZN14HardwareSerial4readEv ; .LVL4: .LBB12: .LBB13: .loc 2 133 0 mov r22,r24 ; , inByte ldi r24,lo8(Serial) ; , ldi r25,hi8(Serial) ; , .LVL5: call _ZN14HardwareSerial5writeEh ; .LVL6: .LBE13: .LBE12: .loc 1 11 0 lds r22,lamp ; D.4204, lamp lds r23,lamp+1 ; D.4204, lamp movw r24,r22 ; D.4204, D.4204 adiw r24,1 ; D.4204, sts lamp+1,r25 ; lamp, D.4204 sts lamp,r24 ; lamp, D.4204 andi r22,lo8(1) ; D.4205, ldi r24,lo8(13) ; , jmp digitalWrite ; .LVL7: .L2: ret .LBE11: .LBE10: .cfi_endproc .LFE113: .size loop, .-loop .global lamp .section .bss .type lamp, @object .size lamp, 2 lamp: .zero 2 .text       :
      :
一応このコードでアセンブリ出力とCのソース場所を確認することができるようになりました。Cのソース場所はディレクティブ.locで表しています.

.loc ファイル番号 行番号 [カラム] [オプション]

コンパイラよりアセンブリ出力は取得できました。が、Cのソースも記載されていないので大きなプログラムではなかなかアセンブリを追うのは難しくなってきます。
Cのソースもアセンブリ上に記載するのが目的でしたがとりあえずここまで。

【方法3】ビルドオプションを変更しアセンブリを出力する

 <<この方法はできませんでした>>
今後この方法の延長線上でできるようになるかもしれませんので、忘備録的に掲載しておきます。

基本的なコンパイルオプションは-S -gです


Arduino IDE ビルドオプションの保存場所
Windows10
    C:/Program Files (x86)/Arduino/hardware/arduino/avr/platform.txt
macOS Sierra 10.12.6
    /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/platform.txt

platform.txt一応バックアップを作ります。
platform_org.txtなどのようにしてコピーします。

ccompiler.c.flagsに-Sを追加します
[platform.txt]
compiler.c.flags=-c -g -S -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects
コンパイル時にエラーが出て停止してしまう上に、アセンブリも出力されません。

■ビルドオプション -save-temp を試す

<以下できなかった方法>

[platform.txt]
build.extra_flags=-save-temps

*.s *.iiファイルの保存先
C:\Users\Owner\AppData\Local\VirtualStore\Program Files (x86)\Arduino

ずいぶんと変なところ。C:\Users\Owner\AppData\Local\Arduinoあたりを探しても見つからないわけですね。

GCCのマニュアルより-save-temps

       -save-temps
       -save-temps=cwd
           Store the usual "temporary" intermediate files permanently; place
           them in the current directory and name them based on the source
           file.  Thus, compiling foo.c with -c -save-temps produces files
           foo.i and foo.s, as well as foo.o.  This creates a preprocessed
           foo.i output file even though the compiler now normally uses an
           integrated preprocessor.

           When used in combination with the -x command-line option,
           -save-temps is sensible enough to avoid over writing an input
           source file with the same extension as an intermediate file.  The
           corresponding intermediate file may be obtained by renaming the
           source file before using -save-temps.

           If you invoke GCC in parallel, compiling several different source
           files that share a common base name in different subdirectories or
           the same source file compiled for multiple output destinations, it
           is likely that the different parallel compilers will interfere with
           each other, and overwrite the temporary files.  For instance:

                   gcc -save-temps -o outdir1/foo.o indir1/foo.c&
                   gcc -save-temps -o outdir2/foo.o indir2/foo.c&

           may result in foo.i and foo.o being written to simultaneously by
           both compilers.

       -save-temps=obj
           Store the usual "temporary" intermediate files permanently.  If the
           -o option is used, the temporary files are based on the object
           file.  If the -o option is not used, the -save-temps=obj switch
           behaves like -save-temps.

           For example:

                   gcc -save-temps=obj -c foo.c
                   gcc -save-temps=obj -c bar.c -o dir/xbar.o
                   gcc -save-temps=obj foobar.c -o dir2/yfoobar

           creates foo.i, foo.s, dir/xbar.i, dir/xbar.s, dir2/yfoobar.i,
           dir2/yfoobar.s, and dir2/yfoobar.o.

実際に得た出力結果は以下の通り。抜粋。
[echo.ino.s]
        .file   "echo.ino.cpp"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
 ;  GNU C++11 (GCC) version 5.4.0 (avr)
 ;      compiled by GNU C version 4.8.2, GMP version 5.0.2, MPFR version 3.0.0, MPC version 0.9
  :
 .text .Ltext0: .section .gnu.lto_.profile.791a772d,"",@progbits .string "x\234ca`d`e`" .string "\222\255\214:" .string "\002;" .ascii "\276" .text .section .gnu.lto_.icf.791a772d,"",@progbits .string "x\234ca`d" .string "\0015\006\004`c\330\324q\373\034\033\343\277\231{\01613\335i\371\271\206\227e\313\263\377\247\331Y75,\275\313\315\266\343\314\214\305l\f" .ascii "ma\022F" .text .section .gnu.lto_.jmpfuncs.791a772d,"",@progbits .ascii "x\234}\216=\n\0021\020\205\347M\262Y\020\004\017`\341!\254\275" .ascii "\327VI\263\250\327\020\304\365\027,,\002v6\202\336@;\261\263" .ascii "\260\260]0\223u\265Z_\223\341\315\373^F\023H4\250\236\250\204"    :

.string "j\001"
.string ""
.string "digitalWrite"
.string ""
.ascii "\002"
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string "l\001"
.string ""
.string "_ZN14HardwareSerial9availableEv"
.string ""
.ascii "\002"
.string ""
.string ""
.string ""

ってな結果で。アセンブリは1行たりともでてこない。アセンブリはどこいった?www

[platform.txt]
build.extra_flags=-save-temps -fverbose-asm

-fverbose-asm ってオプションもあるので、こちらも同時に指定してみた。

GCCマニュアルより -fverbose-asm
       -fverbose-asm
           Put extra commentary information in the generated assembly code to
           make it more readable.  This option is generally only of use to
           those who actually need to read the generated assembly code
           (perhaps while debugging the compiler itself).

           -fno-verbose-asm, the default, causes the extra information to be
           omitted and is useful when comparing two assembler files.

           The added comments include:

           *   information on the compiler version and command-line options,

           *   the source code lines associated with the assembly
               instructions, in the form FILENAME:LINENUMBER:CONTENT OF LINE,

           *   hints on which high-level expressions correspond to the various
               assembly instruction operands.

           For example, given this C source file:

                   int test (int n)
                   {
                     int i;
                     int total = 0;

                     for (i = 0; i < n; i++)
                       total += i * i;

                     return total;
                   }

           compiling to (x86_64) assembly via -S and emitting the result
           direct to stdout via -o -

                   gcc -S test.c -fverbose-asm -Os -o -

           gives output similar to this:

                           .file   "test.c"
                   # GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
                     [...snip...]
                   # options passed:
                     [...snip...]

                           .text
                           .globl  test
                           .type   test, @function
                   test:
                   .LFB0:
                           .cfi_startproc
                   # test.c:4:   int total = 0;
                           xorl    %eax, %eax      # <retval>
                   # test.c:6:   for (i = 0; i < n; i++)
                           xorl    %edx, %edx      # i
                   .L2:
                   # test.c:6:   for (i = 0; i < n; i++)
                           cmpl    %edi, %edx      # n, i
                           jge     .L5     #,
                   # test.c:7:     total += i * i;
                           movl    %edx, %ecx      # i, tmp92
                           imull   %edx, %ecx      # i, tmp92
                   # test.c:6:   for (i = 0; i < n; i++)
                           incl    %edx    # i
                   # test.c:7:     total += i * i;
                           addl    %ecx, %eax      # tmp92, <retval>
                           jmp     .L2     #
                   .L5:
                   # test.c:10: }
                           ret
                           .cfi_endproc
                   .LFE0:
                           .size   test, .-test
                           .ident  "GCC: (GNU) 7.0.0 20160809 (experimental)"
                           .section        .note.GNU-stack,"",@progbits

           The comments are intended for humans rather than machines and hence
           the precise format of the comments is subject to change.

こんな結果がでる予定が。。。変わりませんねぇwww
じゃぁ。。。
コマンドプロンプトで

"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -S -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -save-temps -fverbose-asm "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Owner\\Arduino\\build\\sketch\\echo.ino.cpp" -o -

以下標準出力

        .file   "echo.ino.cpp"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
 ;  GNU C++11 (GCC) version 5.4.0 (avr)
 ;      compiled by GNU C version 4.8.2, GMP version 5.0.2, MPFR version 3.0.0, MPC version 0.9
 :
        .text
.Ltext0:
        .section        .gnu.lto_.profile.793b07df,"",@progbits
        .string "x\234ca`d`e`"
        .string "\222\255\214:"
        .string "\002;"
        .ascii  "\276"
        .text
        .section        .gnu.lto_.icf.793b07df,"",@progbits
        .string "x\234ca`d"
        .string "\0015\006\004`c\330\324q\373\034\033\343\277\231{\01613\335i\371\271\206\227e\313\263\377\247\331Y75,\275\313\315\266\343\314\214\305l\f"
        .ascii  "ma\022F"

一緒ですね。。。これどうなってるのかなぁ?

ちなみにCコンパイラーはここ
C:/Program Files (x86)/Arduino/hardware/tools/avr/bin/
    


この出力はなんなんでしょうね。
結局 avr_objdump を使えばできますってことでw


2019年6月7日金曜日

Arduinoにターミナルで接続するたびにリセットがかかる...困った

最近デジモノいろいろ買っているんですが、もっぱらArduinoで遊んでいます。

おいおい記事を書けたらと思うのですが…。

さて、Arduino UnoやArduino nanoでプログラミングを行うと、ターミナルに接続するたびにArduinoにリセットがかかってしまいます。これは、USB経由のシリアル通信でプログラムの書き込み終了後に、自動リセットを掛けるためのもののようです。
いろいろ調べていくと自動リセットを解除する方法がいくつかあるようです。

 方法1 ターミナルソフトでシリアルポートのDTR端子出力をH(Hi/1)にする
 方法2 Arduino のDTR信号のラインをカットする
     DTR-10uF-GNDと接続する
 方法3 ソフトウエアシリアルを使う

方法1
ターミナルソフトはいくつかありますが
  a Arduino IDE付属のターミナルソフト
   そもそもDTRの設定ができない

  b TeraTerm
   DTRの設定はマクロを記述することで設定できるが、
   COMポートを開いたときにDTRの設定をどうやっても反映されず、
   必ずArduinoが再起動する

  c RLogin
   DTRの設定はあるがどう設定しても必ずArduinoが再起動する

  d ターミナルソフトを自作する 
   未検証
   参考:http://nuneno.cocolog-nifty.com/blog/2014/03/arduino-f24c.html

方法3
 ソフトウエアシリアルを使う

 USB接続のシリアルポートは、プログラム書き込み後にプログラムを起動しないといけないのでリセットしなければならないというしがらみがあるわけで、それならシリアルポートを別にもうければよいのであって、それならばソフトシリアルを使えばよい…

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  Serial.begin(57600); // ハードウェアシリアルを準備
  while (!Serial) {
    ; // シリアルポートの準備ができるのを待つ(Leonardoのみ必要)
  }
  Serial.println("Ready");
  mySerial.begin(4800); // ソフトウェアシリアルの初期化
  mySerial.println("Hello, world?");
}

void loop() {
  if (mySerial.available()) Serial.write(mySerial.read());
  if (Serial.available()) mySerial.write(Serial.read());
}

http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=92
www.musashinodenpa.comより
原理的にはこれで解決できそうです。Arduino.ccのフォーラムでこれを使っている人がいました。

いろいろ試した結果、ターミナルソフトではDTRの設定がうまく反映されず、『ターミナル接続リセット問題』は未解決です。

いや、現状それほど問題ではないのだけれど、Arduinoの動作状況を確認するためにターミナルで接続したとたんリセットかかると動作状況の確認ができないという。簡単に解決できそうでできない。
TeraTarmもなんでできないのだろうか。