特殊電子回路株式会社

 

 

特電について

トップ ページ製品情報ブログ「JTAG日記」JTAG情報会社紹介

インデックス

 ボード図面

 クイックスタート

 主な仕様

 GCCの使い方

 ダウンロード

 RXduinoについて

 JTAG ICE

 注文情報

 ご注意

 

サンプルコード

 サンプルコード集

 

FatFSとライブラリ

RX62NでSDカードを操作するには、FatFSを使うのが最も手軽です。

 

FatFSとはChanさんの作成されたすばらしいライブラリで、組み込みCPU用でSDカードやFATが使えるようにするためのものです。ここではInterface誌に掲載されていたFatFSをGCC用に移植し、手軽に利用できるようライブラリ化しました。ソースコードはRXduinoアーカイブに入っています。

 

FatFSを使用するには、リンク時に./lib/libfatfs.aを一緒にリンクしてください。

 

使用方法

RX-MEGAのSDカードスロットに挿入したSDカードの内容を、シリアルポート経由で読み書き操作できます。

 

 

このプログラムを実行すると、シリアルコンソール上から、SDカードの中身を対話型で操作できます。

ins、dir、cd、type、read、createといったコマンドを用意しています。

 

・ins・・・ディスクが入れ替えられたことを通知する。

dir・・・ディレクトリ内のファイルの一覧を表示する。

cd dirname・・・カレントディレクトリを移動する。

type filename・・・ファイルの内容を表示する。

・read filename・・・ファイルをバイナリモードで読み出して、読み込み速度を測定する。

create filename・・・ファイルを作成して、コンソールから入力した内容を保存する。

 

 

なお、サポートしているファイル名は8.3形式です。ロングファイル名には対応していません。

(ロングファイル名を有効にすると、オブジェクトサイズが64kBほど増えてしまい、RAM内に納まらなくなる)

 

typeコマンドではファイルの内容を表示できます。

 

 

RX-MEGAでは、デフォルトではI/Oポートに挿入キーがつながっていないので、SDカードを交換したらinsコマンド打ってください。すると、新しいディスクに交換されたと認識されます。

 

 

readコマンドを使うと、読み出し速度を測定できます。

いろいろなカードで速度を測定してみると、750〜950kB/secの範囲でした。SPIバスの速度が24MHzなので、その3分の1程度しか出ていない計算になります。送受信の部分をアセンブラで書けば、おそらく2倍は速くなると思います。

 

 

ソースコードの公開(C言語)

プログラムを作成する上で、注意すべき点は2箇所あります。

 

FatFSには void disk_timerproc (void) という関数があります。この関数を、メインのプログラムからタイマ割り込みを使って1ms周期で呼び出してください。これを行わないと、タイムアウトの処理や、カードの抜き差し通知だけでなく、様々な箇所がうまく動きません。

 

また、FatFSではカード挿入状態をI/Oピン(実際にはINSというマクロ経由で)知ることになっています。しかし、RX-MEGAではすべての端子を自由にするという方針のため、デフォルトではカード挿入検出信号をI/Oポートにつないでいません。そこで、カードの挿入や抜き取りはユーザアプリケーションから指示することになります。

具体的には、disk_ins (int ins) という関数を用意したので、カードが挿入された場合をエミュレーションするには、disk_ins(1)を呼び出してください。カードが抜きとらられた場合をエミュレーションするにはdisk_ins(0)を呼び出してください。

 

// RX62NのGCCサンプルプログラム
// SDカードとFatFSの動作サンプル
// (C)Copyright 2011 特殊電子回路

// 特電HALを使う
#include "tkdn_hal.h"

#include <stdio.h>
#include <string.h>

// C言語で書かれたライブラリのヘッダファイルをインクルードする
#ifdef __cplusplus
extern "C" {
#endif

#include "ff.h"

void  disk_timerproc (void);
void  disk_ins (int ins);

#ifdef __cplusplus
}
#endif

int found_files;

