Esempio n. 1
0
/*----------------------------------------------------------------------------*/
static void unitReleaseChannel(struct GpTimerPwmUnit *unit, uint8_t channel)
{
  const irqState state = irqSave();

  unit->matches &= ~(1 << channel);

  irqRestore(state);
}
Esempio n. 2
0
File: wdt.c Progetto: stxent/halm
/*----------------------------------------------------------------------------*/
static enum Result wdtInit(void *object, const void *configBase)
{
  const struct WdtConfig * const config = configBase;
  assert(config);

  const struct WdtBaseConfig baseConfig = {
      .source = config->source
  };
  enum Result res;

  /* Call base class constructor */
  if ((res = WdtBase->init(object, &baseConfig)) != E_OK)
    return res;

  const uint32_t clock = wdtGetClock(object) / 4;
  const uint32_t prescaler = config->period * (clock / 1000);

  assert(prescaler >= 1 << 8);
  assert(prescaler <= 0xFFFFFFFFUL >> (32 - WDT_TIMER_RESOLUTION));

  LPC_WDT->TC = prescaler;
  LPC_WDT->MOD = MOD_WDEN | MOD_WDRESET;

  wdtReload(object);

  return E_OK;
}
/*----------------------------------------------------------------------------*/
static enum Result wdtSetCallback(void *object __attribute__((unused)),
    void (*callback)(void *) __attribute__((unused)),
    void *argument __attribute__((unused)))
{
  /*
   * The intent of the WDT interrupt is to allow debugging. This interrupt
   * can not be used as a regular timer interrupt.
   */
  return E_INVALID;
}
/*----------------------------------------------------------------------------*/
static void wdtReload(void *object __attribute__((unused)))
{
  const IrqState state = irqSave();

  LPC_WDT->FEED = FEED_FIRST;
  LPC_WDT->FEED = FEED_SECOND;

  irqRestore(state);
}
Esempio n. 3
0
/*----------------------------------------------------------------------------*/
static size_t canWrite(void *object, const void *buffer, size_t length)
{
  assert(length % sizeof(struct CanStandardMessage) == 0);

  struct Can * const interface = object;

  if (interface->mode == MODE_LISTENER)
    return 0;

  LPC_CAN_Type * const reg = interface->base.reg;
  const struct CanStandardMessage *input = buffer;
  const size_t initialLength = length;

  const irqState state = irqSave();

  if (queueEmpty(&interface->txQueue))
  {
    uint32_t status = reg->SR;

    while (length && (status & SR_TBS_MASK))
    {
      /* One of transmit buffers is empty */
      status = sendMessage(interface, (const struct CanMessage *)input, status);

      length -= sizeof(*input);
      ++input;
    }
  }

  while (length && !queueFull(&interface->txQueue))
  {
    struct CanMessage *output;

    queuePop(&interface->pool, &output);
    memcpy(output, input, sizeof(*input));
    queuePush(&interface->txQueue, &output);
    length -= sizeof(*input);
    ++input;
  }

  irqRestore(state);

  return initialLength - length;
}
Esempio n. 4
0
/*----------------------------------------------------------------------------*/
static enum result unitAllocateChannel(struct GpTimerPwmUnit *unit,
    uint8_t channel)
{
  enum result res = E_BUSY;
  const uint8_t mask = 1 << channel;
  const irqState state = irqSave();

  const int freeChannel = gpTimerAllocateChannel(unit->matches | mask);

  if (freeChannel != -1 && !(unit->matches & mask))
  {
    unit->matches |= mask;
    unitUpdateResolution(unit, freeChannel);
    res = E_OK;
  }

  irqRestore(state);
  return res;
}
Esempio n. 5
-1
/*----------------------------------------------------------------------------*/
static enum result canInit(void *object, const void *configBase)
{
  const struct CanConfig * const config = configBase;
  const struct CanBaseConfig baseConfig = {
      .channel = config->channel,
      .rx = config->rx,
      .tx = config->tx
  };
  struct Can * const interface = object;
  enum result res;

  /* Call base class constructor */
  if ((res = CanBase->init(object, &baseConfig)) != E_OK)
    return res;

  interface->base.handler = interruptHandler;
  interface->callback = 0;
  interface->timer = config->timer;
  interface->mode = MODE_LISTENER;

  const size_t poolSize = config->rxBuffers + config->txBuffers;

