/*----------------------------------------------------------------------------*/ static void readMessage(struct Can *interface, struct CanMessage *message) { LPC_CAN_Type * const reg = interface->base.reg; const uint32_t information = reg->RFS; message->id = reg->RID; message->flags = 0; message->length = RFS_DLC_VALUE(information); if (information & RFS_RTR) { message->flags |= CAN_RTR; } else { const uint32_t data[2] = { reg->RDA, reg->RDB }; memcpy(message->data, data, sizeof(data)); } if (information & RFS_FF) { message->flags |= CAN_EXT_ID; } }
/*----------------------------------------------------------------------------*/ static void interruptHandler(void *object) { struct Can * const interface = object; LPC_CAN_Type * const reg = interface->base.reg; bool event = false; while (reg->SR & SR_RBS) { if (!queueEmpty(&interface->pool)) { const uint32_t timestamp = interface->timer ? timerGetValue(interface->timer) : 0; const uint32_t data[2] = {reg->RDA, reg->RDB}; const uint32_t information = reg->RFS; struct CanStandardMessage *message; queuePop(&interface->pool, &message); message->timestamp = timestamp; message->id = reg->RID; message->length = RFS_DLC_VALUE(information); message->flags = 0; if (information & RFS_FF) message->flags |= CAN_EXT_ID; if (information & RFS_RTR) message->flags |= CAN_RTR; memcpy(message->data, data, sizeof(data)); queuePush(&interface->rxQueue, &message); event = true; } /* Release receive buffer */ reg->CMR = CMR_RRB; } uint32_t status = reg->SR; if (status & SR_TBS_MASK) { /* Disable interrupts for completed transmit buffers */ uint32_t enabledInterrupts = reg->IER; if (status & SR_TBS(0)) enabledInterrupts &= ~IER_TIE1; if (status & SR_TBS(1)) enabledInterrupts &= ~IER_TIE2; if (status & SR_TBS(2)) enabledInterrupts &= ~IER_TIE3; reg->IER = enabledInterrupts; while (!queueEmpty(&interface->txQueue) && (status & SR_TBS_MASK)) { const struct CanMessage *message; queuePop(&interface->txQueue, &message); status = sendMessage(interface, message, status); } } if (status & SR_BS) { /* * The controller is forced into a bus-off state, RM bit should be cleared * to continue normal operation. */ reg->MOD &= ~MOD_RM; } if (interface->callback && event) interface->callback(interface->callbackArgument); }