Statistics
| Branch: | Tag: | Revision:

amiro-os / periphery-lld / periphAL.h @ 0ecf4119

History | View | Annotate | Download (20.536 KB)

1 e545e620 Thomas Schöpping
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3 84f0ce9e Thomas Schöpping
Copyright (C) 2016..2019  Thomas Schöpping et al.
4 e545e620 Thomas Schöpping

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19 6ff06bbf Thomas Schöpping
#ifndef AMIROOS_PERIPHAL_H
20
#define AMIROOS_PERIPHAL_H
21 e545e620 Thomas Schöpping
22 3940ba8a Thomas Schöpping
#include <amiro-lld.h>
23
24 e545e620 Thomas Schöpping
/*============================================================================*/
25
/* VERSION                                                                    */
26
/*============================================================================*/
27
28
/**
29
 * @brief   The periphery abstraction layer interface major version.
30
 * @note    Changes of the major version imply incompatibilities.
31
 */
32
#define PERIPHAL_VERSION_MAJOR    1
33
34
/**
35
 * @brief   The periphery abstraction layer interface minor version.
36
 * @note    A higher minor version implies new functionalty, but all old interfaces are still available.
37
 */
38 3106e8cc Thomas Schöpping
#define PERIPHAL_VERSION_MINOR    1
39 e545e620 Thomas Schöpping
40
/*============================================================================*/
41
/* DEPENDENCIES                                                               */
42
/*============================================================================*/
43
44 1f94ac64 Thomas Schöpping
#include <aosconf.h>
45 e545e620 Thomas Schöpping
#include <hal.h>
46
47
/*============================================================================*/
48 1f94ac64 Thomas Schöpping
/* DEBUG                                                                      */
49
/*============================================================================*/
50
51
#if (AMIROOS_CFG_DBG == true) || defined(__DOXYGEN__)
52
53 7de0cc90 Thomas Schöpping
#if defined(__cplusplus)
54 1f94ac64 Thomas Schöpping
extern "C" {
55 7de0cc90 Thomas Schöpping
#endif /* defined(__cplusplus) */
56 1f94ac64 Thomas Schöpping
  void _apalDbgAssertMsg(const bool c, const char* fmt, ...);
57
  void apalDbgPrintf(const char* fmt, ...);
58 7de0cc90 Thomas Schöpping
#if defined(__cplusplus)
59 1f94ac64 Thomas Schöpping
}
60 7de0cc90 Thomas Schöpping
#endif /* defined(__cplusplus) */
61 1f94ac64 Thomas Schöpping
62
/**
63
 * @brief Assert function to check a given condition.
64
 *
65
 * @param[in] c     The condition to check.
66
 */
67
#define apalDbgAssert(c)                                                      \
68
  _apalDbgAssertMsg(c, "%s(%u): apalDbgAssert failed", __FILE__, __LINE__);
69
70 7de0cc90 Thomas Schöpping
#else /* (AMIROOS_CFG_DBG != true) */
71 1f94ac64 Thomas Schöpping
72
#define apalDbgAssert(constition)
73
#define apalDbgAssertMsg(condition, fmt, ...)
74
#define apalDbgPrintf(fmt, ...)
75
76 7de0cc90 Thomas Schöpping
#endif /* (AMIROOS_CFG_DBG == true) */
77 1f94ac64 Thomas Schöpping
78
/*============================================================================*/
79 e545e620 Thomas Schöpping
/* GENERAL                                                                    */
80
/*============================================================================*/
81
82
/**
83
 * @brief Delay execution by a specific number of microseconds.
84
 *
85
 * @param[in]   us    Time to sleep until execution continues in microseconds.
86
 */
87
static inline void usleep(apalTime_t us)
88
{
89
  // check if the specified time can be represented by the system
90 1f94ac64 Thomas Schöpping
  apalDbgAssert(us <= chTimeI2US(TIME_INFINITE));
91 e545e620 Thomas Schöpping
92 3940ba8a Thomas Schöpping
  const sysinterval_t interval = chTimeUS2I(us);
93 e545e620 Thomas Schöpping
  // TIME_IMMEDIATE makes no sense and would even cause system halt
94 3940ba8a Thomas Schöpping
  if (interval != TIME_IMMEDIATE) {
95
    chThdSleep(interval);
96 e545e620 Thomas Schöpping
  }
97
  return;
98
}
99
100
/*============================================================================*/
101
/* GPIO                                                                       */
102
/*============================================================================*/
103
104 7de0cc90 Thomas Schöpping
#if (HAL_USE_PAL == TRUE) || defined (__DOXYGEN__)
105 e545e620 Thomas Schöpping
106
/**
107
 * @brief GPIO driver type.
108
 */
