You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/06/28 12:03:14 UTC

[incubator-nuttx] 01/02: risc-v/bl602: Support AP and STA as independent network interface device

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit cd5065058354f00953cce679661b0eb30feafb30
Author: Virus.V <vi...@live.com>
AuthorDate: Mon Jun 28 09:45:46 2021 +0800

    risc-v/bl602: Support AP and STA as independent network interface device
    
    Signed-off-by: Virus.V <vi...@live.com>
---
 arch/risc-v/src/bl602/Kconfig                    |   7 +-
 arch/risc-v/src/bl602/Make.defs                  |  13 +-
 arch/risc-v/src/bl602/bl602_netdev.c             | 284 +++++++++++++++++------
 arch/risc-v/src/bl602/bl602_netdev.h             |   3 +-
 boards/risc-v/bl602/bl602evb/scripts/ld.script   |  15 ++
 boards/risc-v/bl602/bl602evb/src/bl602_bringup.c |   4 +-
 6 files changed, 241 insertions(+), 85 deletions(-)

diff --git a/arch/risc-v/src/bl602/Kconfig b/arch/risc-v/src/bl602/Kconfig
index 5d97add..e813dbf 100644
--- a/arch/risc-v/src/bl602/Kconfig
+++ b/arch/risc-v/src/bl602/Kconfig
@@ -92,11 +92,14 @@ config BL602_WIRELESS_CONTRY_CODE
 	depends on BL602_WIRELESS
 	default "CN"
 
+config BL602_NET_MULTI_INTERFACE
+	bool "STA and AP as independent interfaces"
+	depends on BL602_WIRELESS
+	default n
+
 config BL602_BLE_CONTROLLER
 	bool "ble controller support"
 	default n
-	depends on PSEUDOTERM
-	depends on PSEUDOTERM_SUSV1
 	depends on !DISABLE_MQUEUE
 	depends on SCHED_HPWORK
 	depends on BL602_WIRELESS
diff --git a/arch/risc-v/src/bl602/Make.defs b/arch/risc-v/src/bl602/Make.defs
index 213d960..f5abde8 100644
--- a/arch/risc-v/src/bl602/Make.defs
+++ b/arch/risc-v/src/bl602/Make.defs
@@ -83,10 +83,9 @@ CHIP_CSRCS += bl602_glb.c bl602_gpio.c bl602_hbn.c bl602_systemreset.c
 
 ifeq ($(CONFIG_BL602_WIRELESS),y)
 WIRELESS_DRV_UNPACK  = bl_blob
-WIRELESS_DRV_VERSION = v1.6.19
-WIRELESS_DRV_ID      = dev_irq
-WIRELESS_DRV_ZIP     = $(WIRELESS_DRV_ID).zip
-WIRELESS_DRV_URL     = https://github.com/bouffalolab/bl_blob/archive
+WIRELESS_DRV_VERSION = 1.6.20
+WIRELESS_DRV_ZIP     = v$(WIRELESS_DRV_VERSION).zip
+WIRELESS_DRV_URL     = https://github.com/bouffalolab/bl_blob/archive/refs/heads
 
 $(WIRELESS_DRV_ZIP):
 	$(Q) echo "Downloading: BL602 Wireless Drivers"
@@ -96,7 +95,7 @@ chip/$(WIRELESS_DRV_UNPACK): $(WIRELESS_DRV_ZIP)
 	$(Q) echo "Unpacking: BL602 Wireless Drivers"
 	$(Q) mkdir -p chip/$(WIRELESS_DRV_UNPACK)
 	$(Q) unzip -oqq chip/$(WIRELESS_DRV_ZIP) -d chip/
