/** ****************************************************************************** * @file stm32l4xx_hal_swpmi.c * @author MCD Application Team * @brief SWPMI HAL module driver. * This file provides firmware functions to manage the following * functionalities of the Single Wire Protocol Master Interface (SWPMI). * + Initialization and Configuration * + Data transfers functions * + DMA transfers management * + Interrupts and flags management ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** @verbatim =============================================================================== ##### How to use this driver ##### =============================================================================== [..] The SWPMI HAL driver can be used as follows: (#) Declare a SWPMI_HandleTypeDef handle structure (eg. SWPMI_HandleTypeDef hswpmi). (#) Initialize the SWPMI low level resources by implementing the HAL_SWPMI_MspInit() API: (##) Enable the SWPMIx interface clock with __HAL_RCC_SWPMIx_CLK_ENABLE(). (##) SWPMI IO configuration: (+++) Enable the clock for the SWPMI GPIO. (+++) Configure these SWPMI pins as alternate function pull-up. (##) NVIC configuration if you need to use interrupt process (HAL_SWPMI_Transmit_IT() and HAL_SWPMI_Receive_IT() APIs): (+++) Configure the SWPMIx interrupt priority with HAL_NVIC_SetPriority(). (+++) Enable the NVIC SWPMI IRQ handle with HAL_NVIC_EnableIRQ(). (##) DMA Configuration if you need to use DMA process (HAL_SWPMI_Transmit_DMA() and HAL_SWPMI_Receive_DMA() APIs): (+++) Declare a DMA handle structure for the Tx/Rx channels. (+++) Enable the DMAx interface clock. (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. (+++) Configure the DMA Tx/Rx channels and requests. (+++) Associate the initialized DMA handle to the SWPMI DMA Tx/Rx handle. (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channels. (#) Program the Bite Rate, Tx Buffering mode, Rx Buffering mode in the Init structure. (#) Enable the SWPMI peripheral by calling the HAL_SWPMI_Init() function. [..] Three operation modes are available within this driver : *** Polling mode IO operation *** ================================= [..] (+) Send an amount of data in blocking mode using HAL_SWPMI_Transmit() (+) Receive an amount of data in blocking mode using HAL_SWPMI_Receive() *** Interrupt mode IO operation *** =================================== [..] (+) Send an amount of data in non-blocking mode using HAL_SWPMI_Transmit_IT() (+) At transmission end of transfer HAL_SWPMI_TxCpltCallback() is executed and user can add his own code by customization of function pointer HAL_SWPMI_TxCpltCallback() (+) Receive an amount of data in non-blocking mode using HAL_SWPMI_Receive_IT() (+) At reception end of transfer HAL_SWPMI_RxCpltCallback() is executed and user can add his own code by customization of function pointer HAL_SWPMI_RxCpltCallback() (+) In case of flag error, HAL_SWPMI_ErrorCallback() function is executed and user can add his own code by customization of function pointer HAL_SWPMI_ErrorCallback() *** DMA mode IO operation *** ============================= [..] (+) Send an amount of data in non-blocking mode (DMA) using HAL_SWPMI_Transmit_DMA() (+) At transmission end of transfer HAL_SWPMI_TxCpltCallback() is executed and user can add his own code by customization of function pointer HAL_SWPMI_TxCpltCallback() (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SWPMI_Receive_DMA() (+) At reception end of transfer HAL_SWPMI_RxCpltCallback() is executed and user can add his own code by customization of function pointer HAL_SWPMI_RxCpltCallback() (+) In case of flag error, HAL_SWPMI_ErrorCallback() function is executed and user can add his own code by customization of function pointer HAL_SWPMI_ErrorCallback() (+) Stop the DMA Transfer using HAL_SWPMI_DMAStop() *** SWPMI HAL driver additional function list *** =============================================== [..] Below the list the others API available SWPMI HAL driver : (+) HAL_SWPMI_EnableLoopback(): Enable the loopback mode for test purpose only (+) HAL_SWPMI_DisableLoopback(): Disable the loopback mode *** SWPMI HAL driver macros list *** ================================== [..] Below the list of most used macros in SWPMI HAL driver : (+) __HAL_SWPMI_ENABLE(): Enable the SWPMI peripheral (+) __HAL_SWPMI_DISABLE(): Disable the SWPMI peripheral (+) __HAL_SWPMI_ENABLE_IT(): Enable the specified SWPMI interrupts (+) __HAL_SWPMI_DISABLE_IT(): Disable the specified SWPMI interrupts (+) __HAL_SWPMI_GET_IT_SOURCE(): Check if the specified SWPMI interrupt source is enabled or disabled (+) __HAL_SWPMI_GET_FLAG(): Check whether the specified SWPMI flag is set or not *** Callback registration *** ============================= [..] The compilation define USE_HAL_SWPMI_REGISTER_CALLBACKS when set to 1 allows the user to configure dynamically the driver callbacks. [..] Use function HAL_SWPMI_RegisterCallback() to register a user callback. It allows to register the following callbacks: (+) RxCpltCallback : SWPMI receive complete. (+) RxHalfCpltCallback : SWPMI receive half complete. (+) TxCpltCallback : SWPMI transmit complete. (+) TxHalfCpltCallback : SWPMI transmit half complete. (+) ErrorCallback : SWPMI error. (+) MspInitCallback : SWPMI MspInit. (+) MspDeInitCallback : SWPMI MspDeInit. [..] This function takes as parameters the HAL peripheral handle, the callback ID and a pointer to the user callback function. [..] Use function HAL_SWPMI_UnRegisterCallback() to reset a callback to the default weak (surcharged) function. HAL_SWPMI_UnRegisterCallback() takes as parameters the HAL peripheral handle, and the callback ID. This function allows to reset following callbacks: (+) RxCpltCallback : SWPMI receive complete. (+) RxHalfCpltCallback : SWPMI receive half complete. (+) TxCpltCallback : SWPMI transmit complete. (+) TxHalfCpltCallback : SWPMI transmit half complete. (+) ErrorCallback : SWPMI error. (+) MspInitCallback : SWPMI MspInit. (+) MspDeInitCallback : SWPMI MspDeInit. [..] By default, after the HAL_SWPMI_Init and if the state is HAL_SWPMI_STATE_RESET all callbacks are reset to the corresponding legacy weak (surcharged) functions: examples HAL_SWPMI_RxCpltCallback(), HAL_SWPMI_ErrorCallback(). Exception done for MspInit and MspDeInit callbacks that are respectively reset to the legacy weak (surcharged) functions in the HAL_SWPMI_Init and HAL_SWPMI_DeInit only when these callbacks are null (not registered beforehand). If not, MspInit or MspDeInit are not null, the HAL_SWPMI_Init and HAL_SWPMI_DeInit keep and use the user MspInit/MspDeInit callbacks (registered beforehand). [..] Callbacks can be registered/unregistered in READY state only. Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. In that case first register the MspInit/MspDeInit user callbacks using HAL_SWPMI_RegisterCallback before calling HAL_SWPMI_DeInit or HAL_SWPMI_Init function. [..] When the compilation define USE_HAL_SWPMI_REGISTER_CALLBACKS is set to 0 or not defined, the callback registering feature is not available and weak (surcharged) callbacks are used. @endverbatim */ /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal.h" /** @addtogroup STM32L4xx_HAL_Driver * @{ */ #if defined(SWPMI1) /** @defgroup SWPMI SWPMI * @brief HAL SWPMI module driver * @{ */ #ifdef HAL_SWPMI_MODULE_ENABLED /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private constants ---------------------------------------------------------*/ /** @addtogroup SWPMI_Private_Constants SWPMI Private Constants * @{ */ #define SWPMI_TIMEOUT_VALUE 22000U /* End of transmission timeout */ /** * @} */ /* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ static void SWPMI_DMATransmitCplt(DMA_HandleTypeDef *hdma); static void SWPMI_DMATxHalfCplt(DMA_HandleTypeDef *hdma); static void SWPMI_DMAReceiveCplt(DMA_HandleTypeDef *hdma); static void SWPMI_DMARxHalfCplt(DMA_HandleTypeDef *hdma); static void SWPMI_DMAError(DMA_HandleTypeDef *hdma); static void SWPMI_DMAAbortOnError(DMA_HandleTypeDef *hdma); static void SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi); static void SWPMI_EndTransmit_IT(SWPMI_HandleTypeDef *hswpmi); static void SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi); static void SWPMI_EndReceive_IT(SWPMI_HandleTypeDef *hswpmi); static void SWPMI_EndTransmitReceive_IT(SWPMI_HandleTypeDef *hswpmi); static HAL_StatusTypeDef SWPMI_WaitOnFlagSetUntilTimeout(SWPMI_HandleTypeDef *hswpmi, uint32_t Flag, uint32_t Tickstart, uint32_t Timeout); /* Exported functions --------------------------------------------------------*/ /** @defgroup SWPMI_Exported_Functions SWPMI Exported Functions * @{ */ /** @defgroup SWPMI_Exported_Group1 Initialization/de-initialization methods * @brief Initialization and Configuration functions * @verbatim =============================================================================== ##### Initialization and Configuration functions ##### =============================================================================== [..] This section provides functions allowing to: (+) Initialize and configure the SWPMI peripheral. (+) De-initialize the SWPMI peripheral. @endverbatim * @{ */ /** * @brief Initialize the SWPMI peripheral according to the specified parameters in the SWPMI_InitTypeDef. * @param hswpmi SWPMI handle * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Init(SWPMI_HandleTypeDef *hswpmi) { HAL_StatusTypeDef status = HAL_OK; __IO uint32_t wait_loop_index = 0U; /* Check the SWPMI handle allocation */ if (hswpmi == NULL) { status = HAL_ERROR; } else { /* Check the parameters */ assert_param(IS_SWPMI_VOLTAGE_CLASS(hswpmi->Init.VoltageClass)); assert_param(IS_SWPMI_BITRATE_VALUE(hswpmi->Init.BitRate)); assert_param(IS_SWPMI_TX_BUFFERING_MODE(hswpmi->Init.TxBufferingMode)); assert_param(IS_SWPMI_RX_BUFFERING_MODE(hswpmi->Init.RxBufferingMode)); if (hswpmi->State == HAL_SWPMI_STATE_RESET) { /* Allocate lock resource and initialize it */ hswpmi->Lock = HAL_UNLOCKED; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) /* Reset callback pointers to the weak predefined callbacks */ hswpmi->RxCpltCallback = HAL_SWPMI_RxCpltCallback; hswpmi->RxHalfCpltCallback = HAL_SWPMI_RxHalfCpltCallback; hswpmi->TxCpltCallback = HAL_SWPMI_TxCpltCallback; hswpmi->TxHalfCpltCallback = HAL_SWPMI_TxHalfCpltCallback; hswpmi->ErrorCallback = HAL_SWPMI_ErrorCallback; /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ if (hswpmi->MspInitCallback == NULL) { hswpmi->MspInitCallback = HAL_SWPMI_MspInit; } hswpmi->MspInitCallback(hswpmi); #else /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ HAL_SWPMI_MspInit(hswpmi); #endif } hswpmi->State = HAL_SWPMI_STATE_BUSY; /* Disable SWPMI interface */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Clear all SWPMI interface flags */ WRITE_REG(hswpmi->Instance->ICR, 0x019F); /* Apply Voltage class selection */ MODIFY_REG(hswpmi->Instance->OR, SWPMI_OR_CLASS, hswpmi->Init.VoltageClass); /* If Voltage class B, apply 300us delay */ if (hswpmi->Init.VoltageClass == SWPMI_VOLTAGE_CLASS_B) { /* Insure 300us wait to insure SWPMI_IO output not higher than 1.8V */ /* Wait loop initialization and execution */ /* Note: Variable divided by 4 to compensate partially CPU processing cycles. */ wait_loop_index = (300U * (SystemCoreClock / (1000000U * 4U))) + 150U; while (wait_loop_index != 0U) { wait_loop_index--; } } /* Configure the BRR register (Bitrate) */ WRITE_REG(hswpmi->Instance->BRR, hswpmi->Init.BitRate); /* Apply SWPMI CR configuration */ MODIFY_REG(hswpmi->Instance->CR, \ SWPMI_CR_RXDMA | SWPMI_CR_TXDMA | SWPMI_CR_RXMODE | SWPMI_CR_TXMODE, \ hswpmi->Init.TxBufferingMode | hswpmi->Init.RxBufferingMode); hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; hswpmi->State = HAL_SWPMI_STATE_READY; /* Enable SWPMI peripheral */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } return status; } /** * @brief De-initialize the SWPMI peripheral. * @param hswpmi SWPMI handle * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_DeInit(SWPMI_HandleTypeDef *hswpmi) { HAL_StatusTypeDef status = HAL_OK; /* Check the SWPMI handle allocation */ if (hswpmi == NULL) { status = HAL_ERROR; } else { /* Check the parameters */ assert_param(IS_SWPMI_INSTANCE(hswpmi->Instance)); hswpmi->State = HAL_SWPMI_STATE_BUSY; /* Disable SWPMI interface */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Disable Loopback mode */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK); /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) if (hswpmi->MspDeInitCallback == NULL) { hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit; } hswpmi->MspDeInitCallback(hswpmi); #else HAL_SWPMI_MspDeInit(hswpmi); #endif hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; hswpmi->State = HAL_SWPMI_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hswpmi); } return status; } /** * @brief Initialize the SWPMI MSP. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_MspInit(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SWPMI_MspInit can be implemented in the user file */ } /** * @brief DeInitialize the SWPMI MSP. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_MspDeInit(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SWPMI_MspDeInit can be implemented in the user file */ } #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) /** * @brief Register a user SWPMI callback * to be used instead of the weak predefined callback. * @param hswpmi SWPMI handle. * @param CallbackID ID of the callback to be registered. * This parameter can be one of the following values: * @arg @ref HAL_SWPMI_RX_COMPLETE_CB_ID receive complete callback ID. * @arg @ref HAL_SWPMI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. * @arg @ref HAL_SWPMI_TX_COMPLETE_CB_ID transmit complete callback ID. * @arg @ref HAL_SWPMI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. * @arg @ref HAL_SWPMI_ERROR_CB_ID error callback ID. * @arg @ref HAL_SWPMI_MSPINIT_CB_ID MSP init callback ID. * @arg @ref HAL_SWPMI_MSPDEINIT_CB_ID MSP de-init callback ID. * @param pCallback pointer to the callback function. * @retval HAL status. */ HAL_StatusTypeDef HAL_SWPMI_RegisterCallback(SWPMI_HandleTypeDef *hswpmi, HAL_SWPMI_CallbackIDTypeDef CallbackID, pSWPMI_CallbackTypeDef pCallback) { HAL_StatusTypeDef status = HAL_OK; if (pCallback == NULL) { /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; } else { if (hswpmi->State == HAL_SWPMI_STATE_READY) { switch (CallbackID) { case HAL_SWPMI_RX_COMPLETE_CB_ID : hswpmi->RxCpltCallback = pCallback; break; case HAL_SWPMI_RX_HALFCOMPLETE_CB_ID : hswpmi->RxHalfCpltCallback = pCallback; break; case HAL_SWPMI_TX_COMPLETE_CB_ID : hswpmi->TxCpltCallback = pCallback; break; case HAL_SWPMI_TX_HALFCOMPLETE_CB_ID : hswpmi->TxHalfCpltCallback = pCallback; break; case HAL_SWPMI_ERROR_CB_ID : hswpmi->ErrorCallback = pCallback; break; case HAL_SWPMI_MSPINIT_CB_ID : hswpmi->MspInitCallback = pCallback; break; case HAL_SWPMI_MSPDEINIT_CB_ID : hswpmi->MspDeInitCallback = pCallback; break; default : /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; break; } } else if (hswpmi->State == HAL_SWPMI_STATE_RESET) { switch (CallbackID) { case HAL_SWPMI_MSPINIT_CB_ID : hswpmi->MspInitCallback = pCallback; break; case HAL_SWPMI_MSPDEINIT_CB_ID : hswpmi->MspDeInitCallback = pCallback; break; default : /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; break; } } else { /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; } } return status; } /** * @brief Unregister a user SWPMI callback. * SWPMI callback is redirected to the weak predefined callback. * @param hswpmi SWPMI handle. * @param CallbackID ID of the callback to be unregistered. * This parameter can be one of the following values: * @arg @ref HAL_SWPMI_RX_COMPLETE_CB_ID receive complete callback ID. * @arg @ref HAL_SWPMI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. * @arg @ref HAL_SWPMI_TX_COMPLETE_CB_ID transmit complete callback ID. * @arg @ref HAL_SWPMI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. * @arg @ref HAL_SWPMI_ERROR_CB_ID error callback ID. * @arg @ref HAL_SWPMI_MSPINIT_CB_ID MSP init callback ID. * @arg @ref HAL_SWPMI_MSPDEINIT_CB_ID MSP de-init callback ID. * @retval HAL status. */ HAL_StatusTypeDef HAL_SWPMI_UnRegisterCallback(SWPMI_HandleTypeDef *hswpmi, HAL_SWPMI_CallbackIDTypeDef CallbackID) { HAL_StatusTypeDef status = HAL_OK; if (hswpmi->State == HAL_SWPMI_STATE_READY) { switch (CallbackID) { case HAL_SWPMI_RX_COMPLETE_CB_ID : hswpmi->RxCpltCallback = HAL_SWPMI_RxCpltCallback; break; case HAL_SWPMI_RX_HALFCOMPLETE_CB_ID : hswpmi->RxHalfCpltCallback = HAL_SWPMI_RxHalfCpltCallback; break; case HAL_SWPMI_TX_COMPLETE_CB_ID : hswpmi->TxCpltCallback = HAL_SWPMI_TxCpltCallback; break; case HAL_SWPMI_TX_HALFCOMPLETE_CB_ID : hswpmi->TxHalfCpltCallback = HAL_SWPMI_TxHalfCpltCallback; break; case HAL_SWPMI_ERROR_CB_ID : hswpmi->ErrorCallback = HAL_SWPMI_ErrorCallback; break; case HAL_SWPMI_MSPINIT_CB_ID : hswpmi->MspInitCallback = HAL_SWPMI_MspInit; break; case HAL_SWPMI_MSPDEINIT_CB_ID : hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit; break; default : /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; break; } } else if (hswpmi->State == HAL_SWPMI_STATE_RESET) { switch (CallbackID) { case HAL_SWPMI_MSPINIT_CB_ID : hswpmi->MspInitCallback = HAL_SWPMI_MspInit; break; case HAL_SWPMI_MSPDEINIT_CB_ID : hswpmi->MspDeInitCallback = HAL_SWPMI_MspDeInit; break; default : /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; break; } } else { /* update the error code */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_INVALID_CALLBACK; /* update return status */ status = HAL_ERROR; } return status; } #endif /* USE_HAL_SWPMI_REGISTER_CALLBACKS */ /** * @} */ /** @defgroup SWPMI_Exported_Group2 IO operation methods * @brief SWPMI Transmit/Receive functions * @verbatim =============================================================================== ##### IO operation methods ##### =============================================================================== [..] This subsection provides a set of functions allowing to manage the SWPMI data transfers. (#) There are two modes of transfer: (++) Blocking mode: The communication is performed in polling mode. The HAL status of all data processing is returned by the same function after finishing transfer. (++) Non-Blocking mode: The communication is performed using Interrupts or DMA. The end of the data processing will be indicated through the dedicated SWPMI Interrupt handler (HAL_SWPMI_IRQHandler()) when using Interrupt mode or the selected DMA channel interrupt handler when using DMA mode. The HAL_SWPMI_TxCpltCallback(), HAL_SWPMI_RxCpltCallback() user callbacks will be executed respectively at the end of the transmit or receive process. The HAL_SWPMI_ErrorCallback() user callback will be executed when a communication error is detected. (#) Blocking mode API's are: (++) HAL_SWPMI_Transmit() (++) HAL_SWPMI_Receive() (#) Non-Blocking mode API's with Interrupt are: (++) HAL_SWPMI_Transmit_IT() (++) HAL_SWPMI_Receive_IT() (++) HAL_SWPMI_IRQHandler() (#) Non-Blocking mode API's with DMA are: (++) HAL_SWPMI_Transmit_DMA() (++) HAL_SWPMI_Receive_DMA() (++) HAL_SWPMI_DMAPause() (++) HAL_SWPMI_DMAResume() (++) HAL_SWPMI_DMAStop() (#) A set of Transfer Complete Callbacks are provided in Non-Blocking mode: (++) HAL_SWPMI_TxHalfCpltCallback() (++) HAL_SWPMI_TxCpltCallback() (++) HAL_SWPMI_RxHalfCpltCallback() (++) HAL_SWPMI_RxCpltCallback() (++) HAL_SWPMI_ErrorCallback() (#) The capability to launch the above IO operations in loopback mode for user application verification: (++) HAL_SWPMI_EnableLoopback() (++) HAL_SWPMI_DisableLoopback() @endverbatim * @{ */ /** * @brief Transmit an amount of data in blocking mode. * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains * the configuration information for SWPMI module. * @param pData Pointer to data buffer * @param Size Amount of data to be sent * @param Timeout Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Transmit(SWPMI_HandleTypeDef *hswpmi, const uint32_t *pData, uint16_t Size, uint32_t Timeout) { uint32_t tickstart = HAL_GetTick(); HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; const uint32_t *ptmp_data; uint32_t tmp_size; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX)) { /* Check if a non-blocking receive process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; /* Disable any transmitter interrupts */ __HAL_SWPMI_DISABLE_IT(hswpmi, SWPMI_IT_TCIE | SWPMI_IT_TIE | SWPMI_IT_TXUNRIE | SWPMI_IT_TXBEIE); /* Disable any transmitter flags */ __HAL_SWPMI_CLEAR_FLAG(hswpmi, SWPMI_FLAG_TXBEF | SWPMI_FLAG_TXUNRF | SWPMI_FLAG_TCF); /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } ptmp_data = pData; tmp_size = Size; do { /* Wait the TXE to write data */ if (HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_TXE)) { hswpmi->Instance->TDR = *ptmp_data; ptmp_data++; tmp_size--; } else { /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) { status = HAL_TIMEOUT; break; } } } } while (tmp_size != 0U); /* Wait on TXBEF flag to be able to start a second transfer */ if (SWPMI_WaitOnFlagSetUntilTimeout(hswpmi, SWPMI_FLAG_TXBEF, tickstart, Timeout) != HAL_OK) { /* Timeout occurred */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_TXBEF_TIMEOUT; status = HAL_TIMEOUT; } if (status == HAL_OK) { /* Check if a non-blocking receive Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } } } else { status = HAL_BUSY; } } if ((status != HAL_OK) && (status != HAL_BUSY)) { hswpmi->State = HAL_SWPMI_STATE_READY; } /* Process Unlocked */ __HAL_UNLOCK(hswpmi); return status; } /** * @brief Receive an amount of data in blocking mode. * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains * the configuration information for SWPMI module. * @param pData Pointer to data buffer * @param Size Amount of data to be received * @param Timeout Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Receive(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size, uint32_t Timeout) { uint32_t tickstart = HAL_GetTick(); HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; uint32_t *ptmp_data; uint32_t tmp_size; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX)) { /* Check if a non-blocking transmit process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; /* Disable any receiver interrupts */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_SRIE | SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE); /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } ptmp_data = pData; tmp_size = Size; do { /* Wait the RXNE to read data */ if (HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_RXNE)) { *ptmp_data = hswpmi->Instance->RDR; ptmp_data++; tmp_size--; } else { /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) { status = HAL_TIMEOUT; break; } } } } while (tmp_size != 0U); if (status == HAL_OK) { if (HAL_IS_BIT_SET(hswpmi->Instance->ISR, SWPMI_FLAG_RXBFF)) { /* Clear RXBFF at end of reception */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBFF); } /* Check if a non-blocking transmit Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } } } else { status = HAL_BUSY; } } if ((status != HAL_OK) && (status != HAL_BUSY)) { hswpmi->State = HAL_SWPMI_STATE_READY; } /* Process Unlocked */ __HAL_UNLOCK(hswpmi); return status; } /** * @brief Transmit an amount of data in non-blocking mode with interrupt. * @param hswpmi pointer to a SWPMI_HandleTypeDef structure that contains * the configuration information for SWPMI module. * @param pData Pointer to data buffer * @param Size Amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi, const uint32_t *pData, uint16_t Size) { HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX)) { /* Update handle */ hswpmi->pTxBuffPtr = pData; hswpmi->TxXferSize = Size; hswpmi->TxXferCount = Size; hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; /* Check if a receive process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } /* Enable the SWPMI transmit underrun error */ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TXUNRIE); /* Process Unlocked */ __HAL_UNLOCK(hswpmi); /* Enable the SWPMI interrupts: */ /* - Transmit data register empty */ /* - Transmit buffer empty */ /* - Transmit/Reception completion */ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TIE | SWPMI_IT_TXBEIE | SWPMI_IT_TCIE); } else { status = HAL_BUSY; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } } return status; } /** * @brief Receive an amount of data in non-blocking mode with interrupt. * @param hswpmi SWPMI handle * @param pData Pointer to data buffer * @param Size Amount of data to be received * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size) { HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX)) { /* Update handle */ hswpmi->pRxBuffPtr = pData; hswpmi->RxXferSize = Size; hswpmi->RxXferCount = Size; hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; /* Check if a transmit process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } /* Process Unlocked */ __HAL_UNLOCK(hswpmi); /* Enable the SWPMI slave resume */ /* Enable the SWPMI Data Register not empty Interrupt, receive CRC Error, receive overrun and RxBuf Interrupt */ /* Enable the SWPMI Transmit/Reception completion */ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE); } else { status = HAL_BUSY; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } } return status; } /** * @brief Transmit an amount of data in non-blocking mode with DMA interrupt. * @param hswpmi SWPMI handle * @param pData Pointer to data buffer * @param Size Amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Transmit_DMA(SWPMI_HandleTypeDef *hswpmi, const uint32_t *pData, uint16_t Size) { HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_RX)) { /* Update handle */ hswpmi->pTxBuffPtr = pData; hswpmi->TxXferSize = Size; hswpmi->TxXferCount = Size; hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; /* Check if a receive process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } /* Set the SWPMI DMA transfer complete callback */ hswpmi->hdmatx->XferCpltCallback = SWPMI_DMATransmitCplt; /* Set the SWPMI DMA Half transfer complete callback */ hswpmi->hdmatx->XferHalfCpltCallback = SWPMI_DMATxHalfCplt; /* Set the DMA error callback */ hswpmi->hdmatx->XferErrorCallback = SWPMI_DMAError; /* Enable the SWPMI transmit DMA channel */ if (HAL_DMA_Start_IT(hswpmi->hdmatx, (uint32_t)hswpmi->pTxBuffPtr, (uint32_t)&hswpmi->Instance->TDR, Size) != HAL_OK) { hswpmi->State = tmp_state; /* Back to previous state */ hswpmi->ErrorCode = HAL_SWPMI_ERROR_DMA; status = HAL_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } else { /* Process Unlocked */ __HAL_UNLOCK(hswpmi); /* Enable the SWPMI transmit underrun error */ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_TXUNRIE); /* Enable the DMA transfer for transmit request by setting the TXDMA bit in the SWPMI CR register */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA); } } else { status = HAL_BUSY; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } } return status; } /** * @brief Receive an amount of data in non-blocking mode with DMA interrupt. * @param hswpmi SWPMI handle * @param pData Pointer to data buffer * @param Size Amount of data to be received * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_Receive_DMA(SWPMI_HandleTypeDef *hswpmi, uint32_t *pData, uint16_t Size) { HAL_StatusTypeDef status = HAL_OK; HAL_SWPMI_StateTypeDef tmp_state; if ((pData == NULL) || (Size == 0U)) { status = HAL_ERROR; } else { /* Process Locked */ __HAL_LOCK(hswpmi); tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_READY) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX)) { /* Update handle */ hswpmi->pRxBuffPtr = pData; hswpmi->RxXferSize = Size; hswpmi->ErrorCode = HAL_SWPMI_ERROR_NONE; /* Check if a transmit process is ongoing or not */ if (tmp_state == HAL_SWPMI_STATE_READY) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; /* Enable SWPMI peripheral if not */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); } else { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX_RX; } /* Set the SWPMI DMA transfer complete callback */ hswpmi->hdmarx->XferCpltCallback = SWPMI_DMAReceiveCplt; /* Set the SWPMI DMA Half transfer complete callback */ hswpmi->hdmarx->XferHalfCpltCallback = SWPMI_DMARxHalfCplt; /* Set the DMA error callback */ hswpmi->hdmarx->XferErrorCallback = SWPMI_DMAError; /* Enable the DMA request */ if (HAL_DMA_Start_IT(hswpmi->hdmarx, (uint32_t)&hswpmi->Instance->RDR, (uint32_t)hswpmi->pRxBuffPtr, Size) != HAL_OK) { hswpmi->State = tmp_state; /* Back to previous state */ hswpmi->ErrorCode = HAL_SWPMI_ERROR_DMA; status = HAL_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } else { /* Process Unlocked */ __HAL_UNLOCK(hswpmi); /* Enable the SWPMI receive CRC Error and receive overrun interrupts */ __HAL_SWPMI_ENABLE_IT(hswpmi, SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE); /* Enable the DMA transfer for the receiver request by setting the RXDMA bit in the SWPMI CR register */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA); } } else { status = HAL_BUSY; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); } } return status; } /** * @brief Stop all DMA transfers. * @param hswpmi SWPMI handle * @retval HAL status */ HAL_StatusTypeDef HAL_SWPMI_DMAStop(SWPMI_HandleTypeDef *hswpmi) { HAL_StatusTypeDef status = HAL_OK; /* Process Locked */ __HAL_LOCK(hswpmi); /* Disable the SWPMI Tx/Rx DMA requests */ CLEAR_BIT(hswpmi->Instance->CR, (SWPMI_CR_TXDMA | SWPMI_CR_RXDMA)); /* Abort the SWPMI DMA tx channel */ if (hswpmi->hdmatx != NULL) { if (HAL_DMA_Abort(hswpmi->hdmatx) != HAL_OK) { hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA; status = HAL_ERROR; } } /* Abort the SWPMI DMA rx channel */ if (hswpmi->hdmarx != NULL) { if (HAL_DMA_Abort(hswpmi->hdmarx) != HAL_OK) { hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA; status = HAL_ERROR; } } /* Disable SWPMI interface */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); hswpmi->State = HAL_SWPMI_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hswpmi); return status; } /** * @brief Enable the Loopback mode. * @param hswpmi SWPMI handle * @note Loopback mode is to be used only for test purposes * @retval HAL_OK / HAL_BUSY */ HAL_StatusTypeDef HAL_SWPMI_EnableLoopback(SWPMI_HandleTypeDef *hswpmi) { HAL_StatusTypeDef status = HAL_OK; /* Process Locked */ __HAL_LOCK(hswpmi); /* Make sure the SWPMI interface is not enabled to set the loopback mode */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Set Loopback */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK); /* Enable SWPMI interface in loopback mode */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Process Unlocked */ __HAL_UNLOCK(hswpmi); return status; } /** * @brief Disable the Loopback mode. * @param hswpmi SWPMI handle * @note Loopback mode is to be used only for test purposes * @retval HAL_OK / HAL_BUSY */ HAL_StatusTypeDef HAL_SWPMI_DisableLoopback(SWPMI_HandleTypeDef *hswpmi) { HAL_StatusTypeDef status = HAL_OK; /* Process Locked */ __HAL_LOCK(hswpmi); /* Make sure the SWPMI interface is not enabled to reset the loopback mode */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Reset Loopback */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_LPBK); /* Re-enable SWPMI interface in normal mode */ SET_BIT(hswpmi->Instance->CR, SWPMI_CR_SWPACT); /* Process Unlocked */ __HAL_UNLOCK(hswpmi); return status; } /** * @} */ /** @defgroup SWPMI_Exported_Group3 SWPMI IRQ handler and callbacks * @brief SWPMI IRQ handler. * @verbatim ============================================================================== ##### SWPMI IRQ handler and callbacks ##### ============================================================================== [..] This section provides SWPMI IRQ handler and callback functions called within the IRQ handler. @endverbatim * @{ */ /** * @brief Handle SWPMI interrupt request. * @param hswpmi SWPMI handle * @retval None */ void HAL_SWPMI_IRQHandler(SWPMI_HandleTypeDef *hswpmi) { uint32_t regisr = READ_REG(hswpmi->Instance->ISR); uint32_t regier = READ_REG(hswpmi->Instance->IER); uint32_t errcode = HAL_SWPMI_ERROR_NONE; /* SWPMI CRC error interrupt occurred --------------------------------------*/ if (((regisr & SWPMI_FLAG_RXBERF) != 0U) && ((regier & SWPMI_IT_RXBERIE) != 0U)) { /* Disable Receive CRC interrupt */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RXBERIE | SWPMI_IT_RXBFIE); /* Clear Receive CRC and Receive buffer full flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBERF | SWPMI_FLAG_RXBFF); errcode |= HAL_SWPMI_ERROR_CRC; } /* SWPMI Over-Run interrupt occurred -----------------------------------------*/ if (((regisr & SWPMI_FLAG_RXOVRF) != 0U) && ((regier & SWPMI_IT_RXOVRIE) != 0U)) { /* Disable Receive overrun interrupt */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RXOVRIE); /* Clear Receive overrun flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXOVRF); errcode |= HAL_SWPMI_ERROR_OVR; } /* SWPMI Under-Run interrupt occurred -----------------------------------------*/ if (((regisr & SWPMI_FLAG_TXUNRF) != 0U) && ((regier & SWPMI_IT_TXUNRIE) != 0U)) { /* Disable Transmit under run interrupt */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TXUNRIE); /* Clear Transmit under run flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TXUNRF); errcode |= HAL_SWPMI_ERROR_UDR; } /* Call SWPMI Error Call back function if needed --------------------------*/ if (errcode != HAL_SWPMI_ERROR_NONE) { hswpmi->ErrorCode |= errcode; if ((errcode & HAL_SWPMI_ERROR_UDR) != 0U) { /* Check TXDMA transfer to abort */ if (HAL_IS_BIT_SET(hswpmi->Instance->CR, SWPMI_CR_TXDMA)) { /* Disable DMA TX at SWPMI level */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA); /* Abort the USART DMA Tx channel */ if (hswpmi->hdmatx != NULL) { /* Set the SWPMI Tx DMA Abort callback : will lead to call HAL_SWPMI_ErrorCallback() at end of DMA abort procedure */ hswpmi->hdmatx->XferAbortCallback = SWPMI_DMAAbortOnError; /* Abort DMA TX */ if (HAL_DMA_Abort_IT(hswpmi->hdmatx) != HAL_OK) { /* Call Directly hswpmi->hdmatx->XferAbortCallback function in case of error */ hswpmi->hdmatx->XferAbortCallback(hswpmi->hdmatx); } } else { /* Set the SWPMI state ready to be able to start again the process */ hswpmi->State = HAL_SWPMI_STATE_READY; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } } else { /* Set the SWPMI state ready to be able to start again the process */ hswpmi->State = HAL_SWPMI_STATE_READY; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } } else { /* Check RXDMA transfer to abort */ if (HAL_IS_BIT_SET(hswpmi->Instance->CR, SWPMI_CR_RXDMA)) { /* Disable DMA RX at SWPMI level */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA); /* Abort the USART DMA Rx channel */ if (hswpmi->hdmarx != NULL) { /* Set the SWPMI Rx DMA Abort callback : will lead to call HAL_SWPMI_ErrorCallback() at end of DMA abort procedure */ hswpmi->hdmarx->XferAbortCallback = SWPMI_DMAAbortOnError; /* Abort DMA RX */ if (HAL_DMA_Abort_IT(hswpmi->hdmarx) != HAL_OK) { /* Call Directly hswpmi->hdmarx->XferAbortCallback function in case of error */ hswpmi->hdmarx->XferAbortCallback(hswpmi->hdmarx); } } else { /* Set the SWPMI state ready to be able to start again the process */ hswpmi->State = HAL_SWPMI_STATE_READY; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } } else { /* Set the SWPMI state ready to be able to start again the process */ hswpmi->State = HAL_SWPMI_STATE_READY; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } } } /* SWPMI in mode Receiver ---------------------------------------------------*/ if (((regisr & SWPMI_FLAG_RXNE) != 0U) && ((regier & SWPMI_IT_RIE) != 0U)) { SWPMI_Receive_IT(hswpmi); } /* SWPMI in mode Transmitter ------------------------------------------------*/ if (((regisr & SWPMI_FLAG_TXE) != 0U) && ((regier & SWPMI_IT_TIE) != 0U)) { SWPMI_Transmit_IT(hswpmi); } /* SWPMI in mode Transmitter (Transmit buffer empty) ------------------------*/ if (((regisr & SWPMI_FLAG_TXBEF) != 0U) && ((regier & SWPMI_IT_TXBEIE) != 0U)) { SWPMI_EndTransmit_IT(hswpmi); } /* SWPMI in mode Receiver (Receive buffer full) -----------------------------*/ if (((regisr & SWPMI_FLAG_RXBFF) != 0U) && ((regier & SWPMI_IT_RXBFIE) != 0U)) { SWPMI_EndReceive_IT(hswpmi); } /* Both Transmission and reception complete ---------------------------------*/ if (((regisr & SWPMI_FLAG_TCF) != 0U) && ((regier & SWPMI_IT_TCIE) != 0U)) { SWPMI_EndTransmitReceive_IT(hswpmi); } } /** * @brief Tx Transfer completed callback. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_TxCpltCallback(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SWPMI_TxCpltCallback is to be implemented in the user file */ } /** * @brief Tx Half Transfer completed callback. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_TxHalfCpltCallback(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE: This function should not be modified, when the callback is needed, the HAL_SWPMI_TxHalfCpltCallback is to be implemented in the user file */ } /** * @brief Rx Transfer completed callback. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_RxCpltCallback(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SWPMI_RxCpltCallback is to be implemented in the user file */ } /** * @brief Rx Half Transfer completed callback. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_RxHalfCpltCallback(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE: This function should not be modified, when the callback is needed, the HAL_SWPMI_RxHalfCpltCallback is to be implemented in the user file */ } /** * @brief SWPMI error callback. * @param hswpmi SWPMI handle * @retval None */ __weak void HAL_SWPMI_ErrorCallback(SWPMI_HandleTypeDef *hswpmi) { /* Prevent unused argument(s) compilation warning */ UNUSED(hswpmi); /* NOTE : This function should not be modified, when the callback is needed, the HAL_SWPMI_ErrorCallback is to be implemented in the user file */ } /** * @} */ /** @defgroup SWPMI_Exported_Group4 Peripheral Control methods * @brief SWPMI control functions * @verbatim =============================================================================== ##### Peripheral Control methods ##### =============================================================================== [..] This subsection provides a set of functions allowing to control the SWPMI. (+) HAL_SWPMI_GetState() API is helpful to check in run-time the state of the SWPMI peripheral (+) HAL_SWPMI_GetError() API is helpful to check in run-time the error state of the SWPMI peripheral @endverbatim * @{ */ /** * @brief Return the SWPMI handle state. * @param hswpmi SWPMI handle * @retval HAL state */ HAL_SWPMI_StateTypeDef HAL_SWPMI_GetState(const SWPMI_HandleTypeDef *hswpmi) { /* Return SWPMI handle state */ return hswpmi->State; } /** * @brief Return the SWPMI error code. * @param hswpmi : pointer to a SWPMI_HandleTypeDef structure that contains * the configuration information for the specified SWPMI. * @retval SWPMI Error Code */ uint32_t HAL_SWPMI_GetError(const SWPMI_HandleTypeDef *hswpmi) { return hswpmi->ErrorCode; } /** * @} */ /** * @} */ /* Private functions ---------------------------------------------------------*/ /** @defgroup SWPMI_Private_Functions SWPMI Private Functions * @{ */ /** * @brief Transmit an amount of data in interrupt mode. * @note Function called under interruption only, once interruptions have been enabled by HAL_SWPMI_Transmit_IT() * @param hswpmi SWPMI handle * @retval None */ static void SWPMI_Transmit_IT(SWPMI_HandleTypeDef *hswpmi) { HAL_SWPMI_StateTypeDef tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_BUSY_TX) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX_RX)) { if (hswpmi->TxXferCount == 0U) { /* Disable the SWPMI TXE and Underrun Interrupts */ CLEAR_BIT(hswpmi->Instance->IER, (SWPMI_IT_TIE | SWPMI_IT_TXUNRIE)); } else { hswpmi->Instance->TDR = (uint32_t) * hswpmi->pTxBuffPtr; hswpmi->pTxBuffPtr++; hswpmi->TxXferCount--; } } else { /* nothing to do */ } } /** * @brief Wraps up transmission in non-blocking mode. * @param hswpmi SWPMI handle * @retval None */ static void SWPMI_EndTransmit_IT(SWPMI_HandleTypeDef *hswpmi) { /* Clear the SWPMI Transmit buffer empty Flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TXBEF); /* Disable the all SWPMI Transmit Interrupts */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TIE | SWPMI_IT_TXUNRIE | SWPMI_IT_TXBEIE); /* Check if a receive Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->TxCpltCallback(hswpmi); #else HAL_SWPMI_TxCpltCallback(hswpmi); #endif } /** * @brief Receive an amount of data in interrupt mode. * @note Function called under interruption only, once interruptions have been enabled by HAL_SWPMI_Receive_IT() * @param hswpmi SWPMI handle * @retval None */ static void SWPMI_Receive_IT(SWPMI_HandleTypeDef *hswpmi) { HAL_SWPMI_StateTypeDef tmp_state = hswpmi->State; if ((tmp_state == HAL_SWPMI_STATE_BUSY_RX) || (tmp_state == HAL_SWPMI_STATE_BUSY_TX_RX)) { *hswpmi->pRxBuffPtr = (uint32_t)(hswpmi->Instance->RDR); hswpmi->pRxBuffPtr++; --hswpmi->RxXferCount; if (hswpmi->RxXferCount == 0U) { /* Wait for RXBFF flag to update state */ #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->RxCpltCallback(hswpmi); #else HAL_SWPMI_RxCpltCallback(hswpmi); #endif } } else { /* nothing to do */ } } /** * @brief Wraps up reception in non-blocking mode. * @param hswpmi SWPMI handle * @retval None */ static void SWPMI_EndReceive_IT(SWPMI_HandleTypeDef *hswpmi) { /* Clear the SWPMI Receive buffer full Flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_RXBFF); /* Disable the all SWPMI Receive Interrupts */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_RIE | SWPMI_IT_RXBERIE | SWPMI_IT_RXOVRIE | SWPMI_IT_RXBFIE); /* Check if a transmit Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } } /** * @brief Wraps up transmission and reception in non-blocking mode. * @param hswpmi SWPMI handle * @retval None */ static void SWPMI_EndTransmitReceive_IT(SWPMI_HandleTypeDef *hswpmi) { /* Clear the SWPMI Transmission Complete Flag */ WRITE_REG(hswpmi->Instance->ICR, SWPMI_FLAG_TCF); /* Disable the SWPMI Transmission Complete Interrupt */ CLEAR_BIT(hswpmi->Instance->IER, SWPMI_IT_TCIE); /* Check if a receive Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; } else if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX) { hswpmi->State = HAL_SWPMI_STATE_READY; } else { /* nothing to do */ } } /** * @brief DMA SWPMI transmit process complete callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMATransmitCplt(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; uint32_t tickstart; /* DMA Normal mode*/ if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) { hswpmi->TxXferCount = 0U; /* Disable the DMA transfer for transmit request by setting the TXDMA bit in the SWPMI CR register */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_TXDMA); /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); /* Wait the TXBEF */ if (SWPMI_WaitOnFlagSetUntilTimeout(hswpmi, SWPMI_FLAG_TXBEF, tickstart, SWPMI_TIMEOUT_VALUE) != HAL_OK) { /* Timeout occurred */ hswpmi->ErrorCode |= HAL_SWPMI_ERROR_TXBEF_TIMEOUT; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } else { /* No Timeout */ /* Check if a receive process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_RX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->TxCpltCallback(hswpmi); #else HAL_SWPMI_TxCpltCallback(hswpmi); #endif } } /* DMA Circular mode */ else { #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->TxCpltCallback(hswpmi); #else HAL_SWPMI_TxCpltCallback(hswpmi); #endif } } /** * @brief DMA SWPMI transmit process half complete callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->TxHalfCpltCallback(hswpmi); #else HAL_SWPMI_TxHalfCpltCallback(hswpmi); #endif } /** * @brief DMA SWPMI receive process complete callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMAReceiveCplt(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* DMA Normal mode*/ if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) { hswpmi->RxXferCount = 0U; /* Disable the DMA transfer for the receiver request by setting the RXDMA bit in the SWPMI CR register */ CLEAR_BIT(hswpmi->Instance->CR, SWPMI_CR_RXDMA); /* Check if a transmit Process is ongoing or not */ if (hswpmi->State == HAL_SWPMI_STATE_BUSY_TX_RX) { hswpmi->State = HAL_SWPMI_STATE_BUSY_TX; } else { hswpmi->State = HAL_SWPMI_STATE_READY; } } #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->RxCpltCallback(hswpmi); #else HAL_SWPMI_RxCpltCallback(hswpmi); #endif } /** * @brief DMA SWPMI receive process half complete callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->RxHalfCpltCallback(hswpmi); #else HAL_SWPMI_RxHalfCpltCallback(hswpmi); #endif } /** * @brief DMA SWPMI communication error callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMAError(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Update handle */ hswpmi->RxXferCount = 0U; hswpmi->TxXferCount = 0U; hswpmi->State = HAL_SWPMI_STATE_READY; hswpmi->ErrorCode |= HAL_SWPMI_ERROR_DMA; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } /** * @brief DMA SWPMI communication abort callback. * @param hdma DMA handle * @retval None */ static void SWPMI_DMAAbortOnError(DMA_HandleTypeDef *hdma) { SWPMI_HandleTypeDef *hswpmi = (SWPMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Update handle */ hswpmi->RxXferCount = 0U; hswpmi->TxXferCount = 0U; hswpmi->State = HAL_SWPMI_STATE_READY; #if (USE_HAL_SWPMI_REGISTER_CALLBACKS == 1) hswpmi->ErrorCallback(hswpmi); #else HAL_SWPMI_ErrorCallback(hswpmi); #endif } /** * @brief Handle SWPMI Communication Timeout. * @param hswpmi SWPMI handle * @param Flag specifies the SWPMI flag to check. * @param Tickstart Tick start value * @param Timeout timeout duration. * @retval HAL status */ static HAL_StatusTypeDef SWPMI_WaitOnFlagSetUntilTimeout(SWPMI_HandleTypeDef *hswpmi, uint32_t Flag, uint32_t Tickstart, uint32_t Timeout) { HAL_StatusTypeDef status = HAL_OK; /* Wait until flag is set */ while (!(HAL_IS_BIT_SET(hswpmi->Instance->ISR, Flag))) { /* Check for the Timeout */ if ((((HAL_GetTick() - Tickstart) > Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) { /* Set the SWPMI state ready to be able to start again the process */ hswpmi->State = HAL_SWPMI_STATE_READY; status = HAL_TIMEOUT; break; } } return status; } /** * @} */ #endif /* HAL_SWPMI_MODULE_ENABLED */ /** * @} */ #endif /* SWPMI1 */ /** * @} */