Hello, I have 2 PCBs for drone communication using nRF52820 and nRF21540 FEM module. I'm using the ESB protocol to communicate via radio. There are ready-made esb_prx and esb_ptx codes provided by nRF Connect. Additionally, my PCB has an external 32MHz clock. I'm providing all my code below: DTS, prjconfig, main. Currently, I cannot establish communication.What is the problem?
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#if defined(NRF54L15_XXAA)
#include <hal/nrf_clock.h>
#endif /* defined(NRF54L15_XXAA) */
#include <zephyr/drivers/gpio.h>
#include <zephyr/irq.h>
#include <zephyr/logging/log.h>
#include <nrf.h>
#include <esb.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <dk_buttons_and_leds.h>
#if defined(CONFIG_CLOCK_CONTROL_NRF2)
#include <hal/nrf_lrcconf.h>
#endif
LOG_MODULE_REGISTER(esb_ptx, CONFIG_ESB_PTX_APP_LOG_LEVEL);
static bool ready = true;
static struct esb_payload rx_payload;
static struct esb_payload tx_payload = ESB_CREATE_PAYLOAD(0,
0x01, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
#define _RADIO_SHORTS_COMMON \
(RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \
RADIO_SHORTS_ADDRESS_RSSISTART_Msk | \
RADIO_SHORTS_DISABLED_RSSISTOP_Msk)
void event_handler(struct esb_evt const *event)
{
ready = true;
switch (event->evt_id) {
case ESB_EVENT_TX_SUCCESS:
LOG_DBG("TX SUCCESS EVENT");
break;
case ESB_EVENT_TX_FAILED:
LOG_DBG("TX FAILED EVENT");
break;
case ESB_EVENT_RX_RECEIVED:
while (esb_read_rx_payload(&rx_payload) == 0) {
LOG_DBG("Packet received, len %d : "
"0x%02x, 0x%02x, 0x%02x, 0x%02x, "
"0x%02x, 0x%02x, 0x%02x, 0x%02x",
rx_payload.length, rx_payload.data[0],
rx_payload.data[1], rx_payload.data[2],
rx_payload.data[3], rx_payload.data[4],
rx_payload.data[5], rx_payload.data[6],
rx_payload.data[7]);
}
break;
}
}
#if defined(CONFIG_CLOCK_CONTROL_NRF)
int clocks_start(void)
{
int err;
int res;
struct onoff_manager *clk_mgr;
struct onoff_client clk_cli;
clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!clk_mgr) {
LOG_ERR("Unable to get the Clock manager");
return -ENXIO;
}
sys_notify_init_spinwait(&clk_cli.notify);
err = onoff_request(clk_mgr, &clk_cli);
if (err < 0) {
LOG_ERR("Clock request failed: %d", err);
return err;
}
do {
err = sys_notify_fetch_result(&clk_cli.notify, &res);
if (!err && res) {
LOG_ERR("Clock could not be started: %d", res);
return res;
}
} while (err);
#if defined(NRF54L15_XXAA)
/* MLTPAN-20 */
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_PLLSTART);
#endif /* defined(NRF54L15_XXAA) */
LOG_DBG("HF clock started");
return 0;
}
#elif defined(CONFIG_CLOCK_CONTROL_NRF2)
int clocks_start(void)
{
int err;
int res;
const struct device *radio_clk_dev =
DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(DT_NODELABEL(radio)));
struct onoff_client radio_cli;
/** Keep radio domain powered all the time to reduce latency. */
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_1, true);
sys_notify_init_spinwait(&radio_cli.notify);
err = nrf_clock_control_request(radio_clk_dev, NULL, &radio_cli);
do {
err = sys_notify_fetch_result(&radio_cli.notify, &res);
if (!err && res) {
LOG_ERR("Clock could not be started: %d", res);
return res;
}
} while (err == -EAGAIN);
nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true);
nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0);
LOG_DBG("HF clock started");
return 0;
}
#else
BUILD_ASSERT(false, "No Clock Control driver");
#endif /* defined(CONFIG_CLOCK_CONTROL_NRF2) */
int esb_initialize(void)
{
int err;
/* These are arbitrary default addresses. In end user products
* different addresses should be used for each set of devices.
*/
uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8};
struct esb_config config = ESB_DEFAULT_CONFIG;
config.protocol = ESB_PROTOCOL_ESB_DPL;
config.retransmit_delay = 600;
config.bitrate = ESB_BITRATE_2MBPS;
config.event_handler = event_handler;
config.mode = ESB_MODE_PTX;
config.selective_auto_ack = true;
if (IS_ENABLED(CONFIG_ESB_FAST_SWITCHING)) {
config.use_fast_ramp_up = true;
}
err = esb_init(&config);
if (err) {
return err;
}
err = esb_set_base_address_0(base_addr_0);
if (err) {
return err;
}
err = esb_set_base_address_1(base_addr_1);
if (err) {
return err;
}
err = esb_set_prefixes(addr_prefix, ARRAY_SIZE(addr_prefix));
if (err) {
return err;
}
return 0;
}
static void leds_update(uint8_t value)
{
uint32_t leds_mask =
(!(value % 8 > 0 && value % 8 <= 4) ? DK_LED1_MSK : 0) |
(!(value % 8 > 1 && value % 8 <= 5) ? DK_LED2_MSK : 0) |
(!(value % 8 > 2 && value % 8 <= 6) ? DK_LED3_MSK : 0) |
(!(value % 8 > 3) ? DK_LED4_MSK : 0);
dk_set_leds(leds_mask);
}
int main(void)
{
int err;
LOG_INF("Enhanced ShockBurst ptx sample");
err = clocks_start();
if (err) {
return 0;
}
err = dk_leds_init();
if (err) {
LOG_ERR("LEDs initialization failed, err %d", err);
return 0;
}
err = esb_initialize();
if (err) {
LOG_ERR("ESB initialization failed, err %d", err);
return 0;
}
LOG_INF("Initialization complete");
LOG_INF("Sending test packet");
tx_payload.noack = false;
while (1) {
if (ready) {
ready = false;
esb_flush_tx();
leds_update(tx_payload.data[1]);
err = esb_write_payload(&tx_payload);
if (err) {
LOG_ERR("Payload write failed, err %d", err);
}
tx_payload.data[1]++;
}
k_sleep(K_MSEC(100));
}
}/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#if defined(NRF54L15_XXAA)
#include <hal/nrf_clock.h>
#endif /* defined(NRF54L15_XXAA) */
#include <zephyr/drivers/gpio.h>
#include <zephyr/irq.h>
#include <zephyr/logging/log.h>
#include <nrf.h>
#include <esb.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <dk_buttons_and_leds.h>
#if defined(CONFIG_CLOCK_CONTROL_NRF2)
#include <hal/nrf_lrcconf.h>
#endif
LOG_MODULE_REGISTER(esb_prx, CONFIG_ESB_PRX_APP_LOG_LEVEL);
static struct esb_payload rx_payload;
static struct esb_payload tx_payload = ESB_CREATE_PAYLOAD(0,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17);
static void leds_update(uint8_t value)
{
uint32_t leds_mask =
(!(value % 8 > 0 && value % 8 <= 4) ? DK_LED1_MSK : 0) |
(!(value % 8 > 1 && value % 8 <= 5) ? DK_LED2_MSK : 0) |
(!(value % 8 > 2 && value % 8 <= 6) ? DK_LED3_MSK : 0) |
(!(value % 8 > 3) ? DK_LED4_MSK : 0);
dk_set_leds(leds_mask);
}
void event_handler(struct esb_evt const *event)
{
switch (event->evt_id) {
case ESB_EVENT_TX_SUCCESS:
LOG_DBG("TX SUCCESS EVENT");
break;
case ESB_EVENT_TX_FAILED:
LOG_DBG("TX FAILED EVENT");
break;
case ESB_EVENT_RX_RECEIVED:
if (esb_read_rx_payload(&rx_payload) == 0) {
LOG_DBG("Packet received, len %d : "
"0x%02x, 0x%02x, 0x%02x, 0x%02x, "
"0x%02x, 0x%02x, 0x%02x, 0x%02x",
rx_payload.length, rx_payload.data[0],
rx_payload.data[1], rx_payload.data[2],
rx_payload.data[3], rx_payload.data[4],
rx_payload.data[5], rx_payload.data[6],
rx_payload.data[7]);
leds_update(rx_payload.data[1]);
} else {
LOG_ERR("Error while reading rx packet");
}
break;
}
}
#if defined(CONFIG_CLOCK_CONTROL_NRF)
int clocks_start(void)
{
int err;
int res;
struct onoff_manager *clk_mgr;
struct onoff_client clk_cli;
clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!clk_mgr) {
LOG_ERR("Unable to get the Clock manager");
return -ENXIO;
}
sys_notify_init_spinwait(&clk_cli.notify);
err = onoff_request(clk_mgr, &clk_cli);
if (err < 0) {
LOG_ERR("Clock request failed: %d", err);
return err;
}
do {
err = sys_notify_fetch_result(&clk_cli.notify, &res);
if (!err && res) {
LOG_ERR("Clock could not be started: %d", res);
return res;
}
} while (err);
#if defined(NRF54L15_XXAA)
/* MLTPAN-20 */
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_PLLSTART);
#endif /* defined(NRF54L15_XXAA) */
LOG_DBG("HF clock started");
return 0;
}
#elif defined(CONFIG_CLOCK_CONTROL_NRF2)
int clocks_start(void)
{
int err;
int res;
const struct device *radio_clk_dev =
DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(DT_NODELABEL(radio)));
struct onoff_client radio_cli;
/** Keep radio domain powered all the time to reduce latency. */
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_1, true);
sys_notify_init_spinwait(&radio_cli.notify);
err = nrf_clock_control_request(radio_clk_dev, NULL, &radio_cli);
do {
err = sys_notify_fetch_result(&radio_cli.notify, &res);
if (!err && res) {
LOG_ERR("Clock could not be started: %d", res);
return res;
}
} while (err == -EAGAIN);
nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true);
nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0);
LOG_DBG("HF clock started");
return 0;
}
#else
BUILD_ASSERT(false, "No Clock Control driver");
#endif /* defined(CONFIG_CLOCK_CONTROL_NRF2) */
int esb_initialize(void)
{
int err;
/* These are arbitrary default addresses. In end user products
* different addresses should be used for each set of devices.
*/
uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8};
struct esb_config config = ESB_DEFAULT_CONFIG;
config.protocol = ESB_PROTOCOL_ESB_DPL;
config.bitrate = ESB_BITRATE_2MBPS;
config.mode = ESB_MODE_PRX;
config.event_handler = event_handler;
config.selective_auto_ack = true;
if (IS_ENABLED(CONFIG_ESB_FAST_SWITCHING)) {
config.use_fast_ramp_up = true;
}
err = esb_init(&config);
if (err) {
return err;
}
err = esb_set_base_address_0(base_addr_0);
if (err) {
return err;
}
err = esb_set_base_address_1(base_addr_1);
if (err) {
return err;
}
err = esb_set_prefixes(addr_prefix, ARRAY_SIZE(addr_prefix));
if (err) {
return err;
}
return 0;
}
int main(void)
{
int err;
LOG_INF("Enhanced ShockBurst prx sample");
err = clocks_start();
if (err) {
return 0;
}
err = dk_leds_init();
if (err) {
LOG_ERR("LEDs initialization failed, err %d", err);
return 0;
}
err = esb_initialize();
if (err) {
LOG_ERR("ESB initialization failed, err %d", err);
return 0;
}
LOG_INF("Initialization complete");
err = esb_write_payload(&tx_payload);
if (err) {
LOG_ERR("Write payload, err %d", err);
return 0;
}
LOG_INF("Setting up for packet receiption");
err = esb_start_rx();
if (err) {
LOG_ERR("RX setup failed, err %d", err);
return 0;
}
/* return to idle thread */
return 0;
}
/dts-v1/;
#include <nordic/nrf52820_qdaa.dtsi>
#include "TST-pinctrl.dtsi"
/ {
model = "testing";
compatible = "BY,TST";
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,console = &cdc_acm_uart0;
zephyr,shell-uart = &cdc_acm_uart0;
zephyr,uart-mcumgr = &cdc_acm_uart0;
};
nrf_radio_fem: nrf21540_fem {
compatible = "nordic,nrf21540-fem";
tx-en-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
rx-en-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
pdn-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
mode-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
spi-if = <&nrf_radio_fem_spi>;
supply-voltage-mv = <3300>;
tx-en-settle-time-us = <13>;
rx-en-settle-time-us = <13>;
pdn-settle-time-us = <18>;
trx-hold-time-us = <5>;
};
leds {
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
label = "Green LED 0";
};
led1: led_1 {
gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
label = "Green LED 1";
};
};
aliases {
led0 = &led0;
led1 = &led1;
};
};
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
boot_partition: partition@0 {
label = "mcuboot";
reg = <0x00000000 DT_SIZE_K(48)>;
};
slot0_partition: partition@c000 {
label = "image-0";
reg = <0x0000c000 DT_SIZE_K(92)>;
};
slot1_partition: partition@23000 {
label = "image-1";
reg = <0x00023000 DT_SIZE_K(92)>;
};
storage_partition: partition@3a000 {
label = "storage";
reg = <0x0003a000 DT_SIZE_K(24)>;
};
};
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&clock {
status = "okay";
};
zephyr_udc0: &usbd {
compatible = "nordic,nrf-usbd";
status = "okay";
};
&usbd {
cdc_acm_uart0: cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
};
&spi1 {
compatible = "nordic,nrf-spi";
status = "okay";
pinctrl-0 = <&spi1_default>;
pinctrl-1 = <&spi1_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
nrf_radio_fem_spi: nrf21540_fem_spi@0 {
compatible = "nordic,nrf21540-fem-spi";
status = "okay";
reg = <0>;
spi-max-frequency = <8000000>;
spi-cpol;
spi-cpha;
};
};
&radio {
fem = <&nrf_radio_fem>;
status = "okay";
}; # # Copyright (c) 2019 Nordic Semiconductor ASA # # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # CONFIG_NCS_SAMPLES_DEFAULTS=y CONFIG_ESB=y CONFIG_DK_LIBRARY=y CONFIG_CLOCK_CONTROL=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n CONFIG_MPSL=y CONFIG_MPSL_FEM=y CONFIG_MPSL_FEM_NRF21540_GPIO_SPI=y CONFIG_USE_SEGGER_RTT=y CONFIG_RTT_CONSOLE=y CONFIG_LOG=y CONFIG_LOG_BACKEND_RTT=y CONFIG_LOG_DEFAULT_LEVEL=2