px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_spi.h
1#ifndef __PX_SPI_H__
2#define __PX_SPI_H__
3/* =============================================================================
4 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
5 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
6 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
7 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
8 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
9
10 Copyright (c) 2012 Pieter Conradie <https://piconomix.com>
11
12 License: MIT
13 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
14
15 Title: px_spi.h : SPI Peripheral Driver
16 Author(s): Pieter Conradie
17 Creation Date: 2012-06-23
18
19============================================================================= */
20
21/**
22 * @ingroup AVR
23 * @defgroup AVR_SPI px_spi.h : SPI Peripheral Driver
24 *
25 * Driver for the SPI peripheral to communicate with SPI slaves.
26 *
27 * File(s):
28 * - arch/avr/inc/px_spi.h
29 * - arch/avr/inc/px_spi_cfg_template.h
30 * - arch/avr/inc/px_spi_defs.h
31 * - arch/avr/src/px_spi.c
32 *
33 * The driver must be configured by supplying a project specific "px_spi_cfg.h".
34 * "px_spi_cfg_template.h" can be copied, renamed and modified to supply
35 * compile time options.
36 *
37 * @warn_s
38 * The SPI peripheral Slave Select pin (SS) must be configured as an output
39 * or kept high if it is configured as an input. If this pin is configured
40 * as an input and pulled low, the SPI peripheral will automatically change
41 * from MASTER mode to SLAVE mode.
42 * @warn_e
43 *
44 * @par Example:
45 * @include arch/avr/test/px_spi_test.c
46 *
47 * @{
48 */
49
50/* _____STANDARD INCLUDES____________________________________________________ */
51
52/* _____PROJECT INCLUDES_____________________________________________________ */
53#include "px_defs.h"
54
55// Include project specific configuration. See "px_spi_cfg_template.h"
56#include "px_spi_cfg.h"
57
58// Check that all project specific options have been specified in "px_spi_cfg.h"
59#if ( !defined(PX_SPI_CFG_SPI0_EN ) \
60 || !defined(PX_SPI_CFG_SPCR ) \
61 || !defined(PX_SPI_CFG_USE_SPI2X ) \
62 || !defined(PX_SPI_CFG_DEFAULT_BAUD ) \
63 || !defined(PX_SPI_CFG_DEFAULT_MODE ) \
64 || !defined(PX_SPI_CFG_DEFAULT_DATA_ORDER) \
65 || !defined(PX_SPI_CFG_CS_LO ) \
66 || !defined(PX_SPI_CFG_CS_HI ) )
67 )
68#error "One or more options not defined in 'px_uart_cfg.h'"
69#endif
70
71#if (PX_SPI_CFG_SPI0_EN > 1)
72#error "PX_SPI_CFG_SPIx_EN must be 0 or 1"
73#endif
74
75/// Number of enabled peripherals
76#define PX_SPI_CFG_PER_COUNT (PX_SPI_CFG_SPI0_EN)
77#if (PX_SPI_CFG_PER_COUNT == 0)
78#error "No peripherals enabled"
79#endif
80
81#ifdef __cplusplus
82extern "C" {
83#endif
84/* _____DEFINITIONS__________________________________________________________ */
85
86/* _____TYPE DEFINITIONS_____________________________________________________ */
87/// Specify SPI peripheral
88typedef enum
89{
90 PX_SPI_NR_0 = 0,
92
93/// Specify SPI Clock polarity / Clock phase
94typedef enum
95{
96 PX_SPI_MODE0 = 0, ///< CPOL=0, CPHA=0; SCLK idle polarity low; data sampled on first (rising) edge
97 PX_SPI_MODE1 = 1, ///< CPOL=0, CPHA=1; SCLK idle polarity low; data sampled on second (falling) edge
98 PX_SPI_MODE2 = 2, ///< CPOL=1, CPHA=0; SCLK idle polarity high; data sampled on first (falling) edge
99 PX_SPI_MODE3 = 3, ///< CPOL=1, CPHA=1; SCLK idle polarity high; data sampled on second (rising) edge
101
102/// Specify SPI Data order
103typedef enum
104{
105 PX_SPI_DATA_ORDER_MSB = 0, ///< Data order is Most Significant Bit first (D7, D6, ..., D0)
106 PX_SPI_DATA_ORDER_LSB = 1, ///< Data order is Least Significant Bit first (D0, D1, ..., D7)
108
109/// Specify SPI baud rate as a ratio of the peripheral clock
110typedef enum
111{
112 PX_SPI_BAUD_CLK_DIV_2 = 0, ///< F_CPU / 2
113 PX_SPI_BAUD_CLK_DIV_4, ///< F_CPU / 4
114 PX_SPI_BAUD_CLK_DIV_8, ///< F_CPU / 8
115 PX_SPI_BAUD_CLK_DIV_16, ///< F_CPU / 16
116 PX_SPI_BAUD_CLK_DIV_32, ///< F_CPU / 32
117 PX_SPI_BAUD_CLK_DIV_64, ///< F_CPU / 64
118 PX_SPI_BAUD_CLK_DIV_128, ///< F_CPU / 128
120
121/// @name SPI bit flags to demarcate the start and end of a transaction
122/// @{
123
124/// Begin SPI transaction (take SPI slave's Chip Select line low)
125#define PX_SPI_FLAG_START (1 << 0)
126/// Finish SPI transaction (take SPI slave's Chip Select line high)
127#define PX_SPI_FLAG_STOP (1 << 1)
128/// Begin and finish SPI transaction
129#define PX_SPI_FLAG_START_AND_STOP (PX_SPI_FLAG_START + PX_SPI_FLAG_STOP)
130/// @}
131
132/// Define SPI handle
133typedef struct
134{
135 struct px_spi_per_s * spi_per; ///< SPI peripheral data
136 uint8_t cs_id; ///< Chip Select GPIO ID
137 uint8_t spcr; ///< SPI Control Register value
138 bool use_spi2x; ///< Use 2X clock rate
139 uint8_t mo_dummy_byte; ///< Master Out dummy byte when data is read from Master In
141
142/* _____GLOBAL VARIABLES_____________________________________________________ */
143
144/* _____GLOBAL FUNCTION DECLARATIONS_________________________________________ */
145/**
146 * Initialise SPI driver.
147 */
148void px_spi_init(void);
149
150/**
151 * Open SPI peripheral using predefined (default) parameters.
152 *
153 * @param handle Pointer to handle data structure
154 * @param spi_nr SPI peripheral number
155 * @param cs_id ID to use when calling PX_SPI_CS_xx() macro
156 *
157 * @retval false Error: peripheral was not opened
158 * @retval true Success: peripheral was opened
159 */
160bool px_spi_open(px_spi_handle_t * handle,
161 px_spi_nr_t spi_nr,
162 uint8_t cs_id);
163
164/**
165 * Open SPI peripheral using specified parameters.
166 *
167 * @param handle Pointer to handle data structure
168 * @param spi_nr SPI peripheral number
169 * @param cs_id ID to use when calling PX_SPI_CS() macro
170 * @param baud Desired BAUD rate as a division of peripheral clock
171 * @param mode Clock mode 0,1,2 or 3 @see px_spi_mode_t
172 * @param data_order Data order (MSB first of LSB first)
173 * @param mo_dummy_byte Master Out dummy byte used when reading data from
174 * SPI slave
175 *
176 * @retval false Error: peripheral was not opened
177 * @retval true Success: peripheral was opened
178 */
179bool px_spi_open2(px_spi_handle_t * handle,
180 px_spi_nr_t spi_nr,
181 uint8_t cs_id,
182 px_spi_baud_t baud,
183 px_spi_mode_t mode,
184 px_spi_dord_t data_order,
185 uint8_t mo_dummy_byte);
186
187/**
188 * Close specified device.
189 *
190 * @param handle Pointer to handle data structure
191 *
192 * @retval true Success
193 * @retval false Specified device was already closed (or not opened)
194 */
195bool px_spi_close(px_spi_handle_t * handle);
196
197/**
198 * Perform an SPI write transaction with an SPI slave.
199 *
200 * With the use of flags this function allows concatenation of one or more
201 * writes / reads / exchanges with an SPI slave to form one big transaction.
202 *
203 * If the PX_SPI_FLAG_START flag is specified, the SPI slave is first selected
204 * by taking it's Chip Select line low.
205 *
206 * The specified number of bytes is then written to the SPI slave.
207 *
208 * Finally, if the PX_SPI_FLAG_STOP flag is specified, the SPI slave's Chip
209 * Select line is taken high to complete the transaction.
210 *
211 * @param handle Pointer to handle data structure
212 * @param data Buffer containing data to write
213 * @param nr_of_bytes Number of bytes to write to the slave
214 * @param flags Bit combination of PX_SPI_FLAG_START and
215 * PX_SPI_FLAG_STOP or nothing (0)
216 */
217void px_spi_wr(px_spi_handle_t * handle,
218 const void * data,
219 size_t nr_of_bytes,
220 uint8_t flags);
221
222/**
223 * Perform an SPI read transaction with an SPI slave.
224 *
225 * With the use of flags this function allows concatenation of one or more
226 * writes / reads / exchanges with an SPI slave to form one big transaction.
227 *
228 * If the PX_SPI_FLAG_START flag is specified, the SPI slave is first selected
229 * by taking it's Chip Select line low.
230 *
231 * The specified number of bytes is then read from the SPI slave.
232 *
233 * Finally, if the PX_SPI_FLAG_STOP flag is specified, the SPI slave's Chip
234 * Select line is taken high to complete the transaction.
235 *
236 * @param handle Pointer to handle data structure
237 * @param data Pointer to a buffer where the received data must be
238 * stored
239 * @param nr_of_bytes Number of bytes to read from slave
240 * @param flags Bit combination of PX_SPI_FLAG_START and
241 * PX_SPI_FLAG_STOP or nothing (0)
242 */
243void px_spi_rd(px_spi_handle_t * handle,
244 void * data,
245 size_t nr_of_bytes,
246 uint8_t flags);
247
248/**
249 * Perform an SPI exchange (write and read) transaction with an SPI
250 * slave.
251 *
252 * With the use of flags this function allows concatenation of one or more
253 * writes / reads / exchanges with an SPI slave to form one big transaction.
254 *
255 * If the PX_SPI_FLAG_START flag is specified, the SPI slave is first selected
256 * by taking it's Chip Select line low.
257 *
258 * The specified number of bytes is then written to the slave, while
259 * simultaneously reading the same number of bytes from the slave.
260 *
261 * The write buffer and read buffer must both be at least "nr_of_bytes" bytes
262 * in size. It is acceptable to have the write buffer and read buffer point to
263 * the same location in which case the data to write will be overwritten by the
264 * received data.
265 *
266 * Finally, if the PX_SPI_FLAG_STOP flag is specified, the SPI slave's Chip
267 * Select line is taken high to complete the transaction.
268 *
269 * @param handle Pointer to handle data structure
270 * @param data_wr Pointer to a buffer containing data to be written
271 * @param data_rd Pointer to a buffer where the read data must be stored
272 * @param nr_of_bytes Number of bytes to exchange
273 * @param flags Bit combination of PX_SPI_FLAG_START and
274 * PX_SPI_FLAG_STOP or nothing (0)
275 */
276void px_spi_xc(px_spi_handle_t * handle,
277 const void * data_wr,
278 void * data_rd,
279 size_t nr_of_bytes,
280 uint8_t flags);
281
282/**
283 * Change SPI peripheral baud.
284 *
285 * @param handle Pointer to handle data structure
286 * @param baud Desired BAUD rate as a division of peripheral clock
287 */
289 px_spi_baud_t baud);
290
291/**
292 * Calculate clock divisor that will yield closest frequency equal to or
293 * less than specified baud rate (in Hz).
294 *
295 * @param baud_hz Desired BAUD rate in Hz that SCK must be clocked
296 *
297 * @return px_spi_baud_t Calculated divisor
298 */
300
301/**
302 * Calculate the actual BAUD (in Hz) from the specified division.
303 *
304 * @param baud Desired BAUD rate as a division of peripheral clock
305 *
306 * @return uint32_t Actual BAUD (in Hz)
307 */
309
310/* _____MACROS_______________________________________________________________ */
311
312#ifdef __cplusplus
313}
314#endif
315
316/// @}
317#endif
#define PX_SPI_CFG_SPI0_EN
Enable/disable support for SPI0 peripheral.
@ PX_SPI_MODE0
CPOL=0, CPHA=0; SCLK idle polarity low; data sampled on first (rising) edge.
Definition: px_spi.h:87
@ PX_SPI_MODE3
CPOL=1, CPHA=1; SCLK idle polarity high; data sampled on second (rising) edge.
Definition: px_spi.h:90
@ PX_SPI_MODE1
CPOL=0, CPHA=1; SCLK idle polarity low; data sampled on second (falling) edge.
Definition: px_spi.h:88
@ PX_SPI_MODE2
CPOL=1, CPHA=0; SCLK idle polarity high; data sampled on first (falling) edge.
Definition: px_spi.h:89
@ PX_SPI_DATA_ORDER_LSB
Data order is Least Significant Bit first (D0, D1, ..., D7)
Definition: px_spi.h:97
@ PX_SPI_DATA_ORDER_MSB
Data order is Most Significant Bit first (D7, D6, ..., D0)
Definition: px_spi.h:96
@ PX_SPI_BAUD_CLK_DIV_128
F_PCLK / 128.
Definition: px_spi.h:109
@ PX_SPI_BAUD_CLK_DIV_8
F_PCLK / 8.
Definition: px_spi.h:105
@ PX_SPI_BAUD_CLK_DIV_4
F_PCLK / 4.
Definition: px_spi.h:104
@ PX_SPI_BAUD_CLK_DIV_64
F_PCLK / 64.
Definition: px_spi.h:108
@ PX_SPI_BAUD_CLK_DIV_16
F_PCLK / 16.
Definition: px_spi.h:106
@ PX_SPI_BAUD_CLK_DIV_2
F_PCLK / 2.
Definition: px_spi.h:103
@ PX_SPI_BAUD_CLK_DIV_32
F_PCLK / 32.
Definition: px_spi.h:107
bool use_spi2x
Use 2X clock rate.
Definition: px_spi.h:138
uint8_t spcr
SPI Control Register value.
Definition: px_spi.h:137
bool px_spi_close(px_spi_handle_t *handle)
Close specified device.
Definition: px_spi.c:338
px_spi_mode_t
Specify SPI Clock polarity / Clock phase.
Definition: px_spi.h:86
void px_spi_init(void)
Initialise SPI driver.
Definition: px_spi.c:162
bool px_spi_open2(px_spi_handle_t *handle, px_spi_nr_t spi_nr, uint8_t cs_id, px_spi_baud_t baud, px_spi_mode_t mode, px_spi_dord_t data_order, uint8_t mo_dummy_byte)
Open SPI peripheral using specified parameters.
Definition: px_spi.c:252
px_spi_dord_t
Specify SPI Data order.
Definition: px_spi.h:95
void px_spi_xc(px_spi_handle_t *handle, const void *data_wr, void *data_rd, size_t nr_of_bytes, uint8_t flags)
Perform an SPI exchange (write and read) transaction with an SPI slave.
Definition: px_spi.c:568
void px_spi_wr(px_spi_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI write transaction with an SPI slave.
Definition: px_spi.c:396
void px_spi_rd(px_spi_handle_t *handle, void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI read transaction with an SPI slave.
Definition: px_spi.c:479
px_spi_nr_t
Specify SPI peripheral number.
Definition: px_spi.h:79
void px_spi_change_baud(px_spi_handle_t *handle, px_spi_baud_t baud)
Change SPI peripheral baud.
Definition: px_spi.c:657
uint32_t px_spi_util_clk_div_to_baud_hz(px_spi_baud_t baud)
Calculate the actual BAUD (in Hz) from the specified division.
Definition: px_spi.c:720
bool px_spi_open(px_spi_handle_t *handle, px_spi_nr_t spi_nr, uint8_t cs_id)
Open SPI peripheral using predefined (default) parameters.
Definition: px_spi.c:173
px_spi_baud_t
Specify SPI baud rate as a ratio of the peripheral clock.
Definition: px_spi.h:102
px_spi_baud_t px_spi_util_baud_hz_to_clk_div(uint32_t baud_hz)
Calculate clock divisor that will yield closest frequency equal to or less than specified baud rate (...
Definition: px_spi.c:698
Define SPI handle.
Definition: px_spi.h:126