![]() |
PDL for FM0+
Version1.0
Peripheral Driverl Library for FM0+
|
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