Hi,
I just noticed that there's another issue with my project after upgrading from SDK 2.3.0 to 3.1.1.
I am using the 802.15.4 radio for low level packet communications with nrf_802154_transmit_raw() to send packets. I overrode the weak definitions of nrf_802154_received_raw(), nrf_802154_transmitted_raw(), and nrf_802154_transmit_failed() to handle packet reception and TX completion. See attached radio_interface.c file.
After the upgrade I noticed that every time I transmit, I get a "Transmit failure" message in my log. So my call to nrf_802154_transmit_raw(txdata, NULL) is returning false every time. I confirmed that this was not happening before the SDK upgrade.
I am still getting calls to nrf_802154_transmitted_raw() for every attempted transmit, and I am generally not getting calls to nrf_802154_transmit_failed(). So it seems like maybe my transmits are working even though the transmit call returns a fail.
I just tried sending a reset command to one of my wireless nodes to see if transmit packets are actually working, and it does look like they are - though apparently something went off the rails when that device replied, as I got an "Illegal use of the EPSR" usage failure and my processor rebooted.
Note that this is on a Fanstel module with a FEM, so I'm using MPSL because I believe it's required for FEM control. I attached my prj.conf in case that's helpful.
I tried comparing my project to the only sample I can find that uses the raw interface, but I haven't found the problem yet: \ncs\v3.1.1\nrf\samples\peripheral\802154_phy_test\
Thanks,
Glen
Log snippet showing the usage fault:
U/A to transmit to 837632Transmit failure Forward Rx Data Data from 1067402[01:19:54.213,500] <err> os: ***** USAGE FAULT ***** [01:19:54.219,085] <err> os: Illegal use of the EPSR [01:19:54.224,945] <err> os: r0/a1: 0x00000000 r1/a2: 0x00000020 r2/a3: 0 x00000001 [01:19:54.233,612] <err> os: r3/a4: 0x00000000 r12/ip: 0x20003640 r14/lr: 0 x0001e455 [01:19:54.242,309] <err> os: xpsr: 0x00000000 [01:19:54.247,528] <err> os: Faulting instruction address (r15/pc): 0x0001e468 [01:19:54.255,432] <err> os: >>> ZEPHYR FATAL ERROR 35: Unknown error on CPU 0 [01:19:54.263,336] <err> os: Current thread: 0x20003870 (main) [01:19:54.269,836] <err> os: Halting system à*** Booting nRF Connect SDK v3.1.1-e2a97fe2578a *** *** Using Zephyr OS v4.1.99-ff8f0c579eeb ***
//============================================================================
// Title : radio_interface
// Desc : Nordic radio 802.15.4 interface functions
// 2022-8-5 Glen Created
//============================================================================
// Documentation on the 802.15.4 driver here:
// https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/nrfxlib/nrf_802154/README.html
//
// Sample code used for low level radio functions, rx pool, and how to receive
// are in the SDK here: \nRF_Connect\v2.0.0\nrf\samples\peripheral\802154_phy_test\src
//
//== Includes ================================================================
#include "radio_interface.h"
#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/printk.h>
#include <hal/nrf_radio.h>
#include <string.h>
#include <stdio.h>
#include "radio.h"
#include "iomapping.h"
//== Definitions and Types ===================================================
//#define NO_TRANSMIT_FCC_VERSION 1
#define RF_FCS_SIZE (2u)
#define POWER_OUTPUT_LEVEL_INTO_AMPLIFIER 0 // dBm
#define POWER_INCREASE_AMPLIFIER 22 // dBm
typedef uint16_t ptt_pkt_len_t;
struct rf_rx_pkt_s {
uint8_t *rf_buf; /**< pointer to buffer inside radio driver with a received packet */
uint8_t *data; /**< pointer to payload */
ptt_pkt_len_t length; /**< size of payload of received packet */
int8_t rssi; /**< RSSI */
uint8_t lqi; /**< LQI */
};
//== Global Variables ========================================================
static volatile bool m_tx_complete = true;
//== Function prototypes =====================================================
//============================================================================
//----------------------------------------------------------------------------
// Name : radio_interface_config
// Desc : Meant to reset the radio but there isn't an obvious nrf function to
// that and it might not even make sense for an on-processor radio
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
void radio_interface_config(void)
{
// Clear the TX in progress flag
m_tx_complete = true;
}
//----------------------------------------------------------------------------
// Name : radio_interface_receive
// Desc : Start the radio to receive packets
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
void radio_interface_receive(void)
{
nrf_802154_receive();
}
//----------------------------------------------------------------------------
// Name : radio_interface_init
// Desc : Configure the radio
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
int radio_interface_init(void)
{
/* nrf radio driver initialization */
nrf_802154_init();
uint8_t panId[] = { 0x00, 0x01 };
nrf_802154_pan_id_set(&panId[0]);
nrf_802154_channel_set(25);
nrf_802154_promiscuous_set(false);
return 0;
}
//----------------------------------------------------------------------------
// Name : radio_interface_channel_set
// Desc : Send the channel to the radio driver
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
void radio_interface_channel_set(uint8_t channel)
{
nrf_802154_channel_set(channel);
}
//----------------------------------------------------------------------------
// Name : nrf_802154_received_raw
// Desc : Received a packet from the nrf radio. Save off needed data and call
// rf_process_rx_packets to handle it
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
void nrf_802154_received_raw(uint8_t *data, int8_t power, uint8_t lqi)
{
struct rf_rx_pkt_s rx_pkt;
bool pkt_placed = false;
if (data == NULL)
{
return;
}
rx_pkt.rf_buf = data;
rx_pkt.data = &data[1];
rx_pkt.length = data[0] - RF_FCS_SIZE;
rx_pkt.lqi = lqi; // It looks like we don't need these ED conversions after all
pkt_placed = true;
// Convert the RSSI from dBm to a custom scale
rx_pkt.rssi = radio_interface_signal_strength_lookup(power);
radio_interrupt(true, false, rx_pkt.data, rx_pkt.length, rx_pkt.rssi, rx_pkt.lqi, 0);
nrf_802154_buffer_free_raw(rx_pkt.rf_buf);
}
//----------------------------------------------------------------------------
// Name : nrf_802154_transmitted_raw
// Desc : Override the WEAK defined library "tx done" function so that I can
// add a call to the radio_interrupt in radio.c for status tracking
// If ACK was requested for the transmitted frame, this function is
// called after a proper ACK is received. If ACK was not requested,
// this function is called just after transmission has ended.
// Ins : none
// Outs : none
//----------------------------------------------------------------------------
void nrf_802154_transmitted_raw(uint8_t * p_frame, const nrf_802154_transmit_done_metadata_t * p_metadata)
{
(void)p_frame;
uint8_t * p_ack = p_metadata->data.transmitted.p_ack;
if (p_ack != NULL)
{
nrf_802154_buffer_free_raw(p_ack);
}
radio_interrupt(false, true, NULL, 0, 0, 0, 0); // Call the radio TX complete interrupt, no failure
//printk("TXDONE m_tx_complete = true\r\n");
m_tx_complete = true;
}
//----------------------------------------------------------------------------
// Name : nrf_802154_transmit_failed
// Desc : Notifies that a frame was not transmitted due to a busy channel.
// Ins : p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not transmitted
// Ins : error Reason of the failure.
// Ins : p_metadata Pointer to a metadata structure describing frame passed in @p p_frame.
// Outs : none
//----------------------------------------------------------------------------
void nrf_802154_transmit_failed(uint8_t * p_frame, nrf_802154_tx_error_t error, const nrf_802154_transmit_done_metadata_t * p_metadata)
{
radio_interrupt(false, true, NULL, 0, 0, 0, 1); // Call the radio TX complete interrupt, with a failure
m_tx_complete = true;
//printk("TXFAIL m_tx_complete = true\r\n");
printk("\r\nrf_802154_transmit_failed\r\n");
}
//----------------------------------------------------------------------------
// Name : radio_interface_transmit_packet
// Desc : Send a packet out
// Ins : A pointer to the data to send
// Outs : none
//----------------------------------------------------------------------------
void radio_interface_transmit_packet(uint8_t *txdata)
{
bool txstatus;
// The library is aware of the gain added by the PA, so you have to set the final output
// power level you want, not just the level you want to go into the amplifier like it used to be
nrf_802154_tx_power_set(POWER_OUTPUT_LEVEL_INTO_AMPLIFIER + POWER_INCREASE_AMPLIFIER);
//printk("PRE-TX Set m_tx_complete false, Was %d\r\n", m_tx_complete);
m_tx_complete = false; // Set a flag that will be cleared when the transmission is either complete (plus acknowledgment) or it has failed
txstatus = nrf_802154_transmit_raw(txdata, NULL);
if (txstatus == false) // Failure to transmit
{
printk("\r\nTransmit failure\r\n");
}
}
//----------------------------------------------------------------------------
// Name : radio_interface_get_tx_busy
// Desc : Returns 1 if the radio has not yet completed its transmit (including receiving the hardware ACK if requested)
// Ins : none
// Outs : 1 for busy, 0 for not busy
//----------------------------------------------------------------------------
uint8_t radio_interface_get_tx_busy(void)
{
if (m_tx_complete == false)
{
return 1;
}
else
{
return 0;
}
}




