1 /**
2 *****************************************************************************
3 * @file cmem7_i2c.c
4 *
5 * @brief CMEM7 I2C source file
6 *
7 *
8 * @version V1.0
9 * @date 3. September 2013
10 *
11 * @note
12 *
13 *****************************************************************************
14 * @attention
15 *
16 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
17 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
18 * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
20 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
21 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
22 *
23 * <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2>
24 *****************************************************************************
25 */
26
27 #include "cmem7_i2c.h"
28
29 #define I2C_INNER_INT_ALL 0x3FF
30
31 typedef struct {
32 union {
33 uint32_t DATA_CMD;
34
35 struct {
36 uint32_t DATA : 8;
37 uint32_t RD_CMD : 1;
38 uint32_t WR_CMD : 1;
39 uint32_t WR_RD_CMD : 1;
40 } DATA_CMD_b;
41 } INNER;
42 } I2C_INNER_DATA_CMD;
43
i2c_GetClock(I2C0_Type * I2Cx)44 static uint32_t i2c_GetClock(I2C0_Type* I2Cx) {
45 uint32_t dividor;
46 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
47
48 if ((uint32_t)I2Cx == (uint32_t)I2C0) {
49 dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C0_CLK;
50 } else if ((uint32_t)I2Cx == (uint32_t)I2C1) {
51 dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C1_CLK;
52 }
53
54 return SYSTEM_CLOCK_FREQ / (1 << (dividor + 1));
55 }
56
i2c_NormalizeAddr(I2C0_Type * I2Cx,uint16_t addr)57 static uint16_t i2c_NormalizeAddr(I2C0_Type* I2Cx, uint16_t addr) {
58 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
59
60 if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
61 if (I2Cx->CTRL_b.MASTER_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
62 addr &= 0x007F;
63 } else {
64 addr &= 0x3FF;
65 }
66 }
67
68 if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
69 if (I2Cx->CTRL_b.SLAVE_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
70 addr &= 0x007F;
71 } else {
72 addr &= 0x3FF;
73 }
74 }
75
76 return addr;
77 }
78
i2c_ReadClear(uint32_t bit)79 static void i2c_ReadClear(uint32_t bit) {
80 uint32_t tmp;
81 tmp = bit;
82 tmp = tmp;
83 }
84
I2C_Init(I2C0_Type * I2Cx,I2C_InitTypeDef * I2C_Init)85 void I2C_Init(I2C0_Type* I2Cx, I2C_InitTypeDef* I2C_Init) {
86 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
87 assert_param(I2C_Init);
88 assert_param(IS_I2C_MODE(I2C_Init->I2C_Mode));
89 assert_param(IS_I2C_ADDR_WIDTH(I2C_Init->I2C_AddressWidth));
90
91 // reset
92 I2Cx->ENABLE_b.RESET = FALSE;
93 I2Cx->ENABLE_b.RESET = TRUE;
94
95 // clear interrupt
96 I2Cx->INT_MASK = I2C_INNER_INT_ALL;
97 i2c_ReadClear(I2Cx->CLR_ALL_INT_b.CLEAR);
98
99 I2Cx->CTRL_b.MODE = I2C_Init->I2C_Mode;
100 if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
101 I2Cx->CTRL_b.MASTER_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
102 I2Cx->TAR_b.START_BYTE = TRUE;
103 I2Cx->TAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
104 }
105 if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
106 I2Cx->CTRL_b.SLAVE_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
107 I2Cx->SAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
108 }
109
110 I2Cx->RX_TL_b.THRESHOLD = 0;
111 I2Cx->TX_TL_b.THRESHOLD = 0;
112
113 I2Cx->SLAVE_NACK_b.NACK = FALSE;
114
115 if (I2C_Init->timing) {
116 I2Cx->SCL_CNT_b.HIGH_LEVEL_TICK =
117 i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
118 I2Cx->SCL_CNT_b.LOW_LEVEL_TICK =
119 i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
120 I2Cx->SDA_SETUP_b.TSU_DAT = ((uint64_t)I2C_Init->timing->I2C_TsuDat) *
121 i2c_GetClock(I2Cx) / 1000000000;
122 I2Cx->SDA_SETUP_b.TSETUP = ((uint64_t)I2C_Init->timing->I2C_Tsetup) *
123 i2c_GetClock(I2Cx) / 1000000000;
124 I2Cx->TSU_STA_SETUP_b.TBUF = ((uint64_t)I2C_Init->timing->I2C_Tbuf) *
125 i2c_GetClock(I2Cx) / 1000000000;
126 I2Cx->TSU_STA_SETUP_b.TSU_STA = ((uint64_t)I2C_Init->timing->I2C_TsuSta) *
127 i2c_GetClock(I2Cx) / 1000000000;
128 I2Cx->TSU_STA_SETUP_b.SDA_FILTER_EN = I2C_Init->timing->I2C_SdaFilterEn;
129 I2Cx->TSU_STA_SETUP_b.SDA_FILTER_CNT = I2C_Init->timing->I2C_SdaFilterSpike;
130 I2Cx->TSU_STA_SETUP_b.SCL_FILTER_EN = I2C_Init->timing->I2C_SclFilterEn;
131 I2Cx->TSU_STA_SETUP_b.SCL_FILTER_CNT = I2C_Init->timing->I2C_SclFilterSpike;
132 }
133 }
134
I2C_Enable(I2C0_Type * I2Cx,BOOL enable)135 void I2C_Enable(I2C0_Type* I2Cx, BOOL enable) {
136 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
137
138 I2Cx->ENABLE_b.EN = enable;
139 }
140
I2C_EnableInt(I2C0_Type * I2Cx,uint32_t Int,BOOL enable)141 void I2C_EnableInt(I2C0_Type* I2Cx, uint32_t Int, BOOL enable) {
142 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
143 assert_param(IS_I2C_INT(Int));
144
145 if (enable) {
146 I2Cx->INT_MASK &= ~Int;
147 } else {
148 I2Cx->INT_MASK |= Int;
149 }
150 }
151
I2C_GetIntStatus(I2C0_Type * I2Cx,uint32_t Int)152 BOOL I2C_GetIntStatus(I2C0_Type* I2Cx, uint32_t Int) {
153 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
154 assert_param(IS_I2C_INT(Int));
155
156 if (0 != (I2Cx->INT_STATUS & Int)) {
157 return TRUE;
158 }
159
160 return FALSE;
161 }
I2C_ClearInt(I2C0_Type * I2Cx,uint32_t Int)162 void I2C_ClearInt(I2C0_Type* I2Cx, uint32_t Int) {
163 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
164 assert_param(IS_I2C_INT(Int));
165
166 if (Int == I2C_INT_RX_FIFO_NOT_EMPTY) {
167 // It can't be clear by sw but read data
168 }
169
170 if (Int == I2C_INT_RD_REQUEST) {
171 i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
172 }
173
174 if (Int == I2C_INT_TX_ABORT) {
175 i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
176 }
177
178 if (Int == I2C_INT_RX_DONE) {
179 i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
180 }
181
182 if (Int == I2C_INT_TX_DONE) {
183 i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
184 }
185 }
186
I2C_GetStatus(I2C0_Type * I2Cx,uint32_t Status)187 BOOL I2C_GetStatus(I2C0_Type* I2Cx, uint32_t Status) {
188 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
189 assert_param(IS_I2C_STATUS(Status));
190
191 if (0 != (I2Cx->STATUS & Status)) {
192 return TRUE;
193 }
194
195 return FALSE;
196 }
197
I2C_ClearStatus(I2C0_Type * I2Cx,uint32_t Status)198 void I2C_ClearStatus(I2C0_Type* I2Cx, uint32_t Status) {
199 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
200 assert_param(IS_I2C_STATUS(Status));
201
202 if (Status & I2C_STATUS_RX_FIFO_NOT_EMPTY) {
203 // It can't be clear by sw but read
204 }
205
206 if (Status & I2C_STATUS_RD_REQUEST) {
207 i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
208 }
209
210 if (Status & I2C_STATUS_TX_ABORT) {
211 i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
212 }
213
214 if (Status & I2C_STATUS_RX_DONE) {
215 i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
216 }
217
218 if (Status & I2C_STATUS_TX_DONE) {
219 i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
220 }
221 }
222
I2C_MasterReadReq(I2C0_Type * I2Cx,uint8_t size)223 BOOL I2C_MasterReadReq(I2C0_Type* I2Cx, uint8_t size) {
224 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
225
226 if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
227 return FALSE;
228 }
229
230 if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
231 return FALSE;
232 }
233
234 if (size == 0) {
235 return FALSE;
236 }
237
238 I2Cx->WRITE_READ_CNT_b.RD_BYTE_CNT = size;
239 if (size != 0) {
240 I2C_INNER_DATA_CMD inner;
241
242 inner.INNER.DATA_CMD_b.DATA = 0;
243 inner.INNER.DATA_CMD_b.RD_CMD = TRUE;
244 inner.INNER.DATA_CMD_b.WR_CMD = FALSE;
245 inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
246
247 I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
248 }
249
250 return TRUE;
251 }
252
I2C_ReadFifo(I2C0_Type * I2Cx,uint8_t size,uint8_t * data)253 uint8_t I2C_ReadFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
254 uint8_t count;
255
256 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
257 assert_param(data);
258
259 if (!I2Cx->ENABLE_b.EN) {
260 return 0;
261 }
262
263 count = 0;
264 while (I2Cx->STATUS_b.RX_FIFO_NOT_EMPTY && count < size) {
265 *(data + count++) = I2Cx->DATA_CMD_b.DATA;
266 }
267
268 return count;
269 }
270
I2C_WriteReq(I2C0_Type * I2Cx,uint8_t size,uint8_t firstData)271 BOOL I2C_WriteReq(I2C0_Type* I2Cx, uint8_t size, uint8_t firstData) {
272 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
273
274 if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
275 return FALSE;
276 }
277
278 if (size == 0) {
279 return FALSE;
280 }
281
282 I2Cx->WRITE_READ_CNT_b.WR_BYTE_CNT = size;
283 if (size != 0) {
284 I2C_INNER_DATA_CMD inner;
285
286 inner.INNER.DATA_CMD_b.DATA = firstData ;
287 inner.INNER.DATA_CMD_b.RD_CMD = FALSE;
288 inner.INNER.DATA_CMD_b.WR_CMD =
289 (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) ? FALSE : TRUE;
290 inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
291
292 I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
293 }
294
295 return TRUE;
296 }
297
I2C_WriteFifo(I2C0_Type * I2Cx,uint8_t size,uint8_t * data)298 uint8_t I2C_WriteFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
299 uint8_t count;
300
301 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
302 assert_param(data);
303
304 if (!I2Cx->ENABLE_b.EN) {
305 return 0;
306 }
307
308 count = 0;
309 while (I2Cx->STATUS_b.TX_FIFO_NOT_FULL && count < size) {
310 I2Cx->DATA_CMD_b.DATA = *(data + count++);
311 }
312
313 return count;
314 }
315
I2C_StopReq(I2C0_Type * I2Cx)316 BOOL I2C_StopReq(I2C0_Type* I2Cx) {
317 assert_param(IS_I2C_ALL_PERIPH(I2Cx));
318
319 udelay(600);
320
321 return TRUE;
322 }
323