spi.h
8.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @defgroup drivers_periph_spi SPI
* @ingroup drivers_periph
* @brief Low-level SPI peripheral driver
*
* The current design of this interface targets implementations that use the SPI in blocking mode.
*
* TODO: add means for asynchronous SPI usage
*
* @{
* @file
* @brief Low-level SPI peripheral driver interface definitions
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef SPI_H
#define SPI_H
#include <stdint.h>
#include "periph_cpu.h"
#include "periph_conf.h"
#ifdef __cplusplus
extern "C" {
#endif
/* add guard for the case that no SPI device is defined */
#if SPI_NUMOF
/**
* @brief Definition available SPI devices
*/
typedef enum {
#if SPI_0_EN
SPI_0 = 0, /**< SPI device 0 */
#endif
#if SPI_1_EN
SPI_1, /**< SPI device 1 */
#endif
#if SPI_2_EN
SPI_2, /**< SPI device 2 */
#endif
#if SPI_3_EN
SPI_3, /**< SPI device 3 */
#endif
} spi_t;
/**
* @brief The SPI mode is defined by the four possible combinations of clock polarity and
* clock phase.
* @{
*/
#ifndef HAVE_SPI_CONF_T
typedef enum {
/**
* The first data bit is sampled by the receiver on the first SCK edge. The
* first edge of SCK is rising. This is sometimes also referred to as SPI
* mode 0, or (CPOL=0, CPHA=0).
*/
SPI_CONF_FIRST_RISING = 0,
/**
* The first data bit is sampled by the receiver on the second SCK edge. The
* first edge of SCK is rising, i.e. the sampling edge is falling. This is
* sometimes also referred to as SPI mode 1, or (CPOL=0, CPHA=1).
*/
SPI_CONF_SECOND_RISING = 1,
/**
* The first data bit is sampled by the receiver on the first SCK edge. The
* first edge of SCK is falling. This is sometimes also referred to as SPI
* mode 2, or (CPOL=1, CPHA=0).
*/
SPI_CONF_FIRST_FALLING = 2,
/**
* The first data bit is sampled by the receiver on the second SCK edge. The
* first edge of SCK is falling, i.e. the sampling edge is rising. This is
* sometimes also referred to as SPI mode 3, or (CPOL=1, CPHA=1).
*/
SPI_CONF_SECOND_FALLING = 3
} spi_conf_t;
#endif
/** @} */
/**
* @brief Define a set of pre-defined SPI clock speeds.
*
* The actual speed of the bus can vary to some extend, as the combination of CPU clock and
* available prescale values on certain platforms may not make the exact values possible.
*
* @{
*/
#ifndef HAVE_SPI_SPEED_T
typedef enum {
SPI_SPEED_100KHZ = 0, /**< drive the SPI bus with 100KHz */
SPI_SPEED_400KHZ, /**< drive the SPI bus with 400KHz */
SPI_SPEED_1MHZ, /**< drive the SPI bus with 1MHz */
SPI_SPEED_5MHZ, /**< drive the SPI bus with 5MHz */
SPI_SPEED_10MHZ /**< drive the SPI bus with 10MHz */
} spi_speed_t;
#endif
/** @} */
/**
* @brief Initialize the given SPI device to work in master mode
*
* In master mode the SPI device is configured to control the SPI bus. This means the device
* will start and end all communication on the bus and control the CLK line. For transferring
* data on the bus the below defined transfer functions should be used.
*
* @param[in] dev SPI device to initialize
* @param[in] conf Mode of clock phase and clock polarity
* @param[in] speed desired clock speed for driving the SPI bus
*
* @return 0 on success
* @return -1 on unavailable speed value
* @return -2 on other errors
*/
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed);
/**
* @brief Initialize the given SPI device to work in slave mode
*
* In slave mode the SPI device is purely reacting to the bus. Transaction will be started and
* ended by a connected SPI master. When a byte is received, the callback is called in interrupt
* context with this byte as argument. The return byte of the callback is transferred to the
* master in the next transmission cycle. This interface enables easy implementation of a register
* based access paradigm for the SPI slave.
*
* @param[in] dev The SPI device to initialize as SPI slave
* @param[in] conf Mode of clock phase and polarity
* @param[in] cb callback called every time a byte was received
*
* @return 0 on success
* @return -1 on error
*/
int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data));
/**
* @brief Configure SCK, MISO and MOSI pins for the given SPI device
*
* @param[in] dev SPI device to use
*
* @return 0 on success
* @return -1 on error
*/
int spi_conf_pins(spi_t dev);
/**
* @brief Get mutually exclusive access to the given SPI bus
*
* In case the SPI device is busy, this function will block until the bus is free again.
*
* @param[in] dev SPI device to access
*
* @return 0 on success
* @return -1 on error
*/
int spi_acquire(spi_t dev);
/**
* @brief Release the given SPI device to be used by others
*
* @param[in] dev SPI device to release
*
* @return 0 on success
* @return -1 on error
*/
int spi_release(spi_t dev);
/**
* @brief Transfer one byte on the given SPI bus
*
* @param[in] dev SPI device to use
* @param[in] out Byte to send out, set NULL if only receiving
* @param[out] in Byte to read, set NULL if only sending
*
* @return Number of bytes that were transfered
* @return -1 on error
*/
int spi_transfer_byte(spi_t dev, char out, char *in);
/**
* @brief Transfer a number bytes on the given SPI bus
*
* @param[in] dev SPI device to use
* @param[in] out Array of bytes to send, set NULL if only receiving
* @param[out] in Buffer to receive bytes to, set NULL if only sending
* @param[in] length Number of bytes to transfer
*
* @return Number of bytes that were transfered
* @return -1 on error
*/
int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length);
/**
* @brief Transfer one byte to/from a given register address
*
* This function is a shortcut function for easier handling of register based SPI devices. As
* many SPI devices use a register based addressing scheme, this function is a convenient short-
* cut for interfacing with such devices.
*
* @param[in] dev SPI device to use
* @param[in] reg Register address to transfer data to/from
* @param[in] out Byte to send, set NULL if only receiving data
* @param[out] in Byte to read, set NULL if only sending
*
* @return Number of bytes that were transfered
* @return -1 on error
*/
int spi_transfer_reg(spi_t dev, uint8_t reg, char out, char *in);
/**
* @brief Transfer a number of bytes from/to a given register address
*
* This function is a shortcut function for easier handling of register based SPI devices. As
* many SPI devices use a register based addressing scheme, this function is a convenient short-
* cut for interfacing with such devices.
*
* @param[in] dev SPI device to use
* @param[in] reg Register address to transfer data to/from
* @param[in] out Byte array to send data from, set NULL if only receiving
* @param[out] in Byte buffer to read into, set NULL if only sending
* @param[in] length Number of bytes to transfer
*
* @return Number of bytes that were transfered
* @return -1 on error
*/
int spi_transfer_regs(spi_t dev, uint8_t reg, char *out, char *in, unsigned int length);
/**
* @brief Tell the SPI driver that a new transaction was started. Call only when SPI in slave mode!
*
* @param[in] dev SPI device that is active
* @param[in] reset_val The byte that is send to the master as first byte
*/
void spi_transmission_begin(spi_t dev, char reset_val);
/**
* @brief Power on the given SPI device
*
* @param[in] dev SPI device to power on
*/
void spi_poweron(spi_t dev);
/**
* @brief Power off the given SPI device
*
* @param[in] dev SPI device to power off
*/
void spi_poweroff(spi_t dev);
#endif /* SPI_NUMOF */
#ifdef __cplusplus
}
#endif
#endif /* SPI_H */
/** @} */