drivers: modem: Add support for quectel bg95

Adding support for Quectel BG95 Modem offloaded driver
to zephyr.

The driver currently implements only the
client side functions of the "socket_op_vtable", and
so cannot be used for cases where Zephyr acts as a
server. Moreover the driver only supports TCP for now.

Looking through the guides, the same driver should be
usable for BG96 (and other modems) except for the modem
boot-up sequence. Hence its named as "bg9x" instead of
"bg95".

Tested extensively with Zephyr acting as MQTT endpoint
and publishing / subscribing data to / from an MQTT
broker.

Signed-off-by: Bilal Wasim <bilalwasim676@gmail.com>
This commit is contained in:
Bilal Wasim 2020-11-23 19:54:31 +05:00 committed by Anas Nashif
commit 503a70a40a
9 changed files with 1435 additions and 0 deletions

View file

@ -17,6 +17,11 @@ if(CONFIG_MODEM_UBLOX_SARA)
zephyr_library_sources(ublox-sara-r4.c)
endif()
if(CONFIG_MODEM_QUECTEL_BG9X)
zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
zephyr_library_sources(quectel-bg9x.c)
endif()
if(CONFIG_MODEM_WNCM14A2A)
zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
zephyr_library_sources(wncm14a2a.c)

View file

@ -134,6 +134,7 @@ config MODEM_SIM_NUMBERS
source "drivers/modem/Kconfig.ublox-sara-r4"
source "drivers/modem/Kconfig.quectel-bg9x"
source "drivers/modem/Kconfig.wncm14a2a"
source "drivers/modem/Kconfig.gsm"

View file

@ -0,0 +1,63 @@
# Quectel BG9x driver options
# Copyright (c) 2020 Analog Life LLC
# SPDX-License-Identifier: Apache-2.0
config MODEM_QUECTEL_BG9X
bool "Enable quectel modem driver"
select MODEM_CONTEXT
select MODEM_CMD_HANDLER
select MODEM_IFACE_UART
select MODEM_SOCKET
select NET_SOCKETS_OFFLOAD
imply GPIO
help
Choose this setting to enable quectel BG9x LTE-CatM1/NB-IoT modem
driver.
config MODEM_QUECTEL_BG9X_RX_STACK_SIZE
int "Stack size for the quectel BG9X modem driver RX thread"
default 1028
help
This stack is used by the quectel BG9X RX thread.
config MODEM_QUECTEL_BG9X_RX_WORKQ_STACK_SIZE
int "Stack size for the quectel BG9X modem driver work queue"
default 2048
help
This stack is used by the work queue to pass off net_pkt data
to the rest of the network stack, letting the rx thread continue
processing data.
config MODEM_QUECTEL_BG9X_APN
string "APN for establishing network connection"
default "internet"
help
This setting is used to set the APN name for the network connection
context. This value is specific to the network provider and may
need to be changed.
config MODEM_QUECTEL_BG9X_USERNAME
string "Username for establishing network connection"
default ""
help
This setting is used to set the User name for the network connection
context. This value is specific to the network provider and may
need to be changed.
config MODEM_QUECTEL_BG9X_PASSWORD
string "Password for establishing network connection"
default ""
help
This setting is used to set the Password for the network connection
context. This value is specific to the network provider and may
need to be changed.
config MODEM_QUECTEL_BG9X_INIT_PRIORITY
int "quectel BG9X driver init priority"
default 80
help
quectel BG9X device driver initialization priority.
Do not mess with it unless you know what you are doing.
Note that the priority needs to be lower than the net stack
so that it can start before the networking sub-system.

