dmadrv.c

Go to the documentation of this file.
00001 /***************************************************************************/
00016 #include <stdbool.h>
00017 #include <stddef.h>
00018 
00019 #include "em_device.h"
00020 #include "em_cmu.h"
00021 #include "em_int.h"
00022 
00023 #include "dmadrv.h"
00024 
00025 #if defined( EMDRV_DMADRV_UDMA )
00026 #include "dmactrl.h"
00027 #endif
00028 
00030 
00031 #if !defined( EMDRV_DMADRV_DMA_CH_COUNT ) \
00032     || ( EMDRV_DMADRV_DMA_CH_COUNT > DMA_CHAN_COUNT )
00033 #define EMDRV_DMADRV_DMA_CH_COUNT DMA_CHAN_COUNT
00034 #endif
00035 
00036 typedef enum
00037 {
00038   dmaDirectionMemToPeripheral,
00039   dmaDirectionPeripheralToMem
00040 } DmaDirection_t;
00041 
00042 typedef enum
00043 {
00044   dmaModeBasic,
00045   dmaModePingPong
00046 } DmaMode_t;
00047 
00048 #if defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_UDMA )
00049 typedef struct
00050 {
00051   bool              allocated;
00052 } ChTable_t;
00053 
00054 #elif defined( EMDRV_DMADRV_USE_NATIVE_API ) && defined( EMDRV_DMADRV_LDMA )
00055 typedef struct
00056 {
00057   DMADRV_Callback_t callback;
00058   void              *userParam;
00059   unsigned int      callbackCount;
00060   bool              allocated;
00061 } ChTable_t;
00062 
00063 #else
00064 typedef struct
00065 {
00066   DMADRV_Callback_t callback;
00067   void              *userParam;
00068   unsigned int      callbackCount;
00069 #if defined( EMDRV_DMADRV_UDMA )
00070   int               length;
00071 #endif
00072   bool              allocated;
00073 #if defined( EMDRV_DMADRV_LDMA )
00074   DmaMode_t         mode;
00075 #endif
00076 } ChTable_t;
00077 #endif
00078 
00079 static bool initialized = false;
00080 static ChTable_t chTable[ EMDRV_DMADRV_DMA_CH_COUNT ];
00081 
00082 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
00083 static DMA_CB_TypeDef dmaCallBack[ EMDRV_DMADRV_DMA_CH_COUNT ];
00084 #endif
00085 
00086 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
00087 const LDMA_TransferCfg_t xferCfg = LDMA_TRANSFER_CFG_PERIPHERAL( 0 );
00088 const LDMA_Descriptor_t m2p = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE( NULL, NULL, 0 );
00089 const LDMA_Descriptor_t p2m = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE( NULL, NULL, 0 );
00090 
00091 typedef struct
00092 {
00093   LDMA_Descriptor_t desc[2];
00094 } DmaXfer_t;
00095 
00096 static DmaXfer_t dmaXfer[ EMDRV_DMADRV_DMA_CH_COUNT ];
00097 #endif
00098 
00099 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
00100 static Ecode_t StartTransfer( DmaMode_t             mode,
00101                               DmaDirection_t        direction,
00102                               unsigned int          channelId,
00103                               DMADRV_PeripheralSignal_t
00104                                                     peripheralSignal,
00105                               void                  *buf0,
00106                               void                  *buf1,
00107                               void                  *buf2,
00108                               bool                  bufInc,
00109                               int                   len,
00110                               DMADRV_DataSize_t     size,
00111                               DMADRV_Callback_t     callback,
00112                               void                  *cbUserParam );
00113 #endif
00114 
00116 
00117 /***************************************************************************/
00131 Ecode_t DMADRV_AllocateChannel( unsigned int *channelId, void *capabilities )
00132 {
00133   int i;
00134   (void)capabilities;
00135 
00136   if ( !initialized )
00137   {
00138     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00139   }
00140 
00141   if ( channelId == NULL )
00142   {
00143     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00144   }
00145 
00146   INT_Disable();
00147   for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
00148   {
00149     if ( !chTable[ i ].allocated )
00150     {
00151       *channelId             = i;
00152       chTable[ i ].allocated = true;
00153 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( EMDRV_DMADRV_LDMA )
00154       chTable[ i ].callback  = NULL;
00155 #endif
00156       INT_Enable();
00157       return ECODE_EMDRV_DMADRV_OK;
00158     }
00159   }
00160   INT_Enable();
00161   return ECODE_EMDRV_DMADRV_CHANNELS_EXHAUSTED;
00162 }
00163 
00164 /***************************************************************************/
00176 Ecode_t DMADRV_DeInit( void )
00177 {
00178   int i;
00179   bool inUse;
00180 
00181   inUse = false;
00182 
00183   INT_Disable();
00184   for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
00185   {
00186     if ( chTable[ i ].allocated )
00187     {
00188       inUse = true;
00189       break;
00190     }
00191   }
00192 
00193   if ( !inUse )
00194   {
00195 #if defined( EMDRV_DMADRV_UDMA )
00196     NVIC_DisableIRQ( DMA_IRQn );
00197     DMA->IEN    = _DMA_IEN_RESETVALUE;
00198     DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
00199     CMU_ClockEnable( cmuClock_DMA, false );
00200 #elif defined( EMDRV_DMADRV_LDMA )
00201     LDMA_DeInit();
00202 #endif
00203     initialized = false;
00204     INT_Enable();
00205     return ECODE_EMDRV_DMADRV_OK;
00206   }
00207   INT_Enable();
00208 
00209   return ECODE_EMDRV_DMADRV_IN_USE;
00210 }
00211 
00212 /***************************************************************************/
00223 Ecode_t DMADRV_FreeChannel( unsigned int channelId )
00224 {
00225   if ( !initialized )
00226   {
00227     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00228   }
00229 
00230   if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00231   {
00232     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00233   }
00234 
00235   INT_Disable();
00236   if ( chTable[ channelId ].allocated )
00237   {
00238     chTable[ channelId ].allocated = false;
00239     INT_Enable();
00240     return ECODE_EMDRV_DMADRV_OK;
00241   }
00242   INT_Enable();
00243 
00244   return ECODE_EMDRV_DMADRV_ALREADY_FREED;
00245 }
00246 
00247 /***************************************************************************/
00258 Ecode_t DMADRV_Init( void )
00259 {
00260   int i;
00261 #if defined( EMDRV_DMADRV_UDMA )
00262   DMA_Init_TypeDef dmaInit;
00263 #elif defined( EMDRV_DMADRV_LDMA )
00264   LDMA_Init_t dmaInit = LDMA_INIT_DEFAULT;
00265 #endif
00266 
00267 
00268   INT_Disable();
00269   if ( initialized )
00270   {
00271     INT_Enable();
00272     return ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED;
00273   }
00274   initialized = true;
00275   INT_Enable();
00276 
00277   if ( EMDRV_DMADRV_DMA_IRQ_PRIORITY > 7 )
00278   {
00279     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00280   }
00281 
00282   for ( i=0; i < EMDRV_DMADRV_DMA_CH_COUNT; i++ )
00283   {
00284     chTable[ i ].allocated = false;
00285   }
00286 
00287 #if defined( EMDRV_DMADRV_UDMA )
00288   NVIC_SetPriority( DMA_IRQn, EMDRV_DMADRV_DMA_IRQ_PRIORITY );
00289   dmaInit.hprot        = 0;
00290   dmaInit.controlBlock = dmaControlBlock;
00291   DMA_Init( &dmaInit );
00292 #elif defined( EMDRV_DMADRV_LDMA )
00293   dmaInit.ldmaInitIrqPriority = EMDRV_DMADRV_DMA_IRQ_PRIORITY;
00294   LDMA_Init( &dmaInit );
00295 #endif
00296 
00297   return ECODE_EMDRV_DMADRV_OK;
00298 }
00299 
00300 #if defined( EMDRV_DMADRV_LDMA ) && defined( EMDRV_DMADRV_USE_NATIVE_API )
00301 /***************************************************************************/
00330 Ecode_t DMADRV_LdmaStartTransfer( int                channelId,
00331                                   LDMA_TransferCfg_t *transfer,
00332                                   LDMA_Descriptor_t  *descriptor,
00333                                   DMADRV_Callback_t  callback,
00334                                   void               *cbUserParam )
00335 {
00336   ChTable_t *ch;
00337 
00338   if ( !initialized )
00339   {
00340     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00341   }
00342 
00343   if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00344   {
00345     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00346   }
00347 
00348   ch = &chTable[ channelId ];
00349   if ( ch->allocated == false )
00350   {
00351     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00352   }
00353 
00354   ch->callback      = callback;
00355   ch->userParam     = cbUserParam;
00356   ch->callbackCount = 0;
00357   LDMA_StartTransfer( channelId, transfer, descriptor );
00358 
00359   return ECODE_EMDRV_DMADRV_OK;
00360 }
00361 #endif
00362 
00363 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
00364 /***************************************************************************/
00401 Ecode_t DMADRV_MemoryPeripheral( unsigned int          channelId,
00402                                  DMADRV_PeripheralSignal_t
00403                                                        peripheralSignal,
00404                                  void                  *dst,
00405                                  void                  *src,
00406                                  bool                  srcInc,
00407                                  int                   len,
00408                                  DMADRV_DataSize_t     size,
00409                                  DMADRV_Callback_t     callback,
00410                                  void                  *cbUserParam )
00411 {
00412   return StartTransfer( dmaModeBasic,
00413                         dmaDirectionMemToPeripheral,
00414                         channelId,
00415                         peripheralSignal,
00416                         dst,
00417                         src,
00418                         NULL,
00419                         srcInc,
00420                         len,
00421                         size,
00422                         callback,
00423                         cbUserParam );
00424 }
00425 #endif
00426 
00427 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
00428 /***************************************************************************/
00468 Ecode_t DMADRV_MemoryPeripheralPingPong(
00469                                  unsigned int          channelId,
00470                                  DMADRV_PeripheralSignal_t
00471                                                        peripheralSignal,
00472                                  void                  *dst,
00473                                  void                  *src0,
00474                                  void                  *src1,
00475                                  bool                  srcInc,
00476                                  int                   len,
00477                                  DMADRV_DataSize_t     size,
00478                                  DMADRV_Callback_t     callback,
00479                                  void                  *cbUserParam )
00480 {
00481   return StartTransfer( dmaModePingPong,
00482                         dmaDirectionMemToPeripheral,
00483                         channelId,
00484                         peripheralSignal,
00485                         dst,
00486                         src0,
00487                         src1,
00488                         srcInc,
00489                         len,
00490                         size,
00491                         callback,
00492                         cbUserParam );
00493 }
00494 #endif
00495 
00496 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
00497 /***************************************************************************/
00534 Ecode_t DMADRV_PeripheralMemory( unsigned int          channelId,
00535                                  DMADRV_PeripheralSignal_t
00536                                                        peripheralSignal,
00537                                  void                  *dst,
00538                                  void                  *src,
00539                                  bool                  dstInc,
00540                                  int                   len,
00541                                  DMADRV_DataSize_t     size,
00542                                  DMADRV_Callback_t     callback,
00543                                  void                  *cbUserParam )
00544 {
00545   return StartTransfer( dmaModeBasic,
00546                         dmaDirectionPeripheralToMem,
00547                         channelId,
00548                         peripheralSignal,
00549                         dst,
00550                         src,
00551                         NULL,
00552                         dstInc,
00553                         len,
00554                         size,
00555                         callback,
00556                         cbUserParam );
00557 }
00558 #endif
00559 
00560 #if !defined( EMDRV_DMADRV_USE_NATIVE_API ) || defined( DOXY_DOC_ONLY )
00561 /***************************************************************************/
00601 Ecode_t DMADRV_PeripheralMemoryPingPong(
00602                                  unsigned int          channelId,
00603                                  DMADRV_PeripheralSignal_t
00604                                                        peripheralSignal,
00605                                  void                  *dst0,
00606                                  void                  *dst1,
00607                                  void                  *src,
00608                                  bool                  dstInc,
00609                                  int                   len,
00610                                  DMADRV_DataSize_t     size,
00611                                  DMADRV_Callback_t     callback,
00612                                  void                  *cbUserParam )
00613 {
00614   return StartTransfer( dmaModePingPong,
00615                         dmaDirectionPeripheralToMem,
00616                         channelId,
00617                         peripheralSignal,
00618                         dst0,
00619                         dst1,
00620                         src,
00621                         dstInc,
00622                         len,
00623                         size,
00624                         callback,
00625                         cbUserParam );
00626 }
00627 #endif /* !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
00628 
00629 /***************************************************************************/
00640 Ecode_t DMADRV_StopTransfer( unsigned int channelId )
00641 {
00642   if ( !initialized )
00643   {
00644     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00645   }
00646 
00647   if ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00648   {
00649     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00650   }
00651 
00652   if ( chTable[ channelId ].allocated == false )
00653   {
00654     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00655   }
00656 
00657 #if defined( EMDRV_DMADRV_UDMA )
00658   DMA_ChannelEnable( channelId, false );
00659 #elif defined( EMDRV_DMADRV_LDMA )
00660   LDMA_StopTransfer( channelId );
00661 #endif
00662 
00663   return ECODE_EMDRV_DMADRV_OK;
00664 }
00665 
00666 /***************************************************************************/
00680 Ecode_t DMADRV_TransferActive( unsigned int channelId, bool *active )
00681 {
00682   if ( !initialized )
00683   {
00684     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00685   }
00686 
00687   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00688        || ( active == NULL ) )
00689   {
00690     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00691   }
00692 
00693   if ( chTable[ channelId ].allocated == false )
00694   {
00695     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00696   }
00697 
00698 #if defined( EMDRV_DMADRV_UDMA )
00699   if ( DMA_ChannelEnabled( channelId ) )
00700 #elif defined( EMDRV_DMADRV_LDMA )
00701   if ( LDMA->EN & ( 1 << channelId ) )
00702 #endif
00703   {
00704     *active = true;
00705   }
00706   else
00707   {
00708     *active = false;
00709   }
00710 
00711   return ECODE_EMDRV_DMADRV_OK;
00712 }
00713 
00714 /***************************************************************************/
00732 Ecode_t DMADRV_TransferCompletePending( unsigned int channelId, bool *pending )
00733 {
00734   if ( !initialized )
00735   {
00736     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00737   }
00738 
00739   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00740        || ( pending == NULL ) )
00741   {
00742     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00743   }
00744 
00745   if ( chTable[ channelId ].allocated == false )
00746   {
00747     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00748   }
00749 
00750 #if defined( EMDRV_DMADRV_UDMA )
00751   if ( DMA->IF & ( 1 << channelId ) )
00752 #elif defined( EMDRV_DMADRV_LDMA )
00753   if ( LDMA->IF & ( 1 << channelId ) )
00754 #endif
00755   {
00756     *pending = true;
00757   }
00758   else
00759   {
00760     *pending = false;
00761   }
00762 
00763   return ECODE_EMDRV_DMADRV_OK;
00764 }
00765 
00766 /***************************************************************************/
00785 Ecode_t DMADRV_TransferDone( unsigned int channelId, bool *done )
00786 {
00787 #if defined( EMDRV_DMADRV_UDMA )
00788   uint32_t remaining, iflag;
00789 #endif
00790 
00791   if ( !initialized )
00792   {
00793     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00794   }
00795 
00796   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00797        || ( done == NULL ) )
00798   {
00799     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00800   }
00801 
00802   if ( chTable[ channelId ].allocated == false )
00803   {
00804     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00805   }
00806 
00807 #if defined( EMDRV_DMADRV_UDMA )
00808   INT_Disable();
00809   /* This works for primary channel only ! */
00810   remaining = ( dmaControlBlock[ channelId ].CTRL
00811                 & _DMA_CTRL_N_MINUS_1_MASK )
00812               >> _DMA_CTRL_N_MINUS_1_SHIFT;
00813   iflag = DMA->IF;
00814   INT_Enable();
00815 
00816   if ( ( remaining == 0 ) && ( iflag & ( 1 << channelId ) ) )
00817   {
00818     *done = true;
00819   }
00820   else
00821   {
00822     *done = false;
00823   }
00824 #elif defined( EMDRV_DMADRV_LDMA )
00825   *done = LDMA_TransferDone( channelId );
00826 #endif
00827 
00828   return ECODE_EMDRV_DMADRV_OK;
00829 }
00830 
00831 /***************************************************************************/
00851 Ecode_t DMADRV_TransferRemainingCount( unsigned int channelId,
00852                                   int *remaining )
00853 {
00854 #if defined( EMDRV_DMADRV_UDMA )
00855   uint32_t remain, iflag;
00856 #endif
00857 
00858   if ( !initialized )
00859   {
00860     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
00861   }
00862 
00863   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
00864        || ( remaining == NULL ) )
00865   {
00866     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
00867   }
00868 
00869   if ( chTable[ channelId ].allocated == false )
00870   {
00871     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
00872   }
00873 
00874 #if defined( EMDRV_DMADRV_UDMA )
00875   INT_Disable();
00876   /* This works for primary channel only ! */
00877   remain = ( dmaControlBlock[ channelId ].CTRL
00878              & _DMA_CTRL_N_MINUS_1_MASK )
00879            >> _DMA_CTRL_N_MINUS_1_SHIFT;
00880   iflag = DMA->IF;
00881   INT_Enable();
00882 
00883   if ( ( remain == 0 ) && ( iflag & ( 1 << channelId ) ) )
00884   {
00885     *remaining = 0;
00886   }
00887   else
00888   {
00889     *remaining = 1 + remain;
00890   }
00891 #elif defined( EMDRV_DMADRV_LDMA )
00892   *remaining = LDMA_TransferRemainingCount( channelId );
00893 #endif
00894 
00895   return ECODE_EMDRV_DMADRV_OK;
00896 }
00897 
00899 
00900 #if defined( EMDRV_DMADRV_LDMA )
00901 /***************************************************************************/
00905 void LDMA_IRQHandler( void )
00906 {
00907 #if !defined( EMDRV_DMADRV_USE_NATIVE_API )
00908   bool stop;
00909 #endif
00910   ChTable_t *ch;
00911   uint32_t pending, chnum, chmask;
00912 
00913   /* Get all pending and enabled interrupts */
00914   pending  = LDMA->IF;
00915   pending &= LDMA->IEN;
00916 
00917   /* Check for LDMA error */
00918   if ( pending & LDMA_IF_ERROR )
00919   {
00920     /* Loop here to enable the debugger to see what has happened */
00921     while (1)
00922     {
00923       /* Wait forever. */
00924     }
00925   }
00926 
00927   /* Iterate over all LDMA channels. */
00928   for ( chnum = 0,                          chmask = 1;
00929         chnum < EMDRV_DMADRV_DMA_CH_COUNT;
00930         chnum++,                            chmask <<= 1 )
00931   {
00932     if ( pending & chmask )
00933     {
00934       /* Clear interrupt flag. */
00935       LDMA->IFC = chmask;
00936 
00937       ch = &chTable[ chnum ];
00938       if ( ch->callback != NULL )
00939       {
00940         ch->callbackCount++;
00941 #if defined( EMDRV_DMADRV_USE_NATIVE_API )
00942         ch->callback( chnum, ch->callbackCount, ch->userParam );
00943 #else
00944         stop = !ch->callback( chnum, ch->callbackCount, ch->userParam );
00945 
00946         if ( ( ch->mode == dmaModePingPong ) && stop )
00947         {
00948           dmaXfer[ chnum ].desc[0].xfer.link = 0;
00949           dmaXfer[ chnum ].desc[1].xfer.link = 0;
00950         }
00951 #endif
00952       }
00953     }
00954   }
00955 }
00956 #endif /* defined( EMDRV_DMADRV_LDMA ) */
00957 
00958 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
00959 /***************************************************************************/
00963 static void DmaBasicCallback( unsigned int channel, bool primary, void *user )
00964 {
00965   ChTable_t *ch = &chTable[ channel ];
00966   (void)user;
00967   (void)primary;
00968 
00969   if ( ch->callback != NULL )
00970   {
00971     ch->callbackCount++;
00972     ch->callback( channel, ch->callbackCount, ch->userParam );
00973   }
00974 }
00975 #endif
00976 
00977 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
00978 /***************************************************************************/
00982 static void DmaPingPongCallback( unsigned int channel, bool primary, void *user )
00983 {
00984   bool stop = true;
00985   ChTable_t *ch = &chTable[ channel ];
00986 
00987   (void)user;
00988 
00989   if ( ch->callback != NULL )
00990   {
00991     ch->callbackCount++;
00992     stop = !ch->callback( channel, ch->callbackCount, ch->userParam );
00993   }
00994 
00995   DMA_RefreshPingPong(  0,
00996                         primary,
00997                         false,
00998                         NULL,
00999                         NULL,
01000                         ch->length - 1,
01001                         stop );
01002 }
01003 #endif
01004 
01005 #if defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
01006 /***************************************************************************/
01010 static Ecode_t StartTransfer( DmaMode_t             mode,
01011                               DmaDirection_t        direction,
01012                               unsigned int          channelId,
01013                               DMADRV_PeripheralSignal_t
01014                                                     peripheralSignal,
01015                               void                  *buf0,
01016                               void                  *buf1,
01017                               void                  *buf2,
01018                               bool                  bufInc,
01019                               int                   len,
01020                               DMADRV_DataSize_t     size,
01021                               DMADRV_Callback_t     callback,
01022                               void                  *cbUserParam )
01023 {
01024   ChTable_t *ch;
01025   DMA_CfgChannel_TypeDef chCfg;
01026   DMA_CfgDescr_TypeDef   descrCfg;
01027 
01028   if ( !initialized )
01029   {
01030     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
01031   }
01032 
01033   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
01034        || ( buf0 == NULL )
01035        || ( buf1 == NULL )
01036        || ( len > DMADRV_MAX_XFER_COUNT )
01037        || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
01038   {
01039     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
01040   }
01041 
01042   ch = &chTable[ channelId ];
01043   if ( ch->allocated == false )
01044   {
01045     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
01046   }
01047 
01048   /* Setup the interrupt callback routine. */
01049   if ( mode == dmaModeBasic )
01050   {
01051     dmaCallBack[ channelId ].cbFunc  = DmaBasicCallback;
01052   }
01053   else
01054   {
01055     dmaCallBack[ channelId ].cbFunc  = DmaPingPongCallback;
01056   }
01057   dmaCallBack[ channelId ].userPtr = NULL;
01058 
01059   /* Setup the channel */
01060   chCfg.highPri = false;              /* Can't use hi pri with peripherals. */
01061 
01062   /* Interrupt needed ? */
01063   if ( ( callback != NULL ) || ( mode == dmaModePingPong ) )
01064   {
01065     chCfg.enableInt = true;
01066   }
01067   else
01068   {
01069     chCfg.enableInt = false;
01070   }
01071   chCfg.select = peripheralSignal;
01072   chCfg.cb     = &dmaCallBack[ channelId ];
01073   DMA_CfgChannel( channelId, &chCfg );
01074 
01075   /* Setup channel descriptor. */
01076   if ( direction == dmaDirectionMemToPeripheral )
01077   {
01078     if ( bufInc )
01079     {
01080       if ( size == dmadrvDataSize1 )
01081       {
01082         descrCfg.srcInc = dmaDataInc1;
01083       }
01084       else if ( size == dmadrvDataSize2 )
01085       {
01086         descrCfg.srcInc = dmaDataInc2;
01087       }
01088       else /* dmadrvDataSize4 */
01089       {
01090         descrCfg.srcInc = dmaDataInc4;
01091       }
01092     }
01093     else
01094     {
01095       descrCfg.srcInc = dmaDataIncNone;
01096     }
01097     descrCfg.dstInc = dmaDataIncNone;
01098   }
01099   else
01100   {
01101     if ( bufInc )
01102     {
01103       if ( size == dmadrvDataSize1 )
01104       {
01105         descrCfg.dstInc = dmaDataInc1;
01106       }
01107       else if ( size == dmadrvDataSize2 )
01108       {
01109         descrCfg.dstInc = dmaDataInc2;
01110       }
01111       else /* dmadrvDataSize4 */
01112       {
01113         descrCfg.dstInc = dmaDataInc4;
01114       }
01115     }
01116     else
01117     {
01118       descrCfg.dstInc = dmaDataIncNone;
01119     }
01120     descrCfg.srcInc = dmaDataIncNone;
01121   }
01122   descrCfg.size    = (DMA_DataSize_TypeDef)size;
01123   descrCfg.arbRate = dmaArbitrate1;
01124   descrCfg.hprot   = 0;
01125   DMA_CfgDescr( channelId, true, &descrCfg );
01126   if ( mode == dmaModePingPong )
01127   {
01128     DMA_CfgDescr( channelId, false, &descrCfg );
01129   }
01130 
01131   ch->callback      = callback;
01132   ch->userParam     = cbUserParam;
01133   ch->callbackCount = 0;
01134   ch->length        = len;
01135 
01136   DMA->IFC = 1 << channelId;
01137 
01138   /* Start DMA cycle. */
01139   if ( mode == dmaModeBasic )
01140   {
01141     DMA_ActivateBasic( channelId, true, false, buf0, buf1, len - 1 );
01142   }
01143   else
01144   {
01145     if ( direction == dmaDirectionMemToPeripheral )
01146     {
01147       DMA_ActivatePingPong( channelId,
01148                             false,
01149                             buf0,                             /* dest */
01150                             buf1,                             /* src  */
01151                             len - 1,
01152                             buf0,                             /* dest */
01153                             buf2,                             /* src  */
01154                             len - 1);
01155     }
01156     else
01157     {
01158       DMA_ActivatePingPong( channelId,
01159                             false,
01160                             buf0,                             /* dest */
01161                             buf2,                             /* src  */
01162                             len - 1,
01163                             buf1,                             /* dest */
01164                             buf2,                             /* src  */
01165                             len - 1);
01166     }
01167   }
01168 
01169   return ECODE_EMDRV_DMADRV_OK;
01170 }
01171 #endif /* defined( EMDRV_DMADRV_UDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
01172 
01173 #if defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API )
01174 /***************************************************************************/
01178 static Ecode_t StartTransfer( DmaMode_t             mode,
01179                               DmaDirection_t        direction,
01180                               unsigned int          channelId,
01181                               DMADRV_PeripheralSignal_t
01182                                                     peripheralSignal,
01183                               void                  *buf0,
01184                               void                  *buf1,
01185                               void                  *buf2,
01186                               bool                  bufInc,
01187                               int                   len,
01188                               DMADRV_DataSize_t     size,
01189                               DMADRV_Callback_t     callback,
01190                               void                  *cbUserParam )
01191 {
01192   ChTable_t *ch;
01193   LDMA_TransferCfg_t xfer;
01194   LDMA_Descriptor_t *desc;
01195 
01196   if ( !initialized )
01197   {
01198     return ECODE_EMDRV_DMADRV_NOT_INITIALIZED;
01199   }
01200 
01201   if ( ( channelId > EMDRV_DMADRV_DMA_CH_COUNT )
01202        || ( buf0 == NULL )
01203        || ( buf1 == NULL )
01204        || ( len > DMADRV_MAX_XFER_COUNT )
01205        || ( ( mode == dmaModePingPong ) && ( buf2 == NULL ) ) )
01206   {
01207     return ECODE_EMDRV_DMADRV_PARAM_ERROR;
01208   }
01209 
01210   ch = &chTable[ channelId ];
01211   if ( ch->allocated == false )
01212   {
01213     return ECODE_EMDRV_DMADRV_CH_NOT_ALLOCATED;
01214   }
01215 
01216   xfer = xferCfg;
01217   desc = &dmaXfer[ channelId ].desc[0];
01218 
01219   if ( direction == dmaDirectionMemToPeripheral )
01220   {
01221     *desc = m2p;
01222     if ( !bufInc )
01223     {
01224       desc->xfer.srcInc = ldmaCtrlSrcIncNone;
01225     }
01226   }
01227   else
01228   {
01229     *desc = p2m;
01230     if ( !bufInc )
01231     {
01232       desc->xfer.destInc = ldmaCtrlDstIncNone;
01233     }
01234   }
01235   xfer.ldmaMuxsel    = peripheralSignal;
01236   desc->xfer.xferCnt = len - 1;
01237   desc->xfer.dstAddr = (uint32_t)buf0;
01238   desc->xfer.srcAddr = (uint32_t)buf1;
01239   desc->xfer.size    = size;
01240 
01241   if ( mode == dmaModePingPong )
01242   {
01243     desc->xfer.linkMode = ldmaLinkModeRel;
01244     desc->xfer.link     = 1;
01245     desc->xfer.linkAddr = 4;      /* Refer to "pong" descriptor. */
01246 
01247     /* Set the "pong" descriptor equal to the "ping" descriptor. */
01248     dmaXfer[ channelId ].desc[1] = *desc;
01249     /* Refer to "ping" descriptor. */
01250     dmaXfer[ channelId ].desc[1].xfer.linkAddr = -4;
01251     dmaXfer[ channelId ].desc[1].xfer.srcAddr = (uint32_t)buf2;
01252 
01253     if ( direction == dmaDirectionPeripheralToMem )
01254     {
01255       dmaXfer[ channelId ].desc[1].xfer.dstAddr = (uint32_t)buf1;
01256       desc->xfer.srcAddr = (uint32_t)buf2;
01257     }
01258   }
01259 
01260   /* Interrupt needed ? */
01261   if ( ( callback == NULL ) && ( mode == dmaModeBasic ) )
01262   {
01263     desc->xfer.doneIfs = 0;
01264   }
01265 
01266   ch->callback      = callback;
01267   ch->userParam     = cbUserParam;
01268   ch->callbackCount = 0;
01269   ch->mode          = mode;
01270 
01271   LDMA_StartTransfer( channelId, &xfer, desc );
01272 
01273   return ECODE_EMDRV_DMADRV_OK;
01274 }
01275 #endif /* defined( EMDRV_DMADRV_LDMA ) && !defined( EMDRV_DMADRV_USE_NATIVE_API ) */
01276 
01278 
01279 
01280 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/