Renesas Rulz
Renesas Rulz
  • User
    Join or sign in
  • Site
  • Search RenesasRulz.com
  • User
がじぇっとるねさすコミュニティ
がじぇっとるねさすコミュニティ
GR-ADZUKI SoftwareSerial対応について
  • Forums
  • Files
  • がじぇっとるねさす ゆーざー会 - Wiki
  • Tags
  • More
  • Cancel
  • New

 

 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関連

 女子美コラボ

 その他

 ※プロデューサミーティング中

 作り方使い方資料

 イベント関連

 作品記事

 体験記事

 その他

 

 ライブラリ

 ツール

 その他・過去ファイル

  • Replies 19 replies
  • Subscribers 432 subscribers
  • Views 24457 views
  • Users 0 members are here
Options
  • Share
  • More
  • Cancel
Related Tags
  • auzuki
  • azuki
  • BASIC
  • GR-ADZUKI
  • GR-ADZUKI Node.js Johnny-Five
  • GR-ADZUKI S4A モーター
  • GR-ADZUKI USB
  • WDT
  • デジタルコンパス
  • リセット
  • 省電力
Related

SoftwareSerial対応について

Okamiya Yuuki
Okamiya Yuuki over 4 years ago

RL78/G13用ライブラリに対して、次版のV2.02にSoftwareSerialを入れようと考えています。FTDI USBシリアル変換モジュールを用いて4800, 9600, 57600, 115200bpsでの動作確認を行いました。ソースは以下の通りです。

GR-ADZUKIでは、USB通信用(pin0, pin1)、Wire(pin7, pin8)、モーター(pin9, pin10)でシリアルがつぶれてしまい、ESP8266やXBee等を使ったリモート制御がやりづらい状況でした。SoftwareSerialによって、これを解決したいという理由です。

なお、Arduino(AVR)ではピンチェンジ割り込みというほぼ全端子に外部割り込みが使える機能があるので、ArduinoではSoftwareSerialはほぼ全端子に使えますが、RL78/G13ではそんな機能がないため、シリアルの受信開始用に使用できるピンは外部割り込みがアサインされたpin2(INT0), pin3(INT1)だけとなります。送信はいずれのピンでも大丈夫です。

9月初旬にV-upを考えていますので、何かご意見、コメントありましたらよろしくお願いいたします。

pins_arduino.hも変更してます。

 

以下、サンプルです。

#include <Arduino.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);


// set the data rate for the SoftwareSerial port
mySerial.begin(115200);
}

