static void InitDMA(void) { DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, (uint32_t)&transmitBuf[0]); /* set source address */ DMA_PDD_SetSourceAddressModulo(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_CIRCULAR_BUFFER_DISABLED); /* no circular buffer */ DMA_PDD_EnableSourceAddressIncrement(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* source address will be incremented by transfer size */ DMA_PDD_SetSourceDataTransferSize(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_16_BIT); /* Transfer size from source is 16bit */ DMA_PDD_SetDestinationAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, (uint32_t)&TPM0_C1V); /* set destination address */ DMA_PDD_SetDestinationAddressModulo(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_CIRCULAR_BUFFER_DISABLED); /* no circular buffer */ DMA_PDD_EnableDestinationAddressIncrement(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_DISABLE); /* no auto-increment for destination address */ DMA_PDD_SetDestinationDataTransferSize(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_16_BIT); /* Transfer to destination size is 16bit */ DMA_PDD_SetByteCount(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, NEO_DMA_NOF_BYTES); /* set number of bytes to transfer */ DMA_PDD_EnableTransferCompleteInterrupt(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* request interrupt at the end of the DMA transfer to set new byte count */ DMA_PDD_EnableRequestAutoDisable(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* disable DMA request at the end of the sequence */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* enable request from peripheral */ }
void DMA_Run(void) { for(;;) { //DMA_PDD_SetDestinationAddress(DMA_BASE_PTR, 0, (uint32_t)&TPM0_C1V); /* set destination address */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, 0, (uint32_t)&dmaSrc[0]); /* set source address */ DMA_PDD_SetDestinationAddress(DMA_BASE_PTR, 0, (uint32_t)&dmaDst[0]); /* set destination address */ DMA_PDD_SetByteCount(DMA_BASE_PTR, 0, sizeof(dmaSrc)); DMACH1_EnableRequest(DMACH1_DeviceData); /* enable first transfer */ Cpu_EnableInt(); /* enable interrupts */ for(;;) { //WAIT1_Waitms(200); //DMA1_SetTransactionCount(DMACH1_DeviceData, 3); #if SW_DMA_REQUEST DMA1_SetRequestCount(DMACH1_DeviceData, 1); /* 1: 100->101->102->103->104 3: 100->103->106 */ DMACH1_StartTransfer(DMACH1_DeviceData); #endif //errors = DMACH1_GetError(DMACH1_DeviceData); } } }
static uint8_t Transfer(uint32_t src) { TMOUT1_CounterHandle handle; bool isTimeout; transferComplete = FALSE; DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, src); /* set source address */ DMA_PDD_SetByteCount(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, NEO_DMA_NOF_BYTES); /* set number of bytes to transfer */ DMA_PDD_EnablePeripheralRequest(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* enable request from peripheral */ handle = TMOUT1_GetCounter(100/TMOUT1_TICK_PERIOD_MS); isTimeout = FALSE; while(!transferComplete) { /* wait until transfer is complete */ if (TMOUT1_CounterExpired(handle)) { isTimeout = TRUE; break; /* leave loop */ } } TMOUT1_LeaveCounter(handle); if (isTimeout) { return ERR_BUSY; } return ERR_OK; }
/* DMA Functions */ static void InitDMA(void) { /* enable DMA MUX0: */ DMAMUX_PDD_EnableChannel(DMAMUX0_BASE_PTR, 0, PDD_ENABLE); /* enable DMA MUX0 */ /* PIT triggering for DMA0: */ DMAMUX_PDD_EnableTrigger(DMAMUX0_BASE_PTR, 0, PDD_DISABLE); /* disable PIT Trigger */ /* use TPM0 overflow for DMA0 request: */ DMAMUX_PDD_SetChannelSource(DMAMUX0_BASE_PTR, 0, 25); /* KL25Z reference manual, 3.4.8.1, p64: source number 25 TPM0 CH1 DMA source */ /* DMA channel 0 source configuration: */ DMA_PDD_SetSourceAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, (uint32_t)&GPIOC_PDIR); /* set source address */ DMA_PDD_SetSourceAddressModulo(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_CIRCULAR_BUFFER_DISABLED); /* no circular buffer */ DMA_PDD_EnableSourceAddressIncrement(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_DISABLE); /* source address will be incremented by transfer size */ DMA_PDD_SetSourceDataTransferSize(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_8_BIT); /* Transfer size from source */ /* DMA channel 0 destination configuration: */ DMA_PDD_SetDestinationAddress(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, (uint32_t)&sampleBuffer[0]); /* set destination address */ DMA_PDD_SetDestinationAddressModulo(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_CIRCULAR_BUFFER_DISABLED); /* no circular buffer */ DMA_PDD_EnableDestinationAddressIncrement(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* auto-increment for destination address */ DMA_PDD_SetDestinationDataTransferSize(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, DMA_PDD_8_BIT); /* Transfer to destination size */ /* DMA channel 0 transfer configuration: */ DMA_PDD_EnableTransferCompleteInterrupt(DMA_BASE_PTR, DMA_PDD_CHANNEL_0, PDD_ENABLE); /* request interrupt at the end of the DMA transfer */ (void)DMA_PDD_GetRequestAutoDisableEnabled(DMA_BASE_PTR, DMA_PDD_CHANNEL_0); /* disable DMA request at the end of the sequence */ }
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; }