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
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
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
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
00914 pending = LDMA->IF;
00915 pending &= LDMA->IEN;
00916
00917
00918 if ( pending & LDMA_IF_ERROR )
00919 {
00920
00921 while (1)
00922 {
00923
00924 }
00925 }
00926
00927
00928 for ( chnum = 0, chmask = 1;
00929 chnum < EMDRV_DMADRV_DMA_CH_COUNT;
00930 chnum++, chmask <<= 1 )
00931 {
00932 if ( pending & chmask )
00933 {
00934
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
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
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
01060 chCfg.highPri = false;
01061
01062
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
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
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
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
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,
01150 buf1,
01151 len - 1,
01152 buf0,
01153 buf2,
01154 len - 1);
01155 }
01156 else
01157 {
01158 DMA_ActivatePingPong( channelId,
01159 false,
01160 buf0,
01161 buf2,
01162 len - 1,
01163 buf1,
01164 buf2,
01165 len - 1);
01166 }
01167 }
01168
01169 return ECODE_EMDRV_DMADRV_OK;
01170 }
01171 #endif
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;
01246
01247
01248 dmaXfer[ channelId ].desc[1] = *desc;
01249
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
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
01276
01278
01279
01280