PDL for FM0+  Version1.0
Peripheral Driverl Library for FM0+
C:/pdl_v10/library/driver/dma/dma.c
Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2013 Spansion LLC. All Rights Reserved. 
00003 *
00004 * This software is owned and published by: 
00005 * Spansion LLC, 915 DeGuigne Dr. Sunnyvale, CA  94088-3453 ("Spansion").
00006 *
00007 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND 
00008 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
00009 *
00010 * This software contains source code for use with Spansion 
00011 * components. This software is licensed by Spansion to be adapted only 
00012 * for use in systems utilizing Spansion components. Spansion shall not be 
00013 * responsible for misuse or illegal use of this software for devices not 
00014 * supported herein.  Spansion is providing this software "AS IS" and will 
00015 * not be responsible for issues arising from incorrect user implementation 
00016 * of the software.  
00017 *
00018 * SPANSION MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
00019 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS), 
00020 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING, 
00021 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED 
00022 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED 
00023 * WARRANTY OF NONINFRINGEMENT.  
00024 * SPANSION SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT, 
00025 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT 
00026 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, 
00027 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR 
00028 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT, 
00029 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA, 
00030 * SAVINGS OR PROFITS, 
00031 * EVEN IF SPANSION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
00032 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
00033 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED 
00034 * FROM, THE SOFTWARE.  
00035 *
00036 * This software may be replicated in part or whole for the licensed use, 
00037 * with the restriction that this Disclaimer and Copyright notice must be 
00038 * included with each copy of this software, whether used in part or whole, 
00039 * at all times.  
00040 */
00041 /******************************************************************************/
00053 /******************************************************************************/
00054 /* Include files                                                              */
00055 /******************************************************************************/
00056 #include "dma.h"
00057 
00058 #if (defined(PDL_PERIPHERAL_DMA_ACTIVE))
00059 
00065 
00066 /******************************************************************************/
00067 /* Local pre-processor symbols/macros ('#define')                             */
00068 /******************************************************************************/
00069 // DMACAn => FM3_DMAC_BASE + size of register set + offset of DMACA0
00070 // DMACAn => 0x40060000    + 0x10 * n             + 0x10
00071 #define GET_DMA_ADDRESS(x) (FM0P_DMAC_BASE + (0x10ul * (x)) + 0x10ul)
00072 
00073 /******************************************************************************/
00074 /* Global variable definitions (declared in header file with 'extern')        */
00075 /******************************************************************************/
00076 #if (PDL_INTERRUPT_ENABLE_DMA0 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA1 == PDL_ON) || \
00077     (PDL_INTERRUPT_ENABLE_DMA2 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA3 == PDL_ON)    
00078 static stc_dma_intern_data_t stcDmaInternData; 
00079 #endif
00080 
00081 /******************************************************************************/
00082 /* Local type definitions ('typedef')                                         */
00083 /******************************************************************************/
00084 typedef union
00085 {
00086     uint32_t                 u32DMACA;
00087     stc_dmac_dmaca0_field_t  stcDMACA;
00088     
00089 }un_dmac_dmaca_t;
00090   
00091 typedef union
00092 {
00093     stc_dmac_dmacb0_field_t  stcDMACB;
00094     uint32_t                 u32DMACB;
00095     
00096 }un_dmac_dmacb_t;
00097 
00098 /******************************************************************************/
00099 /* Local function prototypes ('static')                                       */
00100 /******************************************************************************/
00101 
00102 /******************************************************************************/
00103 /* Local variable definitions ('static')                                      */
00104 /******************************************************************************/
00105 #if (PDL_INTERRUPT_ENABLE_DMA0 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA1 == PDL_ON) || \
00106     (PDL_INTERRUPT_ENABLE_DMA2 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA3 == PDL_ON) 
00107 /******************************************************************************/
00108 /* Function implementation - global ('extern') and local ('static')           */
00109 /******************************************************************************/
00110 static en_result_t Dma_Irq_Init(uint8_t u8DmaChannel);
00111 static en_result_t Dma_Irq_DeInit(uint8_t u8DmaChannel);
00112 #endif
00113 
00114 #if (PDL_INTERRUPT_ENABLE_DMA0 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA1 == PDL_ON) || \
00115     (PDL_INTERRUPT_ENABLE_DMA2 == PDL_ON) || (PDL_INTERRUPT_ENABLE_DMA3 == PDL_ON) 
00116 
00127 void DmaIrqHandler(uint8_t u8DmaChannel)
00128 {
00129   uint32_t u32DmaRegisterBaseAddress;
00130   uint32_t u32RegisterReadOut;
00131   uint8_t  u8StopStatus;
00132   
00133   u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00134   
00135   // Readout DMACB and update
00136   u32RegisterReadOut = *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET));
00137   
00138   u8StopStatus = (uint8_t)((u32RegisterReadOut & 0x00070000ul)>> 16u);
00139   
00140   // Clear interrupt cause
00141   u32RegisterReadOut &= 0xFFF8FFFF;     
00142   *(uint32_t*)(uint32_t)((u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) 
00143     = u32RegisterReadOut;  
00144   
00145   if (0x5u == u8StopStatus)  // Successful DMA transfer
00146   {
00147     stcDmaInternData.apfnDmaCallback[u8DmaChannel](); 
00148   }
00149   else                      // Errornous DMA transfer
00150   {
00151     stcDmaInternData.apfnDmaErrorCallback[u8DmaChannel](u8StopStatus);
00152   }
00153 }
00154 
00164 static en_result_t Dma_Irq_Init(uint8_t u8DmaChannel)
00165 {
00166   switch(u8DmaChannel)
00167   {
00168     case 0u:
00169       NVIC_ClearPendingIRQ(MFS6_14_RX_DMA0_IRQn);
00170       NVIC_EnableIRQ(MFS6_14_RX_DMA0_IRQn);
00171       NVIC_SetPriority(MFS6_14_RX_DMA0_IRQn, PDL_IRQ_LEVEL_MFS6_14_RX_DMA0);    
00172     break;
00173     case 1u:
00174       NVIC_ClearPendingIRQ(MFS6_14_TX_DMA1_IRQn);
00175       NVIC_EnableIRQ(MFS6_14_TX_DMA1_IRQn);
00176       NVIC_SetPriority(MFS6_14_TX_DMA1_IRQn, PDL_IRQ_LEVEL_MFS6_14_TX_DMA1);    
00177     break;
00178     case 2u:
00179       NVIC_ClearPendingIRQ(MFS7_15_RX_DMA2_IRQn);
00180       NVIC_EnableIRQ(MFS7_15_RX_DMA2_IRQn);
00181       NVIC_SetPriority(MFS7_15_RX_DMA2_IRQn, PDL_IRQ_LEVEL_MFS7_15_RX_DMA2);    
00182     break;
00183     case 3u:
00184       NVIC_ClearPendingIRQ(MFS7_15_TX_DMA3_IRQn);
00185       NVIC_EnableIRQ(MFS7_15_TX_DMA3_IRQn);
00186       NVIC_SetPriority(MFS7_15_TX_DMA3_IRQn, PDL_IRQ_LEVEL_MFS7_15_TX_DMA3);    
00187     break;  
00188     default:
00189     break;
00190   }
00191   return Ok;
00192 }
00193 
00203 static en_result_t Dma_Irq_DeInit(uint8_t u8DmaChannel)
00204 {
00205   switch(u8DmaChannel)
00206   {
00207     case 0:
00208 #if (PDL_INTERRUPT_ENABLE_MFS6 == PDL_OFF) && (PDL_INTERRUPT_ENABLE_MFS14 == PDL_OFF)        
00209       NVIC_ClearPendingIRQ(MFS6_14_RX_DMA0_IRQn);
00210       NVIC_DisableIRQ(MFS6_14_RX_DMA0_IRQn);
00211       NVIC_SetPriority(MFS6_14_RX_DMA0_IRQn, PDL_DEFAULT_INTERRUPT_LEVEL);   
00212 #endif      
00213     break;
00214     case 1:
00215 #if (PDL_INTERRUPT_ENABLE_MFS6 == PDL_OFF) && (PDL_INTERRUPT_ENABLE_MFS14 == PDL_OFF)       
00216       NVIC_ClearPendingIRQ(MFS6_14_TX_DMA1_IRQn);
00217       NVIC_DisableIRQ(MFS6_14_TX_DMA1_IRQn);
00218       NVIC_SetPriority(MFS6_14_TX_DMA1_IRQn, PDL_DEFAULT_INTERRUPT_LEVEL);    
00219 #endif      
00220     break;
00221     case 2:
00222 #if (PDL_INTERRUPT_ENABLE_MFS7 == PDL_OFF) && (PDL_INTERRUPT_ENABLE_MFS15 == PDL_OFF)        
00223       NVIC_ClearPendingIRQ(MFS7_15_RX_DMA2_IRQn);
00224       NVIC_DisableIRQ(MFS7_15_RX_DMA2_IRQn);
00225       NVIC_SetPriority(MFS7_15_RX_DMA2_IRQn, PDL_DEFAULT_INTERRUPT_LEVEL);   
00226 #endif      
00227     break;
00228     case 3:
00229 #if (PDL_INTERRUPT_ENABLE_MFS7 == PDL_OFF) && (PDL_INTERRUPT_ENABLE_MFS15 == PDL_OFF)         
00230       NVIC_ClearPendingIRQ(MFS7_15_TX_DMA3_IRQn);
00231       NVIC_DisableIRQ(MFS7_15_TX_DMA3_IRQn);
00232       NVIC_SetPriority(MFS7_15_TX_DMA3_IRQn, PDL_DEFAULT_INTERRUPT_LEVEL);   
00233 #endif      
00234     break;   
00235     default:
00236     break;
00237   }
00238   return Ok;
00239 }
00240 
00257 en_result_t Dma_EnableInt(uint8_t u8DmaChannel, 
00258                           stc_dma_int_sel_t* pstcIntSel,
00259                           stc_dma_int_cb_t* pstcIntCb  )
00260 {
00261     uint32_t u32DmaRegisterBaseAddress; 
00262     un_dmac_dmacb_t unDmacDmacb;
00263     
00264     if(u8DmaChannel > DMA_MAX_CH_INDEX)
00265     {
00266         return ErrorInvalidParameter;
00267     }
00268     
00269     u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00270     
00271     // Readout original DMACB
00272     unDmacDmacb.u32DMACB = *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) ;
00273     
00274     // Update EI and CI bit
00275     if(pstcIntSel->bCompleteInt == TRUE)
00276     {
00277         stcDmaInternData.apfnDmaCallback[u8DmaChannel] = pstcIntCb->pfnCompleteCallback;
00278         unDmacDmacb.stcDMACB.CI = 1;
00279     }
00280     
00281     if(pstcIntSel->bErrorInt == TRUE)
00282     {
00283         stcDmaInternData.apfnDmaErrorCallback[u8DmaChannel] = pstcIntCb->pfnErrorCallback;
00284         unDmacDmacb.stcDMACB.EI = 1;
00285     }
00286     
00287     // Write back to DMACB
00288     *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) = unDmacDmacb.u32DMACB;
00289     
00290     Dma_Irq_Init(u8DmaChannel);
00291     
00292     return Ok;
00293 }
00294 
00308 en_result_t Dma_DisableInt(uint8_t u8DmaChannel, 
00309                            stc_dma_int_sel_t* pstcIntSel )
00310 {
00311     uint32_t u32DmaRegisterBaseAddress;
00312     un_dmac_dmacb_t unDmacDmacb;
00313     
00314     if(u8DmaChannel > DMA_MAX_CH_INDEX)
00315     {
00316         return ErrorInvalidParameter;
00317     }
00318     
00319     u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00320     
00321     // Readout original DMACB
00322     unDmacDmacb.u32DMACB = *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) ;
00323     
00324     // Update EI and CI bit
00325     if(pstcIntSel->bCompleteInt == TRUE)
00326     {
00327         stcDmaInternData.apfnDmaCallback[u8DmaChannel] = NULL;
00328         unDmacDmacb.stcDMACB.CI = 0;
00329     }
00330     
00331     if(pstcIntSel->bErrorInt == TRUE)
00332     {
00333         stcDmaInternData.apfnDmaErrorCallback[u8DmaChannel] = NULL;
00334         unDmacDmacb.stcDMACB.EI = 0;
00335     }
00336     
00337     // Write back to DMACB
00338     *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) = unDmacDmacb.u32DMACB;
00339     
00340     Dma_Irq_DeInit(u8DmaChannel);
00341     
00342     return Ok;
00343 }
00344 
00345 #endif
00346 
00362 en_result_t Dma_Init_Channel(uint8_t u8DmaChannel, volatile stc_dma_config_t* pstcConfig)                   
00363 {  
00364   un_dmac_dmaca_t unDmacDmaca;
00365   un_dmac_dmacb_t unDmacDmacb;
00366   uint32_t        u32DmaRegisterBaseAddress;
00367   uint32_t u32DrqselBit;
00368 
00369   // Check for NULL pointer
00370   if (pstcConfig == NULL)
00371   {
00372     return ErrorInvalidParameter ;
00373   }
00374   
00375   unDmacDmaca.u32DMACA = 0u;
00376   unDmacDmacb.u32DMACB = 0u;
00377 
00378   u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00379   
00380   // Setup DMACA ...
00381   //
00382   // Block Count
00383   unDmacDmaca.stcDMACA.BC = 0x0Fu & (uint32_t)(pstcConfig->u8BlockCount - 1);
00384   
00385   // Transfer Count
00386   unDmacDmaca.stcDMACA.TC = 0xFFFFu & (uint32_t)(pstcConfig->u16TransferCount - 1);
00387   
00388   // Interrupt Request Channel
00389   if (pstcConfig->enDmaIdrq == Software)
00390   {
00391     unDmacDmaca.stcDMACA.IS = 0u;
00392   }
00393   else
00394   {
00395     unDmacDmaca.stcDMACA.IS = 0x20u | (0x1Fu &  (uint32_t)(pstcConfig->enDmaIdrq));
00396   }
00397   
00398   // ... and update hardware
00399   *(uint32_t*)(uint32_t)((u32DmaRegisterBaseAddress + DMA_DMACA_OFFSET)) = unDmacDmaca.u32DMACA ;
00400   
00401   // Setup DMACB ...
00402   //
00403   // First Transfer mode
00404   switch (pstcConfig->enTransferMode)
00405   {
00406     case DmaBlockTransfer:
00407       unDmacDmacb.stcDMACB.MS = 0u;
00408       break;
00409     case DmaBurstTransfer:
00410       unDmacDmacb.stcDMACB.MS = 1u;
00411       break;
00412     case DmaDemandTransfer:
00413       unDmacDmacb.stcDMACB.MS = 2u;
00414       break;
00415     default :
00416       return ErrorInvalidParameter;
00417   }
00418   
00419   // Transfer width
00420   switch (pstcConfig->enTransferWdith)
00421   {
00422     case Dma8Bit:
00423       unDmacDmacb.stcDMACB.TW = 0u;
00424       break;
00425     case Dma16Bit:
00426       unDmacDmacb.stcDMACB.TW = 1u;
00427       break;
00428     case Dma32Bit:
00429       unDmacDmacb.stcDMACB.TW = 2u;
00430       break;
00431     default :
00432       return ErrorInvalidParameter;
00433   }
00434  
00435   // Fixed source
00436   unDmacDmacb.stcDMACB.FS = (uint8_t)((pstcConfig->bFixedSource == TRUE) ? 1u : 0u);
00437   
00438   // Fixed destination
00439   unDmacDmacb.stcDMACB.FD = (uint8_t)((pstcConfig->bFixedDestination == TRUE) ? 1u : 0u);
00440   
00441   // Reload Count (BC/TC reload)
00442   unDmacDmacb.stcDMACB.RC = (uint8_t)((pstcConfig->bReloadCount == TRUE) ? 1u : 0u);
00443   
00444   // Reload Source
00445   unDmacDmacb.stcDMACB.RS = (uint8_t)((pstcConfig->bReloadSource == TRUE) ? 1u : 0u);
00446   
00447   // Reload Destination
00448   unDmacDmacb.stcDMACB.RD = (uint8_t)((pstcConfig->bReloadDestination == TRUE) ? 1u : 0u);
00449   
00450   // Enable bit mask
00451   unDmacDmacb.stcDMACB.EM = (uint8_t)((pstcConfig->bEnableBitMask == TRUE) ? 1u : 0u);
00452   
00453   // ... and update hardware
00454   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET))
00455     = unDmacDmacb.u32DMACB ;
00456   
00457   // Setup source address
00458   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMASA_OFFSET))
00459     = pstcConfig->u32SourceAddress;
00460   
00461   // Setup destination address
00462   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMADA_OFFSET))
00463     = pstcConfig->u32DestinationAddress;
00464   
00465   // Switch resource interrupt to DMA (except software DMA)
00466   if (pstcConfig->enDmaIdrq != Software)
00467   {
00468     u32DrqselBit = 1ul << (uint32_t)(pstcConfig->enDmaIdrq);
00469     FM0P_INTREQ->DRQSEL |= u32DrqselBit;
00470   }
00471   
00472   return Ok;
00473 }
00474 
00487 en_result_t Dma_DeInit_Channel(uint8_t u8DmaChannel)  
00488 {
00489   uint32_t u32DmaRegisterBaseAddress;
00490   
00491   Dma_Irq_DeInit(u8DmaChannel);
00492   
00493   u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00494   
00495   // clear all registers of DMA channel
00496   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACA_OFFSET)) = 0u;
00497   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) = 0u;
00498   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMASA_OFFSET)) = 0u;
00499   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMADA_OFFSET)) = 0u;
00500   
00501   return Ok;
00502 } // Dma_DeInit_Channel
00503 
00520 en_result_t Dma_SetChannel (uint8_t u8DmaChannel, 
00521                             boolean_t bEnable,
00522                             boolean_t bPause,
00523                             boolean_t bSoftwareTrigger) 
00524 {
00525   un_dmac_dmaca_t unDmacDmaca;
00526   uint32_t u32RegisterReadOut ;
00527   uint32_t u32DmaRegisterBaseAddress ;
00528 
00529   unDmacDmaca.u32DMACA = 0u;
00530   unDmacDmaca.stcDMACA.EB = (uint8_t)((bEnable == TRUE) ? 1u : 0u);
00531   unDmacDmaca.stcDMACA.PB = (uint8_t)((bPause == TRUE) ? 1u : 0u);
00532   unDmacDmaca.stcDMACA.ST = (uint8_t)((bSoftwareTrigger == TRUE) ? 1u : 0u);
00533   
00534   u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00535   
00536   // Readout DMACA and update
00537   u32RegisterReadOut = *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACA_OFFSET)) ;
00538   unDmacDmaca.u32DMACA |= (u32RegisterReadOut & 0x1FFFFFFFu);   // masking EB, PB, ST ...
00539   *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACA_OFFSET)) = unDmacDmaca.u32DMACA ;
00540   
00541   return Ok;
00542 }
00543 
00558 en_dma_stop_cause_t Dma_GetStopCause(uint8_t u8DmaChannel)
00559 {
00560     un_dmac_dmacb_t unDmacDmacb;
00561     uint32_t u32DmaRegisterBaseAddress;
00562     
00563     u32DmaRegisterBaseAddress = GET_DMA_ADDRESS(u8DmaChannel);
00564    
00565     // Readout original DMACB
00566     unDmacDmacb.u32DMACB = *(uint32_t*)((uint32_t)(u32DmaRegisterBaseAddress + DMA_DMACB_OFFSET)) ;
00567     
00568     return (en_dma_stop_cause_t) (unDmacDmacb.stcDMACB.SS);
00569 }
00570 
00578 en_result_t Dma_Enable(void)
00579 {
00580   FM0P_DMAC->DMACR = 0x80000000ul; 
00581   
00582   return Ok;
00583 }
00584 
00592 en_result_t Dma_Disable(void)
00593 {
00594   FM0P_DMAC->DMACR = 0u; 
00595   
00596   return Ok;
00597 }
00598 
00599 
00601 
00602 #endif // #if (defined(PDL_PERIPHERAL_DMA_ACTIVE))
00603 
00604 /******************************************************************************/
00605 /* EOF (not truncated)                                                        */
00606 /******************************************************************************/
00607