AFBR-S50 API Reference Manual  v1.6.5
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
argus_s2pi.h
Go to the documentation of this file.
1 /*************************************************************************/
37 #ifndef ARGUS_S2PI_H
38 #define ARGUS_S2PI_H
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /*!***************************************************************************
44  * @defgroup argus_s2pi S2PI: Serial Peripheral Interface
45  * @ingroup argus_hal
46  *
47  * @brief S2PI: SPI incl. GPIO Hardware Layer Module
48  *
49  * @details The S2PI module consists of a standard SPI interface plus a
50  * single GPIO interrupt line. Furthermore, the SPI pins are
51  * accessible via GPIO control to allow a software emulation of
52  * additional protocols using the same pins.
53  *
54  * **SPI interface:**
55  *
56  * The SPI interface is based around a single functionality:
57  *
58  * #S2PI_TransferFrame. This function transfers a specified number
59  * of bytes via the interfaces MOSI line and simultaneously reads
60  * the incoming data on the MOSI line. The read can also be skipped.
61  * The transfer happen asynchronously, e.g. via a DMA request. After
62  * finishing the transfer, the provided callback is invoked with
63  * the status of the transfer and the provided abstract parameter.
64  * Furthermore, the functions receives a slave parameter that can
65  * be used to connect multiple slaves, each with its individual
66  * chip select line.
67  *
68  * The interface also provides functionality to change the SPI
69  * baud rate. An additional abort method is used to cancel the
70  * ongoing transfer.
71  *
72  * **GPIO interface:**
73  *
74  * The GPIO part of the S2PI interface has two distinct concerns:
75  *
76  * First, the GPIO interface handles the measurement finished interrupt
77  * from the device. When the device invokes the interrupt, it pulls
78  * the interrupt line to low. Thus the interrupt must trigger when
79  * a transition from high to low occurs on the interrupt line.
80  *
81  * The module simply invokes a callback when this interrupt occurs.
82  * The #S2PI_SetIrqCallback method is used to install the callback
83  * for a specified slave. Each slave will have its own interrupt
84  * line. An additional callback parameter can be set that would be
85  * passed to the callback function.
86  *
87  * In addition to the interrupt, all SPI pins need to be accessible
88  * as GPIO pins through this interface. This is required to read
89  * the EEPROM memory on the device hat is connected to the SPI
90  * pins but requires a different protocol that is not compatible
91  * to any standard SPI interface. Therefore, the interface provides
92  * the possibility to switch to GPIO control mode that allows to
93  * emulate the EEPROM protocol via software bit banging.
94  *
95  * Two methods are provided to switch forth and back between SPI
96  * and GPIO control. In GPIO mode, several functions are used to
97  * read and write the individual GPIO pins.
98  *
99  * Note that the GPIO mode is only required to readout the EEPROM
100  * upon initialization of the device, i.e. during execution of the
101  * #Argus_Init or #Argus_Reinit methods. The GPIO mode is not used
102  * during measurements.
103  *
104  *
105  * @addtogroup argus_s2pi
106  * @{
107  *****************************************************************************/
108 
109 #include "api/argus_def.h"
110 
111 /*!***************************************************************************
112  * @brief S2PI layer callback function type for the SPI transfer completed event.
113  *
114  * @param status The \link #status_t status\endlink of the completed
115  * transfer (#STATUS_OK on success).
116  *
117  * @param param The provided (optional, can be null) callback parameter.
118  *
119  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
120  *****************************************************************************/
121 typedef status_t (*s2pi_callback_t)(status_t status, void * param);
122 
123 /*!***************************************************************************
124  * @brief S2PI layer callback function type for the GPIO interrupt event.
125  *
126  * @param param The provided (optional, can be null) callback parameter.
127  *****************************************************************************/
128 typedef void (*s2pi_irq_callback_t)(void * param);
129 
132 typedef int32_t s2pi_slave_t;
133 
135 typedef enum s2pi_pin_t
136 {
139 
142 
145 
148 
151 
152 } s2pi_pin_t;
153 
154 
155 /*!***************************************************************************
156  * @brief Returns the status of the SPI module.
157  *
158  * @param slave The specified S2PI slave. Note that the slave information is
159  * only required if multiple SPI instances are used in order to
160  * map to the correct SPI instance.
161  *
162  * @return Returns the \link #status_t status\endlink:
163  * - #STATUS_IDLE: No SPI transfer or GPIO access is ongoing.
164  * - #STATUS_BUSY: An SPI transfer is in progress.
165  * - #STATUS_S2PI_GPIO_MODE: The module is in GPIO mode.
166  *****************************************************************************/
168 
169 /*!***************************************************************************
170  * @brief Tries to grab the SPI interface mutex for the next transfer.
171  *
172  * @details This mutex prevents new asynchronous SPI requests to interfere
173  * with transfers already in progress for this interface.
174  *
175  * Note that this is only required if multiple device are connected to
176  * a single SPI interface. If only operating a single device per SPI,
177  * the function can simply always return #STATUS_OK.
178  *
179  * There must be a dedicated mutex object per SPI interface if
180  * multiple SPI interfaces are used.
181  *
182  * The mutex will be released in the #S2PI_ReleaseMutex function.
183  * See #S2PI_ReleaseMutex for additional information.
184  *
185  * Here is a simple example implementation for the multiple devices on
186  * a single SPI interface case. Note that the SpiMutexBlocked must be
187  * defined per SPI interface if multiple SPI interfaces are used.
188  *
189  * @code
190  * static volatile bool SpiMutexBlocked = false;
191  * status_t S2PI_TryGetMutex(s2pi_slave_t slave)
192  * {
193  * (void) slave; // not used in this implementation as all
194  * // SPI slaves are on the same SPI interface
195  *
196  * status_t status = STATUS_BUSY;
197  * IRQ_LOCK();
198  * if (!SpiMutexBlocked)
199  * {
200  * SpiMutexBlocked = true;
201  * status = STATUS_OK;
202  * }
203  * IRQ_UNLOCK();
204  * return status;
205  * }
206  * void S2PI_ReleaseMutex(s2pi_slave_t slave)
207  * {
208  * (void) slave; // not used in this implementation
209  * SpiMutexBlocked = false;
210  * }
211  * @endcode
212  *
213  * @param slave The specified S2PI slave. Note that the slave information is
214  * only required if multiple SPI instances are used in order to
215  * map to the correct SPI instance.
216  *
217  * @return Returns the \link #status_t status\endlink:
218  * - #STATUS_OK: the SPI interface was successfully reserved for the caller
219  * - #STATUS_BUSY: another transfer is ongoing, the caller must not access the bus
220  *****************************************************************************/
222 
223 /*!***************************************************************************
224  * @brief Releases the SPI interface mutex.
225  *
226  * @details Once the mutex is captured, only a single thread (the one that
227  * captured it) will call this release function, so there is no
228  * need for any test or thread safe barriers. Also there is no
229  * side effect of calling this function when the Mutex is not
230  * taken so this function can be really simple and doesn't need
231  * to return anything.
232  *
233  * See #S2PI_TryGetMutex on more information and an example
234  * implementation for the single SPI interface case.
235  *
236  * @param slave The specified S2PI slave. Note that the slave information is
237  * only required if multiple SPI instances are used in order to
238  * map to the correct SPI instance.
239  *****************************************************************************/
240 void S2PI_ReleaseMutex(s2pi_slave_t slave);
241 
242 /*!***************************************************************************
243  * @brief Transfers a single SPI frame asynchronously.
244  *
245  * @details Transfers a single SPI frame in asynchronous manner. The Tx data
246  * buffer is written to the device via the MOSI line.
247  * Optionally, the data on the MISO line is written to the provided
248  * Rx data buffer. If null, the read data is dismissed. Note that
249  * Rx and Tx buffer can be identical. I.e. the same buffer is used
250  * for writing and reading data. First, a byte is transmitted and
251  * the received byte overwrites the previously send value.
252  *
253  * The transfer of a single frame requires to not toggle the chip
254  * select line to high in between the data frame. The maximum
255  * number of bytes transferred in a single SPI transfer is given by
256  * the data value register of the device, which is 396 data bytes
257  * plus a single address byte: 397 bytes.
258  *
259  * An optional callback is invoked when the asynchronous transfer
260  * is finished. If the \p callback parameter is a null pointer,
261  * no callback is provided. Note that the provided buffer must not
262  * change while the transfer is ongoing.
263  *
264  * Use the slave parameter to determine the corresponding slave via the
265  * given chip select line.
266  *
267  * Usually, two distinct interrupts are required to handle the RX and
268  * TX ready events. The callback must be invoked from whichever
269  * interrupt comes after the SPI transfer has been finished. Note
270  * that new SPI transfers are invoked from within the callback function
271  * (i.e. from within the interrupt service routine of same priority).
272  *
273  * @param slave The specified S2PI slave.
274  * @param txData The 8-bit values to write to the SPI bus MOSI line.
275  * @param rxData The 8-bit values received from the SPI bus MISO line
276  * (pass a null pointer if the data don't need to be read).
277  * @param frameSize The number of 8-bit values to be sent/received.
278  * @param callback A callback function to be invoked when the transfer is
279  * finished. Pass a null pointer if no callback is required.
280  * @param callbackData A pointer to a state that will be passed to the
281  * callback. Pass a null pointer if not used.
282  *
283  * @return Returns the \link #status_t status\endlink:
284  * - #STATUS_OK: Successfully invoked the transfer.
285  * - #ERROR_INVALID_ARGUMENT: An invalid parameter has been passed.
286  * - #ERROR_S2PI_INVALID_SLAVE: A wrong slave identifier is provided.
287  * - #STATUS_BUSY: An SPI transfer is already in progress. The
288  * transfer was not started.
289  * - #STATUS_S2PI_GPIO_MODE: The module is in GPIO mode. The transfer
290  * was not started.
291  *****************************************************************************/
293  uint8_t const * txData,
294  uint8_t * rxData,
295  size_t frameSize,
296  s2pi_callback_t callback,
297  void * callbackData);
298 
299 /*!***************************************************************************
300  * @brief Terminates a currently ongoing asynchronous SPI transfer.
301  *
302  * @details When a callback is set for the current ongoing activity, it is
303  * invoked with the #ERROR_ABORTED error byte.
304  *
305  * @param slave The specified S2PI slave. Note that the slave information is
306  * only required if multiple SPI instances are used in order to
307  * map to the correct SPI instance.
308  *
309  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
310  *****************************************************************************/
312 
313 /*!***************************************************************************
314  * @brief Set a callback for the GPIO IRQ for a specified S2PI slave.
315  *
316  * @param slave The specified S2PI slave.
317  * @param callback A callback function to be invoked when the specified
318  * S2PI slave IRQ occurs. Pass a null pointer to disable
319  * the callback.
320  * @param callbackData A pointer to a state that will be passed to the
321  * callback. Pass a null pointer if not used.
322  *
323  * @return Returns the \link #status_t status\endlink:
324  * - #STATUS_OK: Successfully installation of the callback.
325  * - #ERROR_S2PI_INVALID_SLAVE: A wrong slave identifier is provided.
326  *****************************************************************************/
328  s2pi_irq_callback_t callback,
329  void * callbackData);
330 
331 /*!***************************************************************************
332  * @brief Reads the current interrupt pending status of the IRQ pin.
333  *
334  * @details In order to keep a low priority for GPIO IRQs, the state of the
335  * IRQ pin must be read in order to reliable check for chip timeouts.
336  *
337  * The execution of the interrupt service routine for the data-ready
338  * interrupt from the corresponding GPIO pin might be delayed due to
339  * priority issues. The delayed execution might disable the timeout
340  * for the eye-safety checker too late causing false error messages.
341  * In order to overcome the issue, the interrupt state of the IRQ
342  * GPIO input pin is read before raising a timeout error in order to
343  * check if the device has already finished and the IRQ is still
344  * pending to be executed!
345  *
346  * Note: an easy implementation is to simply return the state of the
347  * IRQ line, i.e. 0 if there is a low input state and 1 if there is
348  * a high input state on the IRQ input pin. However, this
349  * implementation is not fully reliable since the GPIO interrupt
350  * (triggered on the falling edge) might be missed and the callback
351  * is never invoked while the IRQ line is correctly asserted to low
352  * state by the device. In that case, the API is waiting forever
353  * until the callback is invoked which might never happen. Therefore,
354  * it is better if the implementation checks the state of the IRQ
355  * pending status register or even combines both variations.
356 
357  * @param slave The specified S2PI slave.
358  *
359  * @return Returns 1U if the IRQ is NOT pending (pin is in high state) and
360  * 0U if the IRQ is pending (pin is pulled to low state by the device).
361  *****************************************************************************/
362 uint32_t S2PI_ReadIrqPin(s2pi_slave_t slave);
363 
364 /*!***************************************************************************
365  * @brief Cycles the chip select line.
366  *
367  * @details In order to cancel the integration on the ASIC, a fast toggling
368  * of the chip select pin of the corresponding SPI slave is required.
369  * Therefore, this function toggles the CS from high to low and back.
370  * The SPI instance for the specified S2PI slave must be idle,
371  * otherwise the status #STATUS_BUSY is returned.
372  *
373  * @param slave The specified S2PI slave.
374  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
375  *****************************************************************************/
377 
378 /*!*****************************************************************************
379  * @brief Captures the S2PI pins for GPIO usage.
380  *
381  * @details The SPI is disabled (module status: #STATUS_S2PI_GPIO_MODE) and the
382  * pins are configured for GPIO operation. The GPIO control must be
383  * release with the #S2PI_ReleaseGpioControl function in order to
384  * switch back to ordinary SPI functionality.
385  *
386  * @note This function is only called during device initialization!
387  *
388  * @param slave The specified S2PI slave. Note that the slave information is
389  * only required if multiple SPI instances are used in order to
390  * map to the correct SPI instance.
391  *
392  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
393  *****************************************************************************/
395 
396 /*!*****************************************************************************
397  * @brief Releases the S2PI pins from GPIO usage and switches back to SPI mode.
398  *
399  * @details The GPIO pins are configured for SPI operation and the GPIO mode is
400  * left. Must be called if the pins are captured for GPIO operation via
401  * the #S2PI_CaptureGpioControl function.
402  *
403  * @note This function is only called during device initialization!
404  *
405  * @param slave The specified S2PI slave. Note that the slave information is
406  * only required if multiple SPI instances are used in order to
407  * map to the correct SPI instance.
408  *
409  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
410  *****************************************************************************/
412 
413 /*!*****************************************************************************
414  * @brief Writes the output for a specified SPI pin in GPIO mode.
415  *
416  * @details This function writes the value of an SPI pin if the SPI pins are
417  * captured for GPIO operation via the #S2PI_CaptureGpioControl previously.
418  *
419  * @note Since some GPIO peripherals switch the GPIO pins very fast a delay
420  * must be added after each GBIO access (i.e. right before returning
421  * from the #S2PI_WriteGpioPin method) in order to decrease the baud
422  * rate of the software EEPROM protocol. Increase the delay if timing
423  * issues occur while reading the EERPOM. For example:
424  * Delay = 10 µsec => Baud Rate < 100 kHz
425  *
426  * @note This function is only called during device initialization!
427  *
428  * @param slave The specified S2PI slave.
429  * @param pin The specified S2PI pin.
430  * @param value The GPIO pin state to write (0 = low, 1 = high).
431  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
432  *****************************************************************************/
433 status_t S2PI_WriteGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t value);
434 
435 /*!*****************************************************************************
436  * @brief Reads the input from a specified SPI pin in GPIO mode.
437  *
438  * @details This function reads the value of an SPI pin if the SPI pins are
439  * captured for GPIO operation via the #S2PI_CaptureGpioControl previously.
440  *
441  * @note This function is only called during device initialization!
442  *
443  * @param slave The specified S2PI slave.
444  * @param pin The specified S2PI pin.
445  * @param value The GPIO pin state to read (0 = low, GND level, 1 = high, VCC level).
446  * @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
447  *****************************************************************************/
448 status_t S2PI_ReadGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t * value);
449 
451 #ifdef __cplusplus
452 } // extern "C"
453 #endif
454 #endif // ARGUS_S2PI_H
S2PI_CycleCsPin
status_t S2PI_CycleCsPin(s2pi_slave_t slave)
Cycles the chip select line.
S2PI_CaptureGpioControl
status_t S2PI_CaptureGpioControl(s2pi_slave_t slave)
Captures the S2PI pins for GPIO usage.
S2PI_TransferFrame
status_t S2PI_TransferFrame(s2pi_slave_t slave, uint8_t const *txData, uint8_t *rxData, size_t frameSize, s2pi_callback_t callback, void *callbackData)
Transfers a single SPI frame asynchronously.
S2PI_ReadIrqPin
uint32_t S2PI_ReadIrqPin(s2pi_slave_t slave)
Reads the current interrupt pending status of the IRQ pin.
S2PI_MISO
@ S2PI_MISO
Definition: argus_s2pi.h:147
S2PI_CLK
@ S2PI_CLK
Definition: argus_s2pi.h:138
S2PI_Abort
status_t S2PI_Abort(s2pi_slave_t slave)
Terminates a currently ongoing asynchronous SPI transfer.
S2PI_ReadGpioPin
status_t S2PI_ReadGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t *value)
Reads the input from a specified SPI pin in GPIO mode.
S2PI_GetStatus
status_t S2PI_GetStatus(s2pi_slave_t slave)
Returns the status of the SPI module.
argus_def.h
This file is part of the AFBR-S50 hardware API.
S2PI_TryGetMutex
status_t S2PI_TryGetMutex(s2pi_slave_t slave)
Tries to grab the SPI interface mutex for the next transfer.
S2PI_MOSI
@ S2PI_MOSI
Definition: argus_s2pi.h:144
S2PI_WriteGpioPin
status_t S2PI_WriteGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t value)
Writes the output for a specified SPI pin in GPIO mode.
s2pi_slave_t
int32_t s2pi_slave_t
Definition: argus_api.h:67
s2pi_callback_t
status_t(* s2pi_callback_t)(status_t status, void *param)
S2PI layer callback function type for the SPI transfer completed event.
Definition: argus_s2pi.h:121
S2PI_IRQ
@ S2PI_IRQ
Definition: argus_s2pi.h:150
S2PI_ReleaseGpioControl
status_t S2PI_ReleaseGpioControl(s2pi_slave_t slave)
Releases the S2PI pins from GPIO usage and switches back to SPI mode.
s2pi_slave_t
int32_t s2pi_slave_t
Definition: argus_s2pi.h:132
s2pi_irq_callback_t
void(* s2pi_irq_callback_t)(void *param)
S2PI layer callback function type for the GPIO interrupt event.
Definition: argus_s2pi.h:128
status
static status_t status
Definition: argus_xtalk_cal_cli.c:140
S2PI_CS
@ S2PI_CS
Definition: argus_s2pi.h:141
S2PI_ReleaseMutex
void S2PI_ReleaseMutex(s2pi_slave_t slave)
Releases the SPI interface mutex.
status_t
int32_t status_t
Type used for all status and error return values.
Definition: argus_status.h:70
s2pi_pin_t
s2pi_pin_t
Definition: argus_s2pi.h:135
S2PI_SetIrqCallback
status_t S2PI_SetIrqCallback(s2pi_slave_t slave, s2pi_irq_callback_t callback, void *callbackData)
Set a callback for the GPIO IRQ for a specified S2PI slave.