/* ======================================================== MCU CTR BSR 2009/03/30 - 開発技術部 藤田 ブートローダー部 ホストの通信と、自己書き換え、ファームのチェックを行う。 $Id: loader.c 418 2011-09-22 01:35:37Z n2232 $ ======================================================== */ #ifndef _WIN32 #pragma SFR #pragma di #pragma ei #pragma nop #pragma stop #pragma halt #pragma opc #endif #include "incs_loader.h" #include #include "fsl_user.h" #include "i2c_ctr.h" #include "i2c_mcu.h" #include "pm.h" #include "rtc.h" #include "reboot.h" #include "wdt.h" #include "magic.h" #define REG_BIT_RESF_WDT (1<<4) #define REG_BIT_RESF_TRAP (1<<7) #define REG_BIT_RESF_LVI (1<<0) // ======================================================== #if (FSL_DATA_BUFFER_SIZE>0) fsl_u08 fsl_data_buffer[FSL_DATA_BUFFER_SIZE]; #endif #ifdef FSL_INT_BACKUP static fsl_u08 fsl_MK0L_bak_u08; /* if (interrupt backup required) */ static fsl_u08 fsl_MK0H_bak_u08; /* { */ static fsl_u08 fsl_MK1L_bak_u08; /* reserve space for backup information */ static fsl_u08 fsl_MK1H_bak_u08; /* of interrupt mask flags */ static fsl_u08 fsl_MK2L_bak_u08; /* */ static fsl_u08 fsl_MK2H_bak_u08; /* } */ #endif // ======================================================== void hdwinit(); // static にするとcrt0から見えなくなります。注意! static void hdwinit2(); static void chk_platform_type(); static void chk_firm_broke(); extern void main_loop(); /********************************************//** * - ファームアップデート、WDT等のリセット、 * - ファームの破壊、 * - 本体種類の識別、 * - ポート、 * - 低レベルなペリフェラルの初期化をし、 * * main_loop()を呼ぶ。 ***********************************************/ void main( ) { while( 1 ) { WDT_Restart( ); if( RTCEN ) // これはTRAP(自己update)にしか使えない。WDT等では立たない { system_status.reboot = true; } { volatile u8 my_resf = RESF; // ←読むと消える if( ( my_resf & REG_BIT_RESF_WDT ) != 0 ) { vreg_ctr[ VREG_C_MCU_STATUS ] |= REG_BIT_STATUS_WDT_RESET; // set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); // ↑I2Cの初期化後に行う system_status.reboot = true; } else if( ( my_resf & REG_BIT_RESF_TRAP ) != 0 ) // ( FSL_ForceReset, 'r' ) { system_status.reboot = true; } /* LVI使用せず else if(( my_resf & REG_BIT_RESF_LVI ) != 0 ) { vreg_ctr[ VREG_C_MCU_STATUS ] |= ( 1 << 2 ); } */ } //* ROMがどうにも足りなくなったら、評価の上コメントアウト if( !system_status.reboot ) { // 通常の電源投入 // 電池接続時、ちょっと待ってみる(チャタリング対策) u16 pwup_delay0; for( pwup_delay0 = 0xFFFF; pwup_delay0 != 0; pwup_delay0 -- ){;}; } //*/ hdwinit2( ); #ifndef _WIN32 // ファームの整合性チェック // chk_firm_broke(); // 壊れていたら帰ってこない #endif // 機種判定 chk_platform_type(); // HALデバッグリセット hal_reset(); hal_update(); // RTC 初期化 RTC_init( ); // 内部でリブートか判定して初期化するか判断します // 通常運転 main_loop( ); } } /********************************************//** * マジックナンバーをチェックして、動作させようとしているファームが破損していないかチェックします。 * * 壊れていた場合はリストアを試み、MCUはリセットします。 ***********************************************/ static void chk_firm_broke() { u8 i; u8 comp = 0; // ローダーと本体は同じバージョンか? /// 次へのアップデートの途中で終わってないか? for( i = 0; i < sizeof( __TIME__ ); i++ ) // sizeof( __TIME__ ) = 8 らし { comp += ( *( __far u8 * )( MGC_LOAD + i ) == *( u8 * )( MGC_FOOT + i ) ) ? 0 : 1; comp += ( *( u8 * )( MGC_HEAD + i ) == *( u8 * )( MGC_FOOT + i ) ) ? 0 : 1; } if( *( u8 * )( MGC_FOOT +2 ) != ':' ) // 消去済のまま { comp ++; } if( comp != 0 ) { // ファームリストアを試みる firm_restore( ); // 帰ってこない。リセットをかける。 } } /********************************************//** プラットフォームの判定を行い、system_statusにセットします。 デバッガつないでると上手に判定できないことがあります。 ●CTRファミリ DEV_DET(P12.[2:1]) ●CTR&その開発機材 P40,41 !注意! デバッグ有効でP40がLだとMCUが起動しません! - HH 実機 - HL NBD試遊台 - LH スタンドアロン試遊台 - LL ISデバッガ ***********************************************/ void chk_platform_type() { // ●CTRファミリ // system_status.family = (enum family_)( DEV_DET >> 1 ); /// あぁ... #ifdef _DBG_FORCE_FLOWER // 強制的に機種設定をしてデバッグしたいとき // system_status.family = FAMILY_FLOWER; #endif #ifdef _MCU_ARR if( system_status.family == FAMILY_SPFL ) { system_status.family = FAMILY_CLOSER; } #endif if( system_status.family == FAMILY_CTR ) { system_status.LCD_is_CGS = true; } else { // FAMILY_SPFL or FAMILY_SNAKE or FAMILY_FLOWER // アモルファスしか生産しない system_status.LCD_is_CGS = false; } if( system_status.LCD_is_CGS == true ) { pm_reg_bit_vddlcd = PM_REG_BIT_VDDLCD_CGS; } else { pm_reg_bit_vddlcd = PM_REG_BIT_VDDLCD_AMO; } set_vdd_voltages( system_status.family ); // ●CTR&その開発機材 // // 一応初期化 system_status.is_dev = false; system_status.taikendai = false; system_status.taikendai_nbd = false; switch( DIPSW ) { case DIPSW_TAIKENDAI: system_status.taikendai = true; break; case DIPSW_TAIKENDAI_NBD: system_status.taikendai_nbd = true; break; case DIPSW_ISDEV: system_status.is_dev = true; break; } #ifdef _FORCE_TAIKENDAI_ system_status.taikendai = true; #endif #ifdef _FORCE_TAIKENDAI_NBD_ system_status.taikendai_nbd = true; #endif } /********************************************//** 最小限のレジスタ初期化を行います。 組み込みスタートアップルーチンから呼ばれます。 ***********************************************/ void hdwinit( void ) { // スタートアップルーチンが勝手に呼びます DI( ); /* マスタ割り込み禁止 */ CMC = bits8(0,0,0,1, 0,0,0,0); /* X1発振せず(入力ポート)、XT1使用、超低電力発振は不安定に付き通常で */ CSC = bits8(1,0,0,0, 0,0,0,0); /* X1発振なし、XT1発振あり、高速内蔵発振動作 */ OSMC = bits8(0,0,0,0, 0,0,0,1); /* 隠しレジスタ */ NOP();NOP();NOP(); // 3clk開ける CKC = bits8(0,0,0,0, 1,0,0,0); /* CPU/周辺クロック=fMAIN、fMAIN=fMX、fCLK=fMX */ /*--- 低電圧検出回路の設定 ---*/ /* リセット解除時のデフォルトは、オプション・バイトにて指定される */ LVIS = 0x00; /* VLVI = 4.22±0.1V */ // LVIM = 0x00; /* LVI動作禁止 */ /* 電源電圧(VDD)<検出電圧(VLVI)時に割込発生 */ /* 電源電圧(VDD)≧検出電圧