예제 #1
0
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();
    }
}
예제 #2
0
파일: can.c 프로젝트: kammce/SJSU-DEV-Linux
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;
}
예제 #3
0
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;
}
예제 #4
0
파일: can.c 프로젝트: kammce/SJSU-DEV-Linux
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);
    }
}