Fix serial corruption due to deep sleep

Prevent deep sleep when there is still any character being transmitted on the UART.
This allows tickless to be safely enabled.
pull/8479/head
ccli8 2018-08-13 14:25:27 +08:00 committed by adbridge
parent d8b35fe41d
commit bb3875049c
10 changed files with 166 additions and 1 deletions

View File

@ -25,6 +25,7 @@
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include <string.h>
#include <stdbool.h>
#if DEVICE_SERIAL_ASYNCH
#include "dma_api.h"
@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif
bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = {
.ref_cnt = 0,
.obj = NULL,
@ -1171,4 +1174,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
}
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void)
{
bool sleep_allowed = 1;
const struct nu_modinit_s *modinit = uart_modinit_tab;
while (modinit->var != NULL) {
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
if (uart_var->ref_cnt > 0) {
if (!UART_IS_TX_EMPTY(uart_base)) {
sleep_allowed = 0;
break;
}
}
modinit++;
}
return sleep_allowed;
}
#endif // #if DEVICE_SERIAL

View File

@ -22,9 +22,14 @@
#include "device.h"
#include "objects.h"
#include "PeripheralPins.h"
#include <stdbool.h>
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
#if DEVICE_SERIAL
bool serial_can_deep_sleep(void);
#endif
/**
* Enter idle mode, in which just CPU is halted.
*/
@ -42,6 +47,12 @@ void hal_sleep(void)
__NONSECURE_ENTRY
void hal_deepsleep(void)
{
#if DEVICE_SERIAL
if (!serial_can_deep_sleep()) {
return;
}
#endif
SYS_UnlockReg();
CLK_PowerDown();
SYS_LockReg();

View File

@ -25,6 +25,7 @@
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include <string.h>
#include <stdbool.h>
#if DEVICE_SERIAL_ASYNCH
#include "dma_api.h"
@ -83,6 +84,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif
bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = {
.ref_cnt = 0,
.obj = NULL,
@ -1088,4 +1091,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
}
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void)
{
bool sleep_allowed = 1;
const struct nu_modinit_s *modinit = uart_modinit_tab;
while (modinit->var != NULL) {
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
if (uart_var->ref_cnt > 0) {
if (!UART_IS_TX_EMPTY(uart_base)) {
sleep_allowed = 0;
break;
}
}
modinit++;
}
return sleep_allowed;
}
#endif // #if DEVICE_SERIAL

View File

@ -22,6 +22,11 @@
#include "device.h"
#include "objects.h"
#include "PeripheralPins.h"
#include <stdbool.h>
#if DEVICE_SERIAL
bool serial_can_deep_sleep(void);
#endif
/**
* Enter idle mode, in which just CPU is halted.
@ -38,6 +43,12 @@ void hal_sleep(void)
*/
void hal_deepsleep(void)
{
#if DEVICE_SERIAL
if (!serial_can_deep_sleep()) {
return;
}
#endif
SYS_UnlockReg();
CLK_PowerDown();
SYS_LockReg();

View File

@ -25,6 +25,7 @@
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include <string.h>
#include <stdbool.h>
#if DEVICE_SERIAL_ASYNCH
#include "dma_api.h"
@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif
bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = {
.ref_cnt = 0,
.obj = NULL,
@ -1145,4 +1148,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
}
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void)
{
bool sleep_allowed = 1;
const struct nu_modinit_s *modinit = uart_modinit_tab;
while (modinit->var != NULL) {
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
if (uart_var->ref_cnt > 0) {
if (!UART_IS_TX_EMPTY(uart_base)) {
sleep_allowed = 0;
break;
}
}
modinit++;
}
return sleep_allowed;
}
#endif // #if DEVICE_SERIAL

View File

@ -22,6 +22,11 @@
#include "device.h"
#include "objects.h"
#include "PeripheralPins.h"
#include <stdbool.h>
#if DEVICE_SERIAL
bool serial_can_deep_sleep(void);
#endif
/**
* Enter idle mode, in which just CPU is halted.
@ -38,6 +43,12 @@ void hal_sleep(void)
*/
void hal_deepsleep(void)
{
#if DEVICE_SERIAL
if (!serial_can_deep_sleep()) {
return;
}
#endif
SYS_UnlockReg();
CLK_PowerDown();
SYS_LockReg();

View File

@ -18,13 +18,14 @@
#if DEVICE_SERIAL
#include <string.h>
#include "cmsis.h"
#include "mbed_error.h"
#include "mbed_assert.h"
#include "PeripheralPins.h"
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include <string.h>
#include <stdbool.h>
#if DEVICE_SERIAL_ASYNCH
#include "dma_api.h"
@ -76,6 +77,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif
bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = {
.ref_cnt = 0,
.obj = NULL,
@ -990,4 +993,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
}
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void)
{
bool sleep_allowed = 1;
const struct nu_modinit_s *modinit = uart_modinit_tab;
while (modinit->var != NULL) {
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
if (uart_var->ref_cnt > 0) {
if (!UART_IS_TX_EMPTY(uart_base)) {
sleep_allowed = 0;
break;
}
}
modinit++;
}
return sleep_allowed;
}
#endif // #if DEVICE_SERIAL

View File

@ -22,6 +22,11 @@
#include "device.h"
#include "objects.h"
#include "PeripheralPins.h"
#include <stdbool.h>
#if DEVICE_SERIAL
bool serial_can_deep_sleep(void);
#endif
/**
* Enter idle mode, in which just CPU is halted.
@ -38,6 +43,12 @@ void hal_sleep(void)
*/
void hal_deepsleep(void)
{
#if DEVICE_SERIAL
if (!serial_can_deep_sleep()) {
return;
}
#endif
SYS_UnlockReg();
CLK_PowerDown();
SYS_LockReg();

View File

@ -25,6 +25,7 @@
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include <string.h>
#include <stdbool.h>
#if DEVICE_SERIAL_ASYNCH
#include "dma_api.h"
@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
#endif
bool serial_can_deep_sleep(void);
static struct nu_uart_var uart0_var = {
.ref_cnt = 0,
.obj = NULL,
@ -1136,4 +1139,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
}
#endif // #if DEVICE_SERIAL_ASYNCH
bool serial_can_deep_sleep(void)
{
bool sleep_allowed = 1;
const struct nu_modinit_s *modinit = uart_modinit_tab;
while (modinit->var != NULL) {
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
if (uart_var->ref_cnt > 0) {
if (!UART_IS_TX_EMPTY(uart_base)) {
sleep_allowed = 0;
break;
}
}
modinit++;
}
return sleep_allowed;
}
#endif // #if DEVICE_SERIAL

View File

@ -22,6 +22,11 @@
#include "device.h"
#include "objects.h"
#include "PeripheralPins.h"
#include <stdbool.h>
#if DEVICE_SERIAL
bool serial_can_deep_sleep(void);
#endif
/**
* Enter idle mode, in which just CPU is halted.
@ -38,6 +43,12 @@ void hal_sleep(void)
*/
void hal_deepsleep(void)
{
#if DEVICE_SERIAL
if (!serial_can_deep_sleep()) {
return;
}
#endif
SYS_UnlockReg();
CLK_PowerDown();
SYS_LockReg();