]> git.sur5r.net Git - freertos/blob
49b4da4177c9ae2b4849a93d536f30b1623a51f3
[freertos] /
1 /***************************************************************************//**\r
2  * @file em_i2c.h\r
3  * @brief Inter-intergrated circuit (I2C) peripheral API\r
4  * @version 4.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
21  * obligation to support this Software. Silicon Labs is providing the\r
22  * Software "AS IS", with no express or implied warranties of any kind,\r
23  * including, but not limited to, any implied warranties of merchantability\r
24  * or fitness for any particular purpose or warranties against infringement\r
25  * of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Labs will not be liable for any consequential, incidental, or\r
28  * special damages, or any other relief, or for any claim by any third party,\r
29  * arising from your use of this Software.\r
30  *\r
31  ******************************************************************************/\r
32 \r
33 \r
34 #ifndef __SILICON_LABS_EM_I2C_H_\r
35 #define __SILICON_LABS_EM_I2C_H_\r
36 \r
37 #include "em_device.h"\r
38 #if defined(I2C_COUNT) && (I2C_COUNT > 0)\r
39 \r
40 #include <stdbool.h>\r
41 \r
42 #ifdef __cplusplus\r
43 extern "C" {\r
44 #endif\r
45 \r
46 /***************************************************************************//**\r
47  * @addtogroup EM_Library\r
48  * @{\r
49  ******************************************************************************/\r
50 \r
51 /***************************************************************************//**\r
52  * @addtogroup I2C\r
53  * @{\r
54  ******************************************************************************/\r
55 \r
56 /*******************************************************************************\r
57  *******************************   DEFINES   ***********************************\r
58  ******************************************************************************/\r
59 \r
60 /**\r
61  * @brief\r
62  *   Standard mode max frequency assuming using 4:4 ratio for Nlow:Nhigh.\r
63  * @details\r
64  *   From I2C specification: Min Tlow = 4.7us, min Thigh = 4.0us,\r
65  *   max Trise=1.0us, max Tfall=0.3us. Since ratio is 4:4, have to use\r
66  *   worst case value of Tlow or Thigh as base.\r
67  *\r
68  *   1/(Tlow + Thigh + 1us + 0.3us) = 1/(4.7 + 4.7 + 1.3)us = 93458Hz\r
69  * @note\r
70  *   Due to chip characteristics, the max value is somewhat reduced.\r
71  */\r
72 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_TINY_FAMILY) \\r
73     || defined(_EFM32_ZERO_FAMILY) || defined(_EFM32_HAPPY_FAMILY)\r
74 #define I2C_FREQ_STANDARD_MAX    93000\r
75 \r
76 #elif defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
77 #define I2C_FREQ_STANDARD_MAX    92000\r
78 \r
79 #else\r
80 #error "Unknown device family."\r
81 #endif\r
82 \r
83 /**\r
84  * @brief\r
85  *   Fast mode max frequency assuming using 6:3 ratio for Nlow:Nhigh.\r
86  * @details\r
87  *   From I2C specification: Min Tlow = 1.3us, min Thigh = 0.6us,\r
88  *   max Trise=0.3us, max Tfall=0.3us. Since ratio is 6:3, have to use\r
89  *   worst case value of Tlow or 2xThigh as base.\r
90  *\r
91  *   1/(Tlow + Thigh + 0.3us + 0.3us) = 1/(1.3 + 0.65 + 0.6)us = 392157Hz\r
92  */\r
93 #define I2C_FREQ_FAST_MAX        392157\r
94 \r
95 \r
96 /**\r
97  * @brief\r
98  *   Fast mode+ max frequency assuming using 11:6 ratio for Nlow:Nhigh.\r
99  * @details\r
100  *   From I2C specification: Min Tlow = 0.5us, min Thigh = 0.26us,\r
101  *   max Trise=0.12us, max Tfall=0.12us. Since ratio is 11:6, have to use\r
102  *   worst case value of Tlow or (11/6)xThigh as base.\r
103  *\r
104  *   1/(Tlow + Thigh + 0.12us + 0.12us) = 1/(0.5 + 0.273 + 0.24)us = 987167Hz\r
105  */\r
106 #define I2C_FREQ_FASTPLUS_MAX    987167\r
107 \r
108 \r
109 /**\r
110  * @brief\r
111  *   Indicate plain write sequence: S+ADDR(W)+DATA0+P.\r
112  * @details\r
113  *   @li S - Start\r
114  *   @li ADDR(W) - address with W/R bit cleared\r
115  *   @li DATA0 - Data taken from buffer with index 0\r
116  *   @li P - Stop\r
117  */\r
118 #define I2C_FLAG_WRITE          0x0001\r
119 \r
120 /**\r
121  * @brief\r
122  *   Indicate plain read sequence: S+ADDR(R)+DATA0+P.\r
123  * @details\r
124  *   @li S - Start\r
125  *   @li ADDR(R) - address with W/R bit set\r
126  *   @li DATA0 - Data read into buffer with index 0\r
127  *   @li P - Stop\r
128  */\r
129 #define I2C_FLAG_READ           0x0002\r
130 \r
131 /**\r
132  * @brief\r
133  *   Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P.\r
134  * @details\r
135  *   @li S - Start\r
136  *   @li Sr - Repeated start\r
137  *   @li ADDR(W) - address with W/R bit cleared\r
138  *   @li ADDR(R) - address with W/R bit set\r
139  *   @li DATAn - Data written from/read into buffer with index n\r
140  *   @li P - Stop\r
141  */\r
142 #define I2C_FLAG_WRITE_READ     0x0004\r
143 \r
144 /**\r
145  * @brief\r
146  *   Indicate write sequence using two buffers: S+ADDR(W)+DATA0+DATA1+P.\r
147  * @details\r
148  *   @li S - Start\r
149  *   @li ADDR(W) - address with W/R bit cleared\r
150  *   @li DATAn - Data written from buffer with index n\r
151  *   @li P - Stop\r
152  */\r
153 #define I2C_FLAG_WRITE_WRITE    0x0008\r
154 \r
155 /** Use 10 bit address. */\r
156 #define I2C_FLAG_10BIT_ADDR     0x0010\r
157 \r
158 \r
159 /*******************************************************************************\r
160  ********************************   ENUMS   ************************************\r
161  ******************************************************************************/\r
162 \r
163 /** Clock low to high ratio settings. */\r
164 typedef enum\r
165 {\r
166   i2cClockHLRStandard  = _I2C_CTRL_CLHR_STANDARD,      /**< Ratio is 4:4 */\r
167   i2cClockHLRAsymetric = _I2C_CTRL_CLHR_ASYMMETRIC,    /**< Ratio is 6:3 */\r
168   i2cClockHLRFast      = _I2C_CTRL_CLHR_FAST           /**< Ratio is 11:3 */\r
169 } I2C_ClockHLR_TypeDef;\r
170 \r
171 \r
172 /** Return codes for single master mode transfer function. */\r
173 typedef enum\r
174 {\r
175   /* In progress code (>0) */\r
176   i2cTransferInProgress = 1,    /**< Transfer in progress. */\r
177 \r
178   /* Complete code (=0) */\r
179   i2cTransferDone       = 0,    /**< Transfer completed successfully. */\r
180 \r
181   /* Transfer error codes (<0) */\r
182   i2cTransferNack       = -1,   /**< NACK received during transfer. */\r
183   i2cTransferBusErr     = -2,   /**< Bus error during transfer (misplaced START/STOP). */\r
184   i2cTransferArbLost    = -3,   /**< Arbitration lost during transfer. */\r
185   i2cTransferUsageFault = -4,   /**< Usage fault. */\r
186   i2cTransferSwFault    = -5    /**< SW fault. */\r
187 } I2C_TransferReturn_TypeDef;\r
188 \r
189 \r
190 /*******************************************************************************\r
191  *******************************   STRUCTS   ***********************************\r
192  ******************************************************************************/\r
193 \r
194 /** I2C initialization structure. */\r
195 typedef struct\r
196 {\r
197   /** Enable I2C peripheral when init completed. */\r
198   bool                 enable;\r
199 \r
200   /** Set to master (true) or slave (false) mode */\r
201   bool                 master;\r
202 \r
203   /**\r
204    * I2C reference clock assumed when configuring bus frequency setup.\r
205    * Set it to 0 if currently configurated reference clock shall be used\r
206    * This parameter is only applicable if operating in master mode.\r
207    */\r
208   uint32_t             refFreq;\r
209 \r
210   /**\r
211    * (Max) I2C bus frequency to use. This parameter is only applicable\r
212    * if operating in master mode.\r
213    */\r
214   uint32_t             freq;\r
215 \r
216   /** Clock low/high ratio control. */\r
217   I2C_ClockHLR_TypeDef clhr;\r
218 } I2C_Init_TypeDef;\r
219 \r
220 /** Suggested default config for I2C init structure. */\r
221 #define I2C_INIT_DEFAULT                                                    \\r
222   { true,                    /* Enable when init done */                    \\r
223     true,                    /* Set to master mode */                       \\r
224     0,                       /* Use currently configured reference clock */ \\r
225     I2C_FREQ_STANDARD_MAX,   /* Set to standard rate assuring being */      \\r
226                              /* within I2C spec */                          \\r
227     i2cClockHLRStandard      /* Set to use 4:4 low/high duty cycle */       \\r
228   }\r
229 \r
230 \r
231 /**\r
232  * @brief\r
233  *   Master mode transfer message structure used to define a complete\r
234  *   I2C transfer sequence (from start to stop).\r
235  * @details\r
236  *   The structure allows for defining the following types of sequences,\r
237  *   please refer to defines for sequence details.\r
238  *   @li #I2C_FLAG_READ - data read into buf[0].data\r
239  *   @li #I2C_FLAG_WRITE - data written from buf[0].data\r
240  *   @li #I2C_FLAG_WRITE_READ - data written from buf[0].data and read\r
241  *     into buf[1].data\r
242  *   @li #I2C_FLAG_WRITE_WRITE - data written from buf[0].data and\r
243  *     buf[1].data\r
244  */\r
245 typedef struct\r
246 {\r
247   /**\r
248    * @brief\r
249    *   Address to use after (repeated) start.\r
250    * @details\r
251    *   Layout details, A = address bit, X = don't care bit (set to 0):\r
252    *   @li 7 bit address - use format AAAA AAAX.\r
253    *   @li 10 bit address - use format XXXX XAAX AAAA AAAA\r
254    */\r
255   uint16_t addr;\r
256 \r
257   /** Flags defining sequence type and details, see I2C_FLAG_... defines. */\r
258   uint16_t flags;\r
259 \r
260   /**\r
261    * Buffers used to hold data to send from or receive into depending\r
262    * on sequence type.\r
263    */\r
264   struct\r
265   {\r
266     /** Buffer used for data to transmit/receive, must be @p len long. */\r
267     uint8_t  *data;\r
268 \r
269     /**\r
270      * Number of bytes in @p data to send or receive. Notice that when\r
271      * receiving data to this buffer, at least 1 byte must be received.\r
272      * Setting @p len to 0 in the receive case is considered a usage fault.\r
273      * Transmitting 0 bytes is legal, in which case only the address\r
274      * is transmitted after the start condition.\r
275      */\r
276     uint16_t len;\r
277   } buf[2];\r
278 } I2C_TransferSeq_TypeDef;\r
279 \r
280 \r
281 /*******************************************************************************\r
282  *****************************   PROTOTYPES   **********************************\r
283  ******************************************************************************/\r
284 \r
285 uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c);\r
286 void I2C_BusFreqSet(I2C_TypeDef *i2c,\r
287                     uint32_t refFreq,\r
288                     uint32_t freq,\r
289                     I2C_ClockHLR_TypeDef type);\r
290 void I2C_Enable(I2C_TypeDef *i2c, bool enable);\r
291 void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init);\r
292 \r
293 /***************************************************************************//**\r
294  * @brief\r
295  *   Clear one or more pending I2C interrupts.\r
296  *\r
297  * @param[in] i2c\r
298  *   Pointer to I2C peripheral register block.\r
299  *\r
300  * @param[in] flags\r
301  *   Pending I2C interrupt source to clear. Use a bitwse logic OR combination of\r
302  *   valid interrupt flags for the I2C module (I2C_IF_nnn).\r
303  ******************************************************************************/\r
304 __STATIC_INLINE void I2C_IntClear(I2C_TypeDef *i2c, uint32_t flags)\r
305 {\r
306   i2c->IFC = flags;\r
307 }\r
308 \r
309 \r
310 /***************************************************************************//**\r
311  * @brief\r
312  *   Disable one or more I2C interrupts.\r
313  *\r
314  * @param[in] i2c\r
315  *   Pointer to I2C peripheral register block.\r
316  *\r
317  * @param[in] flags\r
318  *   I2C interrupt sources to disable. Use a bitwise logic OR combination of\r
319  *   valid interrupt flags for the I2C module (I2C_IF_nnn).\r
320  ******************************************************************************/\r
321 __STATIC_INLINE void I2C_IntDisable(I2C_TypeDef *i2c, uint32_t flags)\r
322 {\r
323   i2c->IEN &= ~(flags);\r
324 }\r
325 \r
326 \r
327 /***************************************************************************//**\r
328  * @brief\r
329  *   Enable one or more I2C interrupts.\r
330  *\r
331  * @note\r
332  *   Depending on the use, a pending interrupt may already be set prior to\r
333  *   enabling the interrupt. Consider using I2C_IntClear() prior to enabling\r
334  *   if such a pending interrupt should be ignored.\r
335  *\r
336  * @param[in] i2c\r
337  *   Pointer to I2C peripheral register block.\r
338  *\r
339  * @param[in] flags\r
340  *   I2C interrupt sources to enable. Use a bitwise logic OR combination of\r
341  *   valid interrupt flags for the I2C module (I2C_IF_nnn).\r
342  ******************************************************************************/\r
343 __STATIC_INLINE void I2C_IntEnable(I2C_TypeDef *i2c, uint32_t flags)\r
344 {\r
345   i2c->IEN |= flags;\r
346 }\r
347 \r
348 \r
349 /***************************************************************************//**\r
350  * @brief\r
351  *   Get pending I2C interrupt flags.\r
352  *\r
353  * @note\r
354  *   The event bits are not cleared by the use of this function.\r
355  *\r
356  * @param[in] i2c\r
357  *   Pointer to I2C peripheral register block.\r
358  *\r
359  * @return\r
360  *   I2C interrupt sources pending. A bitwise logic OR combination of valid\r
361  *   interrupt flags for the I2C module (I2C_IF_nnn).\r
362  ******************************************************************************/\r
363 __STATIC_INLINE uint32_t I2C_IntGet(I2C_TypeDef *i2c)\r
364 {\r
365   return(i2c->IF);\r
366 }\r
367 \r
368 \r
369 /***************************************************************************//**\r
370  * @brief\r
371  *   Set one or more pending I2C interrupts from SW.\r
372  *\r
373  * @param[in] i2c\r
374  *   Pointer to I2C peripheral register block.\r
375  *\r
376  * @param[in] flags\r
377  *   I2C interrupt sources to set to pending. Use a bitwise logic OR combination\r
378  *   of valid interrupt flags for the I2C module (I2C_IF_nnn).\r
379  ******************************************************************************/\r
380 __STATIC_INLINE void I2C_IntSet(I2C_TypeDef *i2c, uint32_t flags)\r
381 {\r
382   i2c->IFS = flags;\r
383 }\r
384 \r
385 void I2C_Reset(I2C_TypeDef *i2c);\r
386 \r
387 /***************************************************************************//**\r
388  * @brief\r
389  *   Get slave address used for I2C peripheral (when operating in slave mode).\r
390  *\r
391  * @details\r
392  *   For 10 bit addressing mode, the address is split in two bytes, and only\r
393  *   the first byte setting is fetched, effectively only controlling the 2 most\r
394  *   significant bits of the 10 bit address. Full handling of 10 bit addressing\r
395  *   in slave mode requires additional SW handling.\r
396  *\r
397  * @param[in] i2c\r
398  *   Pointer to I2C peripheral register block.\r
399  *\r
400  * @return\r
401  *   I2C slave address in use. The 7 most significant bits define the actual\r
402  *   address, the least significant bit is reserved and always returned as 0.\r
403  ******************************************************************************/\r
404 __STATIC_INLINE uint8_t I2C_SlaveAddressGet(I2C_TypeDef *i2c)\r
405 {\r
406   return((uint8_t)(i2c->SADDR));\r
407 }\r
408 \r
409 \r
410 /***************************************************************************//**\r
411  * @brief\r
412  *   Set slave address to use for I2C peripheral (when operating in slave mode).\r
413  *\r
414  * @details\r
415  *   For 10 bit addressing mode, the address is split in two bytes, and only\r
416  *   the first byte is set, effectively only controlling the 2 most significant\r
417  *   bits of the 10 bit address. Full handling of 10 bit addressing in slave\r
418  *   mode requires additional SW handling.\r
419  *\r
420  * @param[in] i2c\r
421  *   Pointer to I2C peripheral register block.\r
422  *\r
423  * @param[in] addr\r
424  *   I2C slave address to use. The 7 most significant bits define the actual\r
425  *   address, the least significant bit is reserved and always set to 0.\r
426  ******************************************************************************/\r
427 __STATIC_INLINE void I2C_SlaveAddressSet(I2C_TypeDef *i2c, uint8_t addr)\r
428 {\r
429   i2c->SADDR = (uint32_t)addr & 0xfe;\r
430 }\r
431 \r
432 \r
433 /***************************************************************************//**\r
434  * @brief\r
435  *   Get slave address mask used for I2C peripheral (when operating in slave\r
436  *   mode).\r
437  *\r
438  * @details\r
439  *   The address mask defines how the comparator works. A bit position with\r
440  *   value 0 means that the corresponding slave address bit is ignored during\r
441  *   comparison (don't care). A bit position with value 1 means that the\r
442  *   corresponding slave address bit must match.\r
443  *\r
444  *   For 10 bit addressing mode, the address is split in two bytes, and only\r
445  *   the mask for the first address byte is fetched, effectively only\r
446  *   controlling the 2 most significant bits of the 10 bit address.\r
447  *\r
448  * @param[in] i2c\r
449  *   Pointer to I2C peripheral register block.\r
450  *\r
451  * @return\r
452  *   I2C slave address mask in use. The 7 most significant bits define the\r
453  *   actual address mask, the least significant bit is reserved and always\r
454  *   returned as 0.\r
455  ******************************************************************************/\r
456 __STATIC_INLINE uint8_t I2C_SlaveAddressMaskGet(I2C_TypeDef *i2c)\r
457 {\r
458   return((uint8_t)(i2c->SADDRMASK));\r
459 }\r
460 \r
461 \r
462 /***************************************************************************//**\r
463  * @brief\r
464  *   Set slave address mask used for I2C peripheral (when operating in slave\r
465  *   mode).\r
466  *\r
467  * @details\r
468  *   The address mask defines how the comparator works. A bit position with\r
469  *   value 0 means that the corresponding slave address bit is ignored during\r
470  *   comparison (don't care). A bit position with value 1 means that the\r
471  *   corresponding slave address bit must match.\r
472  *\r
473  *   For 10 bit addressing mode, the address is split in two bytes, and only\r
474  *   the mask for the first address byte is set, effectively only controlling\r
475  *   the 2 most significant bits of the 10 bit address.\r
476  *\r
477  * @param[in] i2c\r
478  *   Pointer to I2C peripheral register block.\r
479  *\r
480  * @param[in] mask\r
481  *   I2C slave address mask to use. The 7 most significant bits define the\r
482  *   actual address mask, the least significant bit is reserved and should\r
483  *   be 0.\r
484  ******************************************************************************/\r
485 __STATIC_INLINE void I2C_SlaveAddressMaskSet(I2C_TypeDef *i2c, uint8_t mask)\r
486 {\r
487   i2c->SADDRMASK = (uint32_t)mask & 0xfe;\r
488 }\r
489 \r
490 \r
491 I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c);\r
492 I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,\r
493                                             I2C_TransferSeq_TypeDef *seq);\r
494 \r
495 /** @} (end addtogroup I2C) */\r
496 /** @} (end addtogroup EM_Library) */\r
497 \r
498 #ifdef __cplusplus\r
499 }\r
500 #endif\r
501 \r
502 #endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */\r
503 #endif /* __SILICON_LABS_EM_I2C_H_ */\r