EL_Init()内でバッファを確保してファイルの読み込みを済ませるようにした。

ログ出力時にもバッファを介して一括で書き出すように変更。
EL_getErrorLogNumおよびEL_getErrorLogの追加。
sscanfをSTDライブラリのものに変更。

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1829 b08762b0-b915-fc4b-9d8c-17b2551a87ff
This commit is contained in:
aoki_ryoma 2008-07-09 08:18:25 +00:00
parent f118b26b18
commit 3aa4681993
4 changed files with 299 additions and 142 deletions

View File

@ -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: TRUEFALSEが返ります
*---------------------------------------------------------------------------*/
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 );
}

View File

@ -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

View File

@ -17,17 +17,20 @@
#include <twl.h>
#include <sysmenu/errorLog.h>
#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();
}

View File

@ -17,7 +17,8 @@
#ifndef __SYSM_ERRORLOG__
#define __SYSM_ERRORLOG__
#include <twl.h>
#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