Skip to content

Commit beb04a8

Browse files
committed
[Nuvoton] 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.
1 parent 310b12a commit beb04a8

File tree

10 files changed

+166
-1
lines changed

10 files changed

+166
-1
lines changed

targets/TARGET_NUVOTON/TARGET_M2351/serial_api.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "nu_modutil.h"
2626
#include "nu_bitutil.h"
2727
#include <string.h>
28+
#include <stdbool.h>
2829

2930
#if DEVICE_SERIAL_ASYNCH
3031
#include "dma_api.h"
@@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
8788
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
8889
#endif
8990

91+
bool serial_can_deep_sleep(void);
92+
9093
static struct nu_uart_var uart0_var = {
9194
.ref_cnt = 0,
9295
.obj = NULL,
@@ -1171,4 +1174,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
11711174
}
11721175

11731176
#endif // #if DEVICE_SERIAL_ASYNCH
1177+
1178+
bool serial_can_deep_sleep(void)
1179+
{
1180+
bool sleep_allowed = 1;
1181+
const struct nu_modinit_s *modinit = uart_modinit_tab;
1182+
while (modinit->var != NULL) {
1183+
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
1184+
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
1185+
if (uart_var->ref_cnt > 0) {
1186+
if (!UART_IS_TX_EMPTY(uart_base)) {
1187+
sleep_allowed = 0;
1188+
break;
1189+
}
1190+
}
1191+
modinit++;
1192+
}
1193+
return sleep_allowed;
1194+
}
1195+
11741196
#endif // #if DEVICE_SERIAL

targets/TARGET_NUVOTON/TARGET_M2351/sleep.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@
2222
#include "device.h"
2323
#include "objects.h"
2424
#include "PeripheralPins.h"
25+
#include <stdbool.h>
2526

2627
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
2728

