#pragma SFR #pragma NOP #pragma HALT #pragma STOP #include "incs.h" #include "i2c_twl.h" #include "i2c_ctr.h" #include "led.h" #include "accero.h" #include "pm.h" #include "rtc.h" #include "sw.h" #include "adc.h" #include "self_flash.h" //========================================================= extern void nop8(); static void chk_emergencyExit(); static void force_off_check(); static void send_getup_to_soc(); //========================================================= extern bit info_led_off; extern bit going_to_sleep; extern bit bt_chg_ready; static u8 timeout_sleep; extern u8 chg_led_override; /* ======================================================== マイコン内部で必要なもの ・省電力に入れる  system_status.pwr_state == OFF_TRIG で、このタスクが呼ばれると、 省電力モードに入ります ======================================================== */ void tsk_sys( ) { static u8 timeout = 0; switch ( system_status.pwr_state ) { case OFF: //------------------------------------------------------- // スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。 if( system_status.poweron_reason == NONE ) { // スイッチで電源on if( SW_pow_count != 0 ) { timeout = 0; } else { timeout += 1; } if( timeout > 100 ) { system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。 renge_task_interval_run_force = true; return; } if( SW_pow_count < 10 ) { // もう少しスイッチの様子を見る return; } // 電源投入 system_status.poweron_reason = PWSW; } SW_pow_mask = true; timeout = 0; // todo debug #ifdef _DEBUG_BT_FUEL_ vreg_ctr[ VREG_C_DBG01 ] = 99; #endif #ifdef _DEBUG_BT_TEMP_ vreg_ctr[ VREG_C_DBG01 ] = 0x80; #endif vreg_ctr[ VREG_C_COMMAND3 ] = 0; // 電源投入 // iic_mcu_start( ); bt_force_update = false; BT_chk(); // 実機やバッテリの判定、電池残量ICの設定 #ifndef _ALLOW_NOBATT_ if( system_status.model == MODEL_JIKKI_NOBATT ) { renge_task_interval_run_force = true; system_status.pwr_state = OFF_TRIG; return; } #endif // 残量チェック BT_get_left(); // 先に、BT_chk()が実行されている必要があります。 if( // ( vreg_ctr[VREG_C_BT_REMAIN] < 1 ) // こっちで判定すると電池がほとんど無いときに // && // アダプタ差しても数分起動できなくなっちゃう ( vreg_ctr[VREG_C_BT_VOLTAGE] < ( V_TH_ZERO / 256 ) ) ) { // 電池が少ないので起動させない(電圧チェックもされてる) renge_task_interval_run_force = true; system_status.pwr_state = OFF_TRIG; return; } // ポートの設定 電源入れる前に。 PM7.4 = 1; // SW_wifi PM20.4 = 1; // sw_home PM20.3 = 1; // wl_tx PM2.3 = 1; // key_sel PM2.5 = 1; // acc_valid1 PM14.1 = 1; // acc_valid2 if( PM_sys_pow_on( ) != ERR_SUCCESS ) { // 電源起動不可エラー renge_task_interval_run_force = true; system_status.pwr_state = OFF_TRIG; return; } // ここまで来ると、電源投入確定 // PU5.1 = 1; // 1:PM_CHARGE PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC_n PU20.4 = 1; // SW_HOME if( system_status.poweron_reason == PWSW ) { // 電源ボタンでのonの時は、LEDを点灯させる vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO; } else { // とりあえず、LED消灯状態で起動させる vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; } system_status.pwr_state = ON_TRIG; PM_LCD_vcom_set( ); // LCDの対向電圧値など書き込み break; case ON_TRIG: //------------------------------------------------------- IIC_ctr_Init( ); IIC_twl_Init( ); RTC_32k_on( ); vreg_twl_init( ); vreg_ctr_reset( ); KRM = 0b00000000; PIF0 = 0; system_status.poweron_reason = NONE; renge_task_interval_run_force = true; MK0 = INT_MSK0_RSV; MK1 = INT_MSK1_RSV; iic_mcu_start(); #ifdef _MCU_BSR_ // MK2 = ~( INT_MSK2_IIC_TWL | INT_MSK2_WIFI_TX_BSR | INT_MSK2_CODEC_PMIRQ ); // PMK21 = 0; // wifi 使わない PMK6 = 0; // pm_irq #else MK2L = ~INT_MSK2_WIFI_TX_KE3; #endif // リブート時、ステータスを何となく更新 if( system_status.reboot ) { u8 bl_status_temp; bl_status_temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ); vreg_ctr[ VREG_C_STATUS ] |= (( bl_status_temp & 0x03 ) << 5 ); set_bit( ( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_LCD ) != 0 ), vreg_ctr[ VREG_C_STATUS ], REG_BIT_LCD_POW ); BT_chk(); } LED_init( ); // reboot時の↑BT_Chk,BT_chk後に行いたい system_status.reboot = 0; system_status.pwr_state = ON; // WDTリセット時、I2Cの初期化まで割り込み保留 // ほんとはここにべた書きしたくないが... if( ( vreg_ctr[ VREG_C_MCU_STATUS ] & REG_BIT_STATUS_WDT_RESET ) != 0 ) { set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); } break; case ON: //--------------------------------------------- // PMICによる強制電源断チェック // デバッガがreset1をアサートすることもある。そのときは全部リセット chk_emergencyExit(); // SLP監視 if( PIF0 ){ // slp割り込み PIF0 = 0; if( !SLP_REQ ){ // 一瞬で起きた send_getup_to_soc(); } else { PM_VDD_ecoMode(); system_status.pwr_state = SLEEP; renge_task_interval_run_force = true; } } if( going_to_sleep ) { timeout_sleep += 1; if( timeout_sleep == 0 ) // sleepするって言ったけど一瞬で起きて気がつかなかった { send_getup_to_soc(); } } // 強制offカウント force_off_check(); #ifdef _TAIKENDAI_ if( PM_EXTDC_n ) { system_status.pwr_state = OFF_TRIG; } #endif break; case SLEEP: //------------------------------------------ chk_emergencyExit(); // スリープから復帰 if( !SLP_REQ ){ PM_VDD_normMode(); wait_ms( 5 ); // tdly_sw send_getup_to_soc(); system_status.pwr_state = ON; } force_off_check(); #ifdef _TAIKENDAI_ if( PM_EXTDC_n ) { system_status.pwr_state = OFF_TRIG; } #endif break; case OFF_TRIG: //--------------------------------------- default: // LED消灯を待つ vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_OFF; vreg_ctr[ VREG_C_LED_WIFI ] = WIFI_LED_OFF; vreg_ctr[ VREG_C_LED_TUNE ] = LED_TUNE_ILM_OFF; info_led_off = true; if( LED_duty_pow_blu != 0 ) { return; } system_status.force_off = 0; vreg_ctr[ VREG_C_ACC_CONFIG ] = 0x00; tski_acc_hosu_set(); LED_stop( ); IIC_ctr_Stop( ); IIC_twl_Stop( ); RTC_32k_off(); vreg_ctr[VREG_C_IRQ0] = 0; vreg_ctr[VREG_C_IRQ1] = 0; vreg_ctr[VREG_C_IRQ2] = 0; vreg_ctr[VREG_C_IRQ3] = 0; // 電源オン条件の割り込みセット // PWSW KR3 押すとL // BG24 KR4 // ふた開け INTP5 閉じるとL // ACアダプタ INTP4 アダプタありでL // RTC while( iic_mcu_busy ) {; } KRM = ( KR_SW_POW ); // Mask ではなく、Modeなのだそうだ。紛らわしい MK0 = ~( INT_MSK0_EXTDC ); MK1 = ~( INT_MSK1_KR | INT_MSK1_RTCALARM | INT_MSK1_RTCINTVAL ); MK2L = 0b11111111; // PU5 そのまま PU7 = 0b00001001; // PWSWI,PM_EXTTDC,( IRQ0_deactive(), PM_IRQ_deactive ) PU20.4 = 0; // SW_HOME 停止 IF0 = 0; IF1 = 0; IF2 = 0; IRQ0_disable; PM_sys_pow_off( ); P7.4 = 0; // SW_wifi PM7.4 = 0; P20.4 = 0; // sw_home PM20.4 = 0; P20.3 = 0; // WL_TX PM20.3 = 0; P2.3 = 0; // KEY_SEL PM2.3 = 0; P2.5 = 0; // ACC_ready1 PM2.5 = 0; P14.1 = 0; // ACC_ready2 PM14.1 = 0; iic_mcu_stop( ); timeout = 0; system_status.pwr_state = BT_CHARGE; SW_pow_mask = true; SW_pow_count = 0; // no break // case BT_CHARGE: if( !PM_EXTDC_n ) { // アダプタが刺さってるときはこのブロックを繰り返す。 BT_chk(); // 要ポーリング(電池抜かれ検出のため) // ↑の中で必要だったらI2C_m_init呼んでます // アダプタ有り:充電温度監視 if( SW_pow_count >= 10 ) // 電源スイッチが押されるのを待つ { // 電源投入 system_status.poweron_reason = PWSW; system_status.pwr_state = OFF; } if( system_status.model != MODEL_JIKKI ) { iic_mcu_stop( ); } #ifdef _TAIKENDAI_ // 電源投入 wait_ms(46); system_status.poweron_reason = PWSW; system_status.pwr_state = OFF; #endif } else { static bit chg_ena_orig; if( chg_led_override != 0 ) // これがゼロになるまで待つ { return; }; chg_ena_orig = BT_CHG_Ena_n; // 省電力へ移行 system_status.poweron_reason = NONE; iic_mcu_stop( ); pm_chk_adapter(); PM_Chg_Stop(); bt_force_update = true; while( RWST ) {;} // 割り込み待ちで寝る // RTCIMK = 1; # ifdef _MCU_BSR_ CKC = 0b00001001; OSMC = 0x00; # endif BT_CHG_ENABLE(); // リークを減らすため STOP( ); // 起きる // // 起きる条件は // ・KeyReturn割り込み(電源ボたん) // ・RTCアラーム // ・アダプタ挿抜 // BT_CHG_Ena_n = chg_ena_orig; // todo rom足りない! if( PM_EXTDC_n ) { // 一度起こしてしまう。ペリフェラルの初期化など流用のため。 // 電源ボタンのタイムアウトで返ってくる SW_pow_mask = false; } # ifdef _MCU_BSR_ OSMC = 0x01; CKC = 0b00001000; # endif RTCIMK = 0; system_status.pwr_state = OFF; #ifdef _TAIKENDAI_ system_status.pwr_state = OFF_TRIG; #endif } return; #if 0 default: NOP( ); // あり得ないステート #endif } } /*******************************************************//** PMICが電源異常で止めたか確認 **********************************************************/ static void chk_emergencyExit(){ static u8 shirobako_power_control_count; if( shirobako_power_control_count == 0 ) { if( !RESET1_n ) // PM_chk_LDSW() はI2C_mを使用し、高コスト { if( PM_chk_LDSW( ) == 0 ) { // リセットが下がってる /// PMICが異常終了判断をした system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = true; } else { // 白箱の仕業 shirobako_power_control_count = 1; } } } else { if( shirobako_power_control_count == 240 ) // <- 240はマジックナンバー // デバッガが何かした。reset1を解除するまでは無視 { if( RESET1_n ) // リセットネゲート待ち { shirobako_power_control_count = 0; } else { // nothing to do } } else if( shirobako_power_control_count == 200 ) // デバッガが何かしたいらしい { // 白箱は電源を切りたいらしい system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = true; shirobako_power_control_count = 240; } else { if( !RESET1_n ) { shirobako_power_control_count += 1; } else { // リセットをかけたらしい iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL, 0 ); vreg_ctr[VREG_C_STATUS] = ( vreg_ctr[VREG_C_STATUS] & 0b10011111 ); vreg_ctr[VREG_C_COMMAND0] |= REG_BIT_RESET1_REQ; renge_task_immed_add( tski_do_command0 ); shirobako_power_control_count = 240; } } } } /* ======================================================== ・電源ボタン長押し ・電池切れ ・電池抜け での強制OFF。発動すると解除不能 ======================================================== */ static void force_off_check() { if( system_status.force_off ) { system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = true; } } /* ======================================================== SoCを起こす   電圧が通常に戻ってから呼んで下さい。 ======================================================== */ void send_getup_to_soc() { going_to_sleep = false; timeout_sleep = 0; #ifdef _MODEL_CTR_ SLP_ACK = 1; nop8(); // nop8(); SLP_ACK = 0; #endif } /*******************************************************//** firm_update()を task_status_immed型 を返すようにすればいいのですが... **********************************************************/ task_status_immed tski_firm_update(){ firm_update(); return( ERR_SUCCESS ); }