void loop() { // run over and over
#if 0
mySerial.println("Hello, world?");
delay(100);
#else
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
#endif
}
  • Reply
  • Cancel
  • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago

    SoftwareSerial を使いたい状況というのは他の用途で既に使ってる等の事情で HardwareSerial に余裕がなくそれでも尚シリアル通信が使いたいという場合だと思いますが、

    GR-ADZUKIでは、USB通信用(pin0, pin1)、Wire(pin7, pin8)、モーター(pin9, pin10)でシリアルがつぶれてしまい、ESP8266やXBee等を使ったリモート制御がやりづらい状況でした。SoftwareSerialによって、これを解決したいという理由です。

    Arduno の SoftwareSerial は送受信時に割り込みを止める仕組みとなっており、↑のような他の通信と同時に使用する用途には向かないと思います。

    GR-SAKURA のSoftwareSerial がタイマー割り込みで全部を回す仕組みに組みなおした気がしますが、GR-ADZUKI も同様の方法を採るのが良いのでは。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago

    SoftwareSerial クラスの仕様ですが HardwareSerial クラスと同様の機能を提供すてべきと思います。較べてみると色々違いがあります。SoftwareSerial クラスを HardwareSerial  の派生クラスにするのが良いかもしれません。

    HardwareSerial クラスも見てみるとメンバ変数 _rx_buffer_head 等が public になってる等、わけわからんところがあるので見直すべきと思う箇所があります。

    HardwareSerial::begin() で受信と送信のバッファのサイズが指定できるよういつの間にかなっており、begin() と end() の中で malloc() と free() を呼んでいますがヒープを使用しない様ならないでしょうか? GNURL78 の標準のライブラリではスタックとヒープの領域が厳密に分けられておらず、ヒープ取得のリクエストがあるとスタックとヒープの共用の領域から「ある程度の容量」をヒープとして確保し、その中から要求された容量を確保する動作となるのでメモリの容量的に無駄があります。また、頻繁にヒープの取得と解放を繰り返すとヒープ領域が増大しスタック領域とクラッシュすることゝなるので、「なんか動くけど動かんプログラム」というものができてしまう危険性もあります。RL78 等の RAM の少ないマイコンで、標準関数でヒープを使うことは避けるべきと思います。begin() や end() の中で malloc()/free() するのではなく、ユーザーが静的か動的かで確保したバッファを指定できるようにするのが無難と思います。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu
    Fujitaさん、早速のコメントありがとうございます。
    Arduino側のSoftwareSerialのほぼ標準?になったようなので、あまりオリジナルから変えず、ちょっと様子を見たいです。
    www.arduino.cc/.../SoftwareSerial

    タイマーに余裕がないのも一つの理由なのですが、ArduinoとESP8266を組み合わせたサンプルは結構ありますので、例えばセンサー値を読んでクラウドにアップするなど、同時でなく順序処理で行うケースに対応したいです。「リモート制御」という表現がよくなかったですね。

    次にHardwareSerial側の可変バッファ構成についてですが、こちらはちょっと検討させてください。バッファ容量がアプリケーションに依存する→「なんか動くけど動かんプログラム」になることは確かだと思います。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to Okamiya Yuuki
    SoftwareSerialですが、115200bpsでFTDIとの通信はできるものの、ESP8266はうまくいかないようです。残念
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago

    > pins_arduino.hも変更してます。
    >
    > pins_arduino.h

    ↓ が追加されてますが

    const uint32_t PROGMEM port_to_output_PGM[] = {
    		0xFFF00,
    		0xFFF01,
    		0xFFF02,
    		0xFFF03,
    		0xFFF04,
    		0xFFF05,
    		0xFFF06,
    		0xFFF07,
    };
    
    const uint32_t PROGMEM port_to_input_PGM[] = {
    		0xFFF00,
    		0xFFF01,
    		0xFFF02,
    		0xFFF03,
    		0xFFF04,
    		0xFFF05,
    		0xFFF06,
    		0xFFF07,
    };
    

    ↓で参照するのはおかしいのでは?

    extern const uint16_t PROGMEM port_to_input_PGM[];
    extern const uint16_t PROGMEM port_to_output_PGM[];
    
    #define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
    #define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
    

    ビルドすると下記のエラーとなりました。

    gr_common/cores/pins_arduino.h:407:24: error: conflicting types for 'port_to_output_PGM'
     const uint32_t PROGMEM port_to_output_PGM[] = {
                            ^
    In file included from gr_common/cores/wiring_private.h:39:0,
                     from gr_common/cores/wiring_digital.c:31:
    gr_common/cores/Arduino.h:529:31: note: previous declaration of 'port_to_output_PGM' was here
     extern const uint16_t PROGMEM port_to_output_PGM[];
                                   ^
    In file included from gr_common/cores/Arduino.h:628:0,
                     from gr_common/cores/wiring_private.h:39,
                     from gr_common/cores/wiring_digital.c:31:
    gr_common/cores/pins_arduino.h:418:24: error: conflicting types for 'port_to_input_PGM'
     const uint32_t PROGMEM port_to_input_PGM[] = {
                            ^
    In file included from gr_common/cores/wiring_private.h:39:0,
                     from gr_common/cores/wiring_digital.c:31:
    gr_common/cores/Arduino.h:528:31: note: previous declaration of 'port_to_input_PGM' was here
     extern const uint16_t PROGMEM port_to_input_PGM[];
                                   ^
    make: *** [makefile:116: gr_common/cores/wiring_digital.o] Error 1
    make: *** Waiting for unfinished jobs....
    

    pins_arduino.h の変更は行わずに ↓ の変更で良い気がしますが。

    #define portOutputRegister(P) ( (volatile uint8_t *)( P0 + (P)) )
    #define portInputRegister(P) ( (volatile uint8_t *)( P0 + (P)) )
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki

    > SoftwareSerialですが、115200bpsでFTDIとの通信はできるものの、ESP8266はうまくいかないようです。

    ビルドすると通信速度に拠ってビット当たりディレイ時間の計算をしている箇所で

    In file included from gr_common/libraries/SoftwareSerial/SoftwareSerial.cpp:44:0:
    gr_common/libraries/SoftwareSerial/SoftwareSerial.cpp: In member function 'void SoftwareSerial::begin(long int)':
    ./gr_common/cores/Arduino.h:452:26: warning: integer overflow in expression [-Woverflow]
     #define F_CPU (32 * 1000 * 1000)
                              ^
    gr_common/libraries/SoftwareSerial/SoftwareSerial.cpp:330:25: note: in expansion of macro 'F_CPU'
       uint16_t bit_delay = (F_CPU / speed) / 9;
    

    以上の警告が出ますが

    #define F_CPU (32 * 1000 * 1000L)
    

    等する必要がある気がします。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu
    Fujitaさん、アドバイスをいただきありがとうございます。

    エラーの件、おっしゃる通りで変更したArduino.hを添付してませんでした。Arduino側の実装に合わせましたが、Fujitaさんの実装でよいと思いますね。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago

    SoftwareSerial.cpp の 時間待ち部分

    void _delay_loop_2(uint16_t __count)
    {
    	// todo: need to implement assemble at 9 cycles
    	volatile uint16_t count = __count;
    	while(count != 0) count--;
    }
    

    を GCC for Renesas 4.9.2.201701-GNURL78 を使用して web コンパイラでの makefile 通りのコンパイルオプションでコンパイルすると

    Disassembly of section .text._Z13_delay_loop_2t:
    
    00000000 <__Z13_delay_loop_2t>:
       0:   20 02                           subw    sp, #2
    
    00000002 <.LBB83>:
       2:   a8 06                           movw    ax, [sp+6]
    
    00000004 <.L20>:
       4:   b8 00                           movw    [sp+0], ax
       6:   44 00 00                        cmpw    ax, #0
       9:   61 f8                           sknz
       b:   ec 00 00 00                     br      !!0 <__Z13_delay_loop_2t>
       f:   a8 00                           movw    ax, [sp+0]
      11:   b1                              decw    ax
      12:   ec 00 00 00                     br      !!0 <__Z13_delay_loop_2t>
    
    00000016 <.L21>:
      16:   10 02                           addw    sp, #2
      18:   d7                              ret
    

    コメントにある通り 1 ループ 9 サイクルのコードが出力されますが、精度は粗く、コンパイル条件が変わると出力コードの内容も保証できないので

    void _delay_loop_2(uint16_t __count)
    {
        __asm __volatile(
            "    movw    ax, %0  \n"
            "    cmpw    ax, #0  \n"
            "    bz      $9f     \n"
            "0:                  \n"
            "    subw    ax, #1  \n"
            "    bnz     $0      \n"
            "9:                  \n"
            :
            : "r"(__count)
            : "ax"
        );
    }
    

    等とした方が良いと思います。1 ループ 5 サイクルとなるので、遅延時間を計算している箇所も

      // Precalculate the various delays, in number of 5-cycle delays
      uint16_t bit_delay = (F_CPU / speed) / 5;
    

    等と変更する必要があります。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki

    > SoftwareSerialですが、115200bpsでFTDIとの通信はできるものの、ESP8266はうまくいかないようです。

    SoftwareSerial::recv() と SoftwareSerial::write(uint8) が GNURL78 のアレな部分も相まってどう見ても精度が出る訳ないコードとなっているので、インラインアセンブラでも使うべきと思います。

    あと、SoftwareSerial::begin(long) の中の

        // Note that this code is a _lot_ slower, mostly due to bad register
        // allocation choices of gcc. This works up to 57600 on 16Mhz and
        // 38400 on 8Mhz.
        _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4);
        _rx_delay_intrabit = subtract_cap(bit_delay - 2, 11 / 4);
        _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4);
    

    は RL78/G13@32MHz 用に適当である気がしません。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to fujita nozomu

    ループの分岐先が間違ってたので訂正

    void _delay_loop_2(uint16_t __count)
    {
        __asm __volatile(
            "    movw    ax, %0  \n"
            "    cmpw    ax, #0  \n"
            "    bz      $9f     \n"
            "0:                  \n"
            "    subw    ax, #1  \n"
            "    bnz     $0b     \n"
            "9:                  \n"
            :
            : "r"(__count)
            : "ax"
        );
    }
    
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to fujita nozomu

    ローカルラベルに 0 は一時期の GNURL78 で使用できない不具合があったことを思い出したので更に修正

    void _delay_loop_2(uint16_t __count)
    {
        __asm __volatile(
            "    movw    ax, %0  \n"
            "    cmpw    ax, #0  \n"
            "    bz      $9f     \n"
            "1:                  \n"
            "    subw    ax, #1  \n"
            "    bnz     $1b     \n"
            "9:                  \n"
            :
            : "r"(__count)
            : "ax"
        );
    }
    
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to fujita nozomu

    _delay_loop_2() の 呼び出し ~ 復帰 のコスト等を考えると

      // Precalculate the various delays, in number of 5-cycle delays
      uint16_t bit_delay = (F_CPU / speed) / 5 - 2;
    

    くらいの調整を加味しても良いかも。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu

    Fujitaさん、ありがとうございます!ESP8266との通信に成功しました。アセンブルで精度を上げられたのがでかいです!

    アクセスポイントへの接続後のIP取得まででき、milkcocoaサービスへのデータアップまでいけました。ちょっとデータのアップが遅いため、途中でデータ化けが起きている可能性はありそうですが、微調整次第な気はします。以下、bit_delay値はTXをオシロを見つつ、8ビット単位で計算して115,200 Hzに近くなるように(-5)を入れてます。

    uint16_t bit_delay = (F_CPU / speed) / 5 - 5;

    ーーーーーーーーーーーーーーーーーーーーー

    wait...
    Milkcocoa SDK demo


    Connecting to WARPSTAR-1153D8
    FW Version:
    to station ok
    Join AP success
    IP: +CIFSR:STAIP,"192.168.0.9"
    +CIFSR:STAMAC,"18:fe:34:ef:08:e2"
    single ok
    milkcocoa on sucesss
    Connecting to MQTT... MQTT Connected!
    onpush
    28

    ーーーーーーーーーーーーーーーーーーーーーー

    以下、変更したソースです。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki
    webコンパイラの GR-KURUMI とその他 RL78系のライブラリが V2.02 に更新され SoftwareSerial が追加されたみたいですが

    > ちょっとデータのアップが遅いため、途中でデータ化けが起きている可能性はありそうですが、微調整次第な気はします。

    というのはどうなったのでしょうか? 中身一緒のようですが。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu
    すみません、パラメータを色々振って試したのですがダメでしたので、そのままアップさせていただいてます。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
>
サイト使用条件
プライバシーポリシー
お問い合わせ
© 2010-2022 Renesas Electronics Corporation. All rights reserved.