109
struct apalGpio_t {
110 3106e8cc Thomas Schöpping
  ioline_t line;
111 e545e620 Thomas Schöpping
} PACKED_VAR;
112
113
/**
114
 * @brief Read the current value of a GPIO pin.
115
 *
116
 * @param[in]   gpio  GPIO to read.
117
 * @param[out]  val   Current value of the GPIO.
118
 *
119
 * @return The status indicates whether the function call was successful.
120
 */
121
static inline apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val)
122
{
123 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
124
  apalDbgAssert(val != NULL);
125 e545e620 Thomas Schöpping
126 3106e8cc Thomas Schöpping
  *val = (palReadLine(gpio->line) == PAL_HIGH) ? APAL_GPIO_HIGH : APAL_GPIO_LOW;
127 e545e620 Thomas Schöpping
  return APAL_STATUS_OK;
128
}
129
130
/**
131
 * @brief Set the value of a GPIO pin.
132
 *
133
 * @param[in] gpio  GPIO to write.
134
 * @param[in] val   Value to set for the GPIO.
135
 *
136
 * @return The status indicates whether the function call was successful.
137
 */
138
static inline apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val)
139
{
140 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
141 e545e620 Thomas Schöpping
142 3106e8cc Thomas Schöpping
  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
143 e545e620 Thomas Schöpping
  syssts_t sysstatus = chSysGetStatusAndLockX();
144 3106e8cc Thomas Schöpping
  palWriteLine(gpio->line, (val == APAL_GPIO_HIGH) ? PAL_HIGH : PAL_LOW);
145 e545e620 Thomas Schöpping
  chSysRestoreStatusX(sysstatus);
146
  return APAL_STATUS_OK;
147
}
148
149
/**
150
 * @brief Toggle the output of a GPIO.
151
 *
152
 * @param[in] gpio  GPIO to toggle.
153
 *
154
 * @return The status indicates whether the function call was successful.
155
 */
156
static inline apalExitStatus_t apalGpioToggle(apalGpio_t* gpio)
157
{
158 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
159 e545e620 Thomas Schöpping
160 3106e8cc Thomas Schöpping
  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
161 e545e620 Thomas Schöpping
  syssts_t sysstatus = chSysGetStatusAndLockX();
162 3106e8cc Thomas Schöpping
  palWriteLine(gpio->line, (palReadLine(gpio->line) == PAL_HIGH) ? PAL_LOW : PAL_HIGH);
163 e545e620 Thomas Schöpping
  chSysRestoreStatusX(sysstatus);
164
  return APAL_STATUS_OK;
165
}
166
167
/**
168
 * @brief Get the current on/off state of a control GPIO.
169
 *
170
 * @param[in]   gpio  Control GPIO to read.
171
 * @param[out]  val   Current activation status of the control GPIO.
172
 *
173
 * @return The status indicates whether the function call was successful.
174
 */
175
static inline apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val)
176
{
177 1f94ac64 Thomas Schöpping
  apalDbgAssert(cgpio != NULL);
178
  apalDbgAssert(cgpio->gpio != NULL);
179
  apalDbgAssert(val != NULL);
180 e545e620 Thomas Schöpping
181 3106e8cc Thomas Schöpping
  *val = ((palReadLine(cgpio->gpio->line) == PAL_HIGH) ^ (cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH)) ? APAL_GPIO_OFF : APAL_GPIO_ON;
182 e545e620 Thomas Schöpping
  return APAL_STATUS_OK;
183
}
184
185
/**
186
 * @brief Turn a control GPIO 'on' or 'off' respectively.
187
 *
188
 * @param[in] gpio  Control GPIO to set.
189
 * @param[in] val   Activation value to set for the control GPIO.
190
 *
191
 * @return The status indicates whether the function call was successful.
192
 */
