RXマイコン用、FatFsとシステムコール

データロガーの実装を進めるに中って、boost を使うようになった。
そうすると、どうしても「システムコール」を実装しなくてはならない状況にな
った。
これは、boost の動作で、ファイルを操作したり、標準出力を使っている為なの
だと思うが、リンク時一連のシステムコールがリンクできずににエラーを起こす。
※boost の内部設定を変更して、それらを使わないように「魔改造」する事も考
えられるが、それはそれで、大変と思うので、とりあえず、標準的な設定で何と
かなるよにしたい。

以前にSH2Aで、LCDの描画などを行った時にも、同じような事があり、実
装したので、どうすれば良いか、簡単に説明しておこうと思う。

まず、最低限必要なのが、標準入出力のしくみなどだ。

以下の関数を最低限実装する必要があるようだ、何か足りなければ、リンクエラ
ーが出るので、その都度追加すればよい。

int open(const char *path, int flags, ...);
int fstat(int file, struct stat *st);
int read(int file, void *ptr, int len);
int write(int file, const void *ptr, int len);
int lseek(int file, int offset, int dir);
int close(int file);
int isatty(int file);
void kill(int n, int m);
int getpid(int n);
void exit(int n);

また、固定のファイルディスクリプタとして以下がある:

stdin  : 0
stdout : 1
stderr : 2

これらは、オープンもクローズもできない、また、シークも必要ない。

「write」、「read」の中で、「file」が0、1、2の場合に、シリアル入出力へ
繋げば良いと思う。
「isatty」は、ファイルディスクリプターが端末を参照しているかをチェックす
る機能なので、これも実装しておく。
※そうすれば、「printf」は使えるようになる。(ただ、C++ ではあくまでも、
iostream が基本なのと、自分の実装では、format があるので必要無い、又、
iostream を使うようなコードを書くと、単純にメモリーが足りなくて、リンク
時にエラーを起こすだけではある)
※とりあえず、この程度なら、RL78やR8Cでも利用可能と思う。

//-----------------------------------------------------------------//
/*!
    @brief      ファイル記述子で指定されたファイルから指定バイトを読む
    @param[in]  file    ファイル記述子
    @param[in]  ptr     読み込み先
    @param[in]  len     読み込みバイト数
    @return     読み込みバイト数
*/
//-----------------------------------------------------------------//
int read(int file, void *ptr, int len)
{
    int l = 0;
    if(file >= 0 && file <= 2) {
        // stdin
        if(file == 0) {
            char *p = ptr;
            for(int i = 0; i < len; ++i) {
                *p++ = sci_getch();
            }
            errno = 0;
            l = len;
        }
    }
    return l;
}

//-----------------------------------------------------------------//
/*!
    @brief      ファイル記述子で指定されたファイルから指定バイトを書く
    @param[in]  file    ファイル記述子
    @param[in]  ptr     書き込み元
    @param[in]  len     書き込みバイト数
    @return     書き込みバイト数
*/
//-----------------------------------------------------------------//
int write(int file, const void *ptr, int len)
{
    int l = -1;
    if(file >= 0 && file <= 2) {
        if(file == 1 || file == 2) {
            const char *p = ptr;
            for(int i = 0; i < len; ++i) {
                char ch = *p++;
                sci_putch(ch);
            }
            l = len;
            errno = 0;
        }
    }
    return l;
}

//-----------------------------------------------------------------//
/*!
    @brief      ファイルディスクリプタが端末を参照しているかをチェックする
    @param[in]  file    ファイル記述子
    @return     端末を参照するオープンされたファイルディスクリプタ @n
                であれば 1 を返す。@n
                そうでなければ 0 を返し、 errno にエラーを示す値を設定する。
*/
//-----------------------------------------------------------------//
int isatty(int file)
{
    if(file >= 0 && file <= 2) {
        errno = 0;
        return 1;
    } else if(file < OPEN_MAX_) {
        errno = ENOTTY;
        return 0;
    }
    errno = EINVAL;
    return 0;
}

--------

FatFs を使って、SDカードにアクセスする場合は、GitHub の syscalls.cを参照してほしい。
RX24Tの場合、RAMは16Kしか無いので、記憶割り当てを実装するのは、
少しキビシイ、そこで、FatFsの設定では、「記憶割り当て」を使わない設
定にしている、そうすると、1個のファイルを開くのに必要なメモリーは、そこ
そこ大きく、最大オープン数を多く取るとスタテックにメモリーを消費する。
ファイルの先頭で、「OPEN_MAX_」を「4」と定義してある。
最大4つまでファイルを開く事ができる、通常これくらいあれば十分と思うが、
アプリにより最適な値を調整する必要があるかもしれない。
又、FatFSを使わない場合には、「FAT_FS」をコメントアウトして、
無効にする。

ファイルをオープンするパスは、UTF-8を使う、内部でShift_JIS
に変換されて、FatFSに渡される。

FatFsを使う場合、内部で「sdc_io」クラスと連携しているので、SDカード
の自動マウントなどを見守る必要がある。