Skip to content

Concepts First

  • STA connection: the module joins a router as a client — the prerequisite for TCP/UDP/HTTP/MQTT communication.
  • Connected vs Got IP: the module first authenticates with the router (associated), then DHCP assigns an IP. CODE_WIFI_ON_GOT_IP means network communication can start.
  • Shell commands: the SDK's Wi-Fi manager exposes connection as shell commands (wifi_sta_connect), so no code changes are needed after flashing.
  • Event callbacks: the example registers an event filter with async_register_event_filter; Wi-Fi state changes (connect/disconnect/got IP) trigger wifi_event_handler.

Example Overview

This page is based on the wifi_tcp example in the official Bouffalo SDK (examples/wifi/sta/wifi_tcp), which demonstrates the full STA connection skeleton:

  • board_init() initializes the board; a shell (bouffalolab />) starts on uart0;
  • rfparam_init() initializes RF parameters, tcpip_init() starts the lwIP stack;
  • A wifi_start_firmware_task task registers the Wi-Fi event filter, starts the Wi-Fi firmware (wifi_task_create) and fhost (fhost_init);
  • The event loop handles connect, disconnect, got-IP, etc.;
  • The shell commands wifi_sta_scan / wifi_sta_connect / wifi_sta_disconnect do the actual work.
  • Sibling examples: wifi_udp, wifi_http, wifi_mqtt, smartconfig_ble under examples/wifi/sta/ use nearly the same main skeleton, adding their own test commands.

Operation Steps

1
Enter the Example Directory

All wireless examples share the same STA skeleton; this page uses the wifi_tcp example. Open a terminal and enter the directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/wifi/sta/wifi_tcp
2
Build the Project

The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:

make CHIP=bl616 BOARD=bl616dk
3
Flash the Firmware

Hold the BOOT button (IO2 on the Ai-M61-32S-Kit), briefly press EN/RST to enter download mode, then flash:

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
Scan and Connect to Wi-Fi

Open a serial tool (baud rate 2000000), wait for the bouffalolab /> prompt, scan for networks, then connect to your router (replace SSID and password):

wifi_sta_scan
wifi_sta_connect Your_SSID 12345678
5
Run and Verify

After a successful connection and IP assignment, the log prints CODE_WIFI_ON_CONNECTED (associated) then CODE_WIFI_ON_GOT_IP (IP obtained) with remaining memory. Disconnecting prints CODE_WIFI_ON_DISCONNECT.

Code Execution Flow

The complete flow from boot to a successful connection:

APIs Used by the Example

board_init()

Initializes the board clock, UART and other basic peripherals; the first step of every main.

Parameters: none

Return: none

shell_init_with_task(shell)

Starts a command shell on the given UART device so you can type commands like wifi_sta_connect.

Parameters:

  • shell: UART device handle (uart0 in the example)

Return: none

rfparam_init(0, NULL, 0)

Loads and initializes RF parameters; Wi-Fi cannot work until this succeeds.

Parameters: pass (0, NULL, 0) for default RF parameters

Return: 0 on success; nonzero on failure

async_register_event_filter(EV_WIFI, handler, NULL)

Registers a Wi-Fi event filter; state changes are delivered to wifi_event_handler.

Parameters:

  • EV_WIFI: event group
  • handler: callback (wifi_event_handler)

Return: none

wifi_sta_connect(SSID, password)

Shell command provided by the SDK's Wi-Fi manager: connects the STA interface to a router.

Parameters:

  • SSID: hotspot name
  • password: passphrase

Return: none (see event logs for result)

Complete Code

The full main.c source of the wifi_tcp example, identical to the official example (examples/wifi/sta/wifi_tcp). Collapsed by default; click to expand:

📜 Click to expand wifi_tcp/main.c full code
c
/****************************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you 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
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include "wifi_mgmr_ext.h"
#ifndef BL602
#include "fhost_api.h"
#include "wifi_mgmr.h"
#endif

#include "bflb_irq.h"
#include "bflb_uart.h"

#include "rfparam_adapter.h"
#include "async_event.h"
#include "mm.h"
#include "board.h"
#include "shell.h"

#define DBG_TAG "MAIN"
#include "log.h"

struct bflb_device_s *gpio;

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/****************************************************************************
 * Private Types
 ****************************************************************************/

/****************************************************************************
 * Private Data
 ****************************************************************************/

static struct bflb_device_s *uart0;

extern void shell_init_with_task(struct bflb_device_s *shell);
extern void wifi_event_handler(async_input_event_t ev, void *priv);
#ifdef BL602
extern void wifi_task_create(void);
extern int fhost_init(void);
extern int wifi_mgmr_task_start(void);
#endif

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/****************************************************************************
 * Functions
 ****************************************************************************/

void wifi_start_firmware_task(void *param)
{
    LOG_I("Starting wifi ...\r\n");

    async_register_event_filter(EV_WIFI, wifi_event_handler, NULL);

    wifi_task_create();

    LOG_I("Starting fhost ...\r\n");
#ifndef BL602
    fhost_init();
#endif

    vTaskDelete(NULL);
}

void wifi_event_handler(async_input_event_t ev, void *priv)
{
    uint32_t code = ev->code;

    switch (code) {
        case CODE_WIFI_ON_INIT_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE\r\n", __func__);
            wifi_mgmr_task_start();
        } break;
        case CODE_WIFI_ON_MGMR_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE\r\n", __func__);
        } break;
        case CODE_WIFI_ON_SCAN_DONE: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE\r\n", __func__);
            wifi_mgmr_sta_scanlist();
        } break;
        case CODE_WIFI_ON_CONNECTED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED\r\n", __func__);
            void mm_sec_keydump();
            mm_sec_keydump();
        } break;
        case CODE_WIFI_ON_GOT_IP: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP\r\n", __func__);
            LOG_I("[SYS] Memory left is %d Bytes\r\n", kfree_size(0));
        } break;
        case CODE_WIFI_ON_DISCONNECT: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STARTED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STOPPED: {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED\r\n", __func__);
        } break;
        case CODE_WIFI_ON_AP_STA_ADD: {
            LOG_I("[APP] [EVT] [AP] [ADD] %lld\r\n", xTaskGetTickCount());
        } break;
        case CODE_WIFI_ON_AP_STA_DEL: {
            LOG_I("[APP] [EVT] [AP] [DEL] %lld\r\n", xTaskGetTickCount());
        } break;
        default: {
            LOG_I("[APP] [EVT] Unknown code %u \r\n", code);
        }
    }
}

int main(void)
{
    board_init();

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    if (0 != rfparam_init(0, NULL, 0)) {
        LOG_I("PHY RF init failed!\r\n");
        return 0;
    }

    LOG_I("PHY RF init success!\r\n");

    tcpip_init(NULL, NULL);

    xTaskCreate(wifi_start_firmware_task, "wifi init", 1024, NULL, 10, NULL);

    vTaskStartScheduler();

    while (1) {
    }
}

FAQ

No bouffalolab prompt on the serial port

Make sure the baud rate is 2000000 and the firmware was flashed successfully in download mode; on some boards the USB-UART adapter must be wired to the uart0 pins.

wifi_sta_connect never gets an IP

Check the SSID/password and that the router has DHCP enabled; 2.4GHz signal may be weak — move closer; watch for CODE_WIFI_ON_GOT_IP in the event log.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23