Statistics
| Branch: | Tag: | Revision:

amiro-os / periphery-lld / periphAL.h @ ad02f035

History | View | Annotate | Download (20.623 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
#define PERIPHAL_VERSION_MINOR    0
39
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 1e5f7648 Thomas Schöpping
  ioportid_t port;
111
  iopadid_t pad;
112 e545e620 Thomas Schöpping
} PACKED_VAR;
113
114
/**
115
 * @brief Read the current value of a GPIO pin.
116
 *
117
 * @param[in]   gpio  GPIO to read.
118
 * @param[out]  val   Current value of the GPIO.
119
 *
120
 * @return The status indicates whether the function call was successful.
121
 */
122
static inline apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val)
123
{
124 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
125
  apalDbgAssert(val != NULL);
126 e545e620 Thomas Schöpping
127
  *val = (palReadPad(gpio->port, gpio->pad) == PAL_HIGH) ? APAL_GPIO_HIGH : APAL_GPIO_LOW;
128
  return APAL_STATUS_OK;
129
}
130
131
/**
132
 * @brief Set the value of a GPIO pin.
133
 *
134
 * @param[in] gpio  GPIO to write.
135
 * @param[in] val   Value to set for the GPIO.
136
 *
137
 * @return The status indicates whether the function call was successful.
138
 */
139
static inline apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val)
140
{
141 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
142 e545e620 Thomas Schöpping
143
  // palWritePad() is not guaranteed to be atomic, thus the scheduler is locked.
144
  syssts_t sysstatus = chSysGetStatusAndLockX();
145
  palWritePad(gpio->port, gpio->pad, (val == APAL_GPIO_HIGH) ? PAL_HIGH : PAL_LOW);
146
  chSysRestoreStatusX(sysstatus);
147
  return APAL_STATUS_OK;
148
}
149
150
/**
151
 * @brief Toggle the output of a GPIO.
152
 *
153
 * @param[in] gpio  GPIO to toggle.
154
 *
155
 * @return The status indicates whether the function call was successful.
156
 */
157
static inline apalExitStatus_t apalGpioToggle(apalGpio_t* gpio)
158
{
159 1f94ac64 Thomas Schöpping
  apalDbgAssert(gpio != NULL);
160 e545e620 Thomas Schöpping
161
  // palWritePad() is not guaranteed to be atomic, thus the scheduler is locked.
162
  syssts_t sysstatus = chSysGetStatusAndLockX();
163
  palWritePad(gpio->port, gpio->pad, (palReadPad(gpio->port, gpio->pad) == PAL_HIGH) ? PAL_LOW : PAL_HIGH);
164
  chSysRestoreStatusX(sysstatus);
165
  return APAL_STATUS_OK;
166
}
167
168
/**
169
 * @brief Get the current on/off state of a control GPIO.
170
 *
171
 * @param[in]   gpio  Control GPIO to read.
172
 * @param[out]  val   Current activation status of the control GPIO.
173
 *
174
 * @return The status indicates whether the function call was successful.
175
 */
176
static inline apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val)
177
{
178 1f94ac64 Thomas Schöpping
  apalDbgAssert(cgpio != NULL);
179
  apalDbgAssert(cgpio->gpio != NULL);
180
  apalDbgAssert(val != NULL);
181 e545e620 Thomas Schöpping
182
  *val = ((palReadPad(cgpio->gpio->port, cgpio->gpio->pad) == PAL_HIGH) ^ (cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH)) ? APAL_GPIO_OFF : APAL_GPIO_ON;
183
  return APAL_STATUS_OK;
184
}
185
186
/**
187
 * @brief Turn a control GPIO 'on' or 'off' respectively.
188
 *
189
 * @param[in] gpio  Control GPIO to set.
190
 * @param[in] val   Activation value to set for the control GPIO.
191
 *
192
 * @return The status indicates whether the function call was successful.
193
 */
