Igor Stepura / kw41z-rf-driver Featured

ARM mbed Nanostack RF driver for NXP KW41Z 802.15.4 wireless MCU

This driver is used with 6LoWPAN stack.

Code far from being stable yet, but basic functionality seems to be working. Two FRDM-KW41Z boards running code build from mbed-os-example-mesh-minimal and nanostack-border-router are able to build mesh.

Main repository is at https://github.com/istepura/kw41z-rf-driver

Files at this revision

API Documentation at this revision

Comitter:
Igor Stepura
Date:
Sat Jul 22 13:22:46 2017 -0400
Parent:
1:4e0ed8184753
Child:
3:9f6427e86978
Commit message:
Code cleanup

Changed in this revision

README.md Show annotated file Show diff for this revision Revisions of this file
source/NanostackRfPhyKw41z.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/README.md	Fri Jul 21 20:56:10 2017 -0400
+++ b/README.md	Sat Jul 22 13:22:46 2017 -0400
@@ -1,5 +1,5 @@
 # kw41z-rf-driver
-ARM mbed Nanostack RF driver for NXP KW4xZ 802.15.4 wireless MCU
+ARM mbed Nanostack RF driver for NXP KW41Z/21Z 802.15.4 wireless MCU
 
 This driver is used with 6LoWPAN stack. 
 
--- a/source/NanostackRfPhyKw41z.cpp	Fri Jul 21 20:56:10 2017 -0400
+++ b/source/NanostackRfPhyKw41z.cpp	Sat Jul 22 13:22:46 2017 -0400
@@ -1,6 +1,9 @@
 /*
    Copyright 2017, Igor Stepura <igor.stepura@gmail.com>
 
+   Inspired by mcr20a-rf-driver by Andrei Kovacs <Andrei.Kovacs@freescale.com>
+   and NXP KW41Z 802.15.4 PHY implementation
+
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
@@ -34,12 +37,8 @@
 }phySeqState_t;
 
 typedef enum{
-    gPhyPwrIdle_c,
-    gPhyPwrAutodoze_c,
-    gPhyPwrDoze_c,
-    gPhyPwrHibernate_c,
+    gPhyPwrRun_c,
     gPhyPwrDSM_c,
-    gPhyPwrReset_c
 }phyPwrMode_t;
 
 /* PHY channel state */
@@ -62,11 +61,7 @@
   gInvalidCcaType_c    /* illegal type */
 };
 
-enum {
-  gNormalCca_c,
-  gContinuousCca_c
-};
-static phyPwrMode_t mPhyPwrState = gPhyPwrIdle_c;
+static phyPwrMode_t mPhyPwrState = gPhyPwrRun_c;
 #ifndef MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS
 #define MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS  {1, 2, 3, 4, 5, 6, 7, 8}
 #endif
@@ -77,7 +72,11 @@
 
 static uint8_t MAC_address[8] = MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS;
 static NanostackRfPhyKw41z *rf = NULL;
+
+#ifdef MBED_CONF_RTOS_PRESENT
 static Thread irq_thread(osPriorityRealtime, 1024);
+#endif
+
 static phy_device_driver_s device_driver;
 static int8_t  rf_radio_driver_id = -1;
 static uint8_t  mac_tx_handle = 0;
@@ -268,10 +267,7 @@
     /* Set Rx watermark level */
     ZLL->RX_WTR_MARK = 0;
 
-    /*Read eui64*/
-    //rf_set_address(MAC_address);
     rf_channel_set(MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL);
-    /*Start receiver*/
     
     /* DSM settings */
     phyReg = (RSIM->RF_OSC_CTRL & RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_MASK) >> 
@@ -325,7 +321,7 @@
     {
         return;
     }
-    rf_set_power_state(gPhyPwrAutodoze_c);
+    rf_set_power_state(gPhyPwrRun_c);
 
     /* Ensure that no spurious interrupts are raised, but do not change TMR1 and TMR4 IRQ status */
     irqSts = ZLL->IRQSTS;
@@ -334,9 +330,7 @@
     ZLL->IRQSTS = irqSts;
 
     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
-    /* Start the RX sequence */
     ZLL->PHY_CTRL |= gRX_c ;
-    /* unmask SEQ interrupt */
     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
 }
 
@@ -408,7 +402,7 @@
     need_ack = (*data_ptr & 0x20) == 0x20;
 
     /* Set XCVR power state in run mode */
-    rf_set_power_state(gPhyPwrAutodoze_c);
+    rf_set_power_state(gPhyPwrRun_c);
 
     uint8_t xcvseq;    
     if(need_ack)
