source: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/i2c.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 19.6 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 * Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
9 *
10 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * の無保証規定を掲載すること.
20 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * と.
23 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
25 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * 報告すること.
27 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31 * 免責すること.
32 *
33 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37 * の責任を負わない.
38 *
39 * @(#) $Id$
40 */
41/*
42 *
43 * K210 I2Cドライバ関数群
44 *
45 */
46#include "kernel_impl.h"
47#include <t_syslog.h>
48#include <t_stdlib.h>
49#include <string.h>
50#include <sil.h>
51#include <target_syssvc.h>
52#include "device.h"
53#include "i2c.h"
54
55/*
56 * SIL関数のマクロ定義
57 */
58#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
59#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
60#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
61
62/*
63 * I2CポートIDから管理ブロックを取り出すためのマクロ
64 */
65#define INDEX_I2C(i2cid) ((uint_t)((i2cid) - 1))
66
67#ifndef I2C_TIMEOUT
68#define I2C_TIMEOUT 500 /* 500ms */
69#endif
70
71#define I2C_CON_SPEED_STANDARD 0x00000020 /* <=100Kbit/s */
72#define I2C_CON_SPEED_FAST 0x00000040 /* <=400Kbit/s or <=1000Kbit/s */
73#define I2C_CON_SPEED_HIGH 0x00000060 /* <=3.4Mbit/s */
74
75#define DEFAULT_THRESHOLD 3
76#define DEFAULT_MASTER (I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN)
77#define DEFAULT_SLAVE (I2C_CON_STOP_DET_IFADDRESSED)
78#define DEFAULT_INTRM (I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ)
79
80/*
81 * I2Cポート設定テーブル
82 */
83static const I2C_PortControlBlock i2c_pcb[NUM_I2CPORT] = {
84 { TADR_I2C0_BASE, SYSCTL_CLK_EN_PERI_I2C0_CLK_EN, 8, FUNC_I2C0_SCLK, FUNC_I2C0_SDA },
85 { TADR_I2C1_BASE, SYSCTL_CLK_EN_PERI_I2C1_CLK_EN, 16, FUNC_I2C1_SCLK, FUNC_I2C1_SDA },
86 { TADR_I2C2_BASE, SYSCTL_CLK_EN_PERI_I2C2_CLK_EN, 24, FUNC_I2C2_SCLK, FUNC_I2C2_SDA }
87};
88
89static I2C_Handle_t i2cHandle[3];
90
91
92/*
93 * I2C転送待ち
94 * parameter1 hi2c: I2Cハンドラへのポインタ
95 * parameter2 Timeout:タイムアウト時間(ms)
96 */
97static ER
98i2c_transwait(I2C_Handle_t *hi2c, uint32_t Timeout)
99{
100 uint32_t tick = 0;
101
102 while(hi2c->status != I2C_STATUS_READY){
103 if(tick >= Timeout)
104 return E_TMOUT;
105 if(hi2c->Init.semid != 0)
106 twai_sem(hi2c->Init.semid, 1);
107 else
108 dly_tsk(1);
109 tick++;
110 }
111 if(hi2c->ErrorCode != 0)
112 return E_SYS;
113 else
114 return E_OK;
115}
116
117/*
118 * I2Cデータ送信モジュール
119 */
120static void
121i2c_send_data(I2C_Handle_t *hi2c)
122{
123 uint32_t fifo_len, i, tmp;
124
125 if(hi2c->tXferCount > 0){
126 uint8_t *send_buf;
127 int addr_len = hi2c->aXferSize - hi2c->aXferCount;
128 fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
129 if(addr_len > 0){
130 fifo_len = addr_len < fifo_len ? addr_len : fifo_len;
131 send_buf = &hi2c->aBuffer[hi2c->aXferCount];
132 }
133 else{
134 fifo_len = hi2c->tXferCount < fifo_len ? hi2c->tXferCount : fifo_len;
135 send_buf = hi2c->pBuffPtr;
136 }
137 for(i = 0 ; i < fifo_len ; i++)
138 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), *send_buf++);
139 if(addr_len > 0)
140 hi2c->aXferCount += fifo_len;
141 else{
142 hi2c->pBuffPtr += fifo_len;
143 hi2c->XferCount += fifo_len;
144 }
145 hi2c->tXferCount -= fifo_len;
146 }
147 (void)(tmp);
148}
149
150/*
151 * I2Cデータ受信モジュール
152 */
153static void
154i2c_recv_data(I2C_Handle_t *hi2c)
155{
156 uint32_t fifo_len, i, tmp;
157 int rx_len = hi2c->XferSize - hi2c->XferCount;
158
159 if(hi2c->tXferCount > 0 || rx_len > 0){
160 fifo_len = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_RXFLR));
161 fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
162 for(i = 0 ; i < fifo_len ; i++){
163 tmp = (uint8_t)sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD));
164 *hi2c->pBuffPtr++ = (uint8_t)tmp;
165 }
166 hi2c->XferCount += fifo_len;
167 fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
168 fifo_len = hi2c->tXferCount < fifo_len ? hi2c->tXferCount : fifo_len;
169 for(i = 0 ; i < fifo_len ; i++)
170 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), I2C_DATA_CMD_CMD);
171 hi2c->tXferCount -= fifo_len;
172 }
173}
174
175
176/*
177 * I2Cデバイスの初期化
178 * parameter1 hi2c I2Cハンドラへのポインタ
179 * return 正常終了時、E_OK
180 */
181I2C_Handle_t *
182i2c_init(ID portid, I2C_Init_t *ii2c)
183{
184 I2C_Handle_t *hi2c;
185 const I2C_PortControlBlock *pcb;
186 uint32_t v_i2c_freq = 0;
187 uint32_t threshold = 0;
188 int32_t v_period_clk_cnt2 = 0;
189 uint16_t v_period_clk_cnt;
190 uint8_t no;
191 uint32_t speed_mode = I2C_CON_SPEED_STANDARD;
192
193 if(portid < I2C1_PORTID || portid >= NUM_I2CPORT)
194 return NULL;
195
196 no = INDEX_I2C(portid);
197 hi2c = &i2cHandle[no];
198 hi2c->i2cid = portid;
199 pcb = &i2c_pcb[no];
200 hi2c->base = pcb->base;
201 memcpy(&hi2c->Init, ii2c, sizeof(I2C_Init_t));
202
203 /*
204 * ファンクションピン設定
205 */
206 if(ii2c->SdaPin >= 0)
207 fpioa_set_function(ii2c->SdaPin, pcb->sdafunc);
208 if(ii2c->SclPin >= 0)
209 fpioa_set_function(ii2c->SclPin, pcb->sclfunc);
210
211 /*
212 * クロック設定
213 */
214 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_SEL0_APB0_CLK_SEL);
215 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
216 threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
217 threshold &= ~(0xff << pcb->thresholdshift);
218 threshold |= (DEFAULT_THRESHOLD << pcb->thresholdshift);
219 sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5), threshold);
220
221 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_SEL0_APB0_CLK_SEL);
222 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
223 threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
224 threshold &= ~(0xff << pcb->thresholdshift);
225 threshold |= (DEFAULT_THRESHOLD << pcb->thresholdshift);
226 sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5), threshold);
227
228 threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH5));
229 threshold = (threshold >> pcb->thresholdshift) & 0xff;
230 v_i2c_freq = get_pll_clock(0) / ((threshold + 1) * 2);
231 v_period_clk_cnt2 = (((int64_t)v_i2c_freq * 1000L) / ii2c->ClockSpeed / 2) + 500;
232 v_period_clk_cnt = v_period_clk_cnt2 / 1000;
233
234 if(v_period_clk_cnt <= 6)
235 v_period_clk_cnt = 6;
236 if(v_period_clk_cnt >= 65525)
237 v_period_clk_cnt = 65525;
238 if((ii2c->ClockSpeed > 100000) && (ii2c->ClockSpeed <= 1000000))
239 speed_mode = I2C_CON_SPEED_FAST;
240 else if(ii2c->ClockSpeed > 1000000)
241 speed_mode = I2C_CON_SPEED_HIGH;
242 else
243 speed_mode = I2C_CON_SPEED_STANDARD;
244
245 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), 0);
246 if(ii2c->OwnAddress1 == 0) /* master */
247 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CON), (DEFAULT_MASTER | ii2c->AddressingMode | speed_mode));
248 else /* slave */
249 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CON), (DEFAULT_SLAVE | ii2c->AddressingMode | speed_mode));
250 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_SS_SCL_HCNT), v_period_clk_cnt);
251 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_SS_SCL_LCNT), v_period_clk_cnt);
252
253 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), ii2c->OwnAddress1/2);
254 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_RX_TL), 0);
255 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_TL), 0);
256 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), DEFAULT_INTRM);
257 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_CR), (I2C_DMA_CR_RDMAE | I2C_DMA_CR_TDMAE));
258 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_RDLR), 0);
259 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_TDLR), 4);
260 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), I2C_ENABLE_ENABLE);
261 hi2c->status = I2C_STATUS_READY;
262 syslog_3(LOG_NOTICE, "## abrt[%08x] dmacr[%08x] intrm[%08x] ##", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_DMA_CR)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK)));
263 return hi2c;
264}
265
266/*
267 * I2Cデバイスの無効化
268 * parameter1 hi2c I2Cハンドラへのポインタ
269 * return 正常終了時、E_OK
270 */
271ER
272i2c_deinit(I2C_Handle_t *hi2c)
273{
274 uint8_t no;
275
276 if(hi2c == NULL)
277 return E_PAR;
278 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_ENABLE), 0);
279 no = INDEX_I2C(hi2c->i2cid);
280 hi2c->status = I2C_STATUS_RESET;
281 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), (SYSCTL_CLK_EN_PERI_I2C0_CLK_EN<<no));
282 return E_OK;
283}
284
285/*
286 * I2Cスレーブ受信
287 * parameter1 hi2c: I2Cハンドラへのポインタ
288 * parameter2 pData: 読み出しバッファへのポインタ
289 * parameter3 Size: 読み出しサイズ
290 * return 正常終了ならE_OK
291 */
292ER
293i2c_slaveread(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size)
294{
295 ER ercd = E_OK;
296 uint32_t tmp;
297
298 if(hi2c == NULL || pData == NULL || Size == 0)
299 return E_PAR;
300 if(hi2c->status != I2C_STATUS_READY)
301 return E_OBJ;
302
303 /*
304 * 読み出しロック
305 */
306 if(hi2c->Init.semlock != 0)
307 wai_sem(hi2c->Init.semlock);
308
309 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
310 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
311
312 hi2c->aXferSize = 0;
313 hi2c->aXferCount = 0;
314 hi2c->pBuffPtr = pData;
315 hi2c->XferSize = Size;
316 hi2c->XferCount = 0;
317 hi2c->tXferCount = Size;
318 hi2c->status = I2C_STATUS_BUSY_RX;
319 sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
320
321 i2c_recv_data(hi2c);
322 ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
323
324 /*
325 * 読み出しロック解除
326 */
327 if(hi2c->Init.semlock != 0)
328 sig_sem(hi2c->Init.semlock);
329 return ercd;
330}
331
332/*
333 * I2Cスレーブ送信
334 * parameter1 hi2c: I2Cハンドラへのポインタ
335 * parameter2 pData: 読み出しバッファへのポインタ
336 * parameter3 Size: 読み出しサイズ
337 * return 正常終了ならE_OK
338 */
339ER
340i2c_slavewrite(I2C_Handle_t *hi2c, uint8_t *pData, uint16_t Size)
341{
342 ER ercd = E_OK;
343 uint32_t tmp;
344
345 if(hi2c == NULL || pData == NULL || Size == 0)
346 return E_PAR;
347 if(hi2c->status != I2C_STATUS_READY)
348 return E_OBJ;
349
350 /*
351 * 書き込みロック
352 */
353 if(hi2c->Init.semlock != 0)
354 wai_sem(hi2c->Init.semlock);
355
356 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
357 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
358
359 hi2c->aXferSize = 0;
360 hi2c->aXferCount = 0;
361 hi2c->pBuffPtr = pData;
362 hi2c->XferSize = Size;
363 hi2c->XferCount = 0;
364 hi2c->tXferCount = Size;
365 hi2c->status = I2C_STATUS_BUSY_TX;
366
367 i2c_send_data(hi2c);
368 sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
369 ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
370
371 while((sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)) & I2C_STATUS_TFE) == 0){
372 syslog_2(LOG_ERROR, "i2c_slavewrite status[%08x] abrt[%08x]", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)));
373 dly_tsk(50);
374 }
375
376 /*
377 * 書き込みロック解除
378 */
379 if(hi2c->Init.semlock != 0)
380 sig_sem(hi2c->Init.semlock);
381 return ercd;
382}
383
384/*
385 * I2Cデータリード
386 * parameter1 hi2c: I2Cハンドラへのポインタ
387 * parameter2 DevAddress: スレーブアドレス
388 * parameter3 MemAddress: メモリアドレス
389 * parameter4 MemAddSize: メモリアドレスサイズ
390 * parameter5 pData: 読み出しバッファへのポインタ
391 * parameter6 Size: 読み出しサイズ
392 * return 正常終了ならE_OK
393 */
394ER
395i2c_memread(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
396{
397 ER ercd = E_OK;
398 int32_t send_buf_len, timeout = I2C_TIMEOUT;
399 uint32_t fifo_len, abrt, i, tmp;
400
401 if(hi2c == NULL || pData == NULL || Size == 0)
402 return E_PAR;
403 if(hi2c->status != I2C_STATUS_READY)
404 return E_OBJ;
405
406 /*
407 * 読み出しロック
408 */
409 if(hi2c->Init.semlock != 0)
410 wai_sem(hi2c->Init.semlock);
411
412 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
413 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
414
415 if(MemAddSize == 2){
416 hi2c->aBuffer[0] = (uint8_t)(MemAddress >> 8);
417 hi2c->aBuffer[1] = (uint8_t)MemAddress;
418 }
419 else if(MemAddSize == 1)
420 hi2c->aBuffer[0] = (uint8_t)MemAddress;
421 hi2c->aXferSize = MemAddSize;
422 hi2c->aXferCount = 0;
423 hi2c->pBuffPtr = pData;
424 hi2c->XferSize = Size;
425 hi2c->XferCount = 0;
426 hi2c->tXferCount = Size;
427 hi2c->status = I2C_STATUS_BUSY_RX;
428
429 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), DevAddress/2);
430 while(hi2c->aXferSize > hi2c->aXferCount){
431 send_buf_len = hi2c->aXferSize - hi2c->aXferCount;
432 fifo_len = 8 - sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TXFLR));
433 fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
434 if(fifo_len == 0){
435 dly_tsk(1);
436 if(--timeout == 0){
437 hi2c->ErrorCode = I2C_ERROR_TIMEOUT;
438 if(hi2c->Init.semlock != 0)
439 sig_sem(hi2c->Init.semlock);
440 return E_TMOUT;
441 }
442 }
443 for(i = 0 ; i < fifo_len; i++)
444 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_DATA_CMD), hi2c->aBuffer[hi2c->aXferCount++]);
445 if((abrt = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE))) != 0){
446 hi2c->ErrorCode = abrt;
447 if(hi2c->Init.semlock != 0)
448 sig_sem(hi2c->Init.semlock);
449 return E_SYS;
450 }
451 hi2c->aXferCount += fifo_len;
452 }
453 sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
454
455 i2c_recv_data(hi2c);
456 ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
457
458 /*
459 * 読み出しロック解除
460 */
461 if(hi2c->Init.semlock != 0)
462 sig_sem(hi2c->Init.semlock);
463 return ercd;
464}
465
466/*
467 * I2Cデータライト
468 * parameter1 hi2c: I2Cハンドラへのポインタ
469 * parameter2 DevAddress: スレーブアドレス
470 * parameter3 MemAddress: メモリアドレス
471 * parameter4 MemAddSize: メモリアドレスサイズ
472 * parameter5 pData: 書込みバッファへのポインタ
473 * parameter6 Size: 書込みサイズ
474 * return 正常終了ならE_OK
475 */
476ER
477i2c_memwrite(I2C_Handle_t *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
478{
479 ER ercd;
480 uint32_t tmp;
481
482 if(hi2c == NULL || pData == NULL || Size == 0)
483 return E_PAR;
484 if(hi2c->status != I2C_STATUS_READY)
485 return E_OBJ;
486
487 /*
488 * 書き込みロック
489 */
490 if(hi2c->Init.semlock != 0)
491 wai_sem(hi2c->Init.semlock);
492
493 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT));
494 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_TX_ABRT), tmp);
495
496 if(MemAddSize == 2){
497 hi2c->aBuffer[0] = (uint8_t)(MemAddress >> 8);
498 hi2c->aBuffer[1] = (uint8_t)MemAddress;
499 }
500 else if(MemAddSize == 1)
501 hi2c->aBuffer[0] = (uint8_t)MemAddress;
502 hi2c->aXferSize = MemAddSize;
503 hi2c->aXferCount = 0;
504 hi2c->pBuffPtr = pData;
505 hi2c->XferSize = Size;
506 hi2c->XferCount = 0;
507 hi2c->tXferCount = MemAddSize + Size;
508 hi2c->status = I2C_STATUS_BUSY_TX;
509
510 sil_wrw_mem((uint32_t *)(hi2c->base+TOFF_I2C_TAR), DevAddress/2);
511 i2c_send_data(hi2c);
512 sil_orw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
513 ercd = i2c_transwait(hi2c, I2C_TIMEOUT);
514
515 while((sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)) & I2C_STATUS_TFE) == 0){
516 syslog_2(LOG_NOTICE, "i2c_memwrite status[%08x] abrt[%08x]", sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS)), sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE)));
517 dly_tsk(100);
518 }
519
520 /*
521 * 書き込みロック解除
522 */
523 if(hi2c->Init.semlock != 0)
524 sig_sem(hi2c->Init.semlock);
525 return ercd;
526}
527
528/*
529 * I2C割込みハンドラ
530 */
531void
532i2c_isr(intptr_t exinf)
533{
534 I2C_Handle_t *hi2c = &i2cHandle[INDEX_I2C(exinf)];
535 uint32_t istatus = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_STAT));
536 uint32_t abrt = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_TX_ABRT_SOURCE));
537 uint32_t status = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_STATUS));
538 uint32_t tmp;
539 syslog_3(LOG_DEBUG, "i2c_isr[%08x] abrt[%08x] status[%08x]", istatus, abrt, status);
540 if(istatus & I2C_INTR_STAT_START_DET){
541 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_START_DET));
542 }
543 if(istatus & I2C_INTR_STAT_STOP_DET){
544 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_STOP_DET));
545 if((status & I2C_STATUS_ACTIVITY) == 0){
546 hi2c->status = I2C_STATUS_READY;
547 hi2c->ErrorCode = abrt;
548 if(abrt != 0 && hi2c->errorcallback != NULL)
549 hi2c->errorcallback(hi2c);
550 if(hi2c->Init.semid != 0)
551 isig_sem(hi2c->Init.semid);
552 }
553 }
554 if(istatus & I2C_INTR_STAT_TX_EMPTY){
555 tmp = sil_rew_mem((uint32_t *)(hi2c->base+I2C_INTR_STAT_TX_EMPTY));
556 if(abrt != 0){
557 hi2c->status = I2C_STATUS_READY;
558 hi2c->ErrorCode = abrt;
559 if(hi2c->errorcallback != NULL)
560 hi2c->errorcallback(hi2c);
561 hi2c->tXferCount = 0;
562 }
563 else if(hi2c->status == I2C_STATUS_BUSY_TX){
564 if(hi2c->tXferCount > 0)
565 i2c_send_data(hi2c);
566 }
567 if(hi2c->tXferCount == 0){
568 sil_andw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_TX_EMPTY);
569 if(hi2c->writecallback != NULL)
570 hi2c->writecallback(hi2c);
571 }
572 }
573 if(istatus & I2C_INTR_STAT_RX_FULL){
574 if(abrt != 0){
575 hi2c->status = I2C_STATUS_READY;
576 hi2c->ErrorCode = abrt;
577 if(hi2c->errorcallback != NULL)
578 hi2c->errorcallback(hi2c);
579 hi2c->tXferCount = 0;
580 hi2c->XferCount = hi2c->XferSize;
581 }
582 else if(hi2c->status == I2C_STATUS_BUSY_RX){
583 if(hi2c->XferSize > hi2c->XferCount)
584 i2c_recv_data(hi2c);
585 }
586 if(hi2c->XferSize <= hi2c->XferCount){
587 sil_andw_mem((uint32_t *)(hi2c->base+TOFF_I2C_INTR_MASK), I2C_INTR_MASK_RX_FULL);
588 if(hi2c->readcallback != NULL)
589 hi2c->readcallback(hi2c);
590 }
591 }
592 if(istatus & I2C_INTR_STAT_RD_REQ){
593 tmp = sil_rew_mem((uint32_t *)(hi2c->base+TOFF_I2C_CLR_RD_REQ));
594 }
595 (void)(tmp);
596}
597
Note: See TracBrowser for help on using the repository browser.