/*----------------------------------------------------------------------------*/ static void unitReleaseChannel(struct GpTimerPwmUnit *unit, uint8_t channel) { const irqState state = irqSave(); unit->matches &= ~(1 << channel); irqRestore(state); }
/*----------------------------------------------------------------------------*/ 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); }
/*----------------------------------------------------------------------------*/ 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; }
/*----------------------------------------------------------------------------*/ 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; }
/*----------------------------------------------------------------------------*/ 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; }