194
static inline apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val)
195
{
196 1f94ac64 Thomas Schöpping
  apalDbgAssert(cgpio != NULL);
197
  apalDbgAssert(cgpio->gpio != NULL);
198
  apalDbgAssert(cgpio->meta.direction == APAL_GPIO_DIRECTION_OUTPUT || cgpio->meta.direction == APAL_GPIO_DIRECTION_BIDIRECTIONAL);
199 e545e620 Thomas Schöpping
200
  // palWritePad() is not guaranteed to be atomic, thus the scheduler is locked.
201
  syssts_t sysstatus = chSysGetStatusAndLockX();
202
  palWritePad(cgpio->gpio->port, cgpio->gpio->pad, ((cgpio->meta.active == APAL_GPIO_ACTIVE_HIGH) ^ (val == APAL_GPIO_ON)) ? PAL_LOW : PAL_HIGH);
203
  chSysRestoreStatusX(sysstatus);
204
  return APAL_STATUS_OK;
205
}
206
207
/**
208 1e5f7648 Thomas Schöpping
 * @brief   Converts an apalGpioEdge_t to an ChibiOS PAL edge.
209 e545e620 Thomas Schöpping
 */
210 1e5f7648 Thomas Schöpping
#define APAL2CH_EDGE(edge)                                            \
211
  ((edge == APAL_GPIO_EDGE_RISING) ? PAL_EVENT_MODE_RISING_EDGE :     \
212
    (edge == APAL_GPIO_EDGE_FALLING) ? PAL_EVENT_MODE_FALLING_EDGE :  \
213 542939ea Thomas Schöpping
     (edge == APAL_GPIO_EDGE_BOTH) ? PAL_EVENT_MODE_BOTH_EDGES :      \
214
      PAL_EVENT_MODE_DISABLED)
215 e545e620 Thomas Schöpping
216 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_PAL == TRUE) */
217 e545e620 Thomas Schöpping
218
/*============================================================================*/
219
/* PWM                                                                        */
220
/*============================================================================*/
221
222 7de0cc90 Thomas Schöpping
#if (HAL_USE_PWM == TRUE) || defined (__DOXYGEN__)
223 e545e620 Thomas Schöpping
224
/**
225
 * @brief PWM driver type.
226
 */
227
typedef PWMDriver apalPWMDriver_t;
228
229
/**
230
 * @brief   Set the PWM with given parameters.
231
 *
232
 * @param[in] pwm       PWM driver to set.
233
 * @param[in] channel   Channel of the PWM driver to set.
234
 * @param[in] width     Width to set the channel to.
235
 *
236
 * @return  The status indicates whether the function call was successful.
237
 */
238
static inline apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width)
239
{
240 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
241 e545e620 Thomas Schöpping
242
  pwmEnableChannel(pwm, (pwmchannel_t)channel, pwm->period * ((float)width / (float)APAL_PWM_WIDTH_MAX) + 0.5f);
243
  return APAL_STATUS_OK;
244
}
245
246
/**
247
 * @brief   Retrieve the current frequency of the PWM.
248
 *
249
 * @param[in]  pwm        PWM driver to read.
250
 * @param[out] frequency  The currently set frequency.
251
 *
252
 * @return  The status indicates whether the function call was successful.
253
 */
254
static inline apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency)
255
{
256 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
257
  apalDbgAssert(frequency != NULL);
258 e545e620 Thomas Schöpping
259
  *frequency = pwm->config->frequency;
260
  return APAL_STATUS_OK;
261
}
262
263
/**
264
 * @brief   Retrieve the current period of the PWM.
265
 *
266
 * @param[in]   pwm     PWM driver to read.
267
 * @param[out]  period  The currently set period.
268
 *
269
 * @return  The status indicates whether the function call was successful.
270
 */
271
static inline apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period)
272
{
273 1f94ac64 Thomas Schöpping
  apalDbgAssert(pwm != NULL);
274
  apalDbgAssert(period != NULL);
275 e545e620 Thomas Schöpping
276
  *period = pwm->period;
277
  return APAL_STATUS_OK;
278
}
279
280 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_PWM == TRUE) */
281 e545e620 Thomas Schöpping
282
/*============================================================================*/
283
/* QEI                                                                        */
284
/*============================================================================*/
285
286 7de0cc90 Thomas Schöpping
#if (HAL_USE_QEI == TRUE) || defined (__DOXYGEN__)
287 e545e620 Thomas Schöpping
288
/**
289
 * @brief QEI driver type.
290
 */
291
typedef QEIDriver apalQEIDriver_t;
292
293
/**
294
 * @brief Gets the direction of the last transition.
295
 *
296
 * @param[in]   qei         The QEI driver to use.
297
 * @param[out]  direction   The direction of the last transition.
298
 *
299
 * @return The status indicates whether the function call was successful.
300
 */
