diff --git a/build/libraries_sysmenu/errorLog/ARM9/src/errorLog.c b/build/libraries_sysmenu/errorLog/ARM9/src/errorLog.c index d643ee9f..ea06c435 100644 --- a/build/libraries_sysmenu/errorLog/ARM9/src/errorLog.c +++ b/build/libraries_sysmenu/errorLog/ARM9/src/errorLog.c @@ -45,29 +45,19 @@ typedef enum CheckStatus { CHECK_FAILED = 2 } CheckStatus; -// 既に書き込まれたエラーログを表現するためのエントリ -typedef struct ErrorLogEntry{ - // エラーのタイムスタンプ - int year; - int month; - int day; - char week[4]; // 曜日の3文字表現 - int hour; - int minute; - int second; - // エラーコード - int errorCode; -} ErrorLogEntry; -// ログエラーのエントリを持つ +/*-- global variables ----------------------*/ + +ErrorLogWork elWork; /*-- function prototype ----------------------*/ CheckStatus ELi_CheckAndCreateDirectory( const char *path ); -CheckStatus ELi_CheckAndCreateFile( FSFile *file, const char *path ); -int ELi_ReadEntry( FSFile *file, ErrorLogEntry *entry ); +CheckStatus ELi_CheckAndCreateFile( const char *path ); +int ELi_ReadEntry( void ); BOOL ELi_SetString( char *buf, ErrorLogEntry *entry ); -BOOL EL_addNewEntry( ErrorLogEntry *entry, int idx, int errorCode, RTCDate *date, RTCTime *time ); -BOOL ELi_WriteLog( FSFile *file ,ErrorLogEntry *entry, int numEntry ); +BOOL ELi_addNewEntry( int idx, int errorCode, RTCDate *date, RTCTime *time ); +void ELi_WriteLogToBuf( char *buf ); +BOOL ELi_WriteLogToFile( char *buf ); void ELi_fillSpace( char *buf, int bufsize ); static char *s_strWeek[7]; @@ -75,6 +65,81 @@ static char *s_strError[FATAL_ERROR_MAX]; +/*---------------------------------------------------------------------------* + Name: EL_Init + + Description: Errorlogライブラリ用の初期化関数です。 + + + Arguments: Alloc: メモリ確保用の関数です。 + Free: メモリ開放用の関数です。 + + Returns: 成功すればTRUEを、失敗すればFALSEを返します。 + *---------------------------------------------------------------------------*/ +BOOL EL_Init( void* (*AllocFunc) (u32) , void (*FreeFunc) (void*) ) +{ + SDK_POINTER_ASSERT(allocFunc); + SDK_POINTER_ASSERT(freeFunc); + + elWork.Alloc = AllocFunc; + elWork.Free = FreeFunc; + + // ログ読み出し用のバッファを確保 + elWork.entry = (ErrorLogEntry*) elWork.Alloc ( sizeof (ErrorLogEntry) * ERRORLOG_NUM_ENTRY ); + + if( !FS_IsAvailable() ) + { + // FSがInitされてなかったらInitする + FS_Init( FS_DMA_NOT_USE ); + } + + FS_InitFile( &elWork.file ); + + // ファイルの存在確認 + if( ELi_CheckAndCreateDirectory( ERRORLOG_DIRECTORYPATH ) == CHECK_FAILED ) + { + return FALSE; + } + + switch ( ELi_CheckAndCreateFile( ERRORLOG_FILEPATH ) ) + { + case CHECK_FAILED: + return FALSE; + break; + + case CHECK_EXIST: + // 既にログファイルが存在していたら、そこからログを読み出す + elWork.numEntry = ELi_ReadEntry(); + break; + + case CHECK_CREATE: + // 新規にファイルが作られたなら何もしなくていい + break; + } + + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: EL_End + + Description: Errorlogライブラリの終了処理を行います。 + 再度ELライブラリを利用するためにはEL_Initを呼ぶ必要があります。 + + Arguments: なし。 + + Returns: なし。 + *---------------------------------------------------------------------------*/ +void EL_End( void ) +{ + elWork.Free( elWork.entry ); + + if( !FS_CloseFile( &elWork.file ) ) + { + OS_TPrintf("EL Error: FS_CloseFile() failed.\n" ); + } +} + /*---------------------------------------------------------------------------* Name: EL_WriteErrorLog @@ -87,8 +152,6 @@ static char *s_strError[FATAL_ERROR_MAX]; *---------------------------------------------------------------------------*/ BOOL EL_WriteErrorLog( u64 errorCode ) { - FSFile file; - ErrorLogEntry entry[ERRORLOG_NUM_ENTRY]; // エラーエントリを持つリングバッファ int bufBeginPoint = 0; // リングバッファの開始点 int numEntry = 0; int counter = 0; @@ -96,37 +159,10 @@ BOOL EL_WriteErrorLog( u64 errorCode ) RTCDate date; RTCTime time; RTCResult rtcRes; - - if( !FS_IsAvailable() ) - { - // FSがInitされてなかったらInitする - FS_Init( FS_DMA_NOT_USE ); - } - - FS_InitFile( &file ); + char *writeBuf; - if( ELi_CheckAndCreateDirectory( ERRORLOG_DIRECTORYPATH ) == CHECK_FAILED ) - { - return FALSE; - } - - switch ( ELi_CheckAndCreateFile( &file, ERRORLOG_FILEPATH ) ) - { - case CHECK_FAILED: - return FALSE; - break; - - case CHECK_EXIST: - // 既にログファイルが存在していたら、そこからログを読み出す - numEntry = ELi_ReadEntry( &file, entry ); - break; - - case CHECK_CREATE: - // 新規にファイルが作られたなら何もしなくていい - break; - } - + writeBuf = (char*) elWork.Alloc( ERRORLOG_SIZE ); // 新しいログエントリを書き込むためのRTC if( ( rtcRes = RTC_GetDateTime( &date, &time )) != RTC_RESULT_SUCCESS) @@ -141,24 +177,73 @@ BOOL EL_WriteErrorLog( u64 errorCode ) if( ( errorCode >> counter ) & 0x1LL ) { // 末尾のビットが立っていたらエントリに入れてバッファ開始点を進める - EL_addNewEntry( entry, numEntry % ERRORLOG_NUM_ENTRY , counter , &date, &time ); - numEntry++; + ELi_addNewEntry( elWork.numEntry % ERRORLOG_NUM_ENTRY , counter , &date, &time ); + elWork.numEntry++; } } + // まずエントリをもとにバッファに書き込む + ELi_WriteLogToBuf( writeBuf ); + // 最終的にファイルを書き込む - if( !ELi_WriteLog( &file, entry, numEntry ) ) + if( !ELi_WriteLogToFile( writeBuf ) ) { return FALSE; } + elWork.Free( writeBuf ); + return TRUE; } +/*---------------------------------------------------------------------------* + Name: EL_getErrorLogNum + + Description: 読み出したエントリ数を取得します。 + + Arguments: なし。 + + Returns: ログファイルから読み出したエントリ数を返します。 + *---------------------------------------------------------------------------*/ + +int EL_getErrorLogNum() +{ + return elWork.numEntry; +} + + +/*---------------------------------------------------------------------------* + Name: EL_getErrorLog + + Description: 指定したナンバのエラーログエントリへのポインタを取得します。 + + Arguments: idx: エントリ番号の指定 + + Returns: idx番目のエントリへのポインタです。 + *---------------------------------------------------------------------------*/ + +const ErrorLogEntry* EL_getErrorLog( int idx ) +{ + return &elWork.entry[idx]; +} + +/*---------------------------------------------------------------------------* + Name: ELi_addNewEntry + + Description: エラーコードとRTCデータをエラーログのエントリに追加します。 + + Arguments: int: エントリを挿入するインデクス + errorCode: エラーコード + date: 日付データ + time: 時刻データ + + Returns: FATAL_ERROR_MAXを超えるエラーコードが渡された場合はFALSEを、 + それ以外のときはTRUEを返します。 + *---------------------------------------------------------------------------*/ -BOOL EL_addNewEntry( ErrorLogEntry *entry, int idx, int errorCode, RTCDate *date, RTCTime *time ) +BOOL ELi_addNewEntry( int idx, int errorCode, RTCDate *date, RTCTime *time ) { if( errorCode >= FATAL_ERROR_MAX ) @@ -168,14 +253,14 @@ BOOL EL_addNewEntry( ErrorLogEntry *entry, int idx, int errorCode, RTCDate *date return FALSE; } - entry[idx].year = (int)date->year; - entry[idx].month = (int)date->month; - entry[idx].day = (int)date->day; - STD_CopyLStringZeroFill( entry[idx].week, s_strWeek[ date->week ], 4 ); - entry[idx].hour = (int)time->hour; - entry[idx].minute = (int)time->minute; - entry[idx].second = (int)time->second; - entry[idx].errorCode = (int)errorCode; + elWork.entry[idx].year = (int)date->year; + elWork.entry[idx].month = (int)date->month; + elWork.entry[idx].day = (int)date->day; + STD_CopyLStringZeroFill( elWork.entry[idx].week, s_strWeek[ date->week ], 4 ); + elWork.entry[idx].hour = (int)time->hour; + elWork.entry[idx].minute = (int)time->minute; + elWork.entry[idx].second = (int)time->second; + elWork.entry[idx].errorCode = (int)errorCode; return TRUE; } @@ -226,18 +311,17 @@ CheckStatus ELi_CheckAndCreateDirectory( const char *path ) Description: この関数は該当ファイルが存在していれば何もしません。 該当ファイルが存在していなかった場合はファイルを作成します。 - Arguments: file: FSFile構造体へのポインタ - path: チェックを行うファイルのパス + Arguments: path: チェックを行うファイルのパス Returns: ファイルが存在した場合はCHECK_EXISTを、 存在しておらず作成した場合はCHECK_CREATEを、 ファイル作成に失敗した場合はCHECK_FAILEDを返します。 *---------------------------------------------------------------------------*/ -CheckStatus ELi_CheckAndCreateFile( FSFile *file, const char *path ) +CheckStatus ELi_CheckAndCreateFile( const char *path ) { - if( FS_OpenFileEx( file, path, FS_FILEMODE_RWL ) ) + if( FS_OpenFileEx( &elWork.file, path, FS_FILEMODE_RWL ) ) { return CHECK_EXIST; } @@ -252,25 +336,25 @@ CheckStatus ELi_CheckAndCreateFile( FSFile *file, const char *path ) // ファイル作成に成功 - if( !FS_OpenFileEx( file, path, FS_FILEMODE_RW ) ) + if( !FS_OpenFileEx( &elWork.file, path, FS_FILEMODE_RW ) ) { // 作成したファイルをopenできなかった場合 OS_TPrintf("EL Error: FS_OpenFileEx() failed. FSResult: %d\n", FS_GetArchiveResultCode(path) ); return CHECK_FAILED; } - if( FS_SetFileLength( file, ERRORLOG_SIZE ) != FS_RESULT_SUCCESS ) + if( FS_SetFileLength( &elWork.file, ERRORLOG_SIZE ) != FS_RESULT_SUCCESS ) { // 作成したファイルのサイズを設定できなかった OS_TPrintf("EL Error: FS_SetFileLength() failed. FSResult: %d\n", FS_GetArchiveResultCode(path) ); - FS_CloseFile( file ); + FS_CloseFile( &elWork.file ); return CHECK_FAILED; } // サイズ変更が終わったら、念のためファイルサイズ変更不可なRWLモードで開きなおしておく - FS_CloseFile( file ); + FS_CloseFile( &elWork.file ); - if( !FS_OpenFileEx( file, path, FS_FILEMODE_RWL ) ) + if( !FS_OpenFileEx( &elWork.file, path, FS_FILEMODE_RWL ) ) { OS_TPrintf("EL Error: FS_OpenFileEx() failed. FSResult: %d\n", FS_GetArchiveResultCode(path) ); return CHECK_FAILED; @@ -286,12 +370,11 @@ CheckStatus ELi_CheckAndCreateFile( FSFile *file, const char *path ) for(i = 0; i < 16; i++) { - FS_WriteFile( file, nullbuf, 1024); + FS_WriteFile( &elWork.file, nullbuf, 1024); } } return CHECK_CREATE; - } @@ -301,13 +384,12 @@ CheckStatus ELi_CheckAndCreateFile( FSFile *file, const char *path ) Description: ログファイルに書き込まれた過去のエントリを読み出す - Arguments: file: ログファイルのFSFile構造体 - entry: エントリを書き込むバッファへのポインタ + Arguments: なし。 Returns: 読み出したエントリの数 *---------------------------------------------------------------------------*/ -int ELi_ReadEntry( FSFile *file, ErrorLogEntry *entry ) +int ELi_ReadEntry( void ) { char buf[ERRORLOG_BUFSIZE+1]; int numEntry = 0; @@ -315,26 +397,25 @@ int ELi_ReadEntry( FSFile *file, ErrorLogEntry *entry ) buf[ERRORLOG_BUFSIZE] = '\0'; - FS_SeekFileToBegin( file ); - readSize = FS_ReadFile( file, buf, ERRORLOG_BUFSIZE ); + FS_SeekFileToBegin( &elWork.file ); + readSize = FS_ReadFile( &elWork.file, buf, ERRORLOG_BUFSIZE ); // エントリの頭には必ず'#'が書き込まれているのでそれで判定 while( readSize == ERRORLOG_BUFSIZE && buf[0] == '#') { // 決められたファイルフォーマットからエントリに読み込む - sscanf( buf, ERRORLOG_READ_FORMAT, - &(entry[numEntry].year) , - &(entry[numEntry].month) , - &(entry[numEntry].day) , - &(entry[numEntry].week) , - &(entry[numEntry].hour) , - &(entry[numEntry].minute) , - &(entry[numEntry].second) , - &(entry[numEntry].errorCode) ); + STD_TSScanf( buf, ERRORLOG_READ_FORMAT, + &(elWork.entry[numEntry].year) , + &(elWork.entry[numEntry].month) , + &(elWork.entry[numEntry].day) , + &(elWork.entry[numEntry].week) , + &(elWork.entry[numEntry].hour) , + &(elWork.entry[numEntry].minute) , + &(elWork.entry[numEntry].second) , + &(elWork.entry[numEntry].errorCode) ); numEntry++; - readSize = FS_ReadFile( file, buf, ERRORLOG_BUFSIZE ); - + readSize = FS_ReadFile( &elWork.file, buf, ERRORLOG_BUFSIZE ); } return numEntry; @@ -368,68 +449,84 @@ BOOL ELi_SetString( char *buf, ErrorLogEntry *entry ) } /*---------------------------------------------------------------------------* - Name: ELi_WriteLog + Name: ELi_WriteLogToBuf + + Description: 受け取ったエントリの中身をバッファへ書き出します。 + + Arguments: buf: 16KB長バッファへのポインタ + entry: エラー内容のエントリの配列ポインタ + numEntry: 合計エントリ数 + + Returns: なし。 + *---------------------------------------------------------------------------*/ +void ELi_WriteLogToBuf( char *buf ) +{ + // エントリを書き出す開始点 + int entryIdx = elWork.numEntry <= ERRORLOG_NUM_ENTRY ? 0 : elWork.numEntry % ERRORLOG_NUM_ENTRY ; + int counter; + int counterMax = elWork.numEntry <= ERRORLOG_NUM_ENTRY ? elWork.numEntry : ERRORLOG_NUM_ENTRY ; + + // ファイルの頭に戻って書き込みなおす + FS_SeekFileToBegin( &elWork.file ); + + for( counter = 0; counter < counterMax ; counter++ ) + { + // bufに一エントリずつ文字列化して詰めていく + ELi_SetString( &buf[ counter * ERRORLOG_BUFSIZE ], &(elWork.entry[ (entryIdx + counter) % ERRORLOG_NUM_ENTRY ]) ); + + if( counter == counterMax-1 ) + { + // 最後のエントリは改行を入れずにヌル文字で終端 + buf[ (counter+1) * ERRORLOG_BUFSIZE - 1] = '\0'; + } + } + + // バッファのあまり部分をゼロ埋めする + MI_CpuClear8( &buf[ counter * ERRORLOG_BUFSIZE], (u32) ((ERRORLOG_NUM_ENTRY - counter) * ERRORLOG_BUFSIZE ) ); +} + +/*---------------------------------------------------------------------------* + Name: ELi_WriteLogToFile Description: 受け取ったエントリの中身をログファイルに書き出します。 - Arguments: file: ログファイルのFSFile構造体へのポインタ - entry: エラー内容のエントリの配列ポインタ - num: entryに含まれるエントリの数 - err: 今回発生したエラーのエラーコード + Arguments: buf: 書き込み内容の格納されたバッファへのポインタ Returns: 成功した場合はTRUE、失敗した場合はFALSEが返ります。 *---------------------------------------------------------------------------*/ -BOOL ELi_WriteLog( FSFile *file ,ErrorLogEntry *entry, int numEntry ) +BOOL ELi_WriteLogToFile( char *buf ) { + FSResult res; - // エントリを書き出す開始点 - int entryIdx = numEntry <= ERRORLOG_NUM_ENTRY ? 0 : numEntry % ERRORLOG_NUM_ENTRY ; - int counter; - int counterMax = numEntry <= ERRORLOG_NUM_ENTRY ? numEntry : ERRORLOG_NUM_ENTRY ; - char buf[ERRORLOG_BUFSIZE]; - - - // ファイルの頭に戻って書き込みなおす - FS_SeekFileToBegin( file ); - - for( counter = 0; counter < counterMax ; counter++ ) + FS_SeekFileToBegin( &elWork.file ); + if( FS_WriteFile( &elWork.file, buf, ERRORLOG_SIZE ) != ERRORLOG_SIZE ) { - ELi_SetString( buf, &(entry[ (entryIdx + counter) % ERRORLOG_NUM_ENTRY ]) ); - - if( counter == counterMax-1 ) - { - buf[ERRORLOG_BUFSIZE-1] = '\0'; - } - - - if( FS_WriteFile( file, buf, (s32)ERRORLOG_BUFSIZE ) == -1 ) - { - OS_TPrintf("EL Error: FS_WriteFile() failed. entry: %d\n", entryIdx ); - return FALSE; - } - } - - // ファイルの余りを0埋めする - // open modeがサイズ固定なのでファイル終端を気にせず書き込む - MI_CpuClear8( buf, ERRORLOG_BUFSIZE ); - while ( FS_WriteFile( file, buf, (s32) ERRORLOG_BUFSIZE ) == ERRORLOG_BUFSIZE ) {}; - - - if( !FS_CloseFile( file ) ) - { - OS_TPrintf("EL Error: FS_CloseFile() failed.\n" ); + OS_TPrintf("EL Error: FS_WriteFile() failed.\n"); return FALSE; } - + if( ( res = FS_FlushFile( &elWork.file )) != FS_RESULT_SUCCESS ) + { + OS_TPrintf("EL Error: FS_FlushFile() failed. FSResult: %d\n", res); + return FALSE; + } return TRUE; } +/*---------------------------------------------------------------------------* + Name: ELi_fillSpace + + Description: 受け取ったエントリの余りの部分を0で埋めます。 + + Arguments: buf: 書き込み内容の格納されたバッファへのポインタ + bufsize: エントリ全体のサイズ + + Returns: なし。 + *---------------------------------------------------------------------------*/ + void ELi_fillSpace( char *buf, int bufsize ) { - // エントリの末尾にスペースを入れて - // 一つのエントリがちょうど128バイトになるように辻褄を合わせる u32 length = strlen( buf ); MI_CpuFill8( &buf[length], ' ', bufsize - length ); } diff --git a/build/tests/ErrorLogTest/ARM9/Makefile b/build/tests/ErrorLogTest/ARM9/Makefile index 93bc80e7..9cf61266 100644 --- a/build/tests/ErrorLogTest/ARM9/Makefile +++ b/build/tests/ErrorLogTest/ARM9/Makefile @@ -21,14 +21,14 @@ TARGET_FIRM = SYSTEMMENU TARGET_PLATFORM = TWL TWL_ARCHGEN = LIMITED - - - #---------------------------------------------------------------------------- TARGET_BIN = main.srl -SRCS = ErrorLogTest.c +MISC_DIR = ../../../systemMenu_RED/misc +LINCLUDES += $(MISC_DIR)/include + +SRCS = ErrorLogTest.c $(MISC_DIR)/src/misc.c $(MISC_DIR)/src/cmn.c LLIBRARIES += liberrorlog$(TWL_LIBSUFFIX).a diff --git a/build/tests/ErrorLogTest/ARM9/src/ErrorLogTest.c b/build/tests/ErrorLogTest/ARM9/src/ErrorLogTest.c index 35a2fcac..56b4dec2 100644 --- a/build/tests/ErrorLogTest/ARM9/src/ErrorLogTest.c +++ b/build/tests/ErrorLogTest/ARM9/src/ErrorLogTest.c @@ -17,17 +17,20 @@ #include #include +#include "misc.h" // なぜかバッファサイズが256byteを超えると出力が欠けるようになる // ダンプを見ると、OS_TPrintf()呼び出し時にもバッファにはちゃんと格納されている模様 // 原因は現在調査中 -#define BUFSIZE 100 +#define BUFSIZE 128 void VBlankIntr(void); void TwlMain( void ) { + int numEntry; + const ErrorLogEntry *pEntry; OS_Init(); RTC_Init(); @@ -39,9 +42,28 @@ void TwlMain( void ) GX_VBlankIntr(TRUE); FS_Init( FS_DMA_NOT_USE ); - - EL_WriteErrorLog( (u64)0x077777777777LL ); + InitAllocator(); + EL_Init( Alloc, Free ); + + EL_WriteErrorLog( (u64)0x077777777777LL ); + + numEntry = EL_getErrorLogNum(); + OS_TPrintf("numEntry : %d\n", numEntry ); + + if( numEntry > 2 ) + { + pEntry = EL_getErrorLog(1); + OS_TPrintf("entry[1] : %02d-%02d-%02d %02d:%02d:%02d errorCode: %d\n", + pEntry->year, + pEntry->month, + pEntry->day, + pEntry->hour, + pEntry->minute, + pEntry->second, + pEntry->errorCode); + } + OS_TPrintf( "*** log file data\n" ); { @@ -71,15 +93,16 @@ void TwlMain( void ) } + //OS_TPrintf("%s\n",buf); + OS_TPrintf("\n"); FS_CloseFile( &file ); - OS_TPrintf("%s\n",buf); totalSize += nowSize; - OS_TPrintf("num entry : %d\n", numEntry ); OS_TPrintf("total Size : %d\n", totalSize); } + EL_End(); OS_TPrintf( "*** End of demo\n" ); OS_Terminate(); } diff --git a/include/sysmenu/errorLog.h b/include/sysmenu/errorLog.h index 0e3805a4..2620fdae 100644 --- a/include/sysmenu/errorLog.h +++ b/include/sysmenu/errorLog.h @@ -17,7 +17,8 @@ #ifndef __SYSM_ERRORLOG__ #define __SYSM_ERRORLOG__ - + +#include #ifdef __cplusplus extern "C" { @@ -25,10 +26,46 @@ extern "C" { #ifdef SDK_ARM9 +/*-- type definition ----------------------------*/ + + +// 既に書き込まれたエラーログを表現するためのエントリ +typedef struct ErrorLogEntry{ + // エラーのタイムスタンプ + int year; + int month; + int day; + char week[4]; // 曜日の3文字表現 + int hour; + int minute; + int second; + // エラーコード + int errorCode; +} ErrorLogEntry; + +typedef struct ErrorLogWork{ + // メモリ確保用関数 + void* (*Alloc) ( u32 ) ; + void (*Free) ( void* ) ; + // エラーログエントリ保持用変数 + ErrorLogEntry *entry; + // エラーログのエントリ数 + int numEntry; + // エラーログのファイルポインタ + FSFile file; +} ErrorLogWork; + + /*-- function prototype -------------------------*/ extern BOOL EL_WriteErrorLog( u64 errorCode ); +extern BOOL EL_Init( void* (*AllocFunc) (u32) , void (*FreeFunc) (void*) ); +extern void EL_End( void ); +extern int EL_getErrorLogNum() ; +extern const ErrorLogEntry* EL_getErrorLog( int idx ); + + #endif // SDK_ARM9