USART: Split RX driver between L and F families

The USART peripheral in the L and F families is different enough to need
different receive drivers.  In particular, the L family USART perihperal
has no way of disabling the overflow error bit.  So for that family we
check and clear the bit, and keep a count of overflows.

Signed-off-by: Anton Staaf <robotboy@chromium.org>

BRANCH=None
BUG=None
TEST=make buildall -j

Change-Id: Iea26c242d5177afd552a3bd4d6ab1a9c7a65f90e
Reviewed-on: https://chromium-review.googlesource.com/288978
Trybot-Ready: Anton Staaf <robotboy@chromium.org>
Tested-by: Anton Staaf <robotboy@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Anton Staaf <robotboy@chromium.org>
This commit is contained in:
Anton Staaf
2015-07-28 10:30:44 -07:00
committed by ChromeOS Commit Bot
parent 77f68f204f
commit 014d180b1d
8 changed files with 91 additions and 14 deletions

View File

@@ -35,7 +35,8 @@ chip-$(CONFIG_COMMON_GPIO)+=gpio.o gpio-$(CHIP_FAMILY).o
chip-$(CONFIG_COMMON_TIMER)+=hwtimer$(TIMER_TYPE).o
chip-$(CONFIG_I2C)+=i2c-$(CHIP_FAMILY).o
chip-$(CONFIG_STREAM_USART)+=usart.o usart-$(CHIP_FAMILY).o
chip-$(CONFIG_STREAM_USART)+=usart_rx_interrupt.o usart_tx_interrupt.o
chip-$(CONFIG_STREAM_USART)+=usart_rx_interrupt-$(CHIP_FAMILY).o
chip-$(CONFIG_STREAM_USART)+=usart_tx_interrupt.o
chip-$(CONFIG_STREAM_USART)+=usart_tx_dma.o
chip-$(CONFIG_STREAM_USB)+=usb-stream.o
chip-$(CONFIG_WATCHDOG)+=watchdog.o

View File

@@ -189,16 +189,19 @@
#define STM32_USART_RQR(base) STM32_USART_REG(base, 0x18)
#define STM32_USART_ISR(base) STM32_USART_REG(base, 0x1C)
#define STM32_USART_ICR(base) STM32_USART_REG(base, 0x20)
#define STM32_USART_ICR_ORECF (1 << 3)
#define STM32_USART_ICR_TCCF (1 << 6)
#define STM32_USART_RDR(base) STM32_USART_REG(base, 0x24)
#define STM32_USART_TDR(base) STM32_USART_REG(base, 0x28)
/* register alias */
#define STM32_USART_SR(base) STM32_USART_ISR(base)
#define STM32_USART_SR_ORE (1 << 3)
#define STM32_USART_SR_RXNE (1 << 5)
#define STM32_USART_SR_TC (1 << 6)
#define STM32_USART_SR_TXE (1 << 7)
#else /* !CHIP_FAMILY_STM32F0 */
#define STM32_USART_SR(base) STM32_USART_REG(base, 0x00)
#define STM32_USART_SR_ORE (1 << 3)
#define STM32_USART_SR_RXNE (1 << 5)
#define STM32_USART_SR_TC (1 << 6)
#define STM32_USART_SR_TXE (1 << 7)

View File

@@ -42,7 +42,7 @@ void usart_init(struct usart_config const *config)
*/
STM32_USART_CR1(base) = 0x0000;
STM32_USART_CR2(base) = 0x0000;
STM32_USART_CR3(base) = STM32_USART_CR3_OVRDIS;
STM32_USART_CR3(base) = 0x0000;
/*
* Enable the RX, TX, and variant specific HW.
@@ -51,6 +51,12 @@ void usart_init(struct usart_config const *config)
config->tx->init(config);
config->hw->ops->enable(config);
/*
* Clear error counts.
*/
config->state->rx_overrun = 0;
config->state->rx_dropped = 0;
/*
* Enable the USART, this must be done last since most of the
* configuration bits require that the USART be disabled for writes to
@@ -98,6 +104,6 @@ void usart_set_baud_f(struct usart_config const *config, int frequency_hz)
void usart_interrupt(struct usart_config const *config)
{
config->tx->interrupt(config);
config->rx->interrupt(config);
}
config->tx->interrupt(config);
config->rx->interrupt(config);
}

View File

@@ -24,6 +24,7 @@ struct usart_state {
* in the RX queue.
*/
uint32_t rx_dropped;
uint32_t rx_overrun;
};
struct usart_config;

View File

@@ -0,0 +1 @@
usart_rx_interrupt.c

View File

@@ -0,0 +1 @@
usart_rx_interrupt.c

View File

@@ -0,0 +1,64 @@
/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Interrupt based USART RX driver for STM32L */
#include "usart.h"
#include "atomic.h"
#include "common.h"
#include "queue.h"
#include "registers.h"
static void usart_rx_init(struct usart_config const *config)
{
intptr_t base = config->hw->base;
STM32_USART_CR1(base) |= STM32_USART_CR1_RXNEIE;
STM32_USART_CR1(base) |= STM32_USART_CR1_RE;
}
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);
}
}
struct usart_rx const usart_rx_interrupt = {
.producer_ops = {
/*
* Nothing to do here, we either had enough space in the queue
* when a character came in or we dropped it already.
*/
.read = NULL,
},
.init = usart_rx_init,
.interrupt = usart_rx_interrupt_handler,
};

View File

@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
/* Interrupt based USART RX driver for STM32 */
/* Interrupt based USART RX driver for STM32F0 and STM32F3 */
#include "usart.h"
@@ -18,20 +18,20 @@ static void usart_rx_init(struct usart_config const *config)
STM32_USART_CR1(base) |= STM32_USART_CR1_RXNEIE;
STM32_USART_CR1(base) |= STM32_USART_CR1_RE;
STM32_USART_CR3(base) |= STM32_USART_CR3_OVRDIS;
}
static void usart_rx_interrupt_handler(struct usart_config const *config)
{
intptr_t base = config->hw->base;
uint8_t byte;
intptr_t base = config->hw->base;
int32_t status = STM32_USART_SR(base);
if (!(STM32_USART_SR(base) & STM32_USART_SR_RXNE))
return;
if (status & STM32_USART_SR_RXNE) {
uint8_t byte = STM32_USART_RDR(base);
byte = STM32_USART_RDR(base);
if (!queue_add_unit(config->producer.queue, &byte))
atomic_add(&config->state->rx_dropped, 1);
if (!queue_add_unit(config->producer.queue, &byte))
atomic_add(&config->state->rx_dropped, 1);
}
}
struct usart_rx const usart_rx_interrupt = {