Hello,
we started using zephyr OS for our firmware projects. To implement a propriety protocol on top of IEEE802.15.4 I use the radio with CONFIG_IEEE802154_RAW_MODE=y in the prj.conf. For a first test I use this function to send a frame.
void send_frame()
{
struct net_pkt *pkt;
struct net_buf *buf;
uint8_t data[14];
static uint8_t seq_num = 0;
pkt = net_pkt_alloc(K_NO_WAIT);
if (!pkt) {
LOG_INF("No pkt available");
return;
}
net_pkt_alloc_buffer(pkt, 14, 0, K_NO_WAIT);
buf = net_buf_frag_last(pkt->buffer);
/* FCF */
data[0] = 0x23;
data[1] = 0xd0;
/* Sequence Number */
data[2] = seq_num++;
/* PAN ID */
data[3] = 0xcd;
data[4] = 0xab;
/* MAC Address */
memcpy(&data[5], mac_addr, 8);
/* Command Identifier */
data[13] = 0x00;
buf->data = data;
buf->len = 14;
int ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT, pkt, buf);
switch (ret) {
case -ENOMSG:
LOG_INF("TX - no ACK received - stoping radio");
radio_api->stop(ieee802154_dev);
break;
case -EIO:
LOG_INF("TX - aborted or timeslot denied/ended");
break;
case -ENOBUFS:
LOG_INF("TX - no free buffers");
break;
case 0:
LOG_INF("TX - OK");
break;
default:
LOG_INF("TX - unknown error %d", ret);
}
net_pkt_unref(pkt);
}
If I got it right, the radio_api->tx() call takes a semaphore and doesn't return until on of the tramsit callbacks is called by the radio irq. In reality tx() returns immediately with the tx_result of the previous package and the call of radio_api->stop() kills the radio before the actual frame could be transmitted. I digged into the code and found that k_sem_take() in nrf5_tx() returns -EAGAIN, signaling a timeout what is strange as K_FOREVER should be pretty long ;).
Registering an event handler with radio_api->configure(ieee802154_dev, IEEE802154_CONFIG_EVENT_HANDLER, ...) doesn't lead to a solution as there is no event for TX_FINISHED or TX_FAILED.
Is there anything I need to do to make tx() wait for the actual package to get transfered or is this caused by a bug in the ieee driver or semaphore handling?