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