/*
** ===================================================================
**     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 {
  }
}
Exemple #3
0
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;
}