mirror of https://github.com/ARMmbed/mbed-os.git
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
parent
d8b35fe41d
commit
bb3875049c
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue