diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index d81b215facc..35c023e72e4 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -218,3 +218,11 @@ if(CONFIG_ZBUS) zephyr_iterable_section(NAME zbus_channel KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) zephyr_iterable_section(NAME zbus_channel_observation KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) endif() + +if(CONFIG_GNSS) + zephyr_iterable_section(NAME gnss_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() + +if(CONFIG_GNSS_SATELLITES) + zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index e9a1603f8cc..b7fcdbed373 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory_ifdef(CONFIG_ESPI espi) add_subdirectory_ifdef(CONFIG_FLASH flash) add_subdirectory_ifdef(CONFIG_FPGA fpga) add_subdirectory_ifdef(CONFIG_FUEL_GAUGE fuel_gauge) +add_subdirectory_ifdef(CONFIG_GNSS gnss) add_subdirectory_ifdef(CONFIG_GPIO gpio) add_subdirectory_ifdef(CONFIG_HWINFO hwinfo) add_subdirectory_ifdef(CONFIG_I2C i2c) diff --git a/drivers/Kconfig b/drivers/Kconfig index f486badbb38..1eca764fce2 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -31,6 +31,7 @@ source "drivers/ethernet/Kconfig" source "drivers/flash/Kconfig" source "drivers/fpga/Kconfig" source "drivers/fuel_gauge/Kconfig" +source "drivers/gnss/Kconfig" source "drivers/gpio/Kconfig" source "drivers/hwinfo/Kconfig" source "drivers/i2c/Kconfig" diff --git a/drivers/gnss/CMakeLists.txt b/drivers/gnss/CMakeLists.txt new file mode 100644 index 00000000000..71a4d9d4831 --- /dev/null +++ b/drivers/gnss/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(gnss_publish.c) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig new file mode 100644 index 00000000000..4afb167f930 --- /dev/null +++ b/drivers/gnss/Kconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GNSS + bool "GNSS drivers" + select EXPERIMENTAL + help + Enable GNSS drivers and configuration. + +if GNSS + +config GNSS_SATELLITES + bool "GNSS satellites support" + help + Enable GNSS sattelites callback. + +module = GNSS +module-str = gnss +source "subsys/logging/Kconfig.template.log_config" + +endif diff --git a/drivers/gnss/gnss_publish.c b/drivers/gnss/gnss_publish.c new file mode 100644 index 00000000000..98e3a2e5e19 --- /dev/null +++ b/drivers/gnss/gnss_publish.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "gnss_publish.h" +#include +#include + +static struct k_spinlock lock; + +void gnss_publish_data(const struct device *dev, const struct gnss_data *data) +{ + K_SPINLOCK(&lock) { + STRUCT_SECTION_FOREACH(gnss_data_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, data); + } + } + } +} + +#if CONFIG_GNSS_SATELLITES +void gnss_publish_satellites(const struct device *dev, const struct gnss_satellite *satellites, + uint16_t size) +{ + K_SPINLOCK(&lock) { + STRUCT_SECTION_FOREACH(gnss_satellites_callback, callback) { + if (callback->dev == NULL || callback->dev == dev) { + callback->callback(dev, satellites, size); + } + } + } +} +#endif diff --git a/drivers/gnss/gnss_publish.h b/drivers/gnss/gnss_publish.h new file mode 100644 index 00000000000..b686c7eaed1 --- /dev/null +++ b/drivers/gnss/gnss_publish.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GNSS_GNSS_H_ +#define ZEPHYR_DRIVERS_GNSS_GNSS_H_ + +#include + +/** Internal function used by GNSS drivers to publish GNSS data */ +void gnss_publish_data(const struct device *dev, const struct gnss_data *data); + +/** Internal function used by GNSS drivers to publish GNSS satellites */ +void gnss_publish_satellites(const struct device *dev, const struct gnss_satellite *satellites, + uint16_t size); + +#endif /* ZEPHYR_DRIVERS_GNSS_GNSS_H_ */ diff --git a/include/zephyr/drivers/gnss.h b/include/zephyr/drivers/gnss.h new file mode 100644 index 00000000000..4c25bd84a43 --- /dev/null +++ b/include/zephyr/drivers/gnss.h @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2023 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file gnss.h + * @brief Public GNSS API. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ +#define ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ + +/** + * @brief GNSS Interface + * @defgroup gnss_interface GNSS Interface + * @ingroup io_interfaces + * @{ + */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** GNSS PPS modes */ +enum gnss_pps_mode { + /** PPS output disabled */ + GNSS_PPS_MODE_DISABLED = 0, + /** PPS output always enabled */ + GNSS_PPS_MODE_ENABLED = 1, + /** PPS output enabled from first lock */ + GNSS_PPS_MODE_ENABLED_AFTER_LOCK = 2, + /** PPS output enabled while locked */ + GNSS_PPS_MODE_ENABLED_WHILE_LOCKED = 3 +}; + +/** API for setting fix rate */ +typedef int (*gnss_set_fix_rate_t)(const struct device *dev, uint32_t fix_interval_ms); + +/** API for getting fix rate */ +typedef int (*gnss_get_fix_rate_t)(const struct device *dev, uint32_t *fix_interval_ms); + +/** + * @brief GNSS periodic tracking configuration + * + * @note Setting either active_time or inactive_time to 0 will disable periodic + * function. + */ +struct gnss_periodic_config { + /** The time the GNSS will spend in the active state in ms */ + uint32_t active_time_ms; + /** The time the GNSS will spend in the inactive state in ms */ + uint32_t inactive_time_ms; +}; + +/** API for setting periodic tracking configuration */ +typedef int (*gnss_set_periodic_config_t)(const struct device *dev, + const struct gnss_periodic_config *periodic_config); + +/** API for setting periodic tracking configuration */ +typedef int (*gnss_get_periodic_config_t)(const struct device *dev, + struct gnss_periodic_config *periodic_config); + +/** GNSS navigation modes */ +enum gnss_navigation_mode { + /** Dynamics have no impact on tracking */ + GNSS_NAVIGATION_MODE_ZERO_DYNAMICS = 0, + /** Low dynamics have higher impact on tracking */ + GNSS_NAVIGATION_MODE_LOW_DYNAMICS = 1, + /** Low and high dynamics have equal impact on tracking */ + GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS = 2, + /** High dynamics have higher impact on tracking */ + GNSS_NAVIGATION_MODE_HIGH_DYNAMICS = 3 +}; + +/** API for setting navigation mode */ +typedef int (*gnss_set_navigation_mode_t)(const struct device *dev, + enum gnss_navigation_mode mode); + +/** API for getting navigation mode */ +typedef int (*gnss_get_navigation_mode_t)(const struct device *dev, + enum gnss_navigation_mode *mode); + +/** Systems contained in gnss_systems_t */ +enum gnss_system { + /** Global Positioning System (GPS) */ + GNSS_SYSTEM_GPS = BIT(0), + /** GLObal NAvigation Satellite System (GLONASS) */ + GNSS_SYSTEM_GLONASS = BIT(1), + /** Galileo */ + GNSS_SYSTEM_GALILEO = BIT(2), + /** BeiDou Navigation Satellite System */ + GNSS_SYSTEM_BEIDOU = BIT(3), + /** Quasi-Zenith Satellite System (QZSS) */ + GNSS_SYSTEM_QZSS = BIT(4), + /** Indian Regional Navigation Satellite System (IRNSS) */ + GNSS_SYSTEM_IRNSS = BIT(5), + /** Satellite-Based Augmentation System (SBAS) */ + GNSS_SYSTEM_SBAS = BIT(6), + /** Indoor Messaging System (IMES) */ + GNSS_SYSTEM_IMES = BIT(7), +}; + +/** Type storing bitmask of GNSS systems */ +typedef uint32_t gnss_systems_t; + +/** API for enabling systems */ +typedef int (*gnss_set_enabled_systems_t)(const struct device *dev, gnss_systems_t systems); + +/** API for getting enabled systems */ +typedef int (*gnss_get_enabled_systems_t)(const struct device *dev, gnss_systems_t *systems); + +/** API for getting enabled systems */ +typedef int (*gnss_get_supported_systems_t)(const struct device *dev, gnss_systems_t *systems); + +/** GNSS fix status */ +enum gnss_fix_status { + /** No GNSS fix aqcuired */ + GNSS_FIX_STATUS_NO_FIX = 0, + /** GNSS fix aqcuired */ + GNSS_FIX_STATUS_GNSS_FIX = 1, + /** Differential GNSS fix acquired */ + GNSS_FIX_STATUS_DGNSS_FIX = 2, + /** Estimated fix acquired */ + GNSS_FIX_STATUS_ESTIMATED_FIX = 3, +}; + +/** GNSS fix quality */ +enum gnss_fix_quality { + /** Invalid fix */ + GNSS_FIX_QUALITY_INVALID = 0, + /** Standard positioning service */ + GNSS_FIX_QUALITY_GNSS_SPS = 1, + /** Differential GNSS */ + GNSS_FIX_QUALITY_DGNSS = 2, + /** Precise positioning service */ + GNSS_FIX_QUALITY_GNSS_PPS = 3, + /** Real-time kinematic */ + GNSS_FIX_QUALITY_RTK = 4, + /** Floating real-time kinematic */ + GNSS_FIX_QUALITY_FLOAT_RTK = 5, + /** Estimated fix */ + GNSS_FIX_QUALITY_ESTIMATED = 6, +}; + +/** GNSS info data structure */ +struct gnss_info { + /** Number of satellites being tracked */ + uint16_t satellites_cnt; + /** Horizontal dilution of precision in 1/1000 */ + uint16_t hdop; + /** The fix status */ + enum gnss_fix_status fix_status; + /** The fix quality */ + enum gnss_fix_quality fix_quality; +}; + +/** GNSS time data structure */ +struct gnss_time { + /** Hour [0, 23] */ + uint8_t hour; + /** Minute [0, 59] */ + uint8_t minute; + /** Millisecond [0, 59999] */ + uint16_t millisecond; + /** Day of month [1, 31] */ + uint8_t month_day; + /** Month [1, 12] */ + uint8_t month; + /** Year [0, 99] */ + uint8_t century_year; +}; + +/** GNSS API structure */ +__subsystem struct gnss_driver_api { + gnss_set_fix_rate_t set_fix_rate; + gnss_get_fix_rate_t get_fix_rate; + gnss_set_periodic_config_t set_periodic_config; + gnss_get_periodic_config_t get_periodic_config; + gnss_set_navigation_mode_t set_navigation_mode; + gnss_get_navigation_mode_t get_navigation_mode; + gnss_set_enabled_systems_t set_enabled_systems; + gnss_get_enabled_systems_t get_enabled_systems; + gnss_get_supported_systems_t get_supported_systems; +}; + +/** GNSS data structure */ +struct gnss_data { + /** Navigation data acquired */ + struct navigation_data nav_data; + /** GNSS info when navigation data was acquired */ + struct gnss_info info; + /** UTC time when data was acquired */ + struct gnss_time utc; +}; + +/** Template for GNSS data callback */ +typedef void (*gnss_data_callback_t)(const struct device *dev, const struct gnss_data *data); + +/** GNSS callback structure */ +struct gnss_data_callback { + /** Filter callback to GNSS data from this device if not NULL */ + const struct device *dev; + /** Callback called when GNSS data is published */ + gnss_data_callback_t callback; +}; + +/** GNSS satellite structure */ +struct gnss_satellite { + /** Pseudo-random noise sequence */ + uint8_t prn; + /** Signal-to-noise ratio in dB */ + uint8_t snr; + /** Elevation in degrees [0, 90] */ + uint8_t elevation; + /** Azimuth relative to True North in degrees [0, 359] */ + uint16_t azimuth; + /** System of satellite */ + enum gnss_system system; + /** True if satellite is being tracked */ + uint8_t is_tracked : 1; +}; + +/** Template for GNSS satellites callback */ +typedef void (*gnss_satellites_callback_t)(const struct device *dev, + const struct gnss_satellite *satellites, + uint16_t size); + +/** GNSS callback structure */ +struct gnss_satellites_callback { + /** Filter callback to GNSS data from this device if not NULL */ + const struct device *dev; + /** Callback called when GNSS satellites is published */ + gnss_satellites_callback_t callback; +}; + +/** + * @brief Set the GNSS fix rate + * + * @param dev Device instance + * @param fix_interval_ms Fix interval to set in milliseconds + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms); + +static inline int z_impl_gnss_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_fix_rate == NULL) { + return -ENOSYS; + } + + return api->set_fix_rate(dev, fix_interval_ms); +} + +/** + * @brief Get the GNSS fix rate + * + * @param dev Device instance + * @param fix_interval_ms Destination for fix interval in milliseconds + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms); + +static inline int z_impl_gnss_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_fix_rate == NULL) { + return -ENOSYS; + } + + return api->get_fix_rate(dev, fix_interval_ms); +} + +/** + * @brief Set the GNSS periodic tracking configuration + * + * @param dev Device instance + * @param config Periodic tracking configuration to set + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_periodic_config(const struct device *dev, + const struct gnss_periodic_config *config); + +static inline int z_impl_gnss_set_periodic_config(const struct device *dev, + const struct gnss_periodic_config *config) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_periodic_config == NULL) { + return -ENOSYS; + } + + return api->set_periodic_config(dev, config); +} + +/** + * @brief Get the GNSS periodic tracking configuration + * + * @param dev Device instance + * @param config Destination for periodic tracking configuration + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_periodic_config(const struct device *dev, + struct gnss_periodic_config *config); + +static inline int z_impl_gnss_get_periodic_config(const struct device *dev, + struct gnss_periodic_config *config) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_periodic_config == NULL) { + return -ENOSYS; + } + + return api->get_periodic_config(dev, config); +} + +/** + * @brief Set the GNSS navigation mode + * + * @param dev Device instance + * @param mode Navigation mode to set + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode); + +static inline int z_impl_gnss_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_navigation_mode == NULL) { + return -ENOSYS; + } + + return api->set_navigation_mode(dev, mode); +} + +/** + * @brief Get the GNSS navigation mode + * + * @param dev Device instance + * @param mode Destination for navigation mode + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode); + +static inline int z_impl_gnss_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_navigation_mode == NULL) { + return -ENOSYS; + } + + return api->get_navigation_mode(dev, mode); +} + +/** + * @brief Set enabled GNSS systems + * + * @param dev Device instance + * @param systems Systems to enable + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_set_enabled_systems(const struct device *dev, gnss_systems_t systems); + +static inline int z_impl_gnss_set_enabled_systems(const struct device *dev, + gnss_systems_t systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->set_enabled_systems == NULL) { + return -ENOSYS; + } + + return api->set_enabled_systems(dev, systems); +} + +/** + * @brief Get enabled GNSS systems + * + * @param dev Device instance + * @param systems Destination for enabled systems + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_enabled_systems(const struct device *dev, gnss_systems_t *systems); + +static inline int z_impl_gnss_get_enabled_systems(const struct device *dev, + gnss_systems_t *systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_enabled_systems == NULL) { + return -ENOSYS; + } + + return api->get_enabled_systems(dev, systems); +} + +/** + * @brief Get supported GNSS systems + * + * @param dev Device instance + * @param systems Destination for supported systems + * + * @return 0 if successful + * @return -errno negative errno code on failure + */ +__syscall int gnss_get_supported_systems(const struct device *dev, gnss_systems_t *systems); + +static inline int z_impl_gnss_get_supported_systems(const struct device *dev, + gnss_systems_t *systems) +{ + const struct gnss_driver_api *api = (const struct gnss_driver_api *)dev->api; + + if (api->get_supported_systems == NULL) { + return -ENOSYS; + } + + return api->get_supported_systems(dev, systems); +} + +/** + * @brief Register a callback structure for GNSS data published + * + * @param _dev Device pointer + * @param _callback The callback function + */ +#if CONFIG_GNSS +#define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback) \ + static const STRUCT_SECTION_ITERABLE(gnss_data_callback, \ + _gnss_data_callback__##_callback) = { \ + .dev = _dev, \ + .callback = _callback, \ + } +#else +#define GNSS_DATA_CALLBACK_DEFINE(_dev, _callback) +#endif + +/** + * @brief Register a callback structure for GNSS satellites published + * + * @param _dev Device pointer + * @param _callback The callback function + */ +#if CONFIG_GNSS_SATELLITES +#define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback) \ + static const STRUCT_SECTION_ITERABLE(gnss_satellites_callback, \ + _gnss_satellites_callback__##_callback) = { \ + .dev = _dev, \ + .callback = _callback, \ + } +#else +#define GNSS_SATELLITES_CALLBACK_DEFINE(_dev, _callback) +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ */ diff --git a/include/zephyr/linker/common-rom/common-rom-misc.ld b/include/zephyr/linker/common-rom/common-rom-misc.ld index 5da776a6aaf..1fbf777ba55 100644 --- a/include/zephyr/linker/common-rom/common-rom-misc.ld +++ b/include/zephyr/linker/common-rom/common-rom-misc.ld @@ -59,3 +59,11 @@ ITERABLE_SECTION_ROM(shell_dynamic_subcmds, 4) ITERABLE_SECTION_ROM(cfb_font, 4) + +#if defined(CONFIG_GNSS) + ITERABLE_SECTION_ROM(gnss_data_callback, 4) +#endif + +#if defined(CONFIG_GNSS_SATELLITES) + ITERABLE_SECTION_ROM(gnss_satellites_callback, 4) +#endif