Renesas Rulz
Renesas Rulz
  • User
    Join or sign in
  • Site
  • Search RenesasRulz.com
  • User
がじぇっとるねさすコミュニティ
がじぇっとるねさすコミュニティ
GR-KURUMI フォーラム EEPROM ライブラリで使用している pfdl.a 不具合報告
  • 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 6 replies
  • Subscribers 282 subscribers
  • Views 3966 views
  • Users 0 members are here
Options
  • Share
  • More
  • Cancel
Related Tags
  • Arduino Pro-mini
  • E1
  • GPS
  • GR-ADZUKI
  • GR-COTTON
  • GR-KURUMI
  • GR-KURUMI 書き込み
  • gr-sakura
  • Guthub
  • I2c
  • JPEG
  • Kirin
  • PMT
  • RL78 レジスタバンク
  • rx
  • S/Wシリアル
  • sd card
  • Serial2
  • WDT
  • webコンパイラ
  • xbee
  • コンパイル
  • シリコンマイク
  • 誤差補正
  • 音源
Related

EEPROM ライブラリで使用している pfdl.a 不具合報告

fujita nozomu
fujita nozomu over 4 years ago

GR-KURUMI の EEPROM ライブラリは pfdl.a という謎のライブラリをリンクし内部で使用しています。

ライブラリ本体の pfdl.a とヘッダファイルの pfdl.h と pfdl_types.h が標準のテンプレートに含まれるため EEPROM ライブラリを使用しなくとも pfdl.a が使用できそうですが、不具合、あるいは改善すべき点がみつかったので報告いたします。

ヘッダファイルの pfdl.h と pfdl_types.h は C++ のプログラムからインクルードされることを考慮されていないため、C++ のプログラムから利用するためには

extern "C" {
#include <pfdl.h>
#include <pfdl_types.h>
}

とする必要があります。

pfdl.a のバージョン文字列を取得(?)する PFDL_GetVersionString() という関数は

/*GR-KURUMI Sketch Template Version: V2.01*/
#include <Arduino.h>
extern "C" {
#include <pfdl.h>
#include <pfdl_types.h>
}

void setup()
{
    Serial.begin(9600);
    pfdl_u08* version = PFDL_GetVersionString();
    Serial.println((uint16_t)version, HEX);
    Serial.println((const char*)version);
}

void loop()
{
}

等とすれば利用できます。 

2行目が文字列で、1行目がそのアドレスということであり、ビルドの際に生成された .map ファイルを確認すると

 *(PFDL_COD)
 PFDL_COD       0x000085a6       0x1c ./gr_common/libraries/EEPROM/utility/pfdl.a(pfdl_version.o)
                0x000085a6                PFDL_GetVersionString
                0x000085a6                PFDL_GetVersionString
                0x000085af                PFDL_VERSION_STRING

文字列と関数の両方が PFDL_COD というセクションに配置されていることがわかります。

PFDL_GetVersionString() の関数プロトタイプ宣言は pfdl.h で定義されており

extern  pfdl_u08* PFDL_GetVersionString(void)  __attribute__ ((section ("PFDL_COD")));

となっていますが、PFDL_GetVersionString() の機能が ROM に配置された PFDL_VERSION_STRING のアドレスを返すのであれば

extern  const pfdl_u08* PFDL_GetVersionString(void)  __attribute__ ((section ("PFDL_COD")));

となっているべきです。

PFDL_COD セクションは gr_common/rl78_R5F100GJAFB.ld では

  .text           :
  {
    PROVIDE (_start = .);
    *(.text P .stub .text.* .gnu.linkonce.t.*)
    *(PFDL_COD)
    ; KEEP(*reset_program.o(.text))
    KEEP (*(.text.*personality*))
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
    *(.interp .hash .dynsym .dynstr .gnu.version*)
    PROVIDE (__etext = .);
    PROVIDE (_etext = .);
    PROVIDE (etext = .);
    . = ALIGN(2);
    KEEP (*(.init))
    KEEP (*(.fini))
  } > ROM

