diff --git a/doc/nrf/app_dev/device_guides/fem/fem_nrf2220.rst b/doc/nrf/app_dev/device_guides/fem/fem_nrf2220.rst index 9dcffd6488a2..9127330380e5 100644 --- a/doc/nrf/app_dev/device_guides/fem/fem_nrf2220.rst +++ b/doc/nrf/app_dev/device_guides/fem/fem_nrf2220.rst @@ -22,6 +22,8 @@ To use nRF2220, complete the following steps: }; }; + Additionally, you can consider setting the :kconfig:option:`CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION` Kconfig option. + #. Optionally replace the device name ``name_of_fem_node``. #. Replace the pin numbers provided for each of the required properties: diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 240cc0dccca5..08b7d9e2b7ad 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -103,7 +103,7 @@ Developing with PMICs Developing with Front-End Modules ================================= -|no_changes_yet_note| +* Added the temperature compensation feature for the nRF2220 Front-End Module. Developing with custom boards ============================= diff --git a/lib/fem_al/fem_al.c b/lib/fem_al/fem_al.c index 4ffdd5d3a300..c0756b52ac08 100644 --- a/lib/fem_al/fem_al.c +++ b/lib/fem_al/fem_al.c @@ -18,6 +18,10 @@ #include #include +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION) && \ + !defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER) +#include +#endif #include "fem_al/fem_al.h" #include "fem_interface.h" @@ -186,6 +190,15 @@ int fem_tx_configure(uint32_t ramp_up_time) fem_activate_event.event.timer.counter_period.end = ramp_up_time; +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION) && \ + !defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER) + err = mpsl_fem_nrf2220_temperature_changed_update_now(); + if (err) { + printk("mpsl_fem_nrf2220_temperature_changed_update_now failed (err %d)\n", err); + return -EFAULT; + } +#endif + mpsl_fem_enable(); err = mpsl_fem_pa_configuration_set(&fem_activate_event, &fem_deactivate_evt); if (err) { diff --git a/subsys/mpsl/fem/Kconfig b/subsys/mpsl/fem/Kconfig index 7791a6ab18fa..ba736f3bfae8 100644 --- a/subsys/mpsl/fem/Kconfig +++ b/subsys/mpsl/fem/Kconfig @@ -288,6 +288,56 @@ config MPSL_FEM_USE_TWI_DRV select I2C default y +config MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION + bool "Temperature compensation of the nRF2220 Front-End Module [EXPERIMENTAL]" + depends on MPSL_FEM_NRF2220 && MPSL_FEM_USE_TWI_DRV + select EXPERIMENTAL + help + This allows to achieve better accuracy in output power among all + temperature ranges for the nRF2220 Front-End modules. + +config MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER + bool + depends on MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION + default y if MPSL && !MPSL_FEM_ONLY + help + Enable this option when using protocols relying on the MPSL scheduler. + After it turns out that for the current temperature some registers + of the nRF2220 must be written, the writes are performed within a timeslot + negotiated with the MPSL scheduler. For operation with Bluetooth, the timeslot + for the nRF2220 register update is between other Bluetooth timeslots. + For operation with the nRF 802.15.4 Radio Driver, the grant for the timeslot + for the nRF2220 register update causes short inability to transmit or receive. + +choice MPSL_FEM_NRF2220_TEMPERATURE_SOURCE + prompt "Source of temperature measurement of the nRF2220" + depends on MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION + default MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_SOC + +config MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_SOC + bool "Temperature of the SoC as the temperature of the nRF2220" + select SENSOR + help + The temperature of the SoC controlling the nRF2220 Front-End Module + is taken as an input for the temperature compensation. + Use this option if there is good thermal coupling between the + temperature of the SoC and the nRF2220 Front-End Module. + +config MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_CUSTOM + bool "Custom nRF2220 temperature measurement provider" + help + Use this option if you have a custom temperature sensor measuring the + temperature of the nRF2220 device. Your custom code must call + the fem_temperature_change() function to notify the module handling the FEM + that the new temperature value is to be processed. + +endchoice # MPSL_FEM_NRF2220_TEMPERATURE_SOURCE + +config MPSL_FEM_NRF2220_TEMPERATURE_POLL_PERIOD + int "Temperature measurement poll period (in ms) for temperature compensation of the nRF2220" + depends on MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_SOC + default 5000 + config MPSL_FEM_INIT_PRIORITY int "Init priority of the Front-End Module support code" depends on MPSL_FEM diff --git a/subsys/mpsl/fem/common/include/mpsl_fem_twi_drv.h b/subsys/mpsl/fem/common/include/mpsl_fem_twi_drv.h index 125ed87ffd71..a61800ab801e 100644 --- a/subsys/mpsl/fem/common/include/mpsl_fem_twi_drv.h +++ b/subsys/mpsl/fem/common/include/mpsl_fem_twi_drv.h @@ -9,25 +9,43 @@ #include #include +#include -/** - * @brief Initializer of structure @c mpsl_fem_twi_if_t allowing to use TWI interface. - * - * @param node_id Devicetree node identifier for the TWI part for the FEM device. - */ -#define MPSL_FEM_TWI_DRV_IF_INITIALIZER(node_id) \ - (mpsl_fem_twi_if_t){ \ - .enabled = true, \ - .slave_address = ((uint8_t)DT_REG_ADDR(node_id)), \ - .p_instance = (void *)DEVICE_DT_GET(DT_BUS(node_id)), \ - .p_xfer_read = mpsl_fem_twi_drv_impl_xfer_read, \ - .p_xfer_write = mpsl_fem_twi_drv_impl_xfer_write, \ +/** @brief Structure representing an I2C bus driver for a Front-End Module. */ +typedef struct { + const struct device *dev; + nrfx_twim_evt_handler_t nrfx_twim_callback_saved; + void *nrfx_twim_callback_ctx_saved; + mpsl_fem_twi_async_xfer_write_cb_t fem_twi_async_xfwr_write_cb; + void *fem_twi_async_xfwr_write_cb_ctx; +} mpsl_fem_twi_drv_t; + +#define MPSL_FEM_TWI_DRV_INITIALIZER(node_id) \ + (mpsl_fem_twi_drv_t){ \ + .dev = DEVICE_DT_GET(DT_BUS(node_id)), \ } -int32_t mpsl_fem_twi_drv_impl_xfer_read(void *p_instance, uint8_t slave_address, - uint8_t internal_address, uint8_t *p_data, uint8_t data_length); +/** @brief Prepare the FEM TWI interface structure. + * + * @note This function prepares just synchronous part of the interface. + * If Front-End Module driver requires an asynchronous part of the interface call + * the @ref mpsl_fem_twi_drv_fem_twi_if_prepare_add_async function afterwards. + * + * @param drv Pointer to the FEM TWI driver instance object initialized with + * MPSL_FEM_TWI_DRV_INITIALIZER. + * @param twi_if Pointer to the FEM TWI interface structure to fill. + * @param address The address of the FEM device on the TWI bus. + */ +void mpsl_fem_twi_drv_fem_twi_if_prepare(mpsl_fem_twi_drv_t *drv, mpsl_fem_twi_if_t *twi_if, + uint8_t address); -int32_t mpsl_fem_twi_drv_impl_xfer_write(void *p_instance, uint8_t slave_address, - uint8_t internal_address, const uint8_t *p_data, uint8_t data_length); +/** @brief Prepare the asynchronous part of the FEM TWI interface structure. + * + * @note Assumes that the @ref mpsl_fem_twi_drv_fem_twi_if_prepare function + * has already been called. + * + * @param twi_if Pointer to the interface structure to fill. + */ +void mpsl_fem_twi_drv_fem_twi_if_prepare_add_async(mpsl_fem_twi_if_t *twi_if); #endif /* MPSL_FEM_TWI_DRV__ */ diff --git a/subsys/mpsl/fem/common/mpsl_fem_twi_drv.c b/subsys/mpsl/fem/common/mpsl_fem_twi_drv.c index 4e2e5cd619c3..dfd8f94fdd17 100644 --- a/subsys/mpsl/fem/common/mpsl_fem_twi_drv.c +++ b/subsys/mpsl/fem/common/mpsl_fem_twi_drv.c @@ -6,20 +6,168 @@ #include #include +#include +#include <../drivers/i2c/i2c_nrfx_twim_common.h> +static int32_t mpsl_fem_twi_drv_impl_xfer_read(void *p_instance, uint8_t slave_address, + uint8_t internal_address, uint8_t *p_data, + uint8_t data_length) +{ + mpsl_fem_twi_drv_t *drv = (mpsl_fem_twi_drv_t *)p_instance; + + return i2c_burst_read(drv->dev, slave_address, internal_address, p_data, data_length); +} + +static int32_t mpsl_fem_twi_drv_impl_xfer_write(void *p_instance, uint8_t slave_address, + uint8_t internal_address, const uint8_t *p_data, + uint8_t data_length) +{ + mpsl_fem_twi_drv_t *drv = (mpsl_fem_twi_drv_t *)p_instance; + + return i2c_burst_write(drv->dev, slave_address, internal_address, p_data, data_length); +} + +static inline void mpsl_fem_twi_drv_nrfx_twim_callback_replace(mpsl_fem_twi_drv_t *drv, + nrfx_twim_evt_handler_t callback) +{ + const struct i2c_nrfx_twim_common_config *config = drv->dev->config; + nrfx_err_t err; + + nrfx_twim_callback_get(&config->twim, &drv->nrfx_twim_callback_saved, + &drv->nrfx_twim_callback_ctx_saved); + + err = nrfx_twim_callback_set(&config->twim, callback, drv); + + __ASSERT_NO_MSG(err == NRFX_SUCCESS); + (void)err; +} + +static inline void mpsl_fem_twi_drv_nrfx_twim_callback_restore(mpsl_fem_twi_drv_t *drv) +{ + const struct i2c_nrfx_twim_common_config *config = drv->dev->config; + nrfx_err_t err; + + err = nrfx_twim_callback_set(&config->twim, drv->nrfx_twim_callback_saved, + drv->nrfx_twim_callback_ctx_saved); + + __ASSERT_NO_MSG(err == NRFX_SUCCESS); + (void)err; +} + +static void mpsl_fem_twi_drv_nrfx_twim_evt_handler(nrfx_twim_evt_t const *p_event, void *p_context) +{ + mpsl_fem_twi_drv_t *drv = (mpsl_fem_twi_drv_t *)p_context; + int32_t res = 0; + + mpsl_fem_twi_drv_nrfx_twim_callback_restore(drv); -int32_t mpsl_fem_twi_drv_impl_xfer_read(void *p_instance, uint8_t slave_address, - uint8_t internal_address, uint8_t *p_data, uint8_t data_length) + if (p_event->type != NRFX_TWIM_EVT_DONE) { + res = -EIO; + } + + /* Call the callback which was passed to the mpsl_fem_twi_drv_impl_xfer_write_async call, + * that started the transfer. + */ + drv->fem_twi_async_xfwr_write_cb(drv, res, drv->fem_twi_async_xfwr_write_cb_ctx); +} + +static int32_t mpsl_fem_twi_drv_impl_xfer_write_async(void *p_instance, uint8_t slave_address, + const uint8_t *p_data, uint8_t data_length, + mpsl_fem_twi_async_xfer_write_cb_t p_callback, + void *p_context) { - const struct device *dev = (const struct device *)p_instance; + mpsl_fem_twi_drv_t *drv = (mpsl_fem_twi_drv_t *)p_instance; + const struct i2c_nrfx_twim_common_config *config = drv->dev->config; + + /* At this moment the exclusive access to the drv->dev should have been already acquired. + * No ongoing twi transfers are expected. Because of that it is safe to replace + * original event handler of the TWIM with custom one, perform twim transfer and then + * restore the original event handler. + */ + + nrfx_twim_xfer_desc_t cur_xfer = { + .address = slave_address, + .type = NRFX_TWIM_XFER_TX, + .p_primary_buf = (uint8_t *)p_data, + .primary_length = data_length, + }; + nrfx_err_t err; + int32_t ret = 0; + + drv->fem_twi_async_xfwr_write_cb = p_callback; + drv->fem_twi_async_xfwr_write_cb_ctx = p_context; - return i2c_burst_read(dev, slave_address, internal_address, p_data, data_length); + mpsl_fem_twi_drv_nrfx_twim_callback_replace(drv, mpsl_fem_twi_drv_nrfx_twim_evt_handler); + + err = nrfx_twim_xfer(&config->twim, &cur_xfer, 0); + + if (err != NRFX_SUCCESS) { + mpsl_fem_twi_drv_nrfx_twim_callback_restore(drv); + if (err == NRFX_ERROR_BUSY) { + ret = -EBUSY; + } else { + ret = -EIO; + } + } + + return ret; } -int32_t mpsl_fem_twi_drv_impl_xfer_write(void *p_instance, uint8_t slave_address, - uint8_t internal_address, const uint8_t *p_data, uint8_t data_length) +static uint32_t mpsl_fem_twi_drv_frequency_hz_get(mpsl_fem_twi_drv_t *drv) { - const struct device *dev = (const struct device *)p_instance; + const struct i2c_nrfx_twim_common_config *config = drv->dev->config; + + switch (config->twim_config.frequency) { + case NRF_TWIM_FREQ_100K: + return 100000; + case NRF_TWIM_FREQ_250K: + return 250000; + case NRF_TWIM_FREQ_400K: + return 400000; +#if NRF_TWIM_HAS_1000_KHZ_FREQ + case NRF_TWIM_FREQ_1000K: + return 1000000; +#endif + default: + __ASSERT_NO_MSG(false); + return 100000; + } +} - return i2c_burst_write(dev, slave_address, internal_address, p_data, data_length); +static uint32_t mpsl_fem_twi_drv_impl_xfer_write_async_time_get(void *p_instance, + uint8_t data_length) +{ + mpsl_fem_twi_drv_t *drv = (mpsl_fem_twi_drv_t *)p_instance; + + static const uint32_t sw_overhead_safety_margin_time_us = 10U; + /* Note: on nRF5 devices the first bit of each data octet is delayed by one period, + * thus +1 below. + */ + static const uint32_t i2c_data_byte_sck_periods_with_ack = 1U + 8U + 1U; + static const uint32_t i2c_start_bit_sck_periods = 2U; + static const uint32_t i2c_stop_bit_sck_periods = 2U; + uint32_t i2c_sck_frequency_hz = mpsl_fem_twi_drv_frequency_hz_get(drv); + + /* Total number of sck periods needed to perform a write transfer. */ + uint32_t total_periods = i2c_start_bit_sck_periods + + (data_length + 1U) * i2c_data_byte_sck_periods_with_ack + + i2c_stop_bit_sck_periods; + + return (total_periods * 1000000 / i2c_sck_frequency_hz) + sw_overhead_safety_margin_time_us; +} + +void mpsl_fem_twi_drv_fem_twi_if_prepare(mpsl_fem_twi_drv_t *drv, mpsl_fem_twi_if_t *twi_if, + uint8_t address) +{ + twi_if->enabled = true; + twi_if->slave_address = address; + twi_if->p_instance = (void *)drv; + twi_if->p_xfer_read = mpsl_fem_twi_drv_impl_xfer_read; + twi_if->p_xfer_write = mpsl_fem_twi_drv_impl_xfer_write; +} + +void mpsl_fem_twi_drv_fem_twi_if_prepare_add_async(mpsl_fem_twi_if_t *twi_if) +{ + twi_if->p_xfer_write_async = mpsl_fem_twi_drv_impl_xfer_write_async; + twi_if->p_xfer_write_async_time_get = mpsl_fem_twi_drv_impl_xfer_write_async_time_get; } diff --git a/subsys/mpsl/fem/nrf2220/mpsl_fem_nrf2220.c b/subsys/mpsl/fem/nrf2220/mpsl_fem_nrf2220.c index a376ce0fcd2e..4db13f84b0e8 100644 --- a/subsys/mpsl/fem/nrf2220/mpsl_fem_nrf2220.c +++ b/subsys/mpsl/fem/nrf2220/mpsl_fem_nrf2220.c @@ -30,12 +30,18 @@ #include #endif +#if IS_ENABLED(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION) +#include +#include +#endif + #if !defined(CONFIG_PINCTRL) #error "The nRF2220 driver must be used with CONFIG_PINCTRL! Set CONFIG_PINCTRL=y" #endif #if DT_NODE_HAS_PROP(DT_NODELABEL(nrf_radio_fem), twi_if) -#define MPSL_FEM_TWI_IF DT_PHANDLE(DT_NODELABEL(nrf_radio_fem), twi_if) +#define MPSL_FEM_TWI_IF DT_PHANDLE(DT_NODELABEL(nrf_radio_fem), twi_if) +#define MPSL_FEM_TWI_ADDRESS DT_REG_ADDR(MPSL_FEM_TWI_IF) #endif #define FEM_OUTPUT_POWER_DBM DT_PROP(DT_NODELABEL(nrf_radio_fem), output_power_dbm) @@ -66,7 +72,16 @@ static void fem_nrf2220_twi_init_regs_configure(mpsl_fem_nrf2220_interface_confi static void fem_nrf2220_twi_configure(mpsl_fem_nrf2220_interface_config_t *cfg) { - cfg->twi_if = MPSL_FEM_TWI_DRV_IF_INITIALIZER(MPSL_FEM_TWI_IF); + static mpsl_fem_twi_drv_t fem_twi_drv = MPSL_FEM_TWI_DRV_INITIALIZER(MPSL_FEM_TWI_IF); + + mpsl_fem_twi_drv_fem_twi_if_prepare(&fem_twi_drv, &cfg->twi_if, MPSL_FEM_TWI_ADDRESS); + if (IS_ENABLED(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER)) { + /* The nRF2220 temperature compensation with the MPSL scheduler requires + * asynchronous interface. + * See mpsl_fem_nrf2220_temperature_changed_update_request function. + */ + mpsl_fem_twi_drv_fem_twi_if_prepare_add_async(&cfg->twi_if); + } } #endif /* DT_NODE_HAS_PROP(DT_NODELABEL(nrf_radio_fem), twi_if) */ @@ -193,4 +208,145 @@ BUILD_ASSERT(CONFIG_MPSL_FEM_INIT_PRIORITY > CONFIG_I2C_INIT_PRIORITY, SYS_INIT(mpsl_fem_init, POST_KERNEL, CONFIG_MPSL_FEM_INIT_PRIORITY); +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION) + +static K_SEM_DEFINE(fem_temperature_new_value_sem, 0, 1); + +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER) +static int32_t fem_temperature_update_result; +static K_SEM_DEFINE(fem_temperature_updated_cb_sem, 0, 1); + +static void fem_temperature_update_cb(int32_t res) +{ + fem_temperature_update_result = res; + k_sem_give(&fem_temperature_updated_cb_sem); +} + +static int32_t fem_temperature_changed_update_now(void) +{ + const struct device *i2c_bus_dev = DEVICE_DT_GET(DT_BUS(MPSL_FEM_TWI_IF)); + + /* Let's have initially "taken" semaphore that will inform the operation + * on the nrf2220 is finished. + */ + k_sem_take(&fem_temperature_updated_cb_sem, K_NO_WAIT); + + (void)i2c_nrfx_twim_exclusive_access_acquire(i2c_bus_dev, K_FOREVER); + + /* Temporary raise i2c_bus_dev IRQ priority, as required by the + * mpsl_fem_nrf2220_temperature_changed_update_request function. + * The IRQs from i2c may not be delayed while performing operations + * in a timeslot granted by the MPSL scheduler. + */ + z_arm_irq_priority_set(DT_IRQN(DT_BUS(MPSL_FEM_TWI_IF)), 0, IRQ_ZERO_LATENCY); + + mpsl_fem_nrf2220_temperature_changed_update_request(fem_temperature_update_cb); + + /* Let's wait until the operation is finished */ + k_sem_take(&fem_temperature_updated_cb_sem, K_FOREVER); + + /* Restore original i2c_bus_dev IRQ priority. */ + z_arm_irq_priority_set(DT_IRQN(DT_BUS(MPSL_FEM_TWI_IF)), + DT_IRQ(DT_BUS(MPSL_FEM_TWI_IF), priority), 0); + + i2c_nrfx_twim_exclusive_access_release(i2c_bus_dev); + + return fem_temperature_update_result; +} +#endif /* CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_MPSL_SCHEDULER */ + +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_SOC) + +#include +#define FEM_TEMPERATURE_NEW_VALUE_SEM_TIMEOUT \ + (K_MSEC(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_POLL_PERIOD)) + +static int8_t fem_temperature_sensor_value_get(void) +{ + const struct device *dev = DEVICE_DT_GET_ONE(nordic_nrf_temp); + + if (!device_is_ready(dev)) { + __ASSERT(false, "Temperature sensor not ready"); + } + + struct sensor_value v; + int ret = sensor_sample_fetch(dev); + + __ASSERT(ret == 0, "Can't fetch temperature sensor sample"); + + ret = sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &v); + __ASSERT(ret == 0, "Can't get temperature of the die"); + + (void)ret; + + return v.val1; +} +#endif /* CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_SOC */ + +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_CUSTOM) + +#define FEM_TEMPERATURE_NEW_VALUE_SEM_TIMEOUT K_FOREVER + +#define NRF2220_TEMPERATURE_DEFAULT 25 + +static int8_t fem_temperature_value = NRF2220_TEMPERATURE_DEFAULT; + +void fem_temperature_change(int8_t temperature) +{ + fem_temperature_value = temperature; + k_sem_give(&fem_temperature_new_value_sem); +} + +static int8_t fem_temperature_sensor_value_get(void) +{ + return fem_temperature_value; +} +#endif /* CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_SOURCE_CUSTOM */ + +static void fem_temperature_compensation_thread(void *dummy1, void *dummy2, void *dummy3) +{ + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy3); + + while (true) { + (void)k_sem_take(&fem_temperature_new_value_sem, + FEM_TEMPERATURE_NEW_VALUE_SEM_TIMEOUT); + + int8_t new_temperature = fem_temperature_sensor_value_get(); + + if (mpsl_fem_nrf2220_temperature_changed(new_temperature)) { +#if defined(CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER) + int32_t res = fem_temperature_changed_update_now(); + + __ASSERT(res == 0, "FEM update on temperature change failed"); + (void)res; +#endif /* CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION_WITH_MPSL_SCHEDULER */ + } + } +} + +#define FEM_TEMPERATURE_COMPENSATION_THREAD_STACK_SIZE 512 + +static K_THREAD_STACK_DEFINE(fem_temperature_compensation_thread_stack, + FEM_TEMPERATURE_COMPENSATION_THREAD_STACK_SIZE); +static struct k_thread fem_temperature_compensation_thread_data; + +static int fem_nrf2220_temperature_compensation_init(void) +{ + (void)k_thread_create(&fem_temperature_compensation_thread_data, + fem_temperature_compensation_thread_stack, + K_THREAD_STACK_SIZEOF(fem_temperature_compensation_thread_stack), + fem_temperature_compensation_thread, + NULL, NULL, NULL, + K_LOWEST_APPLICATION_THREAD_PRIO, 0, K_NO_WAIT); + + return 0; +} + +SYS_INIT(fem_nrf2220_temperature_compensation_init, APPLICATION, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +#endif /* CONFIG_MPSL_FEM_NRF2220_TEMPERATURE_COMPENSATION */ + #endif /* defined(CONFIG_MPSL_FEM_NRF2220) */ diff --git a/subsys/mpsl/fem/nrf2240/mpsl_fem_nrf2240.c b/subsys/mpsl/fem/nrf2240/mpsl_fem_nrf2240.c index ba29aefbd19e..cb97d3df634f 100644 --- a/subsys/mpsl/fem/nrf2240/mpsl_fem_nrf2240.c +++ b/subsys/mpsl/fem/nrf2240/mpsl_fem_nrf2240.c @@ -35,7 +35,8 @@ #endif #if DT_NODE_HAS_PROP(DT_NODELABEL(nrf_radio_fem), twi_if) -#define MPSL_FEM_TWI_IF DT_PHANDLE(DT_NODELABEL(nrf_radio_fem), twi_if) +#define MPSL_FEM_TWI_IF DT_PHANDLE(DT_NODELABEL(nrf_radio_fem), twi_if) +#define MPSL_FEM_TWI_ADDRESS DT_REG_ADDR(MPSL_FEM_TWI_IF) #endif #define FEM_OUTPUT_POWER_DBM DT_PROP(DT_NODELABEL(nrf_radio_fem), output_power_dbm) @@ -74,7 +75,9 @@ static void fem_nrf2240_twi_init_regs_configure(mpsl_fem_nrf2240_interface_confi static void fem_nrf2240_twi_configure(mpsl_fem_nrf2240_interface_config_t *cfg) { - cfg->twi_if = MPSL_FEM_TWI_DRV_IF_INITIALIZER(MPSL_FEM_TWI_IF); + static mpsl_fem_twi_drv_t fem_twi_drv = MPSL_FEM_TWI_DRV_INITIALIZER(MPSL_FEM_TWI_IF); + + mpsl_fem_twi_drv_fem_twi_if_prepare(&fem_twi_drv, &cfg->twi_if, MPSL_FEM_TWI_ADDRESS); } #endif /* DT_NODE_HAS_PROP(DT_NODELABEL(nrf_radio_fem), twi_if) */