aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-04-19 07:49:28 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-04-19 07:49:28 +0000
commitd52ee81b3a0704e8e1e40b6acf3ff03199905303 (patch)
tree33b856218dae7902cffb9f6edd027a13aeafec78 /os/hal
parente2dbf2c514226554968e0e984201d2859011bd62 (diff)
downloadChibiOS-d52ee81b3a0704e8e1e40b6acf3ff03199905303.tar.gz
ChibiOS-d52ee81b3a0704e8e1e40b6acf3ff03199905303.tar.bz2
ChibiOS-d52ee81b3a0704e8e1e40b6acf3ff03199905303.zip
Fixed bug #584.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7905 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/STM32/LLD/USARTv1/uart_lld.c24
-rw-r--r--os/hal/ports/STM32/LLD/USARTv2/uart_lld.c22
2 files changed, 33 insertions, 13 deletions
diff --git a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c
index e72104c7b..44324fc7e 100644
--- a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c
+++ b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c
@@ -222,11 +222,10 @@ static void usart_start(UARTDriver *uartp) {
u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
USART_CR3_EIE;
- if (uartp->config->txend2_cb == NULL)
- cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
- else
- cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE |
- USART_CR1_TCIE;
+
+ /* Mustn't ever set TCIE here - if done, it causes an immediate
+ interrupt.*/
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
u->CR1 = uartp->config->cr1 | cr1;
/* Starting the receiver idle loop.*/
@@ -292,6 +291,12 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
dmaStreamDisable(uartp->dmatx);
+ /* Only enable TC interrupt if there's a callback attached to it.
+ We have to do it here, rather than earlier, because TC flag is set
+ until transmission starts.*/
+ if (uartp->config->txend2_cb != NULL)
+ uartp->usart->CR1 |= USART_CR1_TCIE;
+
/* A callback is generated, if enabled, after a completed transfer.*/
uartp->txstate = UART_TX_COMPLETE;
if (uartp->config->txend1_cb != NULL)
@@ -311,17 +316,22 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
static void serve_usart_irq(UARTDriver *uartp) {
uint16_t sr;
USART_TypeDef *u = uartp->usart;
-
+ uint32_t cr1 = u->CR1;
+
sr = u->SR; /* SR reset step 1.*/
(void)u->DR; /* SR reset step 2.*/
+
if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE |
USART_SR_FE | USART_SR_PE)) {
u->SR = ~USART_SR_LBD;
if (uartp->config->rxerr_cb != NULL)
uartp->config->rxerr_cb(uartp, translate_errors(sr));
}
- if (sr & USART_SR_TC) {
+
+ if ((sr & USART_SR_TC) && (cr1 & USART_CR1_TCIE)) {
+ /* TC interrupt cleared and disabled.*/
u->SR = ~USART_SR_TC;
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
/* End of transmission, a callback is generated.*/
if (uartp->config->txend2_cb != NULL)
diff --git a/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c b/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c
index 61cbe3ac7..1cce68503 100644
--- a/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c
+++ b/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c
@@ -176,11 +176,10 @@ static void usart_start(UARTDriver *uartp) {
u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
USART_CR3_EIE;
- if (uartp->config->txend2_cb == NULL)
- cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
- else
- cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE |
- USART_CR1_TCIE;
+
+ /* Mustn't ever set TCIE here - if done, it causes an immediate
+ interrupt.*/
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
u->CR1 = uartp->config->cr1 | cr1;
/* Starting the receiver idle loop.*/
@@ -246,6 +245,12 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
dmaStreamDisable(uartp->dmatx);
+ /* Only enable TC interrupt if there's a callback attached to it.
+ We have to do it here, rather than earlier, because TC flag is set
+ until transmission starts.*/
+ if (uartp->config->txend2_cb != NULL)
+ uartp->usart->CR1 |= USART_CR1_TCIE;
+
/* A callback is generated, if enabled, after a completed transfer.*/
uartp->txstate = UART_TX_COMPLETE;
if (uartp->config->txend1_cb != NULL)
@@ -265,6 +270,7 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
static void serve_usart_irq(UARTDriver *uartp) {
uint32_t isr;
USART_TypeDef *u = uartp->usart;
+ uint32_t cr1 = u->CR1;
/* Reading and clearing status.*/
isr = u->ISR;
@@ -275,7 +281,11 @@ static void serve_usart_irq(UARTDriver *uartp) {
if (uartp->config->rxerr_cb != NULL)
uartp->config->rxerr_cb(uartp, translate_errors(isr));
}
- if (isr & USART_ISR_TC) {
+
+ if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) {
+ /* TC interrupt disabled.*/
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+
/* End of transmission, a callback is generated.*/
if (uartp->config->txend2_cb != NULL)
uartp->config->txend2_cb(uartp);