ChibiOS  21.6.0
hal_i2c.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 /*
17  Concepts and parts of this file have been contributed by Uladzimir Pylinsky
18  aka barthess.
19  */
20 
21 /**
22  * @file hal_i2c.c
23  * @brief I2C Driver code.
24  *
25  * @addtogroup I2C
26  * @{
27  */
28 #include "hal.h"
29 
30 #if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
31 
32 /*===========================================================================*/
33 /* Driver local definitions. */
34 /*===========================================================================*/
35 
36 /*===========================================================================*/
37 /* Driver exported variables. */
38 /*===========================================================================*/
39 
40 /*===========================================================================*/
41 /* Driver local variables and types. */
42 /*===========================================================================*/
43 
44 /*===========================================================================*/
45 /* Driver local functions. */
46 /*===========================================================================*/
47 
48 /*===========================================================================*/
49 /* Driver exported functions. */
50 /*===========================================================================*/
51 
52 /**
53  * @brief I2C Driver initialization.
54  * @note This function is implicitly invoked by @p halInit(), there is
55  * no need to explicitly initialize the driver.
56  *
57  * @init
58  */
59 void i2cInit(void) {
60 
61  i2c_lld_init();
62 }
63 
64 /**
65  * @brief Initializes the standard part of a @p I2CDriver structure.
66  *
67  * @param[out] i2cp pointer to the @p I2CDriver object
68  *
69  * @init
70  */
71 void i2cObjectInit(I2CDriver *i2cp) {
72 
73  i2cp->state = I2C_STOP;
74  i2cp->config = NULL;
75 
76 #if I2C_USE_MUTUAL_EXCLUSION == TRUE
77  osalMutexObjectInit(&i2cp->mutex);
78 #endif
79 
80 #if defined(I2C_DRIVER_EXT_INIT_HOOK)
81  I2C_DRIVER_EXT_INIT_HOOK(i2cp);
82 #endif
83 }
84 
85 /**
86  * @brief Configures and activates the I2C peripheral.
87  *
88  * @param[in] i2cp pointer to the @p I2CDriver object
89  * @param[in] config pointer to the @p I2CConfig object
90  *
91  * @api
92  */
93 void i2cStart(I2CDriver *i2cp, const I2CConfig *config) {
94 
95  osalDbgCheck((i2cp != NULL) && (config != NULL));
96  osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
97  (i2cp->state == I2C_LOCKED), "invalid state");
98 
99  osalSysLock();
100  i2cp->config = config;
101  i2c_lld_start(i2cp);
102  i2cp->state = I2C_READY;
103  osalSysUnlock();
104 }
105 
106 /**
107  * @brief Deactivates the I2C peripheral.
108  *
109  * @param[in] i2cp pointer to the @p I2CDriver object
110  *
111  * @api
112  */
113 void i2cStop(I2CDriver *i2cp) {
114 
115  osalDbgCheck(i2cp != NULL);
116 
117  osalSysLock();
118 
119  osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
120  (i2cp->state == I2C_LOCKED), "invalid state");
121 
122  i2c_lld_stop(i2cp);
123  i2cp->config = NULL;
124  i2cp->state = I2C_STOP;
125 
126  osalSysUnlock();
127 }
128 
129 /**
130  * @brief Returns the errors mask associated to the previous operation.
131  *
132  * @param[in] i2cp pointer to the @p I2CDriver object
133  * @return The errors mask.
134  *
135  * @api
136  */
138 
139  osalDbgCheck(i2cp != NULL);
140 
141  return i2c_lld_get_errors(i2cp);
142 }
143 
144 /**
145  * @brief Sends data via the I2C bus.
146  * @details Function designed to realize "read-through-write" transfer
147  * paradigm. If you want transmit data without any further read,
148  * than set @b rxbytes field to 0.
149  *
150  * @param[in] i2cp pointer to the @p I2CDriver object
151  * @param[in] addr slave device address (7 bits) without R/W bit
152  * @param[in] txbuf pointer to transmit buffer
153  * @param[in] txbytes number of bytes to be transmitted
154  * @param[out] rxbuf pointer to receive buffer
155  * @param[in] rxbytes number of bytes to be received, set it to 0 if
156  * you want transmit only
157  * @param[in] timeout the number of ticks before the operation timeouts,
158  * the following special values are allowed:
159  * - @a TIME_INFINITE no timeout.
160  * .
161  *
162  * @return The operation status.
163  * @retval MSG_OK if the function succeeded.
164  * @retval MSG_RESET if one or more I2C errors occurred, the errors can
165  * be retrieved using @p i2cGetErrors().
166  * @retval MSG_TIMEOUT if a timeout occurred before operation end.
167  *
168  * @api
169  */
171  i2caddr_t addr,
172  const uint8_t *txbuf,
173  size_t txbytes,
174  uint8_t *rxbuf,
175  size_t rxbytes,
176  sysinterval_t timeout) {
177  msg_t rdymsg;
178 
179  osalDbgCheck((i2cp != NULL) &&
180  (txbytes > 0U) && (txbuf != NULL) &&
181  ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) &&
182  (timeout != TIME_IMMEDIATE));
183 
184  osalDbgAssert(i2cp->state == I2C_READY, "not ready");
185 
186  osalSysLock();
187  i2cp->errors = I2C_NO_ERROR;
188  i2cp->state = I2C_ACTIVE_TX;
189  rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes,
190  rxbuf, rxbytes, timeout);
191  if (rdymsg == MSG_TIMEOUT) {
192  i2cp->state = I2C_LOCKED;
193  }
194  else {
195  i2cp->state = I2C_READY;
196  }
197  osalSysUnlock();
198  return rdymsg;
199 }
200 
201 /**
202  * @brief Receives data from the I2C bus.
203  *
204  * @param[in] i2cp pointer to the @p I2CDriver object
205  * @param[in] addr slave device address (7 bits) without R/W bit
206  * @param[out] rxbuf pointer to receive buffer
207  * @param[in] rxbytes number of bytes to be received
208  * @param[in] timeout the number of ticks before the operation timeouts,
209  * the following special values are allowed:
210  * - @a TIME_INFINITE no timeout.
211  * .
212  *
213  * @return The operation status.
214  * @retval MSG_OK if the function succeeded.
215  * @retval MSG_RESET if one or more I2C errors occurred, the errors can
216  * be retrieved using @p i2cGetErrors().
217  * @retval MSG_TIMEOUT if a timeout occurred before operation end.
218  *
219  * @api
220  */
222  i2caddr_t addr,
223  uint8_t *rxbuf,
224  size_t rxbytes,
225  sysinterval_t timeout) {
226 
227  msg_t rdymsg;
228 
229  osalDbgCheck((i2cp != NULL) && (addr != 0U) &&
230  (rxbytes > 0U) && (rxbuf != NULL) &&
231  (timeout != TIME_IMMEDIATE));
232 
233  osalDbgAssert(i2cp->state == I2C_READY, "not ready");
234 
235  osalSysLock();
236  i2cp->errors = I2C_NO_ERROR;
237  i2cp->state = I2C_ACTIVE_RX;
238  rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout);
239  if (rdymsg == MSG_TIMEOUT) {
240  i2cp->state = I2C_LOCKED;
241  }
242  else {
243  i2cp->state = I2C_READY;
244  }
245  osalSysUnlock();
246  return rdymsg;
247 }
248 
249 #if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
250 /**
251  * @brief Gains exclusive access to the I2C bus.
252  * @details This function tries to gain ownership to the I2C bus, if the bus
253  * is already being used then the invoking thread is queued.
254  * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
255  * must be enabled.
256  *
257  * @param[in] i2cp pointer to the @p I2CDriver object
258  *
259  * @api
260  */
262 
263  osalDbgCheck(i2cp != NULL);
264 
265  osalMutexLock(&i2cp->mutex);
266 }
267 
268 /**
269  * @brief Releases exclusive access to the I2C bus.
270  * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
271  * must be enabled.
272  *
273  * @param[in] i2cp pointer to the @p I2CDriver object
274  *
275  * @api
276  */
278 
279  osalDbgCheck(i2cp != NULL);
280 
281  osalMutexUnlock(&i2cp->mutex);
282 }
283 #endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */
284 
285 #endif /* HAL_USE_I2C == TRUE */
286 
287 /** @} */
I2CDriver
Structure representing an I2C driver.
Definition: hal_i2c_lld.h:88
i2cMasterTransmitTimeout
msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout)
Sends data via the I2C bus.
Definition: hal_i2c.c:170
I2CDriver::config
const I2CConfig * config
Current configuration data.
Definition: hal_i2c_lld.h:96
i2c_lld_stop
void i2c_lld_stop(I2CDriver *i2cp)
Deactivates the I2C peripheral.
Definition: hal_i2c_lld.c:99
i2cReleaseBus
void i2cReleaseBus(I2CDriver *i2cp)
Releases exclusive access to the I2C bus.
Definition: hal_i2c.c:277
hal.h
HAL subsystem header.
I2C_ACTIVE_RX
@ I2C_ACTIVE_RX
Receiving.
Definition: hal_i2c.h:81
i2cGetErrors
i2cflags_t i2cGetErrors(I2CDriver *i2cp)
Returns the errors mask associated to the previous operation.
Definition: hal_i2c.c:137
i2c_lld_master_transmit_timeout
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout)
Transmits data via the I2C bus as master.
Definition: hal_i2c_lld.c:169
i2cStart
void i2cStart(I2CDriver *i2cp, const I2CConfig *config)
Configures and activates the I2C peripheral.
Definition: hal_i2c.c:93
I2C_STOP
@ I2C_STOP
Stopped.
Definition: hal_i2c.h:78
osalSysUnlock
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:611
msg_t
int32_t msg_t
Definition: chearly.h:88
i2cMasterReceiveTimeout
msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout)
Receives data from the I2C bus.
Definition: hal_i2c.c:221
osalMutexLock
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition: osal.c:384
I2C_READY
@ I2C_READY
Ready.
Definition: hal_i2c.h:79
i2cStop
void i2cStop(I2CDriver *i2cp)
Deactivates the I2C peripheral.
Definition: hal_i2c.c:113
i2cObjectInit
void i2cObjectInit(I2CDriver *i2cp)
Initializes the standard part of a I2CDriver structure.
Definition: hal_i2c.c:71
i2c_lld_get_errors
#define i2c_lld_get_errors(i2cp)
Get errors from I2C driver.
Definition: hal_i2c_lld.h:121
i2cAcquireBus
void i2cAcquireBus(I2CDriver *i2cp)
Gains exclusive access to the I2C bus.
Definition: hal_i2c.c:261
TIME_IMMEDIATE
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition: chtime.h:47
i2c_lld_master_receive_timeout
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout)
Receives data via the I2C bus as master.
Definition: hal_i2c_lld.c:133
I2C_ACTIVE_TX
@ I2C_ACTIVE_TX
Transmitting.
Definition: hal_i2c.h:80
i2c_lld_start
void i2c_lld_start(I2CDriver *i2cp)
Configures and activates the I2C peripheral.
Definition: hal_i2c_lld.c:79
i2caddr_t
uint16_t i2caddr_t
Type representing an I2C address.
Definition: hal_i2c_lld.h:63
i2cflags_t
uint32_t i2cflags_t
Type of I2C Driver condition flags.
Definition: hal_i2c_lld.h:68
I2CDriver::errors
i2cflags_t errors
Error flags.
Definition: hal_i2c_lld.h:100
osalDbgCheck
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:284
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
osalSysLock
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:601
i2c_lld_init
void i2c_lld_init(void)
Low level I2C driver initialization.
Definition: hal_i2c_lld.c:65
MSG_TIMEOUT
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition: chschd.h:40
I2C_NO_ERROR
#define I2C_NO_ERROR
No error.
Definition: hal_i2c.h:43
osalDbgAssert
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:264
I2CDriver::state
i2cstate_t state
Driver state.
Definition: hal_i2c_lld.h:92
I2C_LOCKED
@ I2C_LOCKED
Bus locked.
Definition: hal_i2c.h:82
osalMutexUnlock
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition: osal.c:404
osalMutexObjectInit
static void osalMutexObjectInit(mutex_t *mp)
Initializes s mutex_t object.
Definition: osal.h:753
I2CConfig
Type of I2C driver configuration structure.
Definition: hal_i2c_lld.h:75
i2cInit
void i2cInit(void)
I2C Driver initialization.
Definition: hal_i2c.c:59