IOT-OS之RT-Thread(十六)--- WLAN管理框架 + AP6181(BCM43362) WiFi模块

本文详细介绍了RT-Thread操作系统中的WLAN管理框架,包括WLAN Device驱动接口层、WLAN Protocol实现、WLAN Config参数管理和自动连接功能。重点讲解了AP6181 WIFI模块的驱动移植,以及LwIP协议栈的适配过程。此外,还涵盖了WLAN Manager的实现原理,以及WIFI与Socket网络开发示例,帮助开发者更好地理解和使用RT-Thread的WLAN功能。
摘要由CSDN通过智能技术生成

一、WLAN管理框架简介

随着物联网快速发展,越来越多的嵌入式设备上搭载了 WIFI 无线网络设备,为了能够管理 WIFI 网络设备,RT-Thread 引入了 WLAN 设备管理框架。这套框架是 RT-Thread 开发的一套用于管理 WIFI 的中间件:对下连接具体的 WIFI 驱动,控制 WIFI 的连接、断开、扫描等操作;对上承载不同的应用,为应用提供 WIFI 控制、事件、数据导流等操作,为上层应用提供统一的 WIFI 控制接口。

WLAN 框架主要由四个部分组成:Device 驱动接口层,为 WLAN 框架提供统一的调用接口;Manage 管理层为用户提供 WIFI 扫描、连接、断线重连等具体功能;Protocol 协议负责处理 WIFI 上产生的网络数据流,可根据不同的使用场景挂载不同网络协议栈(比如 LWIP );Config配置层可以保存 WIFI 配置参数,为用户提供自动连接服务(可从Flash读取曾经连接过的热点配置信息)。WIFI 框架层次图示如下:
WLAN管理框架
WLAN管理框架各层功能简介如下:

  • APP应用层:是基于 WLAN 框架的具体应用,如 WiFi 相关的 Shell 命令;
  • Airkiss / Voice 配网层:提供无线配网和声波配网等功能;
  • WLAN Manager 管理层:能够对 WLAN 设备进行控制和管理,具备设置模式、连接热点、断开热点、启动热点、扫描热点等 WLAN 控制相关的功能,还提供断线重连、自动切换热点等管理功能;
  • WLAN Protocol 协议层:将数据流递交给具体网络协议进行解析,用户可以指定使用不同的协议进行通信(本文使用LwIP协议);
  • WLAN Config 参数管理层:管理连接成功的热点信息及密码,并写入非易失的存储介质中,可以为用户提供自动连接曾连热点的服务;
  • WLAN Device 驱动接口层:对接具体 WLAN 硬件(本文使用AP6181 WIFI 模块),为管理层提供统一的调用接口。

在WLAN Protocol 与 APP 层之间还应包含网络协议层(比如LwIP),甚至是套接字抽象层SAL(包括网络设备无关层netdev),这些并没有表现在上面的WLAN 框架图中,下文介绍LwIP协议栈移植时再详说。

二、WLAN Device实现与AP6181 WLAN驱动移植

2.1 WLAN Device驱动接口层

  • WLAN设备数据结构
// rt-thread-4.0.1\components\drivers\wlan\wlan_dev.h

struct rt_wlan_device
{
   
    struct rt_device device;
    rt_wlan_mode_t mode;
    struct rt_mutex lock;
    struct rt_wlan_dev_event_desc handler_table[RT_WLAN_DEV_EVT_MAX][RT_WLAN_DEV_EVENT_NUM];
    rt_wlan_pormisc_callback_t pormisc_callback;
    const struct rt_wlan_dev_ops *ops;
    rt_uint32_t flags;
    void *prot;
    void *user_data;
};

typedef enum
{
   
    RT_WLAN_NONE,
    RT_WLAN_STATION,
    RT_WLAN_AP,
    RT_WLAN_MODE_MAX
} rt_wlan_mode_t;

struct rt_wlan_dev_event_desc
{
   
    rt_wlan_dev_event_handler handler;
    void *parameter;
};

typedef void (*rt_wlan_dev_event_handler)(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter);

typedef void (*rt_wlan_pormisc_callback_t)(struct rt_wlan_device *device, void *data, int len);

struct rt_wlan_dev_ops
{
   
