Browse Source

modem_cellular: Add support for the simcom a76xx modem

Add support for the simcom a76xx modem which is similar to the simcom 7080
but has a few key differences. Tested with a simcom A7672SA module but as
there is a single simcom A76XX AT commands manual, the driver should work
with other modems of the series.

Signed-off-by: Olivier Lalonde <o@syskall.com>
pull/90752/head
Olivier Lalonde 2 months ago committed by Benjamin Cabé
parent
commit
afc481ab31
  1. 2
      drivers/modem/Kconfig.cellular
  2. 88
      drivers/modem/modem_cellular.c
  3. 13
      dts/bindings/modem/simcom,a76xx.yaml
  4. 12
      samples/net/cellular_modem/Kconfig
  5. 13
      samples/net/cellular_modem/README.rst
  6. 1
      samples/net/cellular_modem/prj.conf
  7. 2
      samples/net/cellular_modem/src/main.c
  8. 3
      subsys/modem/Kconfig

2
drivers/modem/Kconfig.cellular

@ -14,7 +14,7 @@ config MODEM_CELLULAR
select NET_L2_PPP_OPTION_MRU select NET_L2_PPP_OPTION_MRU
select NET_L2_PPP_PAP select NET_L2_PPP_PAP
select NET_L2_PPP_MGMT select NET_L2_PPP_MGMT
depends on (DT_HAS_QUECTEL_BG95_ENABLED || \ depends on (DT_HAS_QUECTEL_BG95_ENABLED || DT_HAS_SIMCOM_A76XX_ENABLED || \
DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \
DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \ DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \
DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \ DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \

88
drivers/modem/modem_cellular.c

@ -525,8 +525,10 @@ MODEM_CHAT_MATCHES_DEFINE(dial_abort_matches,
MODEM_CHAT_MATCH("NO CARRIER", "", NULL), MODEM_CHAT_MATCH("NO CARRIER", "", NULL),
MODEM_CHAT_MATCH("NO DIALTONE", "", NULL)); MODEM_CHAT_MATCH("NO DIALTONE", "", NULL));
#if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) || DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s) || \ #if DT_HAS_COMPAT_STATUS_OKAY(swir_hl7800) || \
DT_HAS_COMPAT_STATUS_OKAY(quectel_eg800q) DT_HAS_COMPAT_STATUS_OKAY(sqn_gm02s) || \
DT_HAS_COMPAT_STATUS_OKAY(quectel_eg800q) || \
DT_HAS_COMPAT_STATUS_OKAY(simcom_a76xx)
MODEM_CHAT_MATCH_DEFINE(connect_match, "CONNECT", "", NULL); MODEM_CHAT_MATCH_DEFINE(connect_match, "CONNECT", "", NULL);
#endif #endif
@ -2116,6 +2118,64 @@ MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_periodic_chat_script,
modem_cellular_chat_callback_handler, 4); modem_cellular_chat_callback_handler, 4);
#endif #endif
#if DT_HAS_COMPAT_STATUS_OKAY(simcom_a76xx)
MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_a76xx_init_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
/* Power on the GNSS module.
* We need to do this early, otherwise it does not work when
* doing it later (e.g. from a user pipe).
*/
MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGNSSPWR=1", allow_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
MODEM_CHAT_SCRIPT_DEFINE(simcom_a76xx_init_chat_script, simcom_a76xx_init_chat_script_cmds,
abort_matches, modem_cellular_chat_callback_handler, 10);
MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_a76xx_dial_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\","
"\""CONFIG_MODEM_CELLULAR_APN"\"",
ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("ATD*99***1#", connect_match),);
MODEM_CHAT_SCRIPT_DEFINE(simcom_a76xx_dial_chat_script, simcom_a76xx_dial_chat_script_cmds,
dial_abort_matches, modem_cellular_chat_callback_handler, 10);
MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_a76xx_periodic_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
MODEM_CHAT_SCRIPT_DEFINE(simcom_a76xx_periodic_chat_script,
simcom_a76xx_periodic_chat_script_cmds, abort_matches,
modem_cellular_chat_callback_handler, 4);
MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_a76xx_shutdown_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CPOF", ok_match));
MODEM_CHAT_SCRIPT_DEFINE(simcom_a76xx_shutdown_chat_script,
simcom_a76xx_shutdown_chat_script_cmds, abort_matches,
modem_cellular_chat_callback_handler, 15);
#endif
#if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r4) #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_sara_r4)
MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r4_init_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100),
@ -2638,6 +2698,26 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
&simcom_sim7080_dial_chat_script, \ &simcom_sim7080_dial_chat_script, \
&simcom_sim7080_periodic_chat_script, NULL) &simcom_sim7080_periodic_chat_script, NULL)
#define MODEM_CELLULAR_DEVICE_SIMCOM_A76XX(inst) \
MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
\
static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
.chat_delimiter = "\r", \
.chat_filter = "\n", \
.ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
}; \
\
MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
(user_pipe_0, 3), \
(user_pipe_1, 4)) \
\
MODEM_CELLULAR_DEFINE_INSTANCE(inst, 500, 100, 20000, 5000, false, \
NULL, \
&simcom_a76xx_init_chat_script, \
&simcom_a76xx_dial_chat_script, \
&simcom_a76xx_periodic_chat_script, \
&simcom_a76xx_shutdown_chat_script)
#define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4(inst) \ #define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4(inst) \
MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
\ \
@ -2805,6 +2885,10 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_EG800Q)
DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080) DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080)
#undef DT_DRV_COMPAT #undef DT_DRV_COMPAT
#define DT_DRV_COMPAT simcom_a76xx
DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_A76XX)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT u_blox_sara_r4 #define DT_DRV_COMPAT u_blox_sara_r4
DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4) DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4)
#undef DT_DRV_COMPAT #undef DT_DRV_COMPAT