301
static inline apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction)
302
{
303 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
304
  apalDbgAssert(direction != NULL);
305 e545e620 Thomas Schöpping
306
  *direction = (qei_lld_get_direction(qei)) ? APAL_QEI_DIRECTION_DOWN : APAL_QEI_DIRECTION_UP;
307
308
  return APAL_STATUS_OK;
309
}
310
311
/**
312
 * @brief Gets the current position of the ecnoder.
313
 *
314
 * @param[in]   qei       The QEI driver to use.
315
 * @param[out]  position  The current position of the encoder.
316
 *
317
 * @return The status indicates whether the function call was successful.
318
 */
319
static inline apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position)
320
{
321 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
322
  apalDbgAssert(position != NULL);
323 e545e620 Thomas Schöpping
324
  *position = qei_lld_get_position(qei);
325
326
  return APAL_STATUS_OK;
327
}
328
329
/**
330
 * @brief Gets the value range of the encoder.
331
 *
332
 * @param[in]   qei     The QEI driver to use.
333
 * @param[out]  range   The value range of the encoder.
334
 *
335
 * @return The status indicates whether the function call was successful.
336
 */
337
static inline apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range)
338
{
339 1f94ac64 Thomas Schöpping
  apalDbgAssert(qei != NULL);
340
  apalDbgAssert(range != NULL);
341 e545e620 Thomas Schöpping
342
  *range = qei_lld_get_range(qei);
343
344
  return APAL_STATUS_OK;
345
}
346
347 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_QEI == TRUE) */
348 e545e620 Thomas Schöpping
349
/*============================================================================*/
350
/* I2C                                                                        */
351
/*============================================================================*/
352
353 7de0cc90 Thomas Schöpping
#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
354 e545e620 Thomas Schöpping
355
/**
356
 * @brief I2C driver type.
357
 */
358
typedef I2CDriver apalI2CDriver_t;
359
360
/**
361
 * @brief Transmit data and receive a response.
362
 *
363
 * @param[in]   i2cd      The I2C driver to use.
364
 * @param[in]   addr      Address to write to.
365
 * @param[in]   txbuf     Buffer containing data to send.
366
 * @param[in]   txbytes   Number of bytes to send.
367
 * @param[out]  rxbuf     Buffer to store a response to.
368
 * @param[in]   rxbytes   Number of bytes to receive.
369
 * @param[in]   timeout   Timeout for the function to return (in microseconds).
370
 *
371
 * @return The status indicates whether the function call was succesful or a timeout occurred.
372
 */