-	$(Q) mv chip/$(WIRELESS_DRV_UNPACK)-$(WIRELESS_DRV_ID)/* chip/$(WIRELESS_DRV_UNPACK)
+	$(Q) mv chip/$(WIRELESS_DRV_UNPACK)-$(WIRELESS_DRV_VERSION)/* chip/$(WIRELESS_DRV_UNPACK)
 	$(Q) touch chip/$(WIRELESS_DRV_UNPACK)
 
 context:: chip/$(WIRELESS_DRV_UNPACK)
@@ -105,10 +104,10 @@ clean_context::
 	$(call DELFILE, chip/$(WIRELESS_DRV_ZIP))
 	$(call DELDIR, chip/$(WIRELESS_DRV_UNPACK))
 
-INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(WIRELESS_DRV_UNPACK)$(DELIM)includes$(DELIM)$(WIRELESS_DRV_VERSION)$(DELIM)BL602$(DELIM)nuttx)
+INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(WIRELESS_DRV_UNPACK)$(DELIM)includes$(DELIM)BL602$(DELIM)nuttx)
 CHIP_CSRCS += bl602_netdev.c
 
-EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(WIRELESS_DRV_UNPACK)$(DELIM)libs$(DELIM)$(WIRELESS_DRV_VERSION)$(DELIM)BL602$(DELIM)nuttx
+EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(WIRELESS_DRV_UNPACK)$(DELIM)libs$(DELIM)BL602$(DELIM)nuttx
 EXTRA_LIBS += -lbl602_wifi -lblecontroller
 
 # Due to some Wi-Fi related libraries, the option is need to avoid linking too much
diff --git a/arch/risc-v/src/bl602/bl602_netdev.c b/arch/risc-v/src/bl602/bl602_netdev.c
index 6736313..5804c4c 100644
--- a/arch/risc-v/src/bl602/bl602_netdev.c
+++ b/arch/risc-v/src/bl602/bl602_netdev.c
@@ -90,12 +90,14 @@
 
 #define ETHWORK HPWORK
 
-/* CONFIG_BL602_NET_NINTERFACES determines the number of physical interfaces
+/* BL602_NET_NINTERFACES determines the number of physical interfaces
  * that will be supported.
  */
 
-#ifndef CONFIG_BL602_NET_NINTERFACES
-#define CONFIG_BL602_NET_NINTERFACES 1
+#ifndef CONFIG_BL602_NET_MULTI_INTERFACE
+#define BL602_NET_NINTERFACES 1
+#else
+#define BL602_NET_NINTERFACES 2
 #endif
 
 /* TX poll delay = 1 seconds.
@@ -150,7 +152,6 @@ struct bl602_net_driver_s
    */
 
   unsigned int current_mode : 2;    /* current mode */
-  unsigned int scan_result_len : 6; /* max 64 */
   unsigned int push_cnt : 4;        /* max 16 */
   unsigned int prev_connectd : 1;   /* mark of prev connection status */
 
@@ -189,6 +190,7 @@ typedef uint8_t (*tx_buff_t)[BL602_NET_TXBUFF_SIZE];
 struct rx_pending_item_s
 {
   struct list_node node;
+  struct bl602_net_driver_s *priv; /* Which interface should to deliver */
   uint8_t *        data;
   int              len;
 };
@@ -199,7 +201,7 @@ struct rx_pending_item_s
 
 /* Driver state structure */
 
-struct bl602_net_driver_s g_bl602_net[CONFIG_BL602_NET_NINTERFACES];
+struct bl602_net_driver_s g_bl602_net[BL602_NET_NINTERFACES];
 
 static struct tx_buf_ind_s g_tx_buf_indicator =
   BITSET_T_INITIALIZER((1 << BL602_NET_TXBUFF_NUM) - 1);
@@ -214,11 +216,21 @@ static sem_t g_wifi_connect_sem;
 
 static struct list_node g_rx_pending;
 
+/* Firmware default config */
+
 static wifi_conf_t g_conf =
 {
   .country_code = CONFIG_BL602_WIRELESS_CONTRY_CODE,
 };
 
+/* Global state */
+
+static struct
+{
+  uint32_t scan_result_status : 2; /* WiFi scan result status */
+  uint32_t scan_result_len : 6;
+} g_state;
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -645,7 +657,7 @@ static void bl602_net_receive(FAR struct bl602_net_driver_s *priv)
     }
 }
 
