ctr_mcu/trunk/task_sys.c
n2232 264d038c61 ■2.26
○異常終了時にαVOLがLowにならない問題に対応 (SPR_TOOLに対応)
SNAKE/CLOSER用MCU FW ver.2.33, 2.35 でご対応頂いた事と
同様の内容です。

○MAX17048に対応
SNAKE/CLOSER用MCU FW ver.2.34 でご対応頂いた事と
同様の内容です。

を持ってきました。手動コピペです。

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@598 013db118-44a6-b54f-8bf7-843cb86687b1
2014-01-07 01:44:15 +00:00

836 lines
23 KiB
C
Raw Permalink 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.

/* ========================================================
task_sys
電源周りを司るのタスク
$Id$
======================================================== */
#ifndef _WIN32
#pragma SFR
#pragma NOP
#pragma HALT
#pragma STOP
#endif
#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"
#include "i2c_mcu.h"
#include "vreg_twl.h"
//=========================================================
#define WAIT_SHIROBAKO_POW_CONTROL 240
//=========================================================
extern void nop8();
static err chk_emergencyExit();
static void force_off_check();
static void send_getup_to_soc();
static void chk_sleep();
static void chk_awake();
static err direct_boot_sleep_check();
static err chk_pwsw_timeout();
static void go_stop();
static void ports_finalize();
static void irqs_finalize();
static void restore_status_regs();
static err leds_closed();
#ifdef _DBG_CHK_OFF_LEAK_
static void leak_check();
#endif
//=========================================================
extern bit info_led_off;
extern bit going_to_sleep;
extern bit bt_authorized;
static u8 timeout_sleep;
extern u8 chg_led_override;
#ifdef i2c_timeout_test
extern bit i2c_mcu_time_out_error;
#endif
//=========================================================
#define PWSW_POWON_TIME (u8)( 20 / SYS_INTERVAL_TICK ) // [ms] // INTERVAL_TSK_SW で割らない。値が元から小さいので
#define PWSW_ON_CHECK_TIMEOUT 100 // 適当 電源onの為に電源スイッチが操作されたとき、この時間経過したらmcuを省電力に戻す
#define SELSW_DIRECT_BOOT_DELAY (u16)( 1000 / SYS_INTERVAL_TICK )
/********************************************//**
電源の立ち上げやスリープなどを管理
***********************************************/
void tsk_sys( )
{
hal_update();
switch ( system_status.pwr_state )
{
case ON_CHECK: //-------------------------------------------------------
// 強制電源断カウントダウンタイマクリア
clear_pow_off_countdown();
// 他の割り込みでHALT(スリープ)が解除 / アダプタ有時
// 電源スイッチでHALT解除 //
if( system_status.poweron_reason == RSN_PWSW )
{
if( PM_EXTDC_n )
{
// アダプタなし
if( chk_pwsw_timeout() == ERR_ERR )
{
// タイムアウト。スリープに入れる
return;
}
}
else
{
BT_chk(); // バッテリ外されたら充電停止などするため
}
if( SW_pow_count < PWSW_POWON_TIME )
{
// 押し時間が短くて電源onに到達していない
return;
}
}
// else { if( system_status.poweron_reason == RSN_TRIAL、… ) 電源投入 }
SW_pow_mask = true; // pwsw押しっぱなしで電源入/切 を繰り返さないように
// 電源投入 //
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;
}
// ポートの方向設定 電源入れる前に。
PM_SW_WIFI_n = 1;
PM_SW_HOME_n_JIKKI = 1;
PM_WL_TX = 1;
PM_SW_SEL_n = 1;
PM_ACCEL_INT1 = 1;
PM_ACC_VALID = 1;
if( PM_sys_pow_on( ) != ERR_SUCCESS )
{ // 電源起動不可エラー
renge_task_interval_run_force = true;
system_status.pwr_state = OFF_TRIG;
return;
}
// ここまで来ると、電源投入確定 //
// プルアップon //
PU_BT_IN_CHG_n = 1;
PU7 = bits8(0,0,0,1, 1,1,0,1); // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC_n
PU_SW_HOME_n_JIKKI = 1; // SW_HOME
wait_ms( 50 ); // プルアップ後電圧がちゃんと上がるのをまってhal_update() しないと期待したのが取れない
/// 50ms は暫定値
// 蓋閉じなら、HOMEも押されてないと電源を入れない。しかも一秒押し続ける
// (reset解除せずに電源断してしまう。ユーザーには気づくまい。)
system_status.pwr_state = DIRECT_BOOT_CHECK;
// system_status.pwr_state = ON_TRIG;
break;
case DIRECT_BOOT_CHECK: //-------------------------------------------------------
switch( direct_boot_sleep_check() )
{
case ERR_ERR: // スリープが入っていて、必要なキーが足りないので起動させない
system_status.pwr_state = OFF_TRIG;
return;
break;
default:
dbg_nop();
/* fall through */
case ERR_RET1: // 1秒間 sel を押し続けなくてはならない。カウントの途中...
return;
break;
case ERR_SUCCESS: // 起動させる。ダイレクトブートするはず。
system_status.pwr_state = ON_TRIG;
break;
}
case ON_TRIG: //-------------------------------------------------------
reset_release();
if( system_status.poweron_reason == RSN_PWSW ||
system_status.poweron_reason == RSN_TRIAL )
{
// 電源ボタンでの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の対向電圧値など書き込み
IIC_ctr_Init( );
IIC_twl_Init( );
vreg_twl_init( );
vreg_ctr_reset( );
system_status.poweron_reason = NONE;
renge_task_interval_run_force = true;
// 割り込み関係
KRM = bits8(0,0,0,0, 0,0,0,0);
PIF0 = 0;
MK0 = INT_MSK0_RSV;
MK1 = INT_MSK1_RSV;
iic_mcu_start();
// MK2 = ~( INT_MSK2_IIC_TWL | INT_MSK2_WIFI_TX_BSR | INT_MSK2_CODEC_PMIRQ );
// PMK21 = 0; // wifi 使わない
PMK6 = 0; // pm_irq
// リブート時、ステータスを何となく更新
if( system_status.reboot )
{
restore_status_regs();
}
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: //---------------------------------------------
if( chk_emergencyExit() == ERR_ERR )
{
// PMICによる強制電源断チェック
// デバッガがreset1をアサートすることもある。そのときは全部リセット
system_status.pwr_state = OFF_TRIG;
renge_task_interval_run_force = true;
}
chk_sleep(); // SLP監視。system_status.pwr_state いじります。行儀悪い
force_off_check(); // 強制offカウント
#ifndef _TAIKENDAI_SEISAN_SPECIAL_
if( system_status.taikendai ) // アダプタが抜けたら自動で電源off
{
if( PM_EXTDC_n )
{
system_status.pwr_state = OFF_TRIG;
}
}
#endif
break;
case SLEEP: //------------------------------------------
if( chk_emergencyExit() == ERR_ERR )
{
system_status.pwr_state = OFF_TRIG;
renge_task_interval_run_force = true;
}
chk_awake(); // スリープから復帰
force_off_check();
// leak_check();
#ifndef _TAIKENDAI_SEISAN_SPECIAL_
if( system_status.taikendai ) // アダプタが抜けたら自動で電源off
{
if( PM_EXTDC_n )
{
system_status.pwr_state = OFF_TRIG;
}
}
break; // ←ここでよい。
#else
/* FALLTHROUGH */
#endif
default: //---------------------------------------
system_status.pwr_state = OFF_TRIG; // あり得ないステート。デバッグ用
// dbg_nop();
/* FALLTHROUGH */
case OFF_TRIG: //---------------------------------------
// LED消灯を待つ
if( leds_closed() != ERR_SUCCESS )
{
return;
}
// 強制電源断カウントダウンタイマクリア
clear_pow_off_countdown();
// 加速度センサ停止
vreg_ctr[ VREG_C_ACC_CONFIG ] = 0x00;
tski_acc_setup();
EI(); // DI状態でかえって来るので、I2C_mcu 完了させるのに必要
// その他ペリフェラル停止
LED_stop( );
IIC_ctr_Stop( );
IIC_twl_Stop( );
RTC_32k_off();
// 電源オン条件の割り込みセット
// PWSW KR3 押すとL
// BG24 KR4
// ふた開け INTP5 閉じるとL
// ACアダプタ INTP4 アダプタありでL
// RTC
while( iic_mcu_busy )
{;}
irqs_finalize();
IRQ0_disable; // 対 SoC のピン
PM_sys_pow_off( ); // 電源カットオフ
ports_finalize();
system_status.pwr_state = OFF;
SW_pow_mask = true;
SW_pow_count = 0;
// HALデバッグリセット 忘れると電源on出来なくなることが…
hal_reset();
/* FALLTHROUGH */
case OFF:
// 注:現状では電源ボタンしか電源投入はありません。
system_status.poweron_reason = NONE;
LCD_AMOL_HV_CTRL = 0; // 異常終了時、アモルファスLCD用電源を切り忘れてしまう(PM_LCD_OFF()を通らないため)
if( !PM_EXTDC_n
|| chg_led_override != 0 ) // これがゼロになるまで待つ
{
// アダプタ有り /////////////////////////////// または、アダプタさして秒は充電LEDを点けている期間
// 電源ボタン押しチェックへ
system_status.poweron_reason = RSN_PWSW;
system_status.pwr_state = ON_CHECK;
#ifndef _TAIKENDAI_SEISAN_SPECIAL_
// 試遊台なら自動で電源再投入
if( system_status.taikendai )
{
vreg_ctr[ VREG_C_HAL_OVW_CONT0 ] = vreg_ctr[ VREG_C_HAL_OVW_CONT1 ] = 0;
wait_ms(46); // pmicの電源再投入仕様のため
system_status.poweron_reason = RSN_TRIAL;
system_status.pwr_state = ON_CHECK;
}
#endif
}
else
{
// アダプタなし ///////////////////////////////
// 省電力へ移行
iic_mcu_stop( );
pm_chk_adapter();
PM_Chg_Stop();
go_stop(); // 割り込み待ちで stop モードへ。
hal_update();
renge_flg_interval = 0;
bt_force_update = true;
// 起きた理由は?
if( !PM_EXTDC_n ){
system_status.pwr_state = OFF; // 一回回ってきて、ON_CHECKに行く
}
/* 封印中
// RTCアラーム。
else if( vreg_ctr[ VREG_C_IRQ1 ] & REG_BIT_RTC_ALARM )
{
system_status.poweron_reason = RSN_RTC_ALARM;
system_status.pwr_state = ON_CHECK;
}
// else if( 他の割り込みで電源on ){
// 現状他の要因では起きない
// }
*/
else // if( !SW_POW_n ) // (それ以外なら)電源ボタンで起きた
{
SW_pow_mask = false;
system_status.poweron_reason = RSN_PWSW;
system_status.pwr_state = ON_CHECK;
}
RTCIMK = 0; // sys tick タイマー有効
#ifndef _TAIKENDAI_SEISAN_SPECIAL_
if( system_status.taikendai )
{
system_status.pwr_state = OFF_TRIG;
}
#endif
}
}
}
/********************************************//**
電源ボタンチャタリング回避。
タイムアウトするまでに電源投入確定しないとoffに戻る
***********************************************/
static err chk_pwsw_timeout()
{
static u8 pwsw_timeout = 0;
if( SW_pow_count != 0 )
{
pwsw_timeout = 0;
}
else
{
pwsw_timeout ++;
}
if( pwsw_timeout > PWSW_ON_CHECK_TIMEOUT )
{
SW_pow_count = 0;
system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。
renge_task_interval_run_force = true;
return ERR_ERR;
}
return ERR_SUCCESS;
}
/********************************************//**
スリープに入れるか?
SoC から通知がある
***********************************************/
static void chk_sleep()
{
if( going_to_sleep ) // 絶対に SLP_REQ の前に予告が来る
{
timeout_sleep ++;
if( timeout_sleep == 0 || // オーバーフローを期待。sleepするって言ったけど一瞬で起きて気がつかなかった
( PIF0 && !SLP_REQ )) // slp割り込みが入った気がしたが、もう起きてしまった
{
PIF0 = 0;
send_getup_to_soc();
}
if( PIF0 && SLP_REQ ){
PIF0 = 0;
PM_VDD_ecoMode();
system_status.pwr_state = SLEEP;
renge_task_interval_run_force = true;
}
}
}
/********************************************//**
起床させるか?
***********************************************/
static void chk_awake()
{
if( !SLP_REQ ){
PM_VDD_normMode();
wait_ms( 5 ); // tdly_sw
send_getup_to_soc();
system_status.pwr_state = ON;
}
}
/********************************************//**
STOP モードへ移行
諸々のレジスタ設定があります
***********************************************/
static void go_stop()
{
while( RWST )
{;}
// 割り込み待ちで寝る //
RTCIMK = 1; // systick用インターバルタイマー割り込みマスク
#ifdef _DBG_CHK_OFF_LEAK_
leak_check();
#endif
CKC = bits8(0,0,0,0, 1,0,0,1); // 4MHzに落として(bit0)からSTOPしなくてはならない
OSMC = bits8(0,0,0,0, 0,0,0,0); // 5MHz以下モードへ。
if( PM_EXTDC_n_RAW ) // きわどいタイミングで挿抜が起きることがある。HAL通さないべきoff中ですし
{
STOP();
}
// 起きる //
// 起きる条件は
// ・KeyReturn割り込み電源ボタン
// ・RTCアラーム現在封印
// クロック復帰
OSMC = bits8(0,0,0,0, 0,0,0,1); // 8MHz動作準備
nop8();
CKC = bits8(0,0,0,0, 1,0,0,0); // OSMC.FSEL = 1 後3clk以上開ける
}
/********************************************//**
FLOWER direct boot チェック
sleep がスライドスイッチになった都合でチェックを強化(なってるのかなぁ)
MCU 側でやること。
・sleep になってたら起動しない
・ただし、home が押されてたら起動させる
***********************************************/
static err direct_boot_sleep_check()
{
static u16 sel_sw_count;
// 蓋空き?
if( SHELL_OPEN )
{
// 通常起動
sel_sw_count = 0;
return ERR_SUCCESS;
}
// else 蓋閉じ/スリープスイッチon
/// ダイレクトブートチェック
if( SW_SEL_n || SW_POW_n )
{
// sel が押されてない
sel_sw_count = 0;
return ERR_ERR;
}
// else sel が押されてる。時間測定する。
sel_sw_count++;
if( sel_sw_count < SELSW_DIRECT_BOOT_DELAY )
{
return ERR_RET1; // 押しているがまだ足りない
}
// else ダイレクトブート条件満たした
sel_sw_count = 0;
return ERR_SUCCESS;
}
/********************************************//**
ポート類を停止モードに。
こういう回路でも、L出力にしなきゃだめだそうな。
***********************************************/
static void ports_finalize()
{
SW_WIFI_n_RAW = 0;
PM_SW_WIFI_n = 0;
SW_HOME_n_JIKKI_RAW = 0;
PM_SW_HOME_n_JIKKI = 0;
WL_TX = 0;
PM_WL_TX = 0;
SW_SEL_n = 0;
PM_SW_SEL_n = 0;
ACCEL_INT1 = 0;
PM_ACCEL_INT1 = 0;
ACC_VALID = 0;
PM_ACC_VALID = 0;
// PU5 そのまま
PU7 = bits8(0,0,0,0, 1,0,0,1); // PWSWI,PM_EXTTDC,( IRQ0_deactive(), PM_IRQ_deactive )
PU_SW_HOME_n_JIKKI = 0; // SW_HOME 停止
}
/********************************************//**
MCU 内部 IRQ の停止
***********************************************/
static void irqs_finalize()
{
// irqマスク設定
KRM = ( KR_SW_POW ); // Mask ではなく、Modeなのだそうだ。紛らわしい
MK0 = ~( INT_MSK0_EXTDC | INT_MSK0_WDTI );
MK1 = ~( INT_MSK1_KR | INT_MSK1_RTCINTVAL ); // INT_MSK1_RTCALARM | RTCアラーム封印中
MK2L = 0xFF;
// irqフラグクリア
vreg_ctr[VREG_C_IRQ0] = 0;
vreg_ctr[VREG_C_IRQ1] = 0;
vreg_ctr[VREG_C_IRQ2] = 0;
vreg_ctr[VREG_C_IRQ3] = 0;
IF0 = 0;
IF1 = 0;
IF2 = 0;
}
static err leds_closed()
{
vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_OFF;
vreg_ctr[ VREG_C_LED_WIFI ] = WIFI_LED_OFF;
vreg_ctr[ VREG_C_LED_3D ] = LED_3D_ILM_OFF;
info_led_off = true;
if( LED_duty_pow_blu != 0 ||
LED_duty_WiFi != 0 ||
LED_duty_3d != 0 ||
LED_duty_notify_red != 0 ||
LED_duty_notify_grn != 0 ||
LED_duty_notify_blu != 0 )
{
return ERR_ERR;
}
return ERR_SUCCESS;
}
/********************************************//**
PMICが電源異常で止めたか確認
***********************************************/
static err chk_emergencyExit(){
static u8 shirobako_power_control_count;
// wifi モジュールキャリブレーションモードでreset1を自分から下げてるときはチェックをパス
if( is_wifi_calib_resets_ast )
{
return ERR_SUCCESS;
}
if( shirobako_power_control_count == 0 )
{
if( !RESET1_n ) // PM_chk_LDSW() はI2C_mを使用し、高コスト
{
if( !PM_chk_LDSW() )
{
// リセットが下がってる
/// PMICが異常終了判断をした
return ERR_ERR;
}
else
{
// 白箱の仕業
shirobako_power_control_count = 1;
}
}
}
else
{
if( shirobako_power_control_count == WAIT_SHIROBAKO_POW_CONTROL ) // マジックナンバー
// デバッガが何かした。reset1を解除するまでは無視
{
if( RESET1_n ) // リセットネゲート待ち
{
shirobako_power_control_count = 0;
}
else
{
// nothing to do
}
}
else if( shirobako_power_control_count == 200 ) // * (sys_tick)[ms]
// デバッガが何かしたいらしい
{
#ifndef _RVD_
// 白箱は電源を切りたいらしい
shirobako_power_control_count = WAIT_SHIROBAKO_POW_CONTROL;
return ERR_ERR;
#endif
}
else
{
if( !RESET1_n )
{
if( shirobako_power_control_count != 255 )
shirobako_power_control_count ++;
}
else
{
// (TSボードで手動で/デバッガが)リセットをかけたらしい
send_cmd_pmic( PM_REG_ADRS_BL, 0 );
vreg_ctr[VREG_C_STATUS] = ( vreg_ctr[VREG_C_STATUS] & bits8(1,0,0,1, 1,1,1,1) );
vreg_ctr[VREG_C_COMMAND0] |= REG_BIT_RESET1_REQ;
renge_task_immed_add( tski_do_command0 );
shirobako_power_control_count = WAIT_SHIROBAKO_POW_CONTROL;
}
}
}
return ERR_SUCCESS;
}
/********************************************//**
リブート時、バックライトステータスをPMから読みだして再設定しておく
***********************************************/
static void restore_status_regs()
{
// バックライト系
u8 bl_status_temp;
bl_status_temp = read_pmic( PM_REG_ADRS_BL );
vreg_ctr[ VREG_C_STATUS ] |= (( bl_status_temp & 0x03 ) << 5 );
set_bit_if( ( read_pmic( PM_REG_ADRS_VDD_LCD ) != 0 ),
vreg_ctr[ VREG_C_STATUS ], REG_BIT_LCD_POW );
// LCD_AMOL_HV_CTRL はノーケアでよい(レジスタはリセットされないので)
// バッテリ&本体識別
BT_chk();
}
/********************************************//**
- 電源ボタン長押し
- 電池切れ
- 電池抜け
での強制OFF。発動すると解除不能
***********************************************/
static void force_off_check()
{
if( 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();
SLP_ACK = 0;
#endif
}
/********************************************//**
自己アップデート firm_update() を呼ぶisr中から実行できないので
task_status_immed型 を返すようにすればいいのですが...
***********************************************/
task_status_immed tski_firm_update(){
firm_update();
return( ERR_SUCCESS );
}
#ifdef _DBG_CHK_OFF_LEAK_
/********************************************//**
pin設定ミスチェック
***********************************************/
static void leak_check()
{
volatile u8 ports_i[12];
volatile u8 ports_o[12];
// プルアップ切り忘れ?
ports_i[0] = ( PM0 & PU0 & ~P0 );
ports_i[1] = ( PM1 & PU1 & ~P1 );
ports_i[2] = 0;
ports_i[3] = ( PM3 & PU3 & ~P3 );
ports_i[4] = ( PM4 & PU4 & ~P4 );
ports_i[5] = ( PM5 & PU5 & ~P5 );
ports_i[6] = 0;
ports_i[7] = ( PM7 & PU7 & ~P7 );
ports_i[8] = ( PM12 & PU12 & ~P12 );
ports_i[9] = ( PM14 & PU14 & ~P14 );
ports_i[10] = 0;
ports_i[11] = ( PM20 & PU20 & ~P20 );
// H 出力しちゃってるかも
ports_o[0] = ( ~PM0 & P0 );
ports_o[1] = ( ~PM1 & P1 );
ports_o[2] = ( ~PM2 & P2 );
ports_o[3] = ( ~PM3 & P3 & ~POM3 );
ports_o[4] = ( ~PM4 & P4 ); // bit3はchg_enなので1でもよい
ports_o[5] = ( ~PM5 & P5 );
ports_o[6] = ( ~PM6 & P6 );
ports_o[7] = ( ~PM7 & P7 );
ports_o[8] = ( ~PM12 & P12 );
ports_o[9] = ( ~PM14 & P14 );
ports_o[10] = ( ~PM15 & P15 );
ports_o[11] = ( ~PM20 & P20 );
NOP(); // ←ブレーク置くため
}
#endif _DBG_CHK_OFF_LEAK_