/* ===================================================================*/ LDD_TDeviceData* DMA1_Init(LDD_TUserData *UserDataPtr) { uint8_t i; DMA1_TDeviceData *DeviceDataPtr; /* LDD device structure */ DMA1_TDescriptorRecord *DescriptorRecordPtr; /* Auxiliary local pointer to internal descriptor records. */ /* Allocate HAL device structure */ /* {Default RTOS Adapter} Driver memory allocation: Dynamic allocation is simulated by a pointer to the static object */ DeviceDataPtr = &DeviceDataPtr__DEFAULT_RTOS_ALLOC; DeviceDataPtr->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */ /* Enable device clock gate */ /* SIM_SCGC7: DMA=1 */ SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; /* SIM_SCGC6: DMAMUX=1 */ SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; /* Transfer compete interrupt vector(s) allocation */ /* {Default RTOS Adapter} Set interrupt vector: IVT is static, ISR parameter is passed by the global variable */ INT_DMA2__DEFAULT_RTOS_ISRPARAM = DeviceDataPtr; /* Transfer compete interrupt vector(s) priority setting */ /* NVIC_IPR0: PRI_2=0x80 */ NVIC_IPR0 = (uint32_t)((NVIC_IPR0 & (uint32_t)~(uint32_t)( NVIC_IP_PRI_2(0x7F) )) | (uint32_t)( NVIC_IP_PRI_2(0x80) )); /* NVIC_ISER: SETENA|=4 */ NVIC_ISER |= NVIC_ISER_SETENA(0x04); for (i = 0U; i < DMA1_DMA_CHANNELS_NUMBER; i++) { DMA_PDD_WriteControlReg(DMA_BASE_PTR, i, 0U); /* Clear control register. Disable all interrupts and HW requests. */ DMA_PDD_ClearInterruptFlags(DMA_BASE_PTR, i, DMA_PDD_TRANSFER_COMPLETE_FLAG); /* Clear request interrupt flags */ } /* Initialization of channels record field. */ memset(DeviceDataPtr->ChannelRecord, 0, DMA1_DMA_CHANNELS_NUMBER * sizeof(DeviceDataPtr->ChannelRecord[0])); //for(i = 0U; i < DMA1_DMA_CHANNELS_NUMBER; i++) { // DeviceDataPtr->ChannelRecord[i] = NULL; /* Clear pointer to descriptor record of all channels. */ //} /* Initialization of channel and descriptor record fields. */ for(i = 0U; i < DMA1_CONFIGURED_CHANNELS_NUMBER; i++) { DescriptorRecordPtr = &(DeviceDataPtr->DescriptorRecord[i]); /* Store local pointer to descriptor record. */ DescriptorRecordPtr->ChannelNumber = DMA1_ChannelNumbers[i]; /* Store associated channel number. */ DescriptorRecordPtr->DescriptorPtr = NULL; /* Set channel as free. */ DescriptorRecordPtr->Interrupts = DMA1_ChannelInterrupts[i]; /* Store associated channel interrupts enabled/disabled status. */ DescriptorRecordPtr->Initialized = FALSE; /* Set channel as not initialized. */ DescriptorRecordPtr->Enabled = FALSE; /* Set channel as disabled. */ DeviceDataPtr->ChannelRecord[DMA1_ChannelNumbers[i]] = DescriptorRecordPtr; /* Store pointers to descriptor records of fixed channels. */ DeviceDataPtr->EventMask[DMA1_ChannelNumbers[i]] = 0U; /* Clear channel event mask. */ } /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_DMA1_ID,DeviceDataPtr); return ((LDD_TDeviceData *)DeviceDataPtr); /* Return pointer to the data structure */ }
/* ===================================================================*/ 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; }