13
dts/bindings/modem/simcom,a76xx.yaml

@ -0,0 +1,13 @@
# Copyright (C) 2025 Olivier Lalonde
# SPDX-License-Identifier: Apache-2.0
description: Simcom A76XX modem
compatible: "simcom,a76xx"
include: uart-device.yaml
properties:
mdm-power-gpios:
type: phandle-array
required: true

12
samples/net/cellular_modem/Kconfig

@ -0,0 +1,12 @@
# Copyright (c) 2025 Olivier Lalonde
# SPDX-License-Identifier: Apache-2.0
# Configuration options for cellular modem sample
mainmenu "Cellular modem sample application"
config SAMPLE_CELLULAR_MODEM_ENDPOINT_HOSTNAME
string "Endpoint hostname"
default "test-endpoint.com"
source "Kconfig.zephyr"

13
samples/net/cellular_modem/README.rst

@ -55,3 +55,16 @@ Next, the UART API must be specified using ``CONFIG_UART_INTERRUPT_DRIVEN=y`` or
``CONFIG_UART_ASYNC_API=y``. The driver doesn't support UART polling. ``CONFIG_UART_ASYNC_API=y``. The driver doesn't support UART polling.
Lastly, the APN must be configured using ``CONFIG_MODEM_CELLULAR_APN=""``. Lastly, the APN must be configured using ``CONFIG_MODEM_CELLULAR_APN=""``.
Server setup
************
Deploy the server on a publicly accessible host, then set the
:kconfig:option:`CONFIG_SAMPLE_CELLULAR_MODEM_ENDPOINT_HOSTNAME` variable in ``prj.conf`` to the
server's hostname.
.. code-block:: shell
git clone --depth=1 https://github.com/zephyrproject-rtos/zephyr.git
cd zephyr/samples/net/cellular_modem/server
python te.py

1
samples/net/cellular_modem/prj.conf

@ -1,6 +1,5 @@
# Copyright (c) 2023 Bjarki Arge Andreasen # Copyright (c) 2023 Bjarki Arge Andreasen
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
CONFIG_POSIX_API=y CONFIG_POSIX_API=y
# Networking # Networking

2
samples/net/cellular_modem/src/main.c

@ -15,7 +15,7 @@
#include <zephyr/drivers/cellular.h> #include <zephyr/drivers/cellular.h>
#define SAMPLE_TEST_ENDPOINT_HOSTNAME ("test-endpoint.com") #define SAMPLE_TEST_ENDPOINT_HOSTNAME CONFIG_SAMPLE_CELLULAR_MODEM_ENDPOINT_HOSTNAME
#define SAMPLE_TEST_ENDPOINT_UDP_ECHO_PORT (7780) #define SAMPLE_TEST_ENDPOINT_UDP_ECHO_PORT (7780)
#define SAMPLE_TEST_ENDPOINT_UDP_RECEIVE_PORT (7781) #define SAMPLE_TEST_ENDPOINT_UDP_RECEIVE_PORT (7781)
#define SAMPLE_TEST_PACKET_SIZE (1024) #define SAMPLE_TEST_PACKET_SIZE (1024)

3
subsys/modem/Kconfig

@ -35,7 +35,8 @@ config MODEM_CMUX_DEFAULT_MTU_127
DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \
DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \ DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \
DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \ DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_TELIT_ME310G1_ENABLED || \
DT_HAS_SQN_GM02S_ENABLED || DT_HAS_QUECTEL_EG800Q_ENABLED) DT_HAS_SQN_GM02S_ENABLED || DT_HAS_QUECTEL_EG800Q_ENABLED || \
DT_HAS_SIMCOM_A76XX_ENABLED)
help help
Use the default MTU size of 127 bytes for the CMUX module on certain modems. Use the default MTU size of 127 bytes for the CMUX module on certain modems.
This must match the AT+CMUX commands in the modem_cellular driver. This must match the AT+CMUX commands in the modem_cellular driver.

Loading…
Cancel
Save