nRF21540EK integration with nRF5340dk

Hi there,

We are trying to integrate an nRF21540EK shield onto our nRF5340DK. Following the instructions on the following link (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_radio_fem.html#ug-radio-fem-nrf21540-ek-programming) we were able to set up the hardware but we are struggling to find a guide on how to configure the software.

We are seeking to use the nRF21540EK in conjunction with the "Bluetooth: Peripheral UART" sample found in the nRF connect SDK and would like to be able to control the gain and antenna select functions on the nRF21540.

Thanks,

Matt

  • Hello Mathew,

    We have an example for peripheral_uart which was tested on NCS 1.8.0

     The added configuration for nrf21540 are like the following configurations 

    # FEM
    CONFIG_MPSL_FEM=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0
    CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20

    It also needs a function for setting transmit power and for the getting transmit power.

    static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_write_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Set Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        printk("RADIO Tx Power: %d + PA_GAIN(%d) = %d\n", rp->selected_tx_power, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, rp->selected_tx_power + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
        net_buf_unref(rsp);
    }
    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_read_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Read Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;
    
        net_buf_unref(rsp);
    }
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn *default_conn;
    	uint16_t default_conn_handle;
    	int ret;
    	int8_t txp;
    
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		printk("Connection failed (err %u)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	default_conn = bt_conn_ref(conn);
    	ret = bt_hci_get_conn_handle(default_conn,
    						&default_conn_handle);
    	if (ret) {
    		printk("No connection handle (err %d)\n", ret);
    		sys_reboot();
    		return;
    	}
    	
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    			printk("Connected via connection (%d) at %s\n",
    			       default_conn_handle, addr);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    			set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle,
    				     TRANSMIT_POWER_dBm);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    	current_conn = bt_conn_ref(conn);
    
    	dk_set_led_on(CON_STATUS_LED);
    }
    Set_tx_power has to be called from disconnected function to define the transmit power value.
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err = 0;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason %u)\n", log_strdup(addr), reason);
    
    	if (auth_conn) {
    		bt_conn_unref(auth_conn);
    		auth_conn = NULL;
    	}
    
    	if (current_conn) {
    		bt_conn_unref(current_conn);
    		current_conn = NULL;
    		dk_set_led_off(CON_STATUS_LED);
    	}
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
    			      ARRAY_SIZE(sd));
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    }
    From main function set_tx_power has to be called.
    void main(void) {
    ....
    ..
    
    set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    
    }
    You can try this modification in peripheral_uart sample and see the output.
    Let us know the consequence. 
    Thanks.
    Best Regards,
    Kazi Afroza Sultana
  • Hi Kazi, thanks for the reply. We tried to replicate your setup on the nRF5340 but we seem to be getting some errors. I have a few questions:

    • Do we need to use an overlay file to describe how the FEM is connected to the nRF5340 or this handled by adding the shield to the project’s CMakeLists.txt file?
    • Are the variables TRANSMIT_POWER_dBm and CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB referring to the tx power/gain of the nRF5340 and the nRF21540 respectively and do they have to be configured separately?
    •  The project builds but we are getting the error "Set Tx power err: -5 reason 0x00". We previously had trouble configuring the tx power of the nRF5340 using the zephyr controller and had to use the soft device controller, is this error related?

    Many thanks,

    Matt

  • Hello Matt,

    I am adding here the complete project of this application. You can control the external FEM with GPIOs which is supported. I assume LNA is fixed or not supported so, has set this RX gain zero like this CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0. Power amplifier gain is supported which has 20 dbM value (CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20). 

    adv_nRF21540_20dBm.zip

    You can get the idea of overlay file and CMakeList.tst file from here. 

    Best Regards,

    Kazi Afroza Sultana

  • Hi Kazi,

    Thank you for the project files, we gave up using the nRF5340DK and nRF21540EK approach but got everything working using the nRF21540DK.

    Is there currently support for configuring the Rx gain and antenna port selection on the nRF21540DK?

    Many thanks,

    Matt

  • Hello Matt,

    RX gain is +13 dB and when you set the value zero in config (CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0) file you will get this. https://infocenter.nordicsemi.com/topic/ps_nrf21540/chapters/keyparameters/doc/electrical_specification.html?cp=7_0_0_6_1#unique_1296948405 

    Thanks.

    Best Regards,

    Kazi Afroza Sultana

Related