text: /**
    ******************************************************************************
    * @file    stm32h7xx_hal_pssi.c
    * @author  MCD Application Team
    * @brief   PSSI HAL module driver.
    *          This file provides firmware functions to manage the following
    *          functionalities of the Parallel Synchronous Slave Interface (PSSI) peripheral:
    *           + Initialization and de-initialization functions
    *           + IO operation functions
    *           + Peripheral State and Errors functions
    *
    ******************************************************************************
    * @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 PSSI HAL driver can be used as follows:
  
      (#) Declare a PSSI_HandleTypeDef handle structure, for example:
          PSSI_HandleTypeDef  hpssi;
  
      (#) Initialize the PSSI low level resources by implementing the HAL_PSSI_MspInit() API:
          (##) Enable the PSSIx interface clock
          (##) PSSI pins configuration
              (+++) Enable the clock for the PSSI GPIOs
              (+++) Configure PSSI pins as alternate function open-drain
          (##) NVIC configuration if you need to use interrupt process
              (+++) Configure the PSSIx interrupt priority
              (+++) Enable the NVIC PSSI IRQ Channel
          (##) DMA Configuration if you need to use DMA process
              (+++) Declare  DMA_HandleTypeDef handles structure for the transmit and receive
              (+++) Enable the DMAx interface clock
              (+++) Configure the DMA handle parameters
              (+++) Configure the DMA Tx and Rx
              (+++) Associate the initialized DMA handle to the hpssi DMA Tx and Rx handle
              (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on
                    the DMA Tx and Rx
  
      (#) Configure the Communication Bus Width,  Control Signals, Input Polarity and Output Polarity
           in the hpssi Init structure.
  
      (#) Initialize the PSSI registers by calling the HAL_PSSI_Init(), configure also the low level Hardware
          (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_PSSI_MspInit(&hpssi) API.
  
  
      (#) For PSSI IO operations, two operation modes are available within this driver :
  
      *** Polling mode IO operation ***
      =================================
      [..]
        (+) Transmit an amount of data by byte in blocking mode using HAL_PSSI_Transmit()
        (+) Receive an amount of data by byte in blocking mode using HAL_PSSI_Receive()
  
      *** DMA mode IO operation ***
      ==============================
      [..]
        (+) Transmit an amount of data in non-blocking mode (DMA) using
            HAL_PSSI_Transmit_DMA()
        (+) At transmission end of transfer, HAL_PSSI_TxCpltCallback() is executed and user can
             add his own code by customization of function pointer HAL_PSSI_TxCpltCallback()
        (+) Receive an amount of data in non-blocking mode (DMA) using
            HAL_PSSI_Receive_DMA()
        (+) At reception end of transfer, HAL_PSSI_RxCpltCallback() is executed and user can
             add his own code by customization of function pointer HAL_PSSI_RxCpltCallback()
        (+) In case of transfer Error, HAL_PSSI_ErrorCallback() function is executed and user can
             add his own code by customization of function pointer HAL_PSSI_ErrorCallback()
        (+) Abort a  PSSI process communication with Interrupt using HAL_PSSI_Abort_IT()
        (+) End of abort process, HAL_PSSI_AbortCpltCallback() is executed and user can
             add his own code by customization of function pointer HAL_PSSI_AbortCpltCallback()
  
       *** PSSI HAL driver macros list ***
       ==================================
       [..]
         Below the list of most used macros in PSSI HAL driver.
  
        (+) HAL_PSSI_ENABLE     : Enable the PSSI peripheral
        (+) HAL_PSSI_DISABLE    : Disable the PSSI peripheral
        (+) HAL_PSSI_GET_FLAG   : Check whether the specified PSSI flag is set or not
        (+) HAL_PSSI_CLEAR_FLAG : Clear the specified PSSI pending flag
        (+) HAL_PSSI_ENABLE_IT  : Enable the specified PSSI interrupt
        (+) HAL_PSSI_DISABLE_IT : Disable the specified PSSI interrupt
  
       *** Callback registration ***
       =============================================
       Use Functions HAL_PSSI_RegisterCallback() or HAL_PSSI_RegisterAddrCallback()
       to register an interrupt callback.
  
       Function HAL_PSSI_RegisterCallback() allows to register following callbacks:
         (+) TxCpltCallback       : callback for transmission end of transfer.
         (+) RxCpltCallback       : callback for reception end of transfer.
         (+) ErrorCallback        : callback for error detection.
         (+) AbortCpltCallback    : callback for abort completion process.
         (+) MspInitCallback      : callback for Msp Init.
         (+) MspDeInitCallback    : callback for Msp DeInit.
       This function takes as parameters the HAL peripheral handle, the Callback ID
       and a pointer to the user callback function.
  
  
       Use function HAL_PSSI_UnRegisterCallback to reset a callback to the default
       weak function.
       HAL_PSSI_UnRegisterCallback takes as parameters the HAL peripheral handle,
       and the Callback ID.
       This function allows to reset following callbacks:
         (+) TxCpltCallback       : callback for transmission end of transfer.
         (+) RxCpltCallback       : callback for reception end of transfer.
         (+) ErrorCallback        : callback for error detection.
         (+) AbortCpltCallback    : callback for abort completion process.
         (+) MspInitCallback      : callback for Msp Init.
         (+) MspDeInitCallback    : callback for Msp DeInit.
  
  
       By default, after the HAL_PSSI_Init() and when the state is HAL_PSSI_STATE_RESET
       all callbacks are set to the corresponding weak functions:
       examples HAL_PSSI_TxCpltCallback(), HAL_PSSI_RxCpltCallback().
       Exception done for MspInit and MspDeInit functions that are
       reset to the legacy weak functions in the HAL_PSSI_Init()/ HAL_PSSI_DeInit() only when
       these callbacks are null (not registered beforehand).
       If MspInit or MspDeInit are not null, the HAL_PSSI_Init()/ HAL_PSSI_DeInit()
       keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
  
       Callbacks can be registered/unregistered in HAL_PSSI_STATE_READY state only.
       Exception done MspInit/MspDeInit functions that can be registered/unregistered
       in HAL_PSSI_STATE_READY or HAL_PSSI_STATE_RESET state,
       thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
       Then, the user first registers the MspInit/MspDeInit user callbacks
       using HAL_PSSI_RegisterCallback() before calling HAL_PSSI_DeInit()
       or HAL_PSSI_Init() function.
  
  
       [..]
         (@) You can refer to the PSSI HAL driver header file for more useful macros
  
    @endverbatim
    ******************************************************************************
    */
  
  /* Includes ------------------------------------------------------------------*/
  #include "stm32h7xx_hal.h"
  
  /** @addtogroup STM32H7xx_HAL_Driver
    * @{
    */
  
  /** @defgroup PSSI PSSI
    * @brief PSSI HAL module driver
    * @{
    */
  
  #ifdef HAL_PSSI_MODULE_ENABLED
  #if defined(PSSI)
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  
  /** @defgroup PSSI_Private_Define PSSI Private Define
    * @{
    */
  
  
  
  /**
    * @}
    */
  
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  /* Private function prototypes -----------------------------------------------*/
  
  /** @defgroup PSSI_Private_Functions PSSI Private Functions
    * @{
    */
  /* Private functions to handle DMA transfer */
  void PSSI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
  void PSSI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
  void PSSI_DMAError(DMA_HandleTypeDef *hdma);
  void PSSI_DMAAbort(DMA_HandleTypeDef *hdma);
  
  
  /* Private functions to handle IT transfer */
  static void PSSI_Error(PSSI_HandleTypeDef *hpssi, uint32_t ErrorCode);
  
  /* Private functions to handle flags during polling transfer */
  static HAL_StatusTypeDef PSSI_WaitOnStatusUntilTimeout(PSSI_HandleTypeDef *hpssi, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart);
  
  /**
    * @}
    */
  
  /* Exported functions --------------------------------------------------------*/
  
  /** @defgroup PSSI_Exported_Functions PSSI Exported Functions
    * @{
    */
  
  /** @defgroup PSSI_Exported_Functions_Group1 Initialization and de-initialization functions
   *  @brief    Initialization and Configuration functions
   *
  @verbatim
   ===============================================================================
                ##### Initialization and de-initialization functions #####
   ===============================================================================
      [..]  This subsection provides a set of functions allowing to initialize and
            deinitialize the PSSIx peripheral:
  
        (+) User must implement HAL_PSSI_MspInit() function in which he configures
            all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
  
        (+) Call the function HAL_PSSI_Init() to configure the selected device with
            the selected configuration:
          (++) Data Width
          (++) Control Signals
          (++) Input Clock polarity
          (++) Output Clock polarity
  
        (+) Call the function HAL_PSSI_DeInit() to restore the default configuration
            of the selected PSSIx peripheral.
  
  @endverbatim
    * @{
    */
  
  /**
    * @brief  Initializes the PSSI according to the specified parameters
    *         in the PSSI_InitTypeDef and initialize the associated handle.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Init(PSSI_HandleTypeDef *hpssi)
  {
    /* Check the PSSI handle allocation */
    if (hpssi == NULL)
    {
      return HAL_ERROR;
    }
  
    /* Check the parameters */
    assert_param(IS_PSSI_ALL_INSTANCE(hpssi->Instance));
    assert_param(IS_PSSI_CONTROL_SIGNAL(hpssi->Init.ControlSignal));
    assert_param(IS_PSSI_BUSWIDTH(hpssi->Init.BusWidth));
    assert_param(IS_PSSI_CLOCK_POLARITY(hpssi->Init.ClockPolarity));
    assert_param(IS_PSSI_DE_POLARITY(hpssi->Init.DataEnablePolarity));
    assert_param(IS_PSSI_RDY_POLARITY(hpssi->Init.ReadyPolarity));
  
    if (hpssi->State == HAL_PSSI_STATE_RESET)
    {
      /* Allocate lock resource and initialize it */
      hpssi->Lock = HAL_UNLOCKED;
  
      /* Init the PSSI Callback settings */
      hpssi->TxCpltCallback = HAL_PSSI_TxCpltCallback; /* Legacy weak TxCpltCallback */
      hpssi->RxCpltCallback = HAL_PSSI_RxCpltCallback; /* Legacy weak RxCpltCallback */
      hpssi->ErrorCallback        = HAL_PSSI_ErrorCallback;        /* Legacy weak ErrorCallback        */
      hpssi->AbortCpltCallback    = HAL_PSSI_AbortCpltCallback;    /* Legacy weak AbortCpltCallback    */
  
      if (hpssi->MspInitCallback == NULL)
      {
        hpssi->MspInitCallback = HAL_PSSI_MspInit; /* Legacy weak MspInit  */
      }
  
      /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
      hpssi->MspInitCallback(hpssi);
  
    }
  
    hpssi->State = HAL_PSSI_STATE_BUSY;
  
    /* Disable the selected PSSI peripheral */
    HAL_PSSI_DISABLE(hpssi);
  
    /*---------------------------- PSSIx CR Configuration ----------------------*/
    /* Configure PSSIx: Control Signal and Bus Width*/
  
    MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DERDYCFG|PSSI_CR_EDM|PSSI_CR_DEPOL|PSSI_CR_RDYPOL,
               hpssi->Init.ControlSignal|hpssi->Init.DataEnablePolarity|hpssi->Init.ReadyPolarity|hpssi->Init.BusWidth);
  
    hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
    hpssi->State = HAL_PSSI_STATE_READY;
  
    return HAL_OK;
  }
  
  /**
    * @brief  DeInitialize the PSSI peripheral.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_DeInit(PSSI_HandleTypeDef *hpssi)
  {
    /* Check the PSSI handle allocation */
    if (hpssi == NULL)
    {
      return HAL_ERROR;
    }
  
    /* Check the parameters */
    assert_param(IS_PSSI_ALL_INSTANCE(hpssi->Instance));
  
    hpssi->State = HAL_PSSI_STATE_BUSY;
  
    /* Disable the PSSI Peripheral Clock */
    HAL_PSSI_DISABLE(hpssi);
  
    if (hpssi->MspDeInitCallback == NULL)
    {
      hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit; /* Legacy weak MspDeInit  */
    }
  
    /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
    hpssi->MspDeInitCallback(hpssi);
  
    hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
    hpssi->State = HAL_PSSI_STATE_RESET;
  
    /* Release Lock */
    __HAL_UNLOCK(hpssi);
  
    return HAL_OK;
  }
  
  /**
    * @brief Initialize the PSSI MSP.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_MspInit(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_MspInit can be implemented in the user file
     */
  }
  
  /**
    * @brief DeInitialize the PSSI MSP.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_MspDeInit(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_MspDeInit can be implemented in the user file
     */
  }
  
  /**
    * @brief  Register a User PSSI Callback
    *         To be used instead of the weak predefined callback
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  CallbackID ID of the callback to be registered
    *         This parameter can be one of the following values:
    *          @arg @ref HAL_PSSI_TX_COMPLETE_CB_ID  Tx Transfer completed callback ID
    *          @arg @ref HAL_PSSI_RX_COMPLETE_CB_ID  Rx Transfer completed callback ID
    *          @arg @ref HAL_PSSI_ERROR_CB_ID Error callback ID
    *          @arg @ref HAL_PSSI_ABORT_CB_ID Abort callback ID
    *          @arg @ref HAL_PSSI_MSPINIT_CB_ID MspInit callback ID
    *          @arg @ref HAL_PSSI_MSPDEINIT_CB_ID MspDeInit callback ID
    * @param  pCallback pointer to the Callback function
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_RegisterCallback(PSSI_HandleTypeDef *hpssi, HAL_PSSI_CallbackIDTypeDef CallbackID, pPSSI_CallbackTypeDef pCallback)
  {
    HAL_StatusTypeDef status = HAL_OK;
  
    if (pCallback == NULL)
    {
      /* Update the error code */
      hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
      return HAL_ERROR;
    }
    /* Process locked */
    __HAL_LOCK(hpssi);
  
    if (HAL_PSSI_STATE_READY == hpssi->State)
    {
      switch (CallbackID)
      {
        case HAL_PSSI_TX_COMPLETE_CB_ID :
          hpssi->TxCpltCallback = pCallback;
          break;
  
        case HAL_PSSI_RX_COMPLETE_CB_ID :
          hpssi->RxCpltCallback = pCallback;
          break;
  
        case HAL_PSSI_ERROR_CB_ID :
          hpssi->ErrorCallback = pCallback;
          break;
  
        case HAL_PSSI_ABORT_CB_ID :
          hpssi->AbortCpltCallback = pCallback;
          break;
  
        case HAL_PSSI_MSPINIT_CB_ID :
          hpssi->MspInitCallback = pCallback;
          break;
  
        case HAL_PSSI_MSPDEINIT_CB_ID :
          hpssi->MspDeInitCallback = pCallback;
          break;
  
        default :
          /* Update the error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
          /* Return error status */
          status =  HAL_ERROR;
          break;
      }
    }
    else if (HAL_PSSI_STATE_RESET == hpssi->State)
    {
      switch (CallbackID)
      {
        case HAL_PSSI_MSPINIT_CB_ID :
          hpssi->MspInitCallback = pCallback;
          break;
  
        case HAL_PSSI_MSPDEINIT_CB_ID :
          hpssi->MspDeInitCallback = pCallback;
          break;
  
        default :
          /* Update the error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
          /* Return error status */
          status =  HAL_ERROR;
          break;
      }
    }
    else
    {
      /* Update the error code */
      hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
      /* Return error status */
      status =  HAL_ERROR;
    }
  
    /* Release Lock */
    __HAL_UNLOCK(hpssi);
    return status;
  }
  
  /**
    * @brief  Unregister an PSSI Callback
    *         PSSI callback is redirected to the weak predefined callback
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  CallbackID ID of the callback to be unregistered
    *         This parameter can be one of the following values:
    *          @arg @ref HAL_PSSI_TX_COMPLETE_CB_ID  Tx Transfer completed callback ID
    *          @arg @ref HAL_PSSI_RX_COMPLETE_CB_ID  Rx Transfer completed callback ID
    *          @arg @ref HAL_PSSI_ERROR_CB_ID Error callback ID
    *          @arg @ref HAL_PSSI_ABORT_CB_ID Abort callback ID
    *          @arg @ref HAL_PSSI_MSPINIT_CB_ID MspInit callback ID
    *          @arg @ref HAL_PSSI_MSPDEINIT_CB_ID MspDeInit callback ID
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_UnRegisterCallback(PSSI_HandleTypeDef *hpssi, HAL_PSSI_CallbackIDTypeDef CallbackID)
  {
    HAL_StatusTypeDef status = HAL_OK;
  
    /* Process locked */
    __HAL_LOCK(hpssi);
  
    if (HAL_PSSI_STATE_READY == hpssi->State)
    {
      switch (CallbackID)
      {
        case HAL_PSSI_TX_COMPLETE_CB_ID :
          hpssi->TxCpltCallback = HAL_PSSI_TxCpltCallback; /* Legacy weak TxCpltCallback */
          break;
  
        case HAL_PSSI_RX_COMPLETE_CB_ID :
          hpssi->RxCpltCallback = HAL_PSSI_RxCpltCallback;   /* Legacy weak RxCpltCallback  */
          break;
  
        case HAL_PSSI_ERROR_CB_ID :
          hpssi->ErrorCallback = HAL_PSSI_ErrorCallback;               /* Legacy weak ErrorCallback        */
          break;
  
        case HAL_PSSI_ABORT_CB_ID :
          hpssi->AbortCpltCallback = HAL_PSSI_AbortCpltCallback;       /* Legacy weak AbortCpltCallback    */
          break;
  
        case HAL_PSSI_MSPINIT_CB_ID :
          hpssi->MspInitCallback = HAL_PSSI_MspInit;                   /* Legacy weak MspInit              */
          break;
  
        case HAL_PSSI_MSPDEINIT_CB_ID :
          hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit;               /* Legacy weak MspDeInit            */
          break;
  
        default :
          /* Update the error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
          /* Return error status */
          status =  HAL_ERROR;
          break;
      }
    }
    else if (HAL_PSSI_STATE_RESET == hpssi->State)
    {
      switch (CallbackID)
      {
        case HAL_PSSI_MSPINIT_CB_ID :
          hpssi->MspInitCallback = HAL_PSSI_MspInit;                   /* Legacy weak MspInit              */
          break;
  
        case HAL_PSSI_MSPDEINIT_CB_ID :
          hpssi->MspDeInitCallback = HAL_PSSI_MspDeInit;               /* Legacy weak MspDeInit            */
          break;
  
        default :
          /* Update the error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
          /* Return error status */
          status =  HAL_ERROR;
          break;
      }
    }
    else
    {
      /* Update the error code */
      hpssi->ErrorCode |= HAL_PSSI_ERROR_INVALID_CALLBACK;
  
      /* Return error status */
      status =  HAL_ERROR;
    }
  
    /* Release Lock */
    __HAL_UNLOCK(hpssi);
    return status;
  }
  
  
  /**
    * @}
    */
  
  /** @defgroup PSSI_Exported_Functions_Group2 Input and Output operation functions
   *  @brief   Data transfers functions
   *
  @verbatim
   ===============================================================================
                        ##### IO operation functions #####
   ===============================================================================
      [..]
      This subsection provides a set of functions allowing to manage the PSSI data
      transfers.
  
      (#) There are two modes of transfer:
         (++) Blocking mode : The communication is performed in the polling mode.
              The status of all data processing is returned by the same function
              after finishing transfer.
         (++) No-Blocking mode : The communication is performed using DMA.
              These functions return the status of the transfer startup.
              The end of the data processing will be indicated through the
              dedicated  the DMA IRQ .
  
      (#) Blocking mode functions are :
          (++) HAL_PSSI_Transmit()
          (++) HAL_PSSI_Receive()
  
      (#) No-Blocking mode functions with DMA are :
          (++) HAL_PSSI_Transmit_DMA()
          (++) HAL_PSSI_Receive_DMA()
  
      (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
          (++) HAL_PSSI_TxCpltCallback()
          (++) HAL_PSSI_RxCpltCallback()
          (++) HAL_PSSI_ErrorCallback()
          (++) HAL_PSSI_AbortCpltCallback()
  
  @endverbatim
    * @{
    */
  
  /**
    * @brief  Transmits in master mode an amount of data in blocking mode.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  pData Pointer to data buffer
    * @param  Size Amount of data to be sent (in bytes)
    * @param  Timeout Timeout duration
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Transmit(PSSI_HandleTypeDef *hpssi, uint8_t *pData, uint32_t Size, uint32_t Timeout)
  {
    uint32_t tickstart;
    uint32_t  transfer_size = Size;
  
  #if defined (__GNUC__)
    __IO uint16_t *pdr_16bits = (__IO uint16_t *)(&(hpssi->Instance->DR));
  #endif /* __GNUC__ */
  
    if (((hpssi->Init.DataWidth == HAL_PSSI_8BITS) && (hpssi->Init.BusWidth != HAL_PSSI_8LINES)) ||
        ((hpssi->Init.DataWidth == HAL_PSSI_16BITS) && ((Size%2U) != 0U)) ||
        ((hpssi->Init.DataWidth == HAL_PSSI_32BITS) && ((Size%4U) != 0U)))
    {
      hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
      return HAL_ERROR;
    }
    if (hpssi->State == HAL_PSSI_STATE_READY)
    {
      /* Process Locked */
      __HAL_LOCK(hpssi);
  
      hpssi->State     = HAL_PSSI_STATE_BUSY;
      hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
  
      /* Disable the selected PSSI peripheral */
      HAL_PSSI_DISABLE(hpssi);
  
      /* Configure transfer parameters */
      hpssi->Instance->CR |= PSSI_CR_OUTEN_OUTPUT |
        ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL);
      /* DMA Disable */
      hpssi->Instance->CR &= PSSI_CR_DMA_DISABLE;
  
      /* Enable the selected PSSI peripheral */
      HAL_PSSI_ENABLE(hpssi);
  
      if (hpssi->Init.DataWidth == HAL_PSSI_8BITS)
      {
        uint8_t *pbuffer = pData;
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to transfer one byte flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT1B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
          /* Write data to DR */
          *(__IO uint8_t *)(&hpssi->Instance->DR) = *(uint8_t *)pbuffer;
  
          /* Increment Buffer pointer */
          pbuffer++;
  
          transfer_size--;
        }
      }
      else if (hpssi->Init.DataWidth == HAL_PSSI_16BITS)
      {
        uint16_t *pbuffer = (uint16_t *)pData;
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to transfer four bytes flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
          /* Write data to DR */
  #if defined (__GNUC__)
          *pdr_16bits = *pbuffer;
  #else
          *(__IO uint16_t *)((uint32_t)(&hpssi->Instance->DR)) = *pbuffer;
  #endif /* __GNUC__ */
  
          /* Increment Buffer pointer */
          pbuffer++;
          transfer_size -= 2U;
  
        }
      }
      else if (hpssi->Init.DataWidth == HAL_PSSI_32BITS)
      {
        uint32_t *pbuffer = (uint32_t *)pData;
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to transfer four bytes flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
          /* Write data to DR */
          *(__IO uint32_t *)(&hpssi->Instance->DR) = *pbuffer;
  
          /* Increment Buffer pointer */
          pbuffer++;
          transfer_size -= 4U;
        }
  
      }
      else
      {
        hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
        hpssi->State = HAL_PSSI_STATE_READY;
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
        return HAL_ERROR;
      }
  
      /* Check Errors Flags */
      if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_RIS) != 0U)
      {
        HAL_PSSI_CLEAR_FLAG(hpssi, PSSI_FLAG_OVR_RIS);
        HAL_PSSI_DISABLE(hpssi);
        hpssi->ErrorCode = HAL_PSSI_ERROR_UNDER_RUN;
        hpssi->State = HAL_PSSI_STATE_READY;
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
        return HAL_ERROR;
      }
  
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      return HAL_OK;
    }
    else
    {
      return HAL_BUSY;
    }
  }
  
  
  /**
    * @brief  Receives an amount of data in blocking mode.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  pData Pointer to data buffer
    * @param  Size Amount of data to be received (in bytes)
    * @param  Timeout Timeout duration
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Receive(PSSI_HandleTypeDef *hpssi, uint8_t *pData, uint32_t Size, uint32_t Timeout)
  {
    uint32_t tickstart;
    uint32_t  transfer_size = Size;
  #if defined (__GNUC__)
    __IO uint16_t *pdr_16bits = (__IO uint16_t *)(&(hpssi->Instance->DR));
  #endif /* __GNUC__ */
  
    if (((hpssi->Init.DataWidth == HAL_PSSI_8BITS) && (hpssi->Init.BusWidth != HAL_PSSI_8LINES)) ||
        ((hpssi->Init.DataWidth == HAL_PSSI_16BITS) && ((Size%2U) != 0U)) ||
        ((hpssi->Init.DataWidth == HAL_PSSI_32BITS) && ((Size%4U) != 0U)))
    {
      hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
      return HAL_ERROR;
    }
  
    if (hpssi->State == HAL_PSSI_STATE_READY)
    {
      /* Process Locked */
      __HAL_LOCK(hpssi);
  
      hpssi->State     = HAL_PSSI_STATE_BUSY;
      hpssi->ErrorCode = HAL_PSSI_ERROR_NONE;
  
      /* Disable the selected PSSI peripheral */
      HAL_PSSI_DISABLE(hpssi);
      /* Configure transfer parameters */
      hpssi->Instance->CR |= PSSI_CR_OUTEN_INPUT |((hpssi->Init.ClockPolarity == HAL_PSSI_FALLING_EDGE)?0U:PSSI_CR_CKPOL);
  
  
      /* DMA Disable */
      hpssi->Instance->CR &= PSSI_CR_DMA_DISABLE;
  
      /* Enable the selected PSSI peripheral */
      HAL_PSSI_ENABLE(hpssi);
      if (hpssi->Init.DataWidth == HAL_PSSI_8BITS)
      {
        uint8_t *pbuffer = pData;
  
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to receive one byte flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT1B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
          /* Read data from DR */
          *pbuffer = *(__IO uint8_t *)(&hpssi->Instance->DR);
          pbuffer++;
          transfer_size--;
        }
      }
      else if (hpssi->Init.DataWidth == HAL_PSSI_16BITS)
      {
        uint16_t *pbuffer = (uint16_t *)pData;
  
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to receive four bytes flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
  
          /* Read data from DR */
  #if defined (__GNUC__)
          *pbuffer = *pdr_16bits;
  #else
          *pbuffer = *(__IO uint16_t *)((uint32_t)&hpssi->Instance->DR);
  #endif /* __GNUC__ */
  
          pbuffer++;
          transfer_size -= 2U;
  
        }
      }
      else if (hpssi->Init.DataWidth == HAL_PSSI_32BITS)
      {
        uint32_t *pbuffer = (uint32_t *)pData;
  
        while (transfer_size > 0U)
        {
          /* Init tickstart for timeout management*/
          tickstart = HAL_GetTick();
          /* Wait until Fifo is ready to receive four bytes flag is set */
          if (PSSI_WaitOnStatusUntilTimeout(hpssi, PSSI_FLAG_RTT4B, RESET, Timeout, tickstart) != HAL_OK)
          {
            hpssi->ErrorCode = HAL_PSSI_ERROR_TIMEOUT;
            hpssi->State = HAL_PSSI_STATE_READY;
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
            return HAL_ERROR;
          }
  
          /* Read data from DR */
          *pbuffer = *(__IO uint32_t *)(&hpssi->Instance->DR);
          pbuffer++;
          transfer_size -= 4U;
  
        }
      }
      else
      {
        hpssi->ErrorCode = HAL_PSSI_ERROR_NOT_SUPPORTED;
        hpssi->State = HAL_PSSI_STATE_READY;
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
        return HAL_ERROR;
      }
      /* Check Errors Flags */
  
      if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_RIS) != 0U)
      {
        HAL_PSSI_CLEAR_FLAG(hpssi, PSSI_FLAG_OVR_RIS);
        hpssi->ErrorCode = HAL_PSSI_ERROR_OVER_RUN;
        __HAL_UNLOCK(hpssi);
        return HAL_ERROR;
      }
  
  
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      return HAL_OK;
    }
    else
    {
      return HAL_BUSY;
    }
  }
  
  /**
    * @brief  Transmit an amount of data in non-blocking mode with DMA
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  pData Pointer to data buffer
    * @param  Size Amount of data to be sent (in bytes)
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Transmit_DMA(PSSI_HandleTypeDef *hpssi, uint32_t *pData, uint32_t Size)
  {
    HAL_StatusTypeDef dmaxferstatus;
  
    if (hpssi->State == HAL_PSSI_STATE_READY)
    {
  
      /* Process Locked */
      __HAL_LOCK(hpssi);
  
      hpssi->State       = HAL_PSSI_STATE_BUSY_TX;
      hpssi->ErrorCode   = HAL_PSSI_ERROR_NONE;
  
      /* Disable the selected PSSI peripheral */
      HAL_PSSI_DISABLE(hpssi);
  
      /* Prepare transfer parameters */
      hpssi->pBuffPtr    = pData;
      hpssi->XferCount   = Size;
  
      if (hpssi->XferCount > PSSI_MAX_NBYTE_SIZE)
      {
        hpssi->XferSize = PSSI_MAX_NBYTE_SIZE;
      }
      else
      {
        hpssi->XferSize = hpssi->XferCount;
      }
  
      if (hpssi->XferSize > 0U)
      {
        if (hpssi->hdmatx != NULL)
        {
  
          /* Configure BusWidth */
          if( hpssi->hdmatx->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
          {
            MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | PSSI_CR_OUTEN_OUTPUT |
                       ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL));
          }
          else
          {
            MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | hpssi->Init.BusWidth | PSSI_CR_OUTEN_OUTPUT |
                       ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?0U:PSSI_CR_CKPOL));
          }
  
          /* Set the PSSI DMA transfer complete callback */
          hpssi->hdmatx->XferCpltCallback = PSSI_DMATransmitCplt;
  
          /* Set the DMA error callback */
          hpssi->hdmatx->XferErrorCallback = PSSI_DMAError;
  
          /* Set the unused DMA callbacks to NULL */
          hpssi->hdmatx->XferHalfCpltCallback = NULL;
          hpssi->hdmatx->XferAbortCallback = NULL;
  
          /* Enable the DMA  */
          dmaxferstatus = HAL_DMA_Start_IT(hpssi->hdmatx, (uint32_t)pData, (uint32_t)&hpssi->Instance->DR, hpssi->XferSize);
        }
        else
        {
          /* Update PSSI state */
          hpssi->State     = HAL_PSSI_STATE_READY;
  
          /* Update PSSI error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          return HAL_ERROR;
        }
  
        if (dmaxferstatus == HAL_OK)
        {
  
  
          /* Update XferCount value */
          hpssi->XferCount -= hpssi->XferSize;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          /* Note : The PSSI interrupts must be enabled after unlocking current process
                    to avoid the risk of PSSI interrupt handle execution before current
                    process unlock */
          /* Enable ERR interrupt */
          HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
          /* Enable DMA Request */
          hpssi->Instance->CR |= PSSI_CR_DMA_ENABLE;
          /* Enable the selected PSSI peripheral */
          HAL_PSSI_ENABLE(hpssi);
        }
        else
        {
          /* Update PSSI state */
          hpssi->State     = HAL_PSSI_STATE_READY;
  
          /* Update PSSI error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          return HAL_ERROR;
        }
      }
      else
      {
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
  
        /* Note : The PSSI interrupts must be enabled after unlocking current process
                  to avoid the risk of PSSI interrupt handle execution before current
                  process unlock */
        /* Enable ERRinterrupt */
        /* possible to enable all of these */
  
        HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
      }
  
      return HAL_OK;
    }
    else
    {
      return HAL_BUSY;
    }
  }
  
  /**
    * @brief  Receive an amount of data in non-blocking mode with DMA
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  pData Pointer to data buffer
    * @param  Size Amount of data to be received (in bytes)
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Receive_DMA(PSSI_HandleTypeDef *hpssi, uint32_t *pData, uint32_t Size)
  {
  
    HAL_StatusTypeDef dmaxferstatus;
  
    if (hpssi->State == HAL_PSSI_STATE_READY)
    {
  
      /* Disable the selected PSSI peripheral */
      HAL_PSSI_DISABLE(hpssi);
      /* Process Locked */
      __HAL_LOCK(hpssi);
  
      hpssi->State       = HAL_PSSI_STATE_BUSY_RX;
      hpssi->ErrorCode   = HAL_PSSI_ERROR_NONE;
  
      /* Prepare transfer parameters */
      hpssi->pBuffPtr    = pData;
      hpssi->XferCount   = Size;
  
      if (hpssi->XferCount > PSSI_MAX_NBYTE_SIZE)
      {
        hpssi->XferSize = PSSI_MAX_NBYTE_SIZE;
      }
      else
      {
        hpssi->XferSize = hpssi->XferCount;
      }
  
      if (hpssi->XferSize > 0U)
      {
        if (hpssi->hdmarx != NULL)
        {
  
          /* Configure BusWidth */
          if( hpssi->hdmatx->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
          {
            MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE |
                       ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?PSSI_CR_CKPOL:0U));
          }
          else
          {
            MODIFY_REG(hpssi->Instance->CR,PSSI_CR_DMAEN|PSSI_CR_OUTEN|PSSI_CR_CKPOL,PSSI_CR_DMA_ENABLE | hpssi->Init.BusWidth |
                       ((hpssi->Init.ClockPolarity == HAL_PSSI_RISING_EDGE)?PSSI_CR_CKPOL:0U));
          }
  
          /* Set the PSSI DMA transfer complete callback */
          hpssi->hdmarx->XferCpltCallback = PSSI_DMAReceiveCplt;
  
          /* Set the DMA error callback */
          hpssi->hdmarx->XferErrorCallback = PSSI_DMAError;
  
          /* Set the unused DMA callbacks to NULL */
          hpssi->hdmarx->XferHalfCpltCallback = NULL;
          hpssi->hdmarx->XferAbortCallback = NULL;
  
          /* Enable the DMA  */
          dmaxferstatus = HAL_DMA_Start_IT(hpssi->hdmarx, (uint32_t)&hpssi->Instance->DR, (uint32_t)pData, hpssi->XferSize);
        }
        else
        {
          /* Update PSSI state */
          hpssi->State     = HAL_PSSI_STATE_READY;
  
          /* Update PSSI error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          return HAL_ERROR;
        }
  
        if (dmaxferstatus == HAL_OK)
        {
          /* Update XferCount value */
          hpssi->XferCount -= hpssi->XferSize;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          /* Note : The PSSI interrupts must be enabled after unlocking current process
                    to avoid the risk of PSSI interrupt handle execution before current
                    process unlock */
          /* Enable ERR  interrupt */
          HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
          /* Enable DMA Request */
          hpssi->Instance->CR |= PSSI_CR_DMA_ENABLE;
          /* Enable the selected PSSI peripheral */
          HAL_PSSI_ENABLE(hpssi);
        }
        else
        {
          /* Update PSSI state */
          hpssi->State     = HAL_PSSI_STATE_READY;
  
          /* Update PSSI error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_DMA;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          return HAL_ERROR;
        }
      }
      else
      {
  
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
  
        /* Enable ERR,interrupt */
        HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
      }
  
      return HAL_OK;
    }
    else
    {
      return HAL_BUSY;
    }
  }
  
  
  
  /**
    * @brief  Abort a DMA process communication with Interrupt.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval HAL status
    */
  HAL_StatusTypeDef HAL_PSSI_Abort_DMA(PSSI_HandleTypeDef *hpssi)
  {
  
    /* Process Locked */
    __HAL_LOCK(hpssi);
  
    /* Disable Interrupts */
    HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
    /* Set State at HAL_PSSI_STATE_ABORT */
    hpssi->State = HAL_PSSI_STATE_ABORT;
  
    /* Abort DMA TX transfer if any */
    if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
    {
      if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
      {
  
        hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
        if (hpssi->hdmatx != NULL)
        {
          /* Set the PSSI DMA Abort callback :
          will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
          hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
  
          /* Abort DMA TX */
          if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
          {
            /* Call Directly XferAbortCallback function in case of error */
            hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
          }
        }
  
      }
      /* Abort DMA RX transfer if any */
      else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
      {
  
        hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
        if (hpssi->hdmarx != NULL)
        {
          /* Set the PSSI DMA Abort callback :
          will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
          hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
  
          /* Abort DMA RX */
          if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
          {
            /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
            hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
          }
        }
      }
      else
      {
        /* Call the error callback */
        hpssi->ErrorCallback(hpssi);
      }
    }
  
  
    /* Process Unlocked */
    __HAL_UNLOCK(hpssi);
  
    /* Note : The PSSI interrupts must be enabled after unlocking current process
              to avoid the risk of PSSI interrupt handle execution before current
              process unlock */
    HAL_PSSI_ENABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
    return HAL_OK;
  
  }
  
  /**
    * @}
    */
  
  /** @defgroup PSSI_Exported_Functions_Group3 IRQ Handler and Callbacks
   * @{
   */
  
  /**
    * @brief  This function handles PSSI event interrupt request.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  void HAL_PSSI_IRQHandler(PSSI_HandleTypeDef *hpssi)
  {
    /* Overrun/ Underrun Errors */
    if (HAL_PSSI_GET_FLAG(hpssi, PSSI_FLAG_OVR_MIS) != 0U)
    {
      /* Reset handle parameters */
  
      hpssi->XferCount     = 0U;
  
      /* Disable all interrupts */
      HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
  
      /* Abort DMA TX transfer if any */
      if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
      {
        if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
        {
          /* Set new error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_UNDER_RUN;
  
          hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
          if (hpssi->hdmatx != NULL)
          {
            /* Set the PSSI DMA Abort callback :
            will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
            hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
  
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
  
            /* Abort DMA TX */
            if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
            {
              /* Call Directly XferAbortCallback function in case of error */
              hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
            }
          }
  
        }
        /* Abort DMA RX transfer if any */
        else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
        {
          /* Set new error code */
          hpssi->ErrorCode |= HAL_PSSI_ERROR_OVER_RUN;
  
          hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
          if (hpssi->hdmarx != NULL)
          {
            /* Set the PSSI DMA Abort callback :
            will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
            hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
  
            /* Process Unlocked */
            __HAL_UNLOCK(hpssi);
  
            /* Abort DMA RX */
            if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
            {
              /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
              hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
            }
          }
        }
        else
        {
          /* Call the corresponding callback to inform upper layer of the error */
          hpssi->ErrorCallback(hpssi);
        }
      }
  
      /* If state is an abort treatment on going, don't change state */
      if (hpssi->State == HAL_PSSI_STATE_ABORT)
      {
        hpssi->State = HAL_PSSI_STATE_READY;
  
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
  
        /* Call the corresponding callback to inform upper layer of End of Transfer */
        hpssi->AbortCpltCallback(hpssi);
  
      }
      else
      {
        /* Set HAL_PSSI_STATE_READY */
        hpssi->State         = HAL_PSSI_STATE_READY;
        /* Process Unlocked */
        __HAL_UNLOCK(hpssi);
  
        /* Call the corresponding callback to inform upper layer of End of Transfer */
        hpssi->ErrorCallback(hpssi);
  
      }
  
    }
  }
  
  
  /**
    * @brief   Tx Transfer complete callback.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_TxCpltCallback(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_TxCpltCallback can be implemented in the user file
     */
  }
  
  /**
    * @brief   Rx Transfer complete callback.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_RxCpltCallback(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_RxCpltCallback can be implemented in the user file
     */
  }
  
  
  /**
    * @brief  PSSI error callback.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_ErrorCallback(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_ErrorCallback could be implemented in the user file
     */
  }
  
  /**
    * @brief  PSSI abort callback.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval None
    */
  __weak void HAL_PSSI_AbortCpltCallback(PSSI_HandleTypeDef *hpssi)
  {
    /* Prevent unused argument(s) compilation warning */
    UNUSED(hpssi);
  
    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_PSSI_AbortCpltCallback could be implemented in the user file
     */
  }
  
  /**
    * @}
    */
  
  /** @defgroup PSSI_Exported_Functions_Group4 Peripheral State, Mode and Error functions
   *  @brief   Peripheral State, Mode and Error functions
   *
  @verbatim
   ===============================================================================
              ##### Peripheral State, Mode and Error functions #####
   ===============================================================================
      [..]
      This subsection permit to get in run-time the status of the peripheral
      and the data flow.
  
  @endverbatim
    * @{
    */
  
  /**
    * @brief  Return the PSSI handle state.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @retval HAL state
    */
  HAL_PSSI_StateTypeDef HAL_PSSI_GetState(PSSI_HandleTypeDef *hpssi)
  {
    /* Return PSSI handle state */
    return hpssi->State;
  }
  
  
  /**
  * @brief  Return the PSSI error code.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *              the configuration information for the specified PSSI.
  * @retval PSSI Error Code
  */
  uint32_t HAL_PSSI_GetError(PSSI_HandleTypeDef *hpssi)
  {
    return hpssi->ErrorCode;
  }
  
  /**
    * @}
    */
  
  /**
    * @}
    */
  
  /** @addtogroup PSSI_Private_Functions
    * @{
    */
  
  /**
    * @brief  PSSI Errors process.
    * @param  hpssi PSSI handle.
    * @param  ErrorCode Error code to handle.
    * @retval None
    */
  static void PSSI_Error(PSSI_HandleTypeDef *hpssi, uint32_t ErrorCode)
  {
  
    /* Reset handle parameters */
  
    hpssi->XferCount     = 0U;
  
    /* Set new error code */
    hpssi->ErrorCode |= ErrorCode;
  
    /* Disable all interrupts */
    HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
  
    /* Abort DMA TX transfer if any */
    if ((hpssi->Instance->CR & PSSI_CR_DMAEN) == PSSI_CR_DMAEN)
    {
      if (hpssi->State == HAL_PSSI_STATE_BUSY_TX)
      {
        hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
        if (hpssi->hdmatx != NULL)
        {
          /* Set the PSSI DMA Abort callback :
          will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
          hpssi->hdmatx->XferAbortCallback = PSSI_DMAAbort;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          /* Abort DMA TX */
          if (HAL_DMA_Abort_IT(hpssi->hdmatx) != HAL_OK)
          {
            /* Call Directly XferAbortCallback function in case of error */
            hpssi->hdmatx->XferAbortCallback(hpssi->hdmatx);
          }
        }
  
      }
      /* Abort DMA RX transfer if any */
      else if (hpssi->State == HAL_PSSI_STATE_BUSY_RX)
      {
        hpssi->Instance->CR &= ~PSSI_CR_DMAEN;
  
        if (hpssi->hdmarx != NULL)
        {
          /* Set the PSSI DMA Abort callback :
          will lead to call HAL_PSSI_ErrorCallback() at end of DMA abort procedure */
          hpssi->hdmarx->XferAbortCallback = PSSI_DMAAbort;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          /* Abort DMA RX */
          if (HAL_DMA_Abort_IT(hpssi->hdmarx) != HAL_OK)
          {
            /* Call Directly hpssi->hdma->XferAbortCallback function in case of error */
            hpssi->hdmarx->XferAbortCallback(hpssi->hdmarx);
          }
        }
      }
      else
      {
        /*Nothing to do*/
      }
    }
  
    /* If state is an abort treatment on going, don't change state */
    if (hpssi->State == HAL_PSSI_STATE_ABORT)
    {
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
  
      hpssi->AbortCpltCallback(hpssi);
  
    }
    else
    {
      /* Set HAL_PSSI_STATE_READY */
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      hpssi->ErrorCallback(hpssi);
  
    }
  }
  
  /**
    * @brief  DMA PSSI slave transmit process complete callback.
    * @param  hdma DMA handle
    * @retval None
    */
  void PSSI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
  {
    PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
  
    uint32_t tmperror;
  
  
    /* Disable Interrupts */
    HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
    /* Store current volatile hpssi->ErrorCode, misra rule */
    tmperror = hpssi->ErrorCode;
  
    /* Call the corresponding callback to inform upper layer of End of Transfer */
    if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
    {
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      PSSI_Error(hpssi, hpssi->ErrorCode);
    }
    /* hpssi->State == HAL_PSSI_STATE_BUSY_TX */
    else
    {
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
  
      hpssi->TxCpltCallback(hpssi);
  
    }
  
  
  }
  
  /**
    * @brief DMA PSSI master receive process complete callback.
    * @param  hdma DMA handle
    * @retval None
    */
  void PSSI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
  {
    PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
  
    uint32_t tmperror;
  
  
    /* Disable Interrupts */
    HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
    /* Store current volatile hpssi->ErrorCode, misra rule */
    tmperror = hpssi->ErrorCode;
  
    /* Call the corresponding callback to inform upper layer of End of Transfer */
    if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
    {
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      PSSI_Error(hpssi, hpssi->ErrorCode);
    }
    /* hpssi->State == HAL_PSSI_STATE_BUSY_RX */
    else
    {
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      hpssi->RxCpltCallback(hpssi);
  
    }
  
  
  }
  
  /**
    * @brief DMA PSSI communication abort callback
    *        (To be called at end of DMA Abort procedure).
    * @param hdma DMA handle.
    * @retval None
    */
  void PSSI_DMAAbort(DMA_HandleTypeDef *hdma)
  {
    PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
  
    /* Reset AbortCpltCallback */
    hpssi->hdmatx->XferAbortCallback = NULL;
    hpssi->hdmarx->XferAbortCallback = NULL;
  
    /* Check if come from abort from user */
    if (hpssi->State == HAL_PSSI_STATE_ABORT)
    {
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
  
      hpssi->AbortCpltCallback(hpssi);
  
    }
    else
    {
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      hpssi->ErrorCallback(hpssi);
    }
  }
  
  /**
    * @brief  This function handles PSSI Communication Timeout.
    * @param  hpssi Pointer to a PSSI_HandleTypeDef structure that contains
    *                the configuration information for the specified PSSI.
    * @param  Flag Specifies the PSSI flag to check.
    * @param  Status The new Flag status (SET or RESET).
    * @param  Timeout Timeout duration
    * @param  Tickstart Tick start value
    * @retval HAL status
    */
  static HAL_StatusTypeDef PSSI_WaitOnStatusUntilTimeout(PSSI_HandleTypeDef *hpssi, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
  {
    while ((HAL_PSSI_GET_STATUS(hpssi, Flag) & Flag) == (uint32_t)Status)
    {
      /* Check for the Timeout */
      if (Timeout != HAL_MAX_DELAY)
      {
        if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
        {
          hpssi->ErrorCode |= HAL_PSSI_ERROR_TIMEOUT;
          hpssi->State = HAL_PSSI_STATE_READY;
  
          /* Process Unlocked */
          __HAL_UNLOCK(hpssi);
  
          return HAL_ERROR;
        }
      }
    }
    return HAL_OK;
  }
  void PSSI_DMAError(DMA_HandleTypeDef *hdma)
  {
    PSSI_HandleTypeDef *hpssi = (PSSI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */
  
    uint32_t tmperror;
  
  
    /* Disable the selected PSSI peripheral */
    HAL_PSSI_DISABLE(hpssi);
  
    /* Disable Interrupts */
    HAL_PSSI_DISABLE_IT(hpssi, PSSI_FLAG_OVR_RIS);
  
    /* Store current volatile hpssi->ErrorCode, misra rule */
    tmperror = hpssi->ErrorCode;
  
    /* Call the corresponding callback to inform upper layer of End of Transfer */
    if ((hpssi->State == HAL_PSSI_STATE_ABORT) || (tmperror != HAL_PSSI_ERROR_NONE))
    {
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      PSSI_Error(hpssi, hpssi->ErrorCode);
    }
    else
    {
      hpssi->State = HAL_PSSI_STATE_READY;
  
      /* Process Unlocked */
      __HAL_UNLOCK(hpssi);
  
      /* Call the corresponding callback to inform upper layer of End of Transfer */
      hpssi->ErrorCallback(hpssi);
  
    }
  
  }
  
  
  
  /**
    * @}
    */
  #endif /* PSSI */
  #endif /* HAL_PSSI_MODULE_ENABLED */
  /**
    * @}
    */
  
  /**
    * @}
    */
  