Skip to content

Commit ed7505b

Browse files
committed
drivers: modem: hl78xx: add optional auto-baudrate detection and switching
This adds an optional auto-baudrate mechanism that improves robustness when the modem boots with an unknown or changed UART speed. Key additions: * New Kconfig option MODEM_HL78XX_AUTO_BAUDRATE and related settings: - selectable target baud rate - detection baudrate list - detection timeout and retry count - option to persist AT+IPR updates - option to start diagnostics or boot directly with auto-baud logic * UART status tracking added to hl78xx_data, including current and target baud rates * New HL78XX_MODEM_INFO_CURRENT_BAUD_RATE info field * New MODEM_HL78XX_STATE_SET_BAUDRATE state with detection and switching logic * Chat, init, and diagnostic handlers updated to route failures into the auto-baudrate logic when enabled * New helpers: hl78xx_get_uart_config(), hl78xx_try_baudrate(), hl78xx_detect_current_baudrate(), hl78xx_switch_baudrate() * Startup delay increased when auto-baudrate-at-boot is enabled These changes allow the driver to recover from unexpected modem UART rate changes and keep the UART configuration synchronized with the modem. Signed-off-by: Zafer SEN <zafersn93@gmail.com>
1 parent 5156de7 commit ed7505b

File tree

8 files changed

+472
-5
lines changed

8 files changed

+472
-5
lines changed

drivers/modem/hl78xx/Kconfig.hl78xx

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,143 @@ config MODEM_AT_SHELL_RESPONSE_MAX_SIZE
7878

7979
endif # MODEM_HL78XX_AT_SHELL
8080

