Exemplo n.º 1
0
Arquivo: can.c Projeto: stxent/halm
/*----------------------------------------------------------------------------*/
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;
  }
}
Exemplo n.º 2
0
/*----------------------------------------------------------------------------*/
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);
}