RL78マイコン基板(RL78/G13)|rl78flashの書き込みボーレート変更不具合の暫定修正('workaround')
rl78flashというオープンソースソフトウェアのフラッシュ書き込みツールですが、書き込み時の通信ボーレートを
デフォルトの115Kbpsから他のボーレート(250Kbps/500Kbps/1Mbps)へ変更すると以下のようにエラーになって
しまいますので、rl78flashのソースコードを暫定的に修正してみました。(暫定としたのは、FT232RLのWindows
ドライバのバージョンに依存して発生する不具合かも知れず、ドライバのバージョンによっては発生しないのかも
知れないような気がしたからです。私のパソコンのドライバは相当古いのかもしれないと気になり始めましたので、
後でアップデートして、再度確認してみるつもりです。) (それと、SiLabs社のチップでは起きない可能性とか。)
(追記 : FTDI社の以下のWindowsドライバにアップデートして確認してみましたが、結果は変わりませんでした。
他方、SiLabs社のCP2102とSiLabs社の以下のWindowsドライバを試してみるとエラーになりませんでした。
FTDI VCP Driver v2.12.16 (latest version @ Microsoft Update @ 2016/09/16) → NG
FTDI VCP Driver v2.12.18 (latest version @ www.ftdichip.com/Drivers/VCP.htm @ 2016/09/16) → NG
SiLabs VCP Driver v6.7 (latest version @ Microsoft Update @ 2016/09/21) → OK
SiLabs VCP Driver v6.7.3 (latest version @ www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx @ 2016/09/21) → OK
私のパソコンのOSは Windows7 SP1 です。)
(To be continued... What is the conclusion? What does Kurumi Writer's source code(MIT licence) do?)

修正内容は以下の通りです。
ファイル: serial_win32.c
暫定修正内容: 赤字の箇所を追加
int serial_set_dtr(port_handle_t fd, int level)
{
int command;
DCB dcbSerialParams; // Added for a workaround by MON-80 (FTDI's driver problem?)
if (level)
{
//command = CLRDTR;
command = DTR_CONTROL_DISABLE;
}
else
{
//command = SETDTR;
command = DTR_CONTROL_ENABLE;
}
//return EscapeCommFunction(fd, command) != 0 ? 0 : -1;
GetCommState(fd, &dcbSerialParams);
//dcbSerialParams.fDtrControl may differ from EscapeCommFunction()'s CLRDTR/SETDTR
//This is true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
dcbSerialParams.fDtrControl = command;
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}
修正後はエラーになることは無くなりました。

不具合が発生する理由ですが、ボーレートを変更するには以下のようにしてWindows APIを呼び出す必要がある
のですが、使用する構造体の中にボーレート設定値だけでなくDTR信号線/RTS信号線の設定値も含まれていて、
これが適切な値に設定されていないことが原因のようです。とは言え、構造体の内容はWindows APIで取得した
もので、そもそもWindows APIを呼び出したタイミングでのDTR信号線/RTS信号線の設定値をWindows APIが
返さないことが問題のようにも思われるのですが、実はDTR信号線/RTS信号線は以下とは違うWindows APIで
操作されるのが一般的であり、それにも関わらず、そちらのWindows APIでの設定値が反映されるかどうかに
関してWndows APIのドキュメントに記述がありませんでしたので、ちょっと何とも言えない感じです。加えて、
WindowsはFT232RLのWindowsドライバから情報を取得するようになっている可能性もありますが、その場合
にはFT232RLのWindowsドライバが関係してくるかも知れないという気もしなくもないです。(それと、SiLabs
社のチップでは起きない可能性とか。)
ファイル: serial_win32.c
該当箇所の内容:
int serial_set_baud(port_handle_t fd, int baud)
{
DCB dcbSerialParams;
GetCommState(fd, &dcbSerialParams);
dcbSerialParams.BaudRate = baud;
//dcbSerialParams.fDtrControl may differ from EscapeCommFunction()'s CLRDTR/SETDTR
//dcbSerialParams.fRtsControl may differ from EscapeCommFunction()'s CLRRTS/SETRTS
//Both are true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}
追記 : 補足
更に調べてみると、Windows APIで取得した構造体の内容の初期値はFTDI社の場合とSiLabs社の場合とで違う
値になっていました。
ファイル: serial_win32.c
該当箇所の内容: 赤字の箇所は私が追加したコメントです
port_handle_t serial_open(const char *port)
{
port_handle_t fd;
char port_full_name[20];
snprintf(port_full_name, sizeof port_full_name - 2u,
"\\\\.\\%s", port);
if (4 <= verbose_level)
{
printf("\t\tOpen port: %s\n", port_full_name);
}
fd = CreateFile(port_full_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == fd)
{
int error_num = GetLastError();
char error_string[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error_num,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
error_string,
sizeof error_string,
NULL);
fprintf(stderr, "Unable to open port: (%i) %s\n", error_num, error_string);
}
else
{
DCB dcbSerialParams;
GetCommState(fd, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = TWOSTOPBITS;
dcbSerialParams.Parity = NOPARITY;
//Initial value of following members depend on vender of chip/driver (2016/09/22)
//dcbSerialParams.fDtrControl : 1@1st time, or 0* FTDI / 0@1st time, or 1* SiLabs
//dcbSerialParams.fRtsControl : 1@1st time, or 0* FTDI / 0@1st time, or 1* SiLabs
//'*' means "depends on last setting of SetCommState() before COM close"
//Real signal value of following members at this moment(2016/09/23)
//DTR : low@1st time, or high* FTDI / high@1st time, or low* SiLabs
//RTS : low@1st time, or high* FTDI / high@1st time, or low* SiLabs
//'*' means "depends on last setting of SetCommState() before COM close"
SetCommState(fd, &dcbSerialParams);
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=0;
timeouts.WriteTotalTimeoutMultiplier=0;
SetCommTimeouts(fd, &timeouts);
FlushFileBuffers(fd);
}
return fd;
}
追記 : 補足
DTR信号線を使用する-m 2オプションだけでなく、RTS信号線を使用する-m 4オプションでも、同じくエラーに
なりましたので、これについても修正して、エラーにならないようにしました。

int serial_set_rts(port_handle_t fd, int level)
{
int command;
DCB dcbSerialParams; // Added for a workaround by MON-80 (FTDI's driver problem?)
if (level)
{
//command = CLRRTS;
command = RTS_CONTROL_DISABLE;
}
else
{
//command = SETRTS;
command = RTS_CONTROL_ENABLE;
}
//return EscapeCommFunction(fd, command) != 0 ? 0 : -1;
GetCommState(fd, &dcbSerialParams);
//dcbSerialParams.fRtsControl may differ from EscapeCommFunction()'s CLRRTS/SETRTS
//This is true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
dcbSerialParams.fRtsControl = command;
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}

追記 : メモ
Windows Communication API - MSDN
DCB structure
https://msdn.microsoft.com/library/aa363214.aspx
GetCommState
https://msdn.microsoft.com/library/cc429283.aspx
SetCommState
https://msdn.microsoft.com/library/cc429715.aspx
EscapeCommFunction
https://msdn.microsoft.com/library/cc429215.aspx
追記 : メモ
Tool to program RL78 MCUs via serial bootloader - GitHub
master
https://github.com/msalau/rl78flash/
releases
https://github.com/msalau/rl78flash/releases/
v0.5.2
https://github.com/msalau/rl78flash/tree/v0.5.2/
デフォルトの115Kbpsから他のボーレート(250Kbps/500Kbps/1Mbps)へ変更すると以下のようにエラーになって
しまいますので、rl78flashのソースコードを暫定的に修正してみました。(暫定としたのは、FT232RLのWindows
ドライバのバージョンに依存して発生する不具合かも知れず、ドライバのバージョンによっては発生しないのかも
知れないような気がしたからです。私のパソコンのドライバは相当古いのかもしれないと気になり始めましたので、
後でアップデートして、再度確認してみるつもりです。) (それと、SiLabs社のチップでは起きない可能性とか。)
(追記 : FTDI社の以下のWindowsドライバにアップデートして確認してみましたが、結果は変わりませんでした。
他方、SiLabs社のCP2102とSiLabs社の以下のWindowsドライバを試してみるとエラーになりませんでした。
FTDI VCP Driver v2.12.16 (latest version @ Microsoft Update @ 2016/09/16) → NG
FTDI VCP Driver v2.12.18 (latest version @ www.ftdichip.com/Drivers/VCP.htm @ 2016/09/16) → NG
SiLabs VCP Driver v6.7 (latest version @ Microsoft Update @ 2016/09/21) → OK
SiLabs VCP Driver v6.7.3 (latest version @ www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx @ 2016/09/21) → OK
私のパソコンのOSは Windows7 SP1 です。)
(To be continued... What is the conclusion? What does Kurumi Writer's source code(MIT licence) do?)

修正内容は以下の通りです。
ファイル: serial_win32.c
暫定修正内容: 赤字の箇所を追加
int serial_set_dtr(port_handle_t fd, int level)
{
int command;
DCB dcbSerialParams; // Added for a workaround by MON-80 (FTDI's driver problem?)
if (level)
{
//command = CLRDTR;
command = DTR_CONTROL_DISABLE;
}
else
{
//command = SETDTR;
command = DTR_CONTROL_ENABLE;
}
//return EscapeCommFunction(fd, command) != 0 ? 0 : -1;
GetCommState(fd, &dcbSerialParams);
//dcbSerialParams.fDtrControl may differ from EscapeCommFunction()'s CLRDTR/SETDTR
//This is true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
dcbSerialParams.fDtrControl = command;
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}
修正後はエラーになることは無くなりました。

不具合が発生する理由ですが、ボーレートを変更するには以下のようにしてWindows APIを呼び出す必要がある
のですが、使用する構造体の中にボーレート設定値だけでなくDTR信号線/RTS信号線の設定値も含まれていて、
これが適切な値に設定されていないことが原因のようです。とは言え、構造体の内容はWindows APIで取得した
もので、そもそもWindows APIを呼び出したタイミングでのDTR信号線/RTS信号線の設定値をWindows APIが
返さないことが問題のようにも思われるのですが、実はDTR信号線/RTS信号線は以下とは違うWindows APIで
操作されるのが一般的であり、それにも関わらず、そちらのWindows APIでの設定値が反映されるかどうかに
関してWndows APIのドキュメントに記述がありませんでしたので、ちょっと何とも言えない感じです。加えて、
WindowsはFT232RLのWindowsドライバから情報を取得するようになっている可能性もありますが、その場合
にはFT232RLのWindowsドライバが関係してくるかも知れないという気もしなくもないです。(それと、SiLabs
社のチップでは起きない可能性とか。)
ファイル: serial_win32.c
該当箇所の内容:
int serial_set_baud(port_handle_t fd, int baud)
{
DCB dcbSerialParams;
GetCommState(fd, &dcbSerialParams);
dcbSerialParams.BaudRate = baud;
//dcbSerialParams.fDtrControl may differ from EscapeCommFunction()'s CLRDTR/SETDTR
//dcbSerialParams.fRtsControl may differ from EscapeCommFunction()'s CLRRTS/SETRTS
//Both are true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}
追記 : 補足
更に調べてみると、Windows APIで取得した構造体の内容の初期値はFTDI社の場合とSiLabs社の場合とで違う
値になっていました。
ファイル: serial_win32.c
該当箇所の内容: 赤字の箇所は私が追加したコメントです
port_handle_t serial_open(const char *port)
{
port_handle_t fd;
char port_full_name[20];
snprintf(port_full_name, sizeof port_full_name - 2u,
"\\\\.\\%s", port);
if (4 <= verbose_level)
{
printf("\t\tOpen port: %s\n", port_full_name);
}
fd = CreateFile(port_full_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == fd)
{
int error_num = GetLastError();
char error_string[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error_num,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
error_string,
sizeof error_string,
NULL);
fprintf(stderr, "Unable to open port: (%i) %s\n", error_num, error_string);
}
else
{
DCB dcbSerialParams;
GetCommState(fd, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = TWOSTOPBITS;
dcbSerialParams.Parity = NOPARITY;
//Initial value of following members depend on vender of chip/driver (2016/09/22)
//dcbSerialParams.fDtrControl : 1@1st time, or 0* FTDI / 0@1st time, or 1* SiLabs
//dcbSerialParams.fRtsControl : 1@1st time, or 0* FTDI / 0@1st time, or 1* SiLabs
//'*' means "depends on last setting of SetCommState() before COM close"
//Real signal value of following members at this moment(2016/09/23)
//DTR : low@1st time, or high* FTDI / high@1st time, or low* SiLabs
//RTS : low@1st time, or high* FTDI / high@1st time, or low* SiLabs
//'*' means "depends on last setting of SetCommState() before COM close"
SetCommState(fd, &dcbSerialParams);
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=0;
timeouts.WriteTotalTimeoutMultiplier=0;
SetCommTimeouts(fd, &timeouts);
FlushFileBuffers(fd);
}
return fd;
}
追記 : 補足
DTR信号線を使用する-m 2オプションだけでなく、RTS信号線を使用する-m 4オプションでも、同じくエラーに
なりましたので、これについても修正して、エラーにならないようにしました。

int serial_set_rts(port_handle_t fd, int level)
{
int command;
DCB dcbSerialParams; // Added for a workaround by MON-80 (FTDI's driver problem?)
if (level)
{
//command = CLRRTS;
command = RTS_CONTROL_DISABLE;
}
else
{
//command = SETRTS;
command = RTS_CONTROL_ENABLE;
}
//return EscapeCommFunction(fd, command) != 0 ? 0 : -1;
GetCommState(fd, &dcbSerialParams);
//dcbSerialParams.fRtsControl may differ from EscapeCommFunction()'s CLRRTS/SETRTS
//This is true for both FTDI's FT232RL/driver and SiLabs' CP2102/driver (2016/09/22)
dcbSerialParams.fRtsControl = command;
return SetCommState(fd, &dcbSerialParams) != 0 ? 0 : -1;
}

追記 : メモ
Windows Communication API - MSDN
DCB structure
https://msdn.microsoft.com/library/aa363214.aspx
GetCommState
https://msdn.microsoft.com/library/cc429283.aspx
SetCommState
https://msdn.microsoft.com/library/cc429715.aspx
EscapeCommFunction
https://msdn.microsoft.com/library/cc429215.aspx
追記 : メモ
Tool to program RL78 MCUs via serial bootloader - GitHub
master
https://github.com/msalau/rl78flash/
releases
https://github.com/msalau/rl78flash/releases/
v0.5.2
https://github.com/msalau/rl78flash/tree/v0.5.2/
- 関連記事
-
- RL78マイコン基板(RL78/G13)|CP2102+KurumiWriterで秋月のRL78搭載変換モジュールに書き込み
- RL78マイコン基板(RL78/G13)|rl78flashで書き込んでPython+pySerialでシリアル通信する設定
- RL78マイコン基板(RL78/G13)|TeraTermでログにタイムスタンプを付けて自動保存してくれる機能
- RL78マイコン基板(RL78/G13)|WebコンパイラのSerial.printに日本語出力させてTeraTermで表示
- RL78マイコン|日立/RSDの人のCC-RLの論文が情報処理学会の優秀論文(全54編)の1つに選ばれていた
- RL78マイコン基板(RL78/G13)|rl78flashで書き込んでTeraTermでシリアル通信する設定
- RL78マイコン基板(RL78/G13)|KurumiWriter V1.00(ソース公開版)とrl78flashの書き込み時間の比較
- RL78マイコン基板(RL78/G13)|rl78flashの書き込みボーレート変更不具合の暫定修正('workaround')
- RL78マイコン基板(RL78/G13)|KurumiWriter V1.00(ソース公開版)で不安定動作の暫定修正
- RL78マイコン基板(RL78/G13)|KurumiWriterで書き込んでTeraTermでシリアル通信する設定
- RL78マイコン基板(RL78/G13)|rl78flashで秋月のR5F100LGAFB搭載変換モジュールに書き込み
- RL78マイコン基板(RL78/G13)|KurumiWriterで秋月のR5F100LGAFB搭載変換モジュールに書き込み
- RL78マイコン基板(RL78/G13)|GR-COTTONのフラッシュ書き込み回路は抵抗のみ
- RL78マイコン基板(RL78/G13)|Webコンパイラで秋月のR5F100LGAFB搭載変換モジュールを使う
- RL78マイコン(RL78/G10)|Applilet EZ PL for RL78のフラッシュ書き込みタイムアウト時間は長い
2016/09/14 blog-entry-810 category: RL78 /* 16bit,8bit CISC */
| h o m e |