1 /******************************************************************************
2 * Copyright (C) 2016, Huada Semiconductor Co.,Ltd All rights reserved.
3 *
4 * This software is owned and published by:
5 * Huada Semiconductor Co.,Ltd ("HDSC").
6 *
7 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
8 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
9 *
10 * This software contains source code for use with HDSC
11 * components. This software is licensed by HDSC to be adapted only
12 * for use in systems utilizing HDSC components. HDSC shall not be
13 * responsible for misuse or illegal use of this software for devices not
14 * supported herein. HDSC is providing this software "AS IS" and will
15 * not be responsible for issues arising from incorrect user implementation
16 * of the software.
17 *
18 * Disclaimer:
19 * HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
20 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
21 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
22 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
23 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
24 * WARRANTY OF NONINFRINGEMENT.
25 * HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
26 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
27 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
28 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
29 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
31 * SAVINGS OR PROFITS,
32 * EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
34 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
35 * FROM, THE SOFTWARE.
36 *
37 * This software may be replicated in part or whole for the licensed use,
38 * with the restriction that this Disclaimer and Copyright notice must be
39 * included with eaenCh copy of this software, whether used in part or whole,
40 * at all times.
41 */
42 /*****************************************************************************/
43 /** \file spi.c
44 **
45 ** SPI driver API.
46 ** @link Driver Group Some description @endlink
47 **
48 ** - 2018-05-17 1.0 Devi First version for Device Driver Library of
49 ** Module.
50 **
51 *****************************************************************************/
52
53 /******************************************************************************
54 * Include files
55 *****************************************************************************/
56 #include "spi.h"
57
58 /**
59 ******************************************************************************
60 ** \addtogroup SpiGroup
61 *****************************************************************************/
62 //@{
63
64 /******************************************************************************
65 * Local pre-processor symbols/macros ('#define')
66 *****************************************************************************/
67
68 #define IS_VALID_STAT(x) ( SpiIf == (x)||\
69 SpiSserr == (x)||\
70 SpiBusy == (x)||\
71 SpiMdf == (x)||\
72 SpiTxe == (x)||\
73 SpiRxne == (x))
74 #define IS_VALID_CH(x) ( Spi0 == (x)||\
75 Spi1 == (x))
76
77
78 /******************************************************************************/
79 /* Local function prototypes ('static') */
80 /******************************************************************************/
81
82 /******************************************************************************/
83 /* Local variable prototypes ('static') */
84 /******************************************************************************/
85 static func_ptr_t pfnSpi0Callback = NULL; ///< callback function pointer for SPI Irq
86 static func_ptr_t pfnSpi1Callback = NULL; ///< callback function pointer for SPI Irq
87 /**
88 ******************************************************************************
89 ** \brief SPI 中断处理函数
90 **
91 ** \param [in] enCh通道
92 **
93 ** \retval 无
94 **
95 ******************************************************************************/
Spi_IRQHandler(en_spi_channel_t enCh)96 void Spi_IRQHandler(en_spi_channel_t enCh)
97 {
98 if(Spi0 == enCh)
99 {
100 if(NULL != pfnSpi0Callback)
101 {
102 pfnSpi0Callback();
103 }
104 }
105 else
106 {
107 if(NULL != pfnSpi1Callback)
108 {
109 pfnSpi1Callback();
110 }
111
112 }
113 }
114 /**
115 ******************************************************************************
116 ** \brief SPI 请求状态获取
117 **
118 ** \param [in]enCh 通道
119 **
120 ** \retval 请求状态
121 **
122 ******************************************************************************/
Spi_GetState(en_spi_channel_t enCh)123 uint8_t Spi_GetState(en_spi_channel_t enCh)
124 {
125 uint8_t u8State = 0;
126 ASSERT(IS_VALID_CH(enCh));
127 if(Spi0 == enCh)
128 {
129 u8State = M0P_SPI0->STAT;
130 }
131 else
132 {
133 u8State = M0P_SPI1->STAT;
134 }
135 return u8State;
136 }
137 /**
138 ******************************************************************************
139 ** \brief SPI 请求状态获取
140 **
141 ** \param [in]enCh 通道, enStatus 获取请求
142 **
143 ** \retval 请求状态
144 **
145 ******************************************************************************/
Spi_GetStatus(en_spi_channel_t enCh,en_spi_status_t enStatus)146 boolean_t Spi_GetStatus(en_spi_channel_t enCh,en_spi_status_t enStatus)
147 {
148 boolean_t bFlag = FALSE;
149 ASSERT(IS_VALID_CH(enCh));
150 ASSERT(IS_VALID_STAT(enStatus));
151 if(Spi0 == enCh)
152 {
153 switch (enStatus)
154 {
155 case SpiIf:
156 bFlag = M0P_SPI0->STAT_f.SPIF;
157 break;
158 case SpiSserr:
159 bFlag = M0P_SPI0->STAT_f.SSERR;
160 break;
161 case SpiMdf:
162 bFlag = M0P_SPI0->STAT_f.MDF;
163 break;
164 case SpiBusy:
165 bFlag = M0P_SPI0->STAT_f.BUSY;
166 break;
167 case SpiTxe:
168 bFlag = M0P_SPI0->STAT_f.TXE;
169 break;
170 case SpiRxne:
171 bFlag = M0P_SPI0->STAT_f.RXNE;
172 break;
173 default:
174 break;
175 }
176 }
177 else
178 {
179 switch (enStatus)
180 {
181 case SpiIf:
182 bFlag = M0P_SPI1->STAT_f.SPIF;
183 break;
184 case SpiSserr:
185 bFlag = M0P_SPI1->STAT_f.SSERR;
186 break;
187 case SpiMdf:
188 bFlag = M0P_SPI1->STAT_f.MDF;
189 break;
190 case SpiBusy:
191 bFlag = M0P_SPI1->STAT_f.BUSY;
192 break;
193 case SpiTxe:
194 bFlag = M0P_SPI1->STAT_f.TXE;
195 break;
196 case SpiRxne:
197 bFlag = M0P_SPI1->STAT_f.RXNE;
198 break;
199 default:
200 break;
201 }
202 }
203 return bFlag;
204 }
205 /**
206 ******************************************************************************
207 ** \brief SPI中断清除
208 **
209 ** \param [in]enCh 通道, enStatus 获取请求
210 **
211 ** \retval 请求状态
212 **
213 ******************************************************************************/
Spi_ClearStatus(en_spi_channel_t enCh)214 en_result_t Spi_ClearStatus(en_spi_channel_t enCh)
215 {
216 en_result_t enRet = Error;
217 ASSERT(IS_VALID_CH(enCh));
218 if(Spi0 == enCh)
219 {
220 M0P_SPI0->ICLR_f.INT_CLR = 0;
221 }
222 else
223 {
224 M0P_SPI1->ICLR_f.INT_CLR = 0;
225 }
226 enRet = Ok;
227 return enRet;
228 }
229 /**
230 ******************************************************************************
231 ** \brief SPI 功能使能禁止函数
232 **
233 ** \param [in] enCh通道,enFunc功能,bFlag 0/1使能或禁止
234 **
235 ** \retval Ok初始化成功
236 ** \retval ErrorInvalidParameter 初始化错误
237 ******************************************************************************/
Spi_FuncEn(en_spi_channel_t enCh,en_spi_func_t enFunc,boolean_t bFlag)238 en_result_t Spi_FuncEn(en_spi_channel_t enCh,en_spi_func_t enFunc,boolean_t bFlag)
239 {
240 en_result_t enRet = Error;
241 ASSERT(IS_VALID_CH(enCh));
242 if(Spi0 == enCh)
243 {
244 switch(enFunc)
245 {
246 case SpiRxNeIe:
247 M0P_SPI0->CR2_f.RXNEIE = bFlag;
248 break;
249 case SpiTxEIe:
250 M0P_SPI0->CR2_f.TXEIE = bFlag;
251 break;
252 case SpiDmaTxEn:
253 M0P_SPI0->CR2_f.HDMA_TX = bFlag;
254 break;
255 case SpiDmaRxEn:
256 M0P_SPI0->CR2_f.HDMA_RX = bFlag;
257 break;
258 default:
259 return ErrorInvalidParameter;
260 }
261 }
262 else
263 {
264 switch(enFunc)
265 {
266 case SpiRxNeIe:
267 M0P_SPI1->CR2_f.RXNEIE = bFlag;
268 break;
269 case SpiTxEIe:
270 M0P_SPI1->CR2_f.TXEIE = bFlag;
271 break;
272 case SpiDmaTxEn:
273 M0P_SPI1->CR2_f.HDMA_TX = bFlag;
274 break;
275 case SpiDmaRxEn:
276 M0P_SPI1->CR2_f.HDMA_RX = bFlag;
277 break;
278 default:
279 return ErrorInvalidParameter;
280 }
281 }
282 enRet = Ok;
283 return enRet;
284 }
285 /**
286 ******************************************************************************
287 ** \brief SPI 总体初始化函数
288 **
289 ** \param [in]
290 enCh通道
291 pstcSpiConfig初始化结构
292 **
293 ** \retval Ok初始化成功
294 ** \retval ErrorInvalidParameter 初始化错误
295 ******************************************************************************/
Spi_Init(en_spi_channel_t enCh,stc_spi_config_t * pstcSpiConfig)296 en_result_t Spi_Init(en_spi_channel_t enCh,stc_spi_config_t *pstcSpiConfig)
297 {
298 ASSERT(NULL != pstcSpiConfig);
299 ASSERT(IS_VALID_CH(enCh));
300 if(Spi0 == enCh)
301 {
302 M0P_SPI0->CR = 0x00;
303
304 M0P_SPI0->CR_f.MSTR = pstcSpiConfig->bMasterMode;
305 M0P_SPI0->CR_f.CPOL = pstcSpiConfig->bCPOL;
306 M0P_SPI0->CR_f.CPHA = pstcSpiConfig->bCPHA;
307 if(pstcSpiConfig->u8BaudRate > SpiClkDiv16)
308 {
309 M0P_SPI0->CR_f.SPR2 = 1;
310 }
311 M0P_SPI0->CR |= (pstcSpiConfig->u8BaudRate&0x03u);
312
313 M0P_SPI0->STAT = 0x00;
314
315 M0P_SPI0->CR_f.SPEN = TRUE;
316 if (TRUE == pstcSpiConfig->bIrqEn)
317 {
318 M0P_SPI0->CR2_f.INT_EN = 1;
319 EnableNvic(SPI0_IRQn,IrqLevel3,TRUE);
320 }
321 else
322 {
323 EnableNvic(SPI0_IRQn,IrqLevel3,FALSE);
324 }
325 if(NULL != pstcSpiConfig->pfnSpi0IrqCb)
326 {
327 pfnSpi0Callback = pstcSpiConfig->pfnSpi0IrqCb;
328 }
329 }
330 else
331 {
332 M0P_SPI1->CR = 0x00;
333
334 M0P_SPI1->CR_f.MSTR = pstcSpiConfig->bMasterMode;
335 M0P_SPI1->CR_f.CPOL = pstcSpiConfig->bCPOL;
336 M0P_SPI1->CR_f.CPHA = pstcSpiConfig->bCPHA;
337 if(pstcSpiConfig->u8BaudRate > SpiClkDiv16)
338 {
339 M0P_SPI1->CR_f.SPR2 = 1;
340 }
341 M0P_SPI1->CR |= (pstcSpiConfig->u8BaudRate&0x03u);
342
343 M0P_SPI1->STAT = 0x00;
344
345 M0P_SPI1->CR_f.SPEN = TRUE;
346 if (TRUE == pstcSpiConfig->bIrqEn)
347 {
348 M0P_SPI1->CR2_f.INT_EN = 1;
349 EnableNvic(SPI1_IRQn,IrqLevel3,TRUE);
350 }
351 else
352 {
353 EnableNvic(SPI1_IRQn,IrqLevel3,FALSE);
354 }
355 if(NULL != pstcSpiConfig->pfnSpi1IrqCb)
356 {
357 pfnSpi1Callback = pstcSpiConfig->pfnSpi1IrqCb;
358 }
359 }
360 return Ok;
361 }
362
363 /**
364 ******************************************************************************
365 ** \brief SPI 禁止函数
366 **
367 ** \param [in] enCh通道
368 **
369 ** \retval Ok禁止设置成功
370 **
371 ******************************************************************************/
Spi_DeInit(en_spi_channel_t enCh)372 en_result_t Spi_DeInit(en_spi_channel_t enCh)
373 {
374 ASSERT(IS_VALID_CH(enCh));
375 if(Spi0 == enCh)
376 {
377 M0P_SPI0->DATA = 0x00;
378 M0P_SPI0->STAT = 0x00;
379 M0P_SPI0->CR = 0x00;
380 pfnSpi0Callback = NULL;
381 EnableNvic(SPI0_IRQn,IrqLevel3,FALSE);
382 }
383 else
384 {
385 M0P_SPI1->DATA = 0x00;
386 M0P_SPI1->STAT = 0x00;
387 M0P_SPI1->CR = 0x00;
388 pfnSpi1Callback = NULL;
389 EnableNvic(SPI1_IRQn,IrqLevel3,FALSE);
390 }
391 return Ok;
392 }
393 /**
394 ******************************************************************************
395 ** \brief SPI 配置主发送的电平
396 **
397 ** \param [in] 高低电平
398 **
399 ** \retval 无
400 **
401 ******************************************************************************/
Spi_SetCS(en_spi_channel_t enCh,boolean_t bFlag)402 void Spi_SetCS(en_spi_channel_t enCh,boolean_t bFlag)
403 {
404 ASSERT(IS_VALID_CH(enCh));
405 if(Spi0 == enCh)
406 {
407 M0P_SPI0->SSN = bFlag;
408 }
409 else
410 {
411 M0P_SPI1->SSN = bFlag;
412 }
413 }
414 /**
415 ******************************************************************************
416 ** \brief SPI 发送一字节函数
417 **
418 ** \param [in] enCh通道,u8Data发送字节
419 **
420 ** \retval Ok发送成功
421 **
422 ******************************************************************************/
Spi_SendData(en_spi_channel_t enCh,uint8_t u8Data)423 en_result_t Spi_SendData(en_spi_channel_t enCh,uint8_t u8Data)
424 {
425 uint32_t u32TimeOut;
426 ASSERT(IS_VALID_CH(enCh));
427 u32TimeOut = 1000;
428 if(Spi0 == enCh)
429 {
430 while(--u32TimeOut)
431 {
432 if(TRUE == M0P_SPI0->STAT_f.TXE)
433 {
434 break;
435 }
436 }
437 if(u32TimeOut == 0)
438 {
439 return ErrorTimeout;
440 }
441 M0P_SPI0->DATA = u8Data;
442 u32TimeOut = 1000;
443 while(--u32TimeOut)
444 {
445 if(TRUE == M0P_SPI0->STAT_f.RXNE)
446 {
447 break;
448 }
449 }
450 if(u32TimeOut == 0)
451 {
452 return ErrorTimeout;
453 }
454 u8Data = M0P_SPI0->DATA;
455 }
456 else
457 {
458 while(--u32TimeOut)
459 {
460 if(TRUE == M0P_SPI1->STAT_f.TXE)
461
462 {
463 break;
464 }
465 }
466 if(u32TimeOut == 0)
467 {
468 return ErrorTimeout;
469 }
470 M0P_SPI1->DATA = u8Data;
471 u32TimeOut = 1000;
472 while(--u32TimeOut)
473 {
474 if(TRUE == M0P_SPI1->STAT_f.RXNE)
475 {
476 break;
477 }
478 }
479 if(u32TimeOut == 0)
480 {
481 return ErrorTimeout;
482 }
483 u8Data = M0P_SPI1->DATA;
484 }
485 return Ok;
486 }
487
488 /**
489 ******************************************************************************
490 ** \brief SPI 接收一字节函数
491 **
492 ** \param [in] enCh接收通道
493 **
494 ** \retval 接收一字节数据
495 **
496 ******************************************************************************/
Spi_ReceiveData(en_spi_channel_t enCh,boolean_t bMasterOrSlave)497 uint8_t Spi_ReceiveData(en_spi_channel_t enCh,boolean_t bMasterOrSlave)
498 {
499 uint8_t temp;
500 ASSERT(IS_VALID_CH(enCh));
501 if(Spi0 == enCh)
502 {
503 if(1 == bMasterOrSlave)
504 {
505 M0P_SPI0->DATA = 0x00;
506 }
507 while(0 == M0P_SPI0->STAT_f.RXNE){;}
508 temp = M0P_SPI0->DATA;
509 }
510 else
511 {
512 if(1 == bMasterOrSlave)
513 {
514 M0P_SPI1->DATA = 0x00;
515 }
516 while(0 == M0P_SPI1->STAT_f.RXNE){;}
517 temp = M0P_SPI1->DATA;
518 }
519 return temp;
520 }
521
522 //@} // SpiGroup
523 /******************************************************************************
524 * EOF (not truncated)
525 *****************************************************************************/
526
527