GCC Code Coverage Report


Directory: src/drv/
File: src/drv/spi/src/spi_driver.c
Date: 2024-01-25 15:03:18
Exec Total Coverage
Lines: 0 154 0.0%
Branches: 0 78 0.0%

Line Branch Exec Source
1 /********************************************************************************************************//**
2 * @file spi_driver.c
3 *
4 * @brief File containing the APIs for configuring the SPI peripheral.
5 *
6 * Public Functions :
7 * - void SPI_Init(SPI_RegDef_t* pSPI_Handle)
8 * - void SPI_DeInit(SPI_RegDef_t* pSPIx)
9 * - void SPI_PerClkCtrl(SPI_RegDef_t* pSPIx, uint8_t en_or_di)
10 * - void SPI_SendData(SPI_RegDef_t* pSPIx, uint8_t* pTxBuffer, uint32_t len)
11 * - void SPI_ReceiveData(SPI_RegDef_t* pSPIx, uint8_t* pRxBuffer, uint32_t len)
12 * - uint8_t SPI_SendDataIT(SPI_Handle_t* pSPI_Handle, uint8_t* pTxBuffer, uint32_t len)
13 * - uint8_t SPI_ReceiveDataIT(SPI_Handle_t* pSPI_Handle, uint8_t* pRxBuffer, uint32_t len)
14 * - void SPI_IRQHandling(SPI_Handle_t* pSPI_Handle)
15 * - void SPI_Enable(SPI_RegDef_t *pSPIx, uint8_t en_or_di)
16 * - void SPI_SSICfg(SPI_RegDef_t* pSPIx, uint8_t en_or_di)
17 * - void SPI_SSOECfg(SPI_RegDef_t* pSPIx, uint8_t en_or_di)
18 * - uint8_t SPI_GetFlagStatus(SPI_RegDef_t* pSPIx, uint32_t flagname)
19 * - void SPI_ClearOVRFlag(SPI_RegDef_t* pSPIx)
20 * - void SPI_CloseTx(SPI_Handle_t* pSPI_Handle)
21 * - void SPI_CloseRx(SPI_Handle_t* pSPI_Handle)
22 * - void SPI_ApplicationEventCallback(SPI_Handle_t* pSPI_Handle, uint8_t app_event)
23 *
24 * @note
25 * For further information about functions refer to the corresponding header file.
26 **/
27
28 #include <stdint.h>
29 #include <stddef.h>
30 #include "spi_driver.h"
31
32 /***********************************************************************************************************/
33 /* Static Function Prototypes */
34 /***********************************************************************************************************/
35
36 /**
37 * @brief Function to handle transmission interrupt.
38 * @param[in] pSPI_Handle handle structure for the SPI peripheral.
39 * @return void
40 */
41 static void spi_txe_interrupt_handle(SPI_Handle_t* pSPI_Handle);
42
43 /**
44 * @brief Function to handle reception interrupt.
45 * @param[in] pSPI_Handle handle structure for the SPI peripheral.
46 * @return void
47 */
48 static void spi_rxne_interrupt_handle(SPI_Handle_t* pSPI_Handle);
49
50 /**
51 * @brief Function to handle error interrupt.
52 * @param[in] pSPI_Handle handle structure for the SPI peripheral.
53 * @return void
54 */
55 static void spi_ovr_err_interrupt_handle(SPI_Handle_t* pSPI_Handle);
56
57 /***********************************************************************************************************/
58 /* Public API Definitions */
59 /***********************************************************************************************************/
60
61 void SPI_Init(SPI_Handle_t* pSPI_Handle){
62
63 uint32_t temp = 0;
64
65 /* Enable the peripheral clock */
66 SPI_PerClkCtrl(pSPI_Handle->pSPIx, ENABLE);
67
68 /* Configure the SPI_CR1 register */
69 /* Configure the device mode */
70 temp |= pSPI_Handle->SPIConfig.SPI_DeviceMode << SPI_CR1_MSTR;
71
72 /* Configure the bus config */
73 if(pSPI_Handle->SPIConfig.SPI_BusConfig == SPI_BUS_CFG_FD){
74 /* BIDI mode should be cleared */
75 temp &= ~(1 << SPI_CR1_BIDI_MODE);
76 }
77 else if(pSPI_Handle->SPIConfig.SPI_BusConfig == SPI_BUS_CFG_HD){
78 /* BIDI mode should be set */
79 temp |= (1 << SPI_CR1_BIDI_MODE);
80 }
81 else if(pSPI_Handle->SPIConfig.SPI_BusConfig == SPI_BUS_CFG_S_RXONLY){
82 /* BIDI mode should be cleared */
83 temp &= ~(1 << SPI_CR1_BIDI_MODE);
84 /* RXONLY bit must be set */
85 temp |= (1 << SPI_CR1_RXONLY);
86 }
87
88 /* Configure the SPI serial clock speed (baud rate) */
89 temp |= pSPI_Handle->SPIConfig.SPI_SclkSpeed << SPI_CR1_BR;
90
91 /* Configure the DFF */
92 temp |= pSPI_Handle->SPIConfig.SPI_DFF << SPI_CR1_DFF;
93
94 /* Configure the CPOL */
95 temp |= pSPI_Handle->SPIConfig.SPI_CPOL << SPI_CR1_CPOL;
96
97 /* Configure the CPHA */
98 temp |= pSPI_Handle->SPIConfig.SPI_CPHA << SPI_CR1_CPHA;
99
100 /* Configure the SSM */
101 temp |= pSPI_Handle->SPIConfig.SPI_SSM << SPI_CR1_SSM;
102
103 pSPI_Handle->pSPIx->CR1 = temp;
104 }
105
106 void SPI_DeInit(SPI_RegDef_t* pSPIx){
107
108 if(pSPIx == SPI1){
109 SPI1_REG_RESET();
110 }
111 else if(pSPIx == SPI2){
112 SPI2_REG_RESET();
113 }
114 else if(pSPIx == SPI3){
115 SPI3_REG_RESET();
116 }
117 else if(pSPIx == SPI4){
118 SPI4_REG_RESET();
119 }
120 else{
121 /* do nothing */
122 }
123 }
124
125 void SPI_PerClkCtrl(SPI_RegDef_t* pSPIx, uint8_t en_or_di){
126
127 if(en_or_di == ENABLE){
128 if(pSPIx == SPI1){
129 SPI1_PCLK_EN();
130 }
131 else if(pSPIx == SPI2){
132 SPI2_PCLK_EN();
133 }
134 else if(pSPIx == SPI3){
135 SPI3_PCLK_EN();
136 }
137 else if(pSPIx == SPI4){
138 SPI4_PCLK_EN();
139 }
140 else{
141 /* do nothing */
142 }
143 }
144 else{
145 if(pSPIx == SPI1){
146 SPI1_PCLK_DI();
147 }
148 else if(pSPIx == SPI2){
149 SPI2_PCLK_DI();
150 }
151 else if(pSPIx == SPI3){
152 SPI3_PCLK_DI();
153 }
154 else if(pSPIx == SPI4){
155 SPI4_PCLK_DI();
156 }
157 else{
158 /* do nothing */
159 }
160 }
161 }
162
163 void SPI_SendData(SPI_RegDef_t* pSPIx, uint8_t* pTxBuffer, uint32_t len){
164
165 while(len > 0){
166 /* Wait until TXE is set */
167 while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG) == FLAG_RESET);
168 /* Check the DFF bit in CR1 */
169 if((pSPIx->CR1 & (1 << SPI_CR1_DFF))){
170 /* 16 bit DFF */
171 /* Load the data into the DR */
172 pSPIx->DR = *((uint16_t*)pTxBuffer);
173 len--;
174 len--;
175 (uint16_t*)pTxBuffer++;
176 }
177 else{
178 /* 8 bit DFF */
179 pSPIx->DR = *pTxBuffer;
180 len--;
181 pTxBuffer++;
182 }
183 }
184 }
185
186 void SPI_ReceiveData(SPI_RegDef_t* pSPIx, uint8_t* pRxBuffer, uint32_t len){
187
188 while(len > 0){
189 /* Wait until TXE is set */
190 while(SPI_GetFlagStatus(pSPIx, SPI_RXNE_FLAG) == FLAG_RESET);
191 /* Check the DFF bit in CR1 */
192 if((pSPIx->CR1 & (1 << SPI_CR1_DFF))){
193 /* 16 bit DFF */
194 /* Load the data from DR to RxBuffer address*/
195 *((uint16_t*)pRxBuffer) = pSPIx->DR;
196 len--;
197 len--;
198 (uint16_t*)pRxBuffer++;
199 }
200 else{
201 /* 8 bit DFF */
202 *pRxBuffer = pSPIx->DR;
203 len--;
204 pRxBuffer++;
205 }
206 }
207 }
208
209 uint8_t SPI_SendDataIT(SPI_Handle_t* pSPI_Handle, uint8_t* pTxBuffer, uint32_t len){
210
211 uint8_t state = pSPI_Handle->TxState;
212
213 if(state != SPI_BUSY_IN_TX){
214 /* Save the Tx buffer address and length information */
215 pSPI_Handle->pTxBuffer = pTxBuffer;
216 pSPI_Handle->TxLen = len;
217
218 /* Mark the SPI state as busy in transmission so that no other code can take over
219 * same SPI peripheral until transmission is over */
220 pSPI_Handle->TxState = SPI_BUSY_IN_TX;
221
222 /* Enable the TXEIE control bit to get interrupt whenever TXE flag is set in SR */
223 pSPI_Handle->pSPIx->CR2 |= (1 << SPI_CR2_TXEIE);
224 }
225
226 return state;
227 }
228
229 uint8_t SPI_ReceiveDataIT(SPI_Handle_t* pSPI_Handle, uint8_t* pRxBuffer, uint32_t len){
230
231 uint8_t state = pSPI_Handle->RxState;
232
233 if(state != SPI_BUSY_IN_RX){
234 /* Save the Rx buffer address and length information */
235 pSPI_Handle->pRxBuffer = pRxBuffer;
236 pSPI_Handle->RxLen = len;
237
238 /* Mark the SPI state as busy in reception so that no other code can take over
239 * same SPI peripheral until reception is over */
240 pSPI_Handle->RxState = SPI_BUSY_IN_RX;
241
242 /* Enable the RXEIE control bit to get interrupt whenever RXE flag is set in SR */
243 pSPI_Handle->pSPIx->CR2 |= (1 << SPI_CR2_RXNEIE);
244 }
245
246 return state;
247 }
248
249 void SPI_IRQHandling(SPI_Handle_t* pSPI_Handle){
250
251 uint8_t temp1, temp2;
252
253 /* Check for TXE */
254 temp1 = pSPI_Handle->pSPIx->SR & (1 << SPI_SR_TXE);
255 temp2 = pSPI_Handle->pSPIx->CR2 & (1 << SPI_CR2_TXEIE);
256
257 if(temp1 && temp2){
258 /* Handle TXE */
259 spi_txe_interrupt_handle(pSPI_Handle);
260 }
261
262 /* Check for RXNE */
263 temp1 = pSPI_Handle->pSPIx->SR & (1 << SPI_SR_RXNE);
264 temp2 = pSPI_Handle->pSPIx->CR2 & (1 << SPI_CR2_RXNEIE);
265
266 if(temp1 && temp2){
267 /* Handle RXE */
268 spi_rxne_interrupt_handle(pSPI_Handle);
269 }
270
271 /* Check for OVR flag */
272 temp1 = pSPI_Handle->pSPIx->SR & (1 << SPI_SR_OVR);
273 temp2 = pSPI_Handle->pSPIx->CR2 & (1 << SPI_CR2_ERRIE);
274
275 if(temp1 && temp2){
276 /* Handle OVR error */
277 spi_ovr_err_interrupt_handle(pSPI_Handle);
278 }
279 }
280
281 void SPI_Enable(SPI_RegDef_t *pSPIx, uint8_t en_or_di){
282
283 if(en_or_di == ENABLE){
284 pSPIx->CR1 |= (1 << SPI_CR1_SPE);
285 }
286 else{
287 pSPIx->CR1 &= ~(1 << SPI_CR1_SPE);
288 }
289 }
290
291 void SPI_SSICfg(SPI_RegDef_t* pSPIx, uint8_t en_or_di){
292
293 if(en_or_di == ENABLE){
294 pSPIx->CR1 |= (1 << SPI_CR1_SSI);
295 }
296 else{
297 pSPIx->CR1 &= ~(1 << SPI_CR1_SSI);
298 }
299 }
300
301 void SPI_SSOECfg(SPI_RegDef_t* pSPIx, uint8_t en_or_di){
302
303 if(en_or_di == ENABLE){
304 pSPIx->CR2 |= (1 << SPI_CR2_SSOE);
305 }
306 else{
307 pSPIx->CR2 &= ~(1 << SPI_CR2_SSOE);
308 }
309 }
310
311 uint8_t SPI_GetFlagStatus(SPI_RegDef_t* pSPIx, uint32_t flagname){
312
313 if(pSPIx->SR & flagname){
314 return FLAG_SET;
315 }
316 return FLAG_RESET;
317 }
318
319 void SPI_ClearOVRFlag(SPI_RegDef_t* pSPIx){
320
321 uint8_t temp;
322 temp = pSPIx->DR;
323 temp = pSPIx->SR;
324 (void)temp;
325 }
326
327 void SPI_CloseTx(SPI_Handle_t* pSPI_Handle){
328
329 pSPI_Handle->pSPIx->CR2 &= ~(1 << SPI_CR2_TXEIE);
330 pSPI_Handle->pTxBuffer = NULL;
331 pSPI_Handle->TxLen = 0;
332 pSPI_Handle->TxState = SPI_READY;
333 }
334
335 void SPI_CloseRx(SPI_Handle_t* pSPI_Handle){
336
337 pSPI_Handle->pSPIx->CR2 &= ~(1 << SPI_CR2_RXNEIE);
338 pSPI_Handle->pRxBuffer = NULL;
339 pSPI_Handle->RxLen = 0;
340 pSPI_Handle->RxState = SPI_READY;
341 }
342
343 __attribute__((weak)) void SPI_ApplicationEventCallback(SPI_Handle_t* pSPI_Handle, uint8_t app_event){
344
345 /* This is a weak implementation. The application may override this function */
346 (void)pSPI_Handle;
347 (void)app_event;
348 }
349
350 /***********************************************************************************************************/
351 /* Static Function Definitions */
352 /***********************************************************************************************************/
353
354 static void spi_txe_interrupt_handle(SPI_Handle_t* pSPI_Handle){
355
356 /* Check the DFF bit in CR1 */
357 if((pSPI_Handle->pSPIx->CR1 & (1 << SPI_CR1_DFF))){
358 /* 16 bit DFF */
359 /* Load the data from DR to RxBuffer address*/
360 pSPI_Handle->pSPIx->DR = *((uint16_t*)pSPI_Handle->pTxBuffer);
361 pSPI_Handle->TxLen--;
362 pSPI_Handle->TxLen--;
363 (uint16_t*)pSPI_Handle->pRxBuffer++;
364 }
365 else{
366 /* 8 bit DFF */
367 pSPI_Handle->pSPIx->DR = *pSPI_Handle->pTxBuffer;
368 pSPI_Handle->TxLen--;
369 pSPI_Handle->pRxBuffer++;
370 }
371
372 if(!pSPI_Handle->TxLen){
373 /* Close SPI transmission */
374 /* TX is over */
375 /* Prevents interrupts from setting up of TXE flag */
376 SPI_CloseTx(pSPI_Handle);
377 SPI_ApplicationEventCallback(pSPI_Handle, SPI_EVENT_TX_CMPLT);
378 }
379 }
380
381 static void spi_rxne_interrupt_handle(SPI_Handle_t* pSPI_Handle){
382
383 /* Check the DFF bit in CR1 */
384 if((pSPI_Handle->pSPIx->CR1 & (1 << SPI_CR1_DFF))){
385 /* 16 bit DFF */
386 /* Load the data from DR to RxBuffer address*/
387 *((uint16_t*)pSPI_Handle->pRxBuffer) = (uint16_t)pSPI_Handle->pSPIx->DR;
388 pSPI_Handle->RxLen -= 2;
389 pSPI_Handle->pRxBuffer--;
390 pSPI_Handle->pRxBuffer--;
391 }
392 else{
393 /* 8 bit DFF */
394 *(pSPI_Handle->pRxBuffer) = (uint8_t)pSPI_Handle->pSPIx->DR;
395 pSPI_Handle->RxLen--;
396 pSPI_Handle->pRxBuffer--;
397 }
398
399 if(!pSPI_Handle->RxLen){
400 /* RX is complete */
401 SPI_CloseRx(pSPI_Handle);
402 SPI_ApplicationEventCallback(pSPI_Handle, SPI_EVENT_RX_CMPLT);
403 }
404 }
405
406 static void spi_ovr_err_interrupt_handle(SPI_Handle_t* pSPI_Handle){
407
408 uint8_t temp;
409
410 /* Clear the OVR flag */
411 if(pSPI_Handle->TxState != SPI_BUSY_IN_TX){
412 temp = pSPI_Handle->pSPIx->DR;
413 temp = pSPI_Handle->pSPIx->SR;
414 (void)temp;
415 }
416
417 /* Inform the application */
418 SPI_ApplicationEventCallback(pSPI_Handle, SPI_EVENT_OVR_ERR);
419 }
420