29+
#if DEVICE_SERIAL
30+
bool serial_can_deep_sleep(void);
31+
#endif
32+
2833
/**
2934
* Enter idle mode, in which just CPU is halted.
3035
*/
@@ -42,6 +47,12 @@ void hal_sleep(void)
4247
__NONSECURE_ENTRY
4348
void hal_deepsleep(void)
4449
{
50+
#if DEVICE_SERIAL
51+
if (!serial_can_deep_sleep()) {
52+
return;
53+
}
54+
#endif
55+
4556
SYS_UnlockReg();
4657
CLK_PowerDown();
4758
SYS_LockReg();

targets/TARGET_NUVOTON/TARGET_M451/serial_api.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "nu_modutil.h"
2626
#include "nu_bitutil.h"
2727
#include <string.h>
28+
#include <stdbool.h>
2829

2930
#if DEVICE_SERIAL_ASYNCH
3031
#include "dma_api.h"
@@ -83,6 +84,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
8384
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
8485
#endif
8586

87+
bool serial_can_deep_sleep(void);
88+
8689
static struct nu_uart_var uart0_var = {
8790
.ref_cnt = 0,
8891
.obj = NULL,
@@ -1088,4 +1091,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
10881091
}
10891092

10901093
#endif // #if DEVICE_SERIAL_ASYNCH
1094+
1095+
bool serial_can_deep_sleep(void)
1096+
{
1097+
bool sleep_allowed = 1;
1098+
const struct nu_modinit_s *modinit = uart_modinit_tab;
1099+
while (modinit->var != NULL) {
1100+
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
1101+
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
1102+
if (uart_var->ref_cnt > 0) {
1103+
if (!UART_IS_TX_EMPTY(uart_base)) {
1104+
sleep_allowed = 0;
1105+
break;
1106+
}
1107+
}
1108+
modinit++;
1109+
}
1110+
return sleep_allowed;
1111+
}
1112+
10911113
#endif // #if DEVICE_SERIAL

targets/TARGET_NUVOTON/TARGET_M451/sleep.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "device.h"
2323
#include "objects.h"
2424
#include "PeripheralPins.h"
25+
#include <stdbool.h>
26+
27+
#if DEVICE_SERIAL
28+
bool serial_can_deep_sleep(void);
29+
#endif
2530

2631
/**
2732
* Enter idle mode, in which just CPU is halted.
@@ -38,6 +43,12 @@ void hal_sleep(void)
3843
*/
3944
void hal_deepsleep(void)
4045
{
46+
#if DEVICE_SERIAL
47+
if (!serial_can_deep_sleep()) {
48+
return;
49+
}
50+
#endif
51+
4152
SYS_UnlockReg();
4253
CLK_PowerDown();
4354
SYS_LockReg();

targets/TARGET_NUVOTON/TARGET_M480/serial_api.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "nu_modutil.h"
2626
#include "nu_bitutil.h"
2727
#include <string.h>
28+
#include <stdbool.h>
2829

2930
#if DEVICE_SERIAL_ASYNCH
3031
#include "dma_api.h"
@@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
8788
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
8889
#endif
8990

91+
bool serial_can_deep_sleep(void);
92+
9093
static struct nu_uart_var uart0_var = {
9194
.ref_cnt = 0,
9295
.obj = NULL,
@@ -1145,4 +1148,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
11451148
}
11461149

11471150
#endif // #if DEVICE_SERIAL_ASYNCH
1151+
1152+
bool serial_can_deep_sleep(void)
1153+
{
1154+
bool sleep_allowed = 1;
1155+
const struct nu_modinit_s *modinit = uart_modinit_tab;
1156+
while (modinit->var != NULL) {
1157+
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
1158+
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
1159+
if (uart_var->ref_cnt > 0) {
1160+
if (!UART_IS_TX_EMPTY(uart_base)) {
1161+
sleep_allowed = 0;
1162+
break;
1163+
}
1164+
}
1165+
modinit++;
1166+
}
1167+
return sleep_allowed;
1168+
}
1169+
11481170
#endif // #if DEVICE_SERIAL

targets/TARGET_NUVOTON/TARGET_M480/sleep.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "device.h"
2323
#include "objects.h"
2424
#include "PeripheralPins.h"
25+
#include <stdbool.h>
26+
27+
#if DEVICE_SERIAL
28+
bool serial_can_deep_sleep(void);
29+
#endif
2530

2631
/**
2732
* Enter idle mode, in which just CPU is halted.
@@ -38,6 +43,12 @@ void hal_sleep(void)
3843
*/
3944
void hal_deepsleep(void)
4045
{
46+
#if DEVICE_SERIAL
47+
if (!serial_can_deep_sleep()) {
48+
return;
49+
}
50+
#endif
51+
4152
SYS_UnlockReg();
4253
CLK_PowerDown();
4354
SYS_LockReg();

targets/TARGET_NUVOTON/TARGET_NANO100/serial_api.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818

1919
#if DEVICE_SERIAL
2020

21-
#include <string.h>
2221
#include "cmsis.h"
2322
#include "mbed_error.h"
2423
#include "mbed_assert.h"
2524
#include "PeripheralPins.h"
2625
#include "nu_modutil.h"
2726
#include "nu_bitutil.h"
27+
#include <string.h>
28+
#include <stdbool.h>
2829

2930
#if DEVICE_SERIAL_ASYNCH
3031
#include "dma_api.h"
@@ -76,6 +77,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
7677
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
7778
#endif
7879

80+
bool serial_can_deep_sleep(void);
81+
7982
static struct nu_uart_var uart0_var = {
8083
.ref_cnt = 0,
8184
.obj = NULL,
@@ -990,4 +993,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
990993
}
991994

992995
#endif // #if DEVICE_SERIAL_ASYNCH
996+
997+
bool serial_can_deep_sleep(void)
998+
{
999+
bool sleep_allowed = 1;
1000+
const struct nu_modinit_s *modinit = uart_modinit_tab;
1001+
while (modinit->var != NULL) {
1002+
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
1003+
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
1004+
if (uart_var->ref_cnt > 0) {
1005+
if (!UART_IS_TX_EMPTY(uart_base)) {
1006+
sleep_allowed = 0;
1007+
break;
1008+
}
1009+
}
1010+
modinit++;
1011+
}
1012+
return sleep_allowed;
1013+
}
1014+
9931015
#endif // #if DEVICE_SERIAL

targets/TARGET_NUVOTON/TARGET_NANO100/sleep.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "device.h"
2323
#include "objects.h"
2424
#include "PeripheralPins.h"
25+
#include <stdbool.h>
26+
27+
#if DEVICE_SERIAL
28+
bool serial_can_deep_sleep(void);
29+
#endif
2530

2631
/**
2732
* Enter idle mode, in which just CPU is halted.
@@ -38,6 +43,12 @@ void hal_sleep(void)
3843
*/
3944
void hal_deepsleep(void)
4045
{
46+
#if DEVICE_SERIAL
47+
if (!serial_can_deep_sleep()) {
48+
return;
49+
}
50+
#endif
51+
4152
SYS_UnlockReg();
4253
CLK_PowerDown();
4354
SYS_LockReg();

targets/TARGET_NUVOTON/TARGET_NUC472/serial_api.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "nu_modutil.h"
2626
#include "nu_bitutil.h"
2727
#include <string.h>
28+
#include <stdbool.h>
2829

2930
#if DEVICE_SERIAL_ASYNCH
3031
#include "dma_api.h"
@@ -87,6 +88,8 @@ static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
8788
static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
8889
#endif
8990

91+
bool serial_can_deep_sleep(void);
92+
9093
static struct nu_uart_var uart0_var = {
9194
.ref_cnt = 0,
9295
.obj = NULL,
@@ -1136,4 +1139,23 @@ static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
11361139
}
11371140

11381141
#endif // #if DEVICE_SERIAL_ASYNCH
1142+
1143+
bool serial_can_deep_sleep(void)
1144+
{
1145+
bool sleep_allowed = 1;
1146+
const struct nu_modinit_s *modinit = uart_modinit_tab;
1147+
while (modinit->var != NULL) {
1148+
struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
1149+
UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
1150+
if (uart_var->ref_cnt > 0) {
1151+
if (!UART_IS_TX_EMPTY(uart_base)) {
1152+
sleep_allowed = 0;
1153+
break;
1154+
}
1155+
}
1156+
modinit++;
1157+
}
1158+
return sleep_allowed;
1159+
}
1160+
11391161
#endif // #if DEVICE_SERIAL

targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "device.h"
2323
#include "objects.h"
2424
#include "PeripheralPins.h"
25+
#include <stdbool.h>
26+
27+
#if DEVICE_SERIAL
28+
bool serial_can_deep_sleep(void);
29+
#endif
2530

2631
/**
2732
* Enter idle mode, in which just CPU is halted.
@@ -38,6 +43,12 @@ void hal_sleep(void)
3843
*/
3944
void hal_deepsleep(void)
4045
{
46+
#if DEVICE_SERIAL
47+
if (!serial_can_deep_sleep()) {
48+
return;
49+
}
50+
#endif
51+
4152
SYS_UnlockReg();
4253
CLK_PowerDown();
4354
SYS_LockReg();

0 commit comments

Comments
 (0)