373
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)
374
{
375 1f94ac64 Thomas Schöpping
  apalDbgAssert(i2cd != NULL);
376 e545e620 Thomas Schöpping
377
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
378 5ab6a6a4 Thomas Schöpping
  // check whether the I2C driver was locked externally
379
  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
380
  if (!i2cd_locked_external) {
381
    i2cAcquireBus(i2cd);
382
  }
383 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
384 e545e620 Thomas Schöpping
385 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic push
386
#pragma GCC diagnostic ignored "-Wtype-limits"
387 e545e620 Thomas Schöpping
#if defined(STM32F1XX_I2C)
388
  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
389
  msg_t status = MSG_OK;
390
  if (rxbytes == 1) {
391
    uint8_t buffer[2];
392 0128be0f Marc Rothmann
    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
393 e545e620 Thomas Schöpping
    rxbuf[0] = buffer[0];
394
  } else {
395 0128be0f Marc Rothmann
    status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
396 e545e620 Thomas Schöpping
  }
397 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
398 0128be0f Marc Rothmann
  const msg_t status = i2cMasterTransmitTimeout(i2cd, addr, txbuf, txbytes, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
399 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
400 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic pop
401 e545e620 Thomas Schöpping
402
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
403 5ab6a6a4 Thomas Schöpping
  if (!i2cd_locked_external) {
404
    i2cReleaseBus(i2cd);
405
  }
406 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
407 e545e620 Thomas Schöpping
408
  switch (status)
409
  {
410
    case MSG_OK:
411
#if defined(STM32F1XX_I2C)
412
      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
413 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
414 e545e620 Thomas Schöpping
      return APAL_STATUS_OK;
415 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
416 e545e620 Thomas Schöpping
    case MSG_TIMEOUT:
417
      return APAL_STATUS_TIMEOUT;
418
    case MSG_RESET:
419
    default:
420
      return APAL_STATUS_ERROR;
421
  }
422
}
423
424
/**
425
 * @brief Read data from a specific address.
426
 *
427
 * @param[in]   i2cd      The I2C driver to use.
428
 * @param[in]   addr      Address to read.
429
 * @param[out]  rxbuf     Buffer to store the response to.
430
 * @param[in]   rxbytes   Number of bytes to receive.
431
 * @param[in]   timeout   Timeout for the function to return (in microseconds).
432
 *
433
 * @return The status indicates whether the function call was succesful or a timeout occurred.
434
 */
435
static inline apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout)
436
{
437 1f94ac64 Thomas Schöpping
  apalDbgAssert(i2cd != NULL);
438 e545e620 Thomas Schöpping
439
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
440 5ab6a6a4 Thomas Schöpping
  // check whether the I2C driver was locked externally
441
  const bool i2cd_locked_external = i2cd->mutex.owner == currp;
442
  if (!i2cd_locked_external) {
443
    i2cAcquireBus(i2cd);
444
  }
445 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
446 e545e620 Thomas Schöpping
447 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic push
448
#pragma GCC diagnostic ignored "-Wtype-limits"
449 e545e620 Thomas Schöpping
#if defined(STM32F1XX_I2C)
450
  // Due to a hardware limitation, for STM32F1 platform the minimum number of bytes that can be received is two.
451
  msg_t status = MSG_OK;
452
  if (rxbytes == 1) {
453
    uint8_t buffer[2];
454 0128be0f Marc Rothmann
    status = i2cMasterReceiveTimeout(i2cd, addr, buffer, 2, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
455 e545e620 Thomas Schöpping
    rxbuf[0] = buffer[0];
456
  } else {
457 0128be0f Marc Rothmann
    status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
458 e545e620 Thomas Schöpping
  }
459 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
460 0128be0f Marc Rothmann
  const msg_t status = i2cMasterReceiveTimeout(i2cd, addr, rxbuf, rxbytes, ((timeout >= TIME_INFINITE) ? TIME_INFINITE : TIME_US2I(timeout)) );
461 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
462 1e5f7648 Thomas Schöpping
#pragma GCC diagnostic pop
463 e545e620 Thomas Schöpping
464
#if (I2C_USE_MUTUAL_EXCLUSION == TRUE)
465 5ab6a6a4 Thomas Schöpping
  if (!i2cd_locked_external) {
466
    i2cReleaseBus(i2cd);
467
  }
468 7de0cc90 Thomas Schöpping
#endif /* (I2C_USE_MUTUAL_EXCLUSION == TRUE) */
469 e545e620 Thomas Schöpping
470
  switch (status)
471
  {
472
    case MSG_OK:
473
#if defined(STM32F1XX_I2C)
474
      return (rxbytes != 1) ? APAL_STATUS_OK : APAL_STATUS_WARNING;
475 7de0cc90 Thomas Schöpping
#else /* defined(STM32F1XX_I2C) */
476 e545e620 Thomas Schöpping
      return APAL_STATUS_OK;
477 7de0cc90 Thomas Schöpping
#endif /* defined(STM32F1XX_I2C) */
478 e545e620 Thomas Schöpping
    case MSG_TIMEOUT:
479
      return APAL_STATUS_TIMEOUT;
480
    case MSG_RESET:
481
    default:
482
      return APAL_STATUS_ERROR;
483
  }
484
}
485
486 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_I2C == TRUE) */
487 e545e620 Thomas Schöpping
488
/*============================================================================*/
489
/* SPI                                                                        */
490
/*============================================================================*/
491
492 7de0cc90 Thomas Schöpping
#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
493 e545e620 Thomas Schöpping
494
/**
495
 * @brief SPI driver type.
496
 */
497
typedef SPIDriver apalSPIDriver_t;
498
499
/**
500
 * @brief Transmit and receive data from SPI
501
 *
502
 * @param[in]   spid      The SPI driver to use.
503
 * @param[in]   txData    Buffer containing data to send.
504
 * @param[out]  rxData    Buffer to store.
505
 * @param[in]   length    Number of bytes to send.
506
 *
507
 * @return The status indicates whether the function call was succesful.
508
 */
509
static inline apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length)
510
{
511 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
512 e545e620 Thomas Schöpping
513 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
514 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
515
  const bool spid_locked_external = spid->mutex.owner == currp;
516
  if (!spid_locked_external) {
517
    spiAcquireBus(spid);
518
  }
519 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
520 5ab6a6a4 Thomas Schöpping
521 e545e620 Thomas Schöpping
  spiSelect(spid);
522
  spiExchange(spid, length, txData, rxData);
523
  spiUnselect(spid);
524 5ab6a6a4 Thomas Schöpping
525 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
526 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
527
    spiReleaseBus(spid);
528
  }
