mirror of
https://github.com/rvtr/ctr_mcu.git
synced 2025-06-18 16:45:33 -04:00

・充電状況割り込みをtask_status -> task_batt へ統合 ・Doxgenで処理できるように関数の看板を変更、追記など コードそのものはお蔵入りになると思うのですが... ・include を少し整理 git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@406 013db118-44a6-b54f-8bf7-843cb86687b1
636 lines
18 KiB
C
636 lines
18 KiB
C
/* ========================================================
|
||
自己アップデータ
|
||
$Id$
|
||
======================================================== */
|
||
#ifndef _WIN32
|
||
|
||
#pragma SFR
|
||
#pragma di
|
||
#pragma ei
|
||
#pragma nop
|
||
#pragma stop
|
||
#pragma halt
|
||
|
||
#endif
|
||
|
||
#include "incs_loader.h"
|
||
|
||
#include <fsl.h>
|
||
#include "fsl_user.h"
|
||
#include "i2c_ctr.h"
|
||
#include "i2c_mcu.h"
|
||
|
||
#include "pool.h"
|
||
#include "magic.h"
|
||
|
||
#include "pm.h"
|
||
#include "WDT.h"
|
||
#include "util_funcs.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 ALTERNATE_FIRMTOP 20
|
||
|
||
|
||
#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
|
||
|
||
#ifndef _WIN32
|
||
#define LED_POW1 P4.2
|
||
#define LED_PM_POW1 PM4.2
|
||
#else
|
||
#define LED_POW1 mcuRegP[ _P4_2 ]
|
||
#define LED_PM_POW1 mcuRegPM[ _P4_2 ]
|
||
#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 );
|
||
|
||
#ifdef _DBG_LED_PRINT_
|
||
void alert( u8 );
|
||
void led_print( u8 );
|
||
#else
|
||
# define alert( x ) ;
|
||
# define led_print( x ) ;
|
||
#endif
|
||
|
||
|
||
// ========================================================
|
||
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,
|
||
ALTERNATE_FIRMTOP );
|
||
|
||
// 全ブロック削除 /////////////////////////////////////
|
||
// 電源断を判定するため、最初に全クラスタ消去する
|
||
//(新ファームが書かれるところに残ってる、以前のファームのフッタを消したい)
|
||
for( target_block = INACTIVE_BOOTSECT_TOP;
|
||
target_block < ALTERNATE_FIRMTOP;
|
||
target_block ++ )
|
||
{
|
||
FSL_Erase( target_block );
|
||
}
|
||
|
||
|
||
// 書き替え ///////////////////////////////////////////
|
||
// ●ストップコンディションが来るまで続ける
|
||
// ●終わったら、スタートアップルーチンに飛ぶ
|
||
for( target_block = INACTIVE_BOOTSECT_TOP;
|
||
target_block < ALTERNATE_FIRMTOP;
|
||
target_block ++ )
|
||
{
|
||
u8 my_spd;
|
||
|
||
/* すでに消してある。でないと中断されたとき終了してるか判別出来ない
|
||
// // 新ファーム領域削除
|
||
// FSL_Erase( target_block );
|
||
*/
|
||
// 分割書き込み
|
||
for( split_write_count = 0;
|
||
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
|
||
split_write_count ++ )
|
||
{
|
||
u8* p_buffer = &pool.self_update_work[0];
|
||
u16 buff_written_size = 0;
|
||
|
||
WDT_Restart( );
|
||
|
||
// I2Cから書き込みデータをバッファにためる
|
||
do
|
||
{
|
||
while( !IICAIF && !SPD )
|
||
{;}
|
||
my_spd = SPD;
|
||
IICAIF = 0;
|
||
*p_buffer = IICA;
|
||
WREL = 1;
|
||
p_buffer ++;
|
||
buff_written_size ++;
|
||
}
|
||
while( ( buff_written_size != SELF_UPDATE_BUFF_SIZE )
|
||
&& !SPD );
|
||
|
||
my_spd += 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 )
|
||
{
|
||
alert(1);
|
||
// 書き込み後のチェックエラー
|
||
// リストア
|
||
firm_duplicate( ALTERNATE_FIRMTOP, FIRM_TOP );
|
||
FSL_ForceReset(); // リセット
|
||
// FSL_SwapBootCluster( ); // ブートスワップ「せずに」再起動って出来ないらしい
|
||
// 戻ってこない //
|
||
}
|
||
|
||
if( my_spd != 0 )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 1ブロック書き込み完了。内部ベリファイを行う
|
||
if( FSL_IVerify( target_block ) != FSL_OK ){
|
||
alert(2);
|
||
// 再度消去→書き込み ベリファイを繰り返すだけじゃダメでした... /// 再書き込みすべき?
|
||
// リストア
|
||
firm_duplicate( ALTERNATE_FIRMTOP, FIRM_TOP );
|
||
FSL_ForceReset(); // リセット
|
||
// FSL_SwapBootCluster( ); // ブートスワップ「せずに」再起動って出来ないらしい
|
||
// 戻ってこない //
|
||
}
|
||
|
||
if( my_spd != 0 )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
LREL = 1;
|
||
|
||
// 書き込んだファームのチェック //
|
||
{
|
||
u8 i;
|
||
u8 comp = 0;
|
||
|
||
// ローダーのマジックと、本文の末尾のマジックは同じか確認
|
||
for( i = 0; i < sizeof( __TIME__ ); i++ )
|
||
{
|
||
comp += (u8)(( (*( __far u8 * ) ( N_MGC_L + i )) == (*( u8 * ) ( N_MGC_T + i ) )) ? 0 : 1);
|
||
}
|
||
if( *( __far u8 * )( N_MGC_L +2 ) != ':' ) // 消去済のまま
|
||
{
|
||
comp ++;
|
||
}
|
||
|
||
if( comp == 0 )
|
||
{
|
||
// OK!
|
||
FSL_InvertBootFlag( );
|
||
FSL_SwapBootCluster( ); // リセットせずに頭から。FSL_Closeは不要
|
||
}
|
||
else
|
||
{
|
||
// データ(マジックナンバーしか見てない)エラー
|
||
// リストア
|
||
alert(3);
|
||
|
||
firm_duplicate( ALTERNATE_FIRMTOP, FIRM_TOP );
|
||
FSL_ForceReset(); // リセット
|
||
// FSL_SwapBootCluster( ); // ブートスワップ「せずに」再起動って出来ないらしい
|
||
}
|
||
// 戻ってこない //
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/********************************************//**
|
||
ファームをバックアップ領域からリストアします。
|
||
|
||
チェック後、最後の最後でブートスワップするので、
|
||
ここではブートスワップは不要です。
|
||
***********************************************/
|
||
void firm_restore( )
|
||
{
|
||
DBG_LED_on;
|
||
LED_PM_POW1 = 0;
|
||
|
||
// バックアップは正常? //
|
||
{
|
||
u16 i;
|
||
u8 comp = 0;
|
||
|
||
for( i = 0; i < sizeof( __TIME__ ); i++ ) // sizeof( __TIME__ ) = 8 らし
|
||
{
|
||
comp += ( *( __far u8 * )( MGC_LOAD + i ) == *( u8 * )( MGC_HEAD_BKUP + i ) ) ? 0 : 1;
|
||
comp += ( *( u8 * )( MGC_HEAD_BKUP + i ) == *( u8 * )( MGC_FOOT_BKUP + i ) ) ? 0 : 1;
|
||
}
|
||
if( *( u8 * )( MGC_FOOT_BKUP ) == 0xFF )
|
||
{
|
||
comp ++;
|
||
}
|
||
|
||
if( comp != 0 )
|
||
{
|
||
// バックアップ領域も壊れた...
|
||
comp = 0;
|
||
|
||
// 3.3Vが上がらないと困る
|
||
EI( );
|
||
iic_mcu_start( );
|
||
RESET2_ast;
|
||
FCRAM_RST_ast;
|
||
GYRO_DISABLE();
|
||
PM_LDSW_on();
|
||
wait_ms( 1 + DELAY_PM_TW_PWUP );
|
||
PM_VDD_on( );
|
||
|
||
while(1)
|
||
{
|
||
WDT_Restart();
|
||
|
||
{
|
||
// 赤LED ピコピコ
|
||
comp++;
|
||
LED_POW1 = ( comp == 1 || comp == 3 )? 1: 0;
|
||
if( comp == 8 )
|
||
{
|
||
comp = 0;
|
||
}
|
||
}
|
||
|
||
{
|
||
// 電源ボタンで電源off
|
||
static u8 sw_hold_count;
|
||
|
||
if( !SW_POW_n_RAW )
|
||
{
|
||
sw_hold_count++;
|
||
}
|
||
else
|
||
{
|
||
sw_hold_count = 0;
|
||
}
|
||
|
||
if( sw_hold_count > 16 )
|
||
{
|
||
sw_hold_count = 0;
|
||
// 電源off
|
||
PM_LDSW_off( );
|
||
|
||
// pwsw待ちで寝る
|
||
KRM = ( KR_SW_POW ); // Mask ではなく、Mode
|
||
MK0 = 0xFFFF;
|
||
MK1 = ~( INT_MSK1_KR );
|
||
MK2L = 0xFF;
|
||
|
||
// PU5 そのまま
|
||
PU7 = bits8(0,0,0,0, 1,0,0,0); // PWSWI
|
||
PU20 = bits8(0,0,0,0, 0,0,0,0); // SW_HOME 停止
|
||
|
||
STOP( );
|
||
|
||
// mcu_wdt_reset; // 無限ループするのはよくないと思う
|
||
|
||
// while(1){
|
||
// NOP(); // こない
|
||
// }
|
||
}
|
||
}
|
||
|
||
// ウェイト
|
||
for( i = 1; i != 0; i++ )
|
||
{
|
||
NOP();
|
||
NOP();
|
||
NOP();
|
||
NOP();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// else{ // バックアップは生きていた
|
||
|
||
while( my_FSL_Init() != ERR_SUCCESS ){ // FSL初期化失敗するようならもう救えない...
|
||
// todo リトライ回数上限?
|
||
alert(1);
|
||
}
|
||
|
||
/* ファームのリストア
|
||
0x4800 - 0x7FFF (ブロック 18 - 27) から
|
||
0x2000 - 0x47FF (ブロック 8 - 17) へコピー
|
||
*/
|
||
if( firm_duplicate( ALTERNATE_FIRMTOP, FIRM_TOP ) != ERR_SUCCESS )
|
||
{
|
||
alert(2);
|
||
}
|
||
DBG_LED_off;
|
||
|
||
// todo リストア失敗したら、LEDちかちかとかさせて、サービス送りにしてもらう?
|
||
|
||
FSL_ForceReset(); // リセット、戻ってこない
|
||
}
|
||
|
||
|
||
|
||
/********************************************//**
|
||
内蔵フラッシュの書き換えのための前準備
|
||
***********************************************/
|
||
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;
|
||
/*
|
||
LVIM = bits8(0,0,0,0, 0,0,1,0);
|
||
LVIS = bits8(0,0,0,0, 1,0,0,0);
|
||
LVIM = bits8(1,0,0,0, 0,0,1,0);
|
||
*/
|
||
FSL_FLMD0_HIGH; // フラッシュ書き替え許可
|
||
}
|
||
|
||
|
||
|
||
/********************************************//**
|
||
内蔵フラッシュの書き換え終了処理
|
||
***********************************************/
|
||
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( u8 block_src,
|
||
u8 block_dest )
|
||
{
|
||
u8 target_block;
|
||
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
|
||
__far u8* p_src = ( __far u8* )( block_src * 0x400 );
|
||
u8 retry_error;
|
||
|
||
led_print(1);
|
||
|
||
// 書き込み先ブロックの数だけ繰り返す
|
||
for( target_block = block_dest;
|
||
target_block < ( block_dest + FIRM_SIZE );
|
||
target_block ++ )
|
||
{
|
||
led_print(2);
|
||
WDT_Restart( );
|
||
// ブロック消去
|
||
retry_error = 5 + 1;
|
||
while( FSL_BlankCheck( target_block ) != FSL_OK )
|
||
{
|
||
led_print(3);
|
||
FSL_Erase( target_block );
|
||
if( -- retry_error == 0 )
|
||
{
|
||
// フラッシュ寿命?
|
||
FSL_Close( );
|
||
return ( ERR_ERR ); // リセット&復帰を試みる どうなるか知らん
|
||
}
|
||
}
|
||
|
||
led_print(4);
|
||
// 分割書き込み分繰り返す
|
||
for( split_write_count = 0;
|
||
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
|
||
split_write_count ++ )
|
||
{
|
||
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 ++;
|
||
p_buff ++;
|
||
buff_written_size ++;
|
||
}
|
||
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 )
|
||
{
|
||
// リカバリはリブート時 //
|
||
FSL_Close( );
|
||
led_print(5);
|
||
// while(1){}
|
||
return ( ERR_ERR );
|
||
}
|
||
}
|
||
led_print(6);
|
||
|
||
// 1ブロック書き込み完了。内部電圧チェックを行う
|
||
while( FSL_IVerify( target_block ) != FSL_OK )
|
||
{
|
||
// リカバリはリブート時 //
|
||
led_print(7);
|
||
return ( ERR_ERR );
|
||
}
|
||
}
|
||
return( ERR_SUCCESS );
|
||
|
||
}
|
||
|
||
|
||
|
||
/********************************************//**
|
||
私家版内蔵フラッシュの書き換え準備
|
||
***********************************************/
|
||
static err my_FSL_Init()
|
||
{
|
||
u8 rv;
|
||
|
||
RTCE = 0;
|
||
|
||
// 書き替え前準備 //
|
||
DI( );
|
||
FSL_Open( ); // 割り込み禁止など
|
||
|
||
FSL_Init( &pool.self_update_work[0] ); // ライブラリ初期化。割り込み中断考慮せず
|
||
rv = FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず
|
||
|
||
return( (err)rv );
|
||
}
|
||
|
||
|
||
/********************************************//**
|
||
MCUリセット
|
||
|
||
system_status.reboot が立ちます。
|
||
***********************************************/
|
||
task_status_immed tski_mcu_reset()
|
||
{
|
||
// 普通に再起動
|
||
my_FSL_Init();
|
||
|
||
FSL_ForceReset(); // リセット
|
||
FSL_Close( );
|
||
|
||
// 保険? //
|
||
mcu_wdt_reset;
|
||
return( ERR_SUCCESS ); // no reach
|
||
}
|
||
|
||
|
||
|
||
/********************************************//**
|
||
書き換え中にエラーが発生した際にLEDを点滅させてエラーを通知
|
||
|
||
人が見るようではなく、オシロなどでパルス数をチェックする
|
||
|
||
デバッガが使えない区間なので LEDprintf デバッグのため。
|
||
***********************************************/
|
||
#ifdef _DBG_LED_PRINT_
|
||
// P1.5 = led_pow_red_old
|
||
void alert( u8 num )
|
||
{
|
||
u8 i;
|
||
|
||
while(1)
|
||
{
|
||
WDT_Restart();
|
||
LED_POW1 = 1;
|
||
for( i = 0; i < num; i++ )
|
||
{
|
||
DBG_LED_on;
|
||
DBG_LED_off;
|
||
}
|
||
LED_POW1 = 0;
|
||
}
|
||
}
|
||
|
||
|
||
/********************************************//**
|
||
書き換え中にエラーが発生した際にLEDを点滅させてエラーを通知(2)
|
||
|
||
人が見るようではなく、オシロなどでパルス数をチェックする
|
||
|
||
デバッガが使えない区間なので LEDprintf デバッグのため。
|
||
***********************************************/
|
||
void led_print( u8 num )
|
||
{
|
||
u8 i;
|
||
|
||
DBG_LED_on;
|
||
for( i = 0; i < num; i++ )
|
||
{
|
||
LED_POW1 = 1;
|
||
LED_POW1 = 0;
|
||
}
|
||
DBG_LED_off;
|
||
}
|
||
#endif
|