From 938ea96c941d86cab9fda4b571a2e7cc5bde488a Mon Sep 17 00:00:00 2001 From: fujita_ryohei Date: Mon, 6 Jul 2009 06:27:40 +0000 Subject: [PATCH] git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@2 013db118-44a6-b54f-8bf7-843cb86687b1 --- trunk/WDT.c | 8 + trunk/accero.c | 133 +++++++++++++ trunk/adc.c | 105 ++++++++++ trunk/i2c_ctr.c | 230 +++++++++++++++++++++ trunk/i2c_mcu.c | 476 ++++++++++++++++++++++++++++++++++++++++++++ trunk/i2c_twl.c | 157 +++++++++++++++ trunk/ini_VECT.c | 98 +++++++++ trunk/led.c | 119 +++++++++++ trunk/loader.c | 357 +++++++++++++++++++++++++++++++++ trunk/magic.c | 12 ++ trunk/main.c | 141 +++++++++++++ trunk/pm.c | 485 +++++++++++++++++++++++++++++++++++++++++++++ trunk/rtc.c | 93 +++++++++ trunk/self_flash.c | 209 +++++++++++++++++++ trunk/tasks.c | 118 +++++++++++ trunk/tasks_sys.c | 244 +++++++++++++++++++++++ trunk/vreg_ctr.c | 215 ++++++++++++++++++++ trunk/vreg_twl.c | 147 ++++++++++++++ 18 files changed, 3347 insertions(+) create mode 100644 trunk/WDT.c create mode 100644 trunk/accero.c create mode 100644 trunk/adc.c create mode 100644 trunk/i2c_ctr.c create mode 100644 trunk/i2c_mcu.c create mode 100644 trunk/i2c_twl.c create mode 100644 trunk/ini_VECT.c create mode 100644 trunk/led.c create mode 100644 trunk/loader.c create mode 100644 trunk/magic.c create mode 100644 trunk/main.c create mode 100644 trunk/pm.c create mode 100644 trunk/rtc.c create mode 100644 trunk/self_flash.c create mode 100644 trunk/tasks.c create mode 100644 trunk/tasks_sys.c create mode 100644 trunk/vreg_ctr.c create mode 100644 trunk/vreg_twl.c diff --git a/trunk/WDT.c b/trunk/WDT.c new file mode 100644 index 0000000..25f16f0 --- /dev/null +++ b/trunk/WDT.c @@ -0,0 +1,8 @@ +#pragma sfr + +#include "incs_loader.h" + +void WDT_Restart( void ){ + WDTE = 0xAC; // restart watch dog timer +} + diff --git a/trunk/accero.c b/trunk/accero.c new file mode 100644 index 0000000..d77b1d9 --- /dev/null +++ b/trunk/accero.c @@ -0,0 +1,133 @@ +/***************************************************************************** + 加速度センサ関係 +・データ更新完了でデータを吸い上げ手レジスタを更新、CPUに割り込み +・フラグが立っていれば歩数カウント +・加速度センサ割り込みからタスクを登録して下さい。(I2Cの競合回避などがあるので) + + *****************************************************************************/ +#pragma SFR +#pragma NOP +#pragma HALT +#pragma STOP + +#include "incs.h" + + +// レジスタ名 +#define ACC_REG_WHOAMI 0x0F +#define ACC_REG_CTRL1 0x20 +#define ACC_REG_CTRL5 0x24 +#define ACC_REG_X 0x28 + +// ビット位置 +#define ACC_bP_PM0 5 +#define ACC_bP_DR0 3 + +// ビット設定値 +#define ACC_BITS_PM_PDN 0 +#define ACC_BITS_PM_NORM 1 +#define ACC_BITS_PM_LP0R5 2 +#define ACC_BITS_PM_LP1 3 +#define ACC_BITS_PM_LP2 4 +#define ACC_BITS_PM_LP5 5 +#define ACC_BITS_PM_LP10 6 + +#define ACC_BITS_DR_50Hz 0 +#define ACC_BITS_DR_100Hz 1 +#define ACC_BITS_DR_400Hz 2 +#define ACC_BITS_DR_1000Hz 3 + +#define ACC_BITS_ALL_AXIS_ON 7 + + +//************************************* +u8 hosu_mode = 0; +/* + 0: power down 停止 + 1: 動作 +*/ + + +/***************************************************************************** + ・割り込みを確認してデータを吸い上げ、レジスタに書き出します + ・本当であればコールバック関数を登録しておけばいいじゃんとなるのですが、 + I2Cが使用中だったら?とか考えると私ではそこまでできないのです。 + ・自動歩数計とかでも結局 + *****************************************************************************/ +task_status_immed tsk_cbk_accero(){ + static u8 sequence; + u8* dest_adrs; + + if( system_status.pwr_state == ON ){ + + // if( 自動歩数計? ) + // todo + sequence += 1; + vreg_ctr[VREG_C_ACC_0SEQ + 7 * ( sequence & 0x03 )] = sequence; + dest_adrs = &vreg_ctr[VREG_C_ACC_0XH] + 7 * ( sequence & 0x03 ); + iic_mcu_read( IIC_SLA_ACCEL, ( ACC_REG_X | 0x80 ), 6, dest_adrs ); + +#if 0 + switch( system_status.pwr_state ){ + case OFF: + case ON_TRIG: + case ON: + case SLEEP_TRIG: + case SLEEP: + case OFF_TRIG: + default: + break; + } +#endif + } + return( ERR_SUCCESS ); +} + + + +/***************************************************************************** + 自動歩数カウントモードにセット + todo 他のモードだったら止めたり、復帰させたり + 割り込みルーチンなどでカウント判定が必要 + *****************************************************************************/ +err accero_hosu_start(){ + u8 temp; + u8 err; + u8 str_send_buf[4]; + + + if( system_status.pwr_state == ON ){ + err = iic_mcu_read( IIC_SLA_ACCEL, ACC_REG_WHOAMI, 1, &temp ); + if( err == ERR_NAK ){ + vreg_ctr[ VREG_C_ACC_STATUS ] |= 0x80; + return( ERR_ERR ); + } + + str_send_buf[0] = ( ACC_BITS_PM_NORM << ACC_bP_PM0 | ACC_BITS_DR_100Hz << ACC_bP_DR0 | ACC_BITS_ALL_AXIS_ON ); // cont1 + str_send_buf[1] = 0x00; // 泣ける... + str_send_buf[2] = 0x02; + str_send_buf[3] = 0x80; + err = iic_mcu_write( IIC_SLA_ACCEL, ( ACC_REG_CTRL1 | 0x80 ), 4, str_send_buf ); + +// str_send_buf[0] = 0x00; +// err |= iic_mcu_write( IIC_SLA_ACCEL, ACC_REG_CTRL5, 1, str_send_buf ); + + return( err ); +} + } + + + + + +err accero_hosu_stop(){ + u8 err; + u8 str_send_buf[4]; + + str_send_buf[0] = ( ACC_BITS_PM_PDN << ACC_bP_PM0 | 0 << ACC_bP_DR0 | ACC_BITS_ALL_AXIS_ON ); + str_send_buf[1] = 0x00; // 泣ける... + str_send_buf[2] = 0x02; + str_send_buf[3] = 0x80; + err = iic_mcu_write( IIC_SLA_ACCEL, ( ACC_REG_CTRL1 | 0x80 ) , 4, str_send_buf ); + return( err ); +} diff --git a/trunk/adc.c b/trunk/adc.c new file mode 100644 index 0000000..ec822cd --- /dev/null +++ b/trunk/adc.c @@ -0,0 +1,105 @@ + /****************************************************************************** + 対PMIC_TWL2 I2C通信 + de JHL 藤田@開技 + nintendo + '09 Apr + +*******************************************************************************/ +#include "incs_loader.h" +#include "adc.h" +#include "pm.h" + + +/****************************************************************************** + ADC設定と、開始 + + 以下のピンは主にここで操作・監視されます。 + ・BT_TEMP,_P + ・ADIN1 + ・VOL + + 関係ありそうですが別のところで管理しています + ・PM_BT_DET,_P PM_init + + +******************************************************************************/ +task_status tsk_adc(){ + if(( system_status.pwr_state == ON ) + || ( system_status.pwr_state == SLEEP )){ + ADCEN = 1; + ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから + + ADPC = 0x07; // ADCポートのセレクト + ADS = ADC_SEL_3D; + ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける + + ADIF = 0; + ADMK = 0; + + return( 8 ); + } +} + + + + +/****************************************************************************** + 自前で次のチャンネル +  一通り終わったら止める +*******************************************************************************/ +__interrupt void int_adc(){ + switch( ADS ){ + case( ADC_SEL_3D ): + vreg_ctr[ VREG_C_3D_DEPTH ] = ADCRH; + break; + + case( ADC_SEL_VOL ): + vreg_ctr[ VREG_C_VOL ] = ADCRH; + // todo: テーブル引きなど + break; + + case( ADC_SEL_BATT_TEMP ): + raw_adc_temperature = ADCR; + break; + + case( ADC_SEL_BATT_DET ): +// vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH; + break; + } + + +// if( ADS == ADC_SEL_BATT_DET ){ +// もっとまともな書き方がありそうだ + if( ADS == ADC_SEL_BATT_TEMP ){ // 電池判別は電源投入の一回で良いよね + ADCEN = 0; // いっそのこと、止めてしまう + }else{ + ADS += 1; // 次のチャンネル + } +} + + + +/****************************************************************************** + tsk_adcと競合することを考慮していません。 +*******************************************************************************/ +u16 get_adc( u8 ch ){ + u16 temp; + + ADMK = 1; + ADIF = 0; + + ADCEN = 1; + ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから + + ADPC = 0x07; // ADCポートのセレクト + ADS = ch; + ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける + + ADMK = 0; + while( ADIF == 0 ){;} + temp = ADCR; + ADCEN = 0; + + return( temp ); +} + diff --git a/trunk/i2c_ctr.c b/trunk/i2c_ctr.c new file mode 100644 index 0000000..9cd648c --- /dev/null +++ b/trunk/i2c_ctr.c @@ -0,0 +1,230 @@ +/****************************************************************************** + 対SoC 新規チャンネル I2C通信 + de JHL 藤田@開技.nintendo + '09 Apr + *******************************************************************************/ +#include "incs_loader.h" + +u8 vreg_adrs; +u8 pre_dat; + +u16 tot; + + + + +/***************************************************************************** + *****************************************************************************/ +enum{ + IIC_IDLE = 0, + IIC_RCV_REG_ADRS, + IIC_TX_OR_RX, + IIC_TX, + IIC_RX +}; + + +#if 0 +// 1バイト送受の度に割り込みが発生するバージョン +__interrupt void int_iica(){ + static u8 state = 0; + static u8 reg_adrs; + static u8 reg_adrs_internal; + static u8 temp; + + + if( SPD ){ + state = IIC_IDLE; + SPIE = 0; + return; + } + if( ACKD == 0 ){ + LREL = 1; + state = IIC_IDLE; + return; + } + + DBG_P_n = 1; + + switch( state ){ + case( IIC_IDLE ): + // 自局呼び出しに応答。 + // 初期化など + WREL = 1; // ウェイト解除 + SPIE = 1; + state = IIC_RCV_REG_ADRS; + break; + + case( IIC_RCV_REG_ADRS ): + // レジスタアドレス受信 + reg_adrs = IICA & 0x1F; + WREL = 1; + reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs ); + temp = vreg_ctr_read( reg_adrs_internal ); +// temp = vreg_ctr[ reg_adrs ]; + state = IIC_TX_OR_RX; + break; + + case( IIC_TX_OR_RX ): + if( STD ){ + // リードされる + if( !COI ){ + // リスタートで違うデバイスが呼ばれた! + WREL = 1; // ウェイト解除? + state = IIC_IDLE; // 終了処理 + SPIE = 0; + }else{ + state = IIC_TX; + } + }else{ + state = IIC_RX; + } + + // no break; + default: + if( state == IIC_TX ){ + IICA = temp; + }else{ + temp = IICA; + WREL = 1; + vreg_ctr_write( reg_adrs_internal, temp ); +// vreg_ctr[ reg_adrs ] = temp; + } + reg_adrs = ( reg_adrs + 1 ) & 0x1F; + reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs ); + if( state == IIC_TX ){ + temp = vreg_ctr_read( reg_adrs_internal ); +// temp = vreg_ctr[ reg_adrs ]; + } + break; + } + DBG_P_n = 0; + +} + +#endif + +//#if 0 +//一度通信が始まったら終わるまで戻らないバージョン +__interrupt void int_iica(){ + static u8 state = 0; + static u8 reg_adrs; + static u8 reg_adrs_internal; + static u8 trx_buf; + + + DBG_P_n = 1; + + // 自局呼び出しに応答。 + // 初期化など + WREL = 1; // ウェイト解除 + + DBG_P_n = 0; + while( !IICAIF ){;} + IICAIF = 0; + DBG_P_n = 1; + + // レジスタアドレス受信 + reg_adrs = IICA; + WREL = 1; + trx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく + + DBG_P_n = 0; + while( !IICAIF ){;} + IICAIF = 0; + + if( STD ){ // リスタートコンディション + // リードされる + if( !COI ){ + // リスタートで違うデバイスが呼ばれた! + WREL = 1; // ウェイト解除? + state = IIC_IDLE; // 終了処理 + SPIE = 0; + return; + }else{ + state = IIC_TX; + } + }else{ // ライト続行 + state = IIC_RX; + } + + DBG_P_n = 0; + + if( state == IIC_TX ){ // 送信 // + do{ + DBG_P_n = 1; + IICA = trx_buf; + reg_adrs += 1; + trx_buf = vreg_ctr_read( reg_adrs ); + DBG_P_n = 0; + while( !IICAIF ){;} + IICAIF = 0; + }while( ACKD ); + LREL = 1; + + }else{ // 受信 // + SPIE = 1; + do{ + DBG_P_n = 1; + trx_buf = IICA; + WREL = 1; + vreg_ctr_write( reg_adrs, trx_buf ); + reg_adrs += 1; + DBG_P_n = 0; + while( !IICAIF ){;} + IICAIF = 0; + }while( !SPD ); + SPIE = 0; + } + vreg_c_iic_release(); + state = IIC_IDLE; +} +//#endif + +/***************************************************************************** + 基本API + *****************************************************************************/ +void IICA_Init( void ){ + + IICAEN = 1; + + IICE = 0; /* IICA disable */ + + IICAMK = 1; /* INTIICA disable */ + IICAIF = 0; /* clear INTIICA interrupt flag */ + + IICAPR0 = 0; /* set INTIICA high priority */ + IICAPR1 = 0; /* set INTIICA high priority */ + + P6 &= ~0x3; + + SVA = IIC_C_SLAVEADDRESS; + IICF = 0x01; + + STCEN = 1; // リスタートの許可 + IICRSV = 1; // 通信予約をさせない:スレーブに徹する + + SPIE = 0; // ストップコンディションでの割り込みを禁止 + WTIM = 1; // 自動でACKを返した後clkをLに固定する + ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない + + IICWL = 6; // L期間の長さ(?) + IICWH = 5; + + IICAMK = 0; // 割り込みを許可 + + IICE = 1; + PM6 &= ~0x3; /* set clock pin for IICA */ +} + + +//**************************************************************************** +void IICA_Stop( void ){ + IICE = 0; /* IICA disable */ + IICAEN = 0; +} + + + + + diff --git a/trunk/i2c_mcu.c b/trunk/i2c_mcu.c new file mode 100644 index 0000000..17c5911 --- /dev/null +++ b/trunk/i2c_mcu.c @@ -0,0 +1,476 @@ +/****************************************************************************** + 簡易I2C(内蔵ペリフェラル使用)通信 + de JHL 藤田@開技 + '09 Feb - +*******************************************************************************/ +#pragma sfr +#pragma di +#pragma ei +#pragma nop +#pragma inline // memcpy()をインライン展開する + +#include "incs_loader.h" +#include "i2c_mcu.h" +//#include + + +bit iic_mcu_wo_dma; +volatile bit iic_mcu_busy; +volatile bit iic_mcu_initialized; + + +// SSR0n +#define bit_TSF0 6 +// SIR0n +#define PECT0 ( 1 << 1 ) +// SSR0n +#define PEF0 ( 1 << 1 ) + +#define TXE0 ( 1 << 15 ) +#define RXE0 ( 1 << 14 ) +#define SLC02 4 +#define DLS02 0 +#define TSF0 ( 1 << 6 ) + +#define DRS ( 1 << 6 ) + +#define TAUS_MASK 0b0000101100001011; + +static void iic_mcu_send_st(); +static void iic_mcu_send_re_st(); +static void iic_mcu_send_sp(); +static err iic_mcu_send_a_byte( u8 ); +static err iic_mcu_call_slave( u8 slave ); + +u8 iic_send_work[4]; +u8* p_iic_send_wo_dma_dat; +u8 iic_send_wo_dma_len; + +volatile u8 interrupted; + + +u8 dma_state; + + +/***** + スレーブからの 『1文字』 リード + 返値がデータそのものです。 + エラー判定ができません。 + ******************************************************************************/ +u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ){ + u8 dat; + + iic_mcu_read( SLA, adrs, 1, &dat ); + return( dat ); +} + + +/****************************************************************************** + スレーブからのリード + 0 正常終了 + 1 スレーブが応答しない + 2 バスが誰かに占有されていてタイムアウト + 3 意味不明エラー + 【注】 + スレーブがウェイトコンディションを出すことは禁止です。 + その場合でもエラー検出などできません + ******************************************************************************/ +err iic_mcu_read( u8 slave, u8 adrs, u8 len, u8* dest ){ + +//* + // 使用中なら待つ + if( iic_mcu_initialized == 0 ){ +#ifdef _debug_ + iic_mcu_start(); +#else + while(1){}; +#endif + } + while( iic_mcu_busy ){ + DBG_M_n = 1; + NOP(); + } + DBG_M_n = 0; +/*/ + // 使用中なら帰る + if( iic_mcu_initialized == 0 ){ + return(0x80); + } + if( iic_mcu_busy != 0 ){ + return( 3 ); + } +//*/ + + // スタートコンディションとスレーブの呼び出し、レジスタアドレスの送信 + if( iic_mcu_call_slave( slave ) != 0 ){ + return( ERR_NAK ); + } + + // レジスタアドレスの送信 + iic_mcu_send_a_byte( adrs ); // 終わるまで帰ってこない + // if( err != ERR_SUCCESS )〜 + + // データ受信 // + iic_mcu_send_re_st(); // リスタートコンディション + iic_mcu_send_a_byte( slave | 0x01 ); // 送信完了まで戻ってきません。 + + // データ受信 + ST0 = 0x0004; // 受信モードに設定を変えるのでロジック停止 + SCR02 = RXE0 | 1 << SLC02 | 7 << DLS02; // 受信設定 + SS0 = 0x0004; // 通信待機 + + while( len != 0 ){ + if( len == 1 ){ + SOE0 &= ~0x0004; + } + IICIF10 = 0; + SIO10 = 0xFF; // ダミーデータを書くと受信開始 + while( IICIF10 == 0 ){;} + *dest = SIO10; + dest++; + len--; + } + + iic_mcu_send_sp(); + + IICIF10 = 0; + iic_mcu_busy = 0; + + return( ERR_SUCCESS ); +} + + + + +/***** + スレーブへ 『1バイト』 ライト + 前の転送が終わるのを待って、ライトします。 + 返値 iic_mcu_write に同じ + + ■元のデータをそのまま使って、書きっぱなしにするので、 + ポインタをとっておかないと破壊されてしまう…気がする + ******************************************************************************/ +err iic_mcu_write_a_byte( u8 SLA, u8 adrs, u8 dat ){ + volatile static u8 temp; + + while( iic_mcu_busy ){ + DBG_M_n = 1; + NOP(); + } + DBG_M_n = 0; + + temp = dat; + return( iic_mcu_write( SLA, adrs, 1, &temp ) ); +} + + + +u8* p_src_work; // DMA送信バッファ +u8 len_work; + +/****************************************************************************** + スレーブへライト + レジスタ adrs を先頭に、 + *strから + len文字書きます。 + + 0 正常終了 + 1 スレーブが応答しない + 2 バスが誰かに占有されていてタイムアウト + 3 前に指示された通信がまだ終わってない + 【注】 + スレーブがウェイトコンディションを出すことは禁止です。 + その場合でもエラー検出などできません + DMA1を使用します。 + ******************************************************************************/ +err iic_mcu_write( u8 slave, u8 adrs, u8 len, u8* src ){ +//* + // 使用中なら待つ + if( iic_mcu_initialized == 0 ){ +#ifdef _debug_ + iic_mcu_start(); +#else + while(1){}; +#endif + } + while( iic_mcu_busy ){ + DBG_M_n = 1; + NOP(); + } + DBG_M_n = 0; +/*/ + // 使用中なら帰る + if( iic_mcu_initialized == 0 ){ + return(0x80); + } + if( iic_mcu_busy != 0 ){ + return( 3 ); + } +//*/ + + // スタートコンディションとスレーブの呼び出し... + IICMK10 = 1; + if( iic_mcu_call_slave( slave ) != 0 ){ + return( ERR_NAK ); + } + + iic_mcu_busy = 1; + +dma_state = 0; + + + if( !iic_mcu_wo_dma ){ + // DMAを使用する(通常) + + // レジスタアドレスの送信 + memcpy( iic_send_work, src, 4 ); //バッファとして4バイトしか用意して無いため。 + // DMAセット + while( DST1 ){;}; + + DEN1 = 1; + DSA1 = (u8)( &SIO10 ); + DRA1 = (u16)iic_send_work; + DBC1 = len; + DMC1 = DRS | 8; // RAM -> SFR, 8bit, IRQ, IIC10 + + DMAIF1 = 0; + DMAMK1 = 0; + DST1 = 1; + + IICIF10 = 0; + SIO10 = adrs; // 書きっぱなし! 割り込みが発生してDMAスタート + + }else{ + // DMAを使用しない // + + // レジスタアドレスの送信 + IICIF10 = 0; + SIO10 = adrs; + + IICMK10 = 0; + iic_send_wo_dma_len = len; + p_iic_send_wo_dma_dat = src; + // 残りは割り込みルーチン内で + } +dma_state = 1; + return( ERR_SUCCESS ); +} + + + + +/****************************************************************************** + DMA1転送終了割り込み + IIC_mcu の送信完了コールバック関数のようなもの + 注:DMA転送が終わっただけで、I2Cの転送は終わってません + ******************************************************************************/ +__interrupt void int_dma1(){ +dma_state = 2; + DMAMK1 = 1; + DEN1 = 0; + IICMK10 = 0; + // 最後のバイト転送後、I2C割り込みが発生する +} + + + +/** + IIC MCUのバイト送出完了割り込み + ******************************************************************************/ +__interrupt void int_iic10(){ +dma_state = 3; + + if( iic_mcu_wo_dma ){ + // DMA使用せず、転送途中 + if( iic_send_wo_dma_len != 0 ){ + SIO10 = *p_iic_send_wo_dma_dat; + p_iic_send_wo_dma_dat++; + iic_send_wo_dma_len--; + return; + } + } + // 共通(最終バイト送信完了) + IICMK10 = 1; + iic_mcu_send_sp(); + iic_mcu_wo_dma = 0; + iic_mcu_busy = 0; +} + + + +/****************************************************************************** + スレーブの呼び出し + スレーブアドレスを呼んで、ACKの確認。 + ACK →                 返:0 + NACK → ストップコンディションを出す。 返:1 + ******************************************************************************/ +static err iic_mcu_call_slave( u8 slave ){ + // スレーブの呼び出し // + iic_mcu_send_st(); + +// SIR02 = SSR02; // NAKエラーのフラグクリア +#if 0 + if( iic_mcu_send_a_byte( slave ) != 0 ){ + iic_mcu_send_sp(); + return( 1 ); // 指定のスレーブがいない / busy + } +#else + IICIF10 = 0; + SIO10 = slave; + while( IICIF10 == 0 ){ + NOP(); + } // 通信中 + if( SSR02 != 0 ){ + SIR02 = SSR02; + iic_mcu_send_sp(); + return( ERR_NAK ); + } +#endif + return( ERR_SUCCESS ); +} + + + +/** + I2C単機能API + ほんとに1バイト書くだけ。 + 書き終わるまで帰りません + ******************************************************************************/ +static err iic_mcu_send_a_byte( u8 dat ){ + + IICIF10 = 0; + SIO10 = dat; + while( IICIF10 == 0 ){ + NOP(); + } // 通信中 + if( SSR02 != 0 ){ + SIR02 = SSR02; + return( 1 ); // NAK + } + return( 0 ); +} + + + +/** + スタートコンディションを発行 + 自力でぱたぱたしなくてはならない +*******************************************************************************/ +static void iic_mcu_send_st(){ + SO0 &= ~0x0004; // SDA + NOP(); + NOP(); + NOP(); + NOP(); + SO0 &= ~0x0400; // SCL + SOE0 = 0x0004; // ハード制御へ + + SCR02 = TXE0 | 1 << SLC02 | 7 << DLS02; // 送信許可、データは8ビット単位 + SS0 = 0x0004; // 通信待機 +} + + + +/** + リスタート発行 +*******************************************************************************/ +static void iic_mcu_send_re_st(){ + ST0 |= 0x0004; + SO0 |= 0x0400 | TAUS_MASK; // ( SDA = H ), SCL -> H + NOP(); + NOP(); + NOP(); + NOP(); + SOE0 &= ~0x0004; // ( SCL = H ), SDA -> L + NOP(); + NOP(); + NOP(); + NOP(); + iic_mcu_send_st(); +} + + + +/** + ストップコンディション発行 + この前に最後のバイトの送受信の時に前準備が必要です。 +*******************************************************************************/ +static void iic_mcu_send_sp(){ + ST0 |= 0x0004; + SOE0 = 0; // 受信の時はもっと前に「も」設定してる。(NACK出力) + SO0 = 0x0000 | TAUS_MASK; // SCL + NOP(); + NOP(); + NOP(); + NOP(); + SO0 = 0x0400 | TAUS_MASK; // SCL + NOP(); + NOP(); + NOP(); + NOP(); + SO0 = 0x0404 | TAUS_MASK; +} + + + +/** + バスのリセット + (ストップコンディションが出せそうだったらすかさず出す。 + ******************************************************************************/ +void iic2m_bus_reset(){ + u8 count; +/* + for( count = 19; count != 0; count-- ){ + iics_sda_H; + iics_scl_H; + PM1.1 = 1; // SDA + if( iics_sda != 0 ){ + PM1.1 = 0; + iic_mcu_send_sp; + return; + } + PM1.1 = 0; + iics_scl_L; + } + return; + */ +} + + + +/** + * ペリフェラルモジュールの初期化 + *****************************************************************************/ +void iic_mcu_start(){ + I2C_PU = 1; + SAU0EN = 1; + NOP(); // 4clkあける + NOP(); + NOP(); + NOP(); + SPS0 = 0x0000; // シリアルユニットのクロック0。(8M/2)/1 + SMR02 = 0 << 15 | 0 << 14 | 0 << 7 | 0 << 5 | 1 << 4 | 1 << 2; // I2Cとそのクロックなど設定 + SDR02 = 5 << 9; // ボーレート設定 (8M/2)/1/(x+1)/2 + + SO0 = 0x0404 | TAUS_MASK; // 最初はHH + iic_mcu_busy = 0; + iic_mcu_wo_dma = 0; + iic_mcu_initialized = 1; + +} + + + +/** + * モジュールの停止 + * 再度使うときは初期化が必要 + *****************************************************************************/ +void iic_mcu_stop(){ + while( iic_mcu_busy ){;} // DMA動作中はもう少し待つ + iic_mcu_send_re_st(); // SCL,SDAをLLにする + I2C_PU = 0; + SAU0EN = 0; + iic_mcu_initialized = 0; +} + + diff --git a/trunk/i2c_twl.c b/trunk/i2c_twl.c new file mode 100644 index 0000000..4117368 --- /dev/null +++ b/trunk/i2c_twl.c @@ -0,0 +1,157 @@ +#pragma sfr /* 特殊機能レジスタ使用 */ + +#ifndef _TEG_ +// KE3Lの間はプレースホルダ +void IICB_Init( void ){} +void IICB_Stop( void ){} +void IICB_SlaveReceiveStart(){} + + +#else + + +/*============================================================================*/ +#include "incs.h" +#include "i2c_twl_defs.h" + +extern u8 vreg_twl[]; + + +/*============================================================================*/ +u8 vreg_adrs; +u8 pre_dat; + + +u16 tot; +// 注! ↓はマクロなので、returnはメインループに戻ります。 +#define wait_next { \ + tot = 0; \ + while( IICAIF != 1 ){ \ + if( SPD ){ \ + LREL = 1; \ + return; \ + } \ + tot++; \ + if( tot == 0 ){ \ + LREL = 1; \ + return; \ + } \ + } \ +} + + + +__interrupt void int_iicb(){ + WREL = 1; // ウェイト解除して次のバイトを待つ +// WDT_Restart(); + // フラグ1回目 スレーブアドレス,R/W + if( COI != 1 ){ // 被呼び出し? + LREL = 1; // 呼ばれたのは他のID + return; + }else{ +// ACKE0 = 1; // 自動でackを返すようにする +// WREL = 1; // ウェイト解除して次のバイトを待つ + } + + wait_next; // 1バイト受信完了を待つ + + // 2回目 R/W レジスタアドレス + WREL = 1; + IICBIF = 0; + vreg_adrs = adrs_table_twl_ext2int( IICB ); + + // 3回目 + // スタートコンディションか、データ受信完了フラグ待ち + + while( 1 ){ + if( IICBIF == 1 ){ + // 受信 // + IICBIF = 0; + WREL = 1; + + // 通常アクセス(ライト) // + LREL = 1; + vreg_twl_write( vreg_adrs, IICB ); + return; // 受信おしまい // + + }else if( STD ){ + // 送信 // (スタートコンディション検出) + pre_dat = vreg_twl_read( vreg_adrs ); // mcu内部アドレスを渡す。一バイト目の準備 IICBに書き込むとウェイト解除 + + // 自局をRで呼ばれるのを待つ + wait_next; + IICBIF = 0; + if( COI != 1 ){ // 被呼び出し? + LREL = 1; // 呼ばれたのは他のID(あれ?) + return; + } + IICB = pre_dat; // データを送る + + wait_next; + // 4回目。(送信データ後の、ACK/NACK後) どうしても発生してしまう。 + IICBIF = 0; // おしまい + LREL = 1; + return; + }else if( SPD ){ // 強制終了 + LREL = 1; + return; + } + } +} + + + +/***************************************************************************** + 基本API + *****************************************************************************/ +void IICB_Init( void ) +{ + + IICBEN = 1; + + IICE = 0; /* IICB disable */ + + IICBMK = 1; /* INTIICB disable */ + IICBIF = 0; /* clear INTIICB interrupt flag */ + + IICBPR0 = 0; /* set INTIICB high priority */ + IICBPR1 = 0; /* set INTIICB high priority */ + + PM6 &= ~0x3; /* set clock pin for IICB */ + P6 &= ~0x3; + + SVA = IIC_T_SLAVEADDRESS; + IICF = 0x01; + + STCEN = 1; // リスタートの許可 + IICRSV = 1; // 通信予約をさせない:スレーブに徹する + + SPIE = 0; // ストップコンディションでの割り込みを禁止 + WTIM = 1; // 自動でACKを返した後clkをLに固定する + ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない + IICBMK = 0; // 割り込みを許可 + + IICE = 1; +// spie のセット + // 使用時に再初期化 + // IICE0を1にしていいのはscl,sdaがHHの時だけ + +} + + +//**************************************************************************** +void IICB_Stop( void ){ + IICE = 0; /* IICB disable */ +} + + + +void IICB_SlaveReceiveStart(){ + IICE = 1; + LREL = 1; + return; +} + + + +#endif diff --git a/trunk/ini_VECT.c b/trunk/ini_VECT.c new file mode 100644 index 0000000..10e1c2e --- /dev/null +++ b/trunk/ini_VECT.c @@ -0,0 +1,98 @@ +#include "config.h" + +//#pragma interrupt INTWDTI fn_intwdti // 未使用 +//#pragma interrupt INTLVI fn_intlvi // 未使用 + +#pragma interrupt INTP0 intp0 // SLP +//#pragma interrupt INTP1 fn_intp1 // (I2C) +//#pragma interrupt INTP2 fn_intp2 // (I2C) +//#pragma interrupt INTP3 fn_intp3 // 未搭載 +#pragma interrupt INTP4 intp4 // EXTDC +#pragma interrupt INTP5 intp5 // SHELL_CLOSE + +//#pragma interrupt INTCMP0 fn_intcmp0 +//#pragma interrupt INTCMP1 fn_intcmp1 +//#pragma interrupt INTDMA0 fn_intdma0 +#pragma interrupt INTDMA1 int_dma1 + +//#pragma interrupt INTST0 fn_intst0 +/* #pragma interrupt INTCSI00 fn_intcsi00 */ +//#pragma interrupt INTSR0 fn_intsr0 +/* #pragma interrupt INTCSI01 fn_intcsi01 */ +//#pragma interrupt INTSRE0 fn_intsre0 + +//#pragma interrupt INTST1 fn_intst1 +/* #pragma interrupt INTCSI10 fn_intcsi10 */ +#pragma interrupt INTIIC10 int_iic10 +//#pragma interrupt INTSR1 fn_intsr1 +//#pragma interrupt INTSRE1 fn_intsre1 + +#pragma interrupt INTIICA int_iica // CTR側 +#ifndef _TEG_ +#pragma interrupt INTIICB int_iicb // TWL側 +#endif +//#pragma interrupt INTTM00 fn_inttm00 +//#pragma interrupt INTTM01 fn_inttm01 +//#pragma interrupt INTTM02 fn_inttm02 +//#pragma interrupt INTTM03 fn_inttm03 + +#pragma interrupt INTAD int_adc +//#pragma interrupt INTRTC int_rtc +#pragma interrupt INTRTCI int_rtc_int +#pragma interrupt INTKR int_kr +//#pragma interrupt INTMD fn_intmd + +//#pragma interrupt INTTM04 fn_inttm04 +//#pragma interrupt INTTM05 fn_inttm05 +//#pragma interrupt INTTM06 fn_inttm06 +//#pragma interrupt INTTM07 fn_inttm07 +#pragma interrupt INTP6 fn_intp6 +#pragma interrupt INTP7 fn_intp7 + +/****************************************************/ +/* 未使用時のダミー関数定義 */ +/****************************************************/ +__interrupt void fn_intwdti(){ while(1){}; } +__interrupt void fn_intlvi(){ while(1){}; } +//__interrupt void fn_intp0(){} +__interrupt void fn_intp1(){ while(1){}; } // +__interrupt void fn_intp2(){ while(1){}; } +__interrupt void fn_intp3(){ while(1){}; } +__interrupt void fn_intp4(){ while(1){}; } +__interrupt void fn_intp5(){ while(1){}; } + +__interrupt void fn_intcmp0(){ while(1){}; } +__interrupt void fn_intcmp1(){ while(1){}; } +__interrupt void fn_intdma0(){ while(1){}; } +//__interrupt void fn_intdma1(){} // i2c_mcu.cにある + +__interrupt void fn_intst0(){ while(1){}; } +/* __interrupt void fn_intcsi00(){} */ +__interrupt void fn_intsr0(){ while(1){}; } +/* __interrupt void fn_intcsi01(){} */ +__interrupt void fn_intsre0(){ while(1){}; } + +__interrupt void fn_intst1(){ while(1){}; } +/* __interrupt void fn_intcsi10(){} */ +//__interrupt void fn_intiic10(){ while(1){}; } +__interrupt void fn_intsr1(){ while(1){}; } +__interrupt void fn_intsre1(){ while(1){}; } + +//__interrupt void fn_intiica(){} // i2c.cにある +/* __interrupt void fn_inttm00(){} */ /* sub.cにて定義 */ +__interrupt void fn_inttm01(){ while(1){}; } +__interrupt void fn_inttm02(){ while(1){}; } +__interrupt void fn_inttm03(){ while(1){}; } + +//__interrupt void fn_intad(){ while(1){}; } // adc.c +__interrupt void fn_intrtc(){ while(1){}; } +//__interrupt void int_rtcint(){} // rtc.cにある +//__interrupt void fn_intkr(){} // main.c +__interrupt void fn_intmd(){ while(1){}; } + +__interrupt void fn_inttm04(){ while(1){}; } +__interrupt void fn_inttm05(){ while(1){}; } +__interrupt void fn_inttm06(){ while(1){}; } +__interrupt void fn_inttm07(){ while(1){}; } +__interrupt void fn_intp6(){ while(1){}; } +__interrupt void fn_intp7(){ while(1){}; } diff --git a/trunk/led.c b/trunk/led.c new file mode 100644 index 0000000..c9c12ac --- /dev/null +++ b/trunk/led.c @@ -0,0 +1,119 @@ +#pragma sfr + + +#include "incs.h" +#include "led.h" + + +// TPS0 +#define BIT_PRS01 4 +#define BIT_PRS00 0 + +// TMR0 +#define BIT_CKS0 15 +#define BIT_CCS0 12 +#define BIT_MASTER0 11 +#define BIT_STS0 8 +#define BIT_CIS0 6 +#define BIT_MD123 1 +#define BIT_MD0 0 + + + + + +void LED_init(){ +/** + PWMのセット、とりあえず全部消灯 + + マスタチャネル:0 (P01:/reset2) マスターは偶数チャネルしかできない + スレーブ    1 SLTO。(3D LED いるのかい?) +         2 カメラ +         3 WiFi +         4 (ピンはRTC32kHz out に使用) +         5 充電 +         6 電源 L +         7 電源 H + + + */ + TAU0EN = 1; + TPS0 = 1 << BIT_PRS01 | 1 << BIT_PRS00; // マスタークロックはCK01,8M/2/2^4 = 250kHz + + TMR00 = 1 << BIT_CKS0 | 0 << BIT_CCS0 | 1 << BIT_MASTER0 | 0 << BIT_STS0 | 0 << BIT_CIS0 | 0 << BIT_MD123 | 1 << BIT_MD0; + TMR01 = TMR02 = TMR03 = TMR04 = TMR05 = TMR06 = TMR07 \ + = 1 << BIT_CKS0 | 0 << BIT_CCS0 | 0 << BIT_MASTER0 | 4 << BIT_STS0 | 0 << BIT_CIS0 | 4 << BIT_MD123 | 1 << BIT_MD0; + ISC = 0; + TOM0 = 0b0000000011111110; // 出力モード。4はPWM出力しないが1にしないとTO5以降にクロックが届かない + TOL0 = 0; + TO0 = 0; // タイマー動作中で、タイマー出力にしてないときのピンのラッチ。タイマー出力を使わないなら0 + TOE0 = 0b0000000011101110; // TOxをタイマーモジュールが制御? + TS0 = 0b0000000011101111; // 動作開始 + + TDR00 = 0x03FE; // 10bit, 周期 +} + + + +void LED_stop(){ + TT0 = 0b0000000011101111; // 一斉停止(しないとだめ) + TOE0 = 0b0000000000000000; // TOxをタイマーモジュールが制御?(GPIOになる) + TAU0EN = 0; +} + + + + +/******************************************************************************* + LED + LED_Cam TO02 + LED_Charge 5 + LED_POW_B,R 6,7 + LED_Wifi,2 3, P24 + LED_3D 4 + + 基本的にそれぞれの関係するタスクが管理するが、余ってしまったのはここで管理 + + TDR00 周期(0x03FF。TPS0で250kHzでカウントアップ。10bitなら250Hz位になる) + TDR0x Duty 0で消灯、TDR00(より大 =0x03FF以上)で点灯です。 + *******************************************************************************/ +task_status tsk_led(){ + switch( system_status.pwr_state ){ + case OFF: + break; + + case ON_TRIG: + LED_duty_pow_H = 0x01FF; + LED_duty_pow_L = 0x0100; + LED_duty_WiFi = 0x03FF; + LED_duty_CAM = 0x0040; + LED_duty_3D = 0x0001; + break; + + case ON: + LED_duty_WiFi = vreg_ctr[ VREG_C_3D_DEPTH ]; + LED_duty_CAM = vreg_ctr[ VREG_C_VOL ]; + LED_duty_3D = vreg_ctr[ VREG_C_BT_TEMP ]; + break; + + case SLEEP_TRIG: + LED_duty_pow_H = 0x0010; + LED_duty_pow_L = 0x0400; + LED_duty_WiFi = 0x0020; + LED_duty_CAM = 0x0080; + LED_duty_3D = 0x0100; + break; + + case SLEEP: + break; + + case OFF_TRIG: + LED_duty_pow_L = 0x03FE; + break; + + default: + break; + } + + return( 10 ); +} diff --git a/trunk/loader.c b/trunk/loader.c new file mode 100644 index 0000000..058e104 --- /dev/null +++ b/trunk/loader.c @@ -0,0 +1,357 @@ +/*============================================================================ + MCU CTR BSR + 2009/03/30 + 開発技術部 藤田 + + ブートローダー部 + ホストの通信と、自己書き換え、ファームのチェックを行う。 + + ============================================================================*/ +#pragma SFR +#pragma di +#pragma ei +#pragma nop +#pragma stop +#pragma halt + +#include "incs_loader.h" + +#include "fsl.h" +#include "fsl_user.h" + +#include "i2c_ctr.h" +#include "i2c_mcu.h" +#include "pm.h" +#include "rtc.h" + +/*============================================================================*/ +#define VER_HEADER 0x2100 +#define VER_FOOTER 0x7000 + + + +/*============================================================================*/ +#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 FSL_Open(void); +void FSL_Close(void); +void hdwinit(void); +static void emergency_boot(); +void power_save(); + +extern void main_loop(); + + +/*============================================================================*/ +void main(){ + while(1){ + // 電池投入 // + // hdwinit(); 自動実行 + + // 電池投入時のみ初期化 + /// ファーム更新に最低限必要な物 + // + + u8 temp; + + FSL_GetActiveBootCluster( &temp ); + + // ファームの整合性チェック + // とは言っても、領域の先頭と最後のマジックナンバーを見るだけ + { + u8 i; + u8 comp = 0; + for( i = 0; i < sizeof( __TIME__ ); i++ ){ + comp |= ( *((u8*)( VER_HEADER + i )) ^ *((u8*)( VER_FOOTER + i )) ); + } + if( comp != 0 ){ + while(1){ + emergency_boot(); + + P1.4 = 0; + IICA_Stop(); + iic_mcu_stop(); + BT_TEMP_P = 0; + + KRM = KR_SW_POW; + EGP0 = 0b00000000; // 0で検出しない + EGN0 = 0b00000000; // SHELL, EXTDC + // intp20系は後ほど + MK0 = 0b1111111111111111; // SHELL, EXTDC + MK1 = 0b1111011111111111; // KR + // MK1 = 0b1111010111111111; // KR, RTC(Alarm) + MK2L= 0b11111111; + + // pullup_off(); + { + PU5 = 0b00000000; + PU7 = 0b00010000; + } + + STOP(); + } + } + } + + // 通常運転 + main_loop(); + } +} + + + +/****************************************************************************** + ファームが壊れた場合、 + (必要なら)勝手に電源投入を試みて、ファーム異常割り込みを掛けます。 + 電池切れ等だったら、電源ボタンが押されるのを待つ + メインループを回せないのです。 + ******************************************************************************/ +void emergency_boot(){ + // 電源を入れる + iic_mcu_start(); + PM_init(); + // PM_bt_auth(ほげ) + + if( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_SYS ) != 0 ){ + if( PM_sys_pow_on() != ERR_SUCCESS ){ // 電源起動不可エラー + return; + } + } + //* + if( PM_LCD_on() == 0 ){ + return; + } + //*/ + // LEDの強制点灯 + P1.4 = 1; + + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DIR, 0x00 ); + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x80 ); + + RTC_32k_on(); + + vreg_ctr[ VREG_C_MCU_STATUS ] |= REG_BIT_MCU_FIRMBROKEN; + vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_IRQ0_MCUSTATUS; + + IICA_Init(); + IRQ_0_ast; // レジスタリードのところで ngtする + + while(1){ // ファームが送られてくるのを待つ + u16 pwsw_count = 0; + + if( renge_flg_interval ){ + renge_flg_interval = 0; + if( !SW_POW_n ){ // 電源長押しされたら強制電源OFF + pwsw_count += 1; + if( pwsw_count > 400 ){ + return; + } + }else{ + pwsw_count = 0; + } + } + HALT(); + } + +} + + + +void power_save(){ + if( !renge_task_interval_run_force ){ + HALT(); + } +} + + + + +/****************************************************************************** + キーリターン割り込み + 一度にいくつものビットを使わないつもりなんだが + ******************************************************************************/ +__interrupt void int_kr(){ + if( system_status.pwr_state == OFF ){ + // 電源onのカウント。特にすることはない + } +} + + + + +/****************************************************************************** + ext dc + ******************************************************************************/ +__interrupt void intp4(){ +} + + +/****************************************************************************** + shell close + ******************************************************************************/ +__interrupt void intp5(){ +} + + + + + +/*============================================================================*/ +void hdwinit(void){ // スタートアップルーチンが勝手に呼びます + DI(); /* マスタ割り込み禁止 */ + + CMC = 0b00010110; /* X1発振せず(入力ポート)、XT1使用、推奨の推奨で超低電力発振 */ + CSC = 0b10000000; /* X1発振なし、XT1発振あり、高速内蔵発振動作 */ + // OSMC = 0x00; /* フラッシュ・メモリの高速動作用昇圧回路 */ + CKC = 0b00001001; /* CPU/周辺クロック=fMAIN、fMAIN=fMX、fCLK=fMX */ + + /*--- 低電圧検出回路の設定 ---*/ + /* リセット解除時のデフォルトは、オプション・バイトにて指定される */ + LVIS = 0b00000000; /* VLVI = 4.22±0.1V */ + LVIM = 0b00000000; /* LVI動作禁止 */ + /* 電源電圧(VDD)<検出電圧(VLVI)時に割込発生 */ + /* 電源電圧(VDD)≧検出電圧1) BL用PWMはスリープに入る時にはOffにしておかないとまずいですよね? +> 結局順序の保証がいるので、MCUに「PMIC I2C Busy」フラグが欲しいのです +> が、いかがでしょうか?>藤田君 +> 仕様として、SoCからのPMICへの処理依頼の書き込み終了直後に 1 である +> ことが保証され、PMICへの全通信完了後に 0 になるというものです。 +> LCD Off時は50msec待っている間もずっと 1 の方がうれしい気がします。 +> 無理なら、「BL Setting Busy」フラグでも良いですが。 +> +>2) 前、齋藤君がLCD Offの期間 100 msec 保証は SoCの起動に 100 msec かかる +> から心配ないようなことを書いていましたが、実際には、LCD Offシーケンス +> に 50 msec かかるので、LCD Offシーケンス開始からだと合計 150 msec 必 +> 要です。SoCからMCUにLCD Off指示、直後にスリープ、直後にスリープ復帰、 +> 直後にLCD Onとした場合に、十分なOff期間があるかちゃんと計算しておいて +> ください。>これも藤田君? +> +> よく考えたら、スリープに入らずに Off → On する場合も考えておかないと +> いけないので、MCUに「LCD On許可」フラグも用意してもらうべきかも。 + > +> (NITROのスリープで苦労した時間計測もMCUがあれば楽々解決ですね!) + + +■・電源OFFシーケンス中にモデルゲージ(加速度センサ)への通信は止めてください。 +>電源が遅く切り替わると内部回路の最低動作電圧で内部の制御回路が不安定になるの +>でバスをLOWに引っ張ることはないことを保証できないため + + + *****************************************************************************/ +/* +管理担当がついてない + pm_irq + snd_depop + /fcram_reset + /mcu_irq + /reset1 + /reset2 + slp + /wl_reset + wl_rx + wl_tx + extopt_det + accel_valid + accel_int + dbg + shell_close,_p + + + +*/ +//***************************************************************************** +#include "incs.h" + +#include "WDT.h" +#include "rtc.h" +#include "pm.h" +#include "accero.h" + + + +//***************************************************************************** +err to_sleep(); + +static void read_dipsw(); + +unsigned char temp_teg; +extern void power_save(); + + +//***************************************************************************** +bit active; +bit sleep; + +bit rsv_to_sleep; +bit rsv_LCD_on; +bit rsv_BL_on; + + +system_status_ system_status; + + +u8 off_delay; // 電源 OFF から PWSW 等で電源オンする際、押してる時間をカウントするのに使う + + +/****************************************************************************** + 本当のエントリ関数は loader.c にあります + *****************************************************************************/ +void main_loop( void ){ + + // 電池投入時の1回のみ + vreg_ctr_init(); + RTC_init(); // 電池初投入ビットも立てます + PM_reset(); + vreg_twl_init(); + + read_dipsw(); + // 特定スイッチで何かするか? + + + renge_init(); + system_status.pwr_state = OFF_TRIG; + renge_task_interval_run_force = 1; + + EI(); + // メインループ // + while(1){ // システムtick、または割り込みで廻ります。 + WDT_Restart(); + DBG_P_n = 1; + renge_task_interval_run(); // 内部で、システムtickまたは強制起動します + DBG_P_n = 0; + DBG_P_n = 1; + renge_task_immed_run(); // ここのループが廻る度に実行されます + DBG_P_n = 0; + power_save(); + } +} + + + + +static void read_dipsw(){ + // ソフトディップスイッチ読み込み + PU4 |= 0x03; // dip sw 0,1 + system_status.dipsw0 = ( DIPSW_0 == 0 )? 0: 1; + system_status.dipsw1 = ( DIPSW_1 == 0 )? 0: 1; + PU4 &= ~0x03; +} + + + + diff --git a/trunk/pm.c b/trunk/pm.c new file mode 100644 index 0000000..d47d97c --- /dev/null +++ b/trunk/pm.c @@ -0,0 +1,485 @@ + /****************************************************************************** + 対PMIC_TWL2 I2C通信 + de JHL 藤田@開技 + nintendo + '08 Dec + +*******************************************************************************/ +#pragma nop + +#include "incs_loader.h" +#include "i2c_mcu.h" +#include "adc.h" +#include "led.h" +#include "pm.h" + + +#define BT_GAUGE_UNLOCK_ADRS 0x3E +#define BT_BT_PARAM_ADRS 0x40 +#define BT_BT_PARAM_PANA_RCOMP_ADRS 0x0C +// -1.45 ,-3.9} + +static const u8 BT_BT_PARAM_PANA[64] = { + 0xEA, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; + +static const u8 BT_BT_PARAM_PANA_RCOMP_AND_PARAM[3] = { 158, 1, 4 }; // RCOMP, TempCoUp, ---Down; + + +u16 raw_adc_temperature; + + +#define _TEG_ + +/***************************************************************************** + バッテリの認証を行います。 + 引数 無し + 返値 (ERR)ERR_SUCCESS 成功 + それ以外 失敗 + *****************************************************************************/ +err PM_bt_auth(){ + /* + todo + マキシムなら Dallas-1wire 通信 + SHA-1計算 + */ + return( ERR_SUCCESS ); +} + + + +/***************************************************************************** + バッテリ固有のパラメータをセット + ・64バイトのパラメータを直接ROM領域においておきたかったのだが、 +  なんと、DMAがROMRAM領域からしか持ってこられないので +  ランタイムルーチンにスタックにコピーしてもらう orz + ・スタックが不安なので、ベンダの数だけ関数を作る + 引数 無し + 返値 無し + *****************************************************************************/ +static void BT_set_batt_vend1(){ + + iic_mcu_write( IIC_SLA_BT_GAUGE, + BT_BT_PARAM_PANA_RCOMP_ADRS, + sizeof( BT_BT_PARAM_PANA_RCOMP_AND_PARAM ), + BT_BT_PARAM_PANA_RCOMP_AND_PARAM + ); + + iic_mcu_set_wo_dma(); + iic_mcu_write( IIC_SLA_BT_GAUGE, + BT_BT_PARAM_ADRS, + sizeof( BT_BT_PARAM_PANA ), + BT_BT_PARAM_PANA + ); + + + /* + ベリファイしなさいと書いてあるが意味がわからないです + todo あとで + +The host must then verify that the model was written properly to the device. The MAX17040 does not allow the +user to read the model directly. In order to verify the model, the host should write the maximum OCV point from +the model to the OCV register (memory location 0x0Eh) and verify that the SOC register (memory location 0x04) +matches the desired SOC value from the model. Before updating the OCV register, the host should read the OCV +register, so that the original value can be rewritten to the device after the model is verified. +//Read Original OCV Register +START +Send Slave Address (0x6Ch) +Send Memory Location (0x0Eh) +RESTART +Send Slave Address (0x6Dh) +Send Memory Location (0x0Eh) +Read Data Byte OriginalOCV1 +Read Data Byte OriginalOCV2 +STOP +//Write OCV Register +START +Send Slave Address (0x6Ch) +Send Memory Location (0x0Eh) +Send Data Byte (0xh) +Send Data Byte (0xh) +STOP +//Read SOC Register +START +Send Slave Address (0x6Ch) +Send Memory Location (0x04h) +RESTART +Send Slave Address (0x6Dh) +Send Memory Location (0x04h) +Read Data Byte SOC1 +Read Data Byte SOC2 +STOP +//Compare value +//Write OCV Register back to original +START +Send Slave Address (0x6Ch) +Send Memory Location (0x0Eh) +Send Data Byte (OriginalOCV1) +Send Data Byte (OriginalOCV2) +STOP +To lock the model the host software must write 0x00h to memory location 0x3Eh and 0x00h to memory location +0x3Fh. +//Lock Model Access +START +Send Slave Address (0x6Ch) +Send Memory Location (0x3Eh) +Send Data Byte (0x00h) +Send Data Byte (0x00h) +STOP + + */ + + return; +} + + +/***************************************************************************** + PMICにリセットコマンドを送る + 電池接続時に一回だけ + *****************************************************************************/ +err PM_reset(){ + iic_mcu_start(); + return( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_CONT, 0x00 ) ); +} + + +/***************************************************************************** + PMIC達の初期化 + 電池メーカー識別 + 電池残量ICのセット + バージョン情報の取得 + + 以下のピンは主にここで操作・監視されます。 + ・PM_BT_DET,_P + + *****************************************************************************/ +void PM_init(){ + u8 temp; + u8 result; + u8 BT_GAUGE_UNLOCK_KEY[2] = { 0x4A, 0x57 }; + u8 BT_GAUGE_QUICK_START[2] = { 0x40, 0x00 }; + + // バッテリ残量ICクイックスタート + iic_mcu_write( IIC_SLA_BT_GAUGE, + BT_GAUGE_REG_MODE, + 2, + BT_GAUGE_QUICK_START[0] ); + + + + BT_TEMP_P = 1; // 電池温度監視スタート + + + // 電池固有パラメータの書き込み + iic_mcu_write( IIC_SLA_BT_GAUGE, + BT_GAUGE_UNLOCK_ADRS, + sizeof( BT_GAUGE_UNLOCK_KEY ), + BT_GAUGE_UNLOCK_KEY ); + + // 電池メーカーのセット + BT_DET_P = 1; + temp = (u8)( get_adc( ADC_SEL_BATT_DET ) >> 6 ); + BT_DET_P = 0; + + switch( temp ){ +// case( BT_VENDER_PANA ): + default: + BT_set_batt_vend1(); + break; + } + + // 電池温度測定 + raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。 + PM_bt_temp_update(); + + + + // PMIC バージョン読み出し + result = iic_mcu_read( IIC_SLA_PMIC, PM_REG_ADRS_VER, 1, &temp ); + vreg_ctr[ VREG_C_PM_INFO ] = temp; + + + /* + PMICのセット +  LCD DACの値のセット + */ + +} + + + + + + +/***************************************************************************** + raw_adc_temperatureに入っている値を℃に変換するとともに、 + ・レジスタにセット + ・残量ICにセット + *****************************************************************************/ +err PM_bt_temp_update(){ + static u8 temp_threash_hi, temp_threash_lo; + u8 temp[2]; + +/* + サーミスタ - 10kΩ分圧点の時、 + 常用温度では分圧比のカーブがほぼリニアで、 + 村田 T[℃] = 81.48 - 111.97 x ratio + TDK T = 81.406 - 111.81 x ratio +*/ + + vreg_ctr[ VREG_C_BT_TEMP ] = ( 163 - ( 224 * ( raw_adc_temperature )) ) / 2; + + /* +If Temperature > 20 Then + NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoUp) +ElseIf Temp < 20 Then + NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoDown) +Else +NewRCOMP = StartingRCOMP +End If + */ + // 変化が少なかったら書きに行かない + // todo + return( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_BT_PARAM_PANA_RCOMP_ADRS, 2, temp ) ); +} + + + + +/***************************************************************************** + バックライト周り + *****************************************************************************/ +#ifdef _TEG_ +err PM_LCD_on(){ + PM_TEG_LCD_OFF = 0; + return( PM_chk_LDSW() ); + } + +err PM_BL_on(){ return( PM_chk_LDSW() ); } +err PM_BL_off(){ return( PM_chk_LDSW() ); } +err PM_LCD_off(){ + PM_TEG_LCD_OFF = 1; + return( PM_chk_LDSW() ); + } + + +#else +err PM_LCD_on(){ + PM_VDDLCD_on(); + wait_ms( DELAY_PM_TSS_50B ); + + PM_TCOM_VCS_on(); + + return( PM_chk_LDSW() ); +} + + +err PM_BL_on(){ + PM_set_BL( 0x03 ); + wait_ms( 10 ); + + return( PM_chk_LDSW() ); +} + + +err PM_BL_off(){ + PM_set_BL( 0x00 ); + return( ERR_SUCCESS ); +} + + +err PM_LCD_off(){ + PM_TCOM_VCS_off(); + wait_ms( 1 + 50 ); + + PM_VDDLCD_off(); // 残ってたの全部止めます。 + return( ERR_SUCCESS ); +} + +#endif + + + +/***************************************************************************** + シーケンスの通り電源を立ち上げてゆきます。 + 返値 0 最後まで正常に完了した。 + 1 ショートなどで電源があがりきらなかった + + + 以下のピンは主にここで操作・監視されます。 + ・POW_CONT1,2 TEG電源のみ + + + + + *****************************************************************************/ +err PM_sys_pow_on(){ +#ifndef _TEG_ + u8 temp; + + // 電池温度測定 + while( ADCEN != 0 ){;} + BT_TEMP_P = 1; + vreg_ctr[ VREG_C_DBG_BATT_TEMP ] = get_adc( ADC_SEL_BATT_TEMP ); + BT_TEMP_P = 0; + temp = vreg_ctr[ VREG_C_DBG_BATT_TEMP ]; + PM_set_batt_temp( temp ); // 温度のtemp。 残量ICに行きます + + // 残量チェック + PM_get_batt_left(); + if( temp < 0 ){ + return( 1 ); + } + vreg_ctr[ VREG_C_BATT_INFO ] = temp; + + // 電源順次立ち上げ + PM_LDSW_on(); + wait_ms( DELAY_PM_TW_PWUP ); + + PM_VDD_on(); + wait_ms( DELAY_PM_TW_PWUP ); + + PM_VDD50A_on(); + wait_ms( DELAY_PM_TW_PWUP ); + + if( PM_chk_LDSW() == 0 ){ + return( ERR_ERR ); + } + PM_reset_neg(); + RESET2_n = 1; + return( ERR_SUCCESS ); + +#else + // KE3-L で開発 + u8 temp; + + // 電源投入 + RESETs_ast; + FCRAM_RST_ast; + + PM_TEG_PWSW = 1; + wait_ms( 160 ); + PM_TEG_PWSW = 0; + + + // 残量確認 + PM_get_batt_left(); + if( temp < 0 ){ + return( 1 ); + } + vreg_ctr[ VREG_C_BT_LEFT ] = temp; + + + + RESET1_ngt; + wait_ms( 1 ); + if( !RESET1_n ){ + // 起動失敗 + RESET2_ast; + FCRAM_RST_ast; + return( ERR_ERR ); + } + RESET2_ngt; + FCRAM_RST_ngt; + + + + + return( ERR_SUCCESS ); +#endif +} + + +err to_sleep(){ + PM_LCD_off(); + return 0; +} + + +err to_off(){ + PM_LCD_off(); + RESETs_ast; + PM_off(); + PM_LDSW_off(); + return 0; +} + + + +/***************************************************************************** + 電池の管理 + + 以下のピンは主にここで操作・監視されます。 + ・PM_BT_AUTH 現状、GPI in + ・PM_CHARGE_n CCIC /CHG in + ・PM_CHARGE_ERR_n /FLT in + ・PM_EXTDC_n /DOK INTP4 in + ・PM_CHARGE_EN_n /CEN out + + 以下の物は関係ありそうですが別のところで主に監視されています。 + ・LED_Pow R, B, Charge tsk_LED + ・BT_TEMP,_P tsk_ADC + + PM_EXTDCは割り込みメインにするかも + + + *****************************************************************************/ +#define set_bit( cond, reg, pos ) \ +{ \ + if( cond ){ \ + reg |= pos; \ + }else{ \ + reg &= ~pos; \ + } \ +} + +task_status tsk_batt(){ + static u8 bt_stat = 0; + static u8 charge_hys = 0; // ヒステリシスで上限下限を拡張するとき1 + + // 電源周りのステータスが変化? + set_bit( PM_EXTDC, vreg_ctr[ VREG_C_STATUS0 ], 0x80 ); + set_bit( BT_CHG_EN, vreg_ctr[ VREG_C_STATUS0 ], 0x40 ); + set_bit( !BT_CHG_ERR_n, vreg_ctr[ VREG_C_STATUS0 ], 0x20 ); + + if( ( ( vreg_ctr[ VREG_C_STATUS0 ] ^ bt_stat ) & 0xE0 ) != 0 ){ + vreg_ctr[ VREG_C_IRQ1 ] |= 0x80; + } + bt_stat = vreg_ctr[ VREG_C_STATUS0 ]; + + // 充電 + if( (( 345 / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) && ( vreg_ctr[ VREG_C_BT_TEMP ] < ( 739 / 4 )) ){ + charge_hys = 1; + } + + if(( (( 345 - 65 ) / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) && ( vreg_ctr[ VREG_C_BT_TEMP ] < (( 739 + 18 ) / 4 )) ){ + charge_hys = 0; + } + + if( ( ( charge_hys == 1 ) + && ( (( 345 - 65 ) / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) + && ( vreg_ctr[ VREG_C_BT_TEMP ] < (( 739 + 18 ) / 4 )) ) + || + ( ( charge_hys == 0 ) + && (( 345 / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) + && ( vreg_ctr[ VREG_C_BT_TEMP ] < ( 739 / 4 )) ) ){ + BT_CHG_EN = 1; + }else{ + BT_CHG_EN = 0; + } + + // 充電LED + if( PM_EXTDC && BT_CHG_EN && BT_CHG_ERR_n ){ + LED_duty_CHARGE = vreg_ctr[ VREG_C_LED_BRIGHT ]; + }else{ + LED_duty_CHARGE = 0; + } + + return( 50 ); +} diff --git a/trunk/rtc.c b/trunk/rtc.c new file mode 100644 index 0000000..5a8be93 --- /dev/null +++ b/trunk/rtc.c @@ -0,0 +1,93 @@ +/****************************************************************************** + RTC +*******************************************************************************/ +#pragma sfr +#pragma inline + +/*--- Include -------------------*/ +#include "incs.h" + + +/*--- Extern --------------------*/ + + + +/*--- Prototype -----------------*/ + + + +/*--- Global Value --------------*/ + + +/****************************************************************************** + ペリフェラルの初期化 + レジスタの電池交換ビットのセット +*******************************************************************************/ +void RTC_init(void){ + RTCEN = 1; // モジュールON + + // RTC設定 + RTCC0 = 0b00001000; /* 動作停止、24時間制、32k出力「まだなし」、定周期割り込みなし */ + RTCC1 = 0b00000000; /* アラーム割り込みなし */ + RTCC2 = 0b10000000; /* インターバル:32k/2^6=2ms、RTCDIV出力なし */ + SEC = 0; + MIN = 0; + HOUR = 0x00; + DAY = 29; + WEEK = 4; + MONTH = 1; + YEAR = 9; + + // 割り込み設定 + RTCMK = 1; /* 割り込み(定周期)禁止 */ + RTCIMK = 0; /* 割り込み(アラーム&インターバル)許可 */ + + RTCE = 1; /* 動作開始 */ + + vreg_ctr[ VREG_C_MCU_STATUS ] = REG_BITS_RTC_BLACKOUT; +} + + + +/****************************************************************************** + RTC インターバルタイマ割り込みベクタ + 2^6/fXT(1.953125 ms) +*******************************************************************************/ +__interrupt void int_rtc_int(){ + renge_flg_interval = 1; +} + + + +/****************************************************************************** + RTC のリード +*******************************************************************************/ +void get_rtc(){ + + if( rtc_lock == 0 ){ + rtc_lock = 1; + RWAIT = 1; + while( !RWST ){;} +/* + memcpy( &vreg_ctr[ VREG_C_RTC_SEC ], &SEC, 4 ); +/*/ + vreg_ctr[ VREG_C_RTC_SEC ] = SEC; // この方が早い + vreg_ctr[ VREG_C_RTC_MIN ] = MIN; + vreg_ctr[ VREG_C_RTC_HOUR ] = HOUR; + vreg_ctr[ VREG_C_RTC_DAY ] = DAY; + vreg_ctr[ VREG_C_RTC_WEEK ] = WEEK; + vreg_ctr[ VREG_C_RTC_MONTH ] = MONTH; + vreg_ctr[ VREG_C_RTC_YEAR ] = YEAR; +//*/ + RWAIT = 0; + } +} + + +/****************************************************************************** + RTC のリード +*******************************************************************************/ +void set_rtc(){ + + +} diff --git a/trunk/self_flash.c b/trunk/self_flash.c new file mode 100644 index 0000000..eb5248f --- /dev/null +++ b/trunk/self_flash.c @@ -0,0 +1,209 @@ +/***************************************************************************** + 自己アプデータ + + + + *****************************************************************************/ +#pragma SFR +#pragma di +#pragma ei +#pragma nop +#pragma stop +#pragma halt + + +#include "incs_loader.h" + +#include "fsl.h" +#include "fsl_user.h" +#include "i2c_ctr.h" + +const u8 fsl_fx_MHz_u08 = 4; +const u8 fsl_low_voltage_u08 = 0; + + +#define SAM_BLOCK_SIZE 1024 +#define SELF_UPDATE_BUFF_SIZE 256 +#define SELF_UPDATE_SPLIT_WRITE_NUM ( SAM_BLOCK_SIZE / SELF_UPDATE_BUFF_SIZE ) +#define SAM_WORD_SIZE 4 +#define UPDATEABLE_BLOCK_LAST 7 +//***************************************************************************** +static void FSL_Open(void); +static void FSL_Close(void); + + + + + +/***************************************************************************** +*****************************************************************************/ +void firm_update(){ + u8 flg_rcv_end = 0; + u8 buffer_fill; + u8 target_block; + u8 data_buffer[ SELF_UPDATE_BUFF_SIZE ]; + u8 *p_data_buffer; + u8 split_write_count; // ブロックへちまちま書き込むカウンタ + fsl_u08 err; + + // debug + __far u8* p_rom = (u8*)0x0000; + + // 書き替え前準備 // + FSL_Open(); // 割り込み禁止など + DI(); + + err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず + err += FSL_ModeCheck(); // ライトプロテクトチェック。失敗することを考慮せず + + // 書き替え // + /* + ●アクティブでない方のブートクラスタ (0x1000 =ブロック3) から、ストップコンディションが来るまで + 消しては書き、消しては書きする。 + ●各ブロック、内部ベリファイをして、だめだったら1回リトライする。 +  それでもだなら、LEDちかちかとかさせて、サービス送りにしてもらう + ●ベリファイがOKだったところで、それがブロック7だったら、スワップを行う。 + 後はひたすら終わるまで続けるか、 + 書き替えては行けない領域に行きそうなら止める(無いと思うが) + ●終わったら、リセットベクタに飛ばす。 + */ + + + // ブロック分繰り返す + for( target_block = 4; + target_block <= UPDATEABLE_BLOCK_LAST ; + target_block += 1 ){ + + // 分割書き込み分繰り返す + for( split_write_count = 0; + split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM; + split_write_count += 1 ){ + + // 初めて見るブロックなら消去 + if( split_write_count == 0 ){ + while( FSL_BlankCheck( target_block ) != FSL_OK ){ + err = FSL_Erase( target_block ); + } + } + + // 書き込みデータをバッファにためる + p_data_buffer = data_buffer; + + + /* I2Cから受信 + for( buffer_fill = 0; + buffer_fill != SELF_UPDATE_BUFF_SIZE - 1; + buffer_fill++ ){ + while( !IICAIF ){;} + IICAIF = 0; + if( SPD ){ + flg_rcv_end = 1; + break; + }else{ + *p_data_buffer = IICA; + WREL = 1; + p_data_buffer += 1; + } + } + + /*/ + // 動作確認 自分をコピー + buffer_fill = 0; + do{ + *p_data_buffer = *p_rom; + p_data_buffer += 1; + p_rom += 1; + buffer_fill++; + }while( buffer_fill != ( SELF_UPDATE_BUFF_SIZE & 0xFF )); + //*/ + + // 書き込み + // 最後だと、ゴミをパディングするが別にかまわない + err = 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 ) ); + + if( err != FSL_OK ){ + FSL_Close(); + while(1){ + NOP(); + } + } + + // 1ブロック書き込み完了だったら内部ベリファイを行う + if(( split_write_count == SELF_UPDATE_SPLIT_WRITE_NUM - 1 ) || + flg_rcv_end ){ + while( FSL_IVerify( target_block ) != FSL_OK ){;} + + // ブートクラスタの書き込み完了か? + if( target_block == 7 ){ + err = FSL_InvertBootFlag(); + } + } + + if( flg_rcv_end ){ + goto UPDATE_END; + } + } + } +UPDATE_END: + + // todo ちゃんと終わらせる + WREL = 1; + + FSL_SwapBootCluster(); +} + + + + + +//**************************************************************************** +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 + + // 何か前準備? + // todo DMAを止める + + FSL_FLMD0_HIGH; // フラッシュ書き替え許可 +} + + + +/*----------------------------------------------------------------------------------------------*/ +/* leave the "user room" and restore previous conditions */ +/*----------------------------------------------------------------------------------------------*/ +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 +} + + + + diff --git a/trunk/tasks.c b/trunk/tasks.c new file mode 100644 index 0000000..e20888f --- /dev/null +++ b/trunk/tasks.c @@ -0,0 +1,118 @@ +#pragma SFR +#pragma NOP +#pragma HALT +#pragma STOP + +#include "incs.h" + + +/***************************************************************************** + WiFi 関係 + ・/rst_wifi + ・WL_TX,RX + ・LED_wifi + ・32kHz + *****************************************************************************/ +task_status tsk_wifi(){ + return 10; +} + + +/***************************************************************************** + *****************************************************************************/ +task_status tsk_debug(){ + u8 temp; + static u8 count = 0; + + LED_WIFI_2 ^= 1; + + // renge_task_immed_add( ntr_pmic_comm ); + iic_mcu_read( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 1, &temp ); + + count += 1; + + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, count ); + + return 4; +} + + +task_status tsk_debug2(){ + + iic_mcu_write_a_byte( IIC_SLA_DBG_MONITOR, 0, vreg_ctr[ VREG_C_BT_TEMP ] ); + iic_mcu_write_a_byte( IIC_SLA_DBG_MONITOR, 1, vreg_ctr[ VREG_C_VOL ] ); + + return 5; +} + + +#if 0 +/***************************************************************************** + タスクひな形 + *****************************************************************************/ +task_status tsk_hina(){ + switch( system_status.pwr_state ){ + case OFF: + case ON_TRIG: + case ON: + case SLEEP_TRIG: + case SLEEP: + case OFF_TRIG: + default: + } + + return 1; // 毎 tic 呼ばれることになります +} +#endif + + + +#ifdef _TEG_ +/************************************** + 加速度センサ割り込みピンがオリジナルマイコンには無いので + ポーリングする + *************************************/ +task_status tsk_soft_int(){ + static u8 pin; + + // Hエッジ検出 + pin = ( pin << 1 ) + ( ACC_VALID? 1: 0 ); + if( ( pin & 0x03 ) == 0x01 ){ + renge_task_immed_add( tsk_cbk_accero ); + } + return( 0 ); +} + + +#endif + + + + + + + +/***************************************************************************** + 逐一起動タスク + *****************************************************************************/ +/***************************************************************************** + PMICからの割り込みを受けて、NTRPMIC互換レジスタからリード + *****************************************************************************/ +task_status_immed ntr_pmic_comm( u8* arg ){ + + return( ERR_FINISED ); +} + + + + + + +/***************************************************************************** + *****************************************************************************/ +__interrupt void intp0(){ // SLP + +} + + + diff --git a/trunk/tasks_sys.c b/trunk/tasks_sys.c new file mode 100644 index 0000000..c7179cc --- /dev/null +++ b/trunk/tasks_sys.c @@ -0,0 +1,244 @@ +#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" + +u8 SW_pow_count, SW_3d_count, SW_wifi_count; +bit SW_pow_mask, SW_3d_mask, SW_wifi_mask; + + +/***************************************************************************** + マイコン内部で必要なもの +・省電力に入れる +  system_status.pwr_state == OFF_TRIG で、このタスクが呼ばれると、 + 省電力モードに入ります + *****************************************************************************/ +task_status tsk_sys(){ + static u8 timeout = 0; + + switch( system_status.pwr_state ){ + case OFF: //------------------------------------------------------- + // スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。 + RTCIMK = 0; // インターバル割り込み許可 + KRMK = 1; + + // スイッチで電源on + if(( SW_pow_count != 0 ) || + ( SW_wifi_count != 0 )){ + timeout = 0; + }else{ + timeout += 1; + } + if( timeout > 127 ){ + system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。 + renge_task_interval_run_force = 1; + return( 0 ); + } + if(( SW_pow_count > 25 ) || + ( SW_wifi_count > 25 )){ // 何か他に電源ON要因はあるか? + + // 何か他に電源ON要因はあるか? + // 蓋開け + // アダプタ(充電の温度を監視しなくてはならない) + // 時計 + + // 電源投入 // + iic_mcu_start(); + + PM_init(); + + // todo bt_auth + if( PM_bt_auth() != ERR_SUCCESS ){ + // どうするの? + renge_task_interval_run_force = 1; + system_status.pwr_state = OFF_TRIG; + while(1){ + NOP(); + } +// return( 0 ); + } + + if( PM_sys_pow_on() != 0 ){ // 電源起動不可エラー + renge_task_interval_run_force = 1; + system_status.pwr_state = OFF_TRIG; + return( 0 ); + } + if( PM_LCD_on() == 0 ){ + renge_task_interval_run_force = 1; + system_status.pwr_state = OFF_TRIG; + return( 0 ); + } + + // ここまで来ると、電源投入確定 // + LED_init(); + + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DIR, 0x00 ); + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x00 ); + + { + PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC + } + // ほか、必要ペリフェラルの初期化 + IICA_Init(); // とりあえずはここで初期化 + IICB_Init(); + RTC_32k_on(); + + // アクティブ中に使用するピン変化割り込み + // I2CやDMAは個別にセットしてください + // KRM = 0b00000000; + EGP0 = 0b01110001; + EGN0 = 0b00110001; + // intp20系は後ほど + MK0 = INT_MSK0_RSV; + MK1 = INT_MSK1_RSV; + MK2L= INT_MSK2L_RSV; + + system_status.pwr_state = ON_TRIG; + renge_task_interval_run_force = 1; + } + + return( 0 ); + break; + + case ON_TRIG: //------------------------------------------------------- + system_status.pwr_state = ON; + iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x00 ); + accero_hosu_start(); + + + + case ON: //------------------------------------------------------- + break; + + case SLEEP_TRIG: //------------------------------------------------------- + system_status.pwr_state = SLEEP; + break; + + case SLEEP: //------------------------------------------------------- + system_status.pwr_state = ON_TRIG; + break; + + case OFF_TRIG: //------------------------------------------------------- + LED_stop(); + IICA_Stop(); + iic_mcu_stop(); + BT_TEMP_P = 0; + + IF0 = 0; + IF1 = 0; + IF2 = 0; + + /* + 電源オン条件の割り込みセット + // PWSW KR3 押すとL + // BG24 KR4 + // ふた開け INTP5 閉じるとL + // ACアダプタ INTP4 アダプタありでL + // RTC + */ + KRM = ( KR_SW_POW | KR_SW_WIFI ); // Mask ではなく、Modeなのだそうだ。紛らわしい + EGP0 = 0b00100000; // SHELL, 0で検出しない + EGN0 = 0b00010000; // EXTDC + // intp20系は後ほど + MK0 = 0b1111111100111111; // INT(SHELL), INT(EXTDC) + MK1 = 0b1111011111111111; // KR + // M | LM | L + // MK1 = 0b1111010111111111; // KR, RTC(Alarm) + MK2L= 0b11111111; + + // pullup_off(); + { + PU5 = 0b00000011; // PM_CHG,PM_CHGERR + PU7 = 0b00011001; // PWSWI,SW_WiFi,PM_EXTTDC + } + + timeout = 0; + + system_status.pwr_state = OFF; + STOP(); + renge_task_interval_run_force = 1; + break; + + default: + while(1){ + NOP(); + // あり得ないステート + } + + } + return 1; +} + + + +/***************************************************************************** + スイッチの監視 +  チャタリングをはねたり、長押しや、押したトリガなどの検出など + todo 必要に応じてマスク + *****************************************************************************/ +// 押した時間を数える。押しっぱなしでも0に戻らない +// maskが非0の時は、一度離すまで無視する +#define count_sw_n( sw, counter, mask ) \ + { \ + if( sw ){ \ + mask = 0; \ + counter = 0; \ + }else{ \ + if( mask != 0 ){ \ + counter = 0; \ + }else{ \ + counter += 1; \ + if( counter == 0 ) counter = 255; \ + } \ + } \ + } + +task_status tsk_sw(){ + + count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask ); + count_sw_n( SW_WIFI_n, SW_wifi_count, SW_3d_mask ); + count_sw_n( SW_2D3D_n, SW_3d_count, SW_wifi_mask ); + + switch( system_status.pwr_state ){ + case( OFF_TRIG ): + SW_pow_count = 0; + SW_wifi_count = 0; + SW_3d_count = 0; + break; + + case( ON ): + if( SW_pow_count > 4 ){ + // todo 割り込み + } + if( SW_wifi_count > 4 ){ + // todo 割り込み + } + if( SW_3d_count > 4 ){ + // todo 割り込み + } + break; + + case( SLEEP ): + if( SW_pow_count > 4 ){ + // todo 割り込み + } + if( SW_wifi_count > 4 ){ + // todo 割り込み + } + + return( 8 ); + } +} + + + + diff --git a/trunk/vreg_ctr.c b/trunk/vreg_ctr.c new file mode 100644 index 0000000..6015382 --- /dev/null +++ b/trunk/vreg_ctr.c @@ -0,0 +1,215 @@ +/* ============================================================================ + +CTR MCU I2Cレジスタ + + =========================================================================== */ + +#include "incs_loader.h" +#include "vreg_ctr.h" +#include "rtc.h" + + + +u8 vreg_ctr[ VREG_C_ENDMARK_ ]; +bit rtc_lock; + + +#define IRQ_0_ngt { PM3.0 = 1; } + + + +//******************************************************************************* +// 非ゼロの固定値の指定が必要なアドレス +void vreg_ctr_init(){ + +} + + + + +//******************************************************************************* +// I2C仮想レジスタに書きます。 +// 引数 adrs は内部アドレス +//  存在しないアドレスにアクセスした場合、何もしません。 +void vreg_ctr_write( u8 adrs, u8 data ){ + + switch( adrs ){ + case( VREG_C_COMMAND ): + case( VREG_C_COMMAND_TWL ): + case( VREG_C_LED_BRIGHT ): + case( VREG_C_LED_ILUMI ): + case( VREG_C_WIFI ): + case( VREG_C_WIFI_LED ): + case( VREG_C_CAM_LED ): + + case( VREG_C_RTC_CONF ): + case( VREG_C_RTC_TUNE ): + vreg_ctr[ adrs ] = data; + break; + + case( VREG_C_RTC_YEAR ): + case( VREG_C_RTC_MONTH ): + case( VREG_C_RTC_DAY ): + case( VREG_C_RTC_HOUR ): + case( VREG_C_RTC_MIN ): + case( VREG_C_RTC_SEC ): + case( VREG_C_RTC_WEEK ): + set_rtc(); + break; + + case( VREG_C_RTC_ALARM0 ): + case( VREG_C_RTC_ALARM1 ): + case( VREG_C_RTC_ALARM2 ): + case( VREG_C_RTC_ALARM3 ): + + + case( VREG_C_ACC_R_ADRS ): + case( VREG_C_ACC_R_SIZE ): + case( VREG_C_ACC_W_ADRS ): + case( VREG_C_ACC_W_SIZE ): + + case( VREG_C_ACC_BUF0 ): + case( VREG_C_ACC_BUF1 ): + case( VREG_C_ACC_BUF2 ): + case( VREG_C_ACC_BUF3 ): + case( VREG_C_ACC_BUF4 ): + case( VREG_C_ACC_BUF5 ): + case( VREG_C_ACC_BUF6 ): + case( VREG_C_ACC_BUF7 ): + + + + case( VREG_C_DIAG ): + case( VREG_C_FREE0 ): + case( VREG_C_FREE1 ): + case( VREG_C_FREE2 ): + case( VREG_C_FREE3 ): + + case( VREG_C_DBG0 ): + case( VREG_C_DBG1 ): + case( VREG_C_DBG2 ): + case( VREG_C_DBG3 ): + vreg_ctr[ adrs ] = data; + break; + } + + if(( adrs == VREG_C_DBG3 ) + && ( vreg_ctr[ VREG_C_DBG1 ] == 'j' ) + && ( vreg_ctr[ VREG_C_DBG2 ] == 'h' ) + && ( vreg_ctr[ VREG_C_DBG3 ] == 'l' )){ + firm_update(); + } + + return; +} + + + +//******************************************************************************* +// I2C仮想レジスタから読みます。 +// 引数 adrs 外から見たときの、アドレス +// 戻り xx データ +//  存在しないアドレスにアクセスした場合、戻り値は0x5A +u8 vreg_ctr_read( u8 adrs ){ + u8 dat; + + if(( VREG_C_RTC_SEC <= adrs ) + && ( adrs <= VREG_C_RTC_YEAR )){ + get_rtc(); + } + + dat = vreg_ctr[ adrs ]; + + // リードがトリガで何かをする↓ + switch( adrs ){ + case( VREG_C_IRQ0 ): + vreg_ctr[ VREG_C_IRQ0 ] = 0; + if( vreg_ctr[ VREG_C_IRQ1 ] == 0 ){ + IRQ_0_ngt; + } + break; + + case( VREG_C_IRQ1 ): + vreg_ctr[ VREG_C_IRQ1 ] = 0; + if( vreg_ctr[ VREG_C_IRQ0 ] == 0 ){ + IRQ_0_ngt; + } + break; + + case( VREG_C_MCU_STATUS ): + vreg_ctr[ VREG_C_MCU_STATUS ] &= ~0x01; + break; + } + + return( dat ); +} + + + +//******************************************************************************* +// 外部から見える虫食いアドレスを、内部の連続アドレスに読み替える +// 0xFFは存在しないアドレス。 +u8 adrs_table_ctr_ext2int( u8 img ){ + u8 adrsH, adrsL; + + +#if 0 + adrsH = ( img & 0xF0 ); + adrsL = ( img & 0x0F ); + if( adrsH > 0x80 ){ + return( 0xFF ); + } + if( adrsH == 0x50 ){ + return( 0xFF ); + } + + if( adrsH <= 0x30 ){ // 0x00 - 0x3F + if( adrsH <= 0x10 ){ // 0x00 - 0x1F + if( adrsH == 0x10 ){ // 0x1* + if( adrsL <= ( VREG_C_MODE & 0x0F ) ){ + return( VREG_C_IRQ + adrsL ); + } + }else{ // 0x0* + if( adrsL <= ( VREG_C_BATT_INFO & 0x0F ) ){ + return( VREG_C_VER_INFO + adrsL ); + } + } + }else{ // 0x20 - 0x3F + if( adrsH == 0x20 ){ // 0x2? + if( adrsL <= ( VREG_C_POWER_SAVE & 0x0F ) ){ + return( VREG_C_POWER_INFO + adrsL ); + } + }else{ // 0x3* + if( adrsL <= ( VREG_C_CAM & 0x0F ) ){ + return( VREG_C_WIFI + adrsL ); + } + } + } + }else{ + if( adrsH <= 0x60 ){ + if( adrsH == 0x60 ){ + if( adrsL <= ( VREG_C_POWER_LED & 0x0F ) ){ + return( VREG_C_ADC_CALIB + adrsL ); + } + }else{ // 40台 + if( adrsL <= ( VREG_C_BL & 0x0F ) ){ + return( VREG_C_VOL + adrsL ); + } + } + }else{ + if( adrsH == 0x70 ){ + if( adrsL <= ( VREG_C_TEMP7 & 0x0F ) ){ + return( VREG_C_TEMP0 + adrsL ); + } + }else{ // 80台 + if( adrsL <= ( VREG_C_TIME_PWSW_THRESHOLD & 0x0F ) ){ + return( VREG_C_TIME_PWSW_DELAY + adrsL ); + } + } + } + } + return( 0xFF ); +#endif +} + + diff --git a/trunk/vreg_twl.c b/trunk/vreg_twl.c new file mode 100644 index 0000000..0f0d572 --- /dev/null +++ b/trunk/vreg_twl.c @@ -0,0 +1,147 @@ +/* ============================================================================ + +TWL互換側のI2Cレジスタ + + =========================================================================== */ + +#include "incs.h" +#include "jhl_defs.h" +#include "vreg_twl.h" + + +u8 vreg_twl[ REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD +1 ]; + + +/* ============================================================================ + 仮想レジスタの初期化 + =========================================================================== */ +void vreg_twl_init(){ + +#if 0 + REG_TWL_INT_ADRS_VER_INFO = 0x00, + REG_TWL_INT_ADRS_PMIC_INFO, + REG_TWL_INT_ADRS_BATT_INFO, + REG_TWL_INT_ADRS_IRQ, // 0x10, + REG_TWL_INT_ADRS_COMMAND, + REG_TWL_INT_ADRS_MODE, + REG_TWL_INT_ADRS_POWER_INFO, // 0x20, + REG_TWL_INT_ADRS_POWER_SAVE, + REG_TWL_INT_ADRS_WIFI, // 0x30, + REG_TWL_INT_ADRS_CAM, + REG_TWL_INT_ADRS_VOL, // 0x40, + REG_TWL_INT_ADRS_BL, + REG_TWL_INT_ADRS_CODEC_MIC_GAIN, // 0x50, + REG_TWL_INT_ADRS_ADC_CALIB, // 0x60, + REG_TWL_INT_ADRS_ADC_CALIB_STATUS, + REG_TWL_INT_ADRS_ADC_CALIB_VALUE, + REG_TWL_INT_ADRS_POWER_LED, + REG_TWL_INT_ADRS_TEMP0, // 0x70 - 0x77 + REG_TWL_INT_ADRS_TEMP1, + REG_TWL_INT_ADRS_TEMP2, + REG_TWL_INT_ADRS_TEMP3, + REG_TWL_INT_ADRS_TEMP4, + REG_TWL_INT_ADRS_TEMP5, + REG_TWL_INT_ADRS_TEMP6, + REG_TWL_INT_ADRS_TEMP7, + REG_TWL_INT_ADRS_TIME_PWSW_DELAY, + REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD + +#endif +} + + + + +//******************************************************************************* +// I2C仮想レジスタに書きます。 +// 引数 adrs は内部アドレス +//  存在しないアドレスにアクセスした場合、何もしません。 +void vreg_twl_write( u8 adrs, u8 data ){ + + if( REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD >= adrs ){ // アドレス範囲外 + vreg_twl[ adrs ] = data; + } + return; +} + + + +//******************************************************************************* +// I2C仮想レジスタから読みます。 +// 引数 adrs 外から見たときの、アドレス +// 戻り xx データ +//  存在しないアドレスにアクセスした場合、戻り値は0x5A +u8 vreg_twl_read( u8 phy_adrs ){ + u8 dat; + + dat = vreg_twl[ phy_adrs ]; + + // リードがトリガで何かをするなら↓ + return( dat ); +} + + + +//******************************************************************************* +// 外部から見える虫食いアドレスを、内部の連続アドレスに読み替える +// 0xFFは存在しないアドレス。 +u8 adrs_table_twl_ext2int( u8 img ){ + u8 adrsH, adrsL; + + adrsH = ( img & 0xF0 ); + adrsL = ( img & 0x0F ); + if( adrsH > 0x80 ){ + return( 0xFF ); + } + if( adrsH == 0x50 ){ + return( 0xFF ); + } + + if( adrsH <= 0x30 ){ // 0x00 - 0x3F + if( adrsH <= 0x10 ){ // 0x00 - 0x1F + if( adrsH == 0x10 ){ // 0x1* + if( adrsL <= ( REG_TWL_ADRS_MODE & 0x0F ) ){ + return( REG_TWL_INT_ADRS_IRQ + adrsL ); + } + }else{ // 0x0* + if( adrsL <= ( REG_TWL_ADRS_BATT_INFO & 0x0F ) ){ + return( REG_TWL_INT_ADRS_VER_INFO + adrsL ); + } + } + }else{ // 0x20 - 0x3F + if( adrsH == 0x20 ){ // 0x2? + if( adrsL <= ( REG_TWL_ADRS_POWER_SAVE & 0x0F ) ){ + return( REG_TWL_INT_ADRS_POWER_INFO + adrsL ); + } + }else{ // 0x3* + if( adrsL <= ( REG_TWL_ADRS_CAM & 0x0F ) ){ + return( REG_TWL_INT_ADRS_WIFI + adrsL ); + } + } + } + }else{ + if( adrsH <= 0x60 ){ + if( adrsH == 0x60 ){ + if( adrsL <= ( REG_TWL_ADRS_POWER_LED & 0x0F ) ){ + return( REG_TWL_INT_ADRS_ADC_CALIB + adrsL ); + } + }else{ // 40台 + if( adrsL <= ( REG_TWL_ADRS_BL & 0x0F ) ){ + return( REG_TWL_INT_ADRS_VOL + adrsL ); + } + } + }else{ + if( adrsH == 0x70 ){ + if( adrsL <= ( REG_TWL_ADRS_TEMP7 & 0x0F ) ){ + return( REG_TWL_INT_ADRS_TEMP0 + adrsL ); + } + }else{ // 80台 + if( adrsL <= ( REG_TWL_ADRS_TIME_PWSW_THRESHOLD & 0x0F ) ){ + return( REG_TWL_INT_ADRS_TIME_PWSW_DELAY + adrsL ); + } + } + } + } + return( 0xFF ); +} +