    rt_err_t (*wlan_init)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_mode)(struct rt_wlan_device *wlan, rt_wlan_mode_t mode);
    rt_err_t (*wlan_scan)(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info);
    rt_err_t (*wlan_join)(struct rt_wlan_device *wlan, struct rt_sta_info *sta_info);
    rt_err_t (*wlan_softap)(struct rt_wlan_device *wlan, struct rt_ap_info *ap_info);
    rt_err_t (*wlan_disconnect)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_ap_stop)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_ap_deauth)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
    rt_err_t (*wlan_scan_stop)(struct rt_wlan_device *wlan);
    int (*wlan_get_rssi)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_set_powersave)(struct rt_wlan_device *wlan, int level);
    int (*wlan_get_powersave)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_cfg_promisc)(struct rt_wlan_device *wlan, rt_bool_t start);
    rt_err_t (*wlan_cfg_filter)(struct rt_wlan_device *wlan, struct rt_wlan_filter *filter);
    rt_err_t (*wlan_set_channel)(struct rt_wlan_device *wlan, int channel);
    int (*wlan_get_channel)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_set_country)(struct rt_wlan_device *wlan, rt_country_code_t country_code);
    rt_country_code_t (*wlan_get_country)(struct rt_wlan_device *wlan);
    rt_err_t (*wlan_set_mac)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
    rt_err_t (*wlan_get_mac)(struct rt_wlan_device *wlan, rt_uint8_t mac[]);
    int (*wlan_recv)(struct rt_wlan_device *wlan, void *buff, int len);
    int (*wlan_send)(struct rt_wlan_device *wlan, void *buff, int len);
};

结构体 rt_wlan_device 继承自设备基类 rt_device,自然需要将其注册到 I/O 设备管理层。rt_wlan_device 成员还包括WLAN设备工作模式(Access Point模式还是Station模式)、WLAN设备访问互斥锁、WLAN事件回调函数组、WLAN混杂模式回调函数、需要底层驱动实现并注册的WLAN接口函数集合rt_wlan_dev_ops、WLAN标识位(用于标识工作模式或自动连接状态等)、WLAN设备使用的网络协议栈信息、私有数据等。

  • WLAN接口函数及设备注册过程

WLAN设备驱动(这里指的是AP6181 WLAN驱动)需要向WLAN管理框架注册接口函数集合rt_wlan_dev_ops,以便WLAN管理框架对外提供的接口能正常工作,这个函数集合rt_wlan_dev_ops是如何注册到WLAN管理框架的呢?

// rt-thread-4.0.1\components\drivers\wlan\wlan_dev.c

rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, const struct rt_wlan_dev_ops *ops, rt_uint32_t flag, void *user_data)
{
   
    rt_err_t err = RT_EOK;

    if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL))
    ......
    rt_memset(wlan, 0, sizeof(struct rt_wlan_device));
    
#ifdef RT_USING_DEVICE_OPS
    wlan->device.ops = &wlan_ops;
#else
    ......
#endif

    wlan->device.user_data  = RT_NULL;
    wlan->device.type = RT_Device_Class_NetIf;

    wlan->ops = ops;
    wlan->user_data  = user_data;

    wlan->flags = flag;
    err = rt_device_register(&wlan->device, name, RT_DEVICE_FLAG_RDWR);

    return err;
}

#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops wlan_ops =
{
   
    _rt_wlan_dev_init,
    RT_NULL,
    RT_NULL,
    RT_NULL,
    RT_NULL,
    _rt_wlan_dev_control
};
#endif

从函数rt_wlan_dev_register 的代码可以看出,该函数不仅完成了将函数集合rt_wlan_dev_ops注册到WLAN管理框架的工作(通过参数传递),还完成了将函数集合wlan_ops(通过调用rt_wlan_dev_ops接口实现的rt_device_ops接口)注册到 I/O 设备管理框架的工作,注册的WLAN设备类型为网络接口设备RT_Device_Class_NetIf。

完成WLAN设备向WLAN管理框架和 I/O 设备管理框架的注册后,就可以使用 I/O 设备管理层接口或WLAN Device层提供的接口访问WLAN设备了,我们先看下WLAN设备向 I/O 设备管理层注册的函数集合 wlan_ops 的实现代码:

// rt-thread-4.0.1\components\drivers\wlan\wlan_dev.c

static rt_err_t _rt_wlan_dev_init(rt_device_t dev)
{
   
    struct rt_wlan_device *wlan = (struct rt_wlan_device *)dev;
    rt_err_t result = RT_EOK;

    rt_mutex_init(&wlan->lock, "wlan_dev", RT_IPC_FLAG_FIFO);

    if (wlan->ops->wlan_init)
        result = wlan->ops->wlan_init(wlan);
    ......
    return result;
}

