From b8b54a033c67e2dbb98dabda6d1b4c9e64d5db90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 15 Nov 2013 17:24:26 +0100 Subject: [PATCH] cc2538: uart: Fix crippled output occurring upon lpm_enter() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lpm_enter() must not enter PM1+ if the UART TX FIFO is not empty. Otherwise, the UART clock gets disabled, and its TX is broken. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/dev/uart.c | 12 ++++++++++++ cpu/cc2538/lpm.c | 2 +- cpu/cc2538/lpm.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index 8545cf4e2..304f717db 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -41,8 +41,10 @@ #include "dev/ioc.h" #include "dev/gpio.h" #include "dev/uart.h" +#include "lpm.h" #include "reg.h" +#include #include #include @@ -96,9 +98,19 @@ reset(void) REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; } /*---------------------------------------------------------------------------*/ +static bool +permit_pm1(void) +{ + /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ + return (REG(SYS_CTRL_RCGCUART) & SYS_CTRL_RCGCUART_UART) == 0 || + (REG(UART_BASE | UART_FR) & UART_FR_TXFE) != 0; +} +/*---------------------------------------------------------------------------*/ void uart_init(void) { + lpm_register_peripheral(permit_pm1); + /* Enable clock for the UART while Running, in Sleep and Deep Sleep */ REG(SYS_CTRL_RCGCUART) |= SYS_CTRL_RCGCUART_UART; REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_SCGCUART_UART; diff --git a/cpu/cc2538/lpm.c b/cpu/cc2538/lpm.c index 70dca181e..709665e5b 100644 --- a/cpu/cc2538/lpm.c +++ b/cpu/cc2538/lpm.c @@ -102,7 +102,7 @@ static uint8_t max_pm; #ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #else -#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 1 +#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 2 #endif lpm_periph_permit_pm1_func_t diff --git a/cpu/cc2538/lpm.h b/cpu/cc2538/lpm.h index cd8b2b510..22b4d4958 100644 --- a/cpu/cc2538/lpm.h +++ b/cpu/cc2538/lpm.h @@ -182,7 +182,7 @@ typedef bool (*lpm_periph_permit_pm1_func_t)(void); * \param permit_pm1_func Pointer to the function * * Some peripherals are sensitive to PM changes. For instance, we don't want to - * drop to PM1+ if the USB PLL is active. + * drop to PM1+ if the USB PLL is active or if the UART TX FIFO is not clear. * * When changing power modes, the LPM driver will call all FPs registered with * this function. The peripheral's function will return true or false to permit