00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "chip.h"
00065 #include <assert.h>
00066 static uint8_t xDmad_Initialized = 0;
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static uint32_t XDMAD_AllocateXdmacChannel(sXdmad *pXdmad,
00080 uint8_t bSrcID,
00081 uint8_t bDstID)
00082 {
00083 uint32_t i;
00084
00085
00086 if (((bSrcID != XDMAD_TRANSFER_MEMORY)
00087 && (bDstID != XDMAD_TRANSFER_MEMORY)))
00088 return XDMAD_ALLOC_FAILED;
00089
00090
00091 if (bDstID == XDMAD_TRANSFER_MEMORY) {
00092 if ((!XDMAIF_IsValidatedPeripherOnDma(bSrcID))) {
00093 TRACE_ERROR("%s:: Allocation failed", __FUNCTION__);
00094 return XDMAD_ALLOC_FAILED;
00095 }
00096 }
00097
00098
00099 if (bSrcID == XDMAD_TRANSFER_MEMORY) {
00100 if ((!XDMAIF_IsValidatedPeripherOnDma(bDstID))) {
00101 TRACE_ERROR("%s:: Allocation failed", __FUNCTION__);
00102 return XDMAD_ALLOC_FAILED;
00103 }
00104 }
00105
00106 for (i = 0; i < pXdmad->numChannels; i ++) {
00107 if (pXdmad->XdmaChannels[i].state == XDMAD_STATE_FREE) {
00108
00109 pXdmad->XdmaChannels[i].state = XDMAD_STATE_ALLOCATED;
00110
00111 pXdmad->XdmaChannels[i].bSrcPeriphID = bSrcID;
00112 pXdmad->XdmaChannels[i].bDstPeriphID = bDstID;
00113 pXdmad->XdmaChannels[i].bSrcTxIfID =
00114 XDMAIF_Get_ChannelNumber(bSrcID, 0);
00115 pXdmad->XdmaChannels[i].bSrcRxIfID =
00116 XDMAIF_Get_ChannelNumber(bSrcID, 1);
00117 pXdmad->XdmaChannels[i].bDstTxIfID =
00118 XDMAIF_Get_ChannelNumber(bDstID, 0);
00119 pXdmad->XdmaChannels[i].bDstRxIfID =
00120 XDMAIF_Get_ChannelNumber(bDstID, 1);
00121 return ((i) & 0xFF);
00122 }
00123 }
00124
00125 TRACE_ERROR("%s:: Allocation failed, all channels are occupied", __FUNCTION__);
00126 return XDMAD_ALLOC_FAILED;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void XDMAD_Initialize(sXdmad *pXdmad, uint8_t bPollingMode)
00141 {
00142 uint32_t j;
00143 uint32_t volatile timer = 0x7FF;
00144
00145 assert(pXdmad);
00146 LockMutex(pXdmad->xdmaMutex, timer);
00147
00148 if (xDmad_Initialized) {
00149 ReleaseMutex(pXdmad->xdmaMutex);
00150 return;
00151 }
00152
00153 pXdmad->pXdmacs = XDMAC;
00154 pXdmad->pollingMode = bPollingMode;
00155 pXdmad->numControllers = XDMAC_CONTROLLER_NUM;
00156 pXdmad->numChannels = (XDMAC_GTYPE_NB_CH(XDMAC_GetType(XDMAC)) + 1);
00157
00158 for (j = 0; j < pXdmad->numChannels; j ++) {
00159 pXdmad->XdmaChannels[j].fCallback = 0;
00160 pXdmad->XdmaChannels[j].pArg = 0;
00161 pXdmad->XdmaChannels[j].bIrqOwner = 0;
00162 pXdmad->XdmaChannels[j].bSrcPeriphID = 0;
00163 pXdmad->XdmaChannels[j].bDstPeriphID = 0;
00164 pXdmad->XdmaChannels[j].bSrcTxIfID = 0;
00165 pXdmad->XdmaChannels[j].bSrcRxIfID = 0;
00166 pXdmad->XdmaChannels[j].bDstTxIfID = 0;
00167 pXdmad->XdmaChannels[j].bDstRxIfID = 0;
00168 pXdmad->XdmaChannels[j].state = XDMAD_STATE_FREE;
00169 }
00170
00171 xDmad_Initialized = 1;
00172 ReleaseMutex(pXdmad->xdmaMutex);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 uint32_t XDMAD_AllocateChannel(sXdmad *pXdmad,
00185 uint8_t bSrcID,
00186 uint8_t bDstID)
00187 {
00188 uint32_t dwChannel = XDMAD_ALLOC_FAILED;
00189 uint32_t volatile timer = 0x7FF;
00190
00191 LockMutex(pXdmad->xdmaMutex, timer);
00192 dwChannel = XDMAD_AllocateXdmacChannel(pXdmad, bSrcID, bDstID);
00193 ReleaseMutex(pXdmad->xdmaMutex);
00194
00195 return dwChannel;
00196 }
00197
00198
00199
00200
00201
00202
00203 eXdmadRC XDMAD_FreeChannel(sXdmad *pXdmad,
00204 uint32_t dwChannel)
00205 {
00206 uint8_t iChannel = (dwChannel) & 0xFF;
00207 assert(pXdmad != NULL);
00208
00209 if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
00210
00211 switch (pXdmad->XdmaChannels[iChannel].state) {
00212 case XDMAD_STATE_ALLOCATED:
00213 case XDMAD_STATE_START:
00214 case XDMAD_STATE_IN_XFR:
00215 return XDMAD_BUSY;
00216
00217 case XDMAD_STATE_DONE:
00218 case XDMAD_STATE_HALTED:
00219 pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_FREE;
00220 break;
00221 }
00222
00223 return XDMAD_OK;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 eXdmadRC XDMAD_SetCallback(sXdmad *pXdmad,
00234 uint32_t dwChannel,
00235 XdmadTransferCallback fCallback,
00236 void *pArg)
00237 {
00238
00239 uint8_t iChannel = (dwChannel) & 0xFF;
00240 assert(pXdmad != NULL);
00241
00242 if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
00243
00244 if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
00245 return XDMAD_ERROR;
00246 else if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
00247 return XDMAD_BUSY;
00248
00249 pXdmad->XdmaChannels[iChannel].fCallback = fCallback;
00250 pXdmad->XdmaChannels[iChannel].pArg = pArg;
00251
00252 return XDMAD_OK;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 eXdmadRC XDMAD_PrepareChannel(sXdmad *pXdmad, uint32_t dwChannel)
00264 {
00265
00266 uint8_t iChannel = (dwChannel) & 0xFF;
00267 Xdmac *pXdmac = pXdmad->pXdmacs;
00268
00269 assert(pXdmad != NULL);
00270
00271 if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
00272
00273 if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
00274 return XDMAD_ERROR;
00275 else if ((pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
00276 || (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_IN_XFR))
00277 return XDMAD_BUSY;
00278
00279
00280
00281 if (!PMC_IsPeriphEnabled(ID_XDMAC))
00282 PMC_EnablePeripheral(ID_XDMAC);
00283
00284
00285 XDMAC_GetChannelIsr(pXdmac, iChannel);
00286
00287 XDMAC_DisableGIt (pXdmac, iChannel);
00288 XDMAC_DisableChannelIt (pXdmac, iChannel, 0xFF);
00289
00290 XDMAC_DisableChannel(pXdmac, iChannel);
00291 XDMAC_SetSourceAddr(pXdmac, iChannel, 0);
00292 XDMAC_SetDestinationAddr(pXdmac, iChannel, 0);
00293 XDMAC_SetBlockControl(pXdmac, iChannel, 0);
00294 XDMAC_SetChannelConfig(pXdmac, iChannel, 0x20);
00295 XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);
00296 XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);
00297 return XDMAD_OK;
00298 }
00299
00300
00301
00302
00303
00304 void XDMAD_Handler(sXdmad *pDmad)
00305 {
00306 Xdmac *pXdmac;
00307 sXdmadChannel *pCh;
00308 uint32_t xdmaChannelIntStatus, xdmaGlobaIntStatus, xdmaGlobalChStatus;
00309 uint8_t bExec = 0;
00310 uint8_t _iChannel;
00311 assert(pDmad != NULL);
00312
00313 pXdmac = pDmad->pXdmacs;
00314 xdmaGlobaIntStatus = XDMAC_GetGIsr(pXdmac);
00315
00316 if ((xdmaGlobaIntStatus & 0xFFFFFF) != 0) {
00317 xdmaGlobalChStatus = XDMAC_GetGlobalChStatus(pXdmac);
00318
00319 for (_iChannel = 0; _iChannel < pDmad->numChannels; _iChannel ++) {
00320 if (!(xdmaGlobaIntStatus & (1 << _iChannel))) continue;
00321
00322 pCh = &pDmad->XdmaChannels[_iChannel];
00323
00324 if (pCh->state == XDMAD_STATE_FREE) return;
00325
00326 if ((xdmaGlobalChStatus & (XDMAC_GS_ST0 << _iChannel)) == 0) {
00327 bExec = 0;
00328 xdmaChannelIntStatus = XDMAC_GetMaskChannelIsr(pXdmac, _iChannel);
00329
00330 if (xdmaChannelIntStatus & XDMAC_CIS_BIS) {
00331 if ((XDMAC_GetChannelItMask(pXdmac, _iChannel) & XDMAC_CIM_LIM)
00332 == 0) {
00333 pCh->state = XDMAD_STATE_DONE;
00334 bExec = 1;
00335 }
00336
00337 TRACE_DEBUG("XDMAC_CIS_BIS\n\r");
00338 }
00339
00340 if (xdmaChannelIntStatus & XDMAC_CIS_FIS)
00341 TRACE_DEBUG("XDMAC_CIS_FIS\n\r");
00342
00343 if (xdmaChannelIntStatus & XDMAC_CIS_RBEIS)
00344 TRACE_DEBUG("XDMAC_CIS_RBEIS\n\r");
00345
00346 if (xdmaChannelIntStatus & XDMAC_CIS_WBEIS)
00347 TRACE_DEBUG("XDMAC_CIS_WBEIS\n\r");
00348
00349 if (xdmaChannelIntStatus & XDMAC_CIS_ROIS)
00350 TRACE_DEBUG("XDMAC_CIS_ROIS\n\r");
00351
00352 if (xdmaChannelIntStatus & XDMAC_CIS_LIS) {
00353 TRACE_DEBUG("XDMAC_CIS_LIS\n\r");
00354 pCh->state = XDMAD_STATE_DONE;
00355 bExec = 1;
00356 }
00357
00358 if (xdmaChannelIntStatus & XDMAC_CIS_DIS) {
00359 pCh->state = XDMAD_STATE_DONE;
00360 bExec = 1;
00361 }
00362
00363 } else {
00364
00365 if (XDMAC_GetChannelIsr(pXdmac, _iChannel) & XDMAC_CIS_BIS) {
00366
00367 pCh->fCallback(_iChannel, pCh->pArg);
00368 }
00369 }
00370
00371
00372 if (bExec && pCh->fCallback)
00373 pCh->fCallback(_iChannel, pCh->pArg);
00374 }
00375 }
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 eXdmadRC XDMAD_IsTransferDone(sXdmad *pXdmad, uint32_t dwChannel)
00385 {
00386 uint8_t iChannel = (dwChannel) & 0xFF;
00387 uint8_t state;
00388 assert(pXdmad != NULL);
00389
00390 if (iChannel >= pXdmad->numChannels)
00391 return XDMAD_ERROR;
00392
00393 state = pXdmad->XdmaChannels[iChannel].state;
00394
00395 if (state == XDMAD_STATE_ALLOCATED) return XDMAD_OK;
00396
00397 if (state == XDMAD_STATE_FREE) return XDMAD_ERROR;
00398 else if (state != XDMAD_STATE_DONE) {
00399 if (pXdmad->pollingMode) XDMAD_Handler(pXdmad);
00400
00401 return XDMAD_BUSY;
00402 }
00403
00404 return XDMAD_OK;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413 eXdmadRC XDMAD_ConfigureTransfer(sXdmad *pXdmad,
00414 uint32_t dwChannel,
00415 sXdmadCfg *pXdmaParam,
00416 uint32_t dwXdmaDescCfg,
00417 uint32_t dwXdmaDescAddr,
00418 uint32_t dwXdmaIntEn)
00419 {
00420 uint8_t iChannel = (dwChannel) & 0xFF;
00421
00422 assert(pXdmad != NULL);
00423
00424 if (iChannel >= pXdmad->numChannels)
00425 return XDMAD_ERROR;
00426
00427 Xdmac *pXdmac = pXdmad->pXdmacs;
00428 XDMAC_GetChannelIsr(pXdmac, iChannel);
00429
00430 if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
00431 return XDMAD_ERROR;
00432
00433 if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
00434 return XDMAD_BUSY;
00435
00436
00437 if ((dwXdmaDescCfg & XDMAC_CNDC_NDE) == XDMAC_CNDC_NDE_DSCR_FETCH_EN) {
00438 if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV0) {
00439 XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
00440 XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);
00441 XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);
00442 }
00443
00444 if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV1)
00445 XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
00446
00447 XDMAC_SetDescriptorAddr(pXdmac, iChannel, dwXdmaDescAddr, 0);
00448 XDMAC_SetDescriptorControl(pXdmac, iChannel, dwXdmaDescCfg);
00449 XDMAC_DisableChannelIt (pXdmac, iChannel, 0xFF);
00450 XDMAC_EnableChannelIt (pXdmac, iChannel, dwXdmaIntEn);
00451 } else {
00452
00453 XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);
00454 XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);
00455 XDMAC_SetMicroblockControl(pXdmac, iChannel, pXdmaParam->mbr_ubc);
00456 XDMAC_SetBlockControl(pXdmac, iChannel, pXdmaParam->mbr_bc);
00457 XDMAC_SetDataStride_MemPattern(pXdmac, iChannel, pXdmaParam->mbr_ds);
00458 XDMAC_SetSourceMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_sus);
00459 XDMAC_SetDestinationMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_dus);
00460 XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
00461 XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);
00462 XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);
00463 XDMAC_EnableChannelIt (pXdmac, iChannel, dwXdmaIntEn);
00464 }
00465
00466 return XDMAD_OK;
00467 }
00468
00469
00470
00471
00472
00473
00474 eXdmadRC XDMAD_StartTransfer(sXdmad *pXdmad, uint32_t dwChannel)
00475 {
00476 uint8_t iChannel = (dwChannel) & 0xFF;
00477
00478 assert(pXdmad != NULL);
00479
00480 if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
00481
00482 Xdmac *pXdmac = pXdmad->pXdmacs;
00483
00484 if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE) {
00485 TRACE_ERROR("%s:: XDMAD_STATE_FREE \n\r", __FUNCTION__);
00486 return XDMAD_ERROR;
00487 } else if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START) {
00488 TRACE_ERROR("%s:: XDMAD_STATE_START \n\r", __FUNCTION__)
00489 return XDMAD_BUSY;
00490 }
00491
00492
00493 pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_START;
00494 XDMAC_EnableChannel(pXdmac, iChannel);
00495
00496 if (pXdmad->pollingMode == 0)
00497 XDMAC_EnableGIt(pXdmac, iChannel);
00498
00499 return XDMAD_OK;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 eXdmadRC XDMAD_StopTransfer(sXdmad *pXdmad, uint32_t dwChannel)
00509 {
00510 uint8_t _iChannel = (dwChannel) & 0xFF;
00511 assert(pXdmad != NULL);
00512
00513 if (_iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
00514
00515 Xdmac *pXdmac = pXdmad->pXdmacs;
00516
00517 pXdmad->XdmaChannels[_iChannel].state = XDMAD_STATE_HALTED;
00518
00519 XDMAC_DisableChannel(pXdmac, _iChannel);
00520
00521 XDMAC_DisableChannelIt(pXdmac, _iChannel, 0xFF);
00522
00523 XDMAC_GetChannelIsr(pXdmac, _iChannel);
00524 XDMAC_GetGlobalChStatus(pXdmac);
00525 return XDMAD_OK;
00526 }
00527
00528
00529