static rt_err_t _rt_wlan_dev_control(rt_device_t dev, int cmd, void *args)
{
   
    struct rt_wlan_device *wlan = (struct rt_wlan_device *)dev;
    rt_err_t err = RT_EOK;

    WLAN_DEV_LOCK(wlan);

    switch (cmd)
    {
   
    case RT_WLAN_CMD_MODE:
    {
   
        rt_wlan_mode_t mode = *((rt_wlan_mode_t *)args);
        if (wlan->ops->wlan_mode)
            err = wlan->ops->wlan_mode(wlan, mode);
        break;
    }
    case RT_WLAN_CMD_SCAN:
    {
   
        struct rt_scan_info *scan_info = args;
        if (wlan->ops->wlan_scan)
            err = wlan->ops->wlan_scan(wlan, scan_info);
        break;
    }
    case RT_WLAN_CMD_JOIN:
    {
   
        struct rt_sta_info *sta_info = args;
        if (wlan->ops->wlan_join)
            err = wlan->ops->wlan_join(wlan, sta_info);
        break;
    }
    case RT_WLAN_CMD_SOFTAP:
    {
   
        struct rt_ap_info *ap_info = args;
        if (wlan->ops->wlan_softap)
            err = wlan->ops->wlan_softap(wlan, ap_info);
        break;
    }
    case RT_WLAN_CMD_DISCONNECT:
    {
   
        if (wlan->ops->wlan_disconnect)
            err = wlan->ops->wlan_disconnect(wlan);
        break;
    }
    case RT_WLAN_CMD_AP_STOP:
    {
   
        if (wlan->ops->wlan_ap_stop)
            err = wlan->ops->wlan_ap_stop(wlan);
        break;
    }
    case RT_WLAN_CMD_AP_DEAUTH:
    {
   
        if (wlan->ops->wlan_ap_deauth)
            err = wlan->ops->wlan_ap_deauth(wlan, args);
        break;
    }
    case RT_WLAN_CMD_SCAN_STOP:
    {
   
        if (wlan->ops->wlan_scan_stop)
            err = wlan->ops->wlan_scan_stop(wlan);
        break;
    }
    case RT_WLAN_CMD_GET_RSSI:
    {
   
        int *rssi = args;
        if (wlan->ops->wlan_get_rssi)
            *rssi = wlan->ops->wlan_get_rssi(wlan);
        break;
    }
    case RT_WLAN_CMD_SET_POWERSAVE:
    {
   
        int level = *((int *)args);
        if (wlan->ops->wlan_set_powersave)
            err = wlan->ops->wlan_set_powersave(wlan, level);
        break;
    }
    case RT_WLAN_CMD_GET_POWERSAVE:
    {
   
        int *level = args;
        if (wlan->ops->wlan_get_powersave)
            *level = wlan->ops->wlan_get_powersave(wlan);
        break;
    }
    case RT_WLAN_CMD_CFG_PROMISC:
    {
   
        rt_bool_t start = *((rt_bool_t *)args);
        if (wlan->ops->wlan_cfg_promisc)
            err = wlan->ops->wlan_cfg_promisc(wlan, start);
        break;
    }
    case RT_WLAN_CMD_CFG_FILTER:
    {
   
        struct rt_wlan_filter *filter = args;
        if (wlan->ops->wlan_cfg_filter)
            err = wlan->ops->wlan_cfg_filter(wlan, filter);
        break;
    }
    case RT_WLAN_CMD_SET_CHANNEL:
    {
   
        int channel = *(int *)args;
        if (wlan->ops->wlan_set_channel)
            err = wlan->ops->wlan_set_channel(wlan, channel);
        break;
    }
    case RT_WLAN_CMD_GET_CHANNEL:
    {
   
        int *channel = args;
        if (wlan->ops->wlan_get_channel)
            *channel = wlan->ops->wlan_get_channel(wlan);
        break;
    }
    case RT_WLAN_CMD_SET_COUNTRY:
    {
   
        rt_country_code_t country = *(rt_country_code_t *)args;
        if (wlan->ops->wlan_set_country)
            err = wlan->ops->wlan_set_country(wlan, country);
        break;
    }
    case RT_WLAN_CMD_GET_COUNTRY:
    {
   
        rt_country_code_t *country = args;
        if (wlan->ops->wlan_get_country)
            *country = wlan->ops->wlan_get_country(wlan);
        break;
    }
    case RT_WLAN_CMD_SET_MAC:
    {
   
        rt_uint8_t *mac = args;
        if (wlan->ops->wlan_set_mac)
            err = wlan->ops->wlan_set_mac(wlan, mac);
        break;
    }
    case RT_WLAN_CMD_GET_MAC:
    {
   
        rt_uint8_t *mac = args;
        if (wlan->ops->wlan_get_mac)
            err = wlan->ops->wlan_get_mac(wlan, mac);
        break;
    }
    default:
        break;
    }

    WLAN_DEV_UNLOCK(wlan);

    return err;
}

函数集合 wlan_ops 的实现最终都是靠调用WLAN设备驱动提供的函数集合rt_wlan_dev_ops,而且WLAN设备的管理配置主要靠函数rt_device_control 通过发送不同的命令码和参数实现。WLAN Device层提供的接口函数又是通过调用函数集合 wlan_ops 实现的,下面给出WLAN Device层对外提供的接口函数声明:

// rt-thread-4.0.1\components\drivers\wlan\wlan_dev.h

/* wlan device init */
rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode);

/* wlan device station interface */
rt_err_t rt_wlan_dev_connect(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len);
rt_err_t rt_wlan_dev_disconnect(struct rt_wlan_device *device);
int rt_wlan_dev_get_rssi(struct rt_wlan_device *device);