529 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
530 e545e620 Thomas Schöpping
531
  return APAL_STATUS_OK;
532
}
533
534
/**
535
 * @brief Receive data from SPI
536
 *
537
 * @param[in]   spid      The SPI driver to use.
538
 * @param[out]  data      Buffer to store.
539
 * @param[in]   length    Number of bytes to send.
540
 *
541
 * @return The status indicates whether the function call was succesful.
542
 */
543
static inline apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length)
544
{
545 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
546 e545e620 Thomas Schöpping
547 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
548 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
549
  const bool spid_locked_external = spid->mutex.owner == currp;
550
  if (!spid_locked_external) {
551
    spiAcquireBus(spid);
552
  }
553 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
554 5ab6a6a4 Thomas Schöpping
555 e545e620 Thomas Schöpping
  spiSelect(spid);
556
  spiReceive(spid, length, data);
557
  spiUnselect(spid);
558 5ab6a6a4 Thomas Schöpping
559 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
560 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
561
    spiReleaseBus(spid);
562
  }
563 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
564 e545e620 Thomas Schöpping
565
  return APAL_STATUS_OK;
566
}
567
568
/**
569
 * @brief Transmit data to SPI
570
 *
571
 * @param[in]   spid      The SPI driver to use.
572
 * @param[in]   data      Buffer containing data to send.
573
 * @param[in]   length    Number of bytes to send.
574
 *
575
 * @return The status indicates whether the function call was succesful.
576
 */
577
static inline apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length)
578
{
579 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
580 e545e620 Thomas Schöpping
581 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
582 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
583
  const bool spid_locked_external = spid->mutex.owner == currp;
584
  if (!spid_locked_external) {
585
    spiAcquireBus(spid);
586
  }
587 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
588 5ab6a6a4 Thomas Schöpping
589 e545e620 Thomas Schöpping
  spiSelect(spid);
590
  spiSend(spid, length, data);
591
  spiUnselect(spid);
592 5ab6a6a4 Thomas Schöpping
593 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
594 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
595
    spiReleaseBus(spid);
596
  }
597 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
598 e545e620 Thomas Schöpping
599
  return APAL_STATUS_OK;
600
}
601
602 e251c4e6 Robin Ewers
/**
603
 * @brief Transmit data to SPI and receive data afterwards without releasing the bus in between
604
 *
605
 * @param   spid        The SPI driver to use.
606
 * @param   txData      Transmit data buffer.
607
 * @param   rxData      Receive data buffer.
608
 * @param   txLength    Number of bytes to send.
609
 * @param   rxLength    Number of bytes to receive.
610
 *
611
 * @return The status indicates whether the function call was succesful.
612
 */
613
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)
614
{
615 1f94ac64 Thomas Schöpping
  apalDbgAssert(spid != NULL);
616 e251c4e6 Robin Ewers
617 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
618 5ab6a6a4 Thomas Schöpping
  // check whether the SPI driver was locked externally
619
  const bool spid_locked_external = spid->mutex.owner == currp;
620
  if (!spid_locked_external) {
621
    spiAcquireBus(spid);
622
  }
623 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
624 5ab6a6a4 Thomas Schöpping
625 e251c4e6 Robin Ewers
  spiSelect(spid);
626
  spiSend(spid, txLength, txData);
627
  spiReceive(spid, rxLength, rxData);
628
  spiUnselect(spid);
629 5ab6a6a4 Thomas Schöpping
630 7de0cc90 Thomas Schöpping
#if (SPI_USE_MUTUAL_EXCLUSION == TRUE)
631 5ab6a6a4 Thomas Schöpping
  if (!spid_locked_external) {
632
    spiReleaseBus(spid);
633
  }
634 7de0cc90 Thomas Schöpping
#endif /* (SPI_USE_MUTUAL_EXCLUSION == TRUE) */
635 e545e620 Thomas Schöpping
636
  return APAL_STATUS_OK;
637
}
638
639 7de0cc90 Thomas Schöpping
#endif /* (HAL_USE_SPI == TRUE) */
640 1703dfdf Thomas Schöpping
641 6ff06bbf Thomas Schöpping
#endif /* AMIROOS_PERIPHAL_H */