/***************************************************************************** 自己アプデータ *****************************************************************************/ #pragma SFR #pragma di #pragma ei #pragma nop #pragma stop #pragma halt #include "incs_loader.h" #include "fsl.h" #include "fsl_user.h" #include "i2c_ctr.h" const u8 fsl_fx_MHz_u08 = 4; const u8 fsl_low_voltage_u08 = 0; #define SAM_BLOCK_SIZE 1024 #define SELF_UPDATE_BUFF_SIZE 256 #define SELF_UPDATE_SPLIT_WRITE_NUM ( SAM_BLOCK_SIZE / SELF_UPDATE_BUFF_SIZE ) #define SAM_WORD_SIZE 4 #define UPDATEABLE_BLOCK_LAST 7 //***************************************************************************** static void FSL_Open(void); static void FSL_Close(void); /***************************************************************************** *****************************************************************************/ void firm_update(){ u8 flg_rcv_end = 0; u8 buffer_fill; u8 target_block; u8 data_buffer[ SELF_UPDATE_BUFF_SIZE ]; u8 *p_data_buffer; u8 split_write_count; // ブロックへちまちま書き込むカウンタ fsl_u08 err; // debug __far u8* p_rom = (u8*)0x0000; // 書き替え前準備 // FSL_Open(); // 割り込み禁止など DI(); err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず err += FSL_ModeCheck(); // ライトプロテクトチェック。失敗することを考慮せず // 書き替え // /* ●アクティブでない方のブートクラスタ (0x1000 =ブロック3) から、ストップコンディションが来るまで 消しては書き、消しては書きする。 ●各ブロック、内部ベリファイをして、だめだったら1回リトライする。  それでもだなら、LEDちかちかとかさせて、サービス送りにしてもらう ●ベリファイがOKだったところで、それがブロック7だったら、スワップを行う。 後はひたすら終わるまで続けるか、 書き替えては行けない領域に行きそうなら止める(無いと思うが) ●終わったら、リセットベクタに飛ばす。 */ // ブロック分繰り返す for( target_block = 4; target_block <= UPDATEABLE_BLOCK_LAST ; target_block += 1 ){ // 分割書き込み分繰り返す for( split_write_count = 0; split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM; split_write_count += 1 ){ // 初めて見るブロックなら消去 if( split_write_count == 0 ){ while( FSL_BlankCheck( target_block ) != FSL_OK ){ err = FSL_Erase( target_block ); } } // 書き込みデータをバッファにためる p_data_buffer = data_buffer; /* I2Cから受信 for( buffer_fill = 0; buffer_fill != SELF_UPDATE_BUFF_SIZE - 1; buffer_fill++ ){ while( !IICAIF ){;} IICAIF = 0; if( SPD ){ flg_rcv_end = 1; break; }else{ *p_data_buffer = IICA; WREL = 1; p_data_buffer += 1; } } /*/ // 動作確認 自分をコピー buffer_fill = 0; do{ *p_data_buffer = *p_rom; p_data_buffer += 1; p_rom += 1; buffer_fill++; }while( buffer_fill != ( SELF_UPDATE_BUFF_SIZE & 0xFF )); //*/ // 書き込み // 最後だと、ゴミをパディングするが別にかまわない err = FSL_Write( (fsl_u32)( target_block * SAM_BLOCK_SIZE + split_write_count * SELF_UPDATE_BUFF_SIZE ), (fsl_u08)( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) ); if( err != FSL_OK ){ FSL_Close(); while(1){ NOP(); } } // 1ブロック書き込み完了だったら内部ベリファイを行う if(( split_write_count == SELF_UPDATE_SPLIT_WRITE_NUM - 1 ) || flg_rcv_end ){ while( FSL_IVerify( target_block ) != FSL_OK ){;} // ブートクラスタの書き込み完了か? if( target_block == 7 ){ err = FSL_InvertBootFlag(); } } if( flg_rcv_end ){ goto UPDATE_END; } } } UPDATE_END: // todo ちゃんと終わらせる WREL = 1; FSL_SwapBootCluster(); } //**************************************************************************** static void FSL_Open(void) { /* save the configuration of the interrupt controller and set */ #ifdef FSL_INT_BACKUP fsl_MK0L_bak_u08 = MK0L; /* if (interrupt backup required) */ fsl_MK0H_bak_u08 = MK0H; /* { */ fsl_MK1L_bak_u08 = MK1L; /* */ fsl_MK1H_bak_u08 = MK1H; /* save interrupt controller */ fsl_MK2L_bak_u08 = MK2L; /* configuration */ fsl_MK2H_bak_u08 = MK2H; /* */ MK0L = FSL_MK0L_MASK; /* */ MK0H = FSL_MK0H_MASK; /* */ MK1L = FSL_MK1L_MASK; /* prepare interrupt controller */ MK1H = FSL_MK1H_MASK; /* for selfprogramming */ MK2L = FSL_MK2L_MASK; /* */ MK2H = FSL_MK2H_MASK; /* } */ #endif // 何か前準備? // todo DMAを止める FSL_FLMD0_HIGH; // フラッシュ書き替え許可 } /*----------------------------------------------------------------------------------------------*/ /* leave the "user room" and restore previous conditions */ /*----------------------------------------------------------------------------------------------*/ static void FSL_Close(void) { // 何か後始末? FSL_FLMD0_LOW; // フラッシュライトプロテクト #ifdef FSL_INT_BACKUP MK0L = fsl_MK0L_bak_u08; /* do{ */ MK0H = fsl_MK0H_bak_u08; /* restore interrupt controller */ MK1L = fsl_MK1L_bak_u08; /* configuration */ MK1H = fsl_MK1H_bak_u08; /* */ MK2L = fsl_MK2L_bak_u08; /* */ MK2H = fsl_MK2H_bak_u08; /* } */ #endif }