/* wlan device ap interface */
rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info *info, const char *password, int password_len);
rt_err_t rt_wlan_dev_ap_stop(struct rt_wlan_device *device);
rt_err_t rt_wlan_dev_ap_deauth(struct rt_wlan_device *device, rt_uint8_t mac[6]);

/* wlan device scan interface */
rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *info);
rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device);

/* wlan device mac interface */
rt_err_t rt_wlan_dev_get_mac(struct rt_wlan_device *device, rt_uint8_t mac[6]);
rt_err_t rt_wlan_dev_set_mac(struct rt_wlan_device *device, rt_uint8_t mac[6]);

/* wlan device powersave interface */
rt_err_t rt_wlan_dev_set_powersave(struct rt_wlan_device *device, int level);
int rt_wlan_dev_get_powersave(struct rt_wlan_device *device);

/* wlan device event interface */
rt_err_t rt_wlan_dev_register_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler, void *parameter);
rt_err_t rt_wlan_dev_unregister_event_handler(struct rt_wlan_device *device, rt_wlan_dev_event_t event, rt_wlan_dev_event_handler handler);
void rt_wlan_dev_indicate_event_handle(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff);

/* wlan device promisc interface */
rt_err_t rt_wlan_dev_enter_promisc(struct rt_wlan_device *device);
rt_err_t rt_wlan_dev_exit_promisc(struct rt_wlan_device *device);
rt_err_t rt_wlan_dev_set_promisc_callback(struct rt_wlan_device *device, rt_wlan_pormisc_callback_t callback);
void rt_wlan_dev_promisc_handler(struct rt_wlan_device *device, void *data, int len);

/* wlan device filter interface */
rt_err_t rt_wlan_dev_cfg_filter(struct rt_wlan_device *device, struct rt_wlan_filter *filter);

/* wlan device channel interface */
rt_err_t rt_wlan_dev_set_channel(struct rt_wlan_device *device, int channel);
int rt_wlan_dev_get_channel(struct rt_wlan_device *device);

/* wlan device country interface */
rt_err_t rt_wlan_dev_set_country(struct rt_wlan_device *device, rt_country_code_t country_code);
rt_country_code_t rt_wlan_dev_get_country(struct rt_wlan_device *device);

/* wlan device datat transfer interface */
rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len);

/* wlan device register interface */
rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, 
    const struct rt_wlan_dev_ops *ops, rt_uint32_t flag, void *user_data);

WLAN Device层提供的这些接口函数我们虽然可以在应用程序中直接调用,但函数参数有很多结构体类型,在调用这些接口函数前,需要先构造接口函数参数需要的结构体,这就给函数调用带来了不便。WLAN Device层上面的WLAN Manager 层则对这些接口函数进行了再次封装,使用一些全局变量保存必要的信息,简化了参数的构造,我们直接调用WLAN Manager 层提供的接口函数更加方便友好,这些接口函数在下文介绍。

2.2 AP6181 WLAN驱动移植

Pandora开发板的程序源码包并没有为我们提供AP6181 WLAN驱动的源码,而是以库文件的形式给出的,所以这里也没法分析AP6181 WLAN驱动的实现原理,只能根据 SDIO 设备管理框架与WLAN 管理框架对WLAN设备驱动的要求推测一些AP6181 WLAN驱动移植时应实现或调用的函数。这里忍不住吐槽一下提供Pandora开发板 AP6181 WLAN驱动库文件的同学,起码应该给出一些关于AP6181 WLAN驱动库文件如何使用、需要为其实现哪些接口函数、对外提供哪些接口函数、简单的实现原理之类的说明文档,现在缺少这些信息为WLAN驱动移植和调试带来了很大的不便。

  • AP6181 WLAN固件配置

从前篇博客:SDIO设备对象管理 + AP6181(BCM43362) WiFi模块了解到,AP6181 WIFI 模组内部是需要运行WLAN固件程序的,AP6181 内部可能没有ROM空间,这就需要我们将AP6181 内运行的WLAN固件程序存放到主控端的Flash 空间内。在使用WLAN设备前,由WLAN驱动程序负责将Host 端Flash内存放的WLAN固件读取并传送到AP6181 模组内,以便AP6181 WIFI 模组能正常工作(比如完成WIFI数据帧与以太网数据帧之间的转换)。

这里提醒一点,本文使用的AP6181的WLAN固件与驱动都是从Pandora开发板提供的源码包中获得的,且由于WLAN固件与驱动都是以库文件的形式提供的,对运行环境(比如RT-Thread版本)变更比较敏感,因此最好选择与自己使用的RT-Thread版本一致的 Pandora IOT 源码包。比如我使用的是RT-Thread 4.0.1,正点原子官网给的Pandora IOT 源码包默认的基于RT-Thread 4.0.0开发的,我就需要到GitHub 下载基于RT-Thread 4.0.1 版本的Pandora IOT 源码包(本文使用的是Release 1.2.0版本)。下文中使用的AP6181 WLAN固件与驱动都是从Pandora IOT Board Release 1.2.0版本源码包拷贝来的。

