Setting runtime PA Gain on nRF21540 (Dynamic Gain) Fails

I'm evaluating the nRF21540 on the PCA10112 Devkit.

I'm using nRF Connect v2.3.0 and using the openthread cli example (samples\openthread\cli), configured with nrf21540dk_nrf52840.overlay

I would like to be able to dynamically set PA gain for the CLI thread application. Thread supports 2 APIs that look to support this, but the implementations are incomplete, however the these are also declared "weak" so I simply override them in the sample's main.c. These get called as expected. 

Configs, I've changed the gain (GAIN_DB_xxx values) as testing from 10 to 7 and enabled MPSL_FEM_NRF21540_RUNTIME_PA_GAIN_CONTROL

here are the relevant configs:-

CONFIG_DT_HAS_NORDIC_NRF21540_FEM_ENABLED=y
CONFIG_DT_HAS_NORDIC_NRF21540_FEM_SPI_ENABLED=y

# CONFIG_MPSL_FEM_ONLY is not set
CONFIG_MPSL_FEM_ANY_SUPPORT=y
CONFIG_MPSL_FEM_NRF21540_GPIO_SUPPORT=y
CONFIG_MPSL_FEM_NRF21540_GPIO_SPI_SUPPORT=y
CONFIG_MPSL_FEM_NCS_SUPPORTED_FEM_USED=y
CONFIG_MPSL_FEM_API_AVAILABLE=y
CONFIG_MPSL_FEM=y
CONFIG_MPSL_FEM_NRF21540_GPIO=y
# CONFIG_MPSL_FEM_NRF21540_GPIO_SPI is not set
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=7
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB_POUTA=7
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB_POUTB=7
CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=13
CONFIG_MPSL_FEM_NRF21540_RUNTIME_PA_GAIN_CONTROL=y
# CONFIG_MPSL_FEM_POWER_MODEL is not set
CONFIG_MPSL_FEM_DEVICE_CONFIG_254=y
CONFIG_MPSL_THREAD_COOP_PRIO=0
CONFIG_MPSL_WORK_STACK_SIZE=1024
CONFIG_MPSL_TIMESLOT_SESSION_COUNT=0
# CONFIG_MPSL_ASSERT_HANDLER is not set

And my code uses the MPSL API's :-

otError otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
{
    OT_UNUSED_VARIABLE(aInstance);
    mpsl_fem_pa_is_configured(aGain);
    return OT_ERROR_NONE;
}
otError otPlatRadioSetFemLnaGain(otInstance *aInstance, int8_t aGain)
{
    OT_UNUSED_VARIABLE(aInstance);
    otError error = OT_ERROR_NONE;
    
    mpsl_fem_gain_t gain;
    gain.gain_db = aGain;
    gain.private_setting = 0; // Is this applicable for nrf21540??

    

    int32_t res = mpsl_fem_pa_gain_set(&gain);
    if (res != 0)
    {
        printf("DIE %s:%d res=%d\r\n", __FUNCTION__, __LINE__, res);
        error = OT_ERROR_INVALID_ARGS;
    }
 
    return error;
}

Reading the Gain is OK, i get back the value I define in GAIN_DB_xxx, however setting the value always fails UNLESS the set value is the same as the GAIN_DB_xxx value?

From the Thread CLI

uart:~$ ot fem
LNA gain 7 dBm
Done
uart:~$ ot fem lnagain 7    <- Set the default gain always works
Done
uart:~$ ot fem lnagain 8     <- But any other value always fails - why?
DIE otPlatRadioSetFemLnaGain:211 res=-22
Error 7: InvalidArgs
uart:~$

Since the implementation of mpsl_fem_pa_gain_set() is precompiled in the mpsl library, I cant debug this further as the code is hidden. 

1. What do i need to do to have dynamic runtime gain (via the SPI interface) working?

2. Can you add to the documentation for mpsl_fem_gain_t, specifically the private_setting field how should this be used for 21540, what should be the default value?

3. Is there any way to access the other nRF21540 registers? If MPSL wraps the FEM interface, perhaps include a generic fem_read_spi, fem_write_spi API so on board boot, or a production test we can read the DeviceID's (HW_IDx, PARTNUMBER), or set the OTP configuration registers (CONFREGx) 

Many Thanks in advance. 

Related