static void usart_tx_interrupt_handler(struct usart_config const *config)
{
	intptr_t base = config->hw->base;
	uint8_t  byte;

	if (!(STM32_USART_SR(base) & STM32_USART_SR_TXE))
		return;

	if (queue_remove_unit(config->consumer.queue, &byte)) {
		STM32_USART_TDR(base) = byte;

		/*
		 * Make sure the TXE interrupt is enabled and that we won't go
		 * into deep sleep.  This invocation of the USART interrupt
		 * handler may have been manually triggered to start
		 * transmission.
		 */
		disable_sleep(SLEEP_MASK_UART);

		STM32_USART_CR1(base) |= STM32_USART_CR1_TXEIE;
	} else {
		/*
		 * The TX queue is empty, disable the TXE interrupt and enable
		 * deep sleep mode. The TXE interrupt will remain disabled
		 * until a write call happens.
		 */
		enable_sleep(SLEEP_MASK_UART);

		STM32_USART_CR1(base) &= ~STM32_USART_CR1_TXEIE;
	}
}
static void usart_rx_interrupt_handler(struct usart_config const *config)
{
	intptr_t base   = config->hw->base;
	int32_t  status = STM32_USART_SR(base);

	/*
	 * We have to check and clear the overrun error flag on STM32L because
	 * we can't disable it.
	 */
	if (status & STM32_USART_SR_ORE) {
		/*
		 * In the unlikely event that the overrun error bit was set but
		 * the RXNE bit was not (possibly because a read was done from
		 * RDR without first reading the status register) we do a read
		 * here to clear the overrun error bit.
		 */
		if (!(status & STM32_USART_SR_RXNE))
			(void)STM32_USART_RDR(config->hw->base);

		atomic_add(&config->state->rx_overrun, 1);
	}

	if (status & STM32_USART_SR_RXNE) {
		uint8_t byte = STM32_USART_RDR(base);

		if (!queue_add_unit(config->producer.queue, &byte))
			atomic_add(&config->state->rx_dropped, 1);
	}
}
Beispiel #3
0
void usart_clear_tc(struct usart_config const *config)
{
	STM32_USART_SR(config->hw->base) &= ~STM32_USART_SR_TC;
}