Loading...
Searching...
No Matches
spi.c
1/***********************************************************************************
2 * @file spi.c *
3 * @author Matt Ricci *
4 * @addtogroup SPI *
5 * @brief Implements functions for SPI device interface initialization and *
6 * communication. *
7 * *
8 * @todo Rewrite initialisation to implement enum check for 8/16 bit mode *
9 * and assign approprriate function pointers *
10 ***********************************************************************************/
11
12#include "spi.h"
13
14#include "stddef.h"
15
16static void SPI_send8(SPI_t *, uint16_t);
17static void SPI_send16(SPI_t *, uint16_t);
18
19static void SPI_receive8(SPI_t *, volatile uint16_t *);
20static void SPI_receive16(SPI_t *, volatile uint16_t *);
21
22static void _SPI_init(SPI_TypeDef *, SPI_Config *);
23
24/* =============================================================================== */
36SPI_t SPI_init(SPI_TypeDef *interface, SPI_Config *config) {
37 // Early return error struct if peripheral is NULL
38 if (interface == NULL)
39 return (SPI_t){.interface = NULL};
40
41 // Initialise SPI struct with interface
42 SPI_t spi = {.interface = interface};
43
44 // Update config and enable peripheral
45 SPI_updateConfig(&spi, config);
46
47 // Initialise remaining parameters and methods
48 spi.send = (spi.config.DFF == SPI_DFF8) ? SPI_send8 : SPI_send16;
49 spi.receive = (spi.config.DFF == SPI_DFF8) ? SPI_receive8 : SPI_receive16;
52
53 return spi;
54}
55
56// ALLOW FORMATTING
57#ifndef DOXYGEN_PRIVATE
58
59/* =============================================================================== */
71static void _SPI_init(SPI_TypeDef *interface, SPI_Config *config) {
72 // Wait for any ongoing transactions to finish
73 while (interface->SR & SPI_SR_BSY);
74
75 // Disable peripheral and update config
76 config->SPE = false; // Make sure SPE is disabled in config
77 interface->CR1 = *(uint16_t *)config; // Update CR1 with configured values
78
79 // Re-enable peripheral
80 config->SPE = true; // Set SPE back to true
81 interface->CR1 = *(uint16_t *)config; // Update CR1 with SPE enabled
82}
83
84#endif
85
86/* =============================================================================== */
96uint16_t SPI_transmit(SPI_t *spi, uint16_t data) {
97 volatile uint16_t response;
98 spi->send(spi, data);
99 spi->receive(spi, &response);
100 while (spi->interface->SR & SPI_SR_BSY);
101 return response;
102}
103
104/* =============================================================================== */
114static void SPI_send8(SPI_t *spi, uint16_t data) {
115 while (!(spi->interface->SR & SPI_SR_TXE));
116 spi->interface->DR = (uint8_t)data;
117}
118
119static void SPI_send16(SPI_t *spi, uint16_t data) {
120 while (!(spi->interface->SR & SPI_SR_TXE));
121 spi->interface->DR = data;
122}
123
124/* =============================================================================== */
134static void SPI_receive8(SPI_t *spi, volatile uint16_t *data) {
135 while (!(spi->interface->SR & SPI_SR_RXNE));
136 *data = (uint8_t)spi->interface->DR;
137}
138
139/* =============================================================================== */
149static void SPI_receive16(SPI_t *spi, volatile uint16_t *data) {
150 while (!(spi->interface->SR & SPI_SR_RXNE));
151 *data = spi->interface->DR;
152}
153
154/* =============================================================================== */
166void SPI_updateConfig(SPI_t *spi, SPI_Config *config) {
167 // Initialise config with default values if passed NULL.
168 if (config == NULL) {
169 config = &SPI_CONFIG_DEFAULT;
170 }
171
172 // Update peripheral with new config
173 spi->config = *config;
174
175 // Initialise SPI registers and enable peripheral
176 _SPI_init(spi->interface, config);
177}
#define SPI_SR_RXNE
#define SPI_SR_TXE
#define SPI_SR_BSY
__IO uint32_t DR
__IO uint32_t CR1
__IO uint32_t SR
Serial Peripheral Interface.
SPI_DataFormat DFF
SPI data format | (default SPI_DFF8)
Definition spi.h:123
void(* send)(struct SPI *, uint16_t)
SPI send method.
Definition spi.h:137
uint16_t(* transmit)(struct SPI *, uint16_t)
SPI transmit method.
Definition spi.h:139
bool SPE
SPI enable | (default false)
Definition spi.h:118
void(* updateConfig)(struct SPI *, SPI_Config *)
SPI configuration update method.
Definition spi.h:140
SPI_Config config
Configuration parameters for the SPI peripheral.
Definition spi.h:136
void(* receive)(struct SPI *, volatile uint16_t *)
SPI receive method.
Definition spi.h:138
SPI_TypeDef * interface
Pointer to SPI interface struct.
Definition spi.h:135
SPI_t SPI_init(SPI_TypeDef *interface, SPI_Config *config)
Initialiser for an SPI device interface.
Definition spi.c:36
uint16_t SPI_transmit(SPI_t *, uint16_t)
Instance method to communicate a SPI transaction with slave device.
Definition spi.c:96
void SPI_updateConfig(SPI_t *spi, SPI_Config *config)
Update SPI peripheral configuration.
Definition spi.c:166
SPI CR1 configuration struct.
Definition spi.h:113
Struct definition for SPI interface. Provides the interface for API consumers to interact with the SP...
Definition spi.h:134