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 #include "chip.h"
00034
00035 #include <assert.h>
00036
00037
00038
00039
00040 #define TWITIMEOUTMAX 400
00041 static uint32_t dmaWriteChannel, dmaReadChannel;
00042
00043 extern uint32_t twi_send_stop;
00044
00045
00046
00047
00048
00049
00050 typedef void (*TwiCallback)(Async *);
00051
00052
00053 typedef struct _AsyncTwi {
00054
00055
00056 volatile uint8_t status;
00057
00058 TwiCallback callback;
00059
00060 uint8_t *pData;
00061
00062 uint32_t num;
00063
00064 uint32_t transferred;
00065
00066 } AsyncTwi;
00067
00068
00069
00070
00071 static void TWID_DmaInitializeRead(TwihsDma *pTwiXdma)
00072 {
00073
00074 dmaReadChannel = XDMAD_AllocateChannel(pTwiXdma->pTwiDma, pTwiXdma->Twi_id,
00075 XDMAD_TRANSFER_MEMORY);
00076
00077 if (dmaReadChannel == XDMAD_ALLOC_FAILED)
00078 printf("-E- Can't allocate XDMA channel\n\r");
00079
00080 XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaReadChannel);
00081 }
00082
00083
00084
00085
00086 static void TWID_DmaInitializeWrite(TwihsDma *pTwiXdma)
00087 {
00088
00089 dmaWriteChannel = XDMAD_AllocateChannel(pTwiXdma->pTwiDma,
00090 XDMAD_TRANSFER_MEMORY,
00091 pTwiXdma->Twi_id);
00092
00093 if (dmaWriteChannel == XDMAD_ALLOC_FAILED)
00094 printf("-E- Can't allocate XDMA channel\n\r");
00095
00096 XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
00097 }
00098
00099
00100
00101
00102 static uint8_t TWID_XdmaConfigureWrite(TwihsDma *pTwiXdma, uint8_t *buf,
00103 uint32_t len)
00104 {
00105 uint32_t xdmaCndc, Thr, xdmaInt;
00106 sXdmadCfg xdmadTxCfg;
00107
00108 Thr = (uint32_t) & (TWIHS0->TWIHS_THR);
00109
00110 if (pTwiXdma->Twi_id == ID_TWIHS1)
00111 Thr = (uint32_t) & (TWIHS1->TWIHS_THR);
00112
00113 if (pTwiXdma->Twi_id == ID_TWIHS2)
00114 Thr = (uint32_t) & (TWIHS2->TWIHS_THR);
00115
00116 xdmadTxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
00117 XDMA_UBC_NDE_FETCH_DIS |
00118 XDMA_UBC_NSEN_UPDATED | len;
00119
00120 xdmadTxCfg.mbr_sa = (uint32_t)buf;
00121 xdmadTxCfg.mbr_da = Thr;
00122 xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00123 XDMAC_CC_MBSIZE_SINGLE |
00124 XDMAC_CC_DSYNC_MEM2PER |
00125 XDMAC_CC_CSIZE_CHK_1 |
00126 XDMAC_CC_DWIDTH_BYTE |
00127 XDMAC_CC_SIF_AHB_IF1 |
00128 XDMAC_CC_DIF_AHB_IF1 |
00129 XDMAC_CC_SAM_INCREMENTED_AM |
00130 XDMAC_CC_DAM_FIXED_AM |
00131 XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
00132 pTwiXdma->Twi_id, XDMAD_TRANSFER_TX));
00133
00134 xdmadTxCfg.mbr_bc = 0;
00135 xdmadTxCfg.mbr_sus = 0;
00136 xdmadTxCfg.mbr_dus = 0;
00137 xdmaCndc = 0;
00138
00139 xdmaInt = (XDMAC_CIE_BIE |
00140 XDMAC_CIE_RBIE |
00141 XDMAC_CIE_WBIE);
00142
00143 if (XDMAD_ConfigureTransfer(pTwiXdma->pTwiDma, dmaWriteChannel,
00144 &xdmadTxCfg, xdmaCndc, 0, xdmaInt))
00145 return USARTD_ERROR;
00146
00147 return 0;
00148 }
00149
00150
00151
00152
00153
00154 static uint8_t TWID_XdmaConfigureRead(TwihsDma *pTwiXdma, uint8_t *buf,
00155 uint32_t len)
00156 {
00157 uint32_t xdmaCndc, Rhr, xdmaInt;
00158 sXdmadCfg xdmadRxCfg;
00159
00160 Rhr = (uint32_t) & (TWIHS0->TWIHS_RHR);
00161
00162 if (pTwiXdma->Twi_id == ID_TWIHS1)
00163 Rhr = (uint32_t) & (TWIHS1->TWIHS_RHR);
00164
00165 if (pTwiXdma->Twi_id == ID_TWIHS2)
00166 Rhr = (uint32_t) & (TWIHS2->TWIHS_RHR);
00167
00168 xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
00169 XDMA_UBC_NDE_FETCH_DIS |
00170 XDMA_UBC_NDEN_UPDATED |
00171 len;
00172
00173 xdmadRxCfg.mbr_da = (uint32_t)buf;
00174 xdmadRxCfg.mbr_sa = Rhr;
00175
00176 xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00177 XDMAC_CC_MBSIZE_SINGLE |
00178 XDMAC_CC_DSYNC_PER2MEM |
00179 XDMAC_CC_CSIZE_CHK_1 |
00180 XDMAC_CC_DWIDTH_BYTE |
00181 XDMAC_CC_SIF_AHB_IF1 |
00182 XDMAC_CC_DIF_AHB_IF1 |
00183 XDMAC_CC_SAM_FIXED_AM |
00184 XDMAC_CC_DAM_INCREMENTED_AM |
00185 XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
00186 pTwiXdma->Twi_id , XDMAD_TRANSFER_RX));
00187
00188 xdmadRxCfg.mbr_bc = 0;
00189 xdmadRxCfg.mbr_sus = 0;
00190 xdmadRxCfg.mbr_dus = 0;
00191 xdmaCndc = 0;
00192 xdmaInt = (XDMAC_CIE_BIE |
00193 XDMAC_CIE_RBIE |
00194 XDMAC_CIE_WBIE);
00195
00196 if (XDMAD_ConfigureTransfer(pTwiXdma->pTwiDma, dmaReadChannel,
00197 &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
00198 return 1;
00199
00200 return 0;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 uint32_t ASYNC_IsFinished(Async *pAsync)
00212 {
00213 return (pAsync->status != ASYNC_STATUS_PENDING);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223 void TWID_Initialize(Twid *pTwid, Twihs *pTwi)
00224 {
00225 TRACE_DEBUG("TWID_Initialize()\n\r");
00226 assert(pTwid != NULL);
00227 assert(pTwi != NULL);
00228
00229
00230 pTwid->pTwi = pTwi;
00231 pTwid->pTransfer = 0;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 void TWID_Handler(Twid *pTwid)
00241 {
00242 uint8_t status;
00243 AsyncTwi *pTransfer;
00244 Twihs *pTwi;
00245
00246 assert(pTwid != NULL);
00247
00248 pTransfer = (AsyncTwi *)pTwid->pTransfer;
00249 assert(pTransfer != NULL);
00250 pTwi = pTwid->pTwi;
00251 assert(pTwi != NULL);
00252
00253
00254 status = TWI_GetMaskedStatus(pTwi);
00255
00256
00257 if (TWI_STATUS_RXRDY(status)) {
00258
00259 pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
00260 pTransfer->transferred++;
00261
00262
00263 if (pTransfer->transferred == pTransfer->num) {
00264
00265 TWI_DisableIt(pTwi, TWIHS_IDR_RXRDY);
00266 TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
00267 }
00268
00269 else if (pTransfer->transferred == (pTransfer->num - 1))
00270
00271 TWI_Stop(pTwi);
00272 }
00273
00274 else if (TWI_STATUS_TXRDY(status)) {
00275
00276
00277 if (pTransfer->transferred == pTransfer->num) {
00278
00279 TWI_DisableIt(pTwi, TWIHS_IDR_TXRDY);
00280 TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
00281 TWI_SendSTOPCondition(pTwi);
00282 }
00283
00284 else {
00285
00286 TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
00287 pTransfer->transferred++;
00288 }
00289 }
00290
00291 else if (TWI_STATUS_TXCOMP(status)) {
00292
00293 TWI_DisableIt(pTwi, TWIHS_IDR_TXCOMP);
00294 pTransfer->status = 0;
00295
00296 if (pTransfer->callback)
00297 pTransfer->callback((Async *) pTransfer);
00298
00299 pTwid->pTransfer = 0;
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 uint8_t TWID_Read(
00316 Twid *pTwid,
00317 uint8_t address,
00318 uint32_t iaddress,
00319 uint8_t isize,
00320 uint8_t *pData,
00321 uint32_t num,
00322 Async *pAsync)
00323 {
00324 Twihs *pTwi;
00325 AsyncTwi *pTransfer;
00326 uint32_t startTime;
00327 assert(pTwid != NULL);
00328 pTwi = pTwid->pTwi;
00329 pTransfer = (AsyncTwi *) pTwid->pTransfer;
00330
00331 assert((address & 0x80) == 0);
00332 assert((iaddress & 0xFF000000) == 0);
00333 assert(isize < 4);
00334
00335
00336 if (pTransfer) {
00337
00338 TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
00339 return TWID_ERROR_BUSY;
00340 }
00341
00342
00343 twi_send_stop = (num == 1) ? 1 : 0;
00344
00345
00346 if (pAsync) {
00347
00348
00349 pTwid->pTransfer = pAsync;
00350 pTransfer = (AsyncTwi *) pAsync;
00351 pTransfer->status = ASYNC_STATUS_PENDING;
00352 pTransfer->pData = pData;
00353 pTransfer->num = num;
00354 pTransfer->transferred = 0;
00355
00356
00357 TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
00358 TWI_StartRead(pTwi, address, iaddress, isize);
00359 }
00360
00361 else {
00362
00363
00364 TWI_StartRead(pTwi, address, iaddress, isize);
00365
00366
00367 while (num > 0) {
00368
00369
00370 if (num == 1)
00371 TWI_Stop(pTwi);
00372
00373
00374 startTime = GetTicks();
00375
00376 while (!TWI_ByteReceived(pTwi)) {
00377 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00378 TRACE_ERROR("TWID Timeout BR\n\r");
00379 break;
00380 }
00381 }
00382
00383 *pData++ = TWI_ReadByte(pTwi);
00384 num--;
00385 }
00386
00387
00388 startTime = GetTicks();
00389
00390 while (!TWI_TransferComplete(pTwi)) {
00391 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00392 TRACE_ERROR("TWID Timeout TC\n\r");
00393 break;
00394 }
00395 }
00396 }
00397
00398 return 0;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 uint8_t TWID_Write(
00414 Twid *pTwid,
00415 uint8_t address,
00416 uint32_t iaddress,
00417 uint8_t isize,
00418 uint8_t *pData,
00419 uint32_t num,
00420 Async *pAsync)
00421 {
00422 Twihs *pTwi = pTwid->pTwi;
00423 uint32_t startTime;
00424 AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
00425
00426 assert(pTwi != NULL);
00427 assert((address & 0x80) == 0);
00428 assert((iaddress & 0xFF000000) == 0);
00429 assert(isize < 4);
00430
00431
00432 if (pTransfer) {
00433 TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
00434 return TWID_ERROR_BUSY;
00435 }
00436
00437
00438 if (pAsync) {
00439
00440 pTwid->pTransfer = pAsync;
00441 pTransfer = (AsyncTwi *) pAsync;
00442 pTransfer->status = ASYNC_STATUS_PENDING;
00443 pTransfer->pData = pData;
00444 pTransfer->num = num;
00445 pTransfer->transferred = 1;
00446
00447
00448 TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
00449 TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
00450
00451 } else {
00452
00453
00454 TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
00455 num--;
00456
00457
00458 while (num > 0) {
00459
00460 startTime = GetTicks();
00461
00462 while (!TWI_ByteSent(pTwi)) {
00463 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00464 TRACE_ERROR("TWID Timeout BS\n\r");
00465 break;
00466 }
00467 }
00468
00469 TWI_WriteByte(pTwi, *pData++);
00470 num--;
00471 }
00472
00473
00474 startTime = GetTicks();
00475
00476 TWI_SendSTOPCondition(pTwi);
00477
00478 while (!TWI_TransferComplete(pTwi)) {
00479 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00480 TRACE_ERROR("TWID Timeout TC2\n\r");
00481 break;
00482 }
00483 }
00484 }
00485
00486 return 0;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496 void TWID_DmaInitialize(TwihsDma *pTwidma, Twihs *pTwi, uint8_t bPolling)
00497 {
00498 TRACE_DEBUG("TWID_Initialize()\n\r");
00499 assert(pTwidma != NULL);
00500
00501 if ((unsigned int)pTwi == (unsigned int)TWIHS0) pTwidma->Twi_id = ID_TWIHS0;
00502
00503 if ((unsigned int)pTwi == (unsigned int)TWIHS1) pTwidma->Twi_id = ID_TWIHS1;
00504
00505 if ((unsigned int)pTwi == (unsigned int)TWIHS2) pTwidma->Twi_id = ID_TWIHS2;
00506
00507
00508 pTwidma->pTwid->pTwi = pTwi;
00509 pTwidma->pTwid->pTransfer = 0;
00510
00511 if (!bPolling) {
00512
00513
00514 NVIC_ClearPendingIRQ(XDMAC_IRQn);
00515 NVIC_SetPriority(XDMAC_IRQn, 1);
00516 NVIC_EnableIRQ(XDMAC_IRQn);
00517 }
00518
00519
00520 XDMAD_Initialize(pTwidma->pTwiDma, bPolling);
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 uint8_t TWID_DmaRead(
00537 TwihsDma *pTwiXdma,
00538 uint8_t address,
00539 uint32_t iaddress,
00540 uint8_t isize,
00541 uint8_t *pData,
00542 uint32_t num,
00543 Async *pAsync)
00544 {
00545 Twihs *pTwi;
00546 AsyncTwi *pTransfer;
00547 uint32_t status, startTime;
00548
00549 assert(pTwiXdma->pTwid != NULL);
00550 pTwi = pTwiXdma->pTwid->pTwi;
00551 pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
00552
00553 assert((address & 0x80) == 0);
00554 assert((iaddress & 0xFF000000) == 0);
00555 assert(isize < 4);
00556
00557
00558 if (pTransfer) {
00559
00560 TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
00561 return TWID_ERROR_BUSY;
00562 }
00563
00564
00565 if (pAsync) {
00566
00567 pTwiXdma->pTwid->pTransfer = pAsync;
00568 pTransfer = (AsyncTwi *) pAsync;
00569 pTransfer->status = ASYNC_STATUS_PENDING;
00570 pTransfer->pData = pData;
00571 pTransfer->num = num;
00572 pTransfer->transferred = 0;
00573
00574
00575 TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
00576 TWI_StartRead(pTwi, address, iaddress, isize);
00577 } else {
00578
00579 TWID_DmaInitializeRead(pTwiXdma);
00580 TWID_XdmaConfigureRead(pTwiXdma, pData, (num - 2));
00581
00582
00583 XDMAD_StartTransfer(pTwiXdma->pTwiDma, dmaReadChannel);
00584 TWI_StartRead(pTwi, address, iaddress, isize);
00585
00586 startTime = GetTicks();
00587 status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel);
00588
00589 while (status != XDMAD_OK) {
00590 status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel);
00591
00592 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00593 TRACE_ERROR("TWID DMA not done\n\r");
00594 break;
00595 }
00596 }
00597
00598 if (XDMAD_OK == status)
00599 SCB_InvalidateDCache_by_Addr((uint32_t *)pData, (num - 2));
00600
00601 status = TWI_GetStatus(pTwi);
00602 startTime = GetTicks();
00603
00604 while (!(status & TWIHS_SR_RXRDY)) {
00605 status = TWI_GetStatus(pTwi);
00606
00607 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00608 TRACE_ERROR("TWID DMA not done\n\r");
00609 break;
00610 }
00611 }
00612
00613 TWI_Stop(pTwi);
00614
00615 pData[num - 2] = TWI_ReadByte(pTwi);
00616 status = TWI_GetStatus(pTwi);
00617 startTime = GetTicks();
00618
00619 while (!(status & TWIHS_SR_RXRDY)) {
00620 status = TWI_GetStatus(pTwi);
00621
00622 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00623 TRACE_ERROR("TWID Timeout Read\n\r");
00624 break;
00625 }
00626 }
00627
00628 pData[num - 1] = TWI_ReadByte(pTwi);
00629 status = TWI_GetStatus(pTwi);
00630 startTime = GetTicks();
00631
00632 while (!(status & TWIHS_SR_TXCOMP)) {
00633 status = TWI_GetStatus(pTwi);
00634
00635 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00636 TRACE_ERROR("TWID Timeout Read\n\r");
00637 break;
00638 }
00639 }
00640
00641 XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaReadChannel);
00642 XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
00643 }
00644
00645 return 0;
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 uint8_t TWID_DmaWrite(
00662 TwihsDma *pTwiXdma,
00663 uint8_t address,
00664 uint32_t iaddress,
00665 uint8_t isize,
00666 uint8_t *pData,
00667 uint32_t num,
00668 Async *pAsync)
00669 {
00670 Twihs *pTwi = pTwiXdma->pTwid->pTwi;
00671 AsyncTwi *pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
00672 uint32_t status, startTime;
00673
00674 assert(pTwi != NULL);
00675 assert((address & 0x80) == 0);
00676 assert((iaddress & 0xFF000000) == 0);
00677 assert(isize < 4);
00678
00679
00680
00681 if (pTransfer) {
00682
00683 TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
00684 return TWID_ERROR_BUSY;
00685 }
00686
00687
00688 if (pAsync) {
00689
00690
00691 pTwiXdma->pTwid->pTransfer = pAsync;
00692 pTransfer = (AsyncTwi *) pAsync;
00693 pTransfer->status = ASYNC_STATUS_PENDING;
00694 pTransfer->pData = pData;
00695 pTransfer->num = num;
00696 pTransfer->transferred = 1;
00697
00698
00699 TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
00700 TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
00701 } else {
00702
00703 TWID_DmaInitializeWrite(pTwiXdma);
00704 TWID_XdmaConfigureWrite(pTwiXdma, pData, (num - 1));
00705
00706 pTwi->TWIHS_MMR = 0;
00707 pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
00708
00709
00710 pTwi->TWIHS_IADR = 0;
00711 pTwi->TWIHS_IADR = iaddress;
00712
00713
00714 SCB_CleanDCache_by_Addr((uint32_t *)pData, (num - 1));
00715 startTime = GetTicks();
00716
00717 XDMAD_StartTransfer(pTwiXdma->pTwiDma, dmaWriteChannel);
00718
00719 while ((XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaWriteChannel))) {
00720 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00721 TRACE_ERROR("TWID DMA not done, Channel State is %d\n\r",
00722 pTwiXdma->pTwiDma->XdmaChannels[dmaWriteChannel].state);
00723 break;
00724 }
00725 }
00726
00727 status = TWI_GetStatus(pTwi);
00728 startTime = GetTicks();
00729
00730 while (!(status & TWIHS_SR_TXRDY)) {
00731 status = TWI_GetStatus(pTwi);
00732
00733 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00734 TRACE_ERROR("TWID Timeout TXRDY\n\r");
00735 break;
00736 }
00737 }
00738
00739
00740 TWI_Stop(pTwi);
00741
00742 TWI_WriteByte(pTwi, pData[num - 1]);
00743 status = TWI_GetStatus(pTwi);
00744 startTime = GetTicks();
00745
00746 while (!(status & TWIHS_SR_TXCOMP)) {
00747 status = TWI_GetStatus(pTwi);
00748
00749 if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
00750 TRACE_ERROR("TWID Timeout Write\n\r");
00751 break;
00752 }
00753 }
00754
00755 XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaWriteChannel);
00756 XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
00757
00758 }
00759
00760 return 0;
00761 }