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