1182
drivers/modem/quectel-bg9x.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2020 Analog Life LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef QUECTEL_BG9X_H
#define QUECTEL_BG9X_H
#include <kernel.h>
#include <ctype.h>
#include <errno.h>
#include <zephyr.h>
#include <drivers/gpio.h>
#include <device.h>
#include <init.h>
#include <net/net_if.h>
#include <net/net_offload.h>
#include <net/socket_offload.h>
#include "modem_context.h"
#include "modem_socket.h"
#include "modem_cmd_handler.h"
#include "modem_iface_uart.h"
#define MDM_UART_DEV_NAME DT_INST_BUS_LABEL(0)
#define MDM_CMD_TIMEOUT K_SECONDS(10)
#define MDM_CMD_CONN_TIMEOUT K_SECONDS(120)
#define MDM_REGISTRATION_TIMEOUT K_SECONDS(180)
#define MDM_SENDMSG_SLEEP K_MSEC(1)
#define MDM_MAX_DATA_LENGTH 1024
#define MDM_RECV_MAX_BUF 30
#define MDM_RECV_BUF_SIZE 1024
#define MDM_MAX_SOCKETS 5
#define MDM_BASE_SOCKET_NUM 0
#define MDM_NETWORK_RETRY_COUNT 10
#define MDM_INIT_RETRY_COUNT 10
#define MDM_WAIT_FOR_RSSI_COUNT 10
#define MDM_WAIT_FOR_RSSI_DELAY K_SECONDS(2)
#define BUF_ALLOC_TIMEOUT K_SECONDS(1)
#define MDM_MAX_AT_RETRIES 50
/* Default lengths of certain things. */
#define MDM_MANUFACTURER_LENGTH 10
#define MDM_MODEL_LENGTH 16
#define MDM_REVISION_LENGTH 64
#define MDM_IMEI_LENGTH 16
#define MDM_IMSI_LENGTH 16
#define MDM_ICCID_LENGTH 32
#define MDM_APN_LENGTH 32
#define RSSI_TIMEOUT_SECS 30
#define MDM_APN CONFIG_MODEM_QUECTEL_BG9X_APN
#define MDM_USERNAME CONFIG_MODEM_QUECTEL_BG9X_USERNAME
#define MDM_PASSWORD CONFIG_MODEM_QUECTEL_BG9X_PASSWORD
/* Modem ATOI routine. */
#define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__)
/* pin settings */
enum mdm_control_pins {
MDM_POWER = 0,
MDM_RESET,
#if DT_INST_NODE_HAS_PROP(0, mdm_dtr_gpios)
MDM_DTR,
#endif
};
/* driver data */
struct modem_data {
struct net_if *net_iface;
uint8_t mac_addr[6];
/* modem interface */
struct modem_iface_uart_data iface_data;
uint8_t iface_rb_buf[MDM_MAX_DATA_LENGTH];
/* modem cmds */
struct modem_cmd_handler_data cmd_handler_data;
uint8_t cmd_match_buf[MDM_RECV_BUF_SIZE + 1];
/* socket data */
struct modem_socket_config socket_config;
struct modem_socket sockets[MDM_MAX_SOCKETS];
/* RSSI work */
struct k_delayed_work rssi_query_work;
/* modem data */
char mdm_manufacturer[MDM_MANUFACTURER_LENGTH];
char mdm_model[MDM_MODEL_LENGTH];
char mdm_revision[MDM_REVISION_LENGTH];
char mdm_imei[MDM_IMEI_LENGTH];
#if defined(CONFIG_MODEM_SIM_NUMBERS)
char mdm_imsi[MDM_IMSI_LENGTH];
char mdm_iccid[MDM_ICCID_LENGTH];
#endif /* #if defined(CONFIG_MODEM_SIM_NUMBERS) */
/* bytes written to socket in last transaction */
int sock_written;
/* Socket from which we are currently reading data. */
int sock_fd;
/* Semaphore(s) */
struct k_sem sem_response;
struct k_sem sem_tx_ready;
struct k_sem sem_sock_conn;
};
/* Socket read callback data */
struct socket_read_data {
char *recv_buf;
size_t recv_buf_len;
struct sockaddr *recv_addr;
uint16_t recv_read_len;
};
/* Modem pins - Power, Reset & others. */
static struct modem_pin modem_pins[] = {
/* MDM_POWER */
MODEM_PIN(DT_INST_GPIO_LABEL(0, mdm_power_gpios),
DT_INST_GPIO_PIN(0, mdm_power_gpios),
DT_INST_GPIO_FLAGS(0, mdm_power_gpios) | GPIO_OUTPUT_LOW),
/* MDM_RESET */
MODEM_PIN(DT_INST_GPIO_LABEL(0, mdm_reset_gpios),
DT_INST_GPIO_PIN(0, mdm_reset_gpios),
DT_INST_GPIO_FLAGS(0, mdm_reset_gpios) | GPIO_OUTPUT_LOW),
#if DT_INST_NODE_HAS_PROP(0, mdm_dtr_gpios)
/* MDM_DTR */
MODEM_PIN(DT_INST_GPIO_LABEL(0, mdm_dtr_gpios),
DT_INST_GPIO_PIN(0, mdm_dtr_gpios),
DT_INST_GPIO_FLAGS(0, mdm_dtr_gpios) | GPIO_OUTPUT_LOW),
#endif
};
#endif /* #ifndef QUECTEL_BG9X_H */

View file

@ -0,0 +1,24 @@
# Copyright (c) 2020 Analog Life LLC
# SPDX-License-Identifier: Apache-2.0
description: quectel BG9x modem
compatible: "quectel,bg9x"
include: uart-device.yaml
properties:
label:
required: true
mdm-power-gpios:
type: phandle-array
required: true
mdm-reset-gpios:
type: phandle-array
required: true
mdm-dtr-gpios:
type: phandle-array
required: false

View file

@ -0,0 +1,7 @@
CONFIG_TEST=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_MODEM=y
CONFIG_MODEM_QUECTEL_BG9X=y
CONFIG_MODEM_QUECTEL_BG9X_APN="hologram"

View file

@ -94,6 +94,11 @@ tests:
extra_args: CONF_FILE=modem_ublox_sara.conf
platform_exclude: serpente pinnacle_100_dvk
tags: drivers
drivers.modem.quectel_bg9x.build:
build_only: true
extra_args: CONF_FILE=modem_quectel_bg9x.conf
platform_exclude: serpente pinnacle_100_dvk
tags: drivers
drivers.xlnx.build:
build_only: true
extra_args: CONF_FILE=xlnx.conf

View file

@ -37,3 +37,11 @@ test_sara_r4: sara_r4 {
mdm-power-gpios = <&test_gpio 0 0>;
mdm-reset-gpios = <&test_gpio 0 0>;
};
test_quectel_bg9x: quectel_bg9x {
compatible = "quectel,bg9x";
label = "quectel,bg9x";
mdm-power-gpios = <&test_gpio 0 0>;
mdm-reset-gpios = <&test_gpio 0 0>;
};