AP6181 WLAN固件所在路径:

.\IoT_Board\examples\16_iot_wifi_manager\bin\wifi_image_1.0.rbl

我们需要先将该WLAN固件放入Flash(Pandora上的W25Q128芯片)的 wifi_image 分区,本文使用的工程文件是基于博客:FAL分区管理与easyflash变量管理中完成FAL与Easyflash组件移植后的工程文件为基础的。在上面的博客中已经FAL(Flash Abstraction Layer)的实现原理及接口函数,而且在移植FAL组件时配置到分区表也包括wifi_image 分区,这里可以直接该分区存储 AP6181 WLAN 固件镜像文件。

我们如何将AP6181 WLAN固件(wifi_image_1.0.rbl)放到W25Q128 Flash内的wifi_image 分区呢?可以参考下面的文档:

 .\IoT_Board\docs\UM3001-RT-Thread-IoT Board WIFI 模块固件下载手册.pdf

比较简单的方法是先将WLAN固件放到SD卡如下目录中:
/SYSTEM/WIFI/wifi_image_1.0.rbl

然后将SD卡插入到Pandora开发板的SD卡插槽,将综合例程文件(如下路径)烧录到Pandora开发板中:
.\IoT_Board\examples\30_iot_board_demo\bin\all.bin

综合例程文件烧录完成后,Pandora开发板检测到WLAN固件,会自动执行读取、校验、升级WLAN固件的操作,Pandora开发板的LCD也会显示相应的升级信息(如果wifi_image
分区已存在WLAN固件,且与放入SD卡中的WLAN固件版本一致,则不会有相应的加载或升级操作)。

接下来就是AP6181 WLAN驱动负责将存储在W25Q128 Flash wifi_image 分区的WLAN固件读取出来,并通过SDIO总线传输到AP6181 模组内。由于WLAN驱动是以库文件的形式提供的,我们直接从Pandora源码包将WLAN驱动库文件和WLAN驱动移植文件复制到我们的工程中使用,这些文件在Pandora源码包中的路径和复制到我们工程目录的路径如下:

// Pandora IOT Board Release 1.2.0中WLAN驱动库文件和WLAN驱动移植文件路径
.\IoT_Board\libraries\wifi\libwifi_6181_0.2.5_armcm4_gcc.a
.\IoT_Board\libraries\wifi\libwifi_6181_0.2.5_armcm4_iar.a
.\IoT_Board\libraries\wifi\libwifi_6181_0.2.5_armcm4_keil.lib
.\IoT_Board\libraries\wifi\SConscript

.\IoT_Board\drivers\drv_wlan.h
.\IoT_Board\drivers\drv_wlan.c

// WLAN驱动库文件和WLAN驱动移植文件拷贝到我们工程中的目标路径
.\RT-Thread_Projects\libraries\wifi\libwifi_6181_0.2.5_armcm4_gcc.a
.\RT-Thread_Projects\libraries\wifi\libwifi_6181_0.2.5_armcm4_iar.a
.\RT-Thread_Projects\libraries\wifi\libwifi_6181_0.2.5_armcm4_keil.lib
.\RT-Thread_Projects\libraries\wifi\SConscript

.\RT-Thread_Projects\libraries\HAL_Drivers\drv_wlan.h
.\RT-Thread_Projects\libraries\HAL_Drivers\drv_wlan.c

WLAN驱动库文件和WLAN驱动移植文件复制到我们工程中后,需要能编译进我们的工程,因此需要修改SConscript文件和SConstruct文件,将我们拷贝过来的文件添加进编译脚本,新增编译代码如下:

// .\RT-Thread_Projects\libraries\HAL_Drivers\SConscript
......
# add wlan driver code
if GetDepend(['BSP_USING_WIFI']):
    src += ['drv_wlan.c']

src += ['drv_common.c']
......

// .\RT-Thread_Projects\projects\stm32l475_wifi_sample\SConstruct
......
# include drivers
objs.extend(SConscript(os.path.join(libraries_path_prefix, 'HAL_Drivers', 'SConscript')))

# include wifi_libraries
objs.extend(SConscript(os.path.join(libraries_path_prefix, 'wifi', 'SConscript')))

# make a building
DoBuilding(TARGET, objs)

到这里WLAN驱动库文件和WLAN驱动移植文件就添加到我们的工程中了,接下来看WLAN驱动是如何读取WLAN固件镜像文件的:

// .\RT-Thread_Projects\libraries\HAL_Drivers\drv_wlan.c

#define WIFI_IMAGE_PARTITION_NAME       "wifi_image"
static const struct fal_partition *partition = RT_NULL;

