ctr_mcu/trunk/task_sys.c
n2232 7eb9f6bdae 1.08
自己アップデート関数、データの転送が途中で打ち切られたときに不正ファームを書き込み、正常判定、煉瓦になることがあった。
関数名が不適なのを修正 tski_を付けた
起動時のポートなど設定コードの順番がよろしくなかった loader.c
マジックコードを書く場所をちょっと追加 たぶん役に立つ日は来ないが
 ROMがどうにも足りなくなったらあるいは… 多段アップデートしてもらって…
 1.00、1.06から/へ 更新できるのは確認した
違うファイル中で同じ変数名、違う中身を設定していた。怖いのでユニークに magic.c


git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@239 013db118-44a6-b54f-8bf7-843cb86687b1
2010-09-30 01:22:06 +00:00

558 lines
15 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 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 );
}