AnsweredAssumed Answered

HAL_CAN_Transmit_IT & HAL_CAN_Receive_IT can't be used simultaneously

Question asked by pereslegin.dmitriy on Nov 10, 2015
Latest reply on Nov 10, 2015 by pereslegin.dmitriy
Synopsis: HAL_CAN_Transmit_IT & HAL_CAN_Receive_IT can't be used simultaneously effective without data loss risks.


Details:


When you build receive/transmit cycle like below (simplified)


main() {
  HAL_CAN_Receive_IT();
  HAL_CAN_Transmit_IT();
}

HAL_CAN_RxCpltCallback() {
  HAL_CAN_Receive_IT(); // rearm receive
}

HAL_CAN_TxCpltCallback() {
  HAL_CAN_Transmit_IT(); // rearm transmit
}


In some situations HAL_CAN_Receive_IT/HAL_CAN_Transmit_IT drops with busy state.
This occurs because both of Transmit & Receive uses lock via __HAL_LOCK(hcan) 
When you call HAL_CAN_Transmit_IT and interrupt HAL_CAN_RxCpltCallback occurs, state is locked by HAL_CAN_Transmit_IT and rearm rx failed.


What solution to solve?
I can't find easy way now. In my opinion general mistake is unified "HAL_CAN_StateTypeDef State" used for three indenpended flags - General can state, rx state & tx state.


I think solution is split State for {State, rxState & txState} and never lock same thing in both of Receive/Transmit.


For example current structure


typedef enum
{
  HAL_CAN_STATE_RESET             = 0x00,  /*!< CAN not yet initialized or disabled */
  HAL_CAN_STATE_READY             = 0x01,  /*!< CAN initialized and ready for use   */  
  HAL_CAN_STATE_BUSY              = 0x02,  /*!< CAN process is ongoing              */     
  HAL_CAN_STATE_BUSY_TX           = 0x12,  /*!< CAN process is ongoing              */   
  HAL_CAN_STATE_BUSY_RX           = 0x22,  /*!< CAN process is ongoing              */ 
  HAL_CAN_STATE_BUSY_TX_RX        = 0x32,  /*!< CAN process is ongoing              */
  HAL_CAN_STATE_TIMEOUT           = 0x03,  /*!< CAN in Timeout state                */
  HAL_CAN_STATE_ERROR             = 0x04   /*!< CAN error state                     */  


}HAL_CAN_StateTypeDef;


typedef struct
{
  ...
  __IO HAL_CAN_StateTypeDef   State;      /*!< CAN communication state        */
  ...
}CAN_HandleTypeDef;




split to


typedef enum
{
  HAL_CAN_STATE_RESET             = 0x00,  /*!< CAN not yet initialized or disabled */
  HAL_CAN_STATE_READY             = 0x01,  /*!< CAN initialized and ready for use   */  
  HAL_CAN_STATE_BUSY              = 0x02,  /*!< CAN process is ongoing              */     


}HAL_CAN_StateTypeDef;


typedef enum
{
  HAL_CAN_TXRX_STATE_READY             = 0x01,
  HAL_CAN_TXRX_STATE_BUSY              = 0x02,
  HAL_CAN_TXRX_STATE_TIMEOUT           = 0x03,
  HAL_CAN_TXRX_STATE_ERROR             = 0x04 
}HAL_CAN_TxRxStateTypeDef;




typedef struct
{
  ...
  __IO HAL_CAN_StateTypeDef     State;      /*!< CAN communication state        */
  __IO HAL_CAN_TxRxStateTypeDef RxState;    /*!< CAN RX communication state        */
  __IO HAL_CAN_TxRxStateTypeDef TxState;    /*!< CAN TX communication state        */
  ...
}CAN_HandleTypeDef;







But that is awesome library modification. Maybe you know any better solution?
Same problem affects USART library, i think

Outcomes