int wiced_platform_resource_size(int resource)
{
   
    int size = 0;

    /* Download firmware */
    if (resource == 0)
    {
   
        /* initialize fal */
        fal_init();
        partition = fal_partition_find(WIFI_IMAGE_PARTITION_NAME);
        if (partition == RT_NULL)
            return size;

        if ((rt_ota_init() >= 0) && (rt_ota_part_fw_verify(partition) >= 0))
            size =
  • 10
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
全志R16的tinav2.1下调通AP6181的步骤.txt 思路:由于tinav2.1的SDK在全志R16的开发板SC3817上是可以使用AP6212A0的WIFI功能的。 由此证明:SC3817的开发板的WIFI的硬件部分正常。我拿到的tinav2.1的SDK正常。 由于在驱动lichee中,WIFI通过读取ID号自动加载固件的。 因此只需要把AP6181A2的固件放到AP6212的目录下,并适当修改配置文件/做出相应的修改。 就可以让tinav2.1在上电启动的时候,通过自动识别AP6181A2来加载其固件了。 1、使用AP6212原厂/代理商提供的固件在android4.4.2 parrotv1.1下调通AP6181: (如果没有这个文件,可以生成WLAN0节点,但是不能连网) R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\config.txt (这个文件没用) R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\device-bcm.mk R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\fw_bcm40181a2.bin R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\fw_bcm40181a2_apsta.bin R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\fw_bcm40181a2_p2p.bin R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\ap6212\nvram_ap6181.txt 2、 R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\firmware\linux-firmware\broadcom.mk Package/ap6212-firmware = $(call Package/firmware-default,Broadcom AP6212 firmware) define Package/ap6212-firmware/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/*.bin \ $(1)/lib/firmware/ $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/*.hcd \ $(1)/lib/firmware/ $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/nvram_ap6212.txt \ $(1)/lib/firmware/nvram.txt endef $(eval $(call BuildPackage,ap6212-firmware)) 修改为: Package/ap6212-firmware = $(call Package/firmware-default,Broadcom AP6212 firmware) define Package/ap6212-firmware/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/*.bin \ $(1)/lib/firmware/ $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/*.hcd \ $(1)/lib/firmware/ $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/nvram_ap6181.txt \ $(1)/lib/firmware/nvram.txt $(INSTALL_DATA) \ $(TOPDIR)/package/firmware/ap6212/config.txt \ $(1)/lib/firmware/config.txt endef $(eval $(call BuildPackage,ap6212-firmware)) 3、 R:\wyb\ap6181+ap6212a0_r16_tinav2.1\target\allwinner\astar-parrot\configs\sys_config.fex [wakeup_src_para] cpu_en = 0 cpu_freq = 48 ; (cpu:apb:ahb) pll_ratio = 0x111 dram_selfresh_en= 1 dram_freq = 36 wakeup_src_wl = port:PL07<4><default><default><0> wakeup_src_bt = port:PL09<4><default><default><0> bb_wake_ap = port:PL02<4><default><default><0> 修改为: [wakeup_src_para] cpu_en = 0 cpu_freq = 48 ; (cpu:apb:ahb) pll_ratio = 0x111 dram_selfresh_en= 1 dram_freq = 36 ;wakeup_src_wl = port:PL07<4><default><default><0> wakeup_src_wl = port:PG09<4><default><default><0> ;wakeup_src_bt = port:PL09<4><default><default><0> bb_wake_ap = port:PL02<4><default><default><0> [rf_para] module_num = 10 module_power1 = "axp22_dldo1" module_power1_vol = 3300000 module_power2 = "axp22_dldo2" module_power2_vol = 3300000 module_power3 = "axp22_aldo1" module_power3_vol = 3300000 power_switch = chip_en = lpo_use_apclk = "losc_out" 修改为: [rf_para] module_num = 1 module_power1 = "axp22_dldo1" module_power1_vol = 3300000 module_power2 = "axp22_dldo2" module_power2_vol = 3300000 module_power3 = "axp22_aldo1" module_power3_vol = 3300000 power_switch = chip_en = lpo_use_apclk = "losc_out" [wifi_para] wifi_used = 1 wifi_sdc_id = 1 wifi_usbc_id = 1 wifi_usbc_type = 1 wl_reg_on = port:PL06<1><default><default><0> wl_host_wake = port:PL07<4><default><default><0> 修改为: [wifi_para] wifi_used = 1 wifi_sdc_id = 1 wifi_usbc_id = 1 wifi_usbc_type = 1 ;wl_reg_on = port:PL06<1><default><default><0> ;wl_host_wake = port:PL07<4><default><default><0> wl_reg_on = port:PG06<1><default><default><0> wl_host_wake = port:PG09<4><default><default><0> wl_host_wake_invert = 0 AP6181没有蓝牙功能,直接关闭。 [bt_para] bt_used = 0 ;bt_uart_id = 1 ;bt_rst_n = port:PL08<1><default><default><0> ;bt_wake = port:PL10<1><default><default><0> ;bt_host_wake = port:PL09<4><default><default><0> ;bt_host_wake_invert = 0 4、编译系统: rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ source build/envsetup.sh including target/allwinner/tulip-d1/vendorsetup.sh including target/allwinner/azalea-evb/vendorsetup.sh including target/allwinner/octopus-sch/vendorsetup.sh including target/allwinner/astar-evb/vendorsetup.sh including target/allwinner/azalea-perf3/vendorsetup.sh including target/allwinner/azalea-perf2/vendorsetup.sh including target/allwinner/azalea-perf1/vendorsetup.sh including target/allwinner/astar-spk/vendorsetup.sh including target/allwinner/generic/vendorsetup.sh including target/allwinner/astar-parrot/vendorsetup.sh including target/allwinner/octopus-dev/vendorsetup.sh rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ lunch You're building on Linux Lunch menu... pick a combo: 1. tulip_d1-tina 2. tulip_d1-dragonboard 3. azalea_evb-tina 4. azalea_evb-dragonboard 5. octopus_sch-tina 6. octopus_sch-dragonboard 7. astar_evb-tina 8. azalea_perf3-tina 9. azalea_perf3-dragonboard 10. azalea_perf2-tina 11. azalea_perf2-dragonboard 12. azalea_perf1-tina 13. azalea_perf1-dragonboard 14. astar_spk-tina 15. astar_spk-dragonboard 16. astar_parrot-tina 17. astar_parrot-dragonboard 18. octopus_dev-tina 19. octopus_dev-dragonboard Which would you like?16 ============================================ PLATFORM_VERSION_CODENAME=Neptune PLATFORM_VERSION=2.0.0 TARGET_PRODUCT=astar_parrot TARGET_BUILD_VARIANT=tina TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon TARGET_CPU_VARIANT=cortex-a7 TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty HOST_BUILD_TYPE=release BUILD_ID=57513AA3 OUT_DIR= ============================================ rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ make -j8 rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ pack -d 5、打开WIFI连接的应用程序: Tina wifimanager API_V2.0.pdf WIFI管理的API接口文档 rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ make menuconfig Allwinner ---> -*- wifimanager............................................ Tina wifi manager ---> --- wifimanager............................................ Tina wifi manager (选中) <*> wifimanager-demo...................................... Tina wifi app demo R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\allwinner\wifimanager\demo\wifi_on_off_test.c R:\wyb\ap6181+ap6212a0_r16_tinav2.1\package\allwinner\wifimanager\demo\wifi_connect_ap.cpp 编译之后,R16的TINAV2.1的系统的/bin中会有: root@TinaLinux:/bin# ll w* lrwxrwxrwx 1 root root 13 Oct 19 14:22 wget -> uclient-fetch -rwxr-xr-x 1 root root 4102 Oct 19 14:12 wifi_connect_ap_test -rwxr-xr-x 1 root root 4102 Oct 19 14:12 wifi_on_off_test root@TinaLinux:/bin# /* *argc[1] ap ssid *argc[2] ap passwd */ int main(int argv, char *argc[]){ wifi_connect_ap.cpp的main函数嵌可以看见第一个参数为SSID,第二参数为密码,中间用空格隔开即可。 WIFI连接之前: root@TinaLinux:/# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:20 errors:0 dropped:0 overruns:0 frame:0 TX packets:20 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1572 (1.5 KiB) TX bytes:1572 (1.5 KiB) wlan0 Link encap:Ethernet HWaddr 94:A1:A2:C4:E3:12 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@TinaLinux:/# WIFI连接: root@TinaLinux:/bin# root@TinaLinux:/bin# ./wifi_connect_ap_test citybrand-2 citybrand200903 ********************************* ***Start wifi connect ap test!*** ********************************* event_label 0x0 WiFi on success! do cmd LIST_NETWORKS call event 0xf004 do cmd SCAN event_label 0x0 It has no wifi auto connect when wifi on! aw wifi connect state 0xf0 enter get_key_mgmt, ssid citybrand-2 scan stauts 1 do cmd SCAN_RESULTS ssid citybrand-2, flag [WPA2-PSK-CCMP][ESS] do cmd LIST_NETWORKS do cmd ADD_NETWORK do cmd SET_NETWORK 0 ssid "citybrand-2" do cmd SET_NETWORK 0 key_mgmt WPA-PSK do cmd SET_NETWORK 0 psk "citybrand200903" do cmd LIST_NETWORKS do cmd GET_NETWORK 0 priority do cmd SET_NETWORK 0 priority 1 do cmd SELECT_NETWORK 0 do cmd RECONNECT do cmd LIST_NETWORKS connecting id 0, connected id 0 Unknown HZ value! (-1) Assume 1241 ttyS0 15049-12:58:15 udhcpc_wlan0 Command failed: Not found Unknown HZ value! (-1) Assume 1241 ttyS0 15049-12:58:15 udhcpc_wlan0 do cmd SAVE_CONFIG do cmd LIST_NETWORKS do cmd ENABLE_NETWORK 0 do cmd SAVE_CONFIG wifi state busing,waiting vflag= 4 call event 0xf00b event_label 0x1 WiFi connected ap! ****************************** Wifi connect ap test: Success! ****************************** root@TinaLinux:/bin# root@TinaLinux:/bin# root@TinaLinux:/bin# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:40 errors:0 dropped:0 overruns:0 frame:0 TX packets:40 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3116 (3.0 KiB) TX bytes:3116 (3.0 KiB) wlan0 Link encap:Ethernet HWaddr 94:A1:A2:C4:E3:12 inet addr:192.168.0.167 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:34 errors:0 dropped:0 overruns:0 frame:0 TX packets:25 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:3084 (3.0 KiB) TX bytes:2516 (2.4 KiB) root@TinaLinux:/bin# root@TinaLinux:/bin# 6、R16的TINAV2.0平台的SSH连接 rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ make menuconfig Base system ---> (选中这里) <*> dropbear........................................ Small SSH2 client/server Configuration ---> [*] Curve25519 support (NEW) (这里不用选中) [ ] Elliptic curve cryptography (ECC) (NEW) 7、再次编译系统打包刷机之后以SCP方式远程登陆R16的tinav2.1: rootroot@cm-System-Product-Name:/home/wwt/parrot_r16_tinav2.0$ make -j12 rootroot@cm-System-Product-Name:/home/wwt/parrot_r16_tinav2.0$ pack -d 在串口终端中输入(必须设置root用户的密码): root@TinaLinux:/bin# root@TinaLinux:/bin# passwd Changing password for root New password: Bad password: too short Retype password: Password for root changed by root root@TinaLinux:/bin# root@TinaLinux:/bin# SSH连接工具使用:WinSCP_5.9.0.6786_Setup.exe 文件协议选择:SCP 主机名:192.168.0.167(根据你的R16的实际IP修改) 端口号:22 用户名:root 密码:root 点击 登陆 即可。 如果重新刷机,IP地址不变,但是RSA密码改变,选择 更新 即可。 8、在ubuntu14.04中文版下通过SSH访问R16的tinav2.1: (注意刚登陆的地方是空的根目录) rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ rootroot@rootroot-E400:~/wyb/ap6181+ap6212a0_r16_tinav2.1$ ssh root@192.168.0.108 root@192.168.0.108's password: BusyBox v1.24.1 () built-in shell (ash) _____ _ __ _ |_ _||_| ___ _ _ | | |_| ___ _ _ _ _ | | _ | || | | |__ | || || | ||_'_| | | | || | || _ | |_____||_||_|_||___||_,_| |_| |_||_|_||_|_| Tina is Based on OpenWrt! ---------------------------------------------- Tina Linux (Neptune, 57513AA3) ---------------------------------------------- root@TinaLinux:~# ll drwxr-xr-x 2 root root 3 Dec 22 20:11 . drwxr-xr-x 1 root root 1024 Dec 23 2016 .. root@TinaLinux:~# pwd /root root@TinaLinux:~# cd / root@TinaLinux:/# ll drwxr-xr-x 1 root root 1024 Dec 23 2016 . drwxr-xr-x 1 root root 1024 Dec 23 2016 .. drwxr-xr-x 2 root root 984 Dec 22 20:11 bin drwxrwxrwx 2 root root 16384 Jan 1 1970 boot drwxrwxrwx 2 root root 8192 Jan 1 1970 boot-res -rw-r--r-- 1 root root 441 Dec 23 2016 bt_config.xml drwxr-xr-x 9 root root 2900 Dec 23 2016 dev drwxr-xr-x 1 root root 1024 Dec 23 11:33 etc drwxr-xr-x 10 root root 661 Dec 22 19:38 lib drwx------ 2 root root 12288 Dec 23 2016 lost+found drwxr-xr-x 1 root root 1024 Dec 23 2016 mnt drwxr-xr-x 7 root root 1024 Dec 23 2016 overlay dr-xr-xr-x 88 root root 0 Jan 1 1970 proc drwxr-xr-x 16 root root 211 Dec 22 20:11 rom drwxr-xr-x 2 root root 3 Dec 22 20:11 root drwxr-xr-x 2 root root 689 Dec 22 20:11 sbin dr-xr-xr-x 12 root root 0 Dec 23 2016 sys drwxrwxrwt 9 root root 300 Dec 23 2016 tmp drwxr-xr-x 7 root root 101 Dec 22 19:50 usr lrwxrwxrwx 1 root root 4 Dec 22 20:11 var -> /tmp drwxr-xr-x 2 root root 3 Dec 22 20:11 www root@TinaLinux:/#
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流云IoT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值