mirror of
https://github.com/rvtr/ctr_mcu.git
synced 2025-10-31 13:51:10 -04:00
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@4 013db118-44a6-b54f-8bf7-843cb86687b1
355 lines
10 KiB
C
355 lines
10 KiB
C
/* ========================================================
|
||
自己アップデータ
|
||
======================================================== */
|
||
#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 0x6FF6
|
||
|
||
|
||
/* ========================================================
|
||
======================================================== */
|
||
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 + i ) == *(u8*)( N_MGC_T + 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
|
||
}
|