193
static inline apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val)
194
{
195 1f94ac64 Thomas Schöpping
  apalDbgAssert(cgpio != NULL);
196
  apalDbgAssert(cgpio->gpio != NULL);
197
  apalDbgAssert(cgpio->meta.direction == APAL_GPIO_DIRECTION_OUTPUT || cgpio->meta.direction == APAL_GPIO_DIRECTION_BIDIRECTIONAL);
198 e545e620 Thomas Schöpping
199 3106e8cc Thomas Schöpping
  // palWriteLine() is not guaranteed to be atomic, thus the scheduler is locked.
200 e545e620 Thomas Schöpping
  syssts_t sysstatus = chSysGetStatusAndLockX();
201 3106e8cc Thomas Schöpping
  palWriteLine(cgpio->gpio->line, ((cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH) ^ (val == APAL_GPIO_ON)) ? PAL_LOW : PAL_HIGH);
202 e545e620 Thomas Schöpping
  chSysRestoreStatusX(sysstatus);
203
  return APAL_STATUS_OK;
204
}
205
206
/**
207 1e5f7648 Thomas Schöpping
 * @brief   Converts an apalGpioEdge_t to an ChibiOS PAL edge.
208 e545e620 Thomas Schöpping
 */
209 1e5f7648 Thomas Schöpping
#define APAL2CH_EDGE(edge)                                            \
210
  ((edge == APAL_GPIO_EDGE_RISING) ? PAL_EVENT_MODE_RISING_EDGE :     \
211
    (edge == APAL_GPIO_EDGE_FALLING) ? PAL_EVENT_MODE_FALLING_EDGE :  \
212 542939ea Thomas Schöpping
     (edge == APAL_GPIO_EDGE_BOTH) ? PAL_EVENT_MODE_BOTH_EDGES :      \
213
      PAL_EVENT_MODE_DISABLED)
214 e545e620 Thomas Schöpping
215 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_PAL == TRUE) */
216 e545e620 Thomas Schöpping
217
/*============================================================================*/
218
/* PWM                                                                        */
219
/*============================================================================*/
220
221 7de0cc90 Thomas Schöpping
#if (HAL_USE_PWM == TRUE) || defined (__DOXYGEN__)
222 e545e620 Thomas Schöpping
223
/**
224
 * @brief PWM driver type.
225
 */
226
typedef PWMDriver apalPWMDriver_t;
227
228
/**
229
 * @brief   Set the PWM with given parameters.
230
 *
231
 * @param[in] pwm       PWM driver to set.
232
 * @param[in] channel   Channel of the PWM driver to set.
233
 * @param[in] width     Width to set the channel to.
234
 *
235
 * @return  The status indicates whether the function call was successful.
236
 */
237
static inline apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width)
238
{
239 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
240 e545e620 Thomas Schöpping
241
  pwmEnableChannel(pwm, (pwmchannel_t)channel, pwm->period * ((float)width / (float)APAL_PWM_WIDTH_MAX) + 0.5f);
242
  return APAL_STATUS_OK;
243
}
244
245
/**
246
 * @brief   Retrieve the current frequency of the PWM.
247
 *
248
 * @param[in]  pwm        PWM driver to read.
249
 * @param[out] frequency  The currently set frequency.
250
 *
251
 * @return  The status indicates whether the function call was successful.
252
 */
253
static inline apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency)
254
{
255 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
256
  apalDbgAssert(frequency != NULL);
257 e545e620 Thomas Schöpping
258
  *frequency = pwm->config->frequency;
259
  return APAL_STATUS_OK;
260
}
261
262
/**
263
 * @brief   Retrieve the current period of the PWM.
264
 *
265
 * @param[in]   pwm     PWM driver to read.
266
 * @param[out]  period  The currently set period.
267
 *
268
 * @return  The status indicates whether the function call was successful.
269
 */
270
static inline apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period)
271
{
272 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
273
  apalDbgAssert(period != NULL);
274 e545e620 Thomas Schöpping
275
  *period = pwm->period;
276
  return APAL_STATUS_OK;
277
}
278
279 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_PWM == TRUE) */
280 e545e620 Thomas Schöpping
281
/*============================================================================*/
282
/* QEI                                                                        */
283
/*============================================================================*/
284
285 7de0cc90 Thomas Schöpping
#if (HAL_USE_QEI == TRUE) || defined (__DOXYGEN__)
286 e545e620 Thomas Schöpping
287
/**
288
 * @brief QEI driver type.
289
 */
