ctr_mcu/trunk/self_flash.c
fujita_ryohei 28b5f92e98 加速度割り込み周りで取りこぼすことがあったのを救うコード追加
CTRコーデックに対応?
IRQ_0を確実にかける
I2C(TWL/CTR)の割り込み優先度修正(レジスタ名が悪いと思う)
カメラLED、TWLからの操作を追加
loader、文法ミス修正
自己アップデート後、自己リセットをかける。メーカーの回答待ちのため暫定。(セットは電源が切れ、RTCも初期化される)
RTCの初期値を変更(暫定)
バッテリ残量ICとのやりとりを修正。メーカーの推奨の手順が更新されたため。また、不正になりがちなのでリセットをかけるようにしてみた。I2C_mの2バイト書き込みがひどかったので修正
互換側I2Cれじすたの整理。エンバグ心配



git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@13 013db118-44a6-b54f-8bf7-843cb86687b1
2009-10-27 04:12:36 +00:00

415 lines
12 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 = 8;
const u8 fsl_low_voltage_u08 = 1;
// 自己フラッシュパラメータ
#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 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 );
err firm_restore( );
// magic.c の記述と違わないように注意!
#define N_MGC_L 0x1FF6
#define N_MGC_T 0x47F6
// ========================================================
u8 boot_ura; // ブートクラスタ 0/1
/* ========================================================
======================================================== */
err firm_update( )
{
u8 buffer_fill;
u8 target_block;
u8 data_buffer[SELF_UPDATE_BUFF_SIZE];
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
fsl_u08 err;
__far u8 *p_rom;
TOE0 = 0x0000;
TOE0 = 0x0020;
// 書き替え前準備 //
FSL_Open( ); // 割り込み禁止など
DI( );
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err += FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず
// ファームのバックアップ //
/*
0x2000 - 0x47FF (ブロック 8 - 17) を
0x4800 - 0x7FFF (ブロック 18 - 27) にコピー
*/
p_rom = ( __far 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 );
}
WREL = 1;
// ブロックの数だけ繰り返し
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:
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 )
{
FSL_InvertBootFlag( );
// FSL_SwapBootCluster( ); // リセットせずに頭から
FSL_ForceReset(); // リセット
// FSL_SwapActiveBootCluster(); // ←スワップされてしまうので、続けられず暴走!
// 戻ってこない //
}
else
{
FSL_Close( );
firm_restore( );
// 戻ってこない //
}
}
}
/* ========================================================
■ファームをバックアップ領域からリストアします。
0x4800 - 0x7FFF (ブロック 18 - 27)を 0x2000 - 0x47FF (同、8 - 17) にコピーして
再起動します。
ブートスワップは不要です。
======================================================== */
err firm_restore( )
{
u8 buffer_fill;
u8 target_block;
u8 data_buffer[SELF_UPDATE_BUFF_SIZE];
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
fsl_u08 err;
__far u8 *p_rom;
RTCE = 0;
TOE0 = 0x0000;
TOE0 = 0x0080;
// 書き替え前準備 //
DI( );
FSL_Open( ); // 割り込み禁止など
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err += FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず
// ファームのリストア
/*
0x4800 - 0x7FFF (ブロック 18 - 27) から
0x2000 - 0x47FF (ブロック 8 - 17) へコピー
*/
p_rom = ( __far 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 );
}
void chk_bootCluster( )
{
u8 data_buffer[SELF_UPDATE_BUFF_SIZE];
u8 err;
DI( );
FSL_Open( ); // 割り込み禁止など
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err |= FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず
err |= FSL_GetActiveBootCluster( &boot_ura );
FSL_Close( );
}
// ========================================================
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を止める
while( DST1 )
{;
}
DEN1 = 0;
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
}