spidrv.c

Go to the documentation of this file.
00001 /***************************************************************************/
00016 #include <string.h>
00017 
00018 #include "em_device.h"
00019 #include "em_gpio.h"
00020 #include "em_int.h"
00021 #include "em_usart.h"
00022 
00023 #include "dmactrl.h"
00024 #include "spidrv.h"
00025 
00027 
00028 static bool spidrvIsInitialized = false;
00029 
00030 static void     BlockingComplete( SPIDRV_Handle_t handle,
00031                                   Ecode_t transferStatus,
00032                                   int itemsTransferred );
00033 
00034 static Ecode_t  ConfigGPIO(       SPIDRV_Handle_t handle, bool enable );
00035 
00036 static void     RxDMAComplete(    unsigned int channel,
00037                                   bool primary,
00038                                   void *user );
00039 
00040 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00041 static void     SlaveTimeout(     RTCDRV_TimerID_t id,
00042                                   void *user );
00043 #endif
00044 
00045 static void     StartReceiveDMA(  SPIDRV_Handle_t handle,
00046                                   void *buffer,
00047                                   int count,
00048                                   SPIDRV_Callback_t callback );
00049 
00050 static void     StartTransferDMA( SPIDRV_Handle_t handle,
00051                                   const void *txBuffer,
00052                                   void *rxBuffer,
00053                                   int count,
00054                                   SPIDRV_Callback_t callback );
00055 
00056 static void     StartTransmitDMA( SPIDRV_Handle_t handle,
00057                                   const void *buffer,
00058                                   int count,
00059                                   SPIDRV_Callback_t callback );
00060 
00061 static Ecode_t  TransferApiPrologue( SPIDRV_Handle_t handle,
00062                                   void *buffer,
00063                                   int count );
00064 
00065 static Ecode_t  TransferApiBlockingPrologue( SPIDRV_Handle_t handle,
00066                                   void *buffer,
00067                                   int count );
00068 
00069 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00070 static Ecode_t  WaitForIdleLine(  SPIDRV_Handle_t handle );
00071 #endif
00072 
00074 
00075 /***************************************************************************/
00089 Ecode_t SPIDRV_Init( SPIDRV_Handle_t handle, SPIDRV_Init_t *initData )
00090 {
00091   Ecode_t retVal;
00092   DMA_Init_TypeDef dmaInit;
00093   DMA_CfgChannel_TypeDef dmaChannelCfg;
00094   uint32_t rxDmaSrcSelect, txDmaSrcSelect;
00095   USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT;
00096 
00097   if ( handle == NULL ) {
00098     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00099   }
00100 
00101   if ( initData == NULL ) {
00102     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00103   }
00104 
00105   memset( handle, 0, sizeof( SPIDRV_HandleData_t ) );
00106 
00107   if ( 0 ) {
00108   #if defined( USART0 )
00109   } else if ( initData->port == USART0 ) {
00110     handle->usartClock = cmuClock_USART0;
00111     txDmaSrcSelect     = DMAREQ_USART0_TXBL;
00112     rxDmaSrcSelect     = DMAREQ_USART0_RXDATAV;
00113   #endif
00114   #if defined( USART1 )
00115   } else if ( initData->port == USART1 ) {
00116     handle->usartClock = cmuClock_USART1;
00117     txDmaSrcSelect     = DMAREQ_USART1_TXBL;
00118     rxDmaSrcSelect     = DMAREQ_USART1_RXDATAV;
00119   #endif
00120   #if defined( USART2 )
00121   } else if ( initData->port == USART2 ) {
00122     handle->usartClock = cmuClock_USART2;
00123     txDmaSrcSelect     = DMAREQ_USART2_TXBL;
00124     rxDmaSrcSelect     = DMAREQ_USART2_RXDATAV;
00125   #endif
00126   } else {
00127     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00128   }
00129 
00130   handle->initData = *initData;
00131 
00132   if ( initData->bitOrder == spidrvBitOrderMsbFirst ) {
00133     usartInit.msbf = true;
00134   }
00135 
00136   if ( initData->clockMode == spidrvClockMode0 ) {
00137     usartInit.clockMode = usartClockMode0;
00138   } else if ( initData->clockMode == spidrvClockMode1 ) {
00139     usartInit.clockMode = usartClockMode1;
00140   } else if ( initData->clockMode == spidrvClockMode2 ) {
00141     usartInit.clockMode = usartClockMode2;
00142   } else if ( initData->clockMode == spidrvClockMode3 ) {
00143     usartInit.clockMode = usartClockMode3;
00144   } else {
00145     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00146   }
00147 
00148   if ( initData->type == spidrvSlave ) {
00149     usartInit.master = false;
00150     usartInit.baudrate = 1000;      // Dummy value needed by USART_InitSync()
00151   } else {
00152     usartInit.baudrate = initData->bitRate;
00153   }
00154 
00155   CMU_ClockEnable( cmuClock_HFPER, true );
00156   CMU_ClockEnable( cmuClock_GPIO, true );
00157   CMU_ClockEnable( cmuClock_DMA, true );
00158   CMU_ClockEnable( handle->usartClock, true );
00159   USART_InitSync(  initData->port, &usartInit );
00160 
00161   if ( ( initData->type == spidrvMaster )
00162        && ( initData->csControl == spidrvCsControlAuto ) ) {
00163     initData->port->CTRL |= USART_CTRL_AUTOCS;
00164   }
00165 
00166   if ( ( initData->type == spidrvMaster )
00167        && ( initData->csControl == spidrvCsControlApplication ) ) {
00168     initData->port->ROUTE = USART_ROUTE_TXPEN
00169                             | USART_ROUTE_RXPEN
00170                             | USART_ROUTE_CLKPEN
00171                             | (initData->portLocation
00172                               << _USART_ROUTE_LOCATION_SHIFT );
00173   } else {
00174     initData->port->ROUTE = USART_ROUTE_TXPEN
00175                             | USART_ROUTE_RXPEN
00176                             | USART_ROUTE_CLKPEN
00177                             | USART_ROUTE_CSPEN
00178                             | (initData->portLocation
00179                               << _USART_ROUTE_LOCATION_SHIFT );
00180   }
00181 
00182   if ( ( retVal = ConfigGPIO( handle, true ) ) != ECODE_EMDRV_SPIDRV_OK ) {
00183     return retVal;
00184   }
00185 
00186   INT_Disable();
00187   if ( ! spidrvIsInitialized ) {
00188     spidrvIsInitialized = true;
00189     INT_Enable();
00190 
00191     // Do one-time-only initialization.
00192 
00193     // Initialize DMA controller.
00194     NVIC_SetPriority( DMA_IRQn, EMDRV_SPIDRV_DMA_IRQ_PRIORITY );
00195     dmaInit.hprot        = 0;
00196     dmaInit.controlBlock = dmaControlBlock;
00197     DMA_Init( &dmaInit );
00198 
00199 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00200     RTCDRV_Init();
00201 #endif
00202   } else {
00203     INT_Enable();
00204   }
00205 
00206 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00207   if ( initData->type == spidrvSlave ) {
00208     if ( RTCDRV_AllocateTimer( &handle->timer ) != ECODE_EMDRV_RTCDRV_OK ) {
00209       return ECODE_EMDRV_SPIDRV_TIMER_ALLOC_ERROR;
00210     }
00211   }
00212 #endif
00213 
00214   // Initialize DMA channels.
00215   dmaChannelCfg.highPri       = false;
00216 
00217   dmaChannelCfg.enableInt     = false;
00218   dmaChannelCfg.select        = txDmaSrcSelect;
00219   dmaChannelCfg.cb            = NULL;
00220   DMA_CfgChannel( initData->txDMACh, &dmaChannelCfg );
00221 
00222   dmaChannelCfg.enableInt     = true;
00223   dmaChannelCfg.select        = rxDmaSrcSelect;
00224   handle->rxDmaCbData.cbFunc  = RxDMAComplete;
00225   dmaChannelCfg.cb            = &(handle->rxDmaCbData);
00226   handle->rxDmaCbData.userPtr = (void*)handle;
00227   DMA_CfgChannel( initData->rxDMACh, &dmaChannelCfg );
00228 
00229   return ECODE_EMDRV_SPIDRV_OK;
00230 }
00231 
00232 /***************************************************************************/
00242 Ecode_t SPIDRV_DeInit( SPIDRV_Handle_t handle )
00243 {
00244   if ( handle == NULL ) {
00245     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00246   }
00247 
00248   // Stop DMA's.
00249   DMA_ChannelEnable( handle->initData.rxDMACh, false );
00250   DMA_ChannelEnable( handle->initData.txDMACh, false );
00251 
00252   ConfigGPIO( handle, false );
00253 
00254 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00255   if ( handle->initData.type == spidrvSlave ) {
00256     RTCDRV_StopTimer( handle->timer );
00257     RTCDRV_FreeTimer( handle->timer );
00258   }
00259 #endif
00260 
00261   USART_Reset( handle->initData.port );
00262   CMU_ClockEnable( handle->usartClock, false );
00263 
00264   return ECODE_EMDRV_SPIDRV_OK;
00265 }
00266 
00267 /***************************************************************************/
00277 Ecode_t SPIDRV_AbortTransfer( SPIDRV_Handle_t handle )
00278 {
00279   if ( handle == NULL ) {
00280     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00281   }
00282 
00283   INT_Disable();
00284   if ( handle->state == spidrvStateIdle ) {
00285     INT_Enable();
00286     return ECODE_EMDRV_SPIDRV_IDLE;
00287   }
00288 
00289 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00290   if ( handle->initData.type == spidrvSlave ) {
00291     RTCDRV_StopTimer( handle->timer );
00292   }
00293 #endif
00294 
00295   // Stop DMA's.
00296   DMA_ChannelEnable( handle->initData.rxDMACh, false );
00297   DMA_ChannelEnable( handle->initData.txDMACh, false );
00298   handle->remaining = 1 + ( ( dmaControlBlock[ handle->initData.rxDMACh ].CTRL
00299                               & _DMA_CTRL_N_MINUS_1_MASK )
00300                             >> _DMA_CTRL_N_MINUS_1_SHIFT );
00301 
00302   handle->transferStatus    = ECODE_EMDRV_SPIDRV_ABORTED;
00303   handle->state             = spidrvStateIdle;
00304   handle->transferStatus    = ECODE_EMDRV_SPIDRV_ABORTED;
00305   handle->blockingCompleted = true;
00306 
00307   if ( handle->userCallback != NULL ) {
00308     handle->userCallback( handle,
00309                           ECODE_EMDRV_SPIDRV_ABORTED,
00310                           handle->transferCount - handle->remaining );
00311   }
00312   INT_Enable();
00313 
00314   return ECODE_EMDRV_SPIDRV_OK;
00315 }
00316 
00317 /***************************************************************************/
00329 Ecode_t SPIDRV_GetBitrate( SPIDRV_Handle_t handle, uint32_t *bitRate )
00330 {
00331   if ( handle == NULL ) {
00332     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00333   }
00334 
00335   if ( bitRate == NULL ) {
00336     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00337   }
00338 
00339   *bitRate = USART_BaudrateGet( handle->initData.port );
00340 
00341   return ECODE_EMDRV_SPIDRV_OK;
00342 }
00343 
00344 /***************************************************************************/
00356 Ecode_t SPIDRV_GetFramelength( SPIDRV_Handle_t handle, uint32_t *frameLength )
00357 {
00358   if ( handle == NULL ) {
00359     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00360   }
00361 
00362   if ( frameLength == NULL ) {
00363     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00364   }
00365 
00366   *frameLength = handle->initData.frameLength;
00367 
00368   return ECODE_EMDRV_SPIDRV_OK;
00369 }
00370 
00371 /***************************************************************************/
00389 Ecode_t SPIDRV_GetTransferStatus( SPIDRV_Handle_t handle,
00390                                   int *itemsTransferred,
00391                                   int *itemsRemaining )
00392 {
00393   int remaining;
00394 
00395   if ( handle == NULL ) {
00396     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00397   }
00398 
00399   if ( ( itemsTransferred == NULL ) || ( itemsRemaining == NULL ) )
00400     {
00401     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00402   }
00403 
00404   INT_Disable();
00405   if ( handle->state == spidrvStateIdle ) {
00406     remaining = handle->remaining;
00407   } else {
00408     remaining =  1 + ( ( dmaControlBlock[ handle->initData.rxDMACh ].CTRL
00409                        & _DMA_CTRL_N_MINUS_1_MASK )
00410                      >> _DMA_CTRL_N_MINUS_1_SHIFT );
00411   }
00412   INT_Enable();
00413 
00414   *itemsTransferred = handle->transferCount - remaining;
00415   *itemsRemaining   = remaining;
00416 
00417   return ECODE_EMDRV_SPIDRV_OK;
00418 }
00419 
00420 /***************************************************************************/
00439 Ecode_t SPIDRV_MReceive( SPIDRV_Handle_t handle,
00440                          void *buffer,
00441                          int count,
00442                          SPIDRV_Callback_t callback )
00443 {
00444   Ecode_t retVal;
00445 
00446   if ( handle->initData.type == spidrvSlave ) {
00447     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00448   }
00449 
00450   if ( ( retVal = TransferApiPrologue( handle, buffer, count ) )
00451        != ECODE_EMDRV_SPIDRV_OK ) {
00452     return retVal;
00453   }
00454 
00455   StartReceiveDMA( handle, buffer, count, callback );
00456 
00457   return ECODE_EMDRV_SPIDRV_OK;
00458 }
00459 
00460 /***************************************************************************/
00480 Ecode_t SPIDRV_MReceiveB( SPIDRV_Handle_t handle,
00481                           void *buffer,
00482                           int count )
00483 {
00484   Ecode_t retVal;
00485 
00486   if ( handle->initData.type == spidrvSlave ) {
00487     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00488   }
00489 
00490   if ( ( retVal = TransferApiBlockingPrologue( handle, buffer, count ) )
00491        != ECODE_EMDRV_SPIDRV_OK ) {
00492     return retVal;
00493   }
00494 
00495   StartReceiveDMA( handle, buffer, count, BlockingComplete );
00496 
00497   while ( handle->blockingCompleted == false );
00498 
00499   return handle->transferStatus;
00500 }
00501 
00502 /***************************************************************************/
00520 Ecode_t SPIDRV_MTransfer( SPIDRV_Handle_t handle,
00521                           const void *txBuffer,
00522                           void *rxBuffer,
00523                           int count,
00524                           SPIDRV_Callback_t callback )
00525 {
00526   Ecode_t retVal;
00527 
00528   if ( handle->initData.type == spidrvSlave ) {
00529     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00530   }
00531 
00532   if ( ( retVal = TransferApiPrologue( handle, (void*)txBuffer, count ) )
00533        != ECODE_EMDRV_SPIDRV_OK ) {
00534     return retVal;
00535   }
00536 
00537   if ( rxBuffer == NULL ) {
00538     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00539   }
00540 
00541   StartTransferDMA( handle, txBuffer, rxBuffer, count, callback );
00542 
00543   return ECODE_EMDRV_SPIDRV_OK;
00544 }
00545 
00546 /***************************************************************************/
00567 Ecode_t SPIDRV_MTransferB( SPIDRV_Handle_t handle,
00568                            const void *txBuffer,
00569                            void *rxBuffer,
00570                            int count )
00571 {
00572   Ecode_t retVal;
00573 
00574   if ( handle->initData.type == spidrvSlave ) {
00575     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00576   }
00577 
00578   if ( ( retVal = TransferApiBlockingPrologue( handle, (void*)txBuffer, count ))
00579        != ECODE_EMDRV_SPIDRV_OK ) {
00580     return retVal;
00581   }
00582 
00583   if ( rxBuffer == NULL ) {
00584     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00585   }
00586 
00587   StartTransferDMA( handle, txBuffer, rxBuffer, count, BlockingComplete );
00588 
00589   while ( handle->blockingCompleted == false );
00590 
00591   return handle->transferStatus;
00592 }
00593 
00594 /***************************************************************************/
00613 Ecode_t SPIDRV_MTransferSingleItemB( SPIDRV_Handle_t handle,
00614                                      uint32_t txValue,
00615                                      void *rxValue )
00616 {
00617   void *pRx;
00618   uint32_t rxBuffer;
00619 
00620   if ( handle->initData.type == spidrvSlave ) {
00621     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00622   }
00623 
00624   if ( handle == NULL ) {
00625     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00626   }
00627 
00628   if ( INT_Disable() > 1 )
00629   {
00630     INT_Enable();
00631     return ECODE_EMDRV_SPIDRV_ILLEGAL_OPERATION;
00632   }
00633 
00634   if ( handle->state != spidrvStateIdle ) {
00635     INT_Enable();
00636     return ECODE_EMDRV_SPIDRV_BUSY;
00637   }
00638   handle->state = spidrvStateTransferring;
00639   INT_Enable();
00640 
00641   if ( ( pRx = rxValue ) == NULL ) {
00642     pRx = &rxBuffer;
00643   }
00644 
00645   StartTransferDMA( handle, &txValue, pRx, 1, BlockingComplete );
00646 
00647   while ( handle->blockingCompleted == false );
00648 
00649   return handle->transferStatus;
00650 }
00651 
00652 /***************************************************************************/
00671 Ecode_t SPIDRV_MTransmit( SPIDRV_Handle_t handle,
00672                           const void *buffer,
00673                           int count,
00674                           SPIDRV_Callback_t callback )
00675 {
00676   Ecode_t retVal;
00677 
00678   if ( handle->initData.type == spidrvSlave ) {
00679     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00680   }
00681 
00682   if ( ( retVal = TransferApiPrologue( handle, (void*)buffer, count ) )
00683        != ECODE_EMDRV_SPIDRV_OK ) {
00684     return retVal;
00685   }
00686 
00687   StartTransmitDMA( handle, buffer, count, callback );
00688 
00689   return ECODE_EMDRV_SPIDRV_OK;
00690 }
00691 
00692 /***************************************************************************/
00711 Ecode_t SPIDRV_MTransmitB( SPIDRV_Handle_t handle,
00712                            const void *buffer,
00713                            int count )
00714 {
00715   Ecode_t retVal;
00716 
00717   if ( handle->initData.type == spidrvSlave ) {
00718     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00719   }
00720 
00721   if ( ( retVal = TransferApiBlockingPrologue( handle, (void*)buffer, count ) )
00722        != ECODE_EMDRV_SPIDRV_OK ) {
00723     return retVal;
00724   }
00725 
00726   StartTransmitDMA( handle, buffer, count, BlockingComplete );
00727 
00728   while ( handle->blockingCompleted == false );
00729 
00730   return handle->transferStatus;
00731 }
00732 
00733 /***************************************************************************/
00745 Ecode_t SPIDRV_SetBitrate( SPIDRV_Handle_t handle, uint32_t bitRate )
00746 {
00747   if ( handle == NULL ) {
00748     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00749   }
00750 
00751   INT_Disable();
00752   if ( handle->state != spidrvStateIdle ) {
00753     INT_Enable();
00754     return ECODE_EMDRV_SPIDRV_BUSY;
00755   }
00756 
00757   handle->initData.bitRate = bitRate;
00758   USART_BaudrateSyncSet( handle->initData.port, 0, bitRate );
00759   INT_Enable();
00760 
00761   return ECODE_EMDRV_SPIDRV_OK;
00762 }
00763 
00764 /***************************************************************************/
00776 Ecode_t SPIDRV_SetFramelength( SPIDRV_Handle_t handle, uint32_t frameLength )
00777 {
00778   if ( handle == NULL ) {
00779     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
00780   }
00781 
00782   frameLength -= 3;
00783   if ( ( frameLength < _USART_FRAME_DATABITS_FOUR )
00784        || ( frameLength > _USART_FRAME_DATABITS_SIXTEEN ) ) {
00785     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00786   }
00787 
00788   INT_Disable();
00789   if ( handle->state != spidrvStateIdle ) {
00790     INT_Enable();
00791     return ECODE_EMDRV_SPIDRV_BUSY;
00792   }
00793 
00794   handle->initData.frameLength = frameLength + 3;
00795   handle->initData.port->FRAME = ( handle->initData.port->FRAME
00796                                    & ~_USART_FRAME_DATABITS_MASK )
00797                                   | ( frameLength
00798                                       << _USART_FRAME_DATABITS_SHIFT );
00799   INT_Enable();
00800 
00801   return ECODE_EMDRV_SPIDRV_OK;
00802 }
00803 
00804 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
00805 /***************************************************************************/
00826 Ecode_t SPIDRV_SReceive( SPIDRV_Handle_t handle,
00827                          void *buffer,
00828                          int count,
00829                          SPIDRV_Callback_t callback,
00830                          int timeoutMs )
00831 {
00832   Ecode_t retVal;
00833 
00834   if ( handle->initData.type == spidrvMaster ) {
00835     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00836   }
00837 
00838   if ( ( retVal = TransferApiPrologue( handle, buffer, count ) )
00839        != ECODE_EMDRV_SPIDRV_OK ) {
00840     return retVal;
00841   }
00842 
00843   if ( timeoutMs ) {
00844     RTCDRV_StartTimer( handle->timer,
00845                        rtcdrvTimerTypeOneshot,
00846                        timeoutMs,
00847                        SlaveTimeout,
00848                        handle );
00849   }
00850 
00851   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
00852     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
00853       return retVal;
00854     }
00855   }
00856 
00857   StartReceiveDMA( handle, buffer, count, callback );
00858 
00859   return ECODE_EMDRV_SPIDRV_OK;
00860 }
00861 
00862 /***************************************************************************/
00885 Ecode_t SPIDRV_SReceiveB( SPIDRV_Handle_t handle,
00886                           void *buffer,
00887                           int count,
00888                           int timeoutMs )
00889 {
00890   Ecode_t retVal;
00891 
00892   if ( handle->initData.type == spidrvMaster ) {
00893     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00894   }
00895 
00896   if ( ( retVal = TransferApiBlockingPrologue( handle, buffer, count ) )
00897        != ECODE_EMDRV_SPIDRV_OK ) {
00898     return retVal;
00899   }
00900 
00901   if ( timeoutMs ) {
00902     RTCDRV_StartTimer( handle->timer,
00903                        rtcdrvTimerTypeOneshot,
00904                        timeoutMs,
00905                        SlaveTimeout,
00906                        handle );
00907   }
00908 
00909   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
00910     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
00911       return retVal;
00912     }
00913   }
00914 
00915   StartReceiveDMA( handle, buffer, count, BlockingComplete );
00916 
00917   while ( handle->blockingCompleted == false );
00918 
00919   return handle->transferStatus;
00920 }
00921 
00922 /***************************************************************************/
00942 Ecode_t SPIDRV_STransfer( SPIDRV_Handle_t handle,
00943                           const void *txBuffer,
00944                           void *rxBuffer,
00945                           int count,
00946                           SPIDRV_Callback_t callback,
00947                           int timeoutMs )
00948 {
00949   Ecode_t retVal;
00950 
00951   if ( handle->initData.type == spidrvMaster ) {
00952     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
00953   }
00954 
00955   if ( ( retVal = TransferApiPrologue( handle, (void*)txBuffer, count ) )
00956        != ECODE_EMDRV_SPIDRV_OK ) {
00957     return retVal;
00958   }
00959 
00960   if ( rxBuffer == NULL ) {
00961     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
00962   }
00963 
00964   if ( timeoutMs ) {
00965     RTCDRV_StartTimer( handle->timer,
00966                        rtcdrvTimerTypeOneshot,
00967                        timeoutMs,
00968                        SlaveTimeout,
00969                        handle );
00970   }
00971 
00972   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
00973     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
00974       return retVal;
00975     }
00976   }
00977 
00978   StartTransferDMA( handle, txBuffer, rxBuffer, count, callback );
00979 
00980   return ECODE_EMDRV_SPIDRV_OK;
00981 }
00982 
00983 /***************************************************************************/
01007 Ecode_t SPIDRV_STransferB( SPIDRV_Handle_t handle,
01008                            const void *txBuffer,
01009                            void *rxBuffer,
01010                            int count,
01011                            int timeoutMs )
01012 {
01013   Ecode_t retVal;
01014 
01015   if ( handle->initData.type == spidrvMaster ) {
01016     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
01017   }
01018 
01019   if ( ( retVal = TransferApiBlockingPrologue( handle, (void*)txBuffer, count ))
01020        != ECODE_EMDRV_SPIDRV_OK ) {
01021     return retVal;
01022   }
01023 
01024   if ( rxBuffer == NULL ) {
01025     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
01026   }
01027 
01028   if ( timeoutMs ) {
01029     RTCDRV_StartTimer( handle->timer,
01030                        rtcdrvTimerTypeOneshot,
01031                        timeoutMs,
01032                        SlaveTimeout,
01033                        handle );
01034   }
01035 
01036   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
01037     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
01038       return retVal;
01039     }
01040   }
01041 
01042   StartTransferDMA( handle, txBuffer, rxBuffer, count, BlockingComplete );
01043 
01044   while ( handle->blockingCompleted == false );
01045 
01046   return handle->transferStatus;
01047 }
01048 
01049 /***************************************************************************/
01070 Ecode_t SPIDRV_STransmit( SPIDRV_Handle_t handle,
01071                           const void *buffer,
01072                           int count,
01073                           SPIDRV_Callback_t callback,
01074                           int timeoutMs )
01075 {
01076   Ecode_t retVal;
01077 
01078   if ( handle->initData.type == spidrvMaster ) {
01079     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
01080   }
01081 
01082   if ( ( retVal = TransferApiPrologue( handle, (void*)buffer, count ) )
01083        != ECODE_EMDRV_SPIDRV_OK ) {
01084     return retVal;
01085   }
01086 
01087   if ( timeoutMs ) {
01088     RTCDRV_StartTimer( handle->timer,
01089                        rtcdrvTimerTypeOneshot,
01090                        timeoutMs,
01091                        SlaveTimeout,
01092                        handle );
01093   }
01094 
01095   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
01096     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
01097       return retVal;
01098     }
01099   }
01100 
01101   StartTransmitDMA( handle, buffer, count, callback );
01102 
01103   return ECODE_EMDRV_SPIDRV_OK;
01104 }
01105 
01106 /***************************************************************************/
01129 Ecode_t SPIDRV_STransmitB( SPIDRV_Handle_t handle,
01130                            const void *buffer,
01131                            int count,
01132                            int timeoutMs )
01133 {
01134   Ecode_t retVal;
01135 
01136   if ( handle->initData.type == spidrvMaster ) {
01137     return ECODE_EMDRV_SPIDRV_MODE_ERROR;
01138   }
01139 
01140   if ( ( retVal = TransferApiBlockingPrologue( handle, (void*)buffer, count ) )
01141        != ECODE_EMDRV_SPIDRV_OK ) {
01142     return retVal;
01143   }
01144 
01145   if ( timeoutMs ) {
01146     RTCDRV_StartTimer( handle->timer,
01147                        rtcdrvTimerTypeOneshot,
01148                        timeoutMs,
01149                        SlaveTimeout,
01150                        handle );
01151   }
01152 
01153   if ( handle->initData.slaveStartMode == spidrvSlaveStartDelayed ) {
01154     if ( ( retVal = WaitForIdleLine( handle ) ) != ECODE_EMDRV_SPIDRV_OK ) {
01155       return retVal;
01156     }
01157   }
01158 
01159   StartTransmitDMA( handle, buffer, count, BlockingComplete );
01160 
01161   while ( handle->blockingCompleted == false );
01162 
01163   return handle->transferStatus;
01164 }
01165 #endif
01166 
01168 
01169 /***************************************************************************/
01175 static void BlockingComplete( SPIDRV_Handle_t handle,
01176                               Ecode_t transferStatus,
01177                               int itemsTransferred )
01178 {
01179   (void)itemsTransferred;
01180 
01181   handle->transferStatus    = transferStatus;
01182   handle->blockingCompleted = true;
01183 }
01184 
01185 /***************************************************************************/
01188 static Ecode_t ConfigGPIO( SPIDRV_Handle_t handle, bool enable )
01189 {
01190   uint32_t location;
01191   int mosiPin, misoPin, clkPin;
01192   int mosiPort, misoPort, clkPort;
01193 
01194   location = handle->initData.portLocation;
01195 
01196   if ( 0 ) {
01197   #if defined( USART0 )
01198   } else if ( handle->initData.port == USART0 ) {
01199     mosiPort       = AF_USART0_TX_PORT(  location );
01200     misoPort       = AF_USART0_RX_PORT(  location );
01201     clkPort        = AF_USART0_CLK_PORT( location );
01202     handle->csPort = AF_USART0_CS_PORT(  location );
01203     mosiPin        = AF_USART0_TX_PIN(   location );
01204     misoPin        = AF_USART0_RX_PIN(   location );
01205     clkPin         = AF_USART0_CLK_PIN(  location );
01206     handle->csPin  = AF_USART0_CS_PIN(   location );
01207   #endif
01208   #if defined( USART1 )
01209   } else if ( handle->initData.port == USART1 ) {
01210     mosiPort       = AF_USART1_TX_PORT(  location );
01211     misoPort       = AF_USART1_RX_PORT(  location );
01212     clkPort        = AF_USART1_CLK_PORT( location );
01213     handle->csPort = AF_USART1_CS_PORT(  location );
01214     mosiPin        = AF_USART1_TX_PIN(   location );
01215     misoPin        = AF_USART1_RX_PIN(   location );
01216     clkPin         = AF_USART1_CLK_PIN(  location );
01217     handle->csPin  = AF_USART1_CS_PIN(   location );
01218   #endif
01219   #if defined( USART2 )
01220   } else if ( handle->initData.port == USART2 ) {
01221     mosiPort       = AF_USART2_TX_PORT(  location );
01222     misoPort       = AF_USART2_RX_PORT(  location );
01223     clkPort        = AF_USART2_CLK_PORT( location );
01224     handle->csPort = AF_USART2_CS_PORT(  location );
01225     mosiPin        = AF_USART2_TX_PIN(   location );
01226     misoPin        = AF_USART2_RX_PIN(   location );
01227     clkPin         = AF_USART2_CLK_PIN(  location );
01228     handle->csPin  = AF_USART2_CS_PIN(   location );
01229   #endif
01230   } else {
01231     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
01232   }
01233 
01234   if ( enable ) {
01235     if ( handle->initData.type == spidrvMaster ) {
01236       GPIO_PinModeSet( (GPIO_Port_TypeDef)mosiPort, mosiPin,
01237                        gpioModePushPull, 0 );
01238       GPIO_PinModeSet( (GPIO_Port_TypeDef)misoPort, misoPin,
01239                        gpioModeInputPull, 0 );
01240 
01241       if (    ( handle->initData.clockMode == spidrvClockMode0 )
01242            || ( handle->initData.clockMode == spidrvClockMode1 ) ) {
01243         GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin,
01244                          gpioModePushPull, 0 );
01245       } else {
01246         GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin,
01247                          gpioModePushPull, 1 );
01248       }
01249 
01250       GPIO_PinModeSet( (GPIO_Port_TypeDef)handle->csPort, handle->csPin,
01251                        gpioModePushPull, 1 );
01252     } else {
01253       GPIO_PinModeSet( (GPIO_Port_TypeDef)mosiPort, mosiPin,
01254                        gpioModeInputPull, 0 );
01255       GPIO_PinModeSet( (GPIO_Port_TypeDef)misoPort, misoPin,
01256                        gpioModePushPull, 0 );
01257 
01258       if (    ( handle->initData.clockMode == spidrvClockMode0 )
01259            || ( handle->initData.clockMode == spidrvClockMode1 ) ) {
01260         GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin,
01261                          gpioModeInputPull, 0 );
01262       } else {
01263         GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin,
01264                          gpioModeInputPull, 1 );
01265       }
01266 
01267       GPIO_PinModeSet( (GPIO_Port_TypeDef)handle->csPort, handle->csPin,
01268                        gpioModeInputPull, 1 );
01269     }
01270   } else {
01271     GPIO_PinModeSet( (GPIO_Port_TypeDef)mosiPort, mosiPin, gpioModeInputPull,0);
01272     GPIO_PinModeSet( (GPIO_Port_TypeDef)misoPort, misoPin, gpioModeInputPull,0);
01273 
01274     if (    ( handle->initData.clockMode == spidrvClockMode0 )
01275          || ( handle->initData.clockMode == spidrvClockMode1 ) ) {
01276       GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin, gpioModeInputPull,0);
01277     } else {
01278       GPIO_PinModeSet( (GPIO_Port_TypeDef)clkPort, clkPin, gpioModeInputPull,1);
01279     }
01280 
01281     GPIO_PinModeSet( (GPIO_Port_TypeDef)handle->csPort, handle->csPin,
01282                      gpioModeDisabled, 0);
01283   }
01284 
01285   return ECODE_EMDRV_SPIDRV_OK;
01286 }
01287 
01288 /***************************************************************************/
01291 static void RxDMAComplete( unsigned int channel, bool primary, void *user )
01292 {
01293   SPIDRV_Handle_t handle;
01294   (void)channel;
01295   (void)primary;
01296 
01297   INT_Disable();
01298 
01299   handle = (SPIDRV_Handle_t)user;
01300 
01301   handle->transferStatus = ECODE_EMDRV_SPIDRV_OK;
01302   handle->state          = spidrvStateIdle;
01303   handle->remaining      = 0;
01304 
01305 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
01306   if ( handle->initData.type == spidrvSlave ) {
01307     RTCDRV_StopTimer( handle->timer );
01308   }
01309 #endif
01310 
01311   if ( handle->userCallback != NULL ) {
01312     handle->userCallback( handle, ECODE_EMDRV_SPIDRV_OK, handle->transferCount);
01313   }
01314 
01315   INT_Enable();
01316 }
01317 
01318 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
01319 /***************************************************************************/
01322 static void SlaveTimeout( RTCDRV_TimerID_t id, void *user )
01323 {
01324   SPIDRV_Handle_t handle;
01325   (void)id;
01326 
01327   handle = (SPIDRV_Handle_t)user;
01328 
01329   if ( handle->state == spidrvStateTransferring ) {
01330     if ( DMA_ChannelEnabled( handle->initData.rxDMACh ) ) {
01331       // Stop running DMA's
01332       DMA_ChannelEnable( handle->initData.rxDMACh, false );
01333       DMA_ChannelEnable( handle->initData.txDMACh, false );
01334       handle->remaining = 1 +
01335                           ( ( dmaControlBlock[ handle->initData.rxDMACh ].CTRL
01336                               & _DMA_CTRL_N_MINUS_1_MASK )
01337                             >> _DMA_CTRL_N_MINUS_1_SHIFT );
01338     } else {
01339       // DMA is either completed or not yet started
01340       if ( DMA->IF & ( 1 << handle->initData.rxDMACh ) ) {
01341           // We have a pending DMA interrupt, let the DMA handler do the rest
01342           return;
01343       }
01344       handle->remaining = handle->transferCount;
01345     }
01346     handle->transferStatus = ECODE_EMDRV_SPIDRV_TIMEOUT;
01347     handle->state          = spidrvStateIdle;
01348 
01349     if ( handle->userCallback != NULL ) {
01350       handle->userCallback( handle,
01351                             ECODE_EMDRV_SPIDRV_TIMEOUT,
01352                             handle->transferCount - handle->remaining );
01353     }
01354   }
01355 }
01356 #endif
01357 
01358 /***************************************************************************/
01361 static void StartReceiveDMA( SPIDRV_Handle_t handle,
01362                              void *buffer,
01363                              int count,
01364                              SPIDRV_Callback_t callback )
01365 {
01366   void *rxPort, *txPort;
01367   DMA_CfgDescr_TypeDef cfgDesc;
01368 
01369   handle->blockingCompleted  = false;
01370   handle->transferCount      = count;
01371   handle->initData.port->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
01372   handle->userCallback       = callback;
01373 
01374   if ( handle->initData.frameLength > 8 ) {
01375     cfgDesc.size = dmaDataSize2;
01376   } else {
01377     cfgDesc.size = dmaDataSize1;
01378   }
01379   cfgDesc.arbRate = dmaArbitrate1;
01380   cfgDesc.hprot   = 0;
01381 
01382   cfgDesc.srcInc = dmaDataIncNone;
01383   if ( handle->initData.frameLength > 8 ) {
01384     cfgDesc.dstInc = dmaDataInc2;
01385     rxPort = (void *)&(handle->initData.port->RXDOUBLE);
01386     txPort = (void *)&(handle->initData.port->TXDOUBLE);
01387   } else {
01388     cfgDesc.dstInc = dmaDataInc1;
01389     rxPort = (void *)&(handle->initData.port->RXDATA);
01390     txPort = (void *)&(handle->initData.port->TXDATA);
01391   }
01392   DMA_CfgDescr( handle->initData.rxDMACh, true, &cfgDesc );
01393 
01394   cfgDesc.dstInc = dmaDataIncNone;
01395   DMA_CfgDescr( handle->initData.txDMACh, true, &cfgDesc );
01396 
01397   DMA_ActivateBasic( handle->initData.rxDMACh,
01398                      true,
01399                      false,
01400                      buffer,
01401                      rxPort,
01402                      count - 1 );
01403 
01404   DMA_ActivateBasic( handle->initData.txDMACh,
01405                      true,
01406                      false,
01407                      txPort,
01408                      (void *)&(handle->initData.dummyTxValue),
01409                      count - 1 );
01410 }
01411 
01412 /***************************************************************************/
01415 static void StartTransferDMA( SPIDRV_Handle_t handle,
01416                               const void *txBuffer,
01417                               void *rxBuffer,
01418                               int count,
01419                               SPIDRV_Callback_t callback )
01420 {
01421   void *rxPort, *txPort;
01422   DMA_CfgDescr_TypeDef cfgDesc;
01423 
01424   handle->blockingCompleted  = false;
01425   handle->transferCount      = count;
01426   handle->initData.port->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
01427   handle->userCallback       = callback;
01428 
01429   if ( handle->initData.frameLength > 8 ) {
01430     cfgDesc.size = dmaDataSize2;
01431   } else {
01432     cfgDesc.size = dmaDataSize1;
01433   }
01434   cfgDesc.arbRate = dmaArbitrate1;
01435   cfgDesc.hprot   = 0;
01436 
01437   if ( handle->initData.frameLength > 8 ) {
01438     cfgDesc.srcInc = dmaDataInc2;
01439     txPort = (void *)&(handle->initData.port->TXDOUBLE);
01440   } else {
01441     cfgDesc.srcInc = dmaDataInc1;
01442     txPort = (void *)&(handle->initData.port->TXDATA);
01443   }
01444   cfgDesc.dstInc = dmaDataIncNone;
01445   DMA_CfgDescr( handle->initData.txDMACh, true, &cfgDesc );
01446 
01447   cfgDesc.srcInc = dmaDataIncNone;
01448   if ( handle->initData.frameLength > 8 ) {
01449     cfgDesc.dstInc = dmaDataInc2;
01450     rxPort = (void *)&(handle->initData.port->RXDOUBLE);
01451   } else {
01452     cfgDesc.dstInc = dmaDataInc1;
01453     rxPort = (void *)&(handle->initData.port->RXDATA);
01454   }
01455   DMA_CfgDescr( handle->initData.rxDMACh, true, &cfgDesc );
01456 
01457   DMA_ActivateBasic( handle->initData.rxDMACh,
01458                      true,
01459                      false,
01460                      rxBuffer,
01461                      rxPort,
01462                      count - 1 );
01463 
01464   DMA_ActivateBasic( handle->initData.txDMACh,
01465                      true,
01466                      false,
01467                      txPort,
01468                      (void*)txBuffer,
01469                      count - 1 );
01470 }
01471 
01472 /***************************************************************************/
01475 static void StartTransmitDMA( SPIDRV_Handle_t handle,
01476                                const void *buffer,
01477                                int count,
01478                                SPIDRV_Callback_t callback )
01479 {
01480   void *rxPort, *txPort;
01481   DMA_CfgDescr_TypeDef cfgDesc;
01482 
01483   handle->blockingCompleted  = false;
01484   handle->transferCount      = count;
01485   handle->initData.port->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
01486   handle->userCallback       = callback;
01487 
01488   if ( handle->initData.frameLength > 8 ) {
01489     cfgDesc.size = dmaDataSize2;
01490   } else {
01491     cfgDesc.size = dmaDataSize1;
01492   }
01493   cfgDesc.arbRate = dmaArbitrate1;
01494   cfgDesc.hprot   = 0;
01495 
01496   if ( handle->initData.frameLength > 8 ) {
01497     cfgDesc.srcInc = dmaDataInc2;
01498     rxPort = (void *)&(handle->initData.port->RXDOUBLE);
01499     txPort = (void *)&(handle->initData.port->TXDOUBLE);
01500   } else {
01501     cfgDesc.srcInc = dmaDataInc1;
01502     rxPort = (void *)&(handle->initData.port->RXDATA);
01503     txPort = (void *)&(handle->initData.port->TXDATA);
01504   }
01505   cfgDesc.dstInc = dmaDataIncNone;
01506   DMA_CfgDescr( handle->initData.txDMACh, true, &cfgDesc );
01507 
01508   cfgDesc.srcInc = dmaDataIncNone;
01509   DMA_CfgDescr( handle->initData.rxDMACh, true, &cfgDesc );
01510 
01511   // Receive DMA runs only to get precise numbers for SPIDRV_GetTransferStatus()
01512   DMA_ActivateBasic( handle->initData.rxDMACh,
01513                      true,
01514                      false,
01515                      (void *)&(handle->dummyRx),
01516                      rxPort,
01517                      count - 1 );
01518 
01519   DMA_ActivateBasic( handle->initData.txDMACh,
01520                      true,
01521                      false,
01522                      txPort,
01523                      (void*)buffer,
01524                      count - 1 );
01525 }
01526 
01527 /***************************************************************************/
01530 static Ecode_t TransferApiBlockingPrologue( SPIDRV_Handle_t handle,
01531                                             void *buffer,
01532                                             int count )
01533 {
01534   if ( handle == NULL ) {
01535     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
01536   }
01537 
01538   if ( ( buffer == NULL ) || ( count == 0 ) ) {
01539     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
01540   }
01541 
01542   if ( INT_Disable() > 1 )
01543   {
01544     INT_Enable();
01545     return ECODE_EMDRV_SPIDRV_ILLEGAL_OPERATION;
01546   }
01547 
01548   if ( handle->state != spidrvStateIdle ) {
01549     INT_Enable();
01550     return ECODE_EMDRV_SPIDRV_BUSY;
01551   }
01552   handle->state = spidrvStateTransferring;
01553   INT_Enable();
01554 
01555   return ECODE_EMDRV_SPIDRV_OK;
01556 }
01557 
01558 /***************************************************************************/
01561 static Ecode_t TransferApiPrologue( SPIDRV_Handle_t handle,
01562                                     void *buffer,
01563                                     int count )
01564 {
01565   if ( handle == NULL ) {
01566     return ECODE_EMDRV_SPIDRV_ILLEGAL_HANDLE;
01567   }
01568 
01569   if ( ( buffer == NULL ) || ( count == 0 ) ) {
01570     return ECODE_EMDRV_SPIDRV_PARAM_ERROR;
01571   }
01572 
01573   INT_Disable();
01574   if ( handle->state != spidrvStateIdle ) {
01575     INT_Enable();
01576     return ECODE_EMDRV_SPIDRV_BUSY;
01577   }
01578   handle->state = spidrvStateTransferring;
01579   INT_Enable();
01580 
01581   return ECODE_EMDRV_SPIDRV_OK;
01582 }
01583 
01584 #if defined( EMDRV_SPIDRV_INCLUDE_SLAVE )
01585 /***************************************************************************/
01588 static Ecode_t WaitForIdleLine( SPIDRV_Handle_t handle )
01589 {
01590   while ( !GPIO_PinInGet( (GPIO_Port_TypeDef)handle->csPort, handle->csPin )
01591           && ( handle->state != spidrvStateIdle ) );
01592 
01593   if ( handle->state == spidrvStateIdle ) {
01594     return handle->transferStatus;
01595   }
01596 
01597   return ECODE_EMDRV_SPIDRV_OK;
01598 }
01599 #endif
01600 
01602 
01603 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/