ctr_mcu/branches/sim/i2c_ctr.c
n2232 6ec42747e1 ●halの初期化を先頭の方に入れた。ファームアップデート時に電源が切れてしまうことがある。
●スタックがあふれる可能性があったので修正
・スタックをあまり使わないように(accero.c, iic_twl.c, pm.c, vreg_ctr_write からのhosu_increment_if_nesessary(), )
・iic_ctrの割り込み順位を下げた(iic_ctr_init)。iic_twl以外は一律最低に。
 mmen,DS互換で暫く波形を見たが問題なさそう。もう暫くエージング継続
・renge task_interval_runの中からtask_immed_runを呼ぶのをやめた。よーく動作確認をすること!(これは戻すかも)

●ext_infoの実装を修正(task_misc.c)
 romは減ったが、スタティックなRAMが増えた。それでもスタックを使うより安全と思う
●MGICの無い機材(白箱など)でも電池周りのHALが動くよう修正(adc.c)

●voltableを.hではなく.cへ移動

●iic_mcu_startのiic_puウェイトを1msに。別に動でもいいのだが。

○電源offからの電源投入チェック、アダプタ有無で異なるパスを通っていたが、出来るだけ共通に。テスト中



git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@363 013db118-44a6-b54f-8bf7-843cb86687b1
2011-08-09 02:41:16 +00:00

298 lines
7.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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.