と定義されており、.text セクションの次に配置されるようなっていますが、.text セクションの次ではリンクした際に RL78/G13 の Mirror 領域に配置される保証がなく、.text セクションがある程度の大きさになった場合、PFDL_COD セクションが Mirror 領域を超えて PFDL_GetVersionString() で取得した文字列 PFDL_VERSION_STRING が参照できなくなります。

/*GR-KURUMI Sketch Template Version: V2.01*/
#include <Arduino.h>
extern "C" {
#include <pfdl.h>
#include <pfdl_types.h>
}

void setup()
{
    Serial.begin(9600);
    pfdl_u08* version = PFDL_GetVersionString();
    Serial.println((uint16_t)version, HEX);
    Serial.println((const char*)version);
}

void loop()
{
    __asm __volatile(
        "    .rept 0x3000\n"
        "        nop\n"
        "    .endr\n"
    );
}

PFDL_VERSION_STRING は Mirror 領域に配置される標準の .rodata セクションか、あるいは別名の Mirror 領域に配置されるセクションに配置するべきでしょう。

pfdl.a に含まれる関数のコードは PFDL_COD セクションに配置されていますが、これも同様に .text セクションか、別名のセクションに配置するべきでしょう。現状の pfdl.a のまゝ PFDL_COD セクション全体を Mirror 領域に配置する方法も考えられますが、Mirror 領域で参照できる ROM の領域は容量全体の一部でしかなく、そこにコードを配置するのは勿体ないことです。文字列とコードはセクションを別にするべきです。

まとめると

  • ヘッダファイルは C++ に対応するべき
  • PFDL_GetVersionString() の関数プロトタイプ宣言を修正するべき
  • PFDL_GetVersionString() が返す文字列は Mirror 領域に配置するべき
  • pfdl.a で提供される関数のコードは .text セクション等に配置するべき

以上です。

  • Reply
  • Cancel
  • Cancel
