Hi, Craig,
I have read the example code of flexCan located at the directory:
D:\Freescale\KSDK_1.3.0\examples\twrk64f120m\driver_examples\flexcan\flexcan_network\kds
I think the FLEXCAN_DRV_RxMessageBufferBlocking(FSL_CANCOM1, RX_mailbox_num, &rx_buf, CAN_RX_TIMEOUT) function can block the FlexCan receiver MB. I listed all the functions having something to do with the above function.
When a FlexCan interrupt happens, the FLEXCAN_DRV_IRQHandler() is executed automatically, in the function, the interrupt source is identified. If the FlexCan receiving MB leads to the interrupt, the FLEXCAN_DRV_CompleteRxMessageBufferData(instance); is called, the
OSA_SemaPost(&state->rxIrqSync) is called, the FLEXCAN_DRV_RxMessageBufferBlocking() will unblock. Otherwise, the FLEXCAN_DRV_RxMessageBufferBlocking() function will be blocked by the code:
do
{
syncStatus = OSA_SemaWait(&state->rxIrqSync, timeout_ms);
}while(syncStatus == kStatus_OSA_Idle);
If the other fault of FlexCan except for receiving MB interrupt happens, the FLEXCAN_DRV_IRQHandler() is executed, but the FLEXCAN_DRV_CompleteRxMessageBufferData(instance) is NOT called, OSA_SemaPost(&state->rxIrqSync) is NOT signaled, the FLEXCAN_DRV_RxMessageBufferBlocking() will be in blocking state.
Hope it can help you.
BR
Xiangjun Rong
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_RxMessageBufferBlocking
* Description : Start receive data after a Rx MB interrupt occurs.
* This function will lock Rx MB after a Rx MB interrupt occurs.
*
*END**************************************************************************/
flexcan_status_t FLEXCAN_DRV_RxMessageBufferBlocking(
uint8_t instance,
uint32_t mb_idx,
flexcan_msgbuff_t *data,
uint32_t timeout_ms)
{
assert(instance < CAN_INSTANCE_COUNT);
assert(data);
flexcan_status_t result;
flexcan_state_t * state = g_flexcanStatePtr[instance];
osa_status_t syncStatus;
state->isRxBlocking = true;
result = FLEXCAN_DRV_StartRxMessageBufferData(instance, mb_idx, data);
if(result == kStatus_FLEXCAN_Success)
{
do
{
syncStatus = OSA_SemaWait(&state->rxIrqSync, timeout_ms);
}while(syncStatus == kStatus_OSA_Idle);
/* Wait for the interrupt*/
if (syncStatus != kStatus_OSA_Success)
{
return kStatus_FLEXCAN_TimeOut;
}
}
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_StartRxMessageBufferData
* Description : Initiate (start) a receive by beginning the process of
* receiving data and enabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static flexcan_status_t FLEXCAN_DRV_StartRxMessageBufferData(
uint8_t instance,
uint32_t mb_idx,
flexcan_msgbuff_t *data
)
{
flexcan_status_t result;
CAN_Type * base = g_flexcanBase[instance];
flexcan_state_t * state = g_flexcanStatePtr[instance];
/* Start receiving mailbox */
if(state->isRxBusy)
{
return kStatus_FLEXCAN_RxBusy;
}
state->isRxBusy = true;
state->mb_message = data;
/* Enable MB interrupt*/
result = FLEXCAN_HAL_SetMsgBuffIntCmd(base, mb_idx, true);
/* Enable error interrupts */
FLEXCAN_HAL_SetErrIntCmd(base,kFlexCanIntErr,true);
return result;
}
/*FUNCTION**********************************************************************
*
* Function Name : FLEXCAN_DRV_CompleteRxMessageBufferData
* Description : Finish up a receive by completing the process of receiving
* data and disabling the interrupt.
* This is not a public API as it is called from other driver functions.
*
*END**************************************************************************/
static void FLEXCAN_DRV_CompleteRxMessageBufferData(uint32_t instance)
{
assert(instance < CAN_INSTANCE_COUNT);
CAN_Type * base = g_flexcanBase[instance];
flexcan_state_t * state = g_flexcanStatePtr[instance];
FLEXCAN_HAL_SetMsgBuffIntCmd(base, state->rx_mb_idx, false);
/* Disable error interrupts */
FLEXCAN_HAL_SetErrIntCmd(base,kFlexCanIntErr,false);
/* Signal the synchronous completion object. */
if (state->isRxBlocking)
{
OSA_SemaPost(&state->rxIrqSync);
}
/* Update the information of the module driver state */
state->isRxBusy = false;
}
void FLEXCAN_DRV_IRQHandler(uint8_t instance)
{
volatile uint32_t flag_reg;
uint32_t temp;
CAN_Type * base = g_flexcanBase[instance];
flexcan_state_t * state = g_flexcanStatePtr[instance];
/* Get the interrupts that are enabled and ready */
flag_reg = ((FLEXCAN_HAL_GetAllMsgBuffIntStatusFlag(base)) & CAN_IMASK1_BUFLM_MASK) &
CAN_RD_IMASK1(base);
/* Check Tx/Rx interrupt flag and clear the interrupt */
if(flag_reg)
{
if ((flag_reg & 0x20) && CAN_BRD_MCR_RFEN(base))
{
if (state->fifo_message != NULL)
{
/* Get RX FIFO field values */
FLEXCAN_HAL_ReadRxFifo(base, state->fifo_message);
/* Complete receive data */
FLEXCAN_DRV_CompleteRxMessageFifoData(instance);
FLEXCAN_HAL_ClearMsgBuffIntStatusFlag(base, flag_reg);
}
}
else
{
/* Check mailbox completed reception*/
temp = (1 << state->rx_mb_idx);
if (temp & flag_reg)
{
/* Unlock RX message buffer and RX FIFO*/
FLEXCAN_HAL_LockRxMsgBuff(base, state->rx_mb_idx);
/* Get RX MB field values*/
FLEXCAN_HAL_GetMsgBuff(base, state->rx_mb_idx, state->mb_message);
/* Unlock RX message buffer and RX FIFO*/
FLEXCAN_HAL_UnlockRxMsgBuff(base);
/* Complete receive data */
FLEXCAN_DRV_CompleteRxMessageBufferData(instance);
FLEXCAN_HAL_ClearMsgBuffIntStatusFlag(base, temp & flag_reg);
}
/* Check mailbox completed transmission*/
temp = (1 << state->tx_mb_idx);
if (temp & flag_reg)
{
/* Complete transmit data */
FLEXCAN_DRV_CompleteSendData(instance);
FLEXCAN_HAL_ClearMsgBuffIntStatusFlag(base, temp & flag_reg);
}
}
/* Check mailbox completed transmission*/
temp = (1 << state->tx_mb_idx);
if (flag_reg & temp)
{
/* Complete transmit data */
FLEXCAN_DRV_CompleteSendData(instance);
FLEXCAN_HAL_ClearMsgBuffIntStatusFlag(base, temp & flag_reg);
}
}
/* Clear all other interrupts in ERRSTAT register (Error, Busoff, Wakeup) */
FLEXCAN_HAL_ClearErrIntStatusFlag(base);
return;
}