290
typedef QEIDriver apalQEIDriver_t;
291
292
/**
293
 * @brief Gets the direction of the last transition.
294
 *
295
 * @param[in]   qei         The QEI driver to use.
296
 * @param[out]  direction   The direction of the last transition.
297
 *
298
 * @return The status indicates whether the function call was successful.
299
 */
300
static inline apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction)
301
{
302 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
303
  apalDbgAssert(direction != NULL);
304 e545e620 Thomas Schöpping
305
  *direction = (qei_lld_get_direction(qei)) ? APAL_QEI_DIRECTION_DOWN : APAL_QEI_DIRECTION_UP;
306
307
  return APAL_STATUS_OK;
308
}
309
310
/**
311
 * @brief Gets the current position of the ecnoder.
312
 *
313
 * @param[in]   qei       The QEI driver to use.
314
 * @param[out]  position  The current position of the encoder.
315
 *
316
 * @return The status indicates whether the function call was successful.
317
 */
318
static inline apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position)
319
{
320 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
321
  apalDbgAssert(position != NULL);
322 e545e620 Thomas Schöpping
323
  *position = qei_lld_get_position(qei);
324
325
  return APAL_STATUS_OK;
326
}
327
328
/**
329
 * @brief Gets the value range of the encoder.
330
 *
331
 * @param[in]   qei     The QEI driver to use.
332
 * @param[out]  range   The value range of the encoder.
333
 *
334
 * @return The status indicates whether the function call was successful.
335
 */
336
static inline apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range)
337
{
338 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
339
  apalDbgAssert(range != NULL);
340 e545e620 Thomas Schöpping
341
  *range = qei_lld_get_range(qei);
342
343
  return APAL_STATUS_OK;
344
}
345
346 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_QEI == TRUE) */
347 e545e620 Thomas Schöpping
348
/*============================================================================*/
349
/* I2C                                                                        */
350
/*============================================================================*/
351
352 7de0cc90 Thomas Schöpping
#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
353 e545e620 Thomas Schöpping
354
/**
355
 * @brief I2C driver type.
356
 */
357
typedef I2CDriver apalI2CDriver_t;
358
359
/**
360
 * @brief Transmit data and receive a response.
361
 *
362
 * @param[in]   i2cd      The I2C driver to use.
363
 * @param[in]   addr      Address to write to.
364
 * @param[in]   txbuf     Buffer containing data to send.
365
 * @param[in]   txbytes   Number of bytes to send.
366
 * @param[out]  rxbuf     Buffer to store a response to.
367
 * @param[in]   rxbytes   Number of bytes to receive.
368
 * @param[in]   timeout   Timeout for the function to return (in microseconds).
369
 *
370
 * @return The status indicates whether the function call was succesful or a timeout occurred.
371
 */
