net: lib: openthread: Create API for RX frame handling

OpenThread received frame handling shall be done in the OpenThread
thread.
Created API to pass net packets to the proper thread and handle them
there.

Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
This commit is contained in:
Marek Porwisz 2020-03-27 14:49:40 +01:00 committed by Jukka Rissanen
commit 8f2bcee35b
2 changed files with 56 additions and 3 deletions

View file

@ -16,6 +16,7 @@
#include <stdint.h>
#include <openthread/instance.h>
#include <net/net_pkt.h>
/**
* This function initializes the alarm service used by OpenThread.
@ -75,4 +76,10 @@ void platformRandomInit(void);
*/
void platformShellInit(otInstance *aInstance);
/**
* Notify OpenThread task about new rx message.
*/
int notify_new_rx_frame(struct net_pkt *pkt);
#endif /* PLATFORM_POSIX_H_ */

View file

@ -45,7 +45,10 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
#define OT_WORKER_STACK_SIZE 512
#define OT_WORKER_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
#define OT_RX_MESSAGES 5
enum pending_events {
PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */
PENDING_EVENT_TX_STARTED, /* Radio has started transmitting */
PENDING_EVENT_TX_DONE, /* Radio transmission finished */
PENDING_EVENT_DETECT_ENERGY, /* Requested to start Energy Detection
@ -82,6 +85,8 @@ K_THREAD_STACK_DEFINE(ot_task_stack, OT_WORKER_STACK_SIZE);
static struct k_work_q ot_work_q;
static otError tx_result;
K_MSGQ_DEFINE(rx_pkt_queue, sizeof(struct net_pkt *), OT_RX_MESSAGES, 4);
static inline bool is_pending_event_set(enum pending_events event)
{
return atomic_test_bit(pending_events, event);
@ -248,11 +253,9 @@ static inline void handle_tx_done(otInstance *aInstance)
{
if (IS_ENABLED(OPENTHREAD_ENABLE_DIAG) && otPlatDiagModeGet()) {
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame,
tx_result);
tx_result);
} else {
if (sTransmitFrame.mPsdu[0] & IEEE802154_AR_FLAG_SET) {
if (ack_frame.mLength == 0) {
LOG_DBG("No ACK received.");
otPlatRadioTxDone(aInstance, &sTransmitFrame,
@ -269,6 +272,40 @@ static inline void handle_tx_done(otInstance *aInstance)
}
}
static void openthread_handle_received_frame(otInstance *instance,
struct net_pkt *pkt)
{
otRadioFrame recv_frame;
recv_frame.mPsdu = net_buf_frag_last(pkt->buffer)->data;
/* Length inc. CRC. */
recv_frame.mLength = net_buf_frags_len(pkt->buffer);
recv_frame.mChannel = platformRadioChannelGet(instance);
recv_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt);
recv_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt);
if (IS_ENABLED(OPENTHREAD_ENABLE_DIAG) && otPlatDiagModeGet()) {
otPlatDiagRadioReceiveDone(instance,
&recv_frame, OT_ERROR_NONE);
} else {
otPlatRadioReceiveDone(instance,
&recv_frame, OT_ERROR_NONE);
}
net_pkt_unref(pkt);
}
int notify_new_rx_frame(struct net_pkt *pkt)
{
int err = -ENOBUFS;
if (k_msgq_put(&rx_pkt_queue, &pkt, K_FOREVER) == 0) {
err = 0;
set_pending_event(PENDING_EVENT_FRAME_RECEIVED);
}
return err;
}
static int run_tx_task(otInstance *aInstance)
{
@ -291,6 +328,15 @@ void platformRadioProcess(otInstance *aInstance)
{
bool event_pending = false;
if (is_pending_event_set(PENDING_EVENT_FRAME_RECEIVED)) {
struct net_pkt *rx_pkt;
reset_pending_event(PENDING_EVENT_FRAME_RECEIVED);
while (k_msgq_get(&rx_pkt_queue, &rx_pkt, K_NO_WAIT) == 0) {
openthread_handle_received_frame(aInstance, rx_pkt);
}
}
if (is_pending_event_set(PENDING_EVENT_TX_STARTED)) {
reset_pending_event(PENDING_EVENT_TX_STARTED);
otPlatRadioTxStarted(aInstance, &sTransmitFrame);