/* ========================================================
対SoC 新規チャンネル I2C通信
藤田@開技.nintendo
'09 Apr
======================================================== */
#include "config.h"
// TSはマザボでテレコ、WMは回路図がテレコで結局一致…
#ifndef _WIN32
#pragma interrupt INTIICA1 int_iic_ctr RB1
#endif
#include "incs.h"
#ifdef _MCU_BSR_
// #ifdef _MODEL_TS0_ || _MODEL_WM0_
// ワーキングモデルはI2Cが逆
// TEGは回路図でテレコ
#define ACKD ACKD1
#define ACKE ACKE1
#define COI COI1
#define IICAEN IICA1EN
#define IICRSV IICRSV1
#define IICA IICA1
#define IICAIF IICAIF1
#define IICAMK IICAMK1
#define IICAPR0 IICAPR11
#define IICAPR1 IICAPR01
#define IICCTL0 IICCTL10
#define IICE IICE1
#define IICF IICF1
#define IICS IICS1
#define IICWH IICWH1
#define IICWL IICWL1
#define LREL LREL1
#define SPD SPD1
#define SPIE SPIE1
#define STCEN STCEN1
#define STD STD1
#define SVA SVA1
#define WREL WREL1
#define WTIM WTIM1
#define TRC TRC1
#define SMC SMC1
#define DFC DFC1
#endif
// ==============================================
enum en_IIC_STATE
{
IIC_IDLE = 0,
IIC_RCV_REG_ADRS,
IIC_TX_OR_RX,
IIC_TX,
IIC_RX
};
// ==============================================
extern bit irq_readed; // いずれかのIRQレジスタが読まれた
u8 iic_burst_state;
static enum en_IIC_STATE state = IIC_IDLE;
#define bit_iics_spd (i2c_stat & (1<<0))
#define bit_iics_std (i2c_stat & (1<<1))
#define bit_iics_ackd (i2c_stat & (1<<2))
#define bit_iics_trc (i2c_stat & (1<<3))
#define bit_iics_coi (i2c_stat & (1<<4))
// ==============================================
__interrupt void int_iic_ctr( )
{
static u8 reg_adrs;
static u8 tx_buf;
u8 rx_buf;
static u8 adrs_access_from; // バーストアクセスの時に使う
u8 i2c_stat = IICS1; // volatileのため
// 読み出し終了
if( !bit_iics_ackd // 割り込み要因はNAKデータ送信の最後
|| bit_iics_spd ) // ストップコンディション(!ACKD に来たときは割り込み来ない (SPIE = 0))
{
/*
I2Cの反応が遅くてこのフラグを処理する前にSTDがきてしまうことがある
けど、問題なく動作するつもり
*/
// レジスタリードで、割り込みピンをネゲート
// まだ読まれてない割り込みがあれば、再度アサート
if( irq_readed )
{
IRQ0_neg;
irq_readed = false;
if( !( (( vreg_ctr[VREG_C_IRQ0] & vreg_ctr[VREG_C_IRQ_MASK0 ] ) == 0 )
&& (( vreg_ctr[VREG_C_IRQ1] & vreg_ctr[VREG_C_IRQ_MASK1 ] ) == 0 )
&& (( vreg_ctr[VREG_C_IRQ2] & vreg_ctr[VREG_C_IRQ_MASK2 ] ) == 0 )
&& (( vreg_ctr[VREG_C_IRQ3] & vreg_ctr[VREG_C_IRQ_MASK3 ] ) == 0 ) ))
{
while( !IRQ0 ){;} // 時間稼ぎ不要かも
IRQ0_ast;
}
}
// I2C終了時に何かする物 //
hosu_read_end( ); // 歩数計読み出し終了
rtc_unlock( );
state = IIC_IDLE;
SPIE = 0;
LREL = 1;
EI();
return;
}
if( bit_iics_std ) // 割り込み要因:スタートコンディション
{
if( !( state == IIC_IDLE || state == IIC_TX_OR_RX ))
{
// sp/nack 取り損ねた
dbg_nop(); // こないはず...
/*
// パケットの先頭のstと見なす。
// 普通に続行
state = IIC_IDLE;
/*/
// リトライしてもらう
state = IIC_IDLE;
SPIE = 0;
LREL = 1;
EI();
//*/
}
// 通常
}
EI();
switch ( state )
{
case ( IIC_IDLE ):
// 自局呼び出しに応答。
// 初期化など
iic_burst_state = 0;
SPIE = 1;
WREL = 1; // ウェイト解除
state = IIC_RCV_REG_ADRS;
return;
case ( IIC_RCV_REG_ADRS ): // 2バイト目(レジスタアドレス)受信後に来る
// レジスタアドレス受信
reg_adrs = IICA;
WREL = 1;
adrs_access_from = reg_adrs;
tx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく
state = IIC_TX_OR_RX;
return;
case ( IIC_TX_OR_RX ): // ↑の次に来る割り込み。STなら送信準備、データが来たら書き込まれ
// if( TRC ) // 送信方向フラグ で区別するのは、割り込み遅延時に不具合が起こりえる
if( bit_iics_std )
{ // スタートコンディション検出フラグ
// リードされる
if( bit_iics_coi )
{ // アドレス一致フラグ
state = IIC_TX;
// no break, no return //
}
else
{
// リスタートで違うデバイスが呼ばれた!
SPIE = 0;
LREL = 1; // ウェイト解除?
state = IIC_IDLE; // 終了処理
return;
}
}
else
{
state = IIC_RX; // データ1バイト受信の割り込みだった
// no break, no return //
}
/* FALLTHROUGH */
default: // バースト R/W でここが何回も呼ばれることになる
if( state == IIC_TX )
{ // 送信
IICA = tx_buf;
vreg_ctr_after_read( reg_adrs, tx_buf ); // 読んだらクリアなどの処理
}
else
{ // 受信
rx_buf = IICA;
#ifdef _I2C_ERR_ABORT_
if( reg_adrs >= 0x80 || reg_adrs <= 1 )
{
LREL = 1; // なんかデータ化けたので通信終了 nakが返るのがなぁ…
return;
}
#endif
vreg_ctr_write( reg_adrs, rx_buf );
WREL = 1;
}
// レジスタアドレスのインクリメント
/// アクセスポインタを進めない特殊なレジスタ
switch( adrs_access_from )
{
case( VREG_C_ACC_HOSU_HIST ):
case( VREG_C_LED_NOTIFY_DATA ):
case( VREG_C_LED_POW ):
case( VREG_CX_INFO ):
case( VREG_CX_FREE_DATA ):
break;
case( VREG_CX_FREE_ADRS ):
if( reg_adrs == VREG_CX_FREE_ADRS )
{
reg_adrs = VREG_CX_FREE_DATA;
}
break;
default:
reg_adrs ++;
}
if( state == IIC_TX )
{ // さらにつぎに送るデータの準備だけシテオク。SPが来て使われないかもしれない
tx_buf = vreg_ctr_read( reg_adrs );
}
break;
}
}
// ========================================================
void IIC_ctr_Init( void )
{
IICAEN = 1;
IICE = 0; /* IICA disable */
IICAMK = 1; /* INTIICA disable */
IICAIF = 0; /* clear INTIICA interrupt flag */
// IICAPR0 = 1; /* set INTIICA high priority */
// IICAPR1 = 0; /* set INTIICA high priority */ スタック不足
P20 &= ~0x3;
SVA = IIC_C_SLAVEADDRESS;
IICF = 0x01;
STCEN = 1; // リスタートの許可
IICRSV = 1; // 通信予約をさせない:スレーブに徹する
SPIE = 0; // ストップコンディションでの割り込みを禁止
WTIM = 1; // 自動でACKを返した後clkをLに固定する
ACKE = 1;
IICWH = 5;
IICWL = 10; // L期間の長さ
SMC = 1; // 高速モード
DFC = 1; // デジタルフィルタon (@fast mode)
IICAMK = 0; // 割り込みを許可
IICE = 1;
PM20 &= ~0x3; /* set clock pin for IICA */
state = IIC_IDLE;
}
// ========================================================
void IIC_ctr_Stop( void )
{
IICE = 0; /* IICA disable */
IICAEN = 0;
}