/** * @brief Common IRQ handler. * * @param[in] sdp communication channel associated to the USART */ static void serve_interrupt(SerialDriver *sdp) { USART_TypeDef *u = sdp->usart; uint16_t cr1 = u->CR1; uint16_t sr = u->SR; /* Special case, LIN break detection.*/ if (sr & USART_SR_LBD) { osalSysLockFromISR(); chnAddFlagsI(sdp, SD_BREAK_DETECTED); u->SR = ~USART_SR_LBD; osalSysUnlockFromISR(); } /* Data available.*/ osalSysLockFromISR(); while (sr & (USART_SR_RXNE | USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) { uint8_t b; /* Error condition detection.*/ if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) set_error(sdp, sr); b = (uint8_t)u->DR & sdp->rxmask; if (sr & USART_SR_RXNE) sdIncomingDataI(sdp, b); sr = u->SR; } osalSysUnlockFromISR(); /* Transmission buffer empty.*/ if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) { msg_t b; osalSysLockFromISR(); b = oqGetI(&sdp->oqueue); if (b < MSG_OK) { chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; } else u->DR = b; osalSysUnlockFromISR(); } /* Physical transmission end.*/ if ((cr1 & USART_CR1_TCIE) && (sr & USART_SR_TC)) { osalSysLockFromISR(); if (oqIsEmptyI(&sdp->oqueue)) { chnAddFlagsI(sdp, CHN_TRANSMISSION_END); u->CR1 = cr1 & ~USART_CR1_TCIE; } osalSysUnlockFromISR(); } }
/** * @brief Common IRQ handler. * * @param[in] sdp communication channel associated to the USART */ static void serve_interrupt(SerialDriver *sdp) { USART_TypeDef *u = sdp->usart; uint32_t cr1 = u->CR1; uint32_t isr; /* Reading and clearing status.*/ isr = u->ISR; u->ICR = isr; /* Error condition detection.*/ if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)) set_error(sdp, isr); /* Special case, LIN break detection.*/ if (isr & USART_ISR_LBDF) { osalSysLockFromISR(); chnAddFlagsI(sdp, SD_BREAK_DETECTED); osalSysUnlockFromISR(); } /* Data available.*/ if (isr & USART_ISR_RXNE) { osalSysLockFromISR(); sdIncomingDataI(sdp, (uint8_t)u->RDR); osalSysUnlockFromISR(); } /* Transmission buffer empty.*/ if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) { msg_t b; osalSysLockFromISR(); b = oqGetI(&sdp->oqueue); if (b < Q_OK) { chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; } else u->TDR = b; osalSysUnlockFromISR(); } /* Physical transmission end.*/ if (isr & USART_ISR_TC) { osalSysLockFromISR(); if (oqIsEmptyI(&sdp->oqueue)) chnAddFlagsI(sdp, CHN_TRANSMISSION_END); u->CR1 = cr1 & ~USART_CR1_TCIE; osalSysUnlockFromISR(); } }
/** * @brief Output queue read. * @details A byte value is read from the low end of an output queue. * * @param[in] oqp pointer to an @p output_queue_t structure * @return The byte value from the queue. * @retval Q_EMPTY if the queue is empty. * * @iclass */ msg_t oqGetI(output_queue_t *oqp) { uint8_t b; osalDbgCheckClassI(); if (oqIsEmptyI(oqp)) { return Q_EMPTY; } oqp->q_counter++; b = *oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) { oqp->q_rdptr = oqp->q_buffer; } osalThreadDequeueNextI(&oqp->q_waiting, Q_OK); return (msg_t)b; }