/** * @brief Transmits data via the I2C bus as master. * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. * This is hardware restriction. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address * @param[in] txbuf pointer to the transmit buffer * @param[in] txbytes number of bytes to be transmitted * @param[out] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * @return The operation status. * @retval RDY_OK if the function succeeded. * @retval RDY_RESET if one or more I2C errors occurred, the errors can * be retrieved using @p i2cGetErrors(). * @retval RDY_TIMEOUT if a timeout occurred before operation end. <b>After a * timeout the driver must be stopped and restarted * because the bus is in an uncertain state</b>. * * @notapi */ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) { I2C_TypeDef *dp = i2cp->i2c; VirtualTimer vt; #if defined(STM32F1XX_I2C) chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))), "i2c_lld_master_transmit_timeout"); #endif /* Global timeout for the whole operation.*/ if (timeout != TIME_INFINITE) chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); /* Releases the lock from high level driver.*/ chSysUnlock(); /* Initializes driver fields, LSB = 0 -> write.*/ i2cp->addr = addr << 1; i2cp->errors = 0; /* TX DMA setup.*/ dmaStreamSetMemory0(i2cp->dmatx, txbuf); dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); /* RX DMA setup.*/ dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); /* Waits until BUSY flag is reset and the STOP from the previous operation is completed, alternatively for a timeout condition.*/ while ((dp->SR2 & I2C_SR2_BUSY) || (dp->CR1 & I2C_CR1_STOP)) { chSysLock(); if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt)) return RDY_TIMEOUT; chSysUnlock(); } /* This lock will be released in high level driver.*/ chSysLock(); /* Atomic check on the timer in order to make sure that a timeout didn't happen outside the critical zone.*/ if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt)) return RDY_TIMEOUT; /* Starts the operation.*/ dp->CR2 |= I2C_CR2_ITEVTEN; dp->CR1 |= I2C_CR1_START; /* Waits for the operation completion or a timeout.*/ i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); return chThdSelf()->p_u.rdymsg; }
/** * @brief Receives data via the I2C bus as master. * @details Number of receiving bytes must be more than 1 because of stm32 * hardware restrictions. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address * @param[out] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * @return The operation status. * @retval RDY_OK if the function succeeded. * @retval RDY_RESET if one or more I2C errors occurred, the errors can * be retrieved using @p i2cGetErrors(). * @retval RDY_TIMEOUT if a timeout occurred before operation end. <b>After a * timeout the driver must be stopped and restarted * because the bus is in an uncertain state</b>. * * @notapi */ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) { I2C_TypeDef *dp = i2cp->i2c; VirtualTimer vt; msg_t rdymsg; chDbgCheck((rxbytes > 1), "i2c_lld_master_receive_timeout"); /* Global timeout for the whole operation.*/ chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); /* Releases the lock from high level driver.*/ chSysUnlock(); /* Initializes driver fields, LSB = 1 -> receive.*/ i2cp->addr = (addr << 1) | 0x01; i2cp->errors = 0; /* RX DMA setup.*/ dmaStreamSetMemory0(i2cp->dmarx, rxbuf); dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); /* Waits until BUSY flag is reset and the STOP from the previous operation is completed, alternatively for a timeout condition.*/ while ((dp->SR2 & I2C_SR2_BUSY) || (dp->CR1 & I2C_CR1_STOP)) { if (!chVTIsArmedI(&vt)) { chSysLock(); return RDY_TIMEOUT; } } /* This lock will be released in high level driver.*/ chSysLock(); /* Atomic check on the timer in order to make sure that a timeout didn't happen outside the critical zone.*/ if (!chVTIsArmedI(&vt)) return RDY_TIMEOUT; /* Starts the operation.*/ dp->CR2 |= I2C_CR2_ITEVTEN; dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK; /* Waits for the operation completion or a timeout.*/ i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); rdymsg = chThdSelf()->p_u.rdymsg; if (rdymsg != RDY_TIMEOUT) chVTResetI(&vt); return rdymsg; }
/** * @brief Master transmission. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address (7 bits) without R/W bit * @param[in] txbuf transmit data buffer pointer * @param[in] txbytes number of bytes to be transmitted * @param[out] rxbuf receive data buffer pointer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * * @notapi */ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, const uint8_t rxbytes, systime_t timeout) { VirtualTimer vt; /* Global timeout for the whole operation.*/ if (timeout != TIME_INFINITE) chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); i2cp->addr = addr; i2cp->txbuf = txbuf; i2cp->txbytes = txbytes; i2cp->txidx = 0; i2cp->rxbuf = rxbuf; i2cp->rxbytes = rxbytes; i2cp->rxidx = 0; bscdevice_t *device = i2cp->device; device->slaveAddress = addr; device->dataLength = txbytes; device->status = CLEAR_STATUS; /* Enable Interrupts and start transfer.*/ device->control |= (BSC_INTT | BSC_INTD | START_WRITE); /* Is this really needed? there is an outer lock already */ chSysLock(); i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); chSysUnlock(); msg_t status = chThdSelf()->p_u.rdymsg; if (status == RDY_OK && rxbytes > 0) { /* The TIMEOUT_INFINITE prevents receive from setting up it's own timer.*/ status = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); } return status; }
static void doScheduleForLater(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) { int delaySt = MY_US2ST(delayUs); if (delaySt <= 0) { /** * in case of zero delay, we should invoke the callback */ callback(param); return; } bool alreadyLocked = lockAnyContext(); scheduling->callback = callback; scheduling->param = param; int isArmed = chVTIsArmedI(&scheduling->timer); if (isArmed) { /** * timer reuse is normal for example in case of sudden RPM increase */ chVTResetI(&scheduling->timer); } #if EFI_SIMULATOR if (callback == (schfunc_t)&seTurnPinLow) { printf("setTime cb=seTurnPinLow p=%d\r\n", (int)param); } else { // printf("setTime cb=%d p=%d\r\n", (int)callback, (int)param); } #endif /* EFI_SIMULATOR */ chVTSetI(&scheduling->timer, delaySt, (vtfunc_t)timerCallback, scheduling); if (!alreadyLocked) { unlockAnyContext(); } }
void App_t::LedBlink(uint32_t Duration_ms) { PinSet(LED_GPIO, LED_PIN); chSysLock() if(chVTIsArmedI(&TmrLed)) chVTResetI(&TmrLed); chVTSetI(&TmrLed, MS2ST(Duration_ms), LedTmrCallback, nullptr); chSysUnlock(); }
static msg_t spi_thread(void *p) { unsigned i; SPIDriver *spip = (SPIDriver *)p; VirtualTimer vt; uint8_t txbuf[256]; uint8_t rxbuf[256]; /* Prepare transmit pattern.*/ for (i = 0; i < sizeof(txbuf); i++) txbuf[i] = (uint8_t)i; /* Continuous transmission.*/ while (TRUE) { /* Starts a VT working as watchdog to catch a malfunction in the SPI driver.*/ chSysLock(); chVTSetI(&vt, MS2ST(10), tmo, NULL); chSysUnlock(); spiExchange(spip, sizeof(txbuf), txbuf, rxbuf); /* Stops the watchdog.*/ chSysLock(); if (chVTIsArmedI(&vt)) chVTResetI(&vt); chSysUnlock(); } }
/** * @brief Starts the timer * @details If the timer was already running then the function has no effect. * * @param etp pointer to an initialized @p EvTimer structure. */ void evtStart(EvTimer *etp) { chSysLock(); if (!chVTIsArmedI(&etp->et_vt)) chVTSetI(&etp->et_vt, etp->et_interval, tmrcb, etp); chSysUnlock(); }
/** * @brief Stops the timer. * @details If the timer was already stopped then the function has no effect. * * @param etp pointer to an initialized @p EvTimer structure. */ void evtStop(EvTimer *etp) { chSysLock(); if (chVTIsArmedI(&etp->et_vt)) chVTResetI(&etp->et_vt); chSysUnlock(); }
/* * This callback is invoked when a transmission has physically completed. */ static void txend2(UARTDriver *uartp) { (void)uartp; palSetPad(IOPORT3, GPIOC_LED); chSysLockFromIsr(); if (chVTIsArmedI(&vt1)) chVTResetI(&vt1); chVTSetI(&vt1, MS2ST(5000), restart, NULL); chSysUnlockFromIsr(); }
/* * This callback is invoked when a transmission has physically completed. */ static void txend2(UARTDriver *uartp) { (void)uartp; palClearPad(GPIOE, GPIOE_LED3_RED); chSysLockFromIsr(); if (chVTIsArmedI(&vt1)) chVTResetI(&vt1); chVTSetI(&vt1, MS2ST(5000), restart, NULL); chSysUnlockFromIsr(); }
/* Triggered when the button is pressed or released. The LED is set to ON.*/ static void extcb1(EXTDriver *extp, expchannel_t channel) { (void)extp; (void)channel; palClearPad(GPIOC, GPIOC_LED); chSysLockFromIsr(); if (!chVTIsArmedI(&vt)) chVTSetI(&vt, MS2ST(200), ledoff, NULL); chSysUnlockFromIsr(); }
/** * @brief Transmits data via the I2C bus as master. * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. * This is hardware restriction. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address * @param[in] txbuf pointer to the transmit buffer * @param[in] txbytes number of bytes to be transmitted * @param[out] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * @return The operation status. * @retval RDY_OK if the function succeeded. * @retval RDY_RESET if one or more I2C errors occurred, the errors can * be retrieved using @p i2cGetErrors(). * @retval RDY_TIMEOUT if a timeout occurred before operation end. <b>After a * timeout the driver must be stopped and restarted * because the bus is in an uncertain state</b>. * * @notapi */ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, const uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) { LPC_I2C_TypeDef *dp = i2cp->i2c; VirtualTimer vt; i2cp->addr = addr << 1; /* Global timeout for the whole operation.*/ if (timeout != TIME_INFINITE) chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); /* Releases the lock from high level driver.*/ chSysUnlock(); /* Initializes driver fields */ i2cp->errors = 0; i2cp->txbuf = txbuf; i2cp->txbytes = txbytes; i2cp->rxbuf = rxbuf; i2cp->rxbytes = rxbytes; /* This lock will be released in high level driver.*/ chSysLock(); /* Atomic check on the timer in order to make sure that a timeout didn't happen outside the critical zone.*/ if ((timeout != TIME_INFINITE) && !chVTIsArmedI(&vt)) return RDY_TIMEOUT; /* Starts the operation.*/ dp->CONSET = I2C_CONSET_STA; /* Waits for the operation completion or a timeout.*/ i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); return chThdSelf()->p_u.rdymsg; }
void chVTSetAny(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) { if (isIsrContext()) { chSysLockFromIsr() ; if (chVTIsArmedI(vtp)) chVTResetI(vtp); chVTSetI(vtp, time, vtfunc, par); chSysUnlockFromIsr() ; } else { chSysLock() ; if (chVTIsArmedI(vtp)) chVTResetI(vtp); chVTSetI(vtp, time, vtfunc, par); chSysUnlock() ; } }
/* * This callback is invoked when a character is received but the application * was not ready to receive it, the character is passed as parameter. */ static void rxchar(UARTDriver *uartp, uint16_t c) { (void)uartp; (void)c; /* Flashing the LED each time a character is received.*/ palSetPad(GPIOE, GPIOE_LED3_RED); chSysLockFromIsr(); if (chVTIsArmedI(&vt2)) chVTResetI(&vt2); chVTSetI(&vt2, MS2ST(200), ledoff, NULL); chSysUnlockFromIsr(); }
/* Triggered when the button is pressed or released. The LED4 is set to ON.*/ static void extcb1(EXTDriver *extp, expchannel_t channel) { static VirtualTimer vt4; (void)extp; (void)channel; palSetPad(GPIOC, GPIOC_LED4); chSysLockFromIsr(); if (chVTIsArmedI(&vt4)) chVTResetI(&vt4); /* LED4 set to OFF after 200mS.*/ chVTSetI(&vt4, MS2ST(200), led4off, NULL); chSysUnlockFromIsr(); }
void statusLedPulse(int led, systime_t duration) { chSysLock(); switch(led) { case 1: if (chVTIsArmedI(&vt1)) chVTResetI(&vt1); else palSetPad(IOPORT2, GPIOB_LED1); chVTSetI(&vt1, duration, ledoff_1, NULL); break; case 2: if (chVTIsArmedI(&vt2)) chVTResetI(&vt2); else palSetPad(IOPORT2, GPIOB_LED2); chVTSetI(&vt2, duration, ledoff_2, NULL); break; } chSysUnlock(); }
void LedRGB_t::IStartSequenceI(const LedChunk_t *PLedChunk) { // Reset timer if(chVTIsArmedI(&ITmr)) chVTResetI(&ITmr); // Process the sequence while(PLedChunk != nullptr) { // Uart.Printf("\rCh %u", PLedChunk->ChunkSort); switch(PLedChunk->ChunkSort) { case csSetColor: if(ICurrColor != PLedChunk->Color) { if(PLedChunk->SmoothVar == 0) { // If smooth time is zero, SetColor(PLedChunk->Color); // set color now, PLedChunk++; // and goto next chunk } else { // Adjust color ICurrColor.Adjust(&PLedChunk->Color); ISetCurrent(); // Check if completed now if(ICurrColor == PLedChunk->Color) PLedChunk++; else { // Not completed // Calculate time to next adjustment uint32_t DelayR = (ICurrColor.Red == PLedChunk->Color.Red )? 0 : ICalcDelay(ICurrColor.Red, PLedChunk->SmoothVar); uint32_t DelayG = (ICurrColor.Green == PLedChunk->Color.Green)? 0 : ICalcDelay(ICurrColor.Green, PLedChunk->SmoothVar); uint32_t DelayB = (ICurrColor.Blue == PLedChunk->Color.Blue )? 0 : ICalcDelay(ICurrColor.Blue, PLedChunk->SmoothVar); uint32_t Delay = DelayR; if(DelayG > Delay) Delay = DelayG; if(DelayB > Delay) Delay = DelayB; chVTSetI(&ITmr, MS2ST(Delay), LedTmrCallback, (void*)PLedChunk); return; } // Not completed } // if time > 256 } // if color is different else PLedChunk++; // Color is the same, goto next chunk break; case csWait: // Start timer, pointing to next chunk chVTSetI(&ITmr, MS2ST(PLedChunk->Time_ms), LedTmrCallback, (void*)(PLedChunk+1)); return; break; case csJump: PLedChunk = IPStartChunk + PLedChunk->ChunkToJumpTo; break; case csEnd: IPStartChunk = nullptr; return; break; } // switch } // while }
/** * @brief Puts the current thread to sleep into the specified state with * timeout specification. * @details The thread goes into a sleeping state, if it is not awakened * explicitly within the specified timeout then it is forcibly * awakened with a @p RDY_TIMEOUT low level message. The possible * @ref thread_states are defined into @p threads.h. * * @param[in] newstate the new thread state * @param[in] time the number of ticks before the operation timeouts, the * special values are handled as follow: * - @a TIME_INFINITE the thread enters an infinite sleep * state, this is equivalent to invoking * @p chSchGoSleepS() but, of course, less efficient. * - @a TIME_IMMEDIATE this value is not allowed. * . * @return The wakeup message. * @retval RDY_TIMEOUT if a timeout occurs. * * @sclass */ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { if (TIME_INFINITE != time) { VirtualTimer vt; chVTSetI(&vt, time, wakeup, currp); chSchGoSleepS(newstate); if (chVTIsArmedI(&vt)) chVTResetI(&vt); } else chSchGoSleepS(newstate); return currp->p_u.rdymsg; }
/* * Note that this packet is stored and sent in another thread after a delay. The delay is done * in case that this packet is a request from the (Qt) client, which means that more requests * can come within a short time. We want to give the additional requests a chance to arrive * before blocking the RF channel by sending the response. */ void comm_cc2520_send_packet(uint8_t *data, uint8_t len) { memcpy(tx_buffer[tx_slot_write], data, len); tx_slot_len[tx_slot_write] = len; tx_slot_write++; if (tx_slot_write >= TX_BUFFER_SLOTS) { tx_slot_write = 0; } chSysLock(); if (!chVTIsArmedI(&vt)) { chVTSetI(&vt, US2ST(TX_DELAY_US), wakeup_tx, NULL); } chSysUnlock(); }
void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par) { bool wasLocked = lockAnyContext(); /** * todo: this could be simplified once we migrate to ChibiOS 3.0 * See http://www.chibios.org/dokuwiki/doku.php?id=chibios:howtos:porting_from_2_to_3 */ if (chVTIsArmedI(vtp)) { chVTResetI(vtp); } chVTSetI(vtp, time, vtfunc, par); if (!wasLocked) { unlockAnyContext(); } }
/** * @brief Plays a tone asynchronously. * * @param[in] freq approximated tone frequency * @param[in] duration tone duration in systicks */ void buzzPlay(uint32_t freq, systime_t duration) { static VirtualTimer bvt; TC *tc = T1Base; chSysLock(); if (chVTIsArmedI(&bvt)) { /* If a sound is already being */ chVTResetI(&bvt); /* played then aborts it. */ StopCounter(tc); } tc->TC_MR0 = tc->TC_MR1 = (PCLK / (freq * 2)); StartCounter(tc); chVTSetI(&bvt, duration, stop, tc); chSysUnlock(); }
/*! Triggered when the WKUP button is pressed or released. The LED is set to ON. * * Challenge: Add de-bouncing */ void extdetail_wkup_btn(EXTDriver *extp, expchannel_t channel) { static VirtualTimer vt4; (void)extp; (void)channel; palClearPad(GPIOC, GPIOC_LED); chSysLockFromIsr(); chEvtBroadcastI(&extdetail_wkup_event); if (chVTIsArmedI(&vt4)) chVTResetI(&vt4); /* LED4 set to OFF after 500mS.*/ chVTSetI(&vt4, MS2ST(500), green_led_off, NULL); chSysUnlockFromIsr(); }
/** * @brief Puts the current thread to sleep into the specified state with * timeout specification. * @details The thread goes into a sleeping state, if it is not awakened * explicitly within the specified timeout then it is forcibly * awakened with a @p MSG_TIMEOUT low level message. The possible * @ref thread_states are defined into @p threads.h. * * @param[in] newstate the new thread state * @param[in] time the number of ticks before the operation timeouts, the * special values are handled as follow: * - @a TIME_INFINITE the thread enters an infinite sleep * state, this is equivalent to invoking * @p chSchGoSleepS() but, of course, less efficient. * - @a TIME_IMMEDIATE this value is not allowed. * . * @return The wakeup message. * @retval MSG_TIMEOUT if a timeout occurs. * * @sclass */ msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) { chDbgCheckClassS(); if (TIME_INFINITE != time) { virtual_timer_t vt; chVTDoSetI(&vt, time, wakeup, currp); chSchGoSleepS(newstate); if (chVTIsArmedI(&vt)) chVTDoResetI(&vt); } else { chSchGoSleepS(newstate); } return currp->p_u.rdymsg; }
void scheduleTask(const char *prefix, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) { int delaySt = delayUs * CH_FREQUENCY / 1000000; if (delaySt == 0) { /** * in case of zero delay, we should invoke the callback */ callback(param); return; } lockAnyContext(); int isArmed = chVTIsArmedI(&scheduling->timer); if (isArmed) chVTResetI(&scheduling->timer); chVTSetI(&scheduling->timer, delaySt, (vtfunc_t)callback, param); unlockAnyContext(); }
/** * @brief Master receive. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] addr slave device address (7 bits) without R/W bit * @param[out] rxbuf receive data buffer pointer * @param[in] rxbytes number of bytes to be received * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. * . * * @notapi */ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) { VirtualTimer vt; /* Global timeout for the whole operation.*/ if (timeout != TIME_INFINITE) chVTSetI(&vt, timeout, i2c_lld_safety_timeout, (void *)i2cp); i2cp->addr = addr; i2cp->txbuf = NULL; i2cp->txbytes = 0; i2cp->txidx = 0; i2cp->rxbuf = rxbuf; i2cp->rxbytes = rxbytes; i2cp->rxidx = 0; /* Setup device.*/ bscdevice_t *device = i2cp->device; device->slaveAddress = addr; device->dataLength = rxbytes; device->status = CLEAR_STATUS; /* Enable Interrupts and start transfer.*/ device->control = (BSC_INTR | BSC_INTD | START_READ); // needed? there is an outer lock already chSysLock(); i2cp->thread = chThdSelf(); chSchGoSleepS(THD_STATE_SUSPENDED); if ((timeout != TIME_INFINITE) && chVTIsArmedI(&vt)) chVTResetI(&vt); chSysUnlock(); return chThdSelf()->p_u.rdymsg; }
void App_t::SaveSettings() { chSysLock(); if(chVTIsArmedI(&ITmrSaving)) chVTResetI(&ITmrSaving); // Reset timer chVTSetEvtI(&ITmrSaving, S2ST(4), EVTMSK_SAVE); chSysUnlock(); }
bool Timer::isArmedI(void) { return (bool)chVTIsArmedI(&timer_ref); }
void Timer::resetI() { if (chVTIsArmedI(&timer_ref)) chVTResetI(&timer_ref); }
void App_t::ITask() { while(true) { uint32_t EvtMsk = chEvtWaitAny(ALL_EVENTS); // ==== Card ==== if(EvtMsk & EVTMSK_CARD_APPEARS) ProcessCardAppearance(); #if 1 // ==== Door ==== if(EvtMsk & EVTMSK_DOOR_OPEN) { DoorState = dsOpen; Led.StartSequence(lsqDoorOpen); // Set color SndList.PlayRandomFileFromDir(DIRNAME_GOOD_KEY); Uart.Printf("\rDoor is open"); chSysLock(); if(chVTIsArmedI(&IDoorTmr)) chVTResetI(&IDoorTmr); chVTSetI(&IDoorTmr, MS2ST(DOOR_CLOSE_TIMEOUT), TmrGeneralCallback, (void*)EVTMSK_DOOR_SHUT); chSysUnlock(); } if(EvtMsk & EVTMSK_DOOR_SHUT) { DoorState = dsClosed; Led.StartSequence(lsqDoorClose); // Set color SndList.PlayRandomFileFromDir(DIRNAME_DOOR_CLOSING); Uart.Printf("\rDoor is closing"); } if(EvtMsk & EVTMSK_BAD_KEY) { Led.StartSequence(lsqDoorWrongKey); SndList.PlayRandomFileFromDir(DIRNAME_BAD_KEY); Uart.Printf("\rBadKey"); } #endif #if 1 // ==== Secret key ==== if(EvtMsk & EVTMSK_SECRET_KEY) { Led.StartSequence(lsqDoorSecretKey); SndList.PlayRandomFileFromDir(DIRNAME_SECRET); Uart.Printf("\rSecretKey"); } #endif #if 1 // ==== Keys ==== if(EvtMsk & EVTMSK_KEYS) { KeyEvtInfo_t EInfo; while(Keys.EvtBuf.Get(&EInfo) == OK) { // Uart.Printf("\rEinfo: %u, %u, %u", EInfo.Type, EInfo.KeysCnt, EInfo.KeyID[0]); if(EInfo.Type == kePress) { switch(EInfo.KeyID[0]) { // Iterate AccessAdd / AccessRemove / Idle case keyA: switch(State) { case asAddingAccess: EnterState(asRemovingAccess); break; case asRemovingAccess: EnterState(asIdle); break; default: EnterState(asAddingAccess); break; } // switch State break; // Iterate AdderAdd / AdderRemove / Idle case keyB: switch(State) { case asAddingAdder: EnterState(asRemovingAdder); break; case asRemovingAdder: EnterState(asIdle); break; default: EnterState(asAddingAdder); break; } // switch State break; // Iterate RemoverAdd / RemoverRemove / Idle case keyC: switch(State) { case asAddingRemover: EnterState(asRemovingRemover); break; case asRemovingRemover: EnterState(asIdle); break; default: EnterState(asAddingRemover); break; } // switch State break; } // switch } // if keypress else if(EInfo.Type == keCombo and EInfo.KeyID[0] == keyA and EInfo.KeyID[1] == keyB) { LedService.StartSequence(lsqEraseAll); IDStore.EraseAll(); chThdSleepMilliseconds(1530); // Allow LED to complete blinking EnterState(asIdle); } } // while } // if keys #endif #if USB_ENABLED // ==== USB connection ==== if(EvtMsk & EVTMSK_USB_CONNECTED) { chSysLock(); Clk.SetFreq48Mhz(); Clk.InitSysTick(); chSysUnlock(); Usb.Init(); chThdSleepMilliseconds(540); Usb.Connect(); Uart.Printf("\rUsb connected, AHB freq=%uMHz", Clk.AHBFreqHz/1000000); } if(EvtMsk & EVTMSK_USB_DISCONNECTED) { Usb.Shutdown(); MassStorage.Reset(); chSysLock(); Clk.SetFreq12Mhz(); Clk.InitSysTick(); chSysUnlock(); Uart.Printf("\rUsb disconnected, AHB freq=%uMHz", Clk.AHBFreqHz/1000000); } #endif // ==== State timeout ==== if(EvtMsk & EVTMSK_STATE_TIMEOUT) EnterState(asIdle); } // while true }
bool Timer::IsArmed(void) { return chVTIsArmedI(&timer); }