Parents
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago
    Fujitaさん、なるほどご指摘ありがとうございます。次版で取り入れるようにしたいと思います。

    もともとのダウンロードサイトに行って、最新を確認したらV1.05になってますね。失礼しました。
    www2.renesas.eu/.../

    リンカースクリプトのサンプルには以下のように絶対アドレスでPFDL_CODが配置されるようになってました。
    PFDL_COD 0x1000 : AT (0x1000)
    {
    *(PFDL_COD)
    }
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki

    0x1000~ に配置されると RL78/G13 ではミラー領域を通して PFDL_VERSION_STRING にアクセスすることはできないので、ひょっとすると関数のプロトタイプ宣言は __far を加えた

    extern  __far const pfdl_u08* PFDL_GetVersionString(void)  __attribute__ ((section ("PFDL_COD")));

    が正しいのかもしれません。pfdl.a と仕様が同一かは不明ですが、『データ・フラッシュ・ライブラリ Type04 日本リリース版』として公開されている CC-RL 版と CA78K0R 版は関数プロトタイプ宣言が

    extern  __far pfdl_u08* __far PFDL_GetVersionString(void);
    

    となっており、__far 領域に配置された文字列を返すようなっています。

    尤も、現在の GNURL78 ツールチェーンでは C++ は __far ポインタのサポートがなく __far ポインタを返す関数は C++ からは使いづらいため、PFDL_GetVersionString() の仕様としては __far ポインタでない方が望ましいと思います。

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

    0x1000~ に配置されると RL78/G13 ではミラー領域を通して PFDL_VERSION_STRING にアクセスすることはできないので、ひょっとすると関数のプロトタイプ宣言は __far を加えた

    extern  __far const pfdl_u08* PFDL_GetVersionString(void)  __attribute__ ((section ("PFDL_COD")));

    が正しいのかもしれません。pfdl.a と仕様が同一かは不明ですが、『データ・フラッシュ・ライブラリ Type04 日本リリース版』として公開されている CC-RL 版と CA78K0R 版は関数プロトタイプ宣言が

    extern  __far pfdl_u08* __far PFDL_GetVersionString(void);
    

    となっており、__far 領域に配置された文字列を返すようなっています。

    尤も、現在の GNURL78 ツールチェーンでは C++ は __far ポインタのサポートがなく __far ポインタを返す関数は C++ からは使いづらいため、PFDL_GetVersionString() の仕様としては __far ポインタでない方が望ましいと思います。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Children
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu
    なるほど。確かにサンプルでは以下のように__far指定されてます。
    extern pfdl_u08 __far* PFDL_GetVersionString(void) __attribute__ ((section ("PFDL_COD")));

    アドレスはミラー対象の0x2000以降にして__farを取るという方向で合っていますかね?

    ちなみにpfdl.aはGNURL78 V13.02でコンパイルされていまして、今回の変更も適用したいため、提供元にソースで提供できないか聞き込み中です。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki

    pfdl_version.o で PFDL_GetVersionString() と PFDL_VERSION_STRING[] が同一のセクション PFDL_COD に配置されるコードは、例えば

    #include "pfdl_types.h"
    
    extern pfdl_u08 __far* PFDL_GetVersionString(void) __attribute__ ((section ("PFDL_COD")));
    
    __attribute__ ((section ("PFDL_COD"))) pfdl_u08 __far PFDL_VERSION_STRING[] = "DRL78T04U1301GV104";
    
    pfdl_u08 __far* PFDL_GetVersionString(void)
    {
        return PFDL_VERSION_STRING;
    }
    

    C では以上のような書き方になると思いますが、これをコンパイルすると

    $ rl78-elf-gcc -Wall -Wextra -Os -S pfdl_version.c
    pfdl_version.c:6:55: error: PFDL_VERSION_STRING causes a section type conflict with PFDL_GetVersionString
     __attribute__ ((section ("PFDL_COD"))) pfdl_u08 __far PFDL_VERSION_STRING[] = "DRL78T04U1301GV104";
                                                           ^
    pfdl_version.c:8:17: note: 'PFDL_GetVersionString' was declared here
     pfdl_u08 __far* PFDL_GetVersionString(void)
                     ^
    
    $
    

    セクションが矛盾しているというエラーとなってしまうので、オリジナルのソースはアセンブラで書いている気がします。

    セクション名を下記のように変更すれば

    #include "pfdl_types.h"
    
    extern pfdl_u08 __far* PFDL_GetVersionString(void) __attribute__ ((section (".text.pfdl_getversionstring")));
    
    __attribute__ ((section (".frodata.pfdl_version_string"))) pfdl_u08 __far PFDL_VERSION_STRING[] = "DRL78T04U1301GV104";
    
    pfdl_u08 __far* PFDL_GetVersionString(void)
    {
        return PFDL_VERSION_STRING;
    }
    

    セクションの矛盾が解消するためコンパイルは通る様になります。

    $ rl78-elf-gcc -Wall -Wextra -Os -S pfdl_version.c
    
    $
    

    また、セクション名が .text.~ や .rodata.~ となっていると、リンカスクリプトに特別なセクションを用意する必要がなくなる点でもメリットがあります。

    • PFDL_VERSION_STRING[] の配置を __far 領域でなくしたい
    • PFDL_VERSION_STRING[] は ROM 領域なので const を付加したい、
    • pfdl_u08 という型は char で良いのでは

    という点に対応するとすると pfdl_version.c の内容は以下が適当ではないかと思います。

    extern const char* PFDL_GetVersionString(void) __attribute__ ((section (".text.pfdl_getversionstring")));
    
    __attribute__ ((section (".rodata.pfdl_version_string"))) const char PFDL_VERSION_STRING[] = "DRL78T04U1301GV104";
    
    const char * PFDL_GetVersionString(void)
    {
        return PFDL_VERSION_STRING;
    }
    
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 4 years ago in reply to fujita nozomu
    Fujitaさん、ありがとうございます。
    ソース提供のリプライがなかなか来なく、それまでちょっと適用を待っていいでしょうか。const指定とC++対応をまず行いたいと思います。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 4 years ago in reply to Okamiya Yuuki
    > ちょっと適用を待っていいでしょうか。

    PFDL_GetVersionString() をすぐに使いたいという需要もなさそうなので急ぐものではないと思いますが、オリジナルへのフィードバックを期待したいです。現在の pfdl.a/pfdl.h はやっつけ感著しいので。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
サイト使用条件
プライバシーポリシー
お問い合わせ
© 2010-2022 Renesas Electronics Corporation. All rights reserved.