RX64MでSD(TF)カードにアクセスする
RX64MにはSDホストインタフェースが搭載されています。
以前は、ライセンスの関係で一般には使用出来なかった様ですが、最近FITモジュールが公開されていますので、さっそく使用してみたいと思います。
使用したバージョンは以下の通りで、それぞれのFITモジュールを設定していきます。
r_sdc_sdmem_rx 3.00
r_sdhi_rx 2.06
WP端子を使用しない場合はチェックを外します。
アクティブの変更は出来ないようなので、使用する場合は注意します。
r_tfat_driver_rx 1.08
r_tfat_rx 4.00
[設定項目なし]
ソフトウエアについては、システムタイマを使っているので、以下のファイルをインクルードします。
1 2 3 4 5 6 7 8 9 10 |
//システムタイマ #include "r_sys_time_rx_if.h" //SDC #include "r_sdhi_rx_if.h" #include "r_sdhi_rx_pinset.h" #include "r_sdc_sd_rx_if.h" #include "r_sdc_sd_rx_config.h" //FAT #include "r_tfat_driver_rx_if.h" #include "r_tfat_driver_rx_config.h" |
SDカード制御用のソースは、下記の様に作成しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
#define SD_CARD_DEBUG_PRINT 1 //デバッグ用 Printfの有効化 #define SD_CARD_DEV_NO 0 //SDカード デバイス番号 #define SD_CARD_DRV_LETTER "0:" //SDカード ドライブ番号(FatFs) #define SD_POWER_PORT PORT1.PODR.BIT.B0 //SDカード電源制御ポート FATFS SD_CARD_FATFS; //SDカード ファイルシステム uint32_t SD_CARD_WORK_MEM[50]; //SDカード ワークエリア(200Byte必要) unsigned short SD_CARD_POWER_WAIT; //SDカード 電源投入タイマ unsigned short SD_CARD_ERR_STATUS = 0; //SDカード エラーステータス unsigned short SD_CARD_READY = 0; //SDカード 準備テータス //SDカード 電源初期化 sdc_sd_status_t sd_card_power_init(uint32_t card_no){ if (SDC_SD_CARD_NO0 == card_no){ //User must create processing for device number 1 or later. SD_POWER_PORT = 0; //SD-POW } return SDC_SD_SUCCESS; } //SDカード 電源 ON sdc_sd_status_t sd_card_power_on(uint32_t card_no){ if (SDC_SD_CARD_NO0 == card_no){ //User must create processing for device number 1 or later. SD_POWER_PORT = 1; //SD-POW } //R_BSP_SoftwareDelay(10, BSP_DELAY_MILLISECS); //Supplies the Power to the SD Card and waits. SD_CARD_POWER_WAIT = 10; return SDC_SD_SUCCESS; } //SDカード 電源 OFF sdc_sd_status_t sd_card_power_off(uint32_t card_no){ if (SDC_SD_CARD_NO0 == card_no){ //User must create processing for device number 1 or later. SD_POWER_PORT = 0; //SD-POW } //R_BSP_SoftwareDelay(1, BSP_DELAY_MILLISECS); //Supplies the Power to the SD Card and waits. return SDC_SD_SUCCESS; } //カード検出(CD)コールバック sdc_sd_status_t sd_card_cd_callback (int32_t cd){ uint32_t card_no; R_SDC_SD_CdInt(SD_CARD_DEV_NO, SDC_SD_CD_INT_DISABLE, 0); return SDC_SD_SUCCESS; } //カード状態変化コールバック sdc_sd_status_t sd_card_status_callback (int32_t channel){ return SDC_SD_SUCCESS; } //エラー検出 void sd_card_error_trap (uint32_t sdc_sd_card_no){ sdc_sd_status_t err_code; err_code = R_SDC_SD_GetErrCode(sdc_sd_card_no); #ifdef SD_CARD_DEBUG_PRINT printf("ERROR: error code (sdc_sd_status_t) is %d.\n", err_code); #endif SD_CARD_ERR_STATUS |= 0x0020; } //タイマ処理 void sd_card_1ms_interval(void){ if(SD_CARD_POWER_WAIT) SD_CARD_POWER_WAIT--; r_sdc_sd_1msInterval(); } //SDカードの初期化 void sd_card_init(void){ sdc_sd_status_t sdc_sd_status; uint32_t cmt_channel; bool cmt_ret; //1mS周期割り込みの登録 //cmt_ret = R_CMT_CreatePeriodic(1000,(void(*)(void*))R_SDC_SD_1msInterval, &cmt_channel); cmt_ret = R_CMT_CreatePeriodic(1000,(void(*)(void*))sd_card_1ms_interval, &cmt_channel); if(cmt_ret != true){ SD_CARD_ERR_STATUS |= 0x0001; } //SDHI インタフェースの初期化 R_SDHI_PinSetInit(); //SDHI 端子の初期設定 sd_card_power_init(SD_CARD_DEV_NO); //カード電源初期化 //SD メモリカードドライバの初期化 sdc_sd_status = R_SDC_SD_Open(SD_CARD_DEV_NO, SD_CARD_DEV_NO, &SD_CARD_WORK_MEM); if(sdc_sd_status != SDC_SD_SUCCESS){ #ifdef SD_CARD_DEBUG_PRINT printf("ERROR: R_SDC_SD_Open. Error code (sdc_sd_status_t) is %d.\n", sdc_sd_status); #endif SD_CARD_ERR_STATUS |= 0x0010; } sdc_sd_status = R_SDC_SD_CdInt(SD_CARD_DEV_NO, SDC_SD_CD_INT_ENABLE, sd_card_cd_callback); if (SDC_SD_SUCCESS != sdc_sd_status){ sd_card_error_trap(SD_CARD_DEV_NO); } //sdc_sd_status = R_SDC_SD_IntCallback(SD_CARD_DEV_NO, sd_card_status_callback); sdc_sd_status = R_SDC_SD_IntCallback(SD_CARD_DEV_NO, NULL); if (SDC_SD_SUCCESS != sdc_sd_status){ sd_card_error_trap(SD_CARD_DEV_NO); } } //SDカード検出処理 void sd_card_task(void){ static short init_status = 0; //初期化状態フラグ static sdc_sd_status_t pre_detection_status = SDC_SD_SUCCESS; //カード検出前回値 sdc_sd_status_t detection_status; sdc_sd_status_t sdc_sd_status; sdc_sd_cfg_t sdc_sd_config; FRESULT f_res; //カード検出状態の確認 detection_status = R_SDC_SD_GetCardDetection(SD_CARD_DEV_NO); if(pre_detection_status != detection_status){ pre_detection_status = detection_status; if(detection_status == SDC_SD_SUCCESS){ //カード検出時 #ifdef SD_CARD_DEBUG_PRINT printf("Detected attached SD card.\n"); #endif sd_card_power_on(SD_CARD_DEV_NO); //カード電源投入 init_status = 1; }else{ //カード未検出時 #ifdef SD_CARD_DEBUG_PRINT printf("Detected detached SD card.\n"); #endif sdc_sd_status = R_SDC_SD_End(SD_CARD_DEV_NO, SDC_SD_MODE_MEM); if (SDC_SD_SUCCESS != sdc_sd_status){ sd_card_error_trap(SD_CARD_DEV_NO); } init_status = 0; sd_card_power_off(SD_CARD_DEV_NO); SD_CARD_READY = 0; } } //カード初期化処理 if(init_status == 1){ if(SD_CARD_POWER_WAIT == 0){ //電源投入後安定化待ち R_SDHI_PinSetTransfer(); //ホストを転送可能状態にする init_status++; } }else if(init_status){ sdc_sd_config.mode = SDC_SD_CFG_DRIVER_MODE; sdc_sd_config.voltage = SDC_SD_VOLT_3_3; sdc_sd_status = R_SDC_SD_Initialize(SD_CARD_DEV_NO, &sdc_sd_config, SDC_SD_MODE_MEM); if (SDC_SD_SUCCESS == sdc_sd_status){ init_status = 0; f_res = f_mount(&SD_CARD_FATFS, SD_CARD_DRV_LETTER, 0); if(f_res == FR_OK){ SD_CARD_READY = 1; }else{ SD_CARD_ERR_STATUS |= 0x0400; } }else{ sdc_sd_status = R_SDC_SD_End(SD_CARD_DEV_NO, SDC_SD_MODE_MEM); if (SDC_SD_SUCCESS != sdc_sd_status){ sd_card_error_trap(SD_CARD_DEV_NO); } if(init_status++ > 10000){ init_status = 0; SD_CARD_ERR_STATUS |= 0x0100; SD_CARD_READY = 0; } } } } |
初期化処理として、sd_card_init();を一度実行します。
その後はメインループにて、sd_card_task();を常時実行します。
カードの挿入を検出すると、SD_CARD_READY が1となり、アクセスが可能です。
ファイル操作自体は、ChaNさんのFatfsを使用しているので、そちらを参照します。
アプリケーションノートのサンプルをそのまま使用する場合は、こんな感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
void tfat_sample(void){ FIL g_file; FRESULT rst; UINT file_rw_cnt; uint32_t byte_count; uint16_t data_count; uint8_t buff[512]; /* Working buffer */ printf("Start TFAT sample.\n"); // Create the directory rst = f_mkdir("0:FLD1"); if (FR_OK != rst){ R_error(2, &rst); } // Create the file to be written rst = f_open( &g_file, path_txt, FA_CREATE_ALWAYS | FA_WRITE); if (FR_OK != rst){ R_error(3, &rst); } // Complete file open // Copy the contents to the newly created file rst = f_write( &g_file, (void *) filebuffer, sizeof(filebuffer), &file_rw_cnt); if (rst != FR_OK || file_rw_cnt < sizeof(filebuffer)){ R_error(4, &rst); } // file write complete // Close the file rst = f_close( &g_file); if (FR_OK != rst){ R_error(5, &rst); } /* Open the file to be read */ rst = f_open( &g_file, path_txt, FA_OPEN_ALWAYS | FA_READ); if (FR_OK != rst){ R_error(6, &rst); } /* Ensure that the file pointer points at beginning of the file */ rst = f_lseek( &g_file, 0); if (FR_OK != rst){ R_error(7, &rst); } /* Clear the counter before counting the no. of bytes read */ byte_count = 0; /* Repeat the read process until required no. of bytes are read */ while (byte_count < (sizeof(filebuffer) - 1)){ /* Read the file. 512 bytes at a time. */ rst = f_read( &g_file, (void *) buff, sizeof(buff), &file_rw_cnt); /* Check if the read operation was successful & the no. of bytes read by the function matches with the size of the R/W buffer */ if (rst != FR_OK || file_rw_cnt < sizeof(buff)){ R_error(8, &rst); }else{ /* Compare the contents of the file with the ROM data */ for (data_count = 0; data_count < sizeof(buff); data_count++){ if (buff[data_count] != filebuffer[byte_count + data_count]){ /* error indication */ /* explicit error data, address */ R_error(9, &rst); } } /* verify complete */ /* ================== */ } /* Update the counter with the total no. of bytes read from the file */ byte_count += file_rw_cnt; } /* Close the file */ rst = f_close( &g_file); if (FR_OK != rst){ R_error(10, &rst); } printf("Finished TFAT sample.\n"); } |
あとは、const uint8_t filebuffer[] = {・・・} に書き込むダミーデータを用意し、
エラー表示用のstatic void R_error (uint8_t err_code, FRESULT *rst){} 関数を用意します。
標準のファイルシステムがfatfsになったので、使いやすくなりました。
ディスカッション
コメント一覧
まだ、コメントがありません