ctr_mcu/branches/0.18(sdk_0_10)/self_flash.c
N2614 1c8be29949 0.18_beta(sdk0_10)
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@182 013db118-44a6-b54f-8bf7-843cb86687b1
2010-05-28 08:43:58 +00:00

404 lines
12 KiB
C
Raw Permalink 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"
#include "pool.h"
// ========================================================
const u8 fsl_fx_MHz_u08 = 8;
const u8 fsl_low_voltage_u08 = 1;
// 自己フラッシュパラメータ
#define SAM_BLOCK_SIZE 1024
// ↓256バイト以上はまとめてかけません。
#define SELF_UPDATE_BUFF_SIZE 256
#define SELF_UPDATE_SPLIT_WRITE_NUM ( SAM_BLOCK_SIZE / SELF_UPDATE_BUFF_SIZE )
#define SAM_WORD_SIZE 4
// ↓ブロック番号1ブロック1kB
#define INACTIVE_BOOTSECT_TOP 4
#define FIRM_TOP 8
#define FIRM_SIZE 12
#define UPDATE_BLOCK_LAST ( FIRM_TOP + FIRM_SIZE - 1 )
#ifdef _MCU_BSR_
#define ACKD ACKD1
#define ACKE ACKE1
#define COI COI1
#define IICAEN IICA1EN
#define IICAPR0 IICAPR10
#define IICRSV IICRSV1
#define IICA IICA1
#define IICAIF IICAIF1
#define IICAMK IICAMK1
#define IICAPR1 IICAPR11
#define IICCTL0 IICCTL01
#define IICE IICE1
#define IICF IICF1
#define IICS IICS1
#define IICWH IICWH1
#define IICWL IICWL1
#define LREL LREL1
#define SPD SPD1
#define SPIE SPIE1
#define STCEN STCEN1
#define STD STD1
#define SVA SVA1
#define WREL WREL1
#define WTIM WTIM1
#endif
// ========================================================
static void FSL_Open( void );
static void FSL_Close( void );
void firm_restore( );
static err my_FSL_Init();
static err firm_duplicate( u8 block_src, u8 block_dest );
// ========================================================
extern uni_pool pool;
// 0.D以降 新アップデータ向け
#define N_MGC_L 0x1FF6
#define N_MGC_T 0x4FF6
/* ========================================================
I2Cで受信して、
書き込み、
チェックOK  新ファームに切り替えて再起動
    NG  ファームに戻して再起動
(この関数からは戻りません)
======================================================== */
void firm_update( )
{
u8 target_block;
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
// 書き替え前準備 /////////////////////////////////////
my_FSL_Init();
/* ファームのバックアップ
開始アドレス、書き込み先の先頭”ブロック番号” (サイズは FIRM_SIZE)
0x2000 - 0x4FFF を
0x5000 - 0x7FFF (ブロック 20 - 31) にコピー
*/
firm_duplicate( FIRM_TOP,
UPDATE_BLOCK_LAST +1 );
// 全ブロック削除 /////////////////////////////////////
// 電源断を判定するため、最初に全クラスタ消去する
//(新ファームが書かれるところに残ってる、以前のファームのフッタを消したい)
for( target_block = INACTIVE_BOOTSECT_TOP;
target_block <= UPDATE_BLOCK_LAST;
target_block += 1 )
{
FSL_Erase( target_block );
}
// 書き替え ///////////////////////////////////////////
// ●ストップコンディションが来るまで続ける
// ●終わったら、スタートアップルーチンに飛ぶ
for( target_block = INACTIVE_BOOTSECT_TOP;
target_block <= UPDATE_BLOCK_LAST;
target_block += 1 )
{
// 新ファーム領域削除
FSL_Erase( target_block );
// 分割書き込み
for( split_write_count = 0;
( ( split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM )
&& ( !SPD ) );
split_write_count += 1 )
{
u8* p_buffer = &pool.self_update_work[0];
u16 buff_written_size = 0;
// I2Cから書き込みデータをバッファにためる
do
{
while( !IICAIF && !SPD )
{
WDT_Restart( );
}
IICAIF = 0;
*p_buffer = IICA;
WREL = 1;
p_buffer += 1;
buff_written_size += 1;
}
while( ( buff_written_size != SELF_UPDATE_BUFF_SIZE )
&& !SPD );
// 書き込み
// 最後だと、ゴミをパディングするが別にかまわない
if( 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 ) )
!= FSL_OK )
{
// 書き込み後のチェックエラー
// リストア
firm_duplicate( UPDATE_BLOCK_LAST +1,
FIRM_TOP );
FSL_ForceReset();
// 戻ってこない //
}
}
// 1ブロック書き込み完了。内部ベリファイを行う
if( FSL_IVerify( target_block ) != FSL_OK ){
// 再度消去→書き込み ベリファイを繰り返すだけじゃダメでした... todo…
// リストア
firm_duplicate( UPDATE_BLOCK_LAST +1, FIRM_TOP );
FSL_ForceReset();
// 戻ってこない //
}
if( SPD )
{
break;
}
}
LREL = 1;
// 書き込んだファームのチェック //
{
u8 i;
u8 comp = 0;
// ローダーのマジックと、本文の末尾のマジックは同じか確認
for( i = 0; i < sizeof( __TIME__ ); i++ )
{
comp += ( *( u8 * ) ( N_MGC_L + i ) == *( u8 * ) ( N_MGC_T + i ) ) ? 0 : 1;
}
if( comp == 0 )
{
// OK!
FSL_InvertBootFlag( );
FSL_SwapBootCluster( ); // リセットせずに頭から。FSL_Closeは不要
// 戻ってこない //
}
else
{
// データ(マジックナンバーしか見てない)エラー
// リストア
firm_duplicate( UPDATE_BLOCK_LAST,
FIRM_TOP );
FSL_ForceReset(); // リセット
// 戻ってこない //
}
}
}
/* ========================================================
 ■ファームをバックアップ領域からリストアします。
 チェック後、最後の最後でブートスワップするので、
 ここではブートスワップは不要です。
======================================================== */
void firm_restore( )
{
my_FSL_Init();
/* ファームのリストア
0x4800 - 0x7FFF (ブロック 18 - 27) から
0x2000 - 0x47FF (ブロック 8 - 17) へコピー
*/
firm_duplicate( UPDATE_BLOCK_LAST +1, FIRM_TOP );
// todo
//  リストア失敗したら、LEDちかちかとかさせて、サービス送りにしてもらう
// リブート
FSL_InvertBootFlag( );
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
while( DST1 ){;} // DMA停止
DEN1 = 0;
MK0 = 0xFFFF;
MK1 = 0xFFFF;
MK2 = 0xFFFF;
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
}
/* ========================================================
 マイコン内でファームをコピーします。
__far u8 * p_rom コピー元の先頭アドレス
block_dest コピー先の先頭ブロック
コピー先に書けるようにmy_FSL_Initをあらかじめ実行する必要があります。
======================================================== */
//static err firm_duplicate( __far u8 * p_rom,
// u8 block_dest )
static err firm_duplicate( u8 block_src,
u8 block_dest )
{
u8 target_block;
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
__far u8* p_src = ( __far u8* )( block_src * 0x400 );
// 書き込み先ブロックの数だけ繰り返す
for( target_block = block_dest;
target_block < block_dest + FIRM_SIZE;
target_block += 1 )
{
WDT_Restart( );
// ブロック消去
while( FSL_BlankCheck( target_block ) != FSL_OK )
{
FSL_Erase( target_block );
}
// 分割書き込み分繰り返す
for( split_write_count = 0;
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
split_write_count += 1 )
{
u16 buff_written_size;
u8* p_buff;
// 書き込みデータをバッファにためる
buff_written_size = 0;
p_buff = &pool.self_update_work[0];
do
{
*p_buff = *p_src;
p_src += 1;
p_buff += 1;
buff_written_size +=1;
}
while( buff_written_size != SELF_UPDATE_BUFF_SIZE );
// 書き込み
if( 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 ) )
!= FSL_OK )
{
// todo リカバリ? //
FSL_Close( );
return ( ERR_ERR );
}
}
// 1ブロック書き込み完了。内部電圧チェックを行う
while( FSL_IVerify( target_block ) != FSL_OK ){
// todo 失敗時?
;
}
}
return( ERR_SUCCESS );
}
/* ========================================================
======================================================== */
static err my_FSL_Init()
{
RTCE = 0;
// 書き替え前準備 //
DI( );
FSL_Open( ); // 割り込み禁止など
FSL_Init( &pool.self_update_work[0] ); // ライブラリ初期化。割り込み中断考慮せず
FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず
return( ERR_SUCCESS );
}
task_status_immed tski_mcu_reset()
{
// 普通に再起動
my_FSL_Init();
FSL_SwapBootCluster();
FSL_ForceReset(); // リセット
FSL_Close( );
// 保険? //
// WDTE = 0xAA; // WDTで再起動テスト向け
return( ERR_SUCCESS ); // no reach
}