ctr_mcu/trunk/self_flash.c
fujita_ryohei 604432135f V0.25的な物。 自己アップデータの確認で一時的に巻き戻したいため。
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@6 013db118-44a6-b54f-8bf7-843cb86687b1
2009-09-02 10:35:20 +00:00

355 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ========================================================
自己アップデータ
======================================================== */
#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 INACTIVE_BOOTSECT_TOP 4
#define UPDATE_BLOCK_LAST 17
#define FIRM_TOP 8
#define FIRM_SIZE 10
#ifdef _MCU_BSR_
#define ACKD ACKD0
#define ACKE ACKE0
#define COI COI0
#define IICAEN IICA0EN
#define IICAPR0 IICAPR00
#define IICRSV IICRSV0
#define IICA IICA0
#define IICAEN IICA0EN
#define IICAIF IICAIF0
#define IICAMK IICAMK0
#define IICAPR1 IICAPR10
#define IICCTL0 IICCTL00
#define IICE IICE0
#define IICF IICF0
#define IICS IICS0
#define IICWH IICWH0
#define IICWL IICWL0
#define LREL LREL0
#define SPD SPD0
#define SPIE SPIE0
#define STCEN STCEN0
#define STD STD0
#define SVA SVA0
#define WREL WREL0
#define WTIM WTIM0
#endif
// ========================================================
static void FSL_Open(void);
static void FSL_Close(void);
err firm_restore();
// magic.c の記述と違わないように注意!
#define N_MGC_L 0x1FF6
#define N_MGC_T 0x47F6
/* ========================================================
======================================================== */
err firm_update(){
u8 flg_rcv_end;
u8 buffer_fill;
u8 target_block;
u8 data_buffer[ SELF_UPDATE_BUFF_SIZE ];
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
fsl_u08 err;
__far u8* p_rom;
flg_rcv_end = 0;
// 書き替え前準備 //
FSL_Open(); // 割り込み禁止など
DI();
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err += FSL_ModeCheck(); // ライトプロテクトチェック。失敗することを考慮せず
// ファームのバックアップ //
/*
0x2000 - 0x47FF (ブロック 8 - 17) を
0x4800 - 0x7FFF (ブロック 18 - 27) にコピー
*/
p_rom = (u8*)0x2000;
// 書き込み先ブロックの数だけ繰り返す
for( target_block = ( FIRM_TOP + FIRM_SIZE );
target_block < ( FIRM_TOP + FIRM_SIZE + FIRM_SIZE );
target_block += 1 ){
WDT_Restart();
// ブロック消去
while( FSL_BlankCheck( target_block ) != FSL_OK ){
err = FSL_Erase( target_block );
}
// 分割書き込み分繰り返す
for( split_write_count = 0;
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
split_write_count += 1 ){
// 書き込みデータをバッファにためる
buffer_fill = 0;
do{
data_buffer[ buffer_fill ] = *p_rom;
p_rom += 1;
buffer_fill++;
}while( buffer_fill != (u8)SELF_UPDATE_BUFF_SIZE );
// 書き込み
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();
NOP();
return( ERR_ERR );
}
}
// 1ブロック書き込み完了。内部電圧チェックを行う
while( FSL_IVerify( target_block ) != FSL_OK ){ ; }
}
// 書き替え //
/*
●書き込み中の電源断を判定するため、最初に全クラスタ消去する(フッタを消したい)
●ストップコンディションが来るまで続ける結局、0x1000 - 0x47FF まですべて書き替えることにはなる)
●終わったら、リセットする。WDTリセットなので自分でわかる。
*/
// 全ブロック消去
for( target_block = INACTIVE_BOOTSECT_TOP;
target_block <= UPDATE_BLOCK_LAST ;
target_block += 1 ){
err = FSL_Erase( target_block );
}
// ブロックの数だけ繰り返し
for( target_block = INACTIVE_BOOTSECT_TOP;
target_block <= UPDATE_BLOCK_LAST;
target_block += 1 ){
// 分割書き込み
for( split_write_count = 0;
(( split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM ) && ( !SPD ));
split_write_count += 1 ){
WDT_Restart();
// I2Cから書き込みデータをバッファにためる
do{
while( !IICAIF && !SPD ){;}
IICAIF = 0;
data_buffer[ buffer_fill ] = IICA;
WREL = 1;
buffer_fill += 1;
}while(( buffer_fill != (u8)SELF_UPDATE_BUFF_SIZE ) && !SPD );
// 書き込み
// 最後だと、ゴミをパディングするが別にかまわない
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();
return( ERR_ERR );
}
}
// 1ブロック書き込み完了。内部ベリファイを行う
while( FSL_IVerify( target_block ) != FSL_OK ){;}
if( SPD ){
goto firm_update_end;
}
}
firm_update_end:
WREL = 1;
// 書き込んだファームのチェック //
{
u8 i;
u8 comp = 0;
// 少なくとも、ローダーのマジックと、本文の末尾のマジックは同じか確認
for( i = 0; i < sizeof( __TIME__ ); i++ ){
comp += ( *(u8*)( N_MGC_L - sizeof( __TIME__ ) + i ) == *(u8*)( N_MGC_T - sizeof( __TIME__ ) + i ) )? 0: 1;
}
if( comp == 0 ){
FSL_InvertBootFlag();
FSL_SwapBootCluster();
}else{
FSL_ForceReset();
}
}
}
/* ========================================================
■ファームをバックアップ領域からリストアします。
0x4800 - 0x7FFF (ブロック 18 - 27)を 0x2000 - 0x47FF (同、8 - 17) にコピーして
ブートスワップ、リブートを行います。
======================================================== */
err firm_restore(){
u8 flg_rcv_end = 0;
u8 buffer_fill;
u8 target_block;
u8 data_buffer[ SELF_UPDATE_BUFF_SIZE ];
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
fsl_u08 err;
__far u8* p_rom;
// 書き替え前準備 //
FSL_Open(); // 割り込み禁止など
DI();
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err += FSL_ModeCheck(); // ライトプロテクトチェック。失敗することを考慮せず
// ファームのリストア
/*
0x4800 - 0x7FFF (ブロック 18 - 27) から
0x2000 - 0x47FF (ブロック 8 - 17) へコピー
*/
p_rom = (u8*)0x4800;
// 転送先ブロックの数だけ繰り返す
for( target_block = FIRM_TOP;
target_block <= UPDATE_BLOCK_LAST;
target_block += 1 ){
WDT_Restart();
// 壊れたファームを消し
err = FSL_Erase( target_block );
// 分割書き込み分繰り返す
for( split_write_count = 0;
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
split_write_count += 1 ){
// 書き込みデータをバッファにためる
buffer_fill = 0;
do{
data_buffer[ buffer_fill ] = *p_rom;
p_rom += 1;
buffer_fill++;
}while( buffer_fill != (u8)SELF_UPDATE_BUFF_SIZE );
// 書き込み
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();
return( ERR_ERR );
}
}
// 1ブロック書き込み完了したので内部ベリファイを行う
while( FSL_IVerify( target_block ) != FSL_OK ){ ; }
}
// todo
//  それでもだなら、LEDちかちかとかさせて、サービス送りにしてもらう
// リブート
FSL_ForceReset();
return( ERR_SUCCESS );
}
// ========================================================
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
}