#stk500 😐😐😐🥴😐😬🤪💥🔥💥💥🤬🤬🤬🤬🤬🤬🤬🤬🤬🤬...!!! (at Felpham) https://www.instagram.com/p/ByudYJpB7bhz4Pc7DGBV7olqE45X2HSUQORwiA0/?igshid=10i2fcg7ll8uo

seen from United States
seen from United States
seen from China
seen from Finland
seen from China

seen from Netherlands

seen from Australia
seen from Germany
seen from Australia
seen from China
seen from China
seen from United Kingdom
seen from United Kingdom
seen from United Kingdom

seen from United Kingdom
seen from China
seen from Serbia
seen from China
seen from China
seen from China
#stk500 😐😐😐🥴😐😬🤪💥🔥💥💥🤬🤬🤬🤬🤬🤬🤬🤬🤬🤬...!!! (at Felpham) https://www.instagram.com/p/ByudYJpB7bhz4Pc7DGBV7olqE45X2HSUQORwiA0/?igshid=10i2fcg7ll8uo
Understanding Arduino and stk500
Hi everyone! While looking how to improve the keyboard i created, i was looking for a way to make the ATMega16U2 and ATMega328p talked together. First, i started with something really simple like sending messages from ATMega328p to the ATMega16U2 through the command Serial.print(). It works but not as fine as i expected. When i was updating the program on the ATMega328p created with the Arduino Sketch tool, i was having error about the protocol stk500. I was starting to look around to find some informations. The STK-500 is the name of a tool to flash the microcontroller but also a protocol. Differents versions exists but, the one for Arduino is the version 1 (http://www.atmel.com/Images/doc2525.pdf). After getting this information, i wanted to know where was the implementation of s stk500 stack. From the Arduino Sketch tool, i found that he was using avrdude, a companion protocol used to simplify the communication with an AVR chip. The Arduino sketch tool used avrdude in app/src/processing/app/debug/AvrdudeUploader.java with the following command: avrdude -c stk500v1 -P /dev/ttyACM0 -b <upload.speed> -D -Uflash:w:" + buildPath + File.separator + className + ".hex:i According to the help of avrdude: -D Disable auto erase for flash memory -U <memtype>:r|w|v:<filename>[:format] Memory operation specification. Multiple -U options are allowed, each request is performed in the order specified Then, i was interested by how the ATMega328p was interpreting the stk500 messages. The ATMega16u does not interfer in the communication between the computer and the microcontroller. After randomly searching in the source code of ATMega328p, i discovered that it was the bootloader which was responsible of interpreting stk500 messages. The bootloader of ATMega328p can be found in the optiboot folder (https://github.com/arduino/Arduino/blob/master/hardware/arduino/bootloaders/optiboot/optiboot.c). The main algorithm of the ATMega328p bootloader is : - Check if the reset was due to hard reset - If not, start the application of the user - If yes (hard reset), start to receive message Read message until - receiving bad messages - receiving the end message ("Q ") - after waiting too much If one of this condition is realised, throw a soft reset using watchdog. The watchdog is a common system used to prevent the chip from being stuck. You arm it and if you don't reset it fast enough, the chip is resetted. After all my discoveries, I finally managed to understand where was the stack. But, i was stuck in this question: "If the bootloader of the ATMega328p is the only one in charge of the stk500 messages, how can he reply to upload with avrdude ?" The bootloader disappears after the boot! So, i continue to dig through the code I started to think that Serial object was hidding. When you called Serial in your code, you are using this part : hardware/arduino/cores/arduino/HardwareSerial.cpp ==> It defines the RX/TX buffer and nothing more. So, maybe it was due to the appStart() which is called after a soft reset of the bootloader. In fact, the appStart() is designed to bring the address pointer at the adresse 0x00000000. I was able to discovered the main function here: hardware/arduino/cores/arduino/main.cpp. It is a skeleton which called setup() & loop() functions.
int main(void){ init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
When compiled, the binary code should be copied at the address 0x00000000. Eventually, the main function is not doing any stk500 thing. I noticed a wire between the pin13 of ATMega16u2 and the pin RESET of ATMega328p. I started to think that ATMega16U2 can be the last player in this stk500 hunt. When i was analyzing the ATMega16U2, i first didn't understand the aim of this code:
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) { bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR); if (CurrentDTRState) AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; else AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; }
But, the name AVR_RESET_LINE_PORT started to tiggling "my common sense". And Yes, AVR_RESET_LINE_PORT is a alias for the pin 13. DTR for Data Terminal Ready is a virtual serial control line and it is set by the computer when it opens a new connection According to http://www.tldp.org/HOWTO/html_single/Modem-HOWTO/Modem-HOWTO.html#toc12.7, "since there is nothing running on this port anymore, the port closes and sends a hangup signal to the modem by negating DTR. [...]This will almost immediately open the port again and raise DTR." When a connection is opened, the DTR raised, creating an hardreset for atmega328p. All the truth was revealed!
The following picture shows how the boot works:
The computer opens a new connection on /dev/ttyACM.
The microcontroller ATMega16U2 catchs the CDC Line change event and generate a reset by setting its pin 13 to ground
The microcontroller ATMega328p restarts on the bootloader
The computer starts to send and receives stk500 messages
Sanguinololuボードにブートローダーを書き込む(対策編)
Sanguinololuに書き込んだGen7のブートローダーが使うstk500のプロトコルは、ボーレートが115.2kHzに固定されています。ところが見舞われたトラブルである書き込みが動作しないのはシリアル速度の微妙な不一致が原因のように思われます。
前に引用したテーブルを見ると、クリスタルに16MHzを使った場合、ボーレート76800bpsであれば誤差がごくわずかであり、FT232RLもこの速度に対応しているようです。stk500プロトコルの仕様からは外れてしまいますが、シリアル速度の変更を試してみることにします。
まずGen7のブートローダーのソースをgithubから持ってきます。
https://github.com/Traumflug/Generation_7_Electronics/tree/master/arduino%20support
ボーレートを定義している箇所のソースを修正します。
$ cd stk500v2bootloader
$ vi stk500boot.c
//#define BAUDRATE 115200
#define BAUDRATE 76800
makeでクロックとMCUを指定してビルドします。
$ make clean && make F_CPU=16000000 MCU=atmega1284p
できあがったstk500boot.hexを書き込みます。
コマンドラインから書き込む場合は、Arduino-1.0に添付されているavrdudeとconfファイルを使い、usbaspを接続したうえで下記コマンドで書き込みます。ardはArduino-1.0の内部パスを指すシェル変数です。
$ ard=/Applications/Arduino-1.0.app/Contents/Resources/Java/hardware/tools/avr
$ make F_CPU=16000000 MCU=atmega1284p AVRDUDE="$ard/bin/avrdude -C $ard/etc/avrdude.conf" AVRDUDE_PROGRAMMER=usbasp program
Arduino IDEを使って書き込むことも可能です。boards.txtを変更して修正したhexと、ボーレートを指定します。
/Applications/Arduino-1.0.app/Contents/Resources/Java/hardware/Gen7/boards.txt に下記のようなエントリを作成します。
##############################################################
Gen7-1284P-16-768.name=Gen7 with ATmega1284P and 16 MHz(76.8kbps)
Gen7-1284P-16-768.upload.protocol=stk500v2
Gen7-1284P-16-768.upload.maximum_size=129024
Gen7-1284P-16-768.upload.speed=76800
Gen7-1284P-16-768.bootloader.low_fuses=0xF7
Gen7-1284P-16-768.bootloader.high_fuses=0xDC
Gen7-1284P-16-768.bootloader.extended_fuses=0xFC
Gen7-1284P-16-768.bootloader.path=Gen7
Gen7-1284P-16-768.bootloader.file=bootloader-1284P-16MHz-768.hex
Gen7-1284P-16-768.bootloader.unlock_bits=0x3F
Gen7-1284P-16-768.bootloader.lock_bits=0x0F
Gen7-1284P-16-768.build.mcu=atmega1284p
Gen7-1284P-16-768.build.f_cpu=16000000L
Gen7-1284P-16-768.build.core=arduino
Gen7-1284P-16-768.build.variant=gen7
さきほどmakeしたhexファイルをコピーしておきます。
$ cp stk500boot.hex /Applications/Arduino-1.0.app/Contents/Resources/Java/hardware/Gen7/bootloaders/Gen7/bootloader-1284P-16MHz-768.hex
そして、Arduino-1.0を起動し、追加したボードを選択します。
usbaspを接続して、Tools>Burn Bootloaderで書き込みます。
ブートローダーの書き込みが成功したら、サンプルを選んでUploadしてみます。
アップロードが無事成功するようになりました。
コマンドラインからもアクセスしてみます。
$ avrdude -b 76800 -c stk500v2 -p m1284p -P /dev/tty.usbserial-A400FFFS
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude: Device signature = 0x1e9705
avrdude: safemode: Fuses OK
avrdude done. Thank you.
安定して動作するようになりました。
今回の対策は76800bpsという変則的な速度を使うようにしてみましたが、引き続き他の正統的な対策も検討したいところです。
本題から外れたところで時間を要してしまいましたが、引き続きステッピングモーター基板のファームウェアの検討をすることにします。
Sanguinololuボードにブートローダーを書き込む(トラブル編)
ボードが組み上がったら、テストのためにArduinoのツール類が使えるように整備します。
まずはブートローダーの書き込みですが、ここで嵌りました。
Sanguinololu用にどのブートローダを使うべきか探してみたところ、以下のGen7 Electronics向けのものが良さそうでした。
http://reprap.org/wiki/Gen7_Board_1.4#Bootloader_Upload
上記ページのProgramming the bootloader using the Arduino IDEの節を参考に作業します。
Arduino IDEに組み込むためのパッケージを以下からダウンロード&解凍します。
https://github.com/Traumflug/Generation_7_Electronics/blob/Gen7-Arduino-IDE-Support-2.0/release%20documents/Gen7%20Arduino%20IDE%20Support%202.0.zip?raw=true
INSTALL.txtの説明に従いGen7フォルダを、Arduino-1.0のhardwareフォルダにコピーしておきます。Macの場合、hardwareフォルダは、ファインダで/Application/Arduinoアイコンを右ボタンクリックし、Show Package Contentsを選び、下記のパスを開き、ここに先ほど展開したGen7フォルダをD&Dします。
ファイルを正常に組み込むことができたならば、Arduino-1.0を起動するとボードの選択肢にGen7 xxxという選択肢が追加されているはずです。
ツールの準備ができたら次は書き込みです。まずISPコネクタにusbaspをつないでusbaspのUSBをPC(Mac)に接続します。このときSanguinololuのUSBは接続しません。
次にArduino-1.0を起動し、メニューのTools>BoardからGen7 with ATmega1284P and 16MHzを選択します。
さらにTools>Programmerで、usbaspを選択しておきます。そして、Tools>Burn Bootloaderを選ぶとブートローダーが書き込まれます。これには数分かかります。ここまではusbaspが動作していれば正常に進むはずです。
ブートローダーが書き込まれたら、usbaspを取り外し、SanguinololuのUSBをPC(Mac)に接続します。
そうすると、Arduino-1.0のTools>Serial Portに、/dev/tty.usbserial-A400FFFS というような選択肢が追加されるはずですので、これを選択状態にします。
適当なサンプルを開き、Uploadボタンを押します。ビルドは成功するのですが、アップロードがうまくいかず、以下のようなエラーメッセージが表示されてしまいます。
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer
ブートローダーとavrdudeの通信がうまくいっていないようです。
原因切り分けのため、コマンドラインから試してみます。
$ avrdude -c stk500v2 -p m1284p -P /dev/tty.usbserial-A400FFFS
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.01s
avrdude: Device signature = 0x1e9705
avrdude: stk500_2_ReceiveMessage(): timeout
avrdude: stk500v2_cmd(): short reply, len = 0
avrdude: safemode: Fuses OK
avrdude done. Thank you.
先ほどと同じエラーメッセージが途中に表示されています。シグネチャの表示はされているので全く動作していないわけではなさそうです。何度か繰り返すと成功することもありますが、試行のたびに動作が変化し一定しません。
オシロでFT232RLとATmega1284Pの間のシリアルのTX0,RX0をモニタしてみました。
上がFT232RL→ATmega1284Pで、下が逆方向の信号です。リクエストと応答が交互に出ているのが見えますが、最後のリクエストに対して応答が出ていないようです。
波形を拡大してみます。
シリアル信号のパルス幅を見てみると、AVRからは9.000uS(111.1kHz)と、本来の115.2kHzと比べると4%程度低いようです。FT232RLのパルスはぴったり115.2kHzでした。このシリアル速度の違いからAVRのUARTが受信メッセージを受け取り損ねているのではないかと想像されます。
AVRのデータシートを見てみると、想定される誤差とだいたい一致しています。
http://www.atmel.com/Images/doc8059.pdf
このブートローダーが使うstk500のプロトコルは、ボーレートが115.2kHzと固定とのことです。Webで対策を探してみましたが、皆さんトラブルが多発しているようです。上記のずれが原因なのかもしれません。
対策編に続く