@@ -517,13 +511,7 @@
 static uint32_t mPhyDSMDuration = 0xFFFFF0;
 static void rf_set_power_state(phyPwrMode_t newState)
 {
-    /* Parameter validation */
-    if( newState > gPhyPwrReset_c )
-    {
-        return;
-    }
-    /* Check if the new power state = old power state */
-    else if( newState == mPhyPwrState )
+    if( newState == mPhyPwrState )
     {
         return;
     }
@@ -531,7 +519,7 @@
     {
         switch(newState)
         {
-            case gPhyPwrIdle_c:
+            case gPhyPwrRun_c:
                 /* Set XCVR in run mode if not allready */
                 if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK)
                 {
@@ -553,11 +541,6 @@
                         RSIM_DSM_CONTROL_ZIG_SYSCLK_INTERRUPT_EN_MASK;
                 }
                 break;
-
-            default:
-                /* do not change current state */
-                newState = mPhyPwrState;
-                break;
         }
 
         mPhyPwrState = newState;
@@ -566,15 +549,12 @@
 
 static void rf_off(void)
 {
-    /* Abort any ongoing sequences */
     rf_abort();
-    /* Set XCVR in a low power state */
-    rf_set_power_state(gPhyPwrHibernate_c);
+    rf_set_power_state(gPhyPwrDSM_c);
 }
 
 static void rf_shutdown(void)
 {
-    /*Call RF OFF*/
     rf_off();
 }
 
@@ -651,29 +631,34 @@
  *
  * \return none
  */
-static volatile uint8_t gIrqStatus = 0;
+static volatile uint32_t gIrqStatus = 0;
 static void PHY_InterruptHandler(void)
 {
     gIrqStatus = ZLL->IRQSTS;
     ZLL->IRQSTS = gIrqStatus;
+#ifdef MBED_CONF_RTOS_PRESENT
     irq_thread.signal_set(1);
+#else
+    handle_interrupt(gIrqStatus);
+#endif
+
 }
 
 static void PHY_InterruptThread(void)
 {
+#ifdef MBED_CONF_RTOS_PRESENT
     for (;;) {
         osEvent event = irq_thread.signal_wait(0);
         if (event.status != osEventSignal) {
             continue;
         }
-       // rf_if_lock();        
         handle_interrupt(gIrqStatus);
-       // rf_if_unlock();
 
     }
+#endif
 }
 
-static void PhyIsrSeqCleanup(void)
+static inline void rf_clean_seq_isr(void)
 {
     uint32_t irqStatus;
 
@@ -698,7 +683,7 @@
     ZLL->IRQSTS = irqStatus;
 }
 
-static void PhyIsrTimeoutCleanup(void)
+static inline void rf_clean_timeout_isr(void)
 {
     uint32_t irqStatus;
 
@@ -777,7 +762,7 @@
 
 static void handle_interrupt(uint32_t irqStatus)
 {
- /* RSIM Wake-up IRQ */
+     /* RSIM Wake-up IRQ */
     if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_SYSCLK_REQ_INT_MASK)
     {
         RSIM->DSM_CONTROL = RSIM->DSM_CONTROL;
@@ -800,19 +785,19 @@
     {
         if( irqStatus & ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK )
         {
-            PhyIsrSeqCleanup();
+            rf_clean_seq_isr();
         }
         /* TMR3 timeout, the autosequence has been aborted due to TMR3 timeout */
         else if( (irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) &&
             (!(irqStatus & ZLL_IRQSTS_RXIRQ_MASK)) &&
             (gTX_c != xcvseqCopy) )
         {
-            PhyIsrTimeoutCleanup();
+            rf_clean_timeout_isr();
             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
         }
         else
         {
-            PhyIsrSeqCleanup();
+            rf_clean_seq_isr();
             switch(xcvseqCopy)
             {
                 case gTX_c:
@@ -865,11 +850,6 @@
                         }
                     }
                     break;
-
-                case gCCCA_c:
-                    //Radio_Phy_PlmeCcaConfirm(gPhyChannelIdle_c, mPhyInstance);
-                    break;
-
                 default:
                     break;
             }
@@ -878,25 +858,13 @@
     /* Timers interrupt */
     else
     {
-        /* Timer 2 Compare Match */
-        if( (irqStatus & ZLL_IRQSTS_TMR2IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR2MSK_MASK)) )
-        {
-            if( gIdle_c != xcvseqCopy )
-            {
-                //Radio_Phy_TimeStartEventIndication(mPhyInstance);
-            }
-        }
-
         /* Timer 3 Compare Match */
         if( (irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR3MSK_MASK)) )
         {
 
-            /* Ensure that we're not issuing TimeoutIndication while the Automated sequence is still in progress */
-            /* TMR3 can expire during R-T turnaround for example, case in which the sequence is not interrupted */
             if( gIdle_c == xcvseqCopy )
             {
-                //device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
-                //Radio_Phy_TimeRxTimeoutIndication(mPhyInstance);
+                device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
             }
         }
 
@@ -930,7 +898,6 @@
         }
         else
         {
-            // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
         }
     }
@@ -961,7 +928,9 @@
         return -1;
     }
 
+#ifdef MBED_CONF_RTOS_PRESENT
     irq_thread.start(mbed::callback(PHY_InterruptThread));
+#endif
 
     int8_t radio_id = rf_device_register();
     if (radio_id < 0) {