-static int bl602_launch_pending_rx(FAR struct bl602_net_driver_s *priv)
+static int bl602_launch_pending_rx(void)
 {
   struct rx_pending_item_s *item;
   irqstate_t                irqstate;
@@ -689,14 +701,15 @@ static int bl602_launch_pending_rx(FAR struct bl602_net_driver_s *priv)
 
       /* now we have avaliable tx buffer and pending rx data, launch it */
 
-      DEBUGASSERT(priv->net_dev.d_buf == NULL);
+      DEBUGASSERT(item->priv != NULL);
+      DEBUGASSERT(item->priv->net_dev.d_buf == NULL);
       DEBUGASSERT(item->data != NULL && item->len > 0);
 
-      priv->net_dev.d_buf = item->data;
-      priv->net_dev.d_len = item->len;
-      bl602_net_receive(priv);
+      item->priv->net_dev.d_buf = item->data;
+      item->priv->net_dev.d_len = item->len;
+      bl602_net_receive(item->priv);
 
-      DEBUGASSERT(priv->net_dev.d_buf == NULL);
+      DEBUGASSERT(item->priv->net_dev.d_buf == NULL);
       net_unlock();
 
       kmm_free(item);
@@ -713,24 +726,29 @@ static int bl602_launch_pending_rx(FAR struct bl602_net_driver_s *priv)
  *   event: notify type, tx done or received new data
  *   data: The data of the event, may be NULL
  *   len: data length
+ *   opaque: customer data
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
  *
  ****************************************************************************/
 
-int bl602_net_notify(uint32_t event, uint8_t *data, int len)
+int bl602_net_notify(uint32_t event, uint8_t *data, int len, void *opaque)
 {
-  /* TODO distinguish which driver */
+  DEBUGASSERT(opaque != NULL);
+
+  FAR struct bl602_net_driver_s *priv =
+    (FAR struct bl602_net_driver_s *)opaque;
+
+  DEBUGASSERT(priv == &g_bl602_net[0] || priv == &g_bl602_net[1]);
 
-  FAR struct bl602_net_driver_s *priv = &g_bl602_net[0];
-  int                            ret;
+  int ret;
 
   if (event & BL602_NET_EVT_TX_DONE)
     {
       /* if we have tx buffer, we put pending input packet first */
 
-      ret = bl602_launch_pending_rx(priv);
+      ret = bl602_launch_pending_rx();
       if (ret != OK)
         {
           /* There is no tx buffer, we needn't to poll.. */
@@ -782,6 +800,7 @@ int bl602_net_notify(uint32_t event, uint8_t *data, int len)
 
           item->data = data;
           item->len  = len;
+          item->priv = priv;
 
           wlinfo("pending rx data :%p %d\n", item->data, item->len);
 
@@ -959,6 +978,25 @@ static int bl602_net_ifup(FAR struct net_driver_s *dev)
   return OK;
 }
 
+static int bl602_net_soft_reset(void)
+{
+  int idx;
+
+  wifi_mgmr_sta_disconnect();
+  nxsig_sleep(1);
+  wifi_mgmr_api_ap_stop();
+  nxsig_sleep(1);
+  wifi_mgmr_api_idle();
+  wifi_mgmr_reset();
+
+  for (idx = 0; idx < BL602_NET_NINTERFACES; idx++)
+    {
+      g_bl602_net[idx].current_mode = IW_MODE_AUTO;
+    }
+
+  return 0;
+}
+
 /****************************************************************************
  * Name: bl602_net_ifdown
  *
@@ -993,6 +1031,12 @@ static int bl602_net_ifdown(FAR struct net_driver_s *dev)
   wd_cancel(&priv->txpoll);
 
   leave_critical_section(flags);
+
+  if (priv == &g_bl602_net[0])
+    {
+      bl602_net_soft_reset();
+    }
+
   net_unlock();
   return OK;
 }
@@ -1245,7 +1289,7 @@ static void scan_complete_indicate(void *data, void *param)
   para = (struct scan_parse_param_s *)data;
   DEBUGASSERT(para != NULL);
   DEBUGASSERT(para->priv != NULL);
-  para->priv->scan_result_len = 0;
+  g_state.scan_result_len = 0;
 
   for (i = 0;
        i < sizeof(WIFI_MGMR.scan_items) / sizeof(WIFI_MGMR.scan_items[0]);
@@ -1260,14 +1304,19 @@ static void scan_complete_indicate(void *data, void *param)
         }
       else if (scan->is_used)
         {
-          if (para->flags & IW_SCAN_THIS_ESSID)
+          if (para->priv->channel != 0 &&
+              scan->channel != para->priv->channel)
+            {
+              scan->is_used = 0;
+            }
+          else if (para->flags & IW_SCAN_THIS_ESSID)
             {
               if (strncmp(scan->ssid,
                           (char *)para->scan_req.essid,
                           sizeof(scan->ssid)) == 0)
                 {
                   scan->is_used = 1;
-                  para->priv->scan_result_len++;
+                  g_state.scan_result_len++;
                 }
               else
                 {
@@ -1276,12 +1325,11 @@ static void scan_complete_indicate(void *data, void *param)
             }
           else
             {
-              para->priv->scan_result_len++;
+              g_state.scan_result_len++;
             }
         }
     }
 
-  sem_post(&g_wifi_scan_sem);
   kmm_free(data);
   return;
 }
@@ -1453,7 +1501,7 @@ static int bl602_ioctl_wifi_start(FAR struct bl602_net_driver_s *priv,
                                 0,
                                 priv->channel) == -1)
         {
-          return -ENOBUFS;
+          return -EPIPE;
         }
 
       sem_wait(&g_wifi_connect_sem);
@@ -1463,17 +1511,21 @@ static int bl602_ioctl_wifi_start(FAR struct bl602_net_driver_s *priv,
       wifi_mgmr_state_get_internal(&state);
       if (state != WIFI_STATE_CONNECTED_IP_GOT)
         {
-          return -EINVAL;
+          return -EPIPE;
         }
     }
   else if (priv->current_mode == IW_MODE_MASTER)
     {
+      int channel;
+      wifi_mgmr_channel_get(&channel);
+      syslog(LOG_INFO, "current channel:%d\n", channel);
+
       if (wifi_mgmr_api_ap_start(mgmr->wifi_mgmr_stat_info.ssid,
                                  mgmr->wifi_mgmr_stat_info.psk,
-                                 1,
+                                 channel ? channel : 1,
                                  0) < 0)
         {
-          return -ENOBUFS;
+          return -EPIPE;
         }
     }
   else
@@ -1568,7 +1620,16 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
 
           if (sem_trywait(&g_wifi_scan_sem) == 0)
             {
-              wifi_mgmr_scan(para, scan_complete_indicate);
+              if (priv->channel != 0)
+                {
+                  wifi_mgmr_scan_fixed_channels(para, scan_complete_indicate,
+                      &priv->channel, 1);
+                }
+              else
+                {
+                  wifi_mgmr_scan(para, scan_complete_indicate);
+                }
+
               return OK;
             }
           else
@@ -1587,14 +1648,21 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
 
           sem_wait(&g_wifi_scan_sem);
 
-          if (priv->scan_result_len == 0)
+          if (g_state.scan_result_status != 0)
+            {
+              wlwarn("scan failed\n");
+              sem_post(&g_wifi_scan_sem);
+              return -EIO;
+            }
+
+          if (g_state.scan_result_len == 0)
             {
               req->u.data.length = 0;
               sem_post(&g_wifi_scan_sem);
               return OK;
             }
 
-          ret = format_scan_result_to_wapi(req, priv->scan_result_len);
+          ret = format_scan_result_to_wapi(req, g_state.scan_result_len);
           sem_post(&g_wifi_scan_sem);
           return ret;
         }
@@ -1662,6 +1730,13 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
       do
         {
           struct iwreq *req = (struct iwreq *)arg;
+#ifdef CONFIG_BL602_NET_MULTI_INTERFACE
+          int interface_idx = priv - g_bl602_net;
+
+          DEBUGASSERT(interface_idx >= 0 &&
+              interface_idx < BL602_NET_NINTERFACES);
+#endif
+
           if (req->u.mode == priv->current_mode)
             {
               wlinfo("mode not change\n");
@@ -1672,7 +1747,15 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
             {
               /* station */
 
-              priv->wlan = wifi_mgmr_sta_enable();
+#ifdef CONFIG_BL602_NET_MULTI_INTERFACE
+              if (interface_idx != 0)
+                {
+                  wlwarn("The interface does not support this mode.\n");
+                  return -ENOSYS;
+                }
+#endif
+
+              priv->wlan = wifi_mgmr_sta_enable((void *)priv);
 
               memcpy(priv->wlan->mac,
                      priv->net_dev.d_mac.ether.ether_addr_octet,
@@ -1685,7 +1768,15 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
             {
               /* AP Mode */
 
-              priv->wlan = wifi_mgmr_ap_enable();
+#ifdef CONFIG_BL602_NET_MULTI_INTERFACE
+              if (interface_idx != 1)
+                {
+                  wlwarn("The interface does not support this mode.\n");
+                  return -ENOSYS;
+                }
+#endif
+
+              priv->wlan = wifi_mgmr_ap_enable((void *)priv);
               memcpy(priv->wlan->mac,
                      priv->net_dev.d_mac.ether.ether_addr_octet,
                      6);
@@ -1862,6 +1953,22 @@ bl602_net_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg)
       while (0);
       break;
 
+    case SIOCSIWCOUNTRY: /* Set country code */
+      do
+        {
+          struct iwreq *req = (struct iwreq *)arg;
+
+          ret = wifi_mgmr_set_country_code(req->u.data.pointer);
+          if (ret != 0)
+            {
+              return -EINVAL;
+            }
+
+          return OK;
+        }
+      while (0);
+      break;
+
     default:
       wlerr("ERROR: Unrecognized IOCTL command: %d\n", cmd);
       return -ENOTTY; /* Special return value for this case */
@@ -1967,9 +2074,6 @@ void bl602_netdev_free_txbuf(uint8_t *buf)
 
 void bl602_net_event(int evt, int val)
 {
-  /* TODO distinguish which driver */
-
-  FAR struct bl602_net_driver_s *priv = &g_bl602_net[0];
   net_lock();
 
   switch (evt)
@@ -1977,8 +2081,10 @@ void bl602_net_event(int evt, int val)
     case CODE_WIFI_ON_CONNECTED:
       do
         {
+          struct bl602_net_driver_s *priv = &g_bl602_net[0];
           priv->prev_connectd = 1;
 
+          wifi_mgmr_sta_autoconnect_disable();
           sem_post(&g_wifi_connect_sem);
         }
       while (0);
@@ -1987,11 +2093,13 @@ void bl602_net_event(int evt, int val)
     case CODE_WIFI_CMD_RECONNECT:
       do
         {
+          struct bl602_net_driver_s *priv = &g_bl602_net[0];
           static int retry_cnt = 0;
+
           wlinfo("retry connect : %d\n", retry_cnt);
           if (!priv->prev_connectd)
             {
-              if (retry_cnt++ > 3)
+              if (retry_cnt++ > 1)
                 {
                   retry_cnt = 0;
                   wifi_mgmr_sta_autoconnect_disable();
@@ -2004,6 +2112,14 @@ void bl602_net_event(int evt, int val)
       while (0);
       break;
 
+    case CODE_WIFI_ON_SCAN_DONE:
+      do
+        {
+          g_state.scan_result_status = val;
+          sem_post(&g_wifi_scan_sem);
+        }
+      while (0);
+
     default:
       wlwarn("unhandled msg:%d\n", evt);
       break;
@@ -2019,8 +2135,7 @@ void bl602_net_event(int evt, int val)
  *   Initialize the Wireless controller and driver
  *
  * Input Parameters:
- *   intf - In the case where there are multiple EMACs, this value
- *          identifies which EMAC is to be initialized.
+ *    None
  *
  * Returned Value:
  *   OK on success; Negated errno on failure.
@@ -2030,39 +2145,13 @@ void bl602_net_event(int evt, int val)
  *
  ****************************************************************************/
 
-int bl602_net_initialize(int intf)
+int bl602_net_initialize(void)
 {
   FAR struct bl602_net_driver_s *priv;
   int                            tmp;
+  int                            idx;
   uint8_t                        mac[6];
 
-  /* Get the interface structure associated with this interface number. */
-
-  DEBUGASSERT(intf < CONFIG_BL602_NET_NINTERFACES);
-  priv = &g_bl602_net[intf];
-
-  /* Initialize the driver structure */
-
-  memset(priv, 0, sizeof(struct bl602_net_driver_s));
-  priv->net_dev.d_ifup =
-    bl602_net_ifup; /* I/F up (new IP address) callback */
-
-  priv->net_dev.d_ifdown  = bl602_net_ifdown;  /* I/F down callback */
-  priv->net_dev.d_txavail = bl602_net_txavail; /* New TX data callback */
-#ifdef CONFIG_NET_MCASTGROUP
-  priv->net_dev.d_addmac = bl602_net_addmac; /* Add multicast MAC address */
-  priv->net_dev.d_rmmac  = bl602_net_rmmac;  /* Remove multicast MAC address */
-#endif
-#ifdef CONFIG_NETDEV_IOCTL
-  priv->net_dev.d_ioctl = bl602_net_ioctl; /* Handle network IOCTL commands */
-#endif
-  priv->net_dev.d_private = priv; /* Used to recover private state from dev */
-  priv->net_dev.d_pktsize =
-    BL602_NET_TXBUFF_SIZE - PRESERVE_80211_HEADER_LEN;
-
-  priv->current_mode    = IW_MODE_AUTO;
-  priv->scan_result_len = 0;
-
   /* Initialize scan semaphore */
 
   tmp = sem_init(&g_wifi_scan_sem, 0, 1);
@@ -2097,17 +2186,66 @@ int bl602_net_initialize(int intf)
          mac[4],
          mac[5]);
 
-  memcpy(priv->net_dev.d_mac.ether.ether_addr_octet, mac, 6);
-  bl_wifi_ap_mac_addr_set(priv->net_dev.d_mac.ether.ether_addr_octet);
-  bl_wifi_sta_mac_addr_set(priv->net_dev.d_mac.ether.ether_addr_octet);
+  for (idx = 0; idx < BL602_NET_NINTERFACES; idx++)
+    {
+      /* Get the interface structure associated with this interface number. */
+
+      priv = &g_bl602_net[idx];
 
-  /* Register the device with the OS so that socket IOCTLs can be performed */
+      /* Initialize the driver structure */
 
-  tmp = netdev_register(&priv->net_dev, NET_LL_IEEE80211);
-  if (tmp < 0)
-    {
-      sem_destroy(&g_wifi_scan_sem);
-      return tmp;
+      memset(priv, 0, sizeof(struct bl602_net_driver_s));
+      priv->net_dev.d_ifup =
+        bl602_net_ifup; /* I/F up (new IP address) callback */
+
+      priv->net_dev.d_ifdown  = bl602_net_ifdown;  /* I/F down callback */
+      priv->net_dev.d_txavail = bl602_net_txavail; /* New TX data callback */
+#ifdef CONFIG_NET_MCASTGROUP
+      priv->net_dev.d_addmac = bl602_net_addmac; /* Add multicast MAC address */
+      priv->net_dev.d_rmmac  = bl602_net_rmmac;  /* Remove multicast MAC address */
+#endif
+#ifdef CONFIG_NETDEV_IOCTL
+      priv->net_dev.d_ioctl = bl602_net_ioctl; /* Handle network IOCTL commands */
+#endif
+      priv->net_dev.d_private = priv; /* Used to recover private state from dev */
+      priv->net_dev.d_pktsize =
+        BL602_NET_TXBUFF_SIZE - PRESERVE_80211_HEADER_LEN;
+
+#ifdef CONFIG_BL602_NET_MULTI_INTERFACE
+      /* Set AP's MAC address equals STA's MAC */
+
+      memcpy(priv->net_dev.d_mac.ether.ether_addr_octet, mac, 6);
+
+      if (idx == 0)
+        {
+          bl_wifi_sta_mac_addr_set(
+              priv->net_dev.d_mac.ether.ether_addr_octet);
+        }
+      else
+        {
+          bl_wifi_ap_mac_addr_set(
+              priv->net_dev.d_mac.ether.ether_addr_octet);
+        }
+#else
+      DEBUGASSERT(idx == 0);
+
+      memcpy(priv->net_dev.d_mac.ether.ether_addr_octet, mac, 6);
+      bl_wifi_sta_mac_addr_set(priv->net_dev.d_mac.ether.ether_addr_octet);
+      bl_wifi_ap_mac_addr_set(priv->net_dev.d_mac.ether.ether_addr_octet);
+#endif
+
+      priv->current_mode    = IW_MODE_AUTO;
+
+      /* Register the device with the OS so that socket IOCTLs can be
+       * performed
+       */
+
+      tmp = netdev_register(&priv->net_dev, NET_LL_IEEE80211);
+      if (tmp < 0)
+        {
+          sem_destroy(&g_wifi_scan_sem);
+          return tmp;
+        }
     }
 
   return OK;
diff --git a/arch/risc-v/src/bl602/bl602_netdev.h b/arch/risc-v/src/bl602/bl602_netdev.h
index 548c3da..933c34e 100644
--- a/arch/risc-v/src/bl602/bl602_netdev.h
+++ b/arch/risc-v/src/bl602/bl602_netdev.h
@@ -100,13 +100,14 @@ void bl602_netdev_free_txbuf(uint8_t *buf);
  *   event: notify type, tx done or received new data
  *   data: The data of the event, may be NULL
  *   len: data length
+ *   opaque: customer data
  *
  * Returned Value:
  *   OK on success; a negated errno on failure
  *
  ****************************************************************************/
 
-int  bl602_net_notify(uint32_t event, uint8_t *data, int len);
+int  bl602_net_notify(uint32_t event, uint8_t *data, int len, void *opaque);
 
 /****************************************************************************
  * Name: bl602_net_event
diff --git a/boards/risc-v/bl602/bl602evb/scripts/ld.script b/boards/risc-v/bl602/bl602evb/scripts/ld.script
index 74ed85d..da48feb 100644
--- a/boards/risc-v/bl602/bl602evb/scripts/ld.script
+++ b/boards/risc-v/bl602/bl602evb/scripts/ld.script
@@ -3,6 +3,10 @@ OUTPUT_ARCH( "riscv" )
 ENTRY( bl602_start )
 
 __EM_SIZE = DEFINED(ble_controller_init) ? 8K : 0K;
+__RFTLV_SIZE_OFFSET = 1K;
+__RFTLV_SIZE_HOLE = 2K;
+__RFTLV_HEAD1_H = (0x46524C42); /* BLRF */
+__RFTLV_HEAD1_L = (0x41524150); /* PAPA */
 
 MEMORY
 {
@@ -23,6 +27,17 @@ SECTIONS
     KEEP (*(SORT_NONE(.init)))
   } > flash
 
+	/* value for rftlv */
+
+  .rftlv.tool :
+  {
+      . = ORIGIN(flash) + __RFTLV_SIZE_OFFSET;
+      PROVIDE( _ld_symbol_rftlv_address = . );
+      LONG(__RFTLV_HEAD1_H);
+      LONG(__RFTLV_HEAD1_L);
+      . = ORIGIN(flash) + __RFTLV_SIZE_OFFSET + __RFTLV_SIZE_HOLE;
+  } > flash
+
   .text           :
   {
     PROVIDE(_stext = .);
diff --git a/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c b/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c
index 91994fa..0ee1da2 100644
--- a/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c
+++ b/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c
@@ -94,7 +94,7 @@ static struct work_s g_ble_hci_rx_work;
  ****************************************************************************/
 
 #if defined(CONFIG_BL602_WIRELESS)
-extern int bl602_net_initialize(int intf);
+extern int bl602_net_initialize(void);
 #endif
 
 #if defined(CONFIG_BL602_BLE_CONTROLLER)
@@ -274,7 +274,7 @@ int bl602_bringup(void)
 #ifdef CONFIG_BL602_WIRELESS
   bl602_set_em_sel(BL602_GLB_EM_8KB);
 
-  bl602_net_initialize(0);
+  bl602_net_initialize();
 #endif
 
 #ifdef CONFIG_RTC_DRIVER