static void CAN_handle_isr(const uint32_t ibits, const can_t can, volatile LPC_CAN_TypeDef *CANx) { const uint8_t cidx = CAN_INDEX(can); can_msg_t msg; /* Handle received message */ if (ibits & intr_rx) { /** * TO DO Test if we directly have FreeRTOS queue copy the data from CAN registers. * can_msg_t *pMsg = (can_msg_t*) &(CANx->RFS); * xQueueSendFromISR(g_can_rx_qs[CAN_INDEX(can)], pMsg, NULL); * CANx->CMR = 0x04; */ CAN_rx_now(CANx, &msg); xQueueSendFromISR(g_can_rx_qs[cidx], &msg, NULL); } /* A transmit finished, send any queued message(s) */ if (ibits & intr_all_tx) { if (xQueueReceiveFromISR(g_can_tx_qs[cidx], &msg, NULL)) { CAN_tx_now(CANx, &msg); } } /* We only enable interrupt when a valid callback exists, so no need * to check for the callback function being NULL */ if (ibits & intr_berr) { g_can_callbacks[cidx].bus_error(); } if (ibits & intr_ovrn) { g_can_callbacks[cidx].data_overrun(); } }
bool CAN_tx (can_t can, can_msg_t *pCanMsg, uint32_t timeout_ms) { if (!CAN_VALID(can) || !pCanMsg || CAN_is_bus_off(can)) { return false; } bool ok = false; can_struct_t *pStruct = CAN_STRUCT_PTR(can); LPC_CAN_TypeDef *CANx = pStruct->pCanRegs; /* Try transmitting to one of the available buffers */ taskENTER_CRITICAL(); do { ok = CAN_tx_now(pStruct, pCanMsg); } while(0); taskEXIT_CRITICAL(); /* If HW buffer not available, then just queue the message */ if (!ok) { if (taskSCHEDULER_RUNNING == xTaskGetSchedulerState()) { ok = xQueueSend(pStruct->txQ, pCanMsg, OS_MS(timeout_ms)); } else { ok = xQueueSend(pStruct->txQ, pCanMsg, 0); } /* There is possibility that before we queued the message, we got interrupted * and all hw buffers were emptied meanwhile, and our queued message will now * sit in the queue forever until another Tx interrupt takes place. * So we dequeue it here if all are empty and send it over. */ taskENTER_CRITICAL(); do { can_msg_t msg; if (tx_all_avail == (CANx->SR & tx_all_avail) && xQueueReceive(pStruct->txQ, &msg, 0) ) { ok = CAN_tx_now(pStruct, &msg); } } while(0); taskEXIT_CRITICAL(); } return ok; }
bool CAN_tx (can_t can, can_msg_t *pCanMsg, uint32_t timeout_ms) { volatile LPC_CAN_TypeDef *CANx = CAN_ENUM_TO_REGS(can); const uint8_t cidx = CAN_INDEX(can); bool ok = false; if (!CANx || !pCanMsg) { return false; } /* Try transmitting to one of the available buffers */ vPortEnterCritical(); { ok = CAN_tx_now(CANx, pCanMsg); } vPortExitCritical(); /* If all three buffers are busy, just queue the message */ if (!ok) { if (taskSCHEDULER_RUNNING == xTaskGetSchedulerState()) { ok = xQueueSend(g_can_tx_qs[cidx], pCanMsg, OS_MS(timeout_ms)); } else { ok = xQueueSendFromISR(g_can_tx_qs[cidx], pCanMsg, NULL); } /* There is possibility that before we queued the message, we got interrupted * and all hw buffers were emptied meanwhile, and our queued message will now * sit in the queue forever until another Tx interrupt takes place. * So we dequeue it here if all are empty and send it over. */ vPortEnterCritical(); { can_msg_t msg; if (tx_all_avail == (CANx->SR & tx_all_avail) && xQueueReceiveFromISR(g_can_tx_qs[cidx], &msg, NULL) ) { ok = CAN_tx_now(CANx, &msg); } } vPortExitCritical(); } return ok; }
static void CAN_handle_isr(const can_t can) { can_struct_t *pStruct = CAN_STRUCT_PTR(can); LPC_CAN_TypeDef *pCAN = pStruct->pCanRegs; const uint32_t rbs = (1 << 0); const uint32_t ibits = pCAN->ICR; UBaseType_t count; can_msg_t msg; /* Handle the received message */ if ((ibits & intr_rx) | (pCAN->GSR & rbs)) { if( (count = uxQueueMessagesWaitingFromISR(pStruct->rxQ)) > pStruct->rxQWatermark) { pStruct->rxQWatermark = count; } can_msg_t *pHwMsgRegs = (can_msg_t*) &(pCAN->RFS); if (xQueueSendFromISR(pStruct->rxQ, pHwMsgRegs, NULL)) { pStruct->rxMsgCount++; } else { pStruct->droppedRxMsgs++; } pCAN->CMR = 0x04; // Release the receive buffer, no need to bitmask } /* A transmit finished, send any queued message(s) */ if (ibits & intr_all_tx) { if( (count = uxQueueMessagesWaitingFromISR(pStruct->txQ)) > pStruct->txQWatermark) { pStruct->txQWatermark = count; } if (xQueueReceiveFromISR(pStruct->txQ, &msg, NULL)) { CAN_tx_now(pStruct, &msg); } } /* We only enable interrupt when a valid callback exists, so no need * to check for the callback function being NULL */ if (ibits & g_can_bus_err_intr) { pStruct->bus_error(ibits); } if (ibits & intr_ovrn) { pStruct->data_overrun(ibits); } }