BabyOS如何使用WIFI模组

当MCU项目要增加网络通讯功能时可选择支持串口通讯的WIFI模组。

MCU-WIFI硬件框架

WIFI模组硬件连接比较简单,仅需一路串口便可以使用。

软件方面使用AT指令或私有协议进行配置和收发数据。


BabyOS目标是助力MCU项目的开发,那如何友好的兼容各类模组呢?

以下方案作抛砖引玉之用。

软件方面考虑的点:

① AT指令发送后需要等待回复,裸机如何做到不阻塞的等待

② 多个AT指令实现一个功能配置,如何将功能与AT指令对应

③ 各家的指令有差异,但给上层业务调用的接口要做到统一

④ 模组收到数据后如何抛给上层使用

thirdparty增加pt.h

为了让裸机实现不阻塞的等待,BabyOS thirdparty部分增加PT。为了更方便使用,对宏进行了修改:

#define PT_WAIT_UNTIL_FOREVER(pt, condition)
#define PT_WAIT_UNTIL(pt, condition, timeout)
#define PT_WAIT_WHILE(pt, cond)
#define PT_DELAY_MS(pt, ms)

AT指令的处理便非常方便

static int _bEspMainTask(struct pt *pt)
{
    static uint8_t index  = 0;
    uint16_t       retval = 0;
    PT_BEGIN(pt);
    while (1)
    {
        if (bEspRunInfo[index].pcmd == NULL)
        {
            break;
        }

        if (*(bEspRunInfo[index].pcmd) == NULL)
        {
			......
            break;
        }
        //发送AT指令
        retval = (*(bEspRunInfo[index].pcmd))(index, &bEspRunInfo[index].param);
        if (retval > 0)
        {
            //带有超时时间的等待,等模组的回复
            PT_WAIT_UNTIL(pt, bEspRunInfo[index].at_ack.ack == AT_CMD_ACK_DONE, retval);
            ......
        }
        ......
        //非阻塞延时500ms
        PT_DELAY_MS(pt, 500);
    }
    PT_END(pt);
}

增加b_mod_wifi软件模块

增加b_mod_wifi,提供统一的接口给上层调用。

调用bWifiUp时指定设备号并注册事件处理函数。

b_mod_wifi产生事件并通过上层注册的处理函数抛出。

BabyOS WIFI模组框架

b_mod_wifi主要使用bCtl接口操作设备。因此接入的模组,其驱动需要实现b_driver_cmd.h里所列的命令:

///////////////////////////////////////////////////////////
// Wifi Module Command & Data Structure
///////////////////////////////////////////////////////////
#define bCMD_WIFI_MODE_STA 0           // none
#define bCMD_WIFI_MODE_AP 1            // bApInfo_t
#define bCMD_WIFI_MODE_STA_AP 2        // bApInfo_t
#define bCMD_WIFI_JOIN_AP 3            // bApInfo_t
#define bCMD_WIFI_MQTT_CONN 4          // bMqttConnInfo_t
#define bCMD_WIFI_MQTT_SUB 5           // bMqttTopic_t
#define bCMD_WIFI_MQTT_PUB 6           // bMqttData_t
#define bCMD_WIFI_LOCAL_TCP_SERVER 7   // bTcpUdpInfo_t
#define bCMD_WIFI_LOCAL_UDP_SERVER 8   // bTcpUdpInfo_t
#define bCMD_WIFI_REMOT_TCP_SERVER 9   // bTcpUdpInfo_t
#define bCMD_WIFI_REMOT_UDP_SERVER 10  // bTcpUdpInfo_t
#define bCMD_WIFI_PING 11              // default www.baidu.com
#define bCMD_WIFI_GET_CONN_STATUS 12   // bWfifiConnStat_t
#define bCMD_WIFI_REG_CALLBACK 13      // bWifiModuleCallback_t
#define bCMD_WIFI_TCPUDP_CLOSE 14      // bTcpUdpInfo_t
#define bCMD_WIFI_TCPUDP_SEND 15       // bTcpUdpData_t

增加b_util_queue

上层调用接口,无法立即返回结果。创建队列,给上层调用的接口实质是往队列里抛数据。b_mod_wifi有循环调用的处理函数。从队列中取数据并处理。

static int _bModWifiTask(struct pt *pt)
{
    static bWifiQItem_t item;
    void               *param = NULL;
    int                 wait  = 0;
    PT_BEGIN(pt);
    while (1)
    {
        if (bQueuePop(&bModWifiQueue, &item) < 0)
        {
            return -1;
        }
        ......
        if (wait == 1)
        {
            PT_WAIT_UNTIL_FOREVER(pt, item.handle->result >= 0);
        }
        if (item.release)
        {
            item.release(item.param);
        }
        memset(&item, 0, sizeof(bWifiQItem_t));
    }
    PT_END(pt);
}

优化b_util_memp

启用b_mod_wifi时会自动启用动态内存的使用。虽然BabyOS尽量不使用动态内存,但这种场景下没有想到更好的方法,所以决定这一部分使用动态内存。先前只实现了简单的内存池分配,将其重写。

调用bMalloc采用First fit的规则划分空间使用。

调用bFree释放空间,并将相邻的空闲块合并成。

void *bMalloc(uint32_t size);
void  bFree(void *paddr);

uint32_t bGetFreeSize(void);       //获取空闲大小
void     bMallocFailedHook(void);  //bMalloc失败后的处理,弱函数,用户自行实现

公众号助力DIY

使用BabyOS可以很方便的开发一个带网络功能的小玩意。要想通过手机控制设备还需要服务器和APP。BabyOS都已经提供,方便开发者DIY。

MQTT服务: babyos.cn:1883

关注公众号,每个用户都有唯一的topic,给微信公众号发消息便会自动向主题发布消息。

mqtt


以上内容作为抛砖引玉,期待开发者接入更多的模组。如有问题、建议或者需求,提在仓库的Issue页面。会依次处理。

目前BabyOS的文档不再以pdf形式提供,最新文档的访问入口:https://babyos.cn/doc/