/**
 * @brief   Allocates a DMA stream.
 * @details The stream is allocated and, if required, the DMA clock enabled.
 *          The function also enables the IRQ vector associated to the stream
 *          and initializes its priority.
 * @pre     The stream must not be already in use or an error is returned.
 * @post    The stream is allocated and the default ISR handler redirected
 *          to the specified function.
 * @post    The stream ISR vector is enabled and its priority configured.
 * @post    The stream must be freed using @p dmaStreamRelease() before it can
 *          be reused with another peripheral.
 * @post    The stream is in its post-reset state.
 * @note    This function can be invoked in both ISR or thread context.
 *
 * @param[in] dmastp    pointer to a stm32_dma_stream_t structure
 * @param[in] priority  IRQ priority mask for the DMA stream
 * @param[in] func      handling function pointer, can be @p NULL
 * @param[in] param     a parameter to be passed to the handling function
 * @return              The operation status.
 * @retval FALSE        no error, stream taken.
 * @retval TRUE         error, stream already taken.
 *
 * @special
 */
bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
                         uint32_t priority,
                         stm32_dmaisr_t func,
                         void *param) {

  chDbgCheck(dmastp != NULL, "dmaAllocate");

  /* Checks if the stream is already taken.*/
  if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0)
    return TRUE;

  /* Marks the stream as allocated.*/
  dma_isr_redir[dmastp->selfindex].dma_func  = func;
  dma_isr_redir[dmastp->selfindex].dma_param = param;
  dma_streams_mask |= (1 << dmastp->selfindex);

  /* Enabling DMA clocks required by the current streams set.*/
  if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0)
    rccEnableDMA1(FALSE);
#if STM32_HAS_DMA2
  if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0)
    rccEnableDMA2(FALSE);
#endif

  /* Putting the stream in a safe state.*/
  dmaStreamDisable(dmastp);
  dmaStreamClearInterrupt(dmastp);
  dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;

  /* Enables the associated IRQ vector if a callback is defined.*/
  if (func != NULL)
    NVICEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority));

  return FALSE;
}
Exemplo n.º 2
0
/**
 * @brief   Wait end of data transaction and performs finalizations.
 *
 * @param[in] sdcp      pointer to the @p SDCDriver object
 * @param[in] n         number of blocks in transaction
 * @param[in] resp      pointer to the response buffer
 *
 * @return              The operation status.
 * @retval HAL_SUCCESS  operation succeeded.
 * @retval HAL_FAILED   operation failed.
 */
static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
                                         uint32_t *resp) {

  /* Note the mask is checked before going to sleep because the interrupt
     may have occurred before reaching the critical zone.*/
  osalSysLock();
  if (sdcp->sdmmc->MASK != 0)
    osalThreadSuspendS(&sdcp->thread);
  if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) {
    osalSysUnlock();
    return HAL_FAILED;
  }

  /* Wait until DMA channel enabled to be sure that all data transferred.*/
  while (sdcp->dma->stream->CR & STM32_DMA_CR_EN)
    ;

  /* DMA event flags must be manually cleared.*/
  dmaStreamClearInterrupt(sdcp->dma);

  sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
  sdcp->sdmmc->DCTRL = 0;
  osalSysUnlock();

  /* Finalize transaction.*/
  if (n > 1)
    return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);

  return HAL_SUCCESS;
}
Exemplo n.º 3
0
Arquivo: sdc_lld.c Projeto: Kreyl/nute
/**
 * @brief   Performs clean transaction stopping in case of errors.
 *
 * @param[in] sdcp      pointer to the @p SDCDriver object
 * @param[in] n         number of blocks in transaction
 * @param[in] resp      pointer to the response buffer
 *
 * @notapi
 */
static void sdc_lld_error_cleanup(SDCDriver *sdcp,
                                  uint32_t n,
                                  uint32_t *resp) {

  dmaStreamClearInterrupt(sdcp->dma);
  dmaStreamDisable(sdcp->dma);
  SDIO->ICR   = STM32_SDIO_ICR_ALL_FLAGS;
  SDIO->MASK  = 0;
  SDIO->DCTRL = 0;
  sdc_lld_collect_errors(sdcp);
  if (n > 1)
    sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
}
Exemplo n.º 4
0
Arquivo: sdc_lld.c Projeto: Kreyl/nute
/**
 * @brief   Wait end of data transaction and performs finalizations.
 *
 * @param[in] sdcp      pointer to the @p SDCDriver object
 * @param[in] n         number of blocks in transaction
 * @param[in] resp      pointer to the response buffer
 *
 * @return              The operation status.
 * @retval CH_SUCCESS   operation succeeded.
 * @retval CH_FAILED    operation failed.
 */
