1 /*!
2 * @file apm32s10x_spi.c
3 *
4 * @brief This file provides all the SPI firmware functions
5 *
6 * @version V1.0.1
7 *
8 * @date 2022-12-31
9 *
10 * @attention
11 *
12 * Copyright (C) 2022-2023 Geehy Semiconductor
13 *
14 * You may not use this file except in compliance with the
15 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16 *
17 * The program is only for reference, which is distributed in the hope
18 * that it will be usefull and instructional for customers to develop
19 * their software. Unless required by applicable law or agreed to in
20 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23 * and limitations under the License.
24 */
25
26 /* Includes */
27 #include "apm32s10x_spi.h"
28 #include "apm32s10x_rcm.h"
29
30 /** @addtogroup APM32S10x_StdPeriphDriver
31 @{
32 */
33
34 /** @addtogroup SPI_Driver SPI Driver
35 @{
36 */
37
38 /** @defgroup SPI_Functions Functions
39 @{
40 */
41
42 /*!
43 * @brief Reset the specified SPIx peripheral
44 *
45 * @param spi: The SPIx can be 1,2
46 *
47 * @retval None
48 */
SPI_Reset(SPI_T * spi)49 void SPI_Reset(SPI_T* spi)
50 {
51 if (spi == SPI1)
52 {
53 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
54 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
55 }
56 else if (spi == SPI2)
57 {
58 RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2);
59 RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2);
60 }
61 }
62
63 /*!
64 * @brief Configure the SPI peripheral according to the specified parameters in the spiConfig
65 *
66 * @param spi: The SPIx can be 1,2
67 *
68 * @param spiConfig: pointer to a SPI_Config_T structure
69 *
70 * @retval None
71 */
SPI_Config(SPI_T * spi,SPI_Config_T * spiConfig)72 void SPI_Config(SPI_T* spi, SPI_Config_T* spiConfig)
73 {
74 spi->CTRL1 &= 0x3040;
75 spi->CTRL1 |= (uint16_t)((uint32_t)spiConfig->direction | spiConfig->mode |
76 spiConfig->length | spiConfig->polarity |
77 spiConfig->phase | spiConfig->nss |
78 spiConfig->baudrateDiv | spiConfig->firstBit);
79 spi->CRCPOLY = spiConfig->crcPolynomial;
80 }
81
82 /*!
83 * @brief Fill each SPI_Config_T member with its default value
84 *
85 * @param spiConfig: pointer to a SPI_Config_T structure
86 *
87 * @retval None
88 */
SPI_ConfigStructInit(SPI_Config_T * spiConfig)89 void SPI_ConfigStructInit(SPI_Config_T* spiConfig)
90 {
91 spiConfig->direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
92 spiConfig->mode = SPI_MODE_SLAVE;
93 spiConfig->length = SPI_DATA_LENGTH_8B;
94 spiConfig->polarity = SPI_CLKPOL_LOW;
95 spiConfig->phase = SPI_CLKPHA_1EDGE;
96 spiConfig->nss = SPI_NSS_HARD;
97 spiConfig->baudrateDiv = SPI_BAUDRATE_DIV_2;
98 spiConfig->firstBit = SPI_FIRSTBIT_MSB;
99 spiConfig->crcPolynomial = 7;
100 }
101
102 /*!
103 * @brief Enable the specified SPI peripheral
104 *
105 * @param spi: The SPIx can be 1,2
106 *
107 * @retval None
108 */
SPI_Enable(SPI_T * spi)109 void SPI_Enable(SPI_T* spi)
110 {
111 spi->CTRL1_B.SPIEN = BIT_SET;
112 }
113
114 /*!
115 * @brief Disable the specified SPI peripheral
116 *
117 * @param spi: The SPIx can be 1,2
118 *
119 * @retval None
120 */
SPI_Disable(SPI_T * spi)121 void SPI_Disable(SPI_T* spi)
122 {
123 spi->CTRL1_B.SPIEN = BIT_RESET;
124 }
125
126 /*!
127 * @brief Enable the SPIx DMA interface.
128 *
129 * @param spi: The SPIx can be 1,2
130 *
131 * @param dmaReq: specify the SPI DMA transfer request
132 * The parameter can be one of following values:
133 * @arg SPI_DMA_REQ_TX: Tx buffer DMA transfer request
134 * @arg SPI_DMA_REQ_RX: Rx buffer DMA transfer request
135 * @retval None
136 */
SPI_EnableDMA(SPI_T * spi,SPI_DMA_REQ_T dmaReq)137 void SPI_EnableDMA(SPI_T* spi, SPI_DMA_REQ_T dmaReq)
138 {
139 if (dmaReq == SPI_DMA_REQ_TX)
140 {
141 spi->CTRL2_B.TXDEN = ENABLE;
142 }
143 else
144 {
145 spi->CTRL2_B.RXDEN = ENABLE;
146 }
147 }
148
149 /*!
150 * @brief Disable the SPIx DMA interface.
151 *
152 * @param spi: The SPIx can be 1,2
153 *
154 * @param dmaReq: specify the SPI DMA transfer request
155 * The parameter can be one of following values:
156 * @arg SPI_DMA_REQ_TX: Tx buffer DMA transfer request
157 * @arg SPI_DMA_REQ_RX: Rx buffer DMA transfer request
158 * @retval None
159 */
SPI_DisableDMA(SPI_T * spi,SPI_DMA_REQ_T dmaReq)160 void SPI_DisableDMA(SPI_T* spi, SPI_DMA_REQ_T dmaReq)
161 {
162 if (dmaReq == SPI_DMA_REQ_TX)
163 {
164 spi->CTRL2_B.TXDEN = DISABLE;
165 }
166 else
167 {
168 spi->CTRL2_B.RXDEN = DISABLE;
169 }
170 }
171
172 /*!
173 * @brief Transmit a Data through the SPIx peripheral.
174 *
175 * @param spi: The SPIx can be 1,2
176 *
177 * @param data: Data to be transmitted
178 *
179 * @retval None
180 */
SPI_TxData(SPI_T * spi,uint16_t data)181 void SPI_TxData(SPI_T* spi, uint16_t data)
182 {
183 spi->DATA = data;
184 }
185
186 /*!
187 * @brief Return the most recent received data by the SPIx peripheral.
188 *
189 * @param spi: The SPIx can be 1,2
190 *
191 * @retval data :The value of the received data
192 *
193 * @retval None
194 */
SPI_RxData(SPI_T * spi)195 uint16_t SPI_RxData(SPI_T* spi)
196 {
197 return spi->DATA;
198 }
199
200 /*!
201 * @brief Set the SPI NSS internal by Software
202 *
203 * @param spi: The SPIx can be 1,2
204 *
205 * @retval None
206 */
SPI_SetSoftwareNSS(SPI_T * spi)207 void SPI_SetSoftwareNSS(SPI_T* spi)
208 {
209 spi->CTRL1_B.ISSEL = BIT_SET;
210 }
211
212 /*!
213 * @brief Reset the SPI NSS internal by Software
214 *
215 * @param spi: The SPIx can be 1,2
216 *
217 * @retval None
218 */
SPI_ResetSoftwareNSS(SPI_T * spi)219 void SPI_ResetSoftwareNSS(SPI_T* spi)
220 {
221 spi->CTRL1_B.ISSEL = BIT_RESET;
222 }
223
224 /*!
225 * @brief Enable the specified SPI SS output
226 *
227 * @param spi: The SPIx can be 1,2
228 *
229 * @retval None
230 */
SPI_EnableSSOutput(SPI_T * spi)231 void SPI_EnableSSOutput(SPI_T* spi)
232 {
233 spi->CTRL2_B.SSOEN = BIT_SET;
234 }
235
236 /*!
237 * @brief Disable the specified SPI SS output
238 *
239 * @param spi: The SPIx can be 1,2
240 *
241 * @retval None
242 */
SPI_DisableSSOutput(SPI_T * spi)243 void SPI_DisableSSOutput(SPI_T* spi)
244 {
245 spi->CTRL2_B.SSOEN = BIT_RESET;
246 }
247
248 /*!
249 * @brief Configure the specified SPI data size
250 *
251 * @param spi: The SPIx can be 1,2
252 *
253 * @param length: specify the SPI data size.
254 * This parameter can be one of the following values:
255 * @arg SPI_DATA_LENGTH_16B: Set data frame format to 16bit
256 * @arg SPI_DATA_LENGTH_8B : Set data frame format to 8bit
257 *
258 * @retval None
259 */
SPI_ConfigDataSize(SPI_T * spi,SPI_DATA_LENGTH_T length)260 void SPI_ConfigDataSize(SPI_T* spi, SPI_DATA_LENGTH_T length)
261 {
262 spi->CTRL1_B.DFLSEL = BIT_RESET;
263 spi->CTRL1 |= length;
264 }
265
266 /*!
267 * @brief Transmit CRC value
268 *
269 * @param spi: The SPIx can be 1,2
270 *
271 * @retval None
272 */
SPI_TxCRC(SPI_T * spi)273 void SPI_TxCRC(SPI_T* spi)
274 {
275 spi->CTRL1_B.CRCNXT = BIT_SET;
276 }
277
278 /*!
279 * @brief Enable the specified SPI CRC value calculation of the transferred bytes
280 *
281 * @param spi: The SPIx can be 1,2
282 *
283 * @retval None
284 */
SPI_EnableCRC(SPI_T * spi)285 void SPI_EnableCRC(SPI_T* spi)
286 {
287 spi->CTRL1_B.CRCEN = BIT_SET;
288 }
289
290 /*!
291 * @brief Disable the specified SPI CRC value calculation of the transferred bytes
292 *
293 * @param spi: The SPIx can be 1,2
294 *
295 * @retval None
296 */
SPI_DisableCRC(SPI_T * spi)297 void SPI_DisableCRC(SPI_T* spi)
298 {
299 spi->CTRL1_B.CRCEN = BIT_RESET;
300 }
301
302 /*!
303 * @brief Read the specified SPI transmit CRC register value
304 *
305 * @param spi: The SPIx can be 1,2
306 *
307 * @retval The SPI transmit CRC register value
308 */
SPI_ReadTxCRC(SPI_T * spi)309 uint16_t SPI_ReadTxCRC(SPI_T* spi)
310 {
311 return spi->TXCRC_B.TXCRC;
312 }
313
314 /*!
315 * @brief Read the specified SPI receive CRC register value
316 *
317 * @param spi: The SPIx can be 1,2
318 *
319 * @retval The SPI receive CRC register value
320 */
SPI_ReadRxCRC(SPI_T * spi)321 uint16_t SPI_ReadRxCRC(SPI_T* spi)
322 {
323 return spi->RXCRC_B.RXCRC;
324 }
325
326 /*!
327 * @brief Read the specified SPI CRC Polynomial register value
328 *
329 * @param spi: The SPIx can be 1,2
330 *
331 * @retval The SPI CRC Polynomial register value
332 */
SPI_ReadCRCPolynomial(SPI_T * spi)333 uint16_t SPI_ReadCRCPolynomial(SPI_T* spi)
334 {
335 return spi->CRCPOLY_B.CRCPOLY;
336 }
337
338 /*!
339 * @brief Configure the specified SPI data transfer direction
340 *
341 * @param spi: The SPIx can be 1,2
342 *
343 * @param direction: Select the SPI data transfer direction
344 * The parameter can be one of following values:
345 * @arg SPI_DIRECTION_RX: Selects Rx receive direction
346 * @arg SPI_DIRECTION_TX: Selects Tx transmission direction
347 *
348 * @retval None
349 */
SPI_ConfigBiDirectionalLine(SPI_T * spi,SPI_DIRECTION_SELECT_T direction)350 void SPI_ConfigBiDirectionalLine(SPI_T* spi, SPI_DIRECTION_SELECT_T direction)
351 {
352 if (direction == SPI_DIRECTION_TX)
353 {
354 spi->CTRL1 |= SPI_DIRECTION_TX;
355 }
356 else
357 {
358 spi->CTRL1 &= SPI_DIRECTION_RX;
359 }
360 }
361
362 /*!
363 * @brief Enable the specified SPI interrupts.
364 *
365 * @param spi: The SPIx can be 1,2
366 *
367 * @param interrupt: specify the TMR interrupts sources
368 * The parameter can be one of following values:
369 * @arg SPI_INT_TXBE: Tx buffer empty interrupt
370 * @arg SPI_INT_RXBNE: Rx buffer not empty interrupt
371 * @arg SPI_INT_ERR: Error interrupt
372 *
373 * @retval None
374 */
SPI_EnableInterrupt(SPI_T * spi,SPI_INT_T interrupt)375 void SPI_EnableInterrupt(SPI_T* spi, SPI_INT_T interrupt)
376 {
377 spi->CTRL2 |= (interrupt >> 8);
378 }
379
380 /*!
381 * @brief Disable the specified SPI interrupts.
382 *
383 * @param spi: The SPIx can be 1,2
384 *
385 * @param interrupt: specify the TMR interrupts sources
386 * The parameter can be one of following values:
387 * @arg SPI_INT_TXBE: Tx buffer empty interrupt
388 * @arg SPI_INT_RXBNE: Rx buffer not empty interrupt
389 * @arg SPI_INT_ERR: Error interrupt
390 * @retval None
391 */
SPI_DisableInterrupt(SPI_T * spi,SPI_INT_T interrupt)392 void SPI_DisableInterrupt(SPI_T* spi, SPI_INT_T interrupt)
393 {
394 spi->CTRL2 &= ~(interrupt >> 8);
395 }
396
397 /*!
398 * @brief Check whether the specified SPI flag is set or not.
399 *
400 * @param spi: The SPIx can be 1,2
401 *
402 * @param flag: specify the SPI flag to check
403 * The parameter can be one of following values:
404 * @arg SPI_FLAG_RXBNE: Receive buffer not empty flag
405 * @arg SPI_FLAG_TXBE: Transmit buffer empty flag
406 * @arg SPI_FLAG_SCHDIR: Side Channel flag
407 * @arg SPI_FLAG_UDR: Underrun Error flag
408 * @arg SPI_FLAG_CRCE: CRC Error flag
409 * @arg SPI_FLAG_ME: Mode Error flag
410 * @arg SPI_FLAG_OVR: Overrun flag
411 * @arg SPI_FLAG_BSY: Busy flag
412 *
413 * @retval SET or RESET
414 */
SPI_ReadStatusFlag(SPI_T * spi,SPI_FLAG_T flag)415 uint8_t SPI_ReadStatusFlag(SPI_T* spi, SPI_FLAG_T flag)
416 {
417 if ((spi->STS & flag) != RESET)
418 {
419 return SET;
420 }
421 else
422 {
423 return RESET;
424 }
425 }
426
427 /*!
428 * @brief Clear the SPIx CRC Error flag
429 *
430 * @param spi: The SPIx can be 1,2
431 *
432 * @param flag: only clear SPI_FLAG_CRCE(CRC Error flag)
433 *
434 * @retval None
435 *
436 * @note 1)SPI_FLAG_OVR: (OverRun error) flag is cleared by software sequence:
437 * a read operation to SPI_DATA register (SPI_RxData())
438 * followed by a read operation to SPI_STS register (SPI_ReadStatusFlag()).
439 * 2)SPI_FLAG_UDR: (UnderRun error) flag is cleared:
440 * a read operation to SPI_STS register (SPI_ReadStatusFlag()).
441 * 3)SPI_FLAG_ME: (Mode Fault) flag is cleared by software sequence:
442 * a read/write operation to SPI_STS register (SPI_ReadStatusFlag())
443 * followed by a write operation to SPI_CTRL1 register (SPI_Enable()).
444 */
SPI_ClearStatusFlag(SPI_T * spi,SPI_FLAG_T flag)445 void SPI_ClearStatusFlag(SPI_T* spi, SPI_FLAG_T flag)
446 {
447 spi->STS_B.CRCEFLG = BIT_RESET;
448 }
449
450 /*!
451 * @brief Check whether the specified SPI interrupt has occurred or not.
452 *
453 * @param spi: The SPIx can be 1,2
454 *
455 * @param flag: specify the SPI interrupt flag to check.
456 * The parameter can be one of following values:
457 * @arg SPI_INT_RXBNE : Receive buffer not empty interrupt flag
458 * @arg SPI_INT_TXBE : Transmit buffer empty interrupt flag
459 * @arg SPI_INT_OVR : Overrun interrupt flag
460 * @arg SPI_INT_CRCE : CRC Error interrupt flag
461 * @arg SPI_INT_ME : Mode Error interrupt flag
462 * @arg SPI_INT_UDR : Underrun Error interrupt flag
463 *
464 * @retval SET or RESET
465 */
SPI_ReadIntFlag(SPI_T * spi,SPI_INT_T flag)466 uint8_t SPI_ReadIntFlag(SPI_T* spi, SPI_INT_T flag)
467 {
468 uint32_t intEnable;
469 uint32_t intStatus;
470
471 intEnable = (uint32_t)(spi->CTRL2 & (flag >> 8));
472 intStatus = (uint32_t)(spi->STS & flag);
473
474 if (intEnable && intStatus)
475 {
476 return SET;
477 }
478
479 return RESET;
480 }
481
482 /*!
483 * @brief Clear the SPIx CRC Error interrupt flag
484 *
485 * @param spi: The SPIx can be 1,2
486 *
487 * @param flag: only clear SPI_INT_CRCE(CRC Error interrupt flag)
488 *
489 * @retval None
490 *
491 * @note 1)SPI_INT_OVR: (OverRun interrupt error) flag is cleared by software sequence:
492 * a read operation to SPI_DATA register (SPI_RxData())
493 * followed by a read operation to SPI_STS register (SPI_ReadIntFlag()).
494 * 2)SPI_INT_UDR: (UnderRun interrupt error) flag is cleared:
495 * a read operation to SPI_STS register (SPI_ReadIntFlag()).
496 * 3)SPI_INT_ME: (Mode interrupt Fault) flag is cleared by software sequence:
497 * a read/write operation to SPI_STS register (SPI_ReadIntFlag())
498 * followed by a write operation to SPI_CTRL1 register (SPI_Enable()).
499 */
SPI_ClearIntFlag(SPI_T * spi,SPI_INT_T flag)500 void SPI_ClearIntFlag(SPI_T* spi, SPI_INT_T flag)
501 {
502 spi->STS_B.CRCEFLG = BIT_RESET;
503 }
504
505 /**@} end of group SPI_Functions */
506 /**@} end of group SPI_Driver */
507 /**@} end of group APM32S10x_StdPeriphDriver */
508