Sinopsis: las funciones de la biblioteca STM32 HAL HAL_CAN_Transmit_IT
y HAL_CAN_Receive_IT
no pueden usarse simultáneamente de manera efectiva sin riesgos de pérdida de datos.
Detalles:
Cuando creas un ciclo de recepción / transmisión como el de abajo (simplificado)
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
}
En algunas situaciones, HAL_CAN_Receive_IT
/ HAL_CAN_Transmit_IT
cae con un estado ocupado. Esto ocurre porque tanto de Transmisión como de Amp; Receive utiliza un bloqueo a través de __HAL_LOCK(hcan)
.
Cuando se llama a HAL_CAN_Transmit_IT
y se produce la interrupción HAL_CAN_RxCpltCallback
, el estado está bloqueado por HAL_CAN_Transmit_IT
y falla rearm rx.
¿Cuál es la solución para resolver esto?
No puedo encontrar una manera fácil ahora. En mi opinión, un error general es el HAL_CAN_StateTypeDef State
unificado utilizado para tres indicadores independientes: estado CAN general, estado rx y estado tx.
Creo que la solución es dividir State para {State, rxState & txState} y nunca bloquee lo mismo en Recibir / Transmitir.
Por ejemplo, la estructura actual,
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;
dividir a
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;
Pero esa es una modificación impresionante de la biblioteca. Tal vez exista una mejor solución? El mismo problema afecta a la biblioteca USART, creo.