static void dma_irq(DMAName name, int id, SerialIrq txrxirq) { if (serial_irq_ids[id] != 0) { if (txrxirq == RxIrq) { if (__HAL_DMA_GET_TC_FLAG_INDEX(&DmaHandle) != RESET) { irq_handler(serial_irq_ids[id], RxIrq); __HAL_DMA_CLEAR_FLAG(&DmaHandle, DMA_FLAG_TCIF2_6); } } else { if (__HAL_DMA_GET_TC_FLAG_INDEX(&DmaHandle) != RESET) { irq_handler(serial_irq_ids[id], TxIrq); __HAL_DMA_CLEAR_FLAG(&DmaHandle, DMA_FLAG_TCIF0_4); } } } DmaHandle.Instance = (DMA_Stream_TypeDef *)name; if (serial_irq_ids[id] != 0) { if (__HAL_DMA_GET_TC_FLAG_INDEX(&DmaHandle) != RESET) { irq_handler(serial_irq_ids[id], TxIrq); __HAL_DMA_CLEAR_FLAG(&DmaHandle, DMA_FLAG_TCIF0_4); } if (__HAL_DMA_GET_TC_FLAG_INDEX(&DmaHandle) != RESET) { irq_handler(serial_irq_ids[id], RxIrq); __HAL_DMA_CLEAR_FLAG(&DmaHandle, DMA_FLAG_TCIF2_6); } } }
/** * @brief DeInitializes the DMA peripheral * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval HAL status */ static HAL_StatusTypeDef _HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) { /* Check the DMA peripheral state */ if(hdma == NULL) { return HAL_ERROR; } /* Check the DMA peripheral state */ if(hdma->State == HAL_DMA_STATE_BUSY) { return HAL_ERROR; } /* Disable the selected DMA Streamx */ __HAL_DMA_DISABLE(hdma); /* Reset DMA Streamx control register */ hdma->Instance->CR = 0; /* Reset DMA Streamx number of data to transfer register */ hdma->Instance->NDTR = 0; /* Reset DMA Streamx peripheral address register */ hdma->Instance->PAR = 0; /* Reset DMA Streamx memory 0 address register */ hdma->Instance->M0AR = 0; /* Reset DMA Streamx memory 1 address register */ hdma->Instance->M1AR = 0; /* Reset DMA Streamx FIFO control register */ hdma->Instance->FCR = (uint32_t)0x00000021; /* Clear all flags */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Initialize the error code */ hdma->ErrorCode = HAL_DMA_ERROR_NONE; /* Initialize the DMA state */ hdma->State = HAL_DMA_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hdma); return HAL_OK; }
/** * @brief DeInitializes the DMA peripheral * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) { /* Check the DMA handle allocation */ if(hdma == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); /* Check the DMA peripheral state */ if(hdma->State == HAL_DMA_STATE_BUSY) { return HAL_ERROR; } /* Disable the selected DMA Channelx */ __HAL_DMA_DISABLE(hdma); /* Reset DMA Channel control register */ hdma->Instance->CCR = 0; /* Reset DMA Channel Number of Data to Transfer register */ hdma->Instance->CNDTR = 0; /* Reset DMA Channel peripheral address register */ hdma->Instance->CPAR = 0; /* Reset DMA Channel memory address register */ hdma->Instance->CMAR = 0; /* Clear all flags */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Initialize the error code */ hdma->ErrorCode = HAL_DMA_ERROR_NONE; /* Initialize the DMA state */ hdma->State = HAL_DMA_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hdma); return HAL_OK; }
/** * @brief 串口 DMA 发送接口 * @param huart : 串口句柄 * @param pData : 数据指针 * @param Size : 数据长度 * @param tx_tc_flag : 发送完成 flag 偏移 * @retval None */ HAL_StatusTypeDef USER_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, u32 tx_tc_flag) { if(__HAL_DMA_GET_FLAG(huart->hdmatx, tx_tc_flag)) { if(huart->State == HAL_UART_STATE_BUSY_TX_RX) { huart->State = HAL_UART_STATE_BUSY_TX; } else { huart->State = HAL_UART_STATE_READY; } __HAL_UNLOCK(huart->hdmatx); __HAL_DMA_CLEAR_FLAG(huart->hdmatx, tx_tc_flag); } return HAL_UART_Transmit_DMA(huart, pData, Size); }
/** * @brief Manage the SPI transmit * @param TransmitRequest: the transmit request * @retval None */ static void SPI_Transmit_Manager(SPI_TRANSMIT_REQUEST_t TransmitRequest) { /* * Disable both DMA */ __HAL_DMA_DISABLE(SPI_Context.hspi->hdmatx); __HAL_DMA_DISABLE(SPI_Context.hspi->hdmarx); __HAL_DMA_DISABLE_IT(SPI_Context.hspi->hdmarx, DMA_IT_TC); /**< Disable Receive packet notification */ __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); /**< Clear flag in DMA */ HAL_NVIC_ClearPendingIRQ(BNRG_SPI_DMA_TX_IRQn); /**< Clear DMA pending bit in NVIC */ __HAL_DMA_ENABLE_IT(SPI_Context.hspi->hdmatx, DMA_IT_TC); /**< Enable Transmit packet notification */ __HAL_BLUENRG_DMA_SET_MINC(SPI_Context.hspi->hdmatx); /**< Configure DMA to send Tx packet */ switch (TransmitRequest) { case SPI_HEADER_TRANSMIT: SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event = SPI_HEADER_TRANSMITTED; #ifdef ENABLE_SPI_FIX set_irq_as_input(); #endif __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, SPI_Context.SPI_Transmit_Context.header_size); /**< Set counter in DMA TX */ __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)SPI_Context.SPI_Transmit_Context.header_data); /**< Set memory address in DMA TX */ break; case SPI_PAYLOAD_TRANSMIT: SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event = SPI_PAYLOAD_TRANSMITTED; __HAL_BLUENRG_DMA_SET_COUNTER(SPI_Context.hspi->hdmatx, SPI_Context.SPI_Transmit_Context.payload_size_to_transmit); /**< Set counter in DMA TX */ __HAL_BLUENRG_DMA_SET_MEMORY_ADDRESS(SPI_Context.hspi->hdmatx, (uint32_t)SPI_Context.SPI_Transmit_Context.payload_data); /**< Set memory address in DMA TX */ break; default: break; } __HAL_DMA_ENABLE(SPI_Context.hspi->hdmatx); /**< Enable DMA TX */ }
/** * @brief Aborts the DMA Transfer in Interrupt mode. * @param hdma : pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) { HAL_StatusTypeDef status = HAL_OK; if(HAL_DMA_STATE_BUSY != hdma->State) { /* no transfer ongoing */ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; status = HAL_ERROR; } else { /* Disable DMA IT */ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); /* Disable the channel */ __HAL_DMA_DISABLE(hdma); /* Clear all flags */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma)); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); /* Call User Abort callback */ if(hdma->XferAbortCallback != NULL) { hdma->XferAbortCallback(hdma); } } return status; }
/** * @brief Tx and Rx Transfer completed callbacks * @param hspi: pointer to a SPI_HandleTypeDef structure that contains * the configuration information for SPI module. * @retval None */ void BlueNRG_DMA_TxCallback(void) { __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); switch (SPI_Context.SPI_Transmit_Context.Spi_Transmit_Event) { case SPI_HEADER_TRANSMITTED: if(SPI_Context.SPI_Transmit_Context.payload_size_to_transmit != 0) { SPI_Transmit_Manager(SPI_PAYLOAD_TRANSMIT); } else { TransmitClosure(); } break; case SPI_PAYLOAD_TRANSMITTED: if( (SPI_Context.SPI_Transmit_Context.packet_cont == TRUE) && (SPI_Context.SPI_Transmit_Context.payload_size != 0)) { SPI_Context.SPI_Transmit_Context.payload_data += SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; DisableEnable_SPI_CS(); SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_TX); } else { TransmitClosure(); } break; default: break; } return; }
/** * @brief Handles DMA interrupt request. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval None */ void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) { uint32_t flag_it = hdma->DmaBaseAddress->ISR; uint32_t source_it = hdma->Instance->CCR; /* Half Transfer Complete Interrupt management ******************************/ if (((flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_HT) != RESET)) { /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) { /* Disable the half transfer interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); } /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* DMA peripheral state is not updated in Half Transfer */ /* but in Transfer Complete case */ if(hdma->XferHalfCpltCallback != NULL) { /* Half transfer callback */ hdma->XferHalfCpltCallback(hdma); } } /* Transfer Complete Interrupt management ***********************************/ else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET)) { if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) { /* Disable the transfer complete and error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; } /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferCpltCallback != NULL) { /* Transfer complete callback */ hdma->XferCpltCallback(hdma); } } /* Transfer Error Interrupt management **************************************/ else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE))) { /* When a DMA transfer error occurs */ /* A hardware clear of its EN bits is performed */ /* Disable ALL DMA IT */ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); /* Clear all flags */ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); /* Update error code */ hdma->ErrorCode = HAL_DMA_ERROR_TE; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); if (hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } return; }
/** * @brief Polling for transfer complete. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @param CompleteLevel: Specifies the DMA level complete. * @param Timeout: Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout) { uint32_t temp; uint32_t tickstart = 0U; if(HAL_DMA_STATE_BUSY != hdma->State) { /* no transfer ongoing */ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; __HAL_UNLOCK(hdma); return HAL_ERROR; } /* Polling mode not supported in circular mode */ if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC)) { hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; return HAL_ERROR; } /* Get the level transfer complete flag */ if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Transfer Complete flag */ temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma); } else { /* Half Transfer Complete flag */ temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma); } /* Get tick */ tickstart = HAL_GetTick(); while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET) { if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)) { /* When a DMA transfer error occurs */ /* A hardware clear of its EN bits is performed */ /* Clear all flags */ hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE); /* Change the DMA state */ hdma->State= HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); return HAL_ERROR; } /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) { /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); return HAL_ERROR; } } } if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* The selected Channelx EN bit is cleared (DMA is disabled and all transfers are complete) */ hdma->State = HAL_DMA_STATE_READY; } else { /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); } /* Process unlocked */ __HAL_UNLOCK(hdma); return HAL_OK; }
/** * @brief Handles DMA interrupt request. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval None */ void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) { /* Transfer Error Interrupt management ***************************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET) { /* Disable the transfer error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE); /* Clear the transfer error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if (hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /* Half Transfer Complete Interrupt management ******************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET) { /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) { /* Disable the half transfer interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); } /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF; if(hdma->XferHalfCpltCallback != NULL) { /* Half transfer callback */ hdma->XferHalfCpltCallback(hdma); } } } /* Transfer Complete Interrupt management ***********************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET) { if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) { /* Disable the transfer complete interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC); } /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_NONE); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferCpltCallback != NULL) { /* Transfer complete callback */ hdma->XferCpltCallback(hdma); } } } }
/** * @brief Polling for transfer complete. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @param CompleteLevel: Specifies the DMA level complete. * @param Timeout: Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout) { uint32_t temp; uint32_t tickstart = 0x00; /* Get the level transfer complete flag */ if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Transfer Complete flag */ temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma); } else { /* Half Transfer Complete flag */ temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma); } /* Get tick */ tickstart = HAL_GetTick(); while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET) { if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)) { /* Clear the transfer error flags */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE); /* Change the DMA state */ hdma->State= HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); return HAL_ERROR; } /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) { /* Update error code */ SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_TIMEOUT; /* Process Unlocked */ __HAL_UNLOCK(hdma); return HAL_TIMEOUT; } } } if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* The selected Channelx EN bit is cleared (DMA is disabled and all transfers are complete) */ hdma->State = HAL_DMA_STATE_READY; } else { /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* The selected Channelx EN bit is cleared (DMA is disabled and all transfers of half buffer are complete) */ hdma->State = HAL_DMA_STATE_READY_HALF; } /* Process unlocked */ __HAL_UNLOCK(hdma); return HAL_OK; }
/** * @brief Starts the multi_buffer DMA Transfer with interrupt enabled. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @param SrcAddress The source memory Buffer address * @param DstAddress The destination memory Buffer address * @param SecondMemAddress The second memory Buffer address in case of multi buffer Transfer * @param DataLength The length of data to be transferred from source to destination * @retval HAL status */ HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) { HAL_StatusTypeDef status = HAL_OK; /* Check the parameters */ assert_param(IS_DMA_BUFFER_SIZE(DataLength)); /* Memory-to-memory transfer not supported in double buffering mode */ if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) { hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; return HAL_ERROR; } /* Check callback functions */ if ((NULL == hdma->XferCpltCallback) || (NULL == hdma->XferM1CpltCallback) || (NULL == hdma->XferErrorCallback)) { hdma->ErrorCode = HAL_DMA_ERROR_PARAM; return HAL_ERROR; } /* Process locked */ __HAL_LOCK(hdma); if(HAL_DMA_STATE_READY == hdma->State) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_BUSY; /* Initialize the error code */ hdma->ErrorCode = HAL_DMA_ERROR_NONE; /* Enable the Double buffer mode */ hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; /* Configure DMA Stream destination address */ hdma->Instance->M1AR = SecondMemAddress; /* Configure the source, destination address and the data length */ DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength); /* Clear all flags */ __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); /* Enable Common interrupts*/ hdma->Instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME; hdma->Instance->FCR |= DMA_IT_FE; if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL)) { hdma->Instance->CR |= DMA_IT_HT; } /* Enable the peripheral */ __HAL_DMA_ENABLE(hdma); } else { /* Process unlocked */ __HAL_UNLOCK(hdma); /* Return error status */ status = HAL_BUSY; } return status; }
/** * @brief Handles DMA interrupt request. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval None */ void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) { /* Transfer Error Interrupt management ***************************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET) { /* Disable the transfer error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE); /* Clear the transfer error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_TE; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /* FIFO Error Interrupt management ******************************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != RESET) { /* Disable the FIFO Error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_FE); /* Clear the FIFO error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_FE; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /* Direct Mode Error Interrupt management ***********************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != RESET) { /* Disable the direct mode Error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_DME); /* Clear the direct mode error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_DME; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /* Half Transfer Complete Interrupt management ******************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET) { /* Multi_Buffering mode enabled */ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0) { /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Current memory buffer used is Memory 0 */ if((hdma->Instance->CR & DMA_SxCR_CT) == 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0; } /* Current memory buffer used is Memory 1 */ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM1; } } else { /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0) { /* Disable the half transfer interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); } /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0; } if(hdma->XferHalfCpltCallback != NULL) { /* Half transfer callback */ hdma->XferHalfCpltCallback(hdma); } } } /* Transfer Complete Interrupt management ***********************************/ if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET) { if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0) { /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Current memory buffer used is Memory 1 */ if((hdma->Instance->CR & DMA_SxCR_CT) == 0) { if(hdma->XferM1CpltCallback != NULL) { /* Transfer complete Callback for memory1 */ hdma->XferM1CpltCallback(hdma); } } /* Current memory buffer used is Memory 0 */ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0) { if(hdma->XferCpltCallback != NULL) { /* Transfer complete Callback for memory0 */ hdma->XferCpltCallback(hdma); } } } /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */ else { if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0) { /* Disable the transfer complete interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC); } /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_NONE; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY_MEM0; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferCpltCallback != NULL) { /* Transfer complete callback */ hdma->XferCpltCallback(hdma); } } } } }
/** * @brief Polling for transfer complete. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @param CompleteLevel: Specifies the DMA level complete. * @param Timeout: Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout) { uint32_t temp, tmp, tmp1, tmp2; uint32_t timeout = 0x00; /* Get the level transfer complete flag */ if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Transfer Complete flag */ temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma); } else { /* Half Transfer Complete flag */ temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma); } /* Get timeout */ timeout = HAL_GetTick() + Timeout; while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET) { tmp = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); tmp1 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); tmp2 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); if((tmp != RESET) || (tmp1 != RESET) || (tmp2 != RESET)) { /* Clear the transfer error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); /* Clear the FIFO error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); /* Clear the DIrect Mode error flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); /* Change the DMA state */ hdma->State= HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); return HAL_ERROR; } /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if(HAL_GetTick() >= timeout) { /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT; /* Process Unlocked */ __HAL_UNLOCK(hdma); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_TIMEOUT; return HAL_TIMEOUT; } } } /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0; if(CompleteLevel == HAL_DMA_FULL_TRANSFER) { /* Multi_Buffering mode enabled */ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0) { /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Current memory buffer used is Memory 0 */ if((hdma->Instance->CR & DMA_SxCR_CT) == 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_MEM0; } /* Current memory buffer used is Memory 1 */ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_MEM1; } } else { /* Clear the transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* The selected Streamx EN bit is cleared (DMA is disabled and all transfers are complete) */ hdma->State = HAL_DMA_STATE_READY_MEM0; } /* Process Unlocked */ __HAL_UNLOCK(hdma); } else { /* Multi_Buffering mode enabled */ if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0) { /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Current memory buffer used is Memory 0 */ if((hdma->Instance->CR & DMA_SxCR_CT) == 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0; } /* Current memory buffer used is Memory 1 */ else if((hdma->Instance->CR & DMA_SxCR_CT) != 0) { /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM1; } } else { /* Clear the half transfer complete flag */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_READY_HALF_MEM0; } } return HAL_OK; }
/** * @brief DeInitializes the DMA peripheral * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Channel. * @retval HAL status */ HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) { /* Check the DMA peripheral state */ if(hdma->State == HAL_DMA_STATE_BUSY) { return HAL_ERROR; } /* Disable the selected DMA Channelx */ __HAL_DMA_DISABLE(hdma); /* Reset DMA Channel control register */ hdma->Instance->CCR = 0; /* Reset DMA Channel Number of Data to Transfer register */ hdma->Instance->CNDTR = 0; /* Reset DMA Channel peripheral address register */ hdma->Instance->CPAR = 0; /* Reset DMA Channel memory address register */ hdma->Instance->CMAR = 0; /* Clear all flags */ __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); /* Reset DMA channel selection register */ if (hdma->Instance == DMA1_Channel1) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C1S; } else if (hdma->Instance == DMA1_Channel2) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C2S; } else if (hdma->Instance == DMA1_Channel3) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C3S; } else if (hdma->Instance == DMA1_Channel4) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C4S; } else if (hdma->Instance == DMA1_Channel5) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C5S; } else if (hdma->Instance == DMA1_Channel6) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C6S; } else if (hdma->Instance == DMA1_Channel7) { /*Reset DMA request*/ DMA1_CSELR->CSELR &= ~DMA_CSELR_C7S; } /* Initialise the error code */ hdma->ErrorCode = HAL_DMA_ERROR_NONE; /* Initialize the DMA state */ hdma->State = HAL_DMA_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hdma); return HAL_OK; }
/** * @brief Tx and Rx Transfer completed callbacks * @param hspi: pointer to a SPI_HandleTypeDef structure that contains * the configuration information for SPI module. * @retval None */ void BlueNRG_DMA_RxCallback(void) { uint16_t byte_count; uint8_t ready_state; __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmarx, BNRG_SPI_RX_DMA_TC_FLAG); /** * The TCIF shall be cleared to be able to start a new DMA transmission later on when required. * When receiving data, the TCIE is not set as there is no need to handle the interrupt * handler of the DMA_Tx. * The TCIF clearing is mandatory on STM32F4 but not on STM32L0. * In order to keep code identical across platform, the TCIF clearing may be kept as well on * the STM32L0 and all other MCUs. */ __HAL_DMA_CLEAR_FLAG(SPI_Context.hspi->hdmatx, BNRG_SPI_TX_DMA_TC_FLAG); switch (SPI_Context.SPI_Receive_Context.Spi_Receive_Event) { case SPI_CHECK_RECEIVED_HEADER_FOR_RX: byte_count = (Received_Header[4]<<8)|Received_Header[3]; ready_state = Received_Header[0]; if ((byte_count == 0) || (ready_state != BLUENRG_READY_STATE)) { if (HAL_GPIO_ReadPin(BNRG_SPI_IRQ_PORT, BNRG_SPI_IRQ_PIN) == GPIO_PIN_RESET) { /** * This USE CASE shall never happen as this may break the IRQ/CS specification * The IRQ line shall never be low when CS is low to avoid BlueNRG race condition when * entering low power mode * the SPI_END_RECEIVE_FIX has been implemented to make sure this USE CASE never occurs * However, even when the behavior is not compliant to the specification, the BlueNRG * may not fail so it is increasing robustness by adding this checking just in case the * timeout define in the workaround is too short which will end up to marginally brake * the specification. * This checking will poping BluenRG for a dummy even */ /* Release CS line */ Disable_SPI_CS(); LPM_Mode_Request(eLPM_SPI_RX, eLPM_Mode_LP_Stop); ReceiveClosure(); } else { DisableEnable_SPI_CS(); SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_RX); /**< BlueNRG not ready for reading */ } } else { SPI_Receive_Manager(SPI_REQUEST_PAYLOAD); /**< BlueNRG is ready for reading */ } break; case SPI_RECEIVE_END: /* Release CS line */ Disable_SPI_CS(); LPM_Mode_Request(eLPM_SPI_RX, eLPM_Mode_LP_Stop); #if (SPI_END_RECEIVE_FIX == 1) pTimerTxRxCallback = ProcessEndOfReceive; TIMER_Start(TxRxTimerId, SPI_END_RECEIVE_FIX_TIMEOUT); #else ProcessEndOfReceive(); #endif break; case SPI_CHECK_RECEIVED_HEADER_FOR_TX: byte_count = (Received_Header[2]<<8)|Received_Header[1]; ready_state = Received_Header[0]; if ((byte_count == 0) || (ready_state != BLUENRG_READY_STATE)) { DisableEnable_SPI_CS(); SPI_Receive_Manager(SPI_REQUEST_VALID_HEADER_FOR_TX); /**< BlueNRG not ready for writing */ } else { #if (TEST_TX_BUFFER_LIMITATION == 1) if(byte_count > MAX_TX_BUFFER_SIZE) { byte_count = MAX_TX_BUFFER_SIZE; } #endif if(SPI_Context.SPI_Transmit_Context.packet_cont != TRUE) { if( byte_count < (SPI_Context.SPI_Transmit_Context.header_size + SPI_Context.SPI_Transmit_Context.payload_size)) { SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = byte_count - SPI_Context.SPI_Transmit_Context.header_size; SPI_Context.SPI_Transmit_Context.payload_size -= SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; SPI_Context.SPI_Transmit_Context.packet_cont = TRUE; } else { SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = SPI_Context.SPI_Transmit_Context.payload_size; } SPI_Transmit_Manager(SPI_HEADER_TRANSMIT); } else { if( byte_count < SPI_Context.SPI_Transmit_Context.payload_size) { SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = byte_count; SPI_Context.SPI_Transmit_Context.payload_size -= SPI_Context.SPI_Transmit_Context.payload_size_to_transmit; } else { SPI_Context.SPI_Transmit_Context.payload_size_to_transmit = SPI_Context.SPI_Transmit_Context.payload_size; SPI_Context.SPI_Transmit_Context.payload_size = 0; } SPI_Transmit_Manager(SPI_PAYLOAD_TRANSMIT); } } break; default: break; } }