FRESULT scan_files(char *path)
{
  FRESULT res;
  FILINFO fno;
  DIR dir;
  int i;
  char tmp[64];
  
  res = f_opendir(&dir, path); // ディレクトリを開く
  if (res == FR_OK) {
    i = strlen(path);
    for (;;) {
      res = f_readdir(&dir, &fno);// ディレクトリ項目を1個読み出す */
      // エラーまたは項目無しのときは抜ける
      if (res != FR_OK || fno.fname[0] == 0) break;
      // ドットエントリは無視 
      if (fno.fname[0] == '.') continue;  
      if(fno.fattrib & AM_DIR) sci_putc('D');
      else                     sci_putc(' ');
      if(fno.fattrib & AM_RDO) sci_putc('R');
      else                     sci_putc(' ');
      if(fno.fattrib & AM_HID) sci_putc('H');
      else                     sci_putc(' ');
      if(fno.fattrib & AM_SYS) sci_putc('S');
      else                     sci_putc(' ');
      if(fno.fattrib & AM_ARC) sci_putc('A');
      else                     sci_putc(' ');
      sci_putc(' ');
      
      if(1980 + (fno.fdate >> 9) - 2011 + 23 >= 1) {
        sprintf(tmp,"平成%2d年%2d月%2d日 ",
         1980 + (fno.fdate >> 9) - 2011 + 23,
         (fno.fdate >> 5) & 15 , fno.fdate & 31);
      }
      else {
        sprintf(tmp,"昭和%2d年%2d月%2d日 ",
         1980 + (fno.fdate >> 9) - 2011 + 23 + 63,
         (fno.fdate >> 5) & 15 , fno.fdate & 31);
      }
      
      sci_puts(tmp);
      sprintf(tmp,"%2d:%02d:%02d ",
        (fno.ftime >> 11),
        (fno.ftime >> 5) & 63 ,
        (fno.ftime & 31) << 1);
      sci_puts(tmp);
      
      sprintf(tmp,"%10ld ", fno.fsize);
      sci_puts(tmp);
      
      sci_puts(path);
      sci_puts("/");
      sci_puts(fno.fname);
      sci_puts("\n");
      found_files++;
    }
  }
  return res;
}

void timer_interrupt_function(void) {
  disk_timerproc();
}

