From ea03e633fab1c71de480a51f173e70da941a6663 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Fri, 5 Dec 2025 17:56:16 +0000 Subject: [PATCH 01/10] drivers: modem: hl78xx: add ERROR handling and unify OK match usage Extend socket-related chat match tables to handle generic "ERROR" responses for both CONNECT and +KUDP_IND URCs, improving detection of failed socket creation and connection attempts. While updating match handling, unify all modem commands to use the standard OK match set by adding hl78xx_get_ok_match_size(). All remaining users of the former sockets-specific OK match are switched to the unified helpers. Additionally, all dynamic command send paths now provide an explicit match count and use MDM_CMD_TIMEOUT instead of the previous hard-coded `1` for script timeout, improving consistency and reliability across: * RAT configuration * band configuration * APN setup * GSM PDP activation * AirVantage DM session control * socket send and TLS configuration paths This brings all command execution onto the same match/timeout model and ensures ERROR responses are handled correctly during socket operations. Signed-off-by: Zafer SEN --- drivers/modem/hl78xx/hl78xx.c | 3 ++- drivers/modem/hl78xx/hl78xx.h | 1 + drivers/modem/hl78xx/hl78xx_apis.c | 12 ++++++++---- drivers/modem/hl78xx/hl78xx_cfg.c | 27 ++++++++++++++++---------- drivers/modem/hl78xx/hl78xx_chat.c | 28 ++++++++++++++++++--------- drivers/modem/hl78xx/hl78xx_chat.h | 3 ++- drivers/modem/hl78xx/hl78xx_sockets.c | 22 ++++++++++----------- 7 files changed, 60 insertions(+), 36 deletions(-) diff --git a/drivers/modem/hl78xx/hl78xx.c b/drivers/modem/hl78xx/hl78xx.c index 5ab1d2633823b..df4f1ae946c18 100644 --- a/drivers/modem/hl78xx/hl78xx.c +++ b/drivers/modem/hl78xx/hl78xx.c @@ -1141,7 +1141,8 @@ static int hl78xx_on_rat_cfg_script_state_enter(struct hl78xx_data *data) if (modem_require_restart) { HL78XX_LOG_DBG("Modem restart required to apply new RAT/Band settings"); ret = modem_dynamic_cmd_send(data, NULL, cmd_restart, strlen(cmd_restart), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } diff --git a/drivers/modem/hl78xx/hl78xx.h b/drivers/modem/hl78xx/hl78xx.h index 0233b3054c435..23330ddb3957b 100644 --- a/drivers/modem/hl78xx/hl78xx.h +++ b/drivers/modem/hl78xx/hl78xx.h @@ -73,6 +73,7 @@ #define TERMINATION_PATTERN "+++" #define CONNECT_STRING "CONNECT" #define CME_ERROR_STRING "+CME ERROR: " +#define ERROR_STRING "ERROR" #define OK_STRING "OK" /* RAT (Radio Access Technology) commands */ diff --git a/drivers/modem/hl78xx/hl78xx_apis.c b/drivers/modem/hl78xx/hl78xx_apis.c index 760696a6f9402..dcb52778655dc 100644 --- a/drivers/modem/hl78xx/hl78xx_apis.c +++ b/drivers/modem/hl78xx/hl78xx_apis.c @@ -266,7 +266,8 @@ int hl78xx_api_func_set_phone_functionality(const struct device *dev, struct hl78xx_data *data = (struct hl78xx_data *)dev->data; /* configure modem functionality with/without restart */ snprintf(cmd_string, sizeof(cmd_string), "AT+CFUN=%d,%d", functionality, reset); - return hl78xx_send_cmd(data, cmd_string, NULL, hl78xx_get_ok_match(), 1); + return hl78xx_send_cmd(data, cmd_string, NULL, hl78xx_get_ok_match(), + hl78xx_get_ok_match_size()); } int hl78xx_api_func_get_phone_functionality(const struct device *dev, @@ -275,7 +276,8 @@ int hl78xx_api_func_get_phone_functionality(const struct device *dev, const char *cmd_string = GET_FULLFUNCTIONAL_MODE_CMD; struct hl78xx_data *data = (struct hl78xx_data *)dev->data; /* get modem phone functionality */ - return hl78xx_send_cmd(data, cmd_string, NULL, hl78xx_get_ok_match(), 1); + return hl78xx_send_cmd(data, cmd_string, NULL, hl78xx_get_ok_match(), + hl78xx_get_ok_match_size()); } int hl78xx_api_func_modem_dynamic_cmd_send(const struct device *dev, const char *cmd, @@ -300,7 +302,8 @@ int hl78xx_start_airvantage_dm_session(const struct device *dev) ret = modem_dynamic_cmd_send(data, NULL, WDSI_USER_INITIATED_CONNECTION_START_CMD, strlen(WDSI_USER_INITIATED_CONNECTION_START_CMD), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Start DM session error %d", ret); return ret; @@ -315,7 +318,8 @@ int hl78xx_stop_airvantage_dm_session(const struct device *dev) ret = modem_dynamic_cmd_send(data, NULL, WDSI_USER_INITIATED_CONNECTION_STOP_CMD, strlen(WDSI_USER_INITIATED_CONNECTION_STOP_CMD), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Stop DM session error %d", ret); return ret; diff --git a/drivers/modem/hl78xx/hl78xx_cfg.c b/drivers/modem/hl78xx/hl78xx_cfg.c index 2a7e563725336..b640fae32b7be 100644 --- a/drivers/modem/hl78xx/hl78xx_cfg.c +++ b/drivers/modem/hl78xx/hl78xx_cfg.c @@ -35,7 +35,8 @@ int hl78xx_rat_cfg(struct hl78xx_data *data, bool *modem_require_restart, char cmd_kselq[] = "AT+KSELACQ=0," CONFIG_MODEM_HL78XX_AUTORAT_PRL_PROFILES; ret = modem_dynamic_cmd_send(data, NULL, cmd_kselq, strlen(cmd_kselq), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } else { @@ -52,8 +53,8 @@ int hl78xx_rat_cfg(struct hl78xx_data *data, bool *modem_require_restart, if (data->kselacq_data.rat1 != 0 && data->kselacq_data.rat2 != 0 && data->kselacq_data.rat3 != 0) { ret = modem_dynamic_cmd_send(data, NULL, cmd_kselq_disable, - strlen(cmd_kselq_disable), hl78xx_get_ok_match(), 1, - false); + strlen(cmd_kselq_disable), hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } @@ -97,7 +98,8 @@ int hl78xx_rat_cfg(struct hl78xx_data *data, bool *modem_require_restart, if (*rat_request != data->status.registration.rat_mode) { ret = modem_dynamic_cmd_send(data, NULL, cmd_set_rat, strlen(cmd_set_rat), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } else { @@ -162,8 +164,9 @@ int hl78xx_band_cfg(struct hl78xx_data *data, bool *modem_require_restart, char cmd_bnd[80] = {0}; snprintf(cmd_bnd, sizeof(cmd_bnd), "AT+KBNDCFG=%d,%s", rat, bnd_bitmap); - ret = modem_dynamic_cmd_send(data, NULL, cmd_bnd, strlen(cmd_bnd), - hl78xx_get_ok_match(), 1, false); + ret = modem_dynamic_cmd_send( + data, NULL, cmd_bnd, strlen(cmd_bnd), hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } else { @@ -203,20 +206,23 @@ int hl78xx_set_apn_internal(struct hl78xx_data *data, const char *apn, uint16_t apn); ret = modem_dynamic_cmd_send(data, NULL, cmd_string, strlen(cmd_string), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } snprintk(cmd_string, cmd_max_len, "AT+KCNXCFG=1,\"GPRS\",\"%s\",,,\"" MODEM_HL78XX_ADDRESS_FAMILY "\"", apn); ret = modem_dynamic_cmd_send(data, NULL, cmd_string, strlen(cmd_string), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } #ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE ret = modem_dynamic_cmd_send(data, NULL, "AT+WDSS=2,1", strlen("AT+WDSS=2,1"), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } @@ -243,7 +249,8 @@ int hl78xx_gsm_pdp_activate(struct hl78xx_data *data) } ret = modem_dynamic_cmd_send(data, NULL, cmd_activate_pdp, strlen(cmd_activate_pdp), - hl78xx_get_ok_match(), 1, false); + hl78xx_get_ok_match(), hl78xx_get_ok_match_size(), + MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("GSM PDP activation failed: %d", ret); return ret; diff --git a/drivers/modem/hl78xx/hl78xx_chat.c b/drivers/modem/hl78xx/hl78xx_chat.c index a52ce1792743a..8ca45f2d54242 100644 --- a/drivers/modem/hl78xx/hl78xx_chat.c +++ b/drivers/modem/hl78xx/hl78xx_chat.c @@ -74,7 +74,8 @@ void hl78xx_on_wdsi(struct modem_chat *chat, char **argv, uint16_t argc, void *u #endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ MODEM_CHAT_MATCH_DEFINE(hl78xx_ok_match, "OK", "", NULL); MODEM_CHAT_MATCHES_DEFINE(hl78xx_allow_match, MODEM_CHAT_MATCH("OK", "", NULL), - MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL)); + MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL), + MODEM_CHAT_MATCH(ERROR_STRING, "", NULL)); /* clang-format off */ MODEM_CHAT_MATCHES_DEFINE(hl78xx_unsol_matches, MODEM_CHAT_MATCH("+KSUP: ", "", hl78xx_on_ksup), @@ -250,18 +251,17 @@ MODEM_CHAT_SCRIPT_DEFINE(hl78xx_fota_install_accept_script, hl78xx_fota_install_ * definitions. */ MODEM_CHAT_MATCHES_DEFINE(connect_matches, MODEM_CHAT_MATCH(CONNECT_STRING, "", NULL), - MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL)); -MODEM_CHAT_MATCH_DEFINE(kudpind_match, "+KUDP_IND: ", ",", hl78xx_on_kudpsocket_create); + MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL), + MODEM_CHAT_MATCH(ERROR_STRING, "", NULL), ); +MODEM_CHAT_MATCHES_DEFINE(kudpind_allow_match, + MODEM_CHAT_MATCH("+KUDP_IND: ", ",", hl78xx_on_kudpsocket_create), + MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL), + MODEM_CHAT_MATCH(ERROR_STRING, "", NULL), ); MODEM_CHAT_MATCH_DEFINE(ktcpind_match, "+KTCP_IND: ", ",", hl78xx_on_ktcpind); MODEM_CHAT_MATCH_DEFINE(ktcpcfg_match, "+KTCPCFG: ", "", hl78xx_on_ktcpsocket_create); MODEM_CHAT_MATCH_DEFINE(cgdcontrdp_match, "+CGCONTRDP: ", ",", hl78xx_on_cgdcontrdp); MODEM_CHAT_MATCH_DEFINE(ktcp_state_match, "+KTCPSTAT: ", ",", NULL); -const struct modem_chat_match *hl78xx_get_sockets_ok_match(void) -{ - return &hl78xx_ok_match; -} - const struct modem_chat_match *hl78xx_get_connect_matches(void) { return connect_matches; @@ -284,7 +284,12 @@ size_t hl78xx_get_sockets_allow_matches_size(void) const struct modem_chat_match *hl78xx_get_kudpind_match(void) { - return &kudpind_match; + return kudpind_allow_match; +} + +size_t hl78xx_get_kudpind_allow_matches_size(void) +{ + return (size_t)ARRAY_SIZE(kudpind_allow_match); } const struct modem_chat_match *hl78xx_get_ktcpind_match(void) @@ -331,6 +336,11 @@ const struct modem_chat_match *hl78xx_get_ok_match(void) return &hl78xx_ok_match; } +size_t hl78xx_get_ok_match_size(void) +{ + return 1; +} + const struct modem_chat_match *hl78xx_get_abort_matches(void) { return hl78xx_abort_matches; diff --git a/drivers/modem/hl78xx/hl78xx_chat.h b/drivers/modem/hl78xx/hl78xx_chat.h index 5d679e1d215ac..490663d66d7b5 100644 --- a/drivers/modem/hl78xx/hl78xx_chat.h +++ b/drivers/modem/hl78xx/hl78xx_chat.h @@ -33,6 +33,7 @@ void hl78xx_chat_callback_handler(struct modem_chat *chat, enum modem_chat_scrip */ const struct modem_chat_match *hl78xx_get_at_ready_match(void); const struct modem_chat_match *hl78xx_get_ok_match(void); +size_t hl78xx_get_ok_match_size(void); const struct modem_chat_match *hl78xx_get_abort_matches(void); const struct modem_chat_match *hl78xx_get_unsol_matches(void); size_t hl78xx_get_unsol_matches_size(void); @@ -69,12 +70,12 @@ int hl78xx_run_periodic_script_async(struct hl78xx_data *data); const struct modem_chat_match *hl78xx_get_ksrat_match(void); /* Socket-related chat matches used by the sockets TU */ -const struct modem_chat_match *hl78xx_get_sockets_ok_match(void); const struct modem_chat_match *hl78xx_get_connect_matches(void); size_t hl78xx_get_connect_matches_size(void); const struct modem_chat_match *hl78xx_get_sockets_allow_matches(void); size_t hl78xx_get_sockets_allow_matches_size(void); const struct modem_chat_match *hl78xx_get_kudpind_match(void); +size_t hl78xx_get_kudpind_allow_matches_size(void); const struct modem_chat_match *hl78xx_get_ktcpind_match(void); const struct modem_chat_match *hl78xx_get_ktcpcfg_match(void); const struct modem_chat_match *hl78xx_get_cgdcontrdp_match(void); diff --git a/drivers/modem/hl78xx/hl78xx_sockets.c b/drivers/modem/hl78xx/hl78xx_sockets.c index f26d2b2026fb1..cfd002d85494b 100644 --- a/drivers/modem/hl78xx/hl78xx_sockets.c +++ b/drivers/modem/hl78xx/hl78xx_sockets.c @@ -1430,7 +1430,7 @@ static int send_udp_config(const struct net_sockaddr *addr, struct hl78xx_socket (addr->sa_family - 1), 0); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_buf, strlen(cmd_buf), - hl78xx_get_kudpind_match(), 1, false); + hl78xx_get_kudpind_match(), hl78xx_get_kudpind_allow_matches_size(), MDM_CMD_TIMEOUT_MS, false); if (ret < 0) { goto error; } @@ -1998,9 +1998,8 @@ static int transmit_regular_data(struct hl78xx_socket_data *socket_data, const c /* send binary data via the +KUDPSND/+KTCPSND commands */ static ssize_t send_socket_data(void *obj, struct hl78xx_socket_data *socket_data, - const struct net_sockaddr *dst_addr, - const char *buf, size_t buf_len, - k_timeout_t timeout) + const struct net_sockaddr *dst_addr, const char *buf, + size_t buf_len, k_timeout_t timeout) { struct modem_socket *sock = (struct modem_socket *)obj; char cmd_buf[82] = {0}; /* AT+KUDPSND/KTCP=,IP,PORT,LENGTH */ @@ -2030,8 +2029,8 @@ static ssize_t send_socket_data(void *obj, struct hl78xx_socket_data *socket_dat goto cleanup; } modem_chat_attach(&socket_data->mdata_global->chat, socket_data->mdata_global->uart_pipe); - ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, "", 0, - hl78xx_get_sockets_ok_match(), 1, false); + ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, "", 0, hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Final confirmation failed: %d", ret); goto cleanup; @@ -2373,9 +2372,10 @@ static int hl78xx_configure_chipper_suit(struct hl78xx_socket_data *socket_data) { const char *cmd_chipper_suit = "AT+KSSLCRYPTO=0,8,1,8192,4,4,3,0"; - return modem_dynamic_cmd_send( - socket_data->mdata_global, NULL, cmd_chipper_suit, strlen(cmd_chipper_suit), - (const struct modem_chat_match *)hl78xx_get_ok_match(), 1, false); + return modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_chipper_suit, + strlen(cmd_chipper_suit), + (const struct modem_chat_match *)hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); } /* send binary data via the K....STORE commands */ static ssize_t hl78xx_send_cert(struct hl78xx_socket_data *socket_data, const char *cert_data, @@ -2444,8 +2444,8 @@ static ssize_t hl78xx_send_cert(struct hl78xx_socket_data *socket_data, const ch } modem_chat_attach(&socket_data->mdata_global->chat, socket_data->mdata_global->uart_pipe); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, "", 0, - (const struct modem_chat_match *)hl78xx_get_ok_match(), 1, - false); + (const struct modem_chat_match *)hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Final confirmation failed: %d", ret); goto cleanup; From d9b5b3cf3709248cad645713fc9e2fab0642eaf2 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 02:25:35 +0000 Subject: [PATCH 02/10] drivers: modem: hl78xx: support per-command timeout in send API Extend modem_dynamic_cmd_send() with a response_timeout parameter to allow callers to specify the overall script timeout per command. The previously hardcoded 1000 ms timeout is removed (set to 0 in params) and the script timeout is now driven by the passed-in value. Update all internal call sites to provide MDM_CMD_TIMEOUT (in seconds) and increase the default command timeout from 10 s to 40 s. Several chat scripts and configuration paths are updated accordingly. This improves reliability for long-running HL78xx operations and ensures consistent timeout handling across sockets, RAT/band configuration, APN setup, PDP activation, AirVantage DM session control, and TLS/TCP/UDP socket management. Signed-off-by: Zafer SEN --- drivers/modem/hl78xx/hl78xx.c | 6 +++--- drivers/modem/hl78xx/hl78xx.h | 9 ++++++--- drivers/modem/hl78xx/hl78xx_apis.c | 4 ++-- drivers/modem/hl78xx/hl78xx_cfg.c | 2 +- drivers/modem/hl78xx/hl78xx_chat.c | 2 +- drivers/modem/hl78xx/hl78xx_sockets.c | 22 +++++++++++++--------- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/modem/hl78xx/hl78xx.c b/drivers/modem/hl78xx/hl78xx.c index df4f1ae946c18..85343f389a505 100644 --- a/drivers/modem/hl78xx/hl78xx.c +++ b/drivers/modem/hl78xx/hl78xx.c @@ -768,7 +768,7 @@ int modem_dynamic_cmd_send( modem_chat_script_callback script_user_callback, const uint8_t *cmd, uint16_t cmd_size, const struct modem_chat_match *response_matches, uint16_t matches_size, - bool user_cmd + uint16_t response_timeout, bool user_cmd ) { int ret = 0; @@ -784,7 +784,7 @@ int modem_dynamic_cmd_send( .request_size = cmd_size, .response_matches = response_matches, .response_matches_size = matches_size, - .timeout = 1000, + .timeout = 0, /* Has no effect */ }; struct modem_chat_script chat_script = { .name = "dynamic_script", @@ -793,7 +793,7 @@ int modem_dynamic_cmd_send( .abort_matches = hl78xx_get_abort_matches(), .abort_matches_size = hl78xx_get_abort_matches_size(), .callback = script_user_callback, - .timeout = 1000 + .timeout = response_timeout, /* overall script timeout */ }; ret = k_mutex_lock(&data->tx_lock, K_NO_WAIT); diff --git a/drivers/modem/hl78xx/hl78xx.h b/drivers/modem/hl78xx/hl78xx.h index 23330ddb3957b..2018e2c05521a 100644 --- a/drivers/modem/hl78xx/hl78xx.h +++ b/drivers/modem/hl78xx/hl78xx.h @@ -25,8 +25,8 @@ #include "../modem_context.h" #include "../modem_socket.h" #include - -#define MDM_CMD_TIMEOUT (10) /*K_SECONDS*/ +/* clang-format off */ +#define MDM_CMD_TIMEOUT (40) /*K_SECONDS*/ #define MDM_DNS_TIMEOUT (70) /*K_SECONDS*/ #define MDM_CELL_BAND_SEARCH_TIMEOUT (60) /*K_SECONDS*/ #define MDM_CMD_CONN_TIMEOUT (120) /*K_SECONDS*/ @@ -123,6 +123,8 @@ (LOG_DBG(str, ##__VA_ARGS__)), \ ((void)0)) +/* clang-format on */ + /* HL78XX States */ enum hl78xx_state { MODEM_HL78XX_STATE_IDLE = 0, @@ -473,13 +475,14 @@ void iface_status_work_cb(struct hl78xx_data *data, * @param cmd_len Length of the command in bytes. * @param response_matches Array of expected response match patterns. * @param matches_size Number of elements in the response_matches array. + * @param response_timeout Response timeout in seconds. * * @return 0 on success, negative errno code on failure. */ int modem_dynamic_cmd_send(struct hl78xx_data *data, modem_chat_script_callback script_user_callback, const uint8_t *cmd, uint16_t cmd_len, const struct modem_chat_match *response_matches, - uint16_t matches_size, bool user_cmd); + uint16_t matches_size, uint16_t response_timeout, bool user_cmd); #define HASH_MULTIPLIER 37 /** diff --git a/drivers/modem/hl78xx/hl78xx_apis.c b/drivers/modem/hl78xx/hl78xx_apis.c index dcb52778655dc..5d2e11fe5c140 100644 --- a/drivers/modem/hl78xx/hl78xx_apis.c +++ b/drivers/modem/hl78xx/hl78xx_apis.c @@ -28,7 +28,7 @@ static int hl78xx_send_cmd(struct hl78xx_data *data, const char *cmd, return -EINVAL; } return modem_dynamic_cmd_send(data, chat_cb, cmd, (uint16_t)strlen(cmd), matches, - match_count, true); + match_count, MDM_CMD_TIMEOUT, true); } int hl78xx_api_func_get_signal(const struct device *dev, const enum cellular_signal_type type, @@ -292,7 +292,7 @@ int hl78xx_api_func_modem_dynamic_cmd_send(const struct device *dev, const char } /* respect provided matches_size and serialize modem access */ return modem_dynamic_cmd_send(data, NULL, cmd, cmd_size, response_matches, matches_size, - true); + MDM_CMD_TIMEOUT, true); } #ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE int hl78xx_start_airvantage_dm_session(const struct device *dev) diff --git a/drivers/modem/hl78xx/hl78xx_cfg.c b/drivers/modem/hl78xx/hl78xx_cfg.c index b640fae32b7be..e81c55ee4cd29 100644 --- a/drivers/modem/hl78xx/hl78xx_cfg.c +++ b/drivers/modem/hl78xx/hl78xx_cfg.c @@ -61,7 +61,7 @@ int hl78xx_rat_cfg(struct hl78xx_data *data, bool *modem_require_restart, } /* Query current rat */ ret = modem_dynamic_cmd_send(data, NULL, cmd_ksrat_query, strlen(cmd_ksrat_query), - hl78xx_get_ksrat_match(), 1, false); + hl78xx_get_ksrat_match(), 1, MDM_CMD_TIMEOUT, false); if (ret < 0) { goto error; } diff --git a/drivers/modem/hl78xx/hl78xx_chat.c b/drivers/modem/hl78xx/hl78xx_chat.c index 8ca45f2d54242..d120eefc2a1e9 100644 --- a/drivers/modem/hl78xx/hl78xx_chat.c +++ b/drivers/modem/hl78xx/hl78xx_chat.c @@ -186,7 +186,7 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(hl78xx_post_restart_chat_script_cmds, ); MODEM_CHAT_SCRIPT_DEFINE(hl78xx_post_restart_chat_script, hl78xx_post_restart_chat_script_cmds, - hl78xx_abort_matches, hl78xx_chat_callback_handler, 1000); + hl78xx_abort_matches, hl78xx_chat_callback_handler, 12); /* init_fail_script moved from hl78xx.c */ MODEM_CHAT_SCRIPT_CMDS_DEFINE(init_fail_script_cmds, diff --git a/drivers/modem/hl78xx/hl78xx_sockets.c b/drivers/modem/hl78xx/hl78xx_sockets.c index cfd002d85494b..f2bb67f193eb0 100644 --- a/drivers/modem/hl78xx/hl78xx_sockets.c +++ b/drivers/modem/hl78xx/hl78xx_sockets.c @@ -1179,7 +1179,7 @@ void iface_status_work_cb(struct hl78xx_data *data, modem_chat_script_callback s int ret = 0; ret = modem_dynamic_cmd_send(data, script_user_callback, cmd, strlen(cmd), - hl78xx_get_cgdcontrdp_match(), 1, false); + hl78xx_get_cgdcontrdp_match(), 1, MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Failed to send AT+CGCONTRDP command: %d", ret); return; @@ -1402,7 +1402,7 @@ static int send_tcp_or_tls_config(struct modem_socket *sock, uint16_t dst_port, snprintk(cmd_buf, sizeof(cmd_buf), "AT+KTCPCFG=1,%d,\"%s\",%u,,,,%d,%s,0", mode, socket_data->tls.hostname, dst_port, af, mode == 3 ? "0" : ""); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_buf, strlen(cmd_buf), - hl78xx_get_ktcpcfg_match(), 1, false); + hl78xx_get_ktcpcfg_match(), 1, MDM_CMD_TIMEOUT, false); if (ret < 0 || socket_data->tcp_conn_status[HL78XX_TCP_STATUS_ID(sock->id)].is_created == false) { LOG_ERR("%s ret:%d", cmd_buf, ret); @@ -1430,7 +1430,9 @@ static int send_udp_config(const struct net_sockaddr *addr, struct hl78xx_socket (addr->sa_family - 1), 0); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_buf, strlen(cmd_buf), - hl78xx_get_kudpind_match(), hl78xx_get_kudpind_allow_matches_size(), MDM_CMD_TIMEOUT_MS, false); + hl78xx_get_kudpind_match(), + hl78xx_get_kudpind_allow_matches_size(), MDM_CMD_TIMEOUT, + false); if (ret < 0) { goto error; } @@ -1493,7 +1495,8 @@ static int socket_close(struct hl78xx_socket_data *socket_data, struct modem_soc } ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, buf, strlen(buf), hl78xx_get_sockets_allow_matches(), - hl78xx_get_sockets_allow_matches_size(), false); + hl78xx_get_sockets_allow_matches_size(), MDM_CMD_TIMEOUT, + false); if (ret < 0) { LOG_ERR("%s ret:%d", buf, ret); } @@ -1516,7 +1519,8 @@ static int socket_delete(struct hl78xx_socket_data *socket_data, struct modem_so snprintk(buf, sizeof(buf), "AT+KTCPDEL=%d", sock->id); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, buf, strlen(buf), hl78xx_get_sockets_allow_matches(), - hl78xx_get_sockets_allow_matches_size(), false); + hl78xx_get_sockets_allow_matches_size(), MDM_CMD_TIMEOUT, + false); if (ret < 0) { LOG_ERR("%s ret:%d", buf, ret); } @@ -1649,7 +1653,7 @@ static int offload_connect(void *obj, const struct net_sockaddr *addr, net_sockl /* send connect command */ snprintk(cmd_buf, sizeof(cmd_buf), "AT+KTCPCNX=%d", sock->id); ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_buf, strlen(cmd_buf), - hl78xx_get_ktcpind_match(), 1, false); + hl78xx_get_ktcpind_match(), 1, MDM_CMD_TIMEOUT, false); if (ret < 0 || socket_data->tcp_conn_status[HL78XX_TCP_STATUS_ID(sock->id)].is_connected == false) { sock->is_connected = false; @@ -1784,7 +1788,7 @@ static void check_tcp_state_if_needed(struct hl78xx_socket_data *socket_data, sock && sock->ip_proto == NET_IPPROTO_TCP) { modem_dynamic_cmd_send(socket_data->mdata_global, NULL, check_ktcp_stat, strlen(check_ktcp_stat), hl78xx_get_ktcp_state_match(), 1, - true); + MDM_CMD_TIMEOUT, true); } } @@ -2016,7 +2020,7 @@ static ssize_t send_socket_data(void *obj, struct hl78xx_socket_data *socket_dat } ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, cmd_buf, strlen(cmd_buf), (const struct modem_chat_match *)hl78xx_get_connect_matches(), - hl78xx_get_connect_matches_size(), false); + hl78xx_get_connect_matches_size(), MDM_CMD_TIMEOUT, false); if (ret < 0 || socket_data->socket_data_error) { hl78xx_set_errno_from_code(ret); ret = -1; @@ -2417,7 +2421,7 @@ static ssize_t hl78xx_send_cert(struct hl78xx_socket_data *socket_data, const ch } ret = modem_dynamic_cmd_send(socket_data->mdata_global, NULL, send_buf, strlen(send_buf), (const struct modem_chat_match *)hl78xx_get_connect_matches(), - hl78xx_get_connect_matches_size(), false); + hl78xx_get_connect_matches_size(), MDM_CMD_TIMEOUT, false); if (ret < 0) { LOG_ERR("Error sending AT command %d", ret); } From 5156de7c68279720e39aa11c9afdafa2d8767aca Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 02:31:14 +0000 Subject: [PATCH 03/10] drivers: modem: hl78xx: add AT command timeout event and handlers Add MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT event to distinguish chat scripts timeouts from other script failures. The chat callback now maps MODEM_CHAT_SCRIPT_RESULT_TIMEOUT to this new event. Update state handlers so AT command timeouts trigger the init fail diagnostic script during startup, and fall back to the power-on pulse in the init-fail state, similar to existing timeout handling. This improves error classification and enables more accurate recovery logic for long-running or stalled AT command exchanges. Signed-off-by: Zafer SEN --- drivers/modem/hl78xx/hl78xx.c | 7 +++++++ drivers/modem/hl78xx/hl78xx_chat.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/modem/hl78xx/hl78xx.c b/drivers/modem/hl78xx/hl78xx.c index 85343f389a505..8ebed2f390020 100644 --- a/drivers/modem/hl78xx/hl78xx.c +++ b/drivers/modem/hl78xx/hl78xx.c @@ -176,6 +176,8 @@ static const char *hl78xx_event_str(enum hl78xx_event event) #endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ case MODEM_HL78XX_EVENT_MDM_RESTART: return "modem unexpected restart"; + case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT: + return "AT command timeout"; default: return "unknown event"; } @@ -1022,6 +1024,10 @@ static void hl78xx_await_power_on_event_handler(struct hl78xx_data *data, enum h hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_SCRIPT); break; + case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT: + hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT); + break; + default: break; } @@ -1077,6 +1083,7 @@ static void hl78xx_run_init_fail_script_event_handler(struct hl78xx_data *data, } break; case MODEM_HL78XX_EVENT_TIMEOUT: + case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT: if (hl78xx_gpio_is_enabled(&config->mdm_gpio_pwr_on)) { hl78xx_enter_state(data, MODEM_HL78XX_STATE_POWER_ON_PULSE); break; diff --git a/drivers/modem/hl78xx/hl78xx_chat.c b/drivers/modem/hl78xx/hl78xx_chat.c index d120eefc2a1e9..436025a48ee86 100644 --- a/drivers/modem/hl78xx/hl78xx_chat.c +++ b/drivers/modem/hl78xx/hl78xx_chat.c @@ -325,6 +325,8 @@ void hl78xx_chat_callback_handler(struct modem_chat *chat, enum modem_chat_scrip if (result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS) { hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_SUCCESS); + } else if (result == MODEM_CHAT_SCRIPT_RESULT_TIMEOUT) { + hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT); } else { hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_FAILED); } From a24dd9ee19495a84c495c9a86b3a2487f4271f18 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 02:33:16 +0000 Subject: [PATCH 04/10] 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 --- drivers/modem/hl78xx/Kconfig.hl78xx | 143 ++++++++++++++- drivers/modem/hl78xx/hl78xx.c | 111 +++++++++++- drivers/modem/hl78xx/hl78xx.h | 12 ++ drivers/modem/hl78xx/hl78xx_apis.c | 3 + drivers/modem/hl78xx/hl78xx_cfg.c | 193 +++++++++++++++++++++ drivers/modem/hl78xx/hl78xx_cfg.h | 10 ++ drivers/modem/hl78xx/hl78xx_chat.c | 4 +- include/zephyr/drivers/modem/hl78xx_apis.h | 2 + 8 files changed, 473 insertions(+), 5 deletions(-) diff --git a/drivers/modem/hl78xx/Kconfig.hl78xx b/drivers/modem/hl78xx/Kconfig.hl78xx index 54cb90a3ccfe7..335f48a76c592 100644 --- a/drivers/modem/hl78xx/Kconfig.hl78xx +++ b/drivers/modem/hl78xx/Kconfig.hl78xx @@ -78,6 +78,143 @@ config MODEM_AT_SHELL_RESPONSE_MAX_SIZE endif # MODEM_HL78XX_AT_SHELL +menuconfig MODEM_HL78XX_AUTO_BAUDRATE + bool "Auto Baud Rate Detection and Switching" + select UART_USE_RUNTIME_CONFIGURE if SOC_SERIES_NRF52X + help + Enable automatic baud rate detection and switching for the HL78xx modem. + The driver will attempt to detect the modem's current baud rate and + switch to the configured target baud rate using AT+IPR command. + +if MODEM_HL78XX_AUTO_BAUDRATE + +choice MODEM_HL78XX_TARGET_BAUDRATE + prompt "Target UART Baud Rate" + default MODEM_HL78XX_TARGET_BAUDRATE_115200 + help + Select the target baud rate for communication with the modem. + The driver will configure the modem to use this baud rate after detection. + +config MODEM_HL78XX_TARGET_BAUDRATE_9600 + bool "9600" + help + Set modem baud rate to 9600 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_19200 + bool "19200" + help + Set modem baud rate to 19200 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_38400 + bool "38400" + help + Set modem baud rate to 38400 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_57600 + bool "57600" + help + Set modem baud rate to 57600 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_115200 + bool "115200" + help + Set modem baud rate to 115200 bps (default) + +config MODEM_HL78XX_TARGET_BAUDRATE_230400 + bool "230400" + help + Set modem baud rate to 230400 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_460800 + bool "460800" + help + Set modem baud rate to 460800 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_921600 + bool "921600" + help + Set modem baud rate to 921600 bps + +config MODEM_HL78XX_TARGET_BAUDRATE_3000000 + bool "3000000" + depends on MODEM_HL78XX_12 + help + Set modem baud rate to 3000000 bps +endchoice + +config MODEM_HL78XX_TARGET_BAUDRATE_VALUE + int + default 9600 if MODEM_HL78XX_TARGET_BAUDRATE_9600 + default 19200 if MODEM_HL78XX_TARGET_BAUDRATE_19200 + default 38400 if MODEM_HL78XX_TARGET_BAUDRATE_38400 + default 57600 if MODEM_HL78XX_TARGET_BAUDRATE_57600 + default 115200 if MODEM_HL78XX_TARGET_BAUDRATE_115200 + default 230400 if MODEM_HL78XX_TARGET_BAUDRATE_230400 + default 460800 if MODEM_HL78XX_TARGET_BAUDRATE_460800 + default 921600 if MODEM_HL78XX_TARGET_BAUDRATE_921600 + default 3000000 if MODEM_HL78XX_TARGET_BAUDRATE_3000000 + +config MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES + string "Baud rates to try during auto-detection (comma-separated)" + default "115200,9600,57600,38400,19200" + help + Comma-separated list of baud rates to try when auto-detecting + the modem's current baud rate. The driver will try each rate + in order until it successfully communicates with the modem. + Common baud rates: 9600, 19200, 38400, 57600, 115200 + +config MODEM_HL78XX_AUTOBAUD_TIMEOUT + int "Timeout for each baud rate detection attempt (seconds)" + default 4 + range 1 120 + help + Maximum time to wait for a response from the modem when trying + a specific baud rate during auto-detection. + +config MODEM_HL78XX_AUTOBAUD_RETRY_COUNT + int "Number of retries for baud rate detection" + default 3 + range 1 10 + help + Number of times to retry baud rate detection before giving up. + +config MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT + bool "Save detected baud rate persistently" + default y + help + Enable this option to save the configuration to the modem non-volatile memory, + otherwise it will revert to previous setting on power cycle. + Highly recommended to enable this option to detect unexpected modem reboots + and quick recovery. + + Baudrate change will be permanent across power cycles. + NOTE: Changing phone functionality (AT+CFUN) does reset baud rate to default. + +config MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE + bool "Start auto baud rate detection with target baud rate" + default y + help + Enable this option to start the auto baud rate detection process + by first attempting communication at the configured target baud rate. + This can speed up detection if the modem is already set to the target rate. + +config MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL + bool "Only perform auto baud rate detection on communication failure" + default y + help + Enable this option to perform auto baud rate detection only + if initial uart communication with the modem at the configured + target baud rate fails. + +config MODEM_HL78XX_AUTOBAUD_AT_BOOT + bool "Perform auto baud rate detection at boot (skip KSUP wait)" + help + When enabled, the driver will immediately perform auto baud rate detection + as soon as the modem is powered up, without waiting for the KSUP URC + (startup ready indication). + +endif # MODEM_HL78XX_AUTO_BAUDRATE + choice MODEM_HL78XX_ADDRESS_FAMILY prompt "IP Address family" default MODEM_HL78XX_ADDRESS_FAMILY_IPV4V6 @@ -874,13 +1011,17 @@ config MODEM_HL78XX_DEV_RESET_PULSE_DURATION_MS config MODEM_HL78XX_DEV_STARTUP_TIME_MS int "Wait before assuming the device is ready." - default 120 + default 2000 if MODEM_HL78XX_AUTOBAUD_AT_BOOT + default 120 if !MODEM_HL78XX_AUTOBAUD_AT_BOOT help The expected delay time (in milliseconds) the modem needs to fully power on and become operational.This delay before the driver opens the UART pipe and attaches the chat layer. The value must be long enough for the driver startup code to initialize, but short enough to ensure the pipe is ready before the modem sends its first URCs during boot. + BUT, + if auto baudrate detection at boot is enabled, + a longer delay is recommended to allow the modem to complete its boot sequence. config MODEM_HL78XX_DEV_SHUTDOWN_TIME_MS int "Wait before assuming the device is completely off." diff --git a/drivers/modem/hl78xx/hl78xx.c b/drivers/modem/hl78xx/hl78xx.c index 8ebed2f390020..49cebbb3aa996 100644 --- a/drivers/modem/hl78xx/hl78xx.c +++ b/drivers/modem/hl78xx/hl78xx.c @@ -1017,13 +1017,31 @@ static void hl78xx_await_power_on_event_handler(struct hl78xx_data *data, enum h case MODEM_HL78XX_EVENT_BUS_OPENED: modem_chat_attach(&data->chat, data->uart_pipe); +#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT + hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE); +#else hl78xx_run_post_restart_script_async(data); +#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT */ break; case MODEM_HL78XX_EVENT_SCRIPT_SUCCESS: + (void)hl78xx_get_uart_config(data); + LOG_DBG("Current baudrate after post-restart script: %d", + data->status.uart.current_baudrate); +#if defined(CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL) || \ + !defined(CONFIG_MODEM_HL78XX_AUTO_BAUDRATE) hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_SCRIPT); +#else + hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE); +#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL */ break; + case MODEM_HL78XX_EVENT_SCRIPT_FAILED: +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE); +#else + hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT); +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT: hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT); break; @@ -1032,6 +1050,71 @@ static void hl78xx_await_power_on_event_handler(struct hl78xx_data *data, enum h break; } } + +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE +static int hl78xx_on_set_baudrate_state_enter(struct hl78xx_data *data) +{ + int ret; + + data->status.uart.target_baudrate = CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_VALUE; + + /* Detect current baud rate */ + ret = hl78xx_detect_current_baudrate(data); + if (ret < 0) { + LOG_ERR("Baud rate detection failed"); + hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_FAILED); + return ret; + } + + /* Switch to target baud rate if different */ + ret = hl78xx_switch_baudrate(data, data->status.uart.target_baudrate); + if (ret < 0) { + LOG_ERR("Failed to switch baud rate: %d", ret); + hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_FAILED); + return ret; + } + data->status.boot.is_booted_previously = true; + hl78xx_delegate_event(data, MODEM_HL78XX_EVENT_SCRIPT_SUCCESS); + return 0; +} + +static void hl78xx_set_baudrate_event_handler(struct hl78xx_data *data, enum hl78xx_event evt) +{ + switch (evt) { + case MODEM_HL78XX_EVENT_SCRIPT_SUCCESS: + hl78xx_enter_state(data, MODEM_HL78XX_STATE_RUN_INIT_SCRIPT); + break; + + case MODEM_HL78XX_EVENT_SCRIPT_FAILED: + /* Increment retry counter */ + data->status.uart.baudrate_detection_retry++; + + /* Retry detection or give up */ + if (data->status.uart.baudrate_detection_retry < + CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT) { + LOG_WRN("Retrying baud rate detection (attempt %d/%d)", + data->status.uart.baudrate_detection_retry + 1, + CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT); + k_sleep(K_MSEC(500)); + hl78xx_on_set_baudrate_state_enter(data); + } else { + LOG_ERR("Baud rate configuration failed after %d attempts", + data->status.uart.baudrate_detection_retry); + hl78xx_enter_state(data, + MODEM_HL78XX_STATE_RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT); + } + break; + + case MODEM_HL78XX_EVENT_SUSPEND: + hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE); + break; + + default: + break; + } +} +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ + static int hl78xx_on_run_init_script_state_enter(struct hl78xx_data *data) { return hl78xx_run_init_script_async(data); @@ -1083,7 +1166,13 @@ static void hl78xx_run_init_fail_script_event_handler(struct hl78xx_data *data, } break; case MODEM_HL78XX_EVENT_TIMEOUT: + LOG_ERR("Modem initialization failed after diagnostic script"); + hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE); + break; case MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT: +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE); +#else if (hl78xx_gpio_is_enabled(&config->mdm_gpio_pwr_on)) { hl78xx_enter_state(data, MODEM_HL78XX_STATE_POWER_ON_PULSE); break; @@ -1095,6 +1184,7 @@ static void hl78xx_run_init_fail_script_event_handler(struct hl78xx_data *data, } hl78xx_enter_state(data, MODEM_HL78XX_STATE_IDLE); +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ break; case MODEM_HL78XX_EVENT_BUS_CLOSED: break; @@ -1169,6 +1259,12 @@ static void hl78xx_run_rat_cfg_script_event_handler(struct hl78xx_data *data, en { switch (evt) { case MODEM_HL78XX_EVENT_TIMEOUT: +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + if (IS_ENABLED(CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT) == false) { + hl78xx_enter_state(data, MODEM_HL78XX_STATE_SET_BAUDRATE); + } + break; +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ LOG_DBG("Rebooting modem to apply new RAT settings"); break; case MODEM_HL78XX_EVENT_MDM_RESTART: @@ -1827,6 +1923,15 @@ static int hl78xx_init(const struct device *dev) data->buffers.eof_pattern_size = strlen(data->buffers.eof_pattern); data->buffers.termination_pattern_size = strlen(data->buffers.termination_pattern); memset(data->identity.apn, 0, MDM_APN_MAX_LENGTH); +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + data->status.uart.current_baudrate = 0; + data->status.uart.target_baudrate = CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_VALUE; + data->status.uart.baudrate_detection_retry = 0; +#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE + /* Update baud rate */ + configure_uart_for_auto_baudrate(data, data->status.uart.target_baudrate); +#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE */ +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ /* GPIO validation */ const struct gpio_dt_spec *gpio_pins[GPIO_CONFIG_LEN] = { #if HAS_RESET_GPIO @@ -2011,11 +2116,13 @@ const static struct hl78xx_state_handlers hl78xx_state_table[] = { NULL, hl78xx_await_power_on_event_handler }, +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE [MODEM_HL78XX_STATE_SET_BAUDRATE] = { + hl78xx_on_set_baudrate_state_enter, NULL, - NULL, - NULL + hl78xx_set_baudrate_event_handler }, +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ [MODEM_HL78XX_STATE_RUN_INIT_SCRIPT] = { hl78xx_on_run_init_script_state_enter, NULL, diff --git a/drivers/modem/hl78xx/hl78xx.h b/drivers/modem/hl78xx/hl78xx.h index 2018e2c05521a..8b4494a5695d2 100644 --- a/drivers/modem/hl78xx/hl78xx.h +++ b/drivers/modem/hl78xx/hl78xx.h @@ -113,6 +113,9 @@ */ #define WDSI_USER_INITIATED_CONNECTION_START_CMD "AT+WDSS=1,1" #define WDSI_USER_INITIATED_CONNECTION_STOP_CMD "AT+WDSS=1,0" +/* Baud rate commands */ +#define GET_BAUDRATE_CMD "AT+IPR?" +#define SET_BAUDRATE_CMD_FMT "AT+IPR=%d" /* Helper macros */ #define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__) @@ -184,6 +187,7 @@ enum hl78xx_event { MODEM_HL78XX_EVENT_WDSI_FIRMWARE_INSTALL_SUCCEEDED, MODEM_HL78XX_EVENT_WDSI_FIRMWARE_INSTALL_FAILED, #endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ + MODEM_HL78XX_EVENT_AT_CMD_TIMEOUT, MODEM_HL78XX_EVENT_COUNT }; @@ -325,6 +329,13 @@ struct hl78xx_wdsi_status { #endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ +struct hl78xx_modem_uart_status { + uint32_t current_baudrate; +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + uint32_t target_baudrate; + uint8_t baudrate_detection_retry; +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ +}; struct modem_status { struct registration_status registration; int16_t rssi; @@ -343,6 +354,7 @@ struct modem_status { #ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE struct hl78xx_wdsi_status wdsi; #endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ + struct hl78xx_modem_uart_status uart; }; struct modem_gpio_callbacks { diff --git a/drivers/modem/hl78xx/hl78xx_apis.c b/drivers/modem/hl78xx/hl78xx_apis.c index 5d2e11fe5c140..1424856912a5f 100644 --- a/drivers/modem/hl78xx/hl78xx_apis.c +++ b/drivers/modem/hl78xx/hl78xx_apis.c @@ -179,6 +179,9 @@ int hl78xx_api_func_get_modem_info_vendor(const struct device *dev, safe_strncpy(info, (const char *)data->identity.serial_number, MIN(size, sizeof(data->identity.serial_number))); break; + case HL78XX_MODEM_INFO_CURRENT_BAUD_RATE: + *(uint32_t *)info = data->status.uart.current_baudrate; + break; default: break; } diff --git a/drivers/modem/hl78xx/hl78xx_cfg.c b/drivers/modem/hl78xx/hl78xx_cfg.c index e81c55ee4cd29..0d440511d0c45 100644 --- a/drivers/modem/hl78xx/hl78xx_cfg.c +++ b/drivers/modem/hl78xx/hl78xx_cfg.c @@ -21,6 +21,8 @@ LOG_MODULE_DECLARE(hl78xx_dev); #define IMSI_PREFIX_LEN 6 #define MAX_BANDS 32 #define MDM_APN_FULL_STRING_MAX_LEN 256 +/* Delay after AT+IPR command for new rate to take effect */ +#define BAUDRATE_SWITCH_DELAY_MS 2500 int hl78xx_rat_cfg(struct hl78xx_data *data, bool *modem_require_restart, enum hl78xx_cell_rat_mode *rat_request) @@ -647,3 +649,194 @@ void hl78xx_extract_essential_part_apn(const char *full_apn, char *essential_apn essential_apn[max_len - 1] = '\0'; } } + +int hl78xx_get_uart_config(struct hl78xx_data *data) +{ + const struct hl78xx_config *config = (const struct hl78xx_config *)data->dev->config; + struct uart_config uart_cfg; + int ret; + /* Get current UART configuration */ + ret = uart_config_get(config->uart, &uart_cfg); + if (ret < 0) { + LOG_ERR("Failed to get UART config: %d", ret); + return ret; + } + data->status.uart.current_baudrate = uart_cfg.baudrate; + return 0; +} + +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + +int configure_uart_for_auto_baudrate(struct hl78xx_data *data, uint32_t baudrate) +{ + const struct hl78xx_config *config = (const struct hl78xx_config *)data->dev->config; + struct uart_config uart_cfg; + int ret; + + /* Get current UART configuration */ + ret = uart_config_get(config->uart, &uart_cfg); + if (ret < 0) { + LOG_ERR("Failed to get UART config: %d", ret); + return ret; + } + + /* Update baud rate */ + uart_cfg.baudrate = baudrate; + LOG_INF("Trying baud rate: %d", baudrate); + /* Apply new UART configuration */ + ret = uart_configure(config->uart, &uart_cfg); + if (ret < 0) { + LOG_ERR("Failed to set UART baud rate to %d: %d", baudrate, ret); + return ret; + } + + /* Give the modem time to stabilize */ + k_sleep(K_MSEC(50)); + return 0; +} + +int hl78xx_try_baudrate(struct hl78xx_data *data, uint32_t baudrate) +{ + int ret; + /* Configure UART to the target baud rate */ + ret = configure_uart_for_auto_baudrate(data, baudrate); + if (ret < 0) { + return ret; + } + /* Try to send AT command and wait for response */ + const char *test_cmd = "AT"; + + ret = modem_dynamic_cmd_send(data, NULL, test_cmd, strlen(test_cmd), + hl78xx_get_sockets_allow_matches(), + hl78xx_get_sockets_allow_matches_size(), + CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT, false); + + if (ret == 0) { + LOG_INF("Modem responded at %d baud", baudrate); + data->status.uart.current_baudrate = baudrate; + return 0; + } + + return -ENOENT; +} + +int hl78xx_detect_current_baudrate(struct hl78xx_data *data) +{ + const char *baudrate_list = CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES; + char baudrate_str[16]; + const char *ptr = baudrate_list; + int idx = 0; + int ret; + + LOG_INF("Starting baud rate detection..."); + + while (*ptr != '\0') { + /* Extract baud rate from string */ + while (*ptr == ' ' || *ptr == ',') { + ptr++; + } + + if (*ptr == '\0') { + break; + } + + idx = 0; + while (*ptr >= '0' && *ptr <= '9' && idx < sizeof(baudrate_str) - 1) { + baudrate_str[idx++] = *ptr++; + } + baudrate_str[idx] = '\0'; + + if (idx > 0) { + uint32_t baudrate = (uint32_t)strtol(baudrate_str, NULL, 10); + + LOG_DBG("Trying baud rate: %d", baudrate); + ret = hl78xx_try_baudrate(data, baudrate); + if (ret == 0) { + return 0; + } + } + } + + LOG_ERR("Failed to detect modem baud rate"); + return -ENOENT; +} + +int hl78xx_switch_baudrate(struct hl78xx_data *data, uint32_t target_baudrate) +{ + char cmd_buf[32]; + const struct hl78xx_config *config = (const struct hl78xx_config *)data->dev->config; + struct uart_config uart_cfg; + int ret; + + if (data->status.uart.current_baudrate == target_baudrate) { + LOG_INF("Already at target baud rate %d", target_baudrate); + return 0; + } + + LOG_INF("Switching baud rate from %d to %d", data->status.uart.current_baudrate, + target_baudrate); + + /* Send AT+IPR command to set baud rate */ + snprintf(cmd_buf, sizeof(cmd_buf), SET_BAUDRATE_CMD_FMT, target_baudrate); + ret = modem_dynamic_cmd_send(data, NULL, cmd_buf, strlen(cmd_buf), hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); + + if (ret < 0) { + LOG_ERR("Failed to send baud rate change command: %d", ret); + return ret; + } + + /* Wait for new baud rate to take effect (~2s per AT command guide) */ + LOG_DBG("Waiting %d ms for modem to apply new baud rate", BAUDRATE_SWITCH_DELAY_MS); + k_sleep(K_MSEC(BAUDRATE_SWITCH_DELAY_MS)); + + /* Get current UART configuration */ + ret = uart_config_get(config->uart, &uart_cfg); + if (ret < 0) { + LOG_ERR("Failed to get UART config: %d", ret); + return ret; + } + + /* Update to new baud rate */ + uart_cfg.baudrate = target_baudrate; + ret = uart_configure(config->uart, &uart_cfg); + if (ret < 0) { + LOG_ERR("Failed to configure new baud rate: %d", ret); + return ret; + } + + /* Wait for UART to stabilize */ + k_sleep(K_MSEC(50)); + + /* Verify communication at new baud rate */ + const char *test_cmd = "AT"; + + ret = modem_dynamic_cmd_send(data, NULL, test_cmd, strlen(test_cmd), hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), + CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT, false); + + if (ret < 0) { + LOG_ERR("Failed to communicate at new baud rate %d", target_baudrate); + return ret; + } + +#ifdef CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT + /* Save configuration to non-volatile memory (required per AT command guide) */ + const char *cmd_save = "AT&W"; + + ret = modem_dynamic_cmd_send(data, NULL, cmd_save, strlen(cmd_save), hl78xx_get_ok_match(), + hl78xx_get_ok_match_size(), MDM_CMD_TIMEOUT, false); + + if (ret < 0) { + LOG_WRN("Failed to save baud rate to NVRAM: %d (will be temporary)", ret); + /* Continue anyway - baud rate is still active for current session */ + } else { + LOG_DBG("Baud rate configuration saved to NVRAM"); + } +#endif /* CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT */ + data->status.uart.current_baudrate = target_baudrate; + LOG_INF("Successfully switched to baud rate %d", target_baudrate); + + return 0; +} +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ diff --git a/drivers/modem/hl78xx/hl78xx_cfg.h b/drivers/modem/hl78xx/hl78xx_cfg.h index ec4f07db1cf4c..a25244161c399 100644 --- a/drivers/modem/hl78xx/hl78xx_cfg.h +++ b/drivers/modem/hl78xx/hl78xx_cfg.h @@ -29,6 +29,16 @@ int hl78xx_gsm_pdp_activate(struct hl78xx_data *data); int hl78xx_set_apn_internal(struct hl78xx_data *data, const char *apn, uint16_t size); +int hl78xx_get_uart_config(struct hl78xx_data *data); + +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE +/* Baud rate detection and switching */ +int configure_uart_for_auto_baudrate(struct hl78xx_data *data, uint32_t baudrate); +int hl78xx_try_baudrate(struct hl78xx_data *data, uint32_t baudrate); +int hl78xx_detect_current_baudrate(struct hl78xx_data *data); +int hl78xx_switch_baudrate(struct hl78xx_data *data, uint32_t target_baudrate); +#endif /* CONFIG_MODEM_HL78XX_AUTO_BAUDRATE */ + /** * @brief Convert a binary bitmap to a trimmed hexadecimal string. * diff --git a/drivers/modem/hl78xx/hl78xx_chat.c b/drivers/modem/hl78xx/hl78xx_chat.c index 436025a48ee86..f3e0963e26dbb 100644 --- a/drivers/modem/hl78xx/hl78xx_chat.c +++ b/drivers/modem/hl78xx/hl78xx_chat.c @@ -252,11 +252,11 @@ MODEM_CHAT_SCRIPT_DEFINE(hl78xx_fota_install_accept_script, hl78xx_fota_install_ */ MODEM_CHAT_MATCHES_DEFINE(connect_matches, MODEM_CHAT_MATCH(CONNECT_STRING, "", NULL), MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL), - MODEM_CHAT_MATCH(ERROR_STRING, "", NULL), ); + MODEM_CHAT_MATCH(ERROR_STRING, "", NULL)); MODEM_CHAT_MATCHES_DEFINE(kudpind_allow_match, MODEM_CHAT_MATCH("+KUDP_IND: ", ",", hl78xx_on_kudpsocket_create), MODEM_CHAT_MATCH(CME_ERROR_STRING, "", NULL), - MODEM_CHAT_MATCH(ERROR_STRING, "", NULL), ); + MODEM_CHAT_MATCH(ERROR_STRING, "", NULL)); MODEM_CHAT_MATCH_DEFINE(ktcpind_match, "+KTCP_IND: ", ",", hl78xx_on_ktcpind); MODEM_CHAT_MATCH_DEFINE(ktcpcfg_match, "+KTCPCFG: ", "", hl78xx_on_ktcpsocket_create); MODEM_CHAT_MATCH_DEFINE(cgdcontrdp_match, "+CGCONTRDP: ", ",", hl78xx_on_cgdcontrdp); diff --git a/include/zephyr/drivers/modem/hl78xx_apis.h b/include/zephyr/drivers/modem/hl78xx_apis.h index 9dae64c2df5e9..ce2e9dd7d4a31 100644 --- a/include/zephyr/drivers/modem/hl78xx_apis.h +++ b/include/zephyr/drivers/modem/hl78xx_apis.h @@ -106,6 +106,8 @@ enum hl78xx_modem_info_type { HL78XX_MODEM_INFO_NETWORK_OPERATOR, /* */ HL78XX_MODEM_INFO_SERIAL_NUMBER, + /* Current Baud Rate */ + HL78XX_MODEM_INFO_CURRENT_BAUD_RATE, }; /** Cellular network structure */ From 47d6a9b06a29c5f01c4367e6fbc470839d49cd2d Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 04:45:40 +0000 Subject: [PATCH 05/10] samples: modem: hello_hl78xx: restructure prj.conf and verbose overlay Reorganize the sample configuration files for clarity and easier maintenance. This introduces grouped sections with descriptive comments and improves consistency between prj.conf and the verbose-logging overlay. Main updates: * Add structured headers for system, UART, networking, modem, RAT, AirVantage, shell, and logging settings * Expand verbose overlay with clearer purpose, build notes, and grouped modem logging options * Improve readability by aligning comments and collecting related options * No functional behavior is changed; this is a documentation and structure improvement These changes make the sample configuration easier to understand and simplify future maintenance. Signed-off-by: Zafer SEN --- .../overlay-swir_hl78xx-verbose-logging.conf | 18 +++++- samples/drivers/modem/hello_hl78xx/prj.conf | 60 ++++++++++++------- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/samples/drivers/modem/hello_hl78xx/overlay-swir_hl78xx-verbose-logging.conf b/samples/drivers/modem/hello_hl78xx/overlay-swir_hl78xx-verbose-logging.conf index 8fad488237a6e..6724b773cdb91 100644 --- a/samples/drivers/modem/hello_hl78xx/overlay-swir_hl78xx-verbose-logging.conf +++ b/samples/drivers/modem/hello_hl78xx/overlay-swir_hl78xx-verbose-logging.conf @@ -1,8 +1,22 @@ -# Logging +# ============================================================================ +# Verbose Logging Configuration for HL78XX Modem +# ============================================================================ +# Use this overlay for detailed debugging and troubleshooting +# Build with: west build -- -DEXTRA_CONF_FILE=overlay-swir_hl78xx-verbose-logging.conf + +# ============================================================================ +# Logging Infrastructure +# ============================================================================ +# Large log buffer to prevent message loss during verbose logging CONFIG_LOG_BUFFER_SIZE=85536 -# For extra verbosity +# ============================================================================ +# Modem Debug Logging +# ============================================================================ +# Enable debug-level logging for all modem modules CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y CONFIG_MODEM_LOG_LEVEL_DBG=y +# Larger buffer for modem chat logs (captures AT commands and responses) CONFIG_MODEM_CHAT_LOG_BUFFER_SIZE=1024 +# Enable verbose debug context for HL78XX driver CONFIG_MODEM_HL78XX_LOG_CONTEXT_VERBOSE_DEBUG=y diff --git a/samples/drivers/modem/hello_hl78xx/prj.conf b/samples/drivers/modem/hello_hl78xx/prj.conf index f1a0e63ad7e52..eb0f20569b712 100644 --- a/samples/drivers/modem/hello_hl78xx/prj.conf +++ b/samples/drivers/modem/hello_hl78xx/prj.conf @@ -5,67 +5,72 @@ # The HL78xx driver gets its IP settings from the cell network -#system +# ============================================================================ +# System Configuration +# ============================================================================ CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_STACK_SIZE=4096 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_POSIX_API=y -#PM +# ============================================================================ +# Power Management (Optional) +# ============================================================================ # CONFIG_PM_DEVICE=y -#uart +# ============================================================================ +# UART Configuration +# ============================================================================ CONFIG_UART_ASYNC_API=y +# CONFIG_UART_INTERRUPT_DRIVEN=y +# CONFIG_MODEM_BACKEND_UART_ASYNC_HWFC=y -# Generic networking options +# ============================================================================ +# Networking Stack +# ============================================================================ CONFIG_NETWORKING=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y - # DNS CONFIG_DNS_RESOLVER=y CONFIG_NET_SOCKETS_DNS_TIMEOUT=12000 - # Wait for the network to be ready CONFIG_NET_SAMPLE_COMMON_WAIT_DNS_SERVER_ADDITION=y - # Network management CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y # NB-IoT has large latency, so increase timeouts. It is ok to use this for Cat-M1 as well. CONFIG_NET_SOCKETS_CONNECT_TIMEOUT=15000 CONFIG_NET_CONNECTION_MANAGER=y - # Network buffers CONFIG_NET_PKT_RX_COUNT=32 CONFIG_NET_PKT_TX_COUNT=16 CONFIG_NET_BUF_RX_COUNT=64 CONFIG_NET_BUF_TX_COUNT=32 -# Modem driver +# ============================================================================ +# Modem Driver - HL78XX +# ============================================================================ CONFIG_MODEM=y - #hl78xx modem CONFIG_MODEM_HL78XX=y - # Statistics CONFIG_MODEM_STATS=y -# shell -CONFIG_SHELL=y -CONFIG_MODEM_HL78XX_AT_SHELL=y -CONFIG_MODEM_AT_SHELL_COMMAND_MAX_SIZE=256 - -#apn source +# ============================================================================ +# APN Configuration (Disabled - using defaults) +# ============================================================================ # CONFIG_MODEM_HL78XX_APN_SOURCE_KCONFIG=y # CONFIG_MODEM_HL78XX_APN="internet" # CONFIG_MODEM_HL78XX_APN_SOURCE_ICCID=y # CONFIG_MODEM_HL78XX_APN_PROFILES="hologram=23450, wm=20601, vodafone=8988239, em=8988303" -# RAT selection +# ============================================================================ +# Radio Access Technology (RAT) Configuration +# ============================================================================ CONFIG_MODEM_HL78XX_AUTORAT=n # CONFIG_MODEM_HL78XX_AUTORAT_PRL_PROFILES="2,1,3" # CONFIG_MODEM_HL78XX_AUTORAT_NB_BAND_CFG="3,8,20,28" @@ -75,13 +80,28 @@ CONFIG_MODEM_HL78XX_AUTORAT=n # Stay in boot mode until registered to a network # CONFIG_MODEM_HL78XX_STAY_IN_BOOT_MODE_FOR_ROAMING=y -# Enable AirVantage support +# ============================================================================ +# AirVantage Over-The-Air (OTA) Support +# ============================================================================ CONFIG_MODEM_HL78XX_AIRVANTAGE=y CONFIG_MODEM_HL78XX_AIRVANTAGE_USER_AGREEMENT=y CONFIG_MODEM_HL78XX_AIRVANTAGE_UA_CONNECT_AIRVANTAGE=y CONFIG_MODEM_HL78XX_AIRVANTAGE_UA_DOWNLOAD_FIRMWARE=y CONFIG_MODEM_HL78XX_AIRVANTAGE_UA_INSTALL_FIRMWARE=y -# Monitor modem events + +# ============================================================================ +# Shell and Debug Tools +# ============================================================================ +CONFIG_SHELL=y +CONFIG_MODEM_HL78XX_AT_SHELL=y +CONFIG_MODEM_AT_SHELL_COMMAND_MAX_SIZE=256 + +# ============================================================================ +# Event Monitoring +# ============================================================================ CONFIG_HL78XX_EVT_MONITOR=y + +# ============================================================================ # Logging +# ============================================================================ CONFIG_LOG=y From 8c73a0fbeb993d9d436359d4f4724ddb45e2fd67 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 04:49:25 +0000 Subject: [PATCH 06/10] samples: modem: hello_hl78xx: remove POSIX API dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sample no longer requires the POSIX API layer, so the CONFIG_POSIX_API option is removed from prj.conf. The code is updated to use the native zsock_* APIs instead of the POSIX getaddrinfo(), inet_ntop(), and freeaddrinfo() variants. This aligns the sample with Zephyr’s preferred socket API and avoids pulling in unnecessary POSIX compatibility layers. No functional behavior is changed. Signed-off-by: Zafer SEN --- samples/drivers/modem/hello_hl78xx/prj.conf | 1 - samples/drivers/modem/hello_hl78xx/src/main.c | 14 +++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/samples/drivers/modem/hello_hl78xx/prj.conf b/samples/drivers/modem/hello_hl78xx/prj.conf index eb0f20569b712..4b482a9e2c8d4 100644 --- a/samples/drivers/modem/hello_hl78xx/prj.conf +++ b/samples/drivers/modem/hello_hl78xx/prj.conf @@ -11,7 +11,6 @@ CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_STACK_SIZE=4096 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -CONFIG_POSIX_API=y # ============================================================================ # Power Management (Optional) diff --git a/samples/drivers/modem/hello_hl78xx/src/main.c b/samples/drivers/modem/hello_hl78xx/src/main.c index e1f8849851ccb..9e97535236252 100644 --- a/samples/drivers/modem/hello_hl78xx/src/main.c +++ b/samples/drivers/modem/hello_hl78xx/src/main.c @@ -16,10 +16,6 @@ #include #include -#include -#include -#include - /* Macros used to subscribe to specific Zephyr NET management events. */ #if defined(CONFIG_NET_SAMPLE_COMMON_WAIT_DNS_SERVER_ADDITION) #define L4_EVENT_MASK (NET_EVENT_DNS_SERVER_ADD | NET_EVENT_L4_DISCONNECTED) @@ -186,9 +182,9 @@ static void hl78xx_on_ok(struct modem_chat *chat, char **argv, uint16_t argc, vo static int resolve_broker_addr(struct sockaddr_in *broker) { int ret; - struct addrinfo *ai = NULL; + struct zsock_addrinfo *ai = NULL; - const struct addrinfo hints = { + const struct zsock_addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = 0, @@ -196,19 +192,19 @@ static int resolve_broker_addr(struct sockaddr_in *broker) char port_string[6] = {0}; snprintf(port_string, sizeof(port_string), "%d", TEST_SERVER_PORT); - ret = getaddrinfo(TEST_SERVER_ENDPOINT, port_string, &hints, &ai); + ret = zsock_getaddrinfo(TEST_SERVER_ENDPOINT, port_string, &hints, &ai); if (ret == 0) { char addr_str[INET_ADDRSTRLEN]; memcpy(broker, ai->ai_addr, MIN(ai->ai_addrlen, sizeof(struct sockaddr_storage))); - inet_ntop(AF_INET, &broker->sin_addr, addr_str, sizeof(addr_str)); + zsock_inet_ntop(AF_INET, &broker->sin_addr, addr_str, sizeof(addr_str)); LOG_INF("Resolved: %s:%u", addr_str, htons(broker->sin_port)); } else { LOG_ERR("failed to resolve hostname err = %d (errno = %d)", ret, errno); } - freeaddrinfo(ai); + zsock_freeaddrinfo(ai); return ret; } From 5d40291f12b8ac3a383dc64e349fcb8a3987602a Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 05:01:21 +0000 Subject: [PATCH 07/10] samples: modem: hello_hl78xx: demonstrate AirVantage FOTA API Add support for handling AirVantage WDSI indications in the sample application. FOTA update progress, download requests, and completion events are processed and coordinated using a new semaphore. The sample can restart its connection workflow after a successful firmware update. Additional updates include: - add serial number retrieval and logging - add fota_complete_rerun semaphore and status tracking - simplify debug logging in event listener and OK handler - reorganize main loop to support FOTA-triggered reruns This aligns the sample with the modem driver's expanded AirVantage and WDSI support. Signed-off-by: Zafer SEN --- samples/drivers/modem/hello_hl78xx/src/main.c | 81 +++++++++++++++++-- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/samples/drivers/modem/hello_hl78xx/src/main.c b/samples/drivers/modem/hello_hl78xx/src/main.c index 9e97535236252..cedff3a3c61dc 100644 --- a/samples/drivers/modem/hello_hl78xx/src/main.c +++ b/samples/drivers/modem/hello_hl78xx/src/main.c @@ -30,12 +30,16 @@ LOG_MODULE_REGISTER(main, CONFIG_MODEM_LOG_LEVEL); static K_SEM_DEFINE(network_connected_sem, 0, 1); -const struct device *modem = DEVICE_DT_GET(DT_ALIAS(modem)); +static K_SEM_DEFINE(fota_complete_rerun, 0, 1); +const static struct device *modem = DEVICE_DT_GET(DT_ALIAS(modem)); /* Zephyr NET management event callback structures. */ static struct net_mgmt_event_callback l4_cb; static struct net_mgmt_event_callback conn_cb; - +#ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE +static int fota_update_status = -1; +#endif +/** Convert RAT mode enum to string */ static const char *rat_get_in_string(enum hl78xx_cell_rat_mode rat) { switch (rat) { @@ -144,9 +148,6 @@ static void l4_event_handler(struct net_mgmt_event_callback *cb, uint64_t event, static void evnt_listener(struct hl78xx_evt *event, struct hl78xx_evt_monitor_entry *context) { -#ifdef CONFIG_MODEM_HL78XX_LOG_CONTEXT_VERBOSE_DEBUG - LOG_DBG("%d HL78XX modem Event Received: %d", __LINE__, event->type); -#endif switch (event->type) { /* Do something */ case HL78XX_LTE_RAT_UPDATE: @@ -160,7 +161,40 @@ static void evnt_listener(struct hl78xx_evt *event, struct hl78xx_evt_monitor_en LOG_INF("%d HL78XX modem startup status: %s", __LINE__, hl78xx_module_status_to_string(event->content.value)); break; +#ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE + case HL78XX_LTE_FOTA_UPDATE_STATUS: + LOG_INF("%d HL78XX modem FOTA update status: %d", __LINE__, + event->content.wdsi_indication); + if (event->content.wdsi_indication == WDSI_FIRMWARE_UPDATE_SUCCESS) { + LOG_INF("FOTA update complete, restarting modem..."); + k_sem_reset(&network_connected_sem); + fota_update_status = (int)WDSI_FIRMWARE_UPDATE_SUCCESS; + k_sem_give(&fota_complete_rerun); + } else if (event->content.wdsi_indication == WDSI_FIRMWARE_UPDATE_FAILED) { + LOG_INF("FOTA update failed."); + fota_update_status = (int)WDSI_FIRMWARE_UPDATE_FAILED; + k_sem_give(&fota_complete_rerun); + } else if (event->content.wdsi_indication == WDSI_FIRMWARE_DOWNLOAD_REQUEST && + fota_update_status != (int)WDSI_FIRMWARE_DOWNLOAD_REQUEST) { + LOG_INF("FOTA download requested, starting download..."); + if (fota_update_status != (int)WDSI_SESSION_STARTED) { + return; + } + fota_update_status = (int)WDSI_FIRMWARE_DOWNLOAD_REQUEST; + k_sem_give(&fota_complete_rerun); + } else if (event->content.wdsi_indication == WDSI_SESSION_STARTED) { + LOG_INF("FOTA session started..."); + fota_update_status = (int)WDSI_SESSION_STARTED; + } else { + /* Other WDSI indications can be handled here if needed */ + } + + break; +#endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ default: +#ifdef CONFIG_MODEM_HL78XX_LOG_CONTEXT_VERBOSE_DEBUG + LOG_DBG("%d HL78XX modem Event Received: %d", __LINE__, event->type); +#endif break; } } @@ -171,7 +205,7 @@ static void hl78xx_on_ok(struct modem_chat *chat, char **argv, uint16_t argc, vo return; } #ifdef CONFIG_MODEM_HL78XX_LOG_CONTEXT_VERBOSE_DEBUG - LOG_DBG("%d %s %s", __LINE__, __func__, argv[0]); + LOG_DBG("%d %s", __LINE__, argv[0]); #endif } @@ -251,7 +285,6 @@ int main(void) } (void)conn_mgr_if_connect(iface); - LOG_INF("Waiting for network connection..."); k_sem_take(&network_connected_sem, K_FOREVER); } @@ -262,6 +295,7 @@ int main(void) char apn[MDM_APN_MAX_LENGTH] = {0}; char operator[MDM_MODEL_LENGTH] = {0}; char imei[MDM_IMEI_LENGTH] = {0}; + char serial_number[MDM_SERIAL_NUMBER_LENGTH] = {0}; enum hl78xx_cell_rat_mode tech; enum cellular_registration_status status; int16_t rsrp; @@ -289,6 +323,9 @@ int main(void) hl78xx_get_modem_info(modem, HL78XX_MODEM_INFO_APN, (char *)apn, sizeof(apn)); + hl78xx_get_modem_info(modem, HL78XX_MODEM_INFO_SERIAL_NUMBER, (char *)serial_number, + sizeof(serial_number)); + cellular_get_modem_info(modem, CELLULAR_MODEM_INFO_IMEI, imei, sizeof(imei)); #ifdef CONFIG_MODEM_HL78XX_AUTORAT /* In auto rat mode, get the current rat from the modem status */ @@ -308,6 +345,7 @@ int main(void) LOG_RAW("**********************************************************\n"); LOG_INF("Manufacturer: %s", manufacturer); LOG_INF("Firmware Version: %s", fw_ver); + LOG_INF("Module Serial Number: %s", serial_number); LOG_INF("APN: \"%s\"", apn); LOG_INF("Imei: %s", imei); LOG_INF("RAT: %s", rat_get_in_string(tech)); @@ -337,6 +375,35 @@ int main(void) resolve_broker_addr(&test_endpoint_addr); +#ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE +#ifdef CONFIG_MODEM_HL78XX_AIRVANTAGE_UA_CONNECT_AIRVANTAGE + LOG_INF("Starting AirVantage DM session..."); + hl78xx_start_airvantage_dm_session(modem); + k_sem_reset(&fota_complete_rerun); + LOG_INF("Waiting for AirVantage FOTA Creation..."); + /* Wait for FOTA download request, max 120 seconds */ + ret = k_sem_take(&fota_complete_rerun, K_SECONDS(120)); + if (ret < 0) { + LOG_WRN("AirVantage DM session timed out waiting for FOTA download request.%d", + ret); + } else { + k_sem_reset(&fota_complete_rerun); + LOG_INF("Waiting for AirVantage FOTA Completion..."); + /* Wait for FOTA completion */ + ret = k_sem_take(&fota_complete_rerun, K_FOREVER); + if (fota_update_status == (int)WDSI_FIRMWARE_UPDATE_SUCCESS) { + LOG_INF("FOTA update successful, restarting application to apply update."); + } else if (fota_update_status == (int)WDSI_FIRMWARE_UPDATE_FAILED) { + LOG_WRN("FOTA update failed."); + } else { + LOG_WRN("FOTA update status unknown."); + } + } + +#else + LOG_WRN("AirVantage User Agreement not accepted, cannot start DM session."); +#endif +#endif /* CONFIG_MODEM_HL78XX_AIRVANTAGE */ LOG_INF("Sample application finished."); return 0; From 7bbb585f75f54818c312d31588a94ed4a75c3be4 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 05:03:38 +0000 Subject: [PATCH 08/10] samples: modem: hello_hl78xx: select RSSI or RSRP based on RAT mode The sample previously always queried RSRP, which is not valid when the HL78xx operates in GSM mode. Use RSSI when GSM RAT is active and RSRP for other RATs. Update the log output and rename the variable for clarity. Signed-off-by: Zafer SEN --- samples/drivers/modem/hello_hl78xx/src/main.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/samples/drivers/modem/hello_hl78xx/src/main.c b/samples/drivers/modem/hello_hl78xx/src/main.c index cedff3a3c61dc..8e97646353533 100644 --- a/samples/drivers/modem/hello_hl78xx/src/main.c +++ b/samples/drivers/modem/hello_hl78xx/src/main.c @@ -298,7 +298,7 @@ int main(void) char serial_number[MDM_SERIAL_NUMBER_LENGTH] = {0}; enum hl78xx_cell_rat_mode tech; enum cellular_registration_status status; - int16_t rsrp; + int16_t signal_strength = 0; const char *newapn = ""; const char *sample_cmd = "AT"; @@ -335,7 +335,11 @@ int main(void) /* Get the current registration status */ cellular_get_registration_status(modem, hl78xx_rat_to_access_tech(tech), &status); /* Get the current signal strength */ - cellular_get_signal(modem, CELLULAR_SIGNAL_RSRP, &rsrp); +#ifdef CONFIG_MODEM_HL78XX_RAT_GSM + cellular_get_signal(modem, CELLULAR_SIGNAL_RSSI, &signal_strength); +#else + cellular_get_signal(modem, CELLULAR_SIGNAL_RSRP, &signal_strength); +#endif /* Get the current network operator name */ hl78xx_get_modem_info(modem, HL78XX_MODEM_INFO_NETWORK_OPERATOR, (char *)operator, sizeof(operator)); @@ -350,7 +354,11 @@ int main(void) LOG_INF("Imei: %s", imei); LOG_INF("RAT: %s", rat_get_in_string(tech)); LOG_INF("Connection status: %s(%d)", reg_status_get_in_string(status), status); - LOG_INF("RSRP : %d", rsrp); +#ifdef CONFIG_MODEM_HL78XX_RAT_GSM + LOG_INF("RSSI : %d", signal_strength); +#else + LOG_INF("RSRP : %d", signal_strength); +#endif LOG_INF("Operator: %s", (strlen(operator) > 0) ? operator : "\"\""); LOG_RAW("**********************************************************\n\n"); From af5a3fa664e7e0efeab580897a46650153eb31ec Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 05:05:24 +0000 Subject: [PATCH 09/10] samples: modem: hello_hl78xx: add auto-baud support and log current baud Enable HL78XX modem auto-baudrate detection and switching in the sample application. Set 921600 bps as the target baudrate with fallback options (9600, 115200, 57600, 38400, 19200). Also read and log the current baudrate from the modem during startup. This helps verify and debug communication speed mismatches between the modem and the device UART. Signed-off-by: Zafer SEN --- samples/drivers/modem/hello_hl78xx/prj.conf | 20 +++++++++++++++++++ samples/drivers/modem/hello_hl78xx/src/main.c | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/samples/drivers/modem/hello_hl78xx/prj.conf b/samples/drivers/modem/hello_hl78xx/prj.conf index 4b482a9e2c8d4..137f6a1c519aa 100644 --- a/samples/drivers/modem/hello_hl78xx/prj.conf +++ b/samples/drivers/modem/hello_hl78xx/prj.conf @@ -59,6 +59,26 @@ CONFIG_MODEM_HL78XX=y # Statistics CONFIG_MODEM_STATS=y +# ============================================================================ +# Auto Baud Rate Detection and Switching +# ============================================================================ +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +# CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT=y +# CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=n +# CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_9600=y +# CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_115200=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="9600,115200,921600,57600,38400,19200" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=4 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=3 +# After enabling auto-baud once WITH CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT, +# the modem's baud rate is saved to NV-MEM with AT&W, so it persists across power cycles. +# If you later disable CONFIG_MODEM_HL78XX_AUTO_BAUDRATE, the driver won't detect/switch, +# but the modem is still at the target baud rate (e.g., 921600) +# If your device tree UART is at 115200 but the modem is at 921600, communication will fail +# CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=n +# CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=n + # ============================================================================ # APN Configuration (Disabled - using defaults) # ============================================================================ diff --git a/samples/drivers/modem/hello_hl78xx/src/main.c b/samples/drivers/modem/hello_hl78xx/src/main.c index 8e97646353533..bc53e5c10df47 100644 --- a/samples/drivers/modem/hello_hl78xx/src/main.c +++ b/samples/drivers/modem/hello_hl78xx/src/main.c @@ -299,6 +299,7 @@ int main(void) enum hl78xx_cell_rat_mode tech; enum cellular_registration_status status; int16_t signal_strength = 0; + uint32_t current_baudrate = 0; const char *newapn = ""; const char *sample_cmd = "AT"; @@ -343,6 +344,9 @@ int main(void) /* Get the current network operator name */ hl78xx_get_modem_info(modem, HL78XX_MODEM_INFO_NETWORK_OPERATOR, (char *)operator, sizeof(operator)); + /* Get the current baudrate */ + hl78xx_get_modem_info(modem, HL78XX_MODEM_INFO_CURRENT_BAUD_RATE, ¤t_baudrate, + sizeof(current_baudrate)); LOG_RAW("\n**********************************************************\n"); LOG_RAW("********* Hello HL78XX Modem Sample Application **********\n"); @@ -360,6 +364,7 @@ int main(void) LOG_INF("RSRP : %d", signal_strength); #endif LOG_INF("Operator: %s", (strlen(operator) > 0) ? operator : "\"\""); + LOG_INF("Current Baudrate: %dbps", current_baudrate); LOG_RAW("**********************************************************\n\n"); LOG_INF("Setting new APN: %s", newapn); From 813caca2cfdf233b305b918e96bffae2becc4fc8 Mon Sep 17 00:00:00 2001 From: Zafer SEN Date: Sat, 6 Dec 2025 06:51:26 +0000 Subject: [PATCH 10/10] doc: hl78xx: add auto-baudrate detection and switching docs Add detailed documentation for the HL78xx auto-baudrate feature, including: - AUTO_BAUDRATE_README.md: full description, use cases, configuration options, and troubleshooting - QUICK_REFERENCE.md: concise reference for presets, Kconfig options, and supported baud rates Covers: - Feature overview and implementation details - Supported baud rates and Kconfig options - State machine integration - Troubleshooting guidance - Performance and optimization tips - Integration examples This improves usability and provides a quick reference for developers working with the HL78xx modem in Zephyr projects. Signed-off-by: Zafer SEN --- .../doc/auto_baudrate/AUTO_BAUDRATE_README.md | 415 ++++++++++++++++++ .../doc/auto_baudrate/QUICK_REFERENCE.md | 320 ++++++++++++++ .../shields/swir_hl78xx_ev_kit/doc/index.rst | 4 + 3 files changed, 739 insertions(+) create mode 100644 boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/AUTO_BAUDRATE_README.md create mode 100644 boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/QUICK_REFERENCE.md diff --git a/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/AUTO_BAUDRATE_README.md b/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/AUTO_BAUDRATE_README.md new file mode 100644 index 0000000000000..4b376b8da3dc0 --- /dev/null +++ b/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/AUTO_BAUDRATE_README.md @@ -0,0 +1,415 @@ +# Copyright (c) 2025 Netfeasa Ltd. +# SPDX-License-Identifier: Apache-2.0 + +# HL78xx Auto Baud Rate Switching + +## Overview + +This feature enables automatic baud rate detection and switching for the Sierra Wireless HL78xx modem driver. The driver can automatically detect the modem's current baud rate and switch to a configured target baud rate using the AT+IPR command. + +## Features + +- **Auto-detection**: Automatically detects the modem's current baud rate by trying a list of common baud rates +- **Dynamic switching**: Changes the modem's baud rate to the configured target using AT+IPR command +- **Configurable**: Supports multiple baud rates from 9600 to 921600 bps +- **Retry mechanism**: Configurable retry count for robust detection +- **State machine integration**: Seamlessly integrated into the modem initialization sequence + +## Configuration + +Enable the feature in your project's `prj.conf`: + +```ini +# Enable auto baud rate detection and switching +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y + +# Set target baud rate (default is 115200) +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y + +# Configure detection baud rates (comma-separated list) +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,9600,57600,38400,19200" + +# Set timeout for each detection attempt (in seconds) +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=4 + +# Set number of retries +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=3 + +# Save baud rate change to modem NVRAM (default: y, recommended) +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y + +# Try target baud rate first before detection list (default: y, faster) +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y + +# Only perform auto-baud if initial communication fails (default: y, efficient) +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y + +# Perform auto-baud immediately at boot, skip KSUP wait (default: n) +CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT=n +``` + +## Supported Baud Rates + +The following baud rates are supported: + +- 9600 bps +- 19200 bps +- 38400 bps +- 57600 bps +- 115200 bps (default) +- 230400 bps +- 460800 bps +- 921600 bps +- 3000000 bps (HL7812 only) + +## How It Works + +### 1. Detection Phase (MODEM_HL78XX_STATE_SET_BAUDRATE) + +When the modem enters the `SET_BAUDRATE` state after power-on: + +1. The driver tries each baud rate from the detection list +2. For each rate, it: + - Configures the UART to that baud rate + - Sends an "AT" command + - Waits for "OK" response +3. Once a response is received, the current baud rate is identified + +### 2. Switching Phase + +If the detected baud rate differs from the target: + +1. Send `AT+IPR=` command at current baud rate +2. Wait for "OK" response +3. Wait 2.5 seconds for modem to apply the change (~2s per AT command guide) +4. Reconfigure the host UART to the new baud rate +5. Wait 50ms for UART stabilization +6. Verify communication by sending "AT" test command +7. Send `AT&W` to save configuration to NVRAM (persists across power cycles) + +**Note:** After baud rate switching completes, the state machine runs the post-restart script to wait for KUSP URC message before proceeding to initialization. + +### 3. State Transitions + +``` +AWAIT_POWER_ON --> SET_BAUDRATE --> RUN_INIT_SCRIPT + | + +--> [On Failure] --> RUN_INIT_FAIL_DIAGNOSTIC_SCRIPT +``` + +## Use Cases + +### Use Case 1: Unknown Modem Baud Rate + +If you're unsure what baud rate the modem is currently using: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,9600,57600,38400,19200" +``` + +The driver will automatically detect and switch to your preferred rate. + +### Use Case 2: High-Speed Communication + +To maximize throughput, configure a high baud rate: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +``` + +### Use Case 3: Low-Power Applications + +For low-power applications where you want to minimize UART activity: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_9600=y +``` + +### Use Case 4: Fast Boot with Known Baud Rate + +If you know the modem is already at your target baud rate and want fastest boot: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=2 # Short timeout +``` + +**Result:** Boot time ~50-100ms if modem is already at target rate! + +### Use Case 5: Production/Field Deployment + +For maximum reliability in unknown environments: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,57600,38400,19200,9600" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=8 # Longer timeout +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=5 +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` + +### Use Case 6: Temporary Baud Rate Change (Non-Persistent) + +For testing or temporary rate changes that revert on modem reboot: + +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=n # Don't save with AT&W +``` + +**Note:** Modem will revert to previous baud rate after power cycle or AT+CFUN reset. + +## AT Commands Used + +### Query Current Baud Rate +``` +AT+IPR? +``` +Response: `+IPR: ` or `+IPR: 0` (auto-baud) + +### Set Fixed Baud Rate +``` +AT+IPR= +``` +Where `` can be: 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 3000000 (HL7812 only) + +**Important:** The new baud rate takes effect after ~2 seconds. Use `AT&W` to save the configuration to non-volatile memory, otherwise it will revert to previous setting on power cycle or phone functionality changed. + +## Troubleshooting + +### Issue: Detection Fails + +**Symptoms**: Modem enters diagnostic state after multiple retries + +**Solutions**: +1. Verify your detection baud rate list includes the modem's current rate +2. Increase timeout: `CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=10` (10 seconds) +3. Check UART wiring and signal quality +4. Verify modem is powered and responsive + + +### Issue: Switching Fails + +**Symptoms**: Detection succeeds but switching to target rate fails + +**Solutions**: +1. Ensure target baud rate is supported by both modem and UART hardware +2. Check for UART clock limitations +3. Try a lower baud rate first +4. Verify modem firmware supports AT+IPR command + +### Issue: Communication Lost After Switch + +**Symptoms**: Modem stops responding after baud rate change, hangs on AT&W command + +**Root Cause**: Trying to send AT&W before reconfiguring host UART causes mismatch (host at old rate, modem at new rate) +**Solutions**: +1. **Critical:** Reconfigure host UART BEFORE sending AT&W command +2. Wait 2.5 seconds after AT+IPR for modem to apply change +3. Wait for KUSP URC message after baud rate switch +4. Check for UART buffer overflow +5. Ensure proper UART flow control if using high baud rates + +### Issue: Communication Fails After Disabling Auto-Baud + +**Symptoms**: Modem doesn't respond after disabling `CONFIG_MODEM_HL78XX_AUTO_BAUDRATE` + +**Root Cause**: Once auto-baud was enabled and used, the modem's baud rate was changed and saved to NVRAM with `AT&W`. When you disable auto-baud, the driver no longer detects/switches, but the modem is still at the target baud rate (e.g., 921600). If your device tree UART is configured for 115200, communication will fail. + +**Solutions**: +1. **Option A:** Keep auto-baud enabled (recommended) +2. **Option B:** Update device tree UART `current-speed` property to match the target baud rate: + ```dts + &uart_modem { + current-speed = <921600>; /* Match your target rate */ + }; + ``` +3. **Option C:** Manually reset modem baud rate using AT commands at the saved rate before disabling auto-baud + +**Note:** There is no Kconfig option to change UART baud rate - it must be configured in the device tree. + +## Implementation Details + +### Key Functions + +```c +/* Try communication at specific baud rate */ +static int hl78xx_try_baudrate(struct hl78xx_data *data, uint32_t baudrate); + +/* Detect current modem baud rate */ +static int hl78xx_detect_current_baudrate(struct hl78xx_data *data); + +/* Switch to target baud rate */ +static int hl78xx_switch_baudrate(struct hl78xx_data *data, uint32_t target_baudrate); +``` + +### State Handler + +```c +/* State entry handler */ +static int hl78xx_on_set_baudrate_state_enter(struct hl78xx_data *data); + +/* State event handler */ +static void hl78xx_set_baudrate_event_handler(struct hl78xx_data *data, enum hl78xx_event evt); +``` + +### Data Structure + +```c +struct uart_status { +#ifdef CONFIG_MODEM_HL78XX_AUTO_BAUDRATE + uint32_t current_baudrate; + uint32_t target_baudrate; + uint8_t baudrate_detection_retry; +#endif +}; +``` + +## Advanced Configuration Options + +### CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT + +**Default:** `y` (recommended) + +Controls whether the baud rate change is saved to modem's NVRAM using AT&W command. + +- **Enabled (y):** Baud rate persists across power cycles and reboots +- **Disabled (n):** Baud rate reverts to previous setting on modem reset + +**Recommendation:** Always enable in production. This allows detection of unexpected modem reboots and quick recovery since the modem remembers the configured rate. + +### CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE + +**Default:** `y` (recommended) + +When enabled, the driver first attempts communication at the configured target baud rate before trying the detection list. + +**Benefits:** +- Significantly faster boot when modem is already at target rate (~50ms vs several seconds) +- Reduces UART traffic and power consumption +- Works well with `AUTOBAUD_ONLY_IF_COMMS_FAIL` + +**When to disable:** If you frequently switch between different baud rates and want comprehensive detection every boot. + +### CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL + +**Default:** `y` (recommended) + +Only performs auto baud rate detection if initial UART communication with the modem fails. + +**How it works:** +1. Driver attempts normal initialization at target baud rate +2. If modem responds correctly → skip auto-baud detection entirely +3. If communication fails → trigger full auto-baud detection + +**Benefits:** +- Minimal boot time impact when modem is already configured +- Automatic recovery from baud rate mismatches +- Best of both worlds: fast boot + robust recovery + +**When to disable:** If you want to force detection every boot regardless of communication success. + +### CONFIG_MODEM_HL78XX_AUTOBAUD_AT_BOOT + +**Default:** `n` + +Performs auto baud rate detection immediately as soon as the modem is powered up, without waiting for the KSUP URC (startup ready indication). + +**Benefits:** +- Fastest possible modem initialization +- Useful for time-critical applications + +**Warnings:** +- Skips waiting for modem's normal boot sequence +- May attempt communication before modem is fully ready +- Can interfere with modem's internal startup process +- **Use only if you understand the modem's boot behavior** + +**When to enable:** Ultra-fast boot requirements where you control the exact timing of modem power-up. + +## Optimization Strategies + +### Strategy 1: Known Environment (Fastest) +```ini +# Modem is already at target rate, just verify and move on +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=1 # Very short +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200" # Just target rate +``` +**Boot impact:** ~50-100ms + +### Strategy 2: Unknown Environment (Balanced) +```ini +# Detect efficiently, fall back to comprehensive search if needed +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=4 +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,57600,9600" +``` +**Boot impact:** ~50ms (best case) to ~12s (worst case) + +### Strategy 3: Maximum Reliability (Production) +```ini +# Comprehensive detection with diagnostic fallback +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=8 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=5 +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,57600,38400,19200,9600" +``` +**Boot impact:** ~50ms (best case) to ~40s (worst case with retries) + +## Performance Considerations + +### Detection Time + +With default settings (5 baud rates @ 4 seconds timeout): +- Best case: ~50ms (target rate succeeds via `START_WITH_TARGET_BAUDRATE`) +- Worst case: ~20s (all rates tried) +- Average: ~10s +- With `ONLY_IF_COMMS_FAIL`: ~50ms in normal operation, falls back to detection only on failure + +### Optimization Tips + +1. **Order detection list by likelihood**: Put most common baud rates first +2. **Enable smart detection**: Use `START_WITH_TARGET_BAUDRATE=y` and `ONLY_IF_COMMS_FAIL=y` +3. **Reduce timeout**: If your system is fast and reliable, use shorter timeout (e.g., 2000ms) +4. **Limit detection list**: Only include rates you actually use +5. **Use persistent mode**: Enable `AUTOBAUD_CHANGE_PERSISTENT=y` to avoid re-detection after modem reboots + +## Future Enhancements + +Potential improvements for this feature: + +1. **Persistent storage**: Save detected/configured baud rate to avoid re-detection +2. **Dynamic adjustment**: Adjust baud rate based on requirement or link quality +3. **Statistics**: Track detection attempts and success rates +4. **Shell commands**: Runtime baud rate query and adjustment + +## References + +- Sierra Wireless HL78xx AT Command Reference +- HL78xx Product Technical Specification +- Zephyr UART Driver API Documentation +- Zephyr Modem API Documentation + +## License + +Copyright (c) 2025 Netfeasa Ltd. +SPDX-License-Identifier: Apache-2.0 +--- +**Last Updated:** 2025-12-06 \ No newline at end of file diff --git a/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/QUICK_REFERENCE.md b/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/QUICK_REFERENCE.md new file mode 100644 index 0000000000000..32fe0ea6a0d2c --- /dev/null +++ b/boards/shields/swir_hl78xx_ev_kit/doc/auto_baudrate/QUICK_REFERENCE.md @@ -0,0 +1,320 @@ +# Copyright (c) 2025 Netfeasa Ltd. +# SPDX-License-Identifier: Apache-2.0 + +# HL78xx Auto Baud Rate - Quick Reference + +## Enable Feature +```ini +# In prj.conf +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y # Your target rate +``` + +## Common Configurations + +### Preset 1: Smart Default (Recommended) +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="921600,9600,57600,38400,115200" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=4 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=3 +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` +✅ **Use when:** General purpose, handles both known and unknown baud rates efficiently +⏱️ **Boot time impact:** ~50-100ms (if already at target), ~4-20s (if detection needed) +💡 **Why smart:** Only runs full detection if initial communication fails + +### Preset 2: Ultra-Fast Boot (Known Rate) +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="921600" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=1 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=1 +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` +✅ **Use when:** Known initial baud rate, minimal boot time required +⏱️ **Boot time impact:** ~50-100ms +⚠️ **Warning:** May fail if modem is at different rate + +### Preset 3: High Speed +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="921600,460800,230400,115200" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=3 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=3 +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` +✅ **Use when:** High throughput required +⏱️ **Boot time impact:** ~50ms (best), ~3-12s (worst) +⚠️ **Note:** Ensure UART hardware supports high speeds + +### Preset 4: Robust Production +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_DETECTION_BAUDRATES="115200,57600,38400,19200,9600,921600" +CONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=8 +CONFIG_MODEM_HL78XX_AUTOBAUD_RETRY_COUNT=5 +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` +✅ **Use when:** Field deployment, maximum reliability needed +⏱️ **Boot time impact:** ~50ms (best), ~40s (worst with retries) +💡 **Features:** Diagnostic fallback, comprehensive rate coverage + + +### Preset 5: Testing/Development (Non-Persistent) +```ini +CONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y +CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y +CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=n # Don't save with AT&W +CONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y +CONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y +``` +✅ **Use when:** Testing different baud rates temporarily +💡 **Note:** Modem reverts to previous rate after power cycle + +## Supported Baud Rates +| Rate | Kconfig Option | Use Case | +|---------|-------------------------------------|-----------------------| +| 9600 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_9600` | Legacy, low-power | +| 19200 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_19200` | Legacy | +| 38400 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_38400` | Standard | +| 57600 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_57600` | Standard | +| 115200 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600` | Default (recommended) | +| 230400 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_230400` | High speed | +| 460800 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_460800` | High speed | +| 921600 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600` | Very high speed | +| 3000000 | `CONFIG_MODEM_HL78XX_TARGET_BAUDRATE_3000000` | Maximum (HL7812 only) | + +## State Flow + +``` +Power ON + ↓ +[START_WITH_TARGET=y?] → Try target first → [AUTOBAUD_AT_BOOT=y?] → Immediate Detection + ↓ ↓ +Wait KSUP → [ONLY_IF_COMMS_FAIL=y?] → Try Target Rate First + ↓ ↓ +Post-Restart → Communication Success? → Skip Detection (Fast!) + ↓ ↓ + | Communication Fails + | ↓ + +----------→ Detect Baud Rate (tries each rate in list) + ↓ + Rate Detected? → Switch to Target (AT+IPR) + ↓ ↓ + Retry [CHANGE_PERSISTENT=y?] + ↓ ↓ + Max Retries? → Yes → AT&W (Save to NVRAM) + ↓ ↓ + Diagnostic State Initialize Modem + ↓ ↓ + [DIAGNOSING_FIRST=y?] Normal Operation + ↓ + Try Auto-Baud Again +``` + +## Log Messages + +### Success - Smart Default (No Detection Needed) +``` +[hl78xx] Checking if modem is ready at target baud rate 921600... +[hl78xx] Modem ready at target rate, skipping detection +[hl78xx] Baud rate switch not needed +``` + +### Detection Triggered (Communication Failed) +``` +[hl78xx] Modem not responding at target rate 921600, starting detection... +[hl78xx] Attempting recovery from diagnostic state... +[hl78xx] Trying AT+KSREP? and Failing +[hl78xx] Trying baud rate: 921600 +[hl78xx] Trying baud rate: 9600 +[hl78xx] Modem responded at 9600 baud +[hl78xx] Switching baud rate from 921600 to 9600 +[hl78xx] Saving persistent baud rate with AT&W... +[hl78xx] Successfully switched to baud rate 9600 +``` + +### Non-Persistent Mode +``` +[hl78xx] Modem responded at 9600 baud +[hl78xx] Switching baud rate from 9600 to 921600 +[hl78xx] Non-persistent mode: skipping AT&W +[hl78xx] Baud rate changed for this session only +``` + +### Failure +``` +[hl78xx] Starting baud rate detection... +[hl78xx] Trying baud rate: 921600 +[hl78xx] Trying baud rate: 9600 +[hl78xx] Failed to detect modem baud rate +[hl78xx] Retrying baud rate detection (attempt 2/3) +[hl78xx] Max retries reached, consider increasing timeout or adding more rates +``` + +## Troubleshooting + +| Symptom | Likely Cause | Solution | +|---------|--------------|----------| +| "Failed to detect modem baud rate" | Detection list doesn't include actual rate | Add more rates to `AUTOBAUD_DETECTION_BAUDRATES` | +| Times out on each rate | Modem not ready/responding | Increase `AUTOBAUD_TIMEOUT` (in **seconds**) or startup delay | +| Hangs on AT&W command | Sending AT&W before UART reconfig | **Bug fixed**: UART now reconfigured before AT&W | +| Detects but switch fails | AT+IPR not supported | Check modem firmware version | +| Communication lost after switch | UART hardware limitation | Try lower baud rate | +| Fails after disabling auto-baud | Modem at target rate, UART at default | Update device tree `current-speed` to match target rate | +| Multiple retries, then success | Timing/noise issues | Increase retry count and timeout | +| Fast boot not working | Wrong config combination | Enable both `START_WITH_TARGET_BAUDRATE=y` AND `ONLY_IF_COMMS_FAIL=y` | +| Detection runs every boot | `ONLY_IF_COMMS_FAIL` disabled | Enable it for smart detection | +| Rate doesn't persist | `CHANGE_PERSISTENT` disabled | Enable it: `CONFIG_MODEM_HL78XX_AUTOBAUD_CHANGE_PERSISTENT=y` | +| Boot hangs waiting for KSUP | Normal KSUP wait too long | Consider `AUTOBAUD_AT_BOOT=y` (advanced users only!) | + +## Configuration Decision Tree + +``` +Start Here + │ + ├─→ Do you know the modem's current baud rate? + │ │ + │ ├─→ YES, it's at my target rate already + │ │ └─→ Use Preset 2 ( Ultra-Fast Boot (Known Rate)) + │ │ Boot: ~50-100ms + │ │ + │ └─→ NO, or it varies + │ └─→ Continue below + │ + ├─→ Is boot time critical (<200ms)? + │ │ + │ ├─→ YES → Use Preset 5 (Skip KSUP) + │ │ WARNING: Advanced users only! + │ │ + │ └─→ NO → Continue below + │ + ├─→ Is this for production/field deployment? + │ │ + │ ├─→ YES → Use Preset 4 (Robust Production) + │ │ Comprehensive coverage, diagnostic fallback + │ │ + │ └─→ NO → Continue below + │ + ├─→ Do you need high-speed communication (>115200)? + │ │ + │ ├─→ YES → Use Preset 3 (High Speed) + │ │ Set target to 921600 or 460800 + │ │ + │ └─→ NO → Use Preset 1 (Smart Default) + │ Best balance of speed and reliability + │ + └─→ Special Cases: + ├─→ Testing different rates → Preset 6 (Non-Persistent) + └─→ Unknown environment → Preset 1 or 4 +``` + +## AT Commands Reference + +```bash +# Query current baud rate +AT+IPR? +# Response: +IPR: 115200 + +# Set baud rate to 115200 +AT+IPR=115200 +# Response: OK +# Note: New rate takes effect after ~2 seconds + +# Save configuration to NVRAM (required for persistence) +AT&W +# Response: OK +# Note: Without this, baud rate reverts on power cycle +``` + +## API Functions (Internal) + +```c +/* Try communication at specific baud rate */ +int hl78xx_try_baudrate(struct hl78xx_data *data, uint32_t baudrate); + +/* Detect current baud rate from list */ +int hl78xx_detect_current_baudrate(struct hl78xx_data *data); + +/* Switch to target baud rate */ +int hl78xx_switch_baudrate(struct hl78xx_data *data, uint32_t target_baudrate); +``` + +## Shell Commands (Future) +```bash +# Manually trigger detection +modem autobaud detect + +# Show current rate +modem autobaud status + +# Set new rate +modem autobaud set 115200 +``` +*(Not yet implemented)* + +## Performance Tips + +1. **Enable smart defaults:** Set `ONLY_IF_COMMS_FAIL=y` and `START_WITH_TARGET_BAUDRATE=y` for optimal boot times +2. **Order matters:** Put most likely rate first in detection list +3. **Adjust timeout wisely:** Shorter timeouts (1-2 seconds) for known environments, longer (5-8 seconds) for robust detection +4. **Limit detection list:** Only include rates you actually need to minimize detection time +5. **Consider AUTOBAUD_AT_BOOT:** For ultra-fast boot (<200ms) but understand the risks (modem might not be ready) +6. **Enable persistence:** With `CHANGE_PERSISTENT=y`, rate is saved and detection runs only once +7. **Diagnostic fallback:** Enable `AUTOBAUD_DIAGNOSING_FIRST=y` to recover from baud rate mismatches automatically + +## Compatibility + +- ✅ HL7812 (all firmware versions) +- ✅ HL7800 (all firmware versions) +- ✅ Works with Zephyr 4.4 and newer +- ✅ Compatible with all supported boards +- ✅ Smart flags reduce typical boot time from 20s to 50-100ms + +## When NOT to Use + +- ❌ Baud rate is fixed and known AND device tree matches (adds boot overhead) + * But consider using with `ONLY_IF_COMMS_FAIL=y` for safety (minimal overhead) +- ❌ Ultra-fast boot required (<50ms total) - even smart defaults take ~50-100ms +- ❌ Memory-constrained systems (<2KB code space available) +- ❌ Using modem's hardware auto-baud feature (not applicable to HL78xx) + +## Build Example + +```bash +# Create new build with smart default auto-baud +west build -b pinnacle_100_dvk -p -- \ + -DCONFIG_MODEM_HL78XX_AUTO_BAUDRATE=y \ + -DCONFIG_MODEM_HL78XX_TARGET_BAUDRATE_921600=y \ + -DCONFIG_MODEM_HL78XX_AUTOBAUD_ONLY_IF_COMMS_FAIL=y \ + -DCONFIG_MODEM_HL78XX_AUTOBAUD_START_WITH_TARGET_BAUDRATE=y \ + -DCONFIG_MODEM_HL78XX_AUTOBAUD_TIMEOUT=3 + +# Flash to board +west flash + +``` + +## Support + +For issues or questions: +1. Check `AUTO_BAUDRATE_README.md` for detailed documentation +2. Review `IMPLEMENTATION_SUMMARY.md` for technical details +3. Enable verbose logging: `CONFIG_MODEM_HL78XX_LOG_CONTEXT_VERBOSE_DEBUG=y` +4. Check Zephyr modem driver documentation +5. Review troubleshooting table above for common issues + +--- +**Last Updated:** 2025-12-06 diff --git a/boards/shields/swir_hl78xx_ev_kit/doc/index.rst b/boards/shields/swir_hl78xx_ev_kit/doc/index.rst index cc6a9ce761f67..b388082756669 100644 --- a/boards/shields/swir_hl78xx_ev_kit/doc/index.rst +++ b/boards/shields/swir_hl78xx_ev_kit/doc/index.rst @@ -77,3 +77,7 @@ References .. _HL/RC Module Evaluation Kit Shield specification website: https://info.sierrawireless.com/iot-modules-evaluation-kit#guide-for-the-hl78-series-evaluation-kit + +.. _HL/RC Module Evaluation Kit Shield Auto Baud Rate Detection Feature Documentation: + :doc:`auto_baudrate/AUTO_BAUDRATE_README.md` + :doc:`auto_baudrate/QUICK_REFERENCE.md`