/* ** =================================================================== ** Method : _CancelTransfer (component DMAController) ** ** Description : ** CancelTransfer ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void CancelTransfer(DMA1_TChnDevConst const *ChnDevConstPtr) { uint8_t PhyChnNum = ChnDevConstPtr->PhyChnNum; /* Disable new request from peripheral in DMA MUX */ DMAMUX_PDD_EnableChannel(DMAMUX_BASE_PTR, PhyChnNum, PDD_DISABLE); DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum, PDD_DISABLE); /* Disable new request from peripheral. */ if (DMA_PDD_GetActiveFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum)) { /* Channel active? */ DMA_PDD_HaltOperations(DMA_BASE_PTR); /* Yes, stall start of any new channels */ DMA_PDD_CancelTransfer(DMA_BASE_PTR); /* Cancel current transfer */ DMA_PDD_ResumeOperations(DMA_BASE_PTR); /* Resume DMA operation */ } DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); DMA_PDD_ClearChannelInterruptFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); DMA_PDD_ClearChannelErrorFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); /* Enable new request from peripheral in DMA MUX */ DMAMUX_PDD_EnableChannel(DMAMUX_BASE_PTR, PhyChnNum, PDD_ENABLE); }
/* ** =================================================================== ** Method : HandleInterrupt (component DMAController) ** ** Description : ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void HandleInterrupt(DMA1_TChnDevData *ChnDevDataPtr) { DMA1_TChnDevConst const *ChnDevConstPtr = ChnDevDataPtr->ChnDevConstPtr; uint8_t PhyChnNum = ChnDevConstPtr->PhyChnNum; uint32_t ErrorStatus; if (DMA_PDD_GetChannelErrorFlag(DMA_BASE_PTR, PhyChnNum)) { /* Channel error detected */ /* Transfer error */ ErrorStatus = DMA_PDD_GetErrorStatusFlags(DMA_BASE_PTR); /* Get error flags */ if (ErrorStatus != 0U) { /* Any error flag set? */ if (DMA_PDD_GetErrorStatusChannel(DMA_BASE_PTR) == ChnDevConstPtr->PhyChnNum) { /* Channel error flags valid? */ /* Remember all (device and channel) error flags */ ChnDevDataPtr->ErrorFlags |= ErrorStatus; } else { /* Remember device error flags only (if any flag set) */ ChnDevDataPtr->ErrorFlags |= (ErrorStatus & DMA_PDD_DEVICE_ERROR_FLAGS); /* Remember channel error flags are not valid */ ChnDevDataPtr->ErrorFlags |= LDD_DMA_UNKNOWN_ERROR; } } else { /* Error flags not valid */ ChnDevDataPtr->ErrorFlags |= LDD_DMA_UNKNOWN_ERROR; } DMAMUX_PDD_EnableChannel(DMAMUX_BASE_PTR, ChnDevConstPtr->PhyChnNum, PDD_DISABLE); DMA_PDD_ClearChannelErrorFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); if (ChnDevDataPtr->Events.OnErrorFnPtr != NULL) { ChnDevDataPtr->Events.OnErrorFnPtr(ChnDevDataPtr->UserDataPtr); } } else if (DMA_PDD_GetDoneFlag(DMA_BASE_PTR, PhyChnNum)) { /* Transfer done without error */ DMA_PDD_ClearChannelInterruptFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, ChnDevConstPtr->PhyChnNum); if (ChnDevDataPtr->Events.OnCompleteFnPtr != NULL) { ChnDevDataPtr->Events.OnCompleteFnPtr(ChnDevDataPtr->UserDataPtr); } } else { } }
static uint8_t Transfer(uint32_t dataAddress, size_t nofBytes) { static const uint8_t OneValue = 0xFF; /* value to clear or set the port bits */ TMOUT1_CounterHandle handle; bool isTimeout; uint32_t done0, done1, done2; /* clear any pending done flags for DMA channels */ DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_0); DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_1); DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_2); /* set DMA source addresses */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, (uint32_t)&OneValue); /* set source address */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_1, dataAddress); /* set source address */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_2, (uint32_t)&OneValue); /* set source address */ /* set byte count addresses */ DMA_PDD_SetByteCount(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, nofBytes); /* set number of bytes to transfer */ DMA_PDD_SetByteCount(DMA_BASE_PTR, DMA_PDD_CHANNEL_1, nofBytes); /* set number of bytes to transfer */ DMA_PDD_SetByteCount(DMA_BASE_PTR, DMA_PDD_CHANNEL_2, nofBytes); /* set number of bytes to transfer */ /* reset TPM counter */ TPM_PDD_InitializeCounter(TPM0_DEVICE); /* reset timer counter */ TPM_PDD_ClearChannelFlags(TPM0_DEVICE, 0x00); TPM_PDD_ClearOverflowInterruptFlag(TPM0_DEVICE); /* re-enable DMA Muxing: it will disabled at the end of the transfer */ DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 0, PDD_ENABLE); DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 1, PDD_ENABLE); DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 2, PDD_ENABLE); /* enable DMA peripheral requests */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, DMA_PDD_CHANNEL_2, PDD_ENABLE); /* enable request from peripheral */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, DMA_PDD_CHANNEL_1, PDD_ENABLE); /* enable request from peripheral */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* enable request from peripheral */ /* clear timer flags and status so it starts from a clean starting point */ TPM_PDD_ClearChannelFlags(TPM0_DEVICE, 0x00); TPM_PDD_ClearOverflowInterruptFlag(TPM0_DEVICE); /* enable TPM DMA */ TPM_PDD_WriteStatusControlReg(TPM0_DEVICE,TPM_PDD_ReadStatusControlReg(TPM0_DEVICE)|TPM_SC_DMA_MASK); TPM_PDD_EnableChannelDma(TPM0_DEVICE, 1); TPM_PDD_EnableChannelDma(TPM0_DEVICE, 0); /* start the TPM timer */ StartTimer(); isTimeout = FALSE; handle = TMOUT1_GetCounter(100/TMOUT1_TICK_PERIOD_MS); for(;;) { /* wait until transfer is complete */ if (TMOUT1_CounterExpired(handle)) { isTimeout = TRUE; break; /* leave loop */ } done0 = DMA_PDD_GetDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_0); done1 = DMA_PDD_GetDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_1); done2 = DMA_PDD_GetDoneFlag(DMA_BASE_PTR, DMA_PDD_CHANNEL_2); if (done0 && done1 && done2) { break; /* done! */ } WAIT1_WaitOSms(1); /* give back some time */ } TMOUT1_LeaveCounter(handle); WAIT1_Waitus(50); /* latch, low for at least 50 us (40x1.25us) */ /* disable DMA-Muxing: necessary, otherwise DMA events on TPM0 channel 0 might be still latched. * Will enable muxing for next transfer */ DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 0, PDD_DISABLE); DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 1, PDD_DISABLE); DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 2, PDD_DISABLE); /* disable peripheral DMA */ TPM_PDD_WriteStatusControlReg(TPM0_DEVICE,TPM_PDD_ReadStatusControlReg(TPM0_DEVICE)&(~TPM_SC_DMA_MASK)); TPM_PDD_DisableChannelDma(TPM0_DEVICE, 1); TPM_PDD_DisableChannelDma(TPM0_DEVICE, 0); StopTimer(); /* stop TPM */ if (isTimeout) { return ERR_BUSY; } return ERR_OK; }
/* ===================================================================*/ LDD_TError DMA1_EnableChannel(LDD_TDeviceData *DeviceDataPtr, LDD_DMA_TTransferDescriptor *DescriptorPtr) { LDD_DMA_TChannelNumber ChannelNumber; DMA1_TDescriptorRecord *DescriptorRecordPtr; /* Check channel allocation for the transfer descriptor and eventually store pointer to associated descriptor record. */ if (!GetRecord(DeviceDataPtr, DescriptorPtr, &DescriptorRecordPtr)) { return ERR_NOTAVAIL; /* No channel allocated for the transfer. */ } /* Transfer descriptor consistency test - this test can be disabled by setting the "Ignore range checking" property to the "yes" value in the "Configuration inspector" */ if (!VerifyDescriptor(DescriptorPtr)) { return ERR_PARAM_DATA; } ChannelNumber = DescriptorRecordPtr->ChannelNumber; /* Save local auxiliary channel number. */ if (!DescriptorRecordPtr->Initialized) { /* Is channel already initialized? */ /* If channel is not initialized yet, initialize and enable it */ DMA_PDD_WriteControlReg(DMA_BASE_PTR, ChannelNumber, 0U); /* Clear control register. Disable requests. */ DMA_PDD_ClearDoneFlag(DMA_BASE_PTR, ChannelNumber); /* Clear DMA transfer done status flag. */ /* Source address */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->SourceAddress); /* Source address increment */ if (DescriptorPtr->SourceAddressIncrement) { DMA_PDD_EnableSourceAddressIncrement(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); } /* Destination address */ DMA_PDD_SetDestinationAddress(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->DestinationAddress); /* Destination address increment */ if (DescriptorPtr->DestinationAddressIncrement) { DMA_PDD_EnableDestinationAddressIncrement(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); } /* Transfer attributes: source transfer size, destination transfer size, source modulo, destination modulo */ DMA_PDD_SetSourceAddressModulo(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->SourceModuloSize); DMA_PDD_SetSourceDataTransferSize(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->SourceTransferSize); DMA_PDD_SetDestinationAddressModulo(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->DestinationModuloSize); DMA_PDD_SetDestinationDataTransferSize(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->DestinationTransferSize); /* Transfer mode */ if (DescriptorPtr->TransferMode == LDD_DMA_CYCLE_STEAL_TRANSFERS) { DMA_PDD_EnableCycleSteal(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); /* Enable cycle-steal mode. */ } /* Byte count */ DMA_PDD_SetByteCount(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->ByteCount); /* Auto-align mode settings. */ if (DescriptorPtr->AutoAlign) { DMA_PDD_EnableAutoAlign(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); } /* Asynchronous requests settings. */ if (DescriptorPtr->AsynchronousRequests) { DMA_PDD_EnableAsynchronousRequests(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); } /* Channel linking settings. */ switch (DescriptorPtr->ChannelLinkingMode) { case LDD_DMA_LINKING_DISABLED: /* Initialization not needed. */ break; case LDD_DMA_CYCLE_STEAL_AND_TRANSFER_COMPLETE_LINKING: DMA_PDD_SetChannelLinkingMode(DMA_BASE_PTR, ChannelNumber, DMA_PDD_CYCLE_STEAL_AND_TRANSFER_COMPLETE_LINKING); /* Set channel linking mode. */ DMA_PDD_SetLinkChannel1(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->InnerLoopLinkedChannel); /* Set channel linked after each particular read-write operation. */ DMA_PDD_SetLinkChannel2(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->OuterLoopLinkedChannel); /* Set channel linked after transfer byte count reaches zero. */ break; case LDD_DMA_CYCLE_STEAL_LINKING: DMA_PDD_SetChannelLinkingMode(DMA_BASE_PTR, ChannelNumber, DMA_PDD_CYCLE_STEAL_LINKING); /* Set channel linking mode. */ DMA_PDD_SetLinkChannel1(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->InnerLoopLinkedChannel); /* Set channel linked after each particular read-write operation. */ break; case LDD_DMA_TRANSFER_COMPLETE_LINKING: DMA_PDD_SetChannelLinkingMode(DMA_BASE_PTR, ChannelNumber, DMA_PDD_TRANSFER_COMPLETE_LINKING); /* Set channel linking mode. */ DMA_PDD_SetLinkChannel1(DMA_BASE_PTR, ChannelNumber, DescriptorPtr->OuterLoopLinkedChannel); /* Set channel linked after transfer byte count reaches zero. */ break; } if (DescriptorPtr->DisableAfterRequest) { /* Disable after request? */ DMA_PDD_EnableRequestAutoDisable(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); } /* {Default RTOS Adapter} Critical section begin, general PE function is used */ EnterCritical(); DescriptorRecordPtr->Initialized = TRUE; /* Mark channel as initialized. */ DescriptorRecordPtr->Enabled = TRUE; /* Mark channel as enabled. */ DescriptorPtr->ChannelEnabled = TRUE; /* Mark channel as enabled in transfer descriptor. */ if (DescriptorPtr->Interrupts) { /* Interrupts enabled? */ DMA_PDD_EnableTransferCompleteInterrupt(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); if (DescriptorPtr->OnComplete) { /* Is transfer complete event enabled? */ ((DMA1_TDeviceData *)DeviceDataPtr)->EventMask[ChannelNumber] |= LDD_DMA_ON_COMPLETE; } if (DescriptorPtr->OnError) { /* Is transfer error event enabled? */ ((DMA1_TDeviceData *)DeviceDataPtr)->EventMask[ChannelNumber] |= LDD_DMA_ON_ERROR; } } /* DMA channel HW requests source settings */ DMAMUX_PDD_WriteChannelConfigurationReg(DMAMUX0_BASE_PTR, ChannelNumber, 0U); /* Clear DMA MUX channel source register. */ if (DescriptorPtr->TriggerType != LDD_DMA_SW_TRIGGER) { /* SW trigger doesn't need MUX channel nor enabled hardware requests. */ DMAMUX_PDD_SetChannelSource(DMAMUX0_BASE_PTR, ChannelNumber, DescriptorPtr->TriggerSource); /* Set MUX channel source. */ if (DescriptorPtr->PeriodicTrigger) { /* Periodic trigger needed? */ DMAMUX_PDD_EnableTrigger(DMAMUX0_BASE_PTR, ChannelNumber, PDD_ENABLE); } DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, ChannelNumber, PDD_ENABLE); /* Enable channel. */ } DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); /* Enable HW requests. */ /* {Default RTOS Adapter} Critical section end, general PE function is used */ ExitCritical(); } else { /* If channel has already been initialized then enable it only */ /* {Default RTOS Adapter} Critical section begin, general PE function is used */ EnterCritical(); DescriptorRecordPtr->Enabled = TRUE; /* Mark channel as enabled. */ DescriptorPtr->ChannelEnabled = TRUE; /* Mark channel as enabled in transfer descriptor. */ if (DescriptorPtr->TriggerType != LDD_DMA_SW_TRIGGER) { /* SW trigger doesn't need enabled hardware requests. */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, ChannelNumber, PDD_ENABLE); /* Enable HW requests */ } /* {Default RTOS Adapter} Critical section end, general PE function is used */ ExitCritical(); } return ERR_OK; }