TWIペリフェラルを使ってI2Cプロトコルを制御する
Revision | 970a68376e9e8b99dbb8b954d0f8c5ea49d7fe69 (tree) |
---|---|
Time | 2012-08-01 06:53:00 |
Author | takemasa <suikan@sour...> |
Commiter | takemasa |
ソース入力完了
@@ -16,14 +16,19 @@ | ||
16 | 16 | #define I2CNUM 0 |
17 | 17 | |
18 | 18 | /** |
19 | + * \brief I2C ペリフェラルのタイムアウト時間(mSec) | |
20 | + */ | |
21 | +#define I2C_TIMEOUT 100 | |
22 | + | |
23 | +/** | |
19 | 24 | * \brief TWIペリフェラルの管理用ステート型。内部ステートマシンの状態値。 |
20 | 25 | */ |
21 | 26 | enum I2C_STATE { |
22 | - I2C_XMIT_ENTRY, | |
27 | + I2C_XMT_ENTRY, | |
23 | 28 | I2C_XMTRCV_ENTRY, |
24 | - I2C_XMT_WIT_WAIT, | |
25 | - I2C_XMIT_INT, | |
26 | - I2C_XMIT_NEXT_BYTE, | |
29 | + I2C_XMT_WAIT, | |
30 | + I2C_XMT_INT, | |
31 | + I2C_XMT_NEXT_BYTE, | |
27 | 32 | I2C_RCV_ENTRY, |
28 | 33 | I2C_RCV_WAIT, |
29 | 34 | I2C_RCV_INT, |
@@ -38,7 +43,7 @@ enum I2C_STATE { | ||
38 | 43 | struct I2C_MASTER_CONTROL_TYPE { |
39 | 44 | ID signal; /**< データの送受信が全部終わったときに割り込みハンドラからタスクに知らせるためのセマフォ */ |
40 | 45 | ID blocking; /**< I2Cペリフェラルへの排他アクセスのためのセマフォ */ |
41 | - unsigned short int_state; /**< TWIペリフェラルの割り込みステータスのコピー **/ | |
46 | + unsigned short intr_state; /**< TWIペリフェラルの割り込みステータスのコピー **/ | |
42 | 47 | enum I2C_STATE state; /**< I2Cペリフェラルハンドラの内部状態 */ |
43 | 48 | volatile uint16_t * clkdiv ; |
44 | 49 | volatile uint16_t * control ; |
@@ -77,11 +82,19 @@ int i2c_master_read( int peripheral, int slave, unsigned char read_data[], int r | ||
77 | 82 | int i2c_master_write_read( int peripheral, int slave, unsigned char write_data[], int write_count, unsigned char read_data[], int read_count) |
78 | 83 | { |
79 | 84 | struct I2C_MASTER_CONTROL_TYPE *twi; |
80 | - BOOL read, write; | |
85 | + BOOL read, write, rstart; | |
86 | + unsigned char *wptr, *rptr; | |
81 | 87 | |
82 | 88 | // 可読性向上のため、TWI管理構造体のポインタを設定する。 |
83 | 89 | twi = &i2c_control[peripheral]; |
84 | 90 | |
91 | + // 送受信ポインタ.とかくこの世は生きにくい | |
92 | + wptr = write_data; | |
93 | + rptr = read_data; | |
94 | + | |
95 | + // この代入は必要ないが、警告がうるさいので | |
96 | + rstart= FALSE; | |
97 | + | |
85 | 98 | // 読み書きの有無の確認 |
86 | 99 | // バッファがNULLだったり長さが0のパラメタは転送に使わない |
87 | 100 | write = ( write_data != NULL ) && ( write_count != 0 ); |
@@ -91,28 +104,86 @@ int i2c_master_write_read( int peripheral, int slave, unsigned char write_data[] | ||
91 | 104 | if ( read && write ) |
92 | 105 | twi->state = I2C_XMTRCV_ENTRY; |
93 | 106 | else if ( write && ! read ) |
94 | - twi->state = I2C_XMIT_ENTRY; | |
107 | + twi->state = I2C_XMT_ENTRY; | |
95 | 108 | else if ( ! write && read ) |
96 | 109 | twi->state = I2C_RCV_ENTRY; |
97 | 110 | else |
98 | 111 | return I2C_ERR_WRONGPARAM; |
99 | 112 | |
113 | + if ( write_count > 254 || read_count > 254 ) | |
114 | + return I2C_ERR_TOOLONGBUFFER; | |
115 | + | |
100 | 116 | |
101 | 117 | // peripheral 引数で指定されたi2cペリフェラルを排他的に使うためのPV処理。 |
102 | 118 | // これでスレッドセーフにできる |
103 | 119 | wai_sem(twi->blocking); |
104 | 120 | |
105 | - twi->master_addr = | |
106 | - // TODO | |
121 | + // SPIスレーブデバイスのアドレスを設定(7bit) | |
122 | + *twi->master_addr = peripheral; | |
123 | + | |
107 | 124 | // TWIステートマシン |
108 | 125 | do { |
109 | 126 | switch (twi->state) |
110 | 127 | { |
111 | - case I2C_XMIT_ENTRY : | |
128 | + case I2C_XMT_ENTRY : | |
129 | + rstart = FALSE; | |
130 | + *twi->master_ctl = ( write_count<<6 ) | MEN; // no rstart, transmit, no fast mode; | |
131 | + twi->state = I2C_XMT_WAIT; | |
132 | + break; | |
133 | + case I2C_XMTRCV_ENTRY : | |
134 | + rstart = TRUE; | |
135 | + *twi->master_ctl = ( write_count<<6 ) | RSTART | MEN; // rstart, transmit, no fast mode; | |
136 | + twi->state = I2C_XMT_WAIT; | |
137 | + break; | |
138 | + case I2C_RCV_ENTRY : | |
139 | + rstart = FALSE; | |
140 | + *twi->master_ctl = ( write_count<<6 ) | MDIR | MEN; // no rstart, receive, no fast mode; | |
141 | + twi->state = I2C_RCV_WAIT; | |
142 | + break; | |
143 | + case I2C_XMT_WAIT : | |
144 | + // 割り込みハンドラが送信割り込みを通知するまで待つ | |
145 | + if ( E_OK == twai_sem(twi->signal, I2C_TIMEOUT)) | |
146 | + { | |
147 | + twi->intr_state = I2C_ERR_TIMEOUT; | |
148 | + twi->state = I2C_EXIT; | |
149 | + } | |
150 | + else | |
151 | + twi->state = I2C_XMT_INT; | |
152 | + break; | |
153 | + case I2C_XMT_INT : | |
154 | + if ( twi->intr_state & MERR ) // エラーならすぐ終了 | |
155 | + twi->state = I2C_EXIT; | |
156 | + else if ( ( twi->intr_state & MCOMP ) && rstart) // MCOMP かつ RSTARTなら受信へ | |
157 | + twi->state = I2C_RCV_ENTRY; | |
158 | + else if ( twi->intr_state & MCOMP ) // RSTARTがないMCOMPなら終了 | |
159 | + twi->state = I2C_EXIT; | |
160 | + else // それ以外は送信割り込み | |
161 | + twi->state = I2C_XMT_NEXT_BYTE; | |
162 | + break; | |
163 | + case I2C_XMT_NEXT_BYTE : | |
164 | + twi->xmt_data8 = *(wptr++); // 1バイト送信 | |
165 | + twi->state = I2C_XMT_WAIT; // 次の送信待 | |
166 | + break; | |
167 | + case I2C_RCV_WAIT : | |
168 | + // 割り込みハンドラが受信割り込みを通知するまで待つ | |
169 | + if ( E_OK == twai_sem(twi->signal, I2C_TIMEOUT)) | |
170 | + { | |
171 | + twi->intr_state = I2C_ERR_TIMEOUT; | |
172 | + twi->state = I2C_EXIT; | |
173 | + } | |
174 | + else | |
175 | + twi->state = I2C_RCV_INT; | |
176 | + break; | |
177 | + case I2C_RCV_INT : | |
178 | + if ( twi->intr_state & (MERR | MCOMP )) // エラーか終了ならすぐ終了 | |
179 | + twi->state = I2C_EXIT; | |
180 | + else // それ以外は送信割り込み | |
181 | + twi->state = I2C_RCV_NEXT_BYTE; | |
182 | + break; | |
183 | + case I2C_RCV_NEXT_BYTE : | |
184 | + *(wptr++) = twi->rcv_data8; // 1バイト受信 | |
185 | + twi->state = I2C_RCV_WAIT; // 次の受信待 | |
112 | 186 | break; |
113 | - | |
114 | - // 割り込みハンドラが送受処理を完了するまで待つ | |
115 | - wai_sem(twi->signal); | |
116 | 187 | } |
117 | 188 | } while ( twi->state != I2C_EXIT ); |
118 | 189 |
@@ -120,7 +191,7 @@ int i2c_master_write_read( int peripheral, int slave, unsigned char write_data[] | ||
120 | 191 | sig_sem(twi->blocking); |
121 | 192 | |
122 | 193 | // 割り込みステータスを返す。正常終了なら0 |
123 | - return twi->int_state; | |
194 | + return twi->intr_state; | |
124 | 195 | } |
125 | 196 | |
126 | 197 | /** |
@@ -137,7 +208,7 @@ void i2c0_master_handler(void) | ||
137 | 208 | |
138 | 209 | // TWIペリフェラルの割り込みステータスを取得し、コピーを保存する。 |
139 | 210 | // コピーを保存するのは、このあと割り込みクリアで消えるからである。 |
140 | - twi->int_state = *twi->int_stat; | |
211 | + twi->intr_state = *twi->int_stat; | |
141 | 212 | |
142 | 213 | // 割り込みクリア。すべての割り込み要素をクリアしてしまう。ステータスはコピーしているのでタスクで処理する。 |
143 | 214 | *twi->int_stat = 0xFF; |
@@ -39,7 +39,9 @@ | ||
39 | 39 | */ |
40 | 40 | /*@{*/ |
41 | 41 | |
42 | -#define I2C_ERR_WRONGPARAM 0x40000000 | |
42 | +#define I2C_ERR_WRONGPARAM 0x4000 | |
43 | +#define I2C_ERR_TOOLONGBUFFER 0x2000 | |
44 | +#define I2C_ERR_TIMEOUT 0x1000 | |
43 | 45 | |
44 | 46 | /** |
45 | 47 | * \brief i2cマスターモードの割り込みサービスルーチン |