static bool_t sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
                                           uint32_t *resp) {

  /* Note the mask is checked before going to sleep because the interrupt
     may have occurred before reaching the critical zone.*/
  chSysLock();
  if (SDIO->MASK != 0) {
    chDbgAssert(sdcp->thread == NULL,
                "sdc_lld_start_data_transaction(), #1", "not NULL");
    sdcp->thread = chThdSelf();
    chSchGoSleepS(THD_STATE_SUSPENDED);
    chDbgAssert(sdcp->thread == NULL,
                "sdc_lld_start_data_transaction(), #2", "not NULL");
  }

  if ((SDIO->STA & SDIO_STA_DATAEND) == 0) {
    chSysUnlock();
    return CH_FAILED;
  }

#if (defined(STM32F4XX) || defined(STM32F2XX))
  /* Wait until DMA channel enabled to be sure that all data transferred.*/
  while (sdcp->dma->stream->CR & STM32_DMA_CR_EN)
    ;

  /* DMA event flags must be manually cleared.*/
  dmaStreamClearInterrupt(sdcp->dma);

  SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS;
  SDIO->DCTRL = 0;
  chSysUnlock();

  /* Wait until interrupt flags to be cleared.*/
  /*while (((DMA2->LISR) >> (sdcp->dma->ishift)) & STM32_DMA_ISR_TCIF)
    dmaStreamClearInterrupt(sdcp->dma);*/
#else
  /* Waits for transfer completion at DMA level, the the stream is
     disabled and cleared.*/
  dmaWaitCompletion(sdcp->dma);

  SDIO->ICR = STM32_SDIO_ICR_ALL_FLAGS;
  SDIO->DCTRL = 0;
  chSysUnlock();
#endif

  /* Finalize transaction.*/
  if (n > 1)
    return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);

  return CH_SUCCESS;
}
Exemplo n.º 5
0
/**
 * @brief   Wait end of data transaction and performs finalizations.
 *
 * @param[in] sdcp      pointer to the @p SDCDriver object
 * @param[in] n         number of blocks in transaction
 * @param[in] resp      pointer to the response buffer
 *
 * @return              The operation status.
 * @retval HAL_SUCCESS  operation succeeded.
 * @retval HAL_FAILED   operation failed.
 */
static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
        uint32_t *resp) {

    /* Note the mask is checked before going to sleep because the interrupt
       may have occurred before reaching the critical zone.*/
    osalSysLock();
    if (sdcp->sdio->MASK != 0)
        osalThreadSuspendS(&sdcp->thread);
    if ((sdcp->sdio->STA & SDIO_STA_DATAEND) == 0) {
        osalSysUnlock();
        return HAL_FAILED;
    }

#if (defined(STM32F4XX) || defined(STM32F2XX))
    /* Wait until DMA channel enabled to be sure that all data transferred.*/
    while (sdcp->dma->stream->CR & STM32_DMA_CR_EN)
        ;

    /* DMA event flags must be manually cleared.*/
    dmaStreamClearInterrupt(sdcp->dma);

    sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
    sdcp->sdio->DCTRL = 0;
    osalSysUnlock();

    /* Wait until interrupt flags to be cleared.*/
    /*while (((DMA2->LISR) >> (sdcp->dma->ishift)) & STM32_DMA_ISR_TCIF)
      dmaStreamClearInterrupt(sdcp->dma);*/
#else
    /* Waits for transfer completion at DMA level, then the stream is
       disabled and cleared.*/
    dmaWaitCompletion(sdcp->dma);

    sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
    sdcp->sdio->DCTRL = 0;
    osalSysUnlock();
#endif

    /* Finalize transaction.*/
    if (n > 1)
        return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);

    return HAL_SUCCESS;
}