81+
menuconfig MODEM_HL78XX_AUTO_BAUDRATE
82+
bool "Auto Baud Rate Detection and Switching"
83+
select UART_USE_RUNTIME_CONFIGURE if SOC_SERIES_NRF52X
84+
help
85+
Enable automatic baud rate detection and switching for the HL78xx modem.
86+
The driver will attempt to detect the modem's current baud rate and
87+
switch to the configured target baud rate using AT+IPR command.
88+
89+
if MODEM_HL78XX_AUTO_BAUDRATE
90+
91+
choice MODEM_HL78XX_TARGET_BAUDRATE
92+
prompt "Target UART Baud Rate"
93+
default MODEM_HL78XX_TARGET_BAUDRATE_115200
94+
help
95+
Select the target baud rate for communication with the modem.
96+
The driver will configure the modem to use this baud rate after detection.
97+
98+
config MODEM_HL78XX_TARGET_BAUDRATE_9600
99+
bool "9600"
100+
help
101+
Set modem baud rate to 9600 bps
102+
103+
config MODEM_HL78XX_TARGET_BAUDRATE_19200
104+
bool "19200"
105+
help
106+
Set modem baud rate to 19200 bps
107+
108+
config MODEM_HL78XX_TARGET_BAUDRATE_38400
109+
bool "38400"
110+
help
111+
Set modem baud rate to 38400 bps
112+
113+
config MODEM_HL78XX_TARGET_BAUDRATE_57600
114+
bool "57600"
115+
help
116+
Set modem baud rate to 57600 bps
117+
118+
config MODEM_HL78XX_TARGET_BAUDRATE_115200
119+
bool "115200"
120+
help
121+
Set modem baud rate to 115200 bps (default)
122+
123+
config MODEM_HL78XX_TARGET_BAUDRATE_230400
124+
bool "230400"
125+
help
126+
Set modem baud rate to 230400 bps
127+
128+
config MODEM_HL78XX_TARGET_BAUDRATE_460800
129+
bool "460800"
130+
help
131+
Set modem baud rate to 460800 bps
132+
133+
config MODEM_HL78XX_TARGET_BAUDRATE_921600
134+
bool "921600"
135+
help
136+
Set modem baud rate to 921600 bps
137+
138+
config MODEM_HL78XX_TARGET_BAUDRATE_3000000
139+
bool "3000000"
140+
depends on MODEM_HL78XX_12
141+
help
142+
Set modem baud rate to 3000000 bps
143+
endchoice
144+
145+
config MODEM_HL78XX_TARGET_BAUDRATE_VALUE
146+
int
147+
default 9600 if MODEM_HL78XX_TARGET_BAUDRATE_9600
148+
default 19200 if MODEM_HL78XX_TARGET_BAUDRATE_19200
149+
default 38400 if MODEM_HL78XX_TARGET_BAUDRATE_38400
150+
default 57600 if MODEM_HL78XX_TARGET_BAUDRATE_57600
151+
default 115200 if MODEM_HL78XX_TARGET_BAUDRATE_115200
152+
default 230400 if MODEM_HL78XX_TARGET_BAUDRATE_230400
153+
default 460800 if MODEM_HL78XX_TARGET_BAUDRATE_460800
154+
default 921600 if MODEM_HL78XX_TARGET_BAUDRATE_921600
155+
default 3000000 if MODEM_HL78XX_TARGET_BAUDRATE_3000000
156+
157+
config MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES
158+
string "Baud rates to try during auto-detection (comma-separated)"
159+
default "115200,9600,57600,38400,19200"
160+
help
161+
Comma-separated list of baud rates to try when auto-detecting
162+
the modem's current baud rate. The driver will try each rate
163+
in order until it successfully communicates with the modem.
164+
Common baud rates: 9600, 19200, 38400, 57600, 115200
165+
166+
config MODEM_HL78XX_AUTOBAUD_TIMEOUT
167+
int "Timeout for each baud rate detection attempt (seconds)"
168+
default 4
169+
range 1 120
170+
help
171+
Maximum time to wait for a response from the modem when trying
172+
a specific baud rate during auto-detection.
173+
174+
config MODEM_HL78XX_AUTOBAUD_RETRY_COUNT
175+
int "Number of retries for baud rate detection"
176+
default 3
177+
range 1 10
178+
help
179+
Number of times to retry baud rate detection before giving up.
180+
181+
config MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT
182+
bool "Save detected baud rate persistently"
183+
default y
184+
help
185+
Enable this option to save the configuration to the modem non-volatile memory,
186+
otherwise it will revert to previous setting on power cycle.
187+
Highly recommended to enable this option to detect unexpected modem reboots
188+
and quick recovery.
189+
190+
Baudrate change will be permanent across power cycles.
191+
NOTE: Changing phone functionality (AT+CFUN) does reset baud rate to default.
192+
193+
config MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE
194+
bool "Start auto baud rate detection with target baud rate"
195+
default y
196+
help
197+
Enable this option to start the auto baud rate detection process
198+
by first attempting communication at the configured target baud rate.
199+
This can speed up detection if the modem is already set to the target rate.
200+
201+
config MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL
202+
bool "Only perform auto baud rate detection on communication failure"
203+
default y
204+
help
205+
Enable this option to perform auto baud rate detection only
206+
if initial uart communication with the modem at the configured
207+
target baud rate fails.
208+
209+
config MODEM_HL78XX_AUTOBAUD_AT_BOOT
210+
bool "Perform auto baud rate detection at boot (skip KSUP wait)"
211+
help
212+
When enabled, the driver will immediately perform auto baud rate detection
213+
as soon as the modem is powered up, without waiting for the KSUP URC
214+
(startup ready indication).
215+
216+
endif # MODEM_HL78XX_AUTO_BAUDRATE
217+
81218
choice MODEM_HL78XX_ADDRESS_FAMILY
82219
prompt "IP Address family"
83220
default MODEM_HL78XX_ADDRESS_FAMILY_IPV4V6
@@ -874,13 +1011,17 @@ config MODEM_HL78XX_DEV_RESET_PULSE_DURATION_MS
8741011

8751012
config MODEM_HL78XX_DEV_STARTUP_TIME_MS
8761013
int "Wait before assuming the device is ready."
877-
default 120
1014+
default 2000 if MODEM_HL78XX_AUTOBAUD_AT_BOOT
1015+
default 120 if !MODEM_HL78XX_AUTOBAUD_AT_BOOT
8781016
help
8791017
The expected delay time (in milliseconds) the modem needs to fully power on
8801018
and become operational.This delay before the driver opens the UART pipe
8811019
and attaches the chat layer. The value must be long enough for the driver
8821020
startup code to initialize, but short enough to ensure the pipe is ready
8831021
before the modem sends its first URCs during boot.
1022+
BUT,
1023+
if auto baudrate detection at boot is enabled,
1024+
a longer delay is recommended to allow the modem to complete its boot sequence.
8841025

8851026
config MODEM_HL78XX_DEV_SHUTDOWN_TIME_MS
8861027
int "Wait before assuming the device is completely off."

drivers/modem/hl78xx/hl78xx.c

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,13 +1017,30 @@ static void hl78xx_await_power_on_event_handler(struct hl78xx_data *data, enum h
10171017

10181018
case MODEM_HL78XX_EVENT_BUS_OPENED:
10191019
modem_chat_attach(&data->chat, data->uart_pipe);
1020+
#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT
1021+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE);
1022+
#else
10201023
hl78xx_run_post_restart_script_async(data);
1024+
#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT */
10211025
break;
10221026

