GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
GR-SAKURAを使ってGR-KURUMIにbinファイルを書き込もうと試したのですが、うまく行きませんでした。
接続は、写真のようにSCI_SCI0P2xを使って書こうと思って、TxDとRxDをクロスさせる中間基板を作りました。また、GNDと3.3Vは2枚目の写真のように配線しています。
CTSは未接続です(^^;。
これで、下記のようなプログラムを書きました。
#include <rxduino.h> void setup() { pinMode(PIN_LED0,OUTPUT); pinMode(PIN_LED1,OUTPUT); pinMode(PIN_LED2,OUTPUT); pinMode(PIN_LED3,OUTPUT); //基板の青ボタンを有効にします pinMode(PIN_SW, INPUT); Serial.begin(115200); Serial.setDefault(); //現在のシリアルポートを標準出力とするprintfでも出力する setvbuf(stdout,NULL,_IONBF,0); sci_convert_crlf(CRLF_NONE,CRLF_NONE); //バイナリを通せるようにする Serial1.begin(115200, SCI_SCI0P2x); //KURUMI接続ポート sci_convert_crlf_ex(Serial1.get_handle(), CRLF_NONE, CRLF_NONE); //バイナリを通せるようにする // IO2番 出力ポート定義 pinMode( PIN_P22, OUTPUT); digitalWrite( PIN_P22, LOW); //delay(100); //digitalWrite( PIN_P22, HIGH); //何か受信があるまで待つ while(!Serial.available()) { //基板の青ボタンが押されたらKURUMIをリセットする if( digitalRead(PIN_SW)==LOW ){ digitalWrite( PIN_P22, HIGH); while(true); } } //LED0を点灯させる digitalWrite( PIN_LED0, HIGH ); //KURUMIをリセット digitalWrite( PIN_P22, HIGH); delay(10); digitalWrite( PIN_P22, LOW); delay(10); } void loop() { while(Serial.available()) //何か受信があった { Serial1.write( (unsigned char)Serial.read() ); } while(Serial1.available()) //何か受信があった { Serial.write( (unsigned char)Serial1.read() ); } //基板の青ボタンが押されたらKURUMIをリセットする if( digitalRead(PIN_SW)==LOW ){ digitalWrite( PIN_P22, HIGH); while(true); } }
KURUMIを挿して、このプログラムを動かして、PCからKurumiWriter_Win.exeでがじぇっとるねさすのUSBポートにKURUMIのbinファイルを書き出しても、しばらくするとKurumiWriter_Win.exeがエラーを出します。
CTSの制御はやっぱりいるのでしょうか(^^;。DTRはLOWにしっぱなしでいいのでしょうか。
何も考えないで、垂れ流せばいいのかなと思ったら、そうではないようでした。
もし、プロトコルなどご存知の方がいらっしゃれば、後を次いでください。私はここで一旦保留にします。
面白い試みですね。Kurumi WriterはFTDIのEEPROMにアクセスするため、そこのキャンセル処理が不明ですが、少なくともモード引き込みは必要になります。CTS->TOOL0, DTR->RESETに配線されており、以下のドキュメントにプロトコルが掲載されています。
documentation.renesas.com/.../r01an0815jj0100_rl78.pdf
GR-SAKURA の初回のプロデューサミーティングの際に公開された『GR RL78版ボード プログラム作成~マイコン書き込み』の資料では CTS は使用されず、拙作の『Yet Another~』のソースを確認しましたが CTS の制御はなんでかやってなかったにも関らず書き込みできているので←GR-KURUMI の基板上で、TXD を LOW に落とすことで TOOL0 が LOW になる仕組みになってたので取り消し CTS の制御は多分やらんでも大丈夫な気がします。
不安な要素としては、現在の GR-SAKURA のライブラリでは通信のタイミングによって USB の仮想 COM ポート以外でのシリアル通信でけっこう文字をこぼす不具合があるので、その点ですね。←試したら意外と大丈夫だった。
あ、あと書き込みプロトコルの資料によると プログラマ→RL78 のストップビット長が 2ビット ということになってるので、自前で SCI 制御やらんといけない気がします。
書き込みプログラムは Simple Writer を使ったほうが良い気がしますね。
て、あれ? GR-SAKURA でのシリアル通信では start1 data8 parity0 stop1 で通信してるとなんとなく信じてたけど合ってるのかな? どっかに明記されてるのだろうか?
いろいろな情報ありがとうございます。ストップビット長が2ですか。そこで先ずアウトですね。
GR-SAKURAのシリアル通信はボーレート以外の条件設定は持っていないのかな。 sta1 d8 non sto1でしか使ったことが無かったです。
また、時間ができたときに挑戦してみます。
ストップビット長等はシリアルモードレジスタ(SMR)の設定でできるので、度々再設定されたりするのでなければ、Serial1.begin(115200, SCI_SCI0P2x) の後にすれば行けそうな気がします。
PCのWriter側も相手がKURUMIだと思ってストップビット長2で送信してきているとすれば、USBの方もstop2で受ける必要がありますね。
スレが進んでますね、、
CTSは確かに書き込み時は使ってないです。すみません。E1用の配線ですね。
Yamamoto Minao(たろサ)様、
USB の仮想 COM ポートは、物理的なプロトコルはフリしてるだけじゃないでしょうか? 9600bps とかで繋いでもなんか速いし。
Okamiya Yuuki様、
CTS については、書き込みプロトコルのドキュメント上では TOOL0(CTS) への操作について説明があるので従うべきとは思います。
Fujitaさん、コメントありがとうございます。FTDIのときはTOOL0はTXOで擬似的に00送信でローに落として、通信を止めて、その間にRESETを解除してモード引き込みしていたと思います。とはいえSAKURAで書くときはIO制御+シリアルで行えばいいと思いますが、この辺はKurumi Writerからのコマンドに応じたものにしないといけなそうですね。ハックしてみようかなと考え中です。
sakuraがPCから00を受信したらモード引き込みをエミュレーションしてやればできそうですね。
あれ? CTS って制御できるの?←KURUMIの回路図見て納得しました。上手いことやってるのね。
マネして中間基板つくってみました。
GR-KURUMI 側テストプログラム
#include <RLduino78.h> #define LED_R 22 #define LED_G 23 #define LED_B 24 void setup() { Serial.begin(115200); Serial.println("START"); pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT); digitalWrite(LED_R, HIGH); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); } void loop() { static int color = 0; if (Serial.available()) { char buf[100]; int c = Serial.read(); sprintf(buf, "%02x: '%c'", c, isprint(c) ? c : '-'); Serial.println(buf); color = (color % 7) + 1; digitalWrite(LED_R, color & 1 ? LOW : HIGH); digitalWrite(LED_G, color & 2 ? LOW : HIGH); digitalWrite(LED_B, color & 4 ? LOW : HIGH); } }
GR-SAKURA 側テストプログラム
#include <rxduino.h> void setup() { Serial.begin(115200); Serial1.begin(115200, SCI_SCI0P2x); pinMode(PIN_P22, OUTPUT); digitalWrite(PIN_P22, LOW); delay(1); digitalWrite(PIN_P22, HIGH); pinMode(PIN_SW, INPUT); } void loop() { if (Serial.available()) { Serial1.write(Serial.read()); } if (Serial1.available()) { Serial.write(Serial1.read()); } digitalWrite(PIN_P22, digitalRead(PIN_SW)); }
使い方
GR-KURUMI と GR-SAKURA を 中間基板で接続し、GR-SAKURA を USB ケーブルにて PC と接続し、PC で Tera Term を起動して GR-SAKURA の COM ポートを開く
・キーボードから入力した文字の文字コードが Tera Term の画面に表示され、文字を入力するたびに GR-KURUMI の LED の色が変化するか?
・GR-SAKURA の ボード上の青のタクトスイッチを押すと GR-KURUMI がリセットされるか(LED が消灯するか)?
以上の確認ができたら(多分)オッケー
なんか書き込みできたクサイので投稿
#include <rxduino.h> #include <iodefine_gcc63n.h> #define PIN_TXD 1 #define PIN_RESET 2 void setup() { // PC 接続ポート設定 Serial.begin(115200); sci_convert_crlf_ex(Serial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする // TXD 出力ポート設定 pinMode(PIN_TXD, OUTPUT); digitalWrite(PIN_TXD, LOW); // RESET 出力ポート設定 pinMode(PIN_RESET, OUTPUT); digitalWrite(PIN_RESET, LOW); // モード引き込みの際に PC から 0x00 が送信されてくる筈なので待つ while (!Serial.available()) { ; } (void)Serial.read(); // ゴミなので捨て // フラッシュ・メモリ・プログラミング・モードへの引き込み const int tRT = 723; const int tTM = 16; const int tMB = 62; digitalWrite(PIN_RESET, HIGH); delayMicroseconds(tRT); digitalWrite(PIN_TXD, HIGH); delayMicroseconds(tTM); digitalWrite(PIN_TXD, LOW); delayMicroseconds(1000000L / 115200L * (1 + 8)); // KURUMI 接続ポート設定 Serial1.begin(115200, SCI_SCI0P2x); sci_convert_crlf_ex(Serial1.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする SCI0.SMR.BIT.STOP = 1; // ストップビット長を2にする delayMicroseconds(tMB); } void loop() { // PC から来たデータを KURUMI に送る while (Serial.available()) { Serial1.write(byte(Serial.read())); } // KURUMI から来たデータを PC に送る while (Serial1.available()) { Serial.write(byte(Serial1.read())); } }
SimpleWriter でも KurumiWriter でも書き込みできました。
更新:
#include <rxduino.h> #include <iodefine_gcc63n.h> #define PIN_TXD 1 #define PIN_RESET 2 void setup() { // SAKURA の青タクトスイッチを SAKURA のリセットに使用 pinMode(PIN_SW, INPUT); // PC 接続ポート設定 Serial.begin(115200); sci_convert_crlf_ex(Serial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする // TXD 出力ポート設定 pinMode(PIN_TXD, OUTPUT); digitalWrite(PIN_TXD, LOW); // RESET 出力ポート設定 pinMode(PIN_RESET, OUTPUT); digitalWrite(PIN_RESET, LOW); // モード引き込みの際に PC から 0x00 が送信されてくる筈なので待つ while (!Serial.available() || Serial.read() != 0x00) { // 青タクトスイッチが押されたら SAKURA をリセット if (!digitalRead(PIN_SW)) { SYSTEM.SWRR = 0xa501; } } // フラッシュ・メモリ・プログラミング・モードへの引き込み const int tRT = 723; const int tTM = 16; const int tMB = 62; digitalWrite(PIN_RESET, HIGH); delayMicroseconds(tRT); digitalWrite(PIN_TXD, HIGH); delayMicroseconds(tTM); digitalWrite(PIN_TXD, LOW); delayMicroseconds((1 + 8) * 1000000 / 115200); delayMicroseconds(tMB); // KURUMI 接続ポート設定 Serial1.begin(115200, SCI_SCI0P2x); sci_convert_crlf_ex(Serial1.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする } void loop() { // PC から来たデータを KURUMI に送る if (Serial.available()) { Serial1.write(byte(Serial.read())); Serial1.flush(); delayMicroseconds(1 * 1000000 / 115200); } // KURUMI から来たデータを PC に送る if (Serial1.available()) { Serial.write(byte(Serial1.read())); } // 青タクトスイッチが押されたら SAKURA をリセット if (!digitalRead(PIN_SW)) { SYSTEM.SWRR = 0xa501; } }
本当にありがとうございます。ストレージのドライバ部分のほとんどを作っていただいてしまいましたね。脱帽です。
ん?いや、SAKURAがあればFTDIが要らなくなった価値の方がでかいですね。
FTDI free のためにあと必要な機能としては、
辺りでしょうか。
やれば大して難しい処理でもないのですが、PC から送られてくるコマンド・フレームを SAKURA 側で解析する必要があり、現状の、PC から来たデータを KURUMI に送るだけ、KURUMI から来たデータを PC に送るだけ、という「風流さ」が失われてしまうのが悩ましいところです。
私の中間基板でも、fujitaさんのプログラムでSAKURA経由でKURUMIら書き込むことができました。
Simple WriterとKurumiWriter_Winの両方で書き込みができることを確認しました。
すばらしいです。
fujitaさん、ありがとうございます。
fujitaさんのソースを rxduino.h のみでビルドが通るように書き直してみました。初心者向け?(^^;
SWRRレジスタへの直書きを変更しただけです。
--------------
/*GR-SAKURA Sketch Template Version: V1.06*/
#include <rxduino.h>
#define PIN_TXD 1
#define PIN_RESET 2
void setup()
{
// SAKURA の青タクトスイッチを SAKURA のリセットに使用
pinMode(PIN_SW, INPUT);
// PC 接続ポート設定
Serial.begin(115200);
sci_convert_crlf_ex(Serial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする
// TXD 出力ポート設定
pinMode(PIN_TXD, OUTPUT);
digitalWrite(PIN_TXD, LOW);
// RESET 出力ポート設定
pinMode(PIN_RESET, OUTPUT);
digitalWrite(PIN_RESET, LOW);
// モード引き込みの際に PC から 0x00 が送信されてくる筈なので待つ
while (!Serial.available() || Serial.read() != 0x00) {
// 青タクトスイッチが押されたら SAKURA をリセット
if (!digitalRead(PIN_SW)) {
system_reboot( REBOOT_USERAPP );
}
// フラッシュ・メモリ・プログラミング・モードへの引き込み
const int tRT = 723;
const int tTM = 16;
const int tMB = 62;
digitalWrite(PIN_RESET, HIGH);
delayMicroseconds(tRT);
digitalWrite(PIN_TXD, HIGH);
delayMicroseconds(tTM);
delayMicroseconds((1 + 8) * 1000000 / 115200);
delayMicroseconds(tMB);
// KURUMI 接続ポート設定
Serial1.begin(115200, SCI_SCI0P2x);
sci_convert_crlf_ex(Serial1.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする
void loop()
// PC から来たデータを KURUMI に送る
if (Serial.available()) {
Serial1.write(byte(Serial.read()));
Serial1.flush();
delayMicroseconds(1 * 1000000 / 115200);
// KURUMI から来たデータを PC に送る
if (Serial1.available()) {
Serial.write(byte(Serial1.read()));
/*GR-SAKURA Sketch Template Version: V1.06*/ #include <rxduino.h> #include <iodefine_gcc63n.h> #define PIN_RXD 0 // KURUMI からのシリアル通信受信ピン #define PIN_TXD 1 // KURUMI へのシリアル通信送信ピン #define PIN_RESET 2 // KURUMI リセットピン #define UseCMySerial 1 // CMySerial 使用スイッチ #define DefaultBaudRate 115200 // UART 通信の初期ボー・レート //#define MainBaudRate 115200 // UART 通信のボー・レート 115200bps //#define MainBaudRate 250000 // UART 通信のボー・レート 250kbps #define MainBaudRate 500000 // UART 通信のボー・レート 500kbps (オススメ) //#define MainBaudRate 1000000 // UART 通信のボー・レート 1Mbps #if UseCMySerial // CSerial の送信バッファの扱いかなんかで不具合があるクサイのでそれの代替 class CMySerial : public CSerial { private: volatile struct st_sci0* sci; public: CMySerial() : CSerial() { sci = NULL; } void begin(int bps, SCI_PORT port) { CSerial::begin(bps, port); switch (port) { case SCI_SCI0P2x: sci = &SCI0; break; case SCI_SCI1JTAG: sci = &SCI1; break; case SCI_SCI2A: case SCI_SCI2B: sci = &SCI2; break; case SCI_SCI6A: case SCI_SCI6B: sci = &SCI6; break; default: sci = NULL; break; } if (sci != NULL) { sci->SCR.BIT.TIE = 0; // TXI 割り込み禁止 sci->SCR.BIT.TEIE = 0; // TEI 割り込み禁止 } } // 送信するデータをバッファリングせず、TDR が空になるまで待って送信 size_t write(unsigned char val) { if (sci != NULL) { // TDR が空になるまで待つ while (sci->SSR.BIT.TEND == 0) { ; } // 送信データ書き込み sci->TDR = val; return 1; } else { return 0; } } }; #endif // PC とのシリアル通信オブジェクト static CSerial PcSerial; // KURUMI とのシリアル通信オブジェクト #if UseCMySerial static CMySerial KurumiSerial; #else static CSerial KurumiSerial; #endif // 通信タイムアウト計測用変数 static long lastTimer = -1; // タイマー割り込みによるリセット監視 static void timer() { // 青タクトスイッチが押されるか、通信が 500m 秒途絶えたら SAKURA をリセット if (!digitalRead(PIN_SW) || (lastTimer >= 0 && (unsigned short)(timer_get_ms() - lastTimer) >= 500)) { system_reboot(REBOOT_USERAPP); } } // SCI への設定変更 static void setupSCI(volatile struct st_sci0* sci, unsigned int baudRate) { // 送受信禁止 sci->SCR.BIT.TE = 0; sci->SCR.BIT.RE = 0; // 送信ストップビット長を 2 にする sci->SMR.BIT.STOP = 1; // ボーレート設定 sci->SMR.BIT.CKS = 0; // n = 0 sci->SEMR.BIT.ABCS = 1; // 調歩同期基本クロックセレクトビットを 1 にする sci->BRR = (48 * 1000000 / (32 / 2) /*+ (baudRate / 2)*/) / baudRate - 1; // ビットレートレジスタを設定 // 送受信許可 sci->SCR.BIT.TE = 1; sci->SCR.BIT.RE = 1; } void setup() { // ステータス表示 LED 初期化 for (int i = 0; i < 4; i++) { pinMode(PIN_LED0 + i, OUTPUT); digitalWrite(PIN_LED0 + i, LOW); } // PC 接続ポート設定 PcSerial.begin(DefaultBaudRate); sci_convert_crlf_ex(PcSerial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする // TXD 出力ポート設定 pinMode(PIN_TXD, OUTPUT); digitalWrite(PIN_TXD, HIGH); // RESET 出力ポート設定 pinMode(PIN_RESET, OUTPUT); digitalWrite(PIN_RESET, HIGH); // SAKURA の青タクトスイッチを SAKURA のリセットに使用 pinMode(PIN_SW, INPUT); // リセット処理の監視処理をタイマー割り込みに登録 timer_regist_userfunc(timer); // ステータス表示 LED0 のみ点灯(書き込み待ち) for (int i = 0; i < 4; i++) { digitalWrite(PIN_LED0 + i, (i == 0) ? HIGH : LOW); } // モード引き込みの際に PC から 0x00 が送信されてくる筈なので待つ while (!PcSerial.available() || PcSerial.read() != 0x00) { ; } // フラッシュ・メモリ・プログラミング・モードへの引き込み const int tRT = 723; const int tTM = 16; const int tMB = 62; digitalWrite(PIN_TXD, LOW); digitalWrite(PIN_RESET, LOW); digitalWrite(PIN_RESET, HIGH); delayMicroseconds(tRT); digitalWrite(PIN_TXD, HIGH); delayMicroseconds(tTM); digitalWrite(PIN_TXD, LOW); delayMicroseconds((1 + 8) * 1000000 / DefaultBaudRate); delayMicroseconds(tMB); // KURUMI 接続ポート設定 KurumiSerial.begin(DefaultBaudRate, SCI_SCI0P2x); sci_convert_crlf_ex(KurumiSerial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする setupSCI(&SCI0, DefaultBaudRate); } void loop() { // PC から来たコマンド/データ・フレームを KURUMI に送る if (PcSerial.available()) { // コマンド/データ・フレームを格納するバッファ byte buf[1000]; // コマンド/データ・フレームを読み込む for (int i = 0; i <= 1 || i < (byte(buf[1] - 1) + 1 + 4); i++) { while (!PcSerial.available()) { ; } buf[i] = PcSerial.read(); } #if MainBaudRate != DefaultBaudRate // Baud Rate Set コマンドだったのなら、ボー・レート設定データ(D01)を変更する if (buf[0] == 0x01 && buf[1] == 0x03 && buf[2] == 0x9a) { buf[5] += buf[3]; #if MainBaudRate == 250000 buf[3] = 0x01; #elif MainBaudRate == 500000 buf[3] = 0x02; #elif MainBaudRate == 1000000 buf[3] = 0x03; #else #error #endif buf[5] -= buf[3]; } #endif // コマンド/データ・フレームを KURUMI に送る for (int i = 0; i < (byte(buf[1] - 1) + 1 + 4); i++) { KurumiSerial.write(buf[i]); } // KURUMI から来たステータス・フレームを PC に送る int len = 0; for (int i = 0; i <= 1 || i < len; i++) { while (!KurumiSerial.available()) { ; } byte d = KurumiSerial.read(); PcSerial.write(d); if (i == 1) { len = d + 4; } } // PC から来たコマンド・フレームが Baud Rate Set コマンドだったのなら、パラメータに応じてボーレートを変更する if (buf[0] == 0x01 && buf[1] == 0x03 && buf[2] == 0x9a && (buf[3] >= 0x00 && buf[3] <= 0x03)) { static const unsigned long baudRateTable[] = { 115200, 250000, 500000, 1000000, }; setupSCI(&SCI0, baudRateTable[buf[3]]); } // ステータス表示 LED アニメーション(転送中) static int knight2k[][4] = { {10, 50, 250, 0}, {0, 10, 50, 250}, {0, 0, 250, 50}, {0, 250, 50, 10}, {250, 50, 10, 0}, {50, 250, 0, 0}, }; int i = (timer_get_ms() / 100) % (sizeof(knight2k) / sizeof(knight2k[0])); for (int j = 0; j < 4; j++) { analogWrite(PIN_LED0 + j, knight2k[i][j]); } // 通信時刻更新 lastTimer = timer_get_ms(); } // KURUMI からデータ・フレームが来たら PC に送る if (KurumiSerial.available()) { int len = 0; for (int i = 0; i <= 1 || i < len; i++) { while (!KurumiSerial.available()) { ; } byte d = KurumiSerial.read(); PcSerial.write(d); if (i == 1) { len = d + 4; } } } }
1Mbps でも安定して書き込みできるようなったっぽ。
/*GR-SAKURA Sketch Template Version: V1.06*/ #include <rxduino.h> #include <iodefine_gcc63n.h> #define PIN_RXD 0 // KURUMI からのシリアル通信受信ピン #define PIN_TXD 1 // KURUMI へのシリアル通信送信ピン #define PIN_RESET 2 // KURUMI リセットピン #define UseCMySerial 1 // CMySerial 使用スイッチ #define UseStatusDisplay 1 // ステータス表示使用スイッチ #define DefaultBaudRate 115200 // UART 通信の初期ボー・レート //#define MainBaudRate 115200 // UART 通信のボー・レート 115200bps //#define MainBaudRate 250000 // UART 通信のボー・レート 250kbps #define MainBaudRate 500000 // UART 通信のボー・レート 500kbps (オススメ) //#define MainBaudRate 1000000 // UART 通信のボー・レート 1Mbps #if UseCMySerial // CSerial の送信バッファの扱いかなんかで不具合があるクサイのでそれの代替 class CMySerial : public CSerial { private: volatile struct st_sci0* sci; public: CMySerial() : CSerial() { sci = NULL; } void begin(int bps, SCI_PORT port) { CSerial::begin(bps, port); switch (port) { case SCI_SCI0P2x: sci = &SCI0; break; case SCI_SCI1JTAG: sci = &SCI1; break; case SCI_SCI2A: case SCI_SCI2B: sci = &SCI2; break; case SCI_SCI6A: case SCI_SCI6B: sci = &SCI6; break; default: sci = NULL; break; } if (sci != NULL) { sci->SCR.BIT.TIE = 0; // TXI 割り込み禁止 sci->SCR.BIT.TEIE = 0; // TEI 割り込み禁止 } } // 送信するデータをバッファリングせず、TDR が空になるまで待って送信 size_t write(unsigned char val) { if (sci != NULL) { // TDR が空になるまで待つ while (sci->SSR.BIT.TEND == 0) { ; } // 送信データ書き込み sci->TDR = val; return 1; } else { return 0; } } }; #endif // PC とのシリアル通信オブジェクト static CSerial PcSerial; // KURUMI とのシリアル通信オブジェクト #if UseCMySerial static CMySerial KurumiSerial; #else static CSerial KurumiSerial; #endif // 通信タイムアウト計測用変数 static long lastTimer = -1; // タイマー割り込みによるリセット監視 static void timer() { // 青タクトスイッチが押されるか、通信が 500m 秒途絶えたら SAKURA をリセット if (!digitalRead(PIN_SW) || (lastTimer >= 0 && (unsigned short)(timer_get_ms() - lastTimer) >= 500)) { system_reboot(REBOOT_USERAPP); } } // SCI への設定変更 static void setupSCI(volatile struct st_sci0* sci, unsigned int baudRate) { // 送受信禁止 sci->SCR.BIT.TE = 0; sci->SCR.BIT.RE = 0; // 送信ストップビット長を 2 にする sci->SMR.BIT.STOP = 1; // ボーレート設定 sci->SMR.BIT.CKS = 0; // n = 0 sci->SEMR.BIT.ABCS = 1; // 調歩同期基本クロックセレクトビットを 1 にする sci->BRR = (48 * 1000000 / (32 / 2) + (baudRate / 2)) / baudRate - 1; // ビットレートレジスタを設定 // 送受信許可 sci->SCR.BIT.TE = 1; sci->SCR.BIT.RE = 1; } void setup() { #if UseStatusDisplay // ステータス表示 LED 初期化 for (int i = 0; i < 4; i++) { pinMode(PIN_LED0 + i, OUTPUT); digitalWrite(PIN_LED0 + i, LOW); } #endif // PC 接続ポート設定 PcSerial.begin(DefaultBaudRate); sci_convert_crlf_ex(PcSerial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする // TXD 出力ポート設定 pinMode(PIN_TXD, OUTPUT); digitalWrite(PIN_TXD, HIGH); // RESET 出力ポート設定 pinMode(PIN_RESET, OUTPUT); digitalWrite(PIN_RESET, HIGH); // SAKURA の青タクトスイッチを SAKURA のリセットに使用 pinMode(PIN_SW, INPUT); // リセット処理の監視処理をタイマー割り込みに登録 timer_regist_userfunc(timer); #if UseStatusDisplay // ステータス表示 LED0 のみ点灯(書き込み待ち) for (int i = 0; i < 4; i++) { digitalWrite(PIN_LED0 + i, (i == 0) ? HIGH : LOW); } #endif // モード引き込みの際に PC から 0x00 が送信されてくる筈なので待つ while (!PcSerial.available() || PcSerial.read() != 0x00) { ; } // フラッシュ・メモリ・プログラミング・モードへの引き込み const int tRT = 723; const int tTM = 16; const int tMB = 62; digitalWrite(PIN_TXD, LOW); digitalWrite(PIN_RESET, LOW); digitalWrite(PIN_RESET, HIGH); delayMicroseconds(tRT); digitalWrite(PIN_TXD, HIGH); delayMicroseconds(tTM); digitalWrite(PIN_TXD, LOW); delayMicroseconds((1 + 8) * 1000000 / DefaultBaudRate); delayMicroseconds(tMB); // KURUMI 接続ポート設定 KurumiSerial.begin(DefaultBaudRate, SCI_SCI0P2x); sci_convert_crlf_ex(KurumiSerial.get_handle(), CRLF_NONE, CRLF_NONE); // バイナリを通せるようにする setupSCI(&SCI0, DefaultBaudRate); } void loop() { // PC から来たコマンド/データ・フレームを KURUMI に送る if (PcSerial.available()) { // コマンド/データ・フレームを格納するバッファ byte buf[1000]; // コマンド/データ・フレームを読み込む for (int i = 0; i <= 1 || i < (byte(buf[1] - 1) + 1 + 4); i++) { while (!PcSerial.available()) { ; } buf[i] = PcSerial.read(); } #if MainBaudRate != DefaultBaudRate // Baud Rate Set コマンドだったのなら、ボー・レート設定データ(D01)を変更する if (buf[0] == 0x01 && buf[1] == 0x03 && buf[2] == 0x9a) { buf[5] += buf[3]; #if MainBaudRate == 250000 buf[3] = 0x01; #elif MainBaudRate == 500000 buf[3] = 0x02; #elif MainBaudRate == 1000000 buf[3] = 0x03; #else #error #endif buf[5] -= buf[3]; } #endif // コマンド/データ・フレームを KURUMI に送る for (int i = 0; i < (byte(buf[1] - 1) + 1 + 4); i++) { KurumiSerial.write(buf[i]); } // KURUMI から来たステータス・フレームを PC に送る int len = 0; for (int i = 0; i <= 1 || i < len; i++) { while (!KurumiSerial.available()) { ; } byte d = KurumiSerial.read(); PcSerial.write(d); if (i == 1) { len = d + 4; } } // PC から来たコマンド・フレームが Baud Rate Set コマンドだったのなら、パラメータに応じてボーレートを変更する if (buf[0] == 0x01 && buf[1] == 0x03 && buf[2] == 0x9a && (buf[3] >= 0x00 && buf[3] <= 0x03)) { static const unsigned long baudRateTable[] = { 115200, 250000, 500000, 1000000, }; setupSCI(&SCI0, baudRateTable[buf[3]]); } #if UseStatusDisplay // ステータス表示 LED アニメーション(転送中) int i = (timer_get_ms() / 100) & 7; for (int j = 0; j < 4; j++) { digitalWrite(PIN_LED0 + j, j == (i & 4 ? 7 - i : i & 3) ? HIGH : LOW); } #endif // 通信時刻更新 lastTimer = timer_get_ms(); } // KURUMI からデータ・フレームが来たら PC に送る if (KurumiSerial.available()) { int len = 0; for (int i = 0; i <= 1 || i < len; i++) { while (!KurumiSerial.available()) { ; } byte d = KurumiSerial.read(); PcSerial.write(d); if (i == 1) { len = d + 4; } } } }