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