1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include "objects.h"
6 #include "PinNames.h"
7 #include "pinmap.h"
8 #include <drv/iic.h>
9
10 static const PinMap CSI_PinMap_I2C_SCL[] = {
11 {PA_25, (int32_t)I2C0_DEV, PIN_DATA(PullUp, PINMUX_FUNCTION_I2C)},
12 {NC, NC, 0}
13 };
14
15 static const PinMap CSI_PinMap_I2C_SDA[] = {
16 {PA_26, (int32_t)I2C0_DEV, PIN_DATA(PullUp, PINMUX_FUNCTION_I2C)},
17 {NC, NC, 0}
18 };
19
csi_iic_init(csi_iic_t * iic,uint32_t idx)20 csi_error_t csi_iic_init(csi_iic_t *iic, uint32_t idx)
21 {
22 if(idx != 0)
23 return CSI_ERROR;
24
25 if(!iic)
26 return CSI_ERROR;
27
28 iic->priv = (I2C_InitTypeDef *)malloc(sizeof(I2C_InitTypeDef));
29
30 uint32_t i2c_idx = idx;
31 I2C_TypeDef * I2Cx;
32 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
33
34 iic->dev.idx = i2c_idx;
35 iic->mode = I2C_MASTER_MODE;
36 I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
37
38 /* Set I2C Device Number */
39 I2C_InitStruct->I2CIdx = i2c_idx;
40
41 /* Load I2C default value */
42 I2C_StructInit(I2C_InitStruct);
43
44 /* Assign I2C Pin Mux */
45 I2C_InitStruct->I2CMaster = I2C_MASTER_MODE;
46 I2C_InitStruct->I2CSpdMod = I2C_SS_MODE;
47 I2C_InitStruct->I2CClk = 100;
48 I2C_InitStruct->I2CAckAddr = 0;
49
50 /* I2C Pin Mux Initialization */
51 PinName scl = CSI_PinMap_I2C_SCL[i2c_idx].pin;
52 PinName sda = CSI_PinMap_I2C_SDA[i2c_idx].pin;
53
54 printf("scl:%d,sda:%d\n",scl,sda);
55
56 Pinmux_Config(scl, PINMUX_FUNCTION_I2C);
57 Pinmux_Config(sda, PINMUX_FUNCTION_I2C);
58
59 PAD_PullCtrl(scl, GPIO_PuPd_UP);
60 PAD_PullCtrl(sda, GPIO_PuPd_UP);
61
62 /* I2C HAL Initialization */
63 I2C_Init(I2Cx, I2C_InitStruct);
64
65 /* Enable i2c master RESTART function */
66 I2Cx->IC_CON |= BIT_CTRL_IC_CON_IC_RESTART_EN;
67 /* I2C Enable Module */
68 I2C_Cmd(I2Cx, ENABLE);
69 return CSI_OK;
70 }
71
csi_iic_uninit(csi_iic_t * iic)72 void csi_iic_uninit(csi_iic_t *iic)
73 {
74 uint32_t i2c_idx = iic->dev.idx;
75
76 if(i2c_idx != 0)
77 return;
78
79 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
80
81 /* I2C Disable Module */
82 I2C_Cmd(I2Cx, DISABLE);
83
84 if(iic && iic->priv) {
85 free(iic->priv);
86 iic->priv = NULL;
87 }
88 }
89
csi_iic_mode(csi_iic_t * iic,csi_iic_mode_t mode)90 csi_error_t csi_iic_mode(csi_iic_t *iic, csi_iic_mode_t mode)
91 {
92 uint32_t i2c_idx = iic->dev.idx;
93
94 if(i2c_idx != 0)
95 return CSI_ERROR;
96
97 I2C_TypeDef *I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
98 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
99
100 I2C_Cmd(I2Cx, DISABLE);
101
102 iic->mode = mode;
103
104 if(mode == IIC_MODE_MASTER)
105 I2C_InitStruct->I2CMaster = I2C_MASTER_MODE;
106 else if(mode == IIC_MODE_SLAVE)
107 I2C_InitStruct->I2CMaster = I2C_SLAVE_MODE;
108
109 I2C_Init(I2Cx, I2C_InitStruct);
110 I2C_Cmd(I2Cx, ENABLE);
111 return CSI_OK;
112 }
113
csi_iic_addr_mode(csi_iic_t * iic,csi_iic_addr_mode_t addr_mode)114 csi_error_t csi_iic_addr_mode(csi_iic_t *iic, csi_iic_addr_mode_t addr_mode)
115 {
116 uint32_t i2c_idx = iic->dev.idx;
117
118 if(i2c_idx != 0)
119 return CSI_ERROR;
120
121 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
122 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
123
124 I2C_Cmd(I2Cx, DISABLE);
125
126 I2C_InitStruct->I2CAddrMod = addr_mode;
127 I2C_Init(I2Cx, I2C_InitStruct);
128
129 I2C_Cmd(I2Cx, ENABLE);
130 return CSI_OK;
131 }
132
csi_iic_speed(csi_iic_t * iic,csi_iic_speed_t speed)133 csi_error_t csi_iic_speed(csi_iic_t *iic, csi_iic_speed_t speed)
134 {
135 uint32_t i2c_idx = iic->dev.idx;
136
137 if(i2c_idx != 0)
138 return CSI_ERROR;
139
140 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
141 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
142
143 I2C_Cmd(I2Cx, DISABLE);
144
145 switch(speed) {
146 case IIC_BUS_SPEED_STANDARD:
147 I2C_InitStruct->I2CSpdMod = I2C_SS_MODE;
148 I2C_InitStruct->I2CClk = 100;
149 break;
150 case IIC_BUS_SPEED_FAST:
151 I2C_InitStruct->I2CSpdMod = I2C_FS_MODE;
152 I2C_InitStruct->I2CClk = 400;
153 break;
154 case IIC_BUS_SPEED_FAST_PLUS:
155 case IIC_BUS_SPEED_HIGH:
156 I2C_InitStruct->I2CSpdMod = I2C_HS_MODE;
157 I2C_InitStruct->I2CClk = 1000;
158 break;
159 default:
160 I2C_InitStruct->I2CSpdMod = I2C_SS_MODE;
161 I2C_InitStruct->I2CClk = 100;
162 }
163 I2C_Init(I2Cx, I2C_InitStruct);
164 I2C_Cmd(I2Cx, ENABLE);
165 return CSI_OK;
166 }
167
168 /**
169 * @brief Read data with special length in master mode through the I2Cx peripheral under in-house IP.
170 * @param I2Cx: where I2Cx can be I2C0_DEV .
171 * @param pBuf: point to the buffer to hold the received data.
172 * @param len: the length of data that to be received.
173 * @param timeout_ms: specifies timeout time, unit is ms.
174 * @retval the length of data read.
175 */
I2C_MasterRead_TimeOut(I2C_TypeDef * I2Cx,uint8_t * pBuf,uint8_t len,uint32_t timeout_ms)176 int32_t I2C_MasterRead_TimeOut(I2C_TypeDef *I2Cx, uint8_t* pBuf, uint8_t len, uint32_t timeout_ms)
177 {
178 int32_t cnt = 0;
179 uint32_t InTimeoutCount = 0;
180
181 /* read in the DR register the data to be received */
182 for(cnt = 0; cnt < len; cnt++) {
183 InTimeoutCount = timeout_ms*500;
184
185 if(cnt >= len - 1) {
186 /* generate stop singal */
187 I2Cx->IC_DATA_CMD = 0x0003 << 8;
188 } else {
189 I2Cx->IC_DATA_CMD = 0x0001 << 8;
190 }
191
192 /* wait for I2C_FLAG_RFNE flag */
193 while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_RFNE)) == 0) {
194 if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
195 I2C_ClearAllINT(I2Cx);
196 return cnt;
197 }
198
199 DelayUs(2);
200
201 if (InTimeoutCount == 0) {
202 printf("MasterRead_TimeOut\n");
203 return cnt;
204 }
205 InTimeoutCount--;
206 }
207
208 *pBuf++ = (uint8_t)I2Cx->IC_DATA_CMD;
209 }
210
211 return cnt;
212 }
213
214 /**
215 * @brief Write data with special length in master mode through the I2Cx peripheral under in-house IP.
216 * @param I2Cx: where I2Cx can be I2C0_DEV.
217 * @param pBuf: point to the data to be transmitted.
218 * @param len: the length of data that to be received.
219 * @param timeout_ms: specifies timeout time, unit is ms.
220 * @retval the length of data send.
221 */
I2C_MasterWrite_TimeOut(I2C_TypeDef * I2Cx,uint8_t * pBuf,uint8_t len,uint32_t timeout_ms,int32_t stop)222 int32_t I2C_MasterWrite_TimeOut(I2C_TypeDef *I2Cx, uint8_t* pBuf, uint8_t len, uint32_t timeout_ms, int32_t stop)
223 {
224 int32_t cnt = 0;
225 uint32_t InTimeoutCount = 0;
226
227 /* Write in the DR register the data to be sent */
228 for(cnt = 0; cnt < len; cnt++)
229 {
230 InTimeoutCount = timeout_ms*500;
231
232 while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFNF)) == 0);
233
234 if(cnt >= len - 1)
235 {
236 if(stop == 1) {
237 /*generate stop signal*/
238 I2Cx->IC_DATA_CMD = (*pBuf++) | (1 << 9);
239 } else {
240 /*generate restart signal*/
241 I2Cx->IC_DATA_CMD = (*pBuf++) | (1 << 10);
242 }
243 }
244 else
245 {
246 I2Cx->IC_DATA_CMD = (*pBuf++);
247 }
248
249 while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFE)) == 0) {
250 if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
251 printf(" TX_ABRT = %x\n", I2Cx->IC_TX_ABRT_SOURCE);
252 I2C_ClearAllINT(I2Cx);
253 return cnt;
254 }
255
256 DelayUs(2);
257
258 if (InTimeoutCount == 0) {
259 printf("MasterWrite_TimeOut\n");
260 return cnt;
261 }
262 InTimeoutCount--;
263 }
264 }
265
266 return cnt;
267 }
268
269 /**
270 * @brief Master sends single byte through the I2Cx peripheral to detect slave device.
271 * @param obj: i2c object defined in application software.
272 * @param address: the address of slave that to be detected.
273 * @param timeout_ms: specifies timeout time, unit is ms.
274 * @retval Slave ack condition:
275 * - 0: Slave available
276 * - -1: Slave not available
277 */
I2C_MasterSendNullData_TimeOut(I2C_TypeDef * I2Cx,int32_t address,uint32_t timeout_ms)278 int32_t I2C_MasterSendNullData_TimeOut(I2C_TypeDef *I2Cx, int32_t address, uint32_t timeout_ms)
279 {
280 uint8_t I2CTemp = (uint8_t)(address<<1);
281 I2C_MasterSendNullData(I2Cx, &I2CTemp, 0, 1, 0);
282
283 DelayMs(timeout_ms);
284
285 if(I2C_GetRawINT(I2Cx) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
286 I2C_ClearAllINT(I2Cx);
287
288 /* Wait for i2c enter trap state from trap_stop state*/
289 DelayUs(100);
290 I2C_Cmd(I2Cx, DISABLE);
291 I2C_Cmd(I2Cx, ENABLE);
292
293 return CSI_ERROR;
294 }
295 return CSI_OK;
296 }
297
csi_iic_master_send(csi_iic_t * iic,uint32_t devaddr,const void * data,uint32_t size,uint32_t timeout)298 int32_t csi_iic_master_send(csi_iic_t *iic,uint32_t devaddr,const void *data,uint32_t size,uint32_t timeout)
299 {
300 uint32_t i2c_idx = iic->dev.idx;
301
302 if(i2c_idx != 0)
303 return CSI_ERROR;
304
305 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
306 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
307
308 /* Check the parameters */
309 if(!IS_I2C_ALL_PERIPH(I2Cx))
310 return CSI_ERROR;
311
312 if (I2C_InitStruct->I2CAckAddr != devaddr) {
313 /* Deinit I2C first */
314 I2C_Cmd(I2Cx, DISABLE);
315
316 /* Load the user defined I2C target slave address */
317 I2C_InitStruct->I2CAckAddr = devaddr;
318
319 /* Init I2C now */
320 I2C_Init(I2Cx, I2C_InitStruct);
321 I2C_Cmd(I2Cx, ENABLE);
322 }
323
324 if(!size) {
325 return (I2C_MasterSendNullData_TimeOut(I2Cx, devaddr, timeout));
326 }
327
328 return (I2C_MasterWrite_TimeOut(I2Cx, (uint8_t*)data, size,timeout, 1));
329 }
330
csi_iic_master_receive(csi_iic_t * iic,uint32_t devaddr,void * data,uint32_t size,uint32_t timeout)331 int32_t csi_iic_master_receive(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size, uint32_t timeout)
332 {
333 uint32_t i2c_idx = iic->dev.idx;
334
335 if(i2c_idx != 0)
336 return CSI_ERROR;
337
338 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
339 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
340
341 /* Check the parameters */
342 if(!IS_I2C_ALL_PERIPH(I2Cx))
343 return CSI_ERROR;
344
345 if (I2C_InitStruct->I2CAckAddr != devaddr) {
346 /* Deinit I2C first */
347 I2C_Cmd(I2Cx, DISABLE);
348
349 /* Load the user defined I2C target slave address */
350 I2C_InitStruct->I2CAckAddr = devaddr;
351
352 /* Init I2C now */
353 I2C_Init(I2Cx, I2C_InitStruct);
354 I2C_Cmd(I2Cx, ENABLE);
355 }
356 return (I2C_MasterRead_TimeOut(I2Cx, (uint8_t*)data, size,timeout));
357 }
358
csi_iic_mem_send(csi_iic_t * iic,uint32_t devaddr,uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,const void * data,uint32_t size,uint32_t timeout)359 int32_t csi_iic_mem_send(csi_iic_t *iic, uint32_t devaddr,uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size,const void *data,uint32_t size,uint32_t timeout)
360 {
361 uint32_t i = 0;
362 int cnt = 0;
363 uint32_t i2c_idx = iic->dev.idx;
364 uint32_t mem_size;
365 char *buf = NULL;
366
367 if(i2c_idx != 0)
368 return CSI_ERROR;
369
370 buf = malloc(memaddr_size + size);
371 if(!buf) {
372 printf("malloc for i2c mem send fail\r\n");
373 return CSI_ERROR;
374 }
375
376 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
377 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
378
379 switch(memaddr_size) {
380 case IIC_MEM_ADDR_SIZE_8BIT:
381 mem_size = 1;
382 break;
383 case IIC_MEM_ADDR_SIZE_16BIT:
384 mem_size = 2;
385 break;
386 default:
387 mem_size = 1;
388 break;
389 }
390
391 /* Check the parameters */
392 if(!IS_I2C_ALL_PERIPH(I2Cx)) {
393 free(buf);
394 buf = NULL;
395 return CSI_ERROR;
396 }
397
398 if (I2C_InitStruct->I2CAckAddr != devaddr) {
399 /* Deinit I2C first */
400 I2C_Cmd(I2Cx, DISABLE);
401
402 /* Load the user defined I2C target slave address */
403 I2C_InitStruct->I2CAckAddr = devaddr;
404
405 /* Init I2C now */
406 I2C_Init(I2Cx, I2C_InitStruct);
407 I2C_Cmd(I2Cx, ENABLE);
408 }
409
410 if (mem_size == 1) {
411 buf[i++] = (memaddr) & 0xFF;
412 } else
413 buf[i++] = (memaddr >> 8) & 0xFF;
414
415 memcpy(&buf[i], data, size);
416
417 cnt = I2C_MasterWrite_TimeOut(I2Cx, (uint8_t*)buf, mem_size + size, timeout, 1);
418 free(buf);
419 buf = NULL;
420
421 if (cnt == (mem_size + size))
422 return size;
423 else
424 return cnt;
425 }
426
csi_iic_mem_receive(csi_iic_t * iic,uint32_t devaddr,uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,void * data,uint32_t size,uint32_t timeout)427 int32_t csi_iic_mem_receive(csi_iic_t *iic,uint32_t devaddr, uint16_t memaddr,csi_iic_mem_addr_size_t memaddr_size,void *data,uint32_t size,uint32_t timeout)
428 {
429 int cnt = 0;
430 uint32_t i2c_idx = iic->dev.idx;
431 uint32_t mem_size;
432
433 if(i2c_idx != 0)
434 return CSI_ERROR;
435
436 I2C_TypeDef * I2Cx = I2C_DEV_TABLE[i2c_idx].I2Cx;
437 I2C_InitTypeDef *I2C_InitStruct = (I2C_InitTypeDef *)iic->priv;
438
439 uint8_t memaddr_t[2];
440 memaddr_t[0] = (memaddr) & 0xFF;
441 memaddr_t[1] = (memaddr >> 8) & 0xFF;
442
443 switch(memaddr_size) {
444 case IIC_MEM_ADDR_SIZE_8BIT:
445 mem_size = 1;
446 break;
447 case IIC_MEM_ADDR_SIZE_16BIT:
448 mem_size = 2;
449 break;
450 default:
451 mem_size = 1;
452 break;
453 }
454
455 /* Check the parameters */
456 if(!IS_I2C_ALL_PERIPH(I2Cx))
457 return CSI_ERROR;
458
459 if (I2C_InitStruct->I2CAckAddr != devaddr) {
460 /* Deinit I2C first */
461 I2C_Cmd(I2Cx, DISABLE);
462
463 /* Load the user defined I2C target slave address */
464 I2C_InitStruct->I2CAckAddr = devaddr;
465
466 /* Init I2C now */
467 I2C_Init(I2Cx, I2C_InitStruct);
468 I2C_Cmd(I2Cx, ENABLE);
469 }
470
471 cnt = I2C_MasterWrite_TimeOut(I2Cx, memaddr_t, mem_size, timeout, 0);
472 cnt = I2C_MasterRead_TimeOut(I2Cx, (uint8_t *)data, size, timeout);
473 return cnt;
474 }
475