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_modutil.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#include "dma_api.h"
|
#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);
|
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool serial_can_deep_sleep(void);
|
||||||
|
|
||||||
static struct nu_uart_var uart0_var = {
|
static struct nu_uart_var uart0_var = {
|
||||||
.ref_cnt = 0,
|
.ref_cnt = 0,
|
||||||
.obj = NULL,
|
.obj = NULL,
|
||||||
|
@ -1171,4 +1174,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if DEVICE_SERIAL_ASYNCH
|
#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
|
#endif // #if DEVICE_SERIAL
|
||||||
|
|
|
@ -22,9 +22,14 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
#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.
|
* Enter idle mode, in which just CPU is halted.
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +47,12 @@ void hal_sleep(void)
|
||||||
__NONSECURE_ENTRY
|
__NONSECURE_ENTRY
|
||||||
void hal_deepsleep(void)
|
void hal_deepsleep(void)
|
||||||
{
|
{
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
if (!serial_can_deep_sleep()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
CLK_PowerDown();
|
CLK_PowerDown();
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "nu_modutil.h"
|
#include "nu_modutil.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#include "dma_api.h"
|
#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);
|
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool serial_can_deep_sleep(void);
|
||||||
|
|
||||||
static struct nu_uart_var uart0_var = {
|
static struct nu_uart_var uart0_var = {
|
||||||
.ref_cnt = 0,
|
.ref_cnt = 0,
|
||||||
.obj = NULL,
|
.obj = NULL,
|
||||||
|
@ -1088,4 +1091,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if DEVICE_SERIAL_ASYNCH
|
#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
|
#endif // #if DEVICE_SERIAL
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "PeripheralPins.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.
|
* Enter idle mode, in which just CPU is halted.
|
||||||
|
@ -38,6 +43,12 @@ void hal_sleep(void)
|
||||||
*/
|
*/
|
||||||
void hal_deepsleep(void)
|
void hal_deepsleep(void)
|
||||||
{
|
{
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
if (!serial_can_deep_sleep()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
CLK_PowerDown();
|
CLK_PowerDown();
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "nu_modutil.h"
|
#include "nu_modutil.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#include "dma_api.h"
|
#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);
|
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool serial_can_deep_sleep(void);
|
||||||
|
|
||||||
static struct nu_uart_var uart0_var = {
|
static struct nu_uart_var uart0_var = {
|
||||||
.ref_cnt = 0,
|
.ref_cnt = 0,
|
||||||
.obj = NULL,
|
.obj = NULL,
|
||||||
|
@ -1145,4 +1148,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if DEVICE_SERIAL_ASYNCH
|
#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
|
#endif // #if DEVICE_SERIAL
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "PeripheralPins.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.
|
* Enter idle mode, in which just CPU is halted.
|
||||||
|
@ -38,6 +43,12 @@ void hal_sleep(void)
|
||||||
*/
|
*/
|
||||||
void hal_deepsleep(void)
|
void hal_deepsleep(void)
|
||||||
{
|
{
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
if (!serial_can_deep_sleep()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
CLK_PowerDown();
|
CLK_PowerDown();
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
|
@ -18,13 +18,14 @@
|
||||||
|
|
||||||
#if DEVICE_SERIAL
|
#if DEVICE_SERIAL
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
#include "nu_modutil.h"
|
#include "nu_modutil.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#include "dma_api.h"
|
#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);
|
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool serial_can_deep_sleep(void);
|
||||||
|
|
||||||
static struct nu_uart_var uart0_var = {
|
static struct nu_uart_var uart0_var = {
|
||||||
.ref_cnt = 0,
|
.ref_cnt = 0,
|
||||||
.obj = NULL,
|
.obj = NULL,
|
||||||
|
@ -990,4 +993,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if DEVICE_SERIAL_ASYNCH
|
#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
|
#endif // #if DEVICE_SERIAL
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "PeripheralPins.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.
|
* Enter idle mode, in which just CPU is halted.
|
||||||
|
@ -38,6 +43,12 @@ void hal_sleep(void)
|
||||||
*/
|
*/
|
||||||
void hal_deepsleep(void)
|
void hal_deepsleep(void)
|
||||||
{
|
{
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
if (!serial_can_deep_sleep()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
CLK_PowerDown();
|
CLK_PowerDown();
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "nu_modutil.h"
|
#include "nu_modutil.h"
|
||||||
#include "nu_bitutil.h"
|
#include "nu_bitutil.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#include "dma_api.h"
|
#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);
|
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool serial_can_deep_sleep(void);
|
||||||
|
|
||||||
static struct nu_uart_var uart0_var = {
|
static struct nu_uart_var uart0_var = {
|
||||||
.ref_cnt = 0,
|
.ref_cnt = 0,
|
||||||
.obj = NULL,
|
.obj = NULL,
|
||||||
|
@ -1136,4 +1139,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if DEVICE_SERIAL_ASYNCH
|
#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
|
#endif // #if DEVICE_SERIAL
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
#include "PeripheralPins.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.
|
* Enter idle mode, in which just CPU is halted.
|
||||||
|
@ -38,6 +43,12 @@ void hal_sleep(void)
|
||||||
*/
|
*/
|
||||||
void hal_deepsleep(void)
|
void hal_deepsleep(void)
|
||||||
{
|
{
|
||||||
|
#if DEVICE_SERIAL
|
||||||
|
if (!serial_can_deep_sleep()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
CLK_PowerDown();
|
CLK_PowerDown();
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
Loading…
Reference in New Issue