10231027
case MODEM_HL78XX_EVENT_SCRIPT_SUCCESS:
1028+
(void)hl78xx_get_uart_config(data);
1029+
LOG_DBG("Current baudrate after post-restart script: %d",
1030+
data->status.uart.current_baudrate);
1031+
#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL
10241032
hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_SCRIPT);
1033+
#else
1034+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE);
1035+
#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL */
10251036
break;
10261037

1038+
case MODEM_HL78XX_EVENT_SCRIPT_FAILED:
1039+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
1040+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE);
1041+
#else
1042+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT);
1043+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
10271044
case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT:
10281045
hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT);
10291046
break;
@@ -1032,6 +1049,71 @@ static void hl78xx_await_power_on_event_handler(struct hl78xx_data *data, enum h
10321049
break;
10331050
}
10341051
}
1052+
1053+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
1054+
static int hl78xx_on_set_baudrate_state_enter(struct hl78xx_data *data)
1055+
{
1056+
int ret;
1057+
1058+
data->status.uart.target_baudrate = CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_VALUE;
1059+
1060+
/* Detect current baud rate */
1061+
ret = hl78xx_detect_current_baudrate(data);
1062+
if (ret < 0) {
1063+
LOG_ERR("Baud rate detection failed");
1064+
hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_FAILED);
1065+
return ret;
1066+
}
1067+
1068+
/* Switch to target baud rate if different */
1069+
ret = hl78xx_switch_baudrate(data, data->status.uart.target_baudrate);
1070+
if (ret < 0) {
1071+
LOG_ERR("Failed to switch baud rate: %d", ret);
1072+
hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_FAILED);
1073+
return ret;
1074+
}
1075+
data->status.boot.is_booted_previously = true;
1076+
hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_SUCCESS);
1077+
return 0;
1078+
}
1079+
1080+
static void hl78xx_set_baudrate_event_handler(struct hl78xx_data *data, enum hl78xx_event evt)
1081+
{
1082+
switch (evt) {
1083+
case MODEM_HL78XX_EVENT_SCRIPT_SUCCESS:
1084+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_SCRIPT);
1085+
break;
1086+
1087+
case MODEM_HL78XX_EVENT_SCRIPT_FAILED:
1088+
/* Increment retry counter */
1089+
data->status.uart.baudrate_detection_retry++;
1090+
1091+
/* Retry detection or give up */
1092+
if (data->status.uart.baudrate_detection_retry <
1093+
CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT) {
1094+
LOG_WRN("Retrying baud rate detection (attempt %d/%d)",
1095+
data->status.uart.baudrate_detection_retry + 1,
1096+
CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT);
1097+
k_sleep(K_MSEC(500));
1098+
hl78xx_on_set_baudrate_state_enter(data);
1099+
} else {
1100+
LOG_ERR("Baud rate configuration failed after %d attempts",
1101+
data->status.uart.baudrate_detection_retry);
1102+
hl78xx_enter_state(data,
1103+
MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT);
1104+
}
1105+
break;
1106+
1107+
case MODEM_HL78XX_EVENT_SUSPEND:
1108+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE);
1109+
break;
1110+
1111+
default:
1112+
break;
1113+
}
1114+
}
1115+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
1116+
10351117
static int hl78xx_on_run_init_script_state_enter(struct hl78xx_data *data)
10361118
{
10371119
return hl78xx_run_init_script_async(data);
@@ -1083,7 +1165,13 @@ static void hl78xx_run_init_fail_script_event_handler(struct hl78xx_data *data,
10831165
}
10841166
break;
10851167
case MODEM_HL78XX_EVENT_TIMEOUT:
1168+
LOG_ERR("Modem initialization failed after diagnostic script");
1169+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE);
1170+
break;
10861171
case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT:
1172+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
1173+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE);
1174+
#else
10871175
if (hl78xx_gpio_is_enabled(&config->mdm_gpio_pwr_on)) {
10881176
hl78xx_enter_state(data, MODEM_HL78XX_STATE_POWER_ON_PULSE);
10891177
break;
@@ -1095,6 +1183,7 @@ static void hl78xx_run_init_fail_script_event_handler(struct hl78xx_data *data,
10951183
}
10961184

10971185
hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE);
1186+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
10981187
break;
10991188
case MODEM_HL78XX_EVENT_BUS_CLOSED:
11001189
break;
@@ -1169,6 +1258,12 @@ static void hl78xx_run_rat_cfg_script_event_handler(struct hl78xx_data *data, en
11691258
{
11701259
switch (evt) {
11711260
case MODEM_HL78XX_EVENT_TIMEOUT:
1261+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
1262+
if (IS_ENABLED(CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT) == false) {
1263+
hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE);
1264+
}
1265+
break;
1266+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
11721267
LOG_DBG("Rebooting modem to apply new RAT settings");
11731268
break;
11741269
case MODEM_HL78XX_EVENT_MDM_RESTART:
@@ -1827,6 +1922,15 @@ static int hl78xx_init(const struct device *dev)
18271922
data->buffers.eof_pattern_size = strlen(data->buffers.eof_pattern);
18281923
data->buffers.termination_pattern_size = strlen(data->buffers.termination_pattern);
18291924
memset(data->identity.apn, 0, MDM_APN_MAX_LENGTH);
1925+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
1926+
data->status.uart.current_baudrate = 0;
1927+
data->status.uart.target_baudrate = CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_VALUE;
1928+
data->status.uart.baudrate_detection_retry = 0;
1929+
#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE
1930+
/* Update baud rate */
1931+
configure_uart_for_auto_baudrate(data, data->status.uart.target_baudrate);
1932+
#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE */
1933+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
18301934
/* GPIO validation */
18311935
const struct gpio_dt_spec *gpio_pins[GPIO_CONFIG_LEN] = {
18321936
#if HAS_RESET_GPIO
@@ -2011,11 +2115,13 @@ const static struct hl78xx_state_handlers hl78xx_state_table[] = {
20112115
NULL,
20122116
hl78xx_await_power_on_event_handler
20132117
},
2118+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
20142119
[MODEM_HL78XX_STATE_SET_BAUDRATE] = {
2120+
hl78xx_on_set_baudrate_state_enter,
20152121
NULL,
2016-
NULL,
2017-
NULL
2122+
hl78xx_set_baudrate_event_handler
20182123
},
2124+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
20192125
[MODEM_HL78XX_STATE_RUN_INIT_SCRIPT] = {
20202126
hl78xx_on_run_init_script_state_enter,
20212127
NULL,

drivers/modem/hl78xx/hl78xx.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113
*/
114114
#define WDSI_USER_INITIATED_CONNECTION_START_CMD "AT+WDSS=1,1"
115115
#define WDSI_USER_INITIATED_CONNECTION_STOP_CMD "AT+WDSS=1,0"
116+
/* Baud rate commands */
117+
#define GET_BAUDRATE_CMD "AT+IPR?"
118+
#define SET_BAUDRATE_CMD_FMT "AT+IPR=%d"
116119

117120
/* Helper macros */
118121
#define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__)
@@ -184,6 +187,7 @@ enum hl78xx_event {
184187
MODEM_HL78XX_EVENT_WDSI_FIRMWARE_INSTALL_SUCCEEDED,
185188
MODEM_HL78XX_EVENT_WDSI_FIRMWARE_INSTALL_FAILED,
186189
#endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */
190+
MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT,
187191
MODEM_HL78XX_EVENT_COUNT
188192
};
189193

@@ -325,6 +329,13 @@ struct hl78xx_wdsi_status {
325329

326330
#endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */
327331

332+
struct hl78xx_modem_uart_status {
333+
uint32_t current_baudrate;
334+
#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE
335+
uint32_t target_baudrate;
336+
uint8_t baudrate_detection_retry;
337+
#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */
338+
};
328339
struct modem_status {
329340
struct registration_status registration;
330341
int16_t rssi;
@@ -343,6 +354,7 @@ struct modem_status {
343354
#ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE
344355
struct hl78xx_wdsi_status wdsi;
345356
#endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */
357+
struct hl78xx_modem_uart_status uart;
346358
};
347359

348360
struct modem_gpio_callbacks {

drivers/modem/hl78xx/hl78xx_apis.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ int hl78xx_api_func_get_modem_info_vendor(const struct device *dev,
179179
safe_strncpy(info, (const char *)data->identity.serial_number,
180180
MIN(size, sizeof(data->identity.serial_number)));
181181
break;
182+
case HL78XX_MODEM_INFO_CURRENT_BAUD_RATE:
183+
*(uint32_t *)info = data->status.uart.current_baudrate;
184+
break;
182185
default:
183186
break;
184187
}

0 commit comments

Comments
 (0)