  res = queueInit(&interface->pool, sizeof(struct CanMessage *), poolSize);
  if (res != E_OK)
    return res;
  res = queueInit(&interface->rxQueue, sizeof(struct CanMessage *),
      config->rxBuffers);
  if (res != E_OK)
    return res;
  res = queueInit(&interface->txQueue, sizeof(struct CanMessage *),
      config->txBuffers);
  if (res != E_OK)
    return res;

  interface->poolBuffer = malloc(sizeof(struct CanStandardMessage) * poolSize);

  struct CanStandardMessage *message = interface->poolBuffer;

  for (size_t index = 0; index < poolSize; ++index)
  {
    queuePush(&interface->pool, &message);
    ++message;
  }

  LPC_CAN_Type * const reg = interface->base.reg;

  reg->MOD = MOD_RM; /* Reset CAN */
  reg->IER = 0; /* Disable Receive Interrupt */
  reg->GSR = 0; /* Reset error counter */

  interface->rate = config->rate;
  reg->BTR = calcBusTimings(interface, interface->rate);

  /* Disable Reset mode and activate Listen Only mode */
  reg->MOD = MOD_LOM;

  LPC_CANAF->AFMR = AFMR_AccBP; //FIXME

#ifdef CONFIG_CAN_PM
  if ((res = pmRegister(interface, powerStateHandler)) != E_OK)
    return res;
#endif

  irqSetPriority(interface->base.irq, config->priority);

  /* Enable interrupts on message reception and bus error */
  reg->IER = IER_RIE | IER_BEIE;

  return E_OK;
}
/*----------------------------------------------------------------------------*/
static void canDeinit(void *object)
{
  struct Can * const interface = object;
  LPC_CAN_Type * const reg = interface->base.reg;

  /* Disable all interrupts */
  reg->IER = 0;

#ifdef CONFIG_CAN_PM
  pmUnregister(interface);
#endif

  queueDeinit(&interface->txQueue);
  queueDeinit(&interface->rxQueue);
  CanBase->deinit(interface);
}
/*----------------------------------------------------------------------------*/
static enum result canCallback(void *object, void (*callback)(void *),
    void *argument)
{
  struct Can * const interface = object;

  interface->callbackArgument = argument;
  interface->callback = callback;
  return E_OK;
}
/*----------------------------------------------------------------------------*/
static enum result canGet(void *object, enum ifOption option, void *data)
{
  struct Can * const interface = object;

  switch (option)
  {
    case IF_AVAILABLE:
      *(size_t *)data = queueSize(&interface->rxQueue);
      return E_OK;

    case IF_PENDING:
      *(size_t *)data = queueSize(&interface->txQueue);
      return E_OK;

    case IF_RATE:
      *(uint32_t *)data = interface->rate;
      return E_OK;

    default:
      return E_INVALID;
  }
}
/*----------------------------------------------------------------------------*/
static enum result canSet(void *object, enum ifOption option,
    const void *data)
{
  struct Can * const interface = object;
  LPC_CAN_Type * const reg = interface->base.reg;

  switch ((enum canOption)option)
  {
    case IF_CAN_ACTIVE:
      changeMode(interface, MODE_ACTIVE);
      return E_OK;

    case IF_CAN_LISTENER:
      changeMode(interface, MODE_LISTENER);
      return E_OK;

    case IF_CAN_LOOPBACK:
      changeMode(interface, MODE_LOOPBACK);
      return E_OK;

    default:
      break;
  }

  switch (option)
  {
    case IF_RATE:
    {
      const uint32_t rate = *(const uint32_t *)data;

      interface->rate = rate;

      reg->MOD |= MOD_RM; /* Enable Reset mode */
      reg->BTR = calcBusTimings(interface, rate);
      reg->MOD &= ~MOD_RM;

      return E_OK;
    }

    default:
      return E_INVALID;
  }
}
/*----------------------------------------------------------------------------*/
static size_t canRead(void *object, void *buffer, size_t length)
{
  assert(length % sizeof(struct CanStandardMessage) == 0);

  struct Can * const interface = object;
  struct CanStandardMessage *output = buffer;
  size_t read = 0;

  while (read < length && !queueEmpty(&interface->rxQueue))
  {
    struct CanMessage *input;
    const irqState state = irqSave();

    queuePop(&interface->rxQueue, &input);
    memcpy(output, input, sizeof(*output));
    queuePush(&interface->pool, &input);

    irqRestore(state);

    read += sizeof(*output);
    ++output;
  }

  return read;
}