372
static inline apalExitStatus_t apalI2CMasterTransmit(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, const uint8_t* const txbuf, const size_t txbytes, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
373
{
374 1f94ac64 Thomas Schöpping
  apalDbgAssert(i2cd != NULL);
375 e545e620 Thomas Schöpping
376
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
377 5ab6a6a4 Thomas Schöpping
  // check whether the I2C driver was locked externally
378
  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
379
  if (!i2cd_locked_external) {
380
    i2cAcquireBus(i2cd);
381
  }
382 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
383 e545e620 Thomas Schöpping
384 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic push
385
#pragma GCC diagnostic ignored "-Wtype-limits"
386 e545e620 Thomas Schöpping
#if defined(STM32F1XX_I2C)
387
  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
388
  msg_t status = MSG_OK;
389
  if (rxbytes == 1) {
390
    uint8_t buffer[2];
391 0128be0f Marc Rothmann
    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
392 e545e620 Thomas Schöpping
    rxbuf[0] = buffer[0];
393
  } else {
394 0128be0f Marc Rothmann
    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
395 e545e620 Thomas Schöpping
  }
396 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
397 0128be0f Marc Rothmann
  const msg_t status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
398 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
399 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic pop
400 e545e620 Thomas Schöpping
401
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
402 5ab6a6a4 Thomas Schöpping
  if (!i2cd_locked_external) {
403
    i2cReleaseBus(i2cd);
404
  }
405 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
406 e545e620 Thomas Schöpping
407
  switch (status)
408
  {
409
    case MSG_OK:
410
#if defined(STM32F1XX_I2C)
411
      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
412 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
413 e545e620 Thomas Schöpping
      return APAL_STATUS_OK;
414 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
415 e545e620 Thomas Schöpping
    case MSG_TIMEOUT:
416
      return APAL_STATUS_TIMEOUT;
417
    case MSG_RESET:
418
    default:
419
      return APAL_STATUS_ERROR;
420
  }
421
}
422
423
/**
424
 * @brief Read data from a specific address.
425
 *
426
 * @param[in]   i2cd      The I2C driver to use.
427
 * @param[in]   addr      Address to read.
428
 * @param[out]  rxbuf     Buffer to store the response to.
429
 * @param[in]   rxbytes   Number of bytes to receive.
430
 * @param[in]   timeout   Timeout for the function to return (in microseconds).
431
 *
432
 * @return The status indicates whether the function call was succesful or a timeout occurred.
433
 */
434
static inline apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
435
{
436 1f94ac64 Thomas Schöpping
  apalDbgAssert(i2cd != NULL);
437 e545e620 Thomas Schöpping
438
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
439 5ab6a6a4 Thomas Schöpping
  // check whether the I2C driver was locked externally
440
  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
441
  if (!i2cd_locked_external) {
442
    i2cAcquireBus(i2cd);
443
  }
444 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
445 e545e620 Thomas Schöpping
446 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic push
447
#pragma GCC diagnostic ignored "-Wtype-limits"
448 e545e620 Thomas Schöpping
#if defined(STM32F1XX_I2C)
449
  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
450
  msg_t status = MSG_OK;
451
  if (rxbytes == 1) {
452
    uint8_t buffer[2];
453 0128be0f Marc Rothmann
    status = i2cMasterReceiveTimeout(i2cd, addr, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
454 e545e620 Thomas Schöpping
    rxbuf[0] = buffer[0];
455
  } else {
456 0128be0f Marc Rothmann
    status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
457 e545e620 Thomas Schöpping
  }
458 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
459 0128be0f Marc Rothmann
  const msg_t status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
460 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
461 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic pop
462 e545e620 Thomas Schöpping
463
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
464 5ab6a6a4 Thomas Schöpping
  if (!i2cd_locked_external) {
465
    i2cReleaseBus(i2cd);
466
  }
467 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
468 e545e620 Thomas Schöpping
469
  switch (status)
470
  {
471
    case MSG_OK:
472
#if defined(STM32F1XX_I2C)
473
      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
474 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
475 e545e620 Thomas Schöpping
      return APAL_STATUS_OK;
476 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
477 e545e620 Thomas Schöpping
    case MSG_TIMEOUT:
478
      return APAL_STATUS_TIMEOUT;
479
    case MSG_RESET:
480
    default:
481
      return APAL_STATUS_ERROR;
482
  }
483
}
484
485 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_I2C == TRUE) */
486 e545e620 Thomas Schöpping
487
/*============================================================================*/
488
/* SPI                                                                        */
489
/*============================================================================*/
490
491 7de0cc90 Thomas Schöpping
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
492 e545e620 Thomas Schöpping
493
/**
494
 * @brief SPI driver type.
495
 */
496
typedef SPIDriver apalSPIDriver_t;
497
498
/**
499
 * @brief Transmit and receive data from SPI
500
 *
501
 * @param[in]   spid      The SPI driver to use.
502
 * @param[in]   txData    Buffer containing data to send.
503
 * @param[out]  rxData    Buffer to store.
504
 * @param[in]   length    Number of bytes to send.
505
 *
506
 * @return The status indicates whether the function call was succesful.
507
 */
508
static inline apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length)
509
{
510 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
511 e545e620 Thomas Schöpping
512 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
513 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
514
  const bool spid_locked_external = spid->mutex.owner == currp;
515
  if (!spid_locked_external) {
516
    spiAcquireBus(spid);
517
  }
518 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
519 5ab6a6a4 Thomas Schöpping
520 e545e620 Thomas Schöpping
  spiSelect(spid);
521
  spiExchange(spid, length, txData, rxData);
522
  spiUnselect(spid);
523 5ab6a6a4 Thomas Schöpping
524 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
525 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
526
    spiReleaseBus(spid);
527
  }