int main() {
  sci_init(SCI_SCI0P2x,38400);
  sci_convert_crlf(CRLF_CRLF,CRLF_CRLF); // \nを\r\nに変換
  
  // ユーザの割り込み関数を登録する
  timer_regist_userfunc(timer_interrupt_function); 
  gpio_set_pinmode(PIN_BUZZ,1);
  
  sci_puts("\n---------------------------------------------\n");
  sci_puts("RX62NとGCCとFatFSのテスト \n");
  sci_puts("(C)Tokushu Denshi Kairo Inc.\n");
  sci_puts("Compiled on ");
  sci_puts(__DATE__);
  sci_puts(" ");
  sci_puts(__TIME__);
  sci_puts("\n---------------------------------------------\n");
  
  
  FATFS fatfs;      // File system object
  f_mount(0, &fatfs); // Register volume work area (never fails)
  
  while(1)    {
    const int BUFFER_SIZE = 512;
    char line[32];
    char buffer[BUFFER_SIZE];
    unsigned int bytes;
    
    sci_puts("(RX62N)");
    f_getcwd(buffer,255);
    sci_puts(buffer);
    sci_puts("$");
    
    sci_gets(line,31);
    
    char *cmd = strtok(line," ");
    char *param = strtok(0," ");
    
    if(!stricmp(cmd,"ins"))      {
      disk_ins(0);
      timer_wait_ms(100);
      disk_ins(1);
      sci_puts("ディスクの交換が行れたことを通知しました\n");
      continue;
    }
    
    if(!stricmp(cmd,"help")) {
      sci_puts(" ins             ディスクを交換を通知します\n");
      sci_puts(" dir             ファイルの一覧を表\示します\n");
      sci_puts(" cd     dirname  カレントディレクトリを移動します\n");
      sci_puts(" del    filename ファイルを削除します\n");
      sci_puts(" type   filename ファイルの内容を表\示します\n");
      sci_puts(" read   filename ファイルを読み出します\n");
      sci_puts(" create filename ファイルを作成します\n");
      continue;
    }
    
    if(!stricmp(cmd,"create")) {
      if(!param) {
  sci_puts("ファイル名が指定されていません\n");
  continue;
      }
      sci_puts("ファイルを生成します\n");
      sci_puts("\n--開始--\n");
      FIL fil;
      f_open(&fil,param,FA_CREATE_ALWAYS | FA_WRITE);
      
      int p = 0;
      while(1) {
  if(sci_rxcount() == 0) continue;
  char c = sci_getc();
  if(c == 0x03) {
    f_write(&fil,buffer,p,&bytes);
    p = 0;
    break;
  }
  
  sci_putc(c);
  buffer[p++] = c;
  
  if(p == BUFFER_SIZE) {
    f_write(&fil,buffer,p,&bytes);
    p = 0;
  }
      }
      
      f_close(&fil);
      sci_puts("\n--終了--\n");
      continue;
    }
    
    if(!stricmp(cmd,"type")) {
      if(!param) {
  sci_puts("ファイル名が指定されていません\n");
  continue;
      }
      sci_puts("ファイルを表\示します\n");
      sci_puts("\n--開始--\n");
      FIL fil;
      f_open(&fil,param,FA_READ);
      
      while(f_read(&fil,buffer,BUFFER_SIZE,&bytes) == FR_OK) {
  int i;
  for(i=0;i<bytes;i++) sci_putc(buffer[i]);
  if(bytes != BUFFER_SIZE) break;
  if(sci_rxcount()) break;
      }

      f_close(&fil);
      sci_puts("\n--終了--\n");
      continue;
    }

    if(!stricmp(cmd,"read")) {
      if(!param) {
  sci_puts("ファイル名が指定されていません\n");
  continue;
      }
      sci_puts("ファイルを読み出します\n");
      sci_puts("\n--開始--\n");
      int start_ms = timer_get_ms();
      int total_size = 0;
      FIL fil;
      f_open(&fil,param,FA_READ);

      while(f_read(&fil,buffer,BUFFER_SIZE,&bytes) == FR_OK) {
  total_size += bytes;
  if(bytes != BUFFER_SIZE) break;
  if(sci_rxcount()) break;
      }

      f_close(&fil);
      int end_ms = timer_get_ms();
      sci_puts("--終了--\n");
      
      sprintf(buffer,"%d bytes を %d msで読み込みました。",
        total_size,end_ms - start_ms);
      sci_puts(buffer);

      if(end_ms != start_ms) {
  sprintf(buffer,"速度は %dkB/sec です。\n",
    total_size / (end_ms - start_ms));
  sci_puts(buffer);
      }
      else {
  sci_puts("ファイルサイズが小さいため速度が測定できません\n");
      }
      
      continue;
    }

    if(!stricmp(cmd,"del")) {
      if(!param) {
  sci_puts("ファイル名が指定されていません\n");
  continue;
      }
      sprintf(buffer,"ファイル %s を削除します\n",param);
      sci_puts(buffer);
      
      f_unlink(param);
      continue;
    }
    
    if(!stricmp(cmd,"cd")) {
      if(!param) {
  sci_puts("移動先のディレクトリが指定されていません\n");
  continue;
      }
      f_getcwd(buffer,255);
      sci_puts("カレントディレクトリを");
      sci_puts(param);
      sci_puts("に移動します。\n");
      if(f_chdir(param) != FR_OK) {
  sci_puts("失敗\n");
  continue;
      }
      continue;
    }
    
    if(!stricmp(cmd,"dir")) {
      sci_puts("ファイルの一覧を表\示します\n");
      found_files = 0;
      
      if(param) {
  scan_files(param);
      }
      else {
  scan_files("0:");
      }
      
      sprintf(buffer,"\n%d個のファイルが見つかりました。\n",
       found_files);
      sci_puts(buffer);
      continue;
    }
  }
}

DWORD get_fattime (void)
{
  // No RTC feature provided.
  // Return a fixed value 2011/1/29 0:00:00
  return    ((DWORD)(2011 - 1980) << 25)
    | ((DWORD)1  << 21)
    | ((DWORD)29 << 16)
    | ((DWORD)12 << 11)
    | ((DWORD)34 << 5)
    | ((DWORD)56 >> 1);
}                                                                                                                

 

戻る

 


Copyright(C) 2011 TokushuDenshiKairo Inc. All rights reserved.