528 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
529 e545e620 Thomas Schöpping
530
  return APAL_STATUS_OK;
531
}
532
533
/**
534
 * @brief Receive data from SPI
535
 *
536
 * @param[in]   spid      The SPI driver to use.
537
 * @param[out]  data      Buffer to store.
538
 * @param[in]   length    Number of bytes to send.
539
 *
540
 * @return The status indicates whether the function call was succesful.
541
 */
542
static inline apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length)
543
{
544 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
545 e545e620 Thomas Schöpping
546 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
547 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
548
  const bool spid_locked_external = spid->mutex.owner == currp;
549
  if (!spid_locked_external) {
550
    spiAcquireBus(spid);
551
  }
552 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
553 5ab6a6a4 Thomas Schöpping
554 e545e620 Thomas Schöpping
  spiSelect(spid);
555
  spiReceive(spid, length, data);
556
  spiUnselect(spid);
557 5ab6a6a4 Thomas Schöpping
558 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
559 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
560
    spiReleaseBus(spid);
561
  }
562 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
563 e545e620 Thomas Schöpping
564
  return APAL_STATUS_OK;
565
}
566
567
/**
568
 * @brief Transmit data to SPI
569
 *
570
 * @param[in]   spid      The SPI driver to use.
571
 * @param[in]   data      Buffer containing data to send.
572
 * @param[in]   length    Number of bytes to send.
573
 *
574
 * @return The status indicates whether the function call was succesful.
575
 */
576
static inline apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length)
577
{
578 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
579 e545e620 Thomas Schöpping
580 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
581 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
582
  const bool spid_locked_external = spid->mutex.owner == currp;
583
  if (!spid_locked_external) {
584
    spiAcquireBus(spid);
585
  }
586 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
587 5ab6a6a4 Thomas Schöpping
588 e545e620 Thomas Schöpping
  spiSelect(spid);
589
  spiSend(spid, length, data);
590
  spiUnselect(spid);
591 5ab6a6a4 Thomas Schöpping
592 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
593 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
594
    spiReleaseBus(spid);
595
  }
596 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
597 e545e620 Thomas Schöpping
598
  return APAL_STATUS_OK;
599
}
600
601 e251c4e6 Robin Ewers
/**
602 3106e8cc Thomas Schöpping
 * @brief Transmit data to SPI and receive data afterwards without releasing the bus in between.
603 e251c4e6 Robin Ewers
 *
604
 * @param   spid        The SPI driver to use.
605
 * @param   txData      Transmit data buffer.
606
 * @param   rxData      Receive data buffer.
607
 * @param   txLength    Number of bytes to send.
608
 * @param   rxLength    Number of bytes to receive.
609
 *
610
 * @return The status indicates whether the function call was succesful.
611
 */
612
static inline apalExitStatus_t apalSPITransmitAndReceive(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t txLength, const size_t rxLength)
613
{
614 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
615 e251c4e6 Robin Ewers
616 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
617 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
618
  const bool spid_locked_external = spid->mutex.owner == currp;
619
  if (!spid_locked_external) {
620
    spiAcquireBus(spid);
621
  }
622 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
623 5ab6a6a4 Thomas Schöpping
624 e251c4e6 Robin Ewers
  spiSelect(spid);
625
  spiSend(spid, txLength, txData);
626
  spiReceive(spid, rxLength, rxData);
627
  spiUnselect(spid);
628 5ab6a6a4 Thomas Schöpping
629 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
630 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
631
    spiReleaseBus(spid);
632
  }
633 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
634 e545e620 Thomas Schöpping
635
  return APAL_STATUS_OK;
636
}
637
638 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_SPI == TRUE) */
639 1703dfdf Thomas Schöpping
640 6ff06bbf Thomas Schöpping
#endif /* AMIROOS_PERIPHAL_H */