打印
[STM32H7]

STM32H7S78-DK驱动SPI接口WIFI模块(EMW3080)

[复制链接]
6131|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sujingliang 于 2025-5-15 20:19 编辑

起源

在去年STM32H7S78-DK开发板评测中,随套件而来的有一个WI-FI Module (EMW3080-BP) MB1400。
不同常见的WI-FI串口模块,这个模块是基于SPI接口通信。当时就想把它驱动了,但是找遍了例程和application都没有相关资料。倒是凭着ST官方论坛上的互动的只言片语中发现STM32H573I-DK有这款WI-FI模块驱动例程,位置大概在:
C:\Users\用户名\STM32Cube\Repository\STM32Cube_FW_H5_V1.3.0\Projects\STM32H573I-DK\Applications\NetXDuo\Nx_Network_Basics_wifi
由于当时时间紧张,并且能力有限,没有在评测期间在STM32H7S78-DK上的移植。于是一直搁置了,而想要实现对这个WI-FI  SPI接口模块驱动的想法从来没有改变




SPI接口的WI-FI模块

本来想着
今年有幸入围STM32N6570-DK的评测,正好都具有STMOD+CONNECTOR,所以就想着不如在STM32N6570-DK实现对这款模块的驱动,也算了却一个心愿。
于是仿照STM32Cube_FW_H5_V1.3.0的Nx_Network_Basics_wifi例程开始搭建N6下的应用。开始并不顺利,由于对ThreadX、NetXDuo不了解,而且似乎串口重定向和程序有冲突也耽误了一些时间。最后程序调试通了,因为日志已经打印出来了,可以肉眼可见几个线程都跑起来了,似乎一切都向好的方向发展。但接上WI-FI模块,还是报错了无法连接,后来查看了一下STM32N6570-DK原理图,发现开发板上的STMOD+CONNECTOR引出的是串口,而非SPI,乌龙了。无法在STM32N6570-DK中实现驱动这个模块了。

偶然发现

尽管很乌龙,但是经过之前的磨难基本把STM32cubeMX配置和在KEIL中的编码流程搞清楚了,再到STM32H7S78-DK搭建应该是不成问题了。所以又回到原点,在STM32H7S78-DK中驱动这个模块。


照例打开STM32cubeMX,STM32H7RS软件包升级到v1.2.0,选择STM32H7S78-DK。突发奇想为什么每次都费时费力从空模板开始,为什么不从Start My project from Example开始一个工程,也许能解决一些时间。于是就发现虽然软件包的目录中没有WI-FI例程,但是MX例程中是存在WI-FI模块的例程。这难道就是众里寻他千百度,那人却在灯火阑珊处吗?我已顾不上各种复杂的心情,快速生成了工程,在经过漫长的编译,烧录后,验证一切功能正常,可以驱动了。




简单分析一下
这是生成的工程:

ThreadXThreadX是Express Logic公司开发的一款高性能实时操作系统(RTOS),现在由Microsoft维护。
NetXDuoNetX Duo 是 Azure RTOS(ThreadX)提供的 双协议栈(IPv4/IPv6)网络协议栈,专为嵌入式设备设计,支持 TCP/IP、UDP、DHCP、DNS 等协议,具有低内存占用和高实时性特点。
mx_wifi:WIFI模块驱动,其中包括spi接口的EMW3080。
FileX:在这里用来生成网页。


1、main.c主要部分
int main(void)
{

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_GPDMA1_Init();
  MX_SPI4_Init();
  MX_UART4_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  MX_ThreadX_Init();

  while (1)
  {
  }

}
MX_ThreadX_Init();//ThreadX初始化

2、app_threadx.c
void MX_ThreadX_Init(void)
{
  /* USER CODE BEGIN  Before_Kernel_Start */

  /* USER CODE END  Before_Kernel_Start */

  tx_kernel_enter();

  /* USER CODE BEGIN  Kernel_Start_Error */

  /* USER CODE END  Kernel_Start_Error */
}
tx_kernel_enter();//ThreadX入口

3、app_azure_rtos.c

VOID tx_application_define(VOID *first_unused_memory)
中调用了:
    status = MX_FileX_Init(memory_ptr);//处理网页读取
    status = MX_NetXDuo_Init(memory_ptr);//处理网络相关


4、app_netxduo.c

UINT MX_NetXDuo_Init(VOID *memory_ptr)
中执行了:
  ret = tx_thread_create(&AppMainThread, AppMainThreadName, App_Main_Thread_Entry,
                           (ULONG)byte_pool, stack_ptr, stack_size,
                           MAIN_THREAD_PRIORITY, MAIN_THREAD_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);

    ret = tx_thread_create(&AppMain2Thread, AppMain2ThreadName, App_Main2_Thread_Entry,
                           (ULONG)byte_pool, stack_ptr, stack_size,
                           MAIN2_THREAD_PRIORITY, MAIN2_THREAD_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);

    ret = tx_thread_create(&AppIperfThread, AppIperfThreadName, App_Iperf_Thread_Entry,
                           (ULONG)byte_pool, stack_ptr, stack_size,
                           APP_IPERF_THREAD_PRIORITY, APP_IPERF_THREAD_PRIORITY, TX_NO_TIME_SLICE, TX_DONT_START);

生成了几个线程,其中App_Iperf_Thread_Entry生成了一个Iperf网络测试界面供浏览器访问。
static VOID App_Iperf_Thread_Entry(ULONG thread_input)
{
  TX_BYTE_POOL *const byte_pool = (TX_BYTE_POOL *) thread_input;

  MSG_DEBUG("[%06" PRIu32 "]>\n", HAL_GetTick());

  {
    MSG_INFO(" - Device Name    : %s.\n", wifi_obj_get()->SysInfo.Product_Name);
    MSG_INFO(" - Device ID      : %s.\n", wifi_obj_get()->SysInfo.Product_ID);
    MSG_INFO(" - Device Version : %s.\n", wifi_obj_get()->SysInfo.FW_Rev);
    MSG_INFO(" - MAC address    : %02X.%02X.%02X.%02X.%02X.%02X\n",
             wifi_obj_get()->SysInfo.MAC[0], wifi_obj_get()->SysInfo.MAC[1],
             wifi_obj_get()->SysInfo.MAC[2], wifi_obj_get()->SysInfo.MAC[3],
             wifi_obj_get()->SysInfo.MAC[4], wifi_obj_get()->SysInfo.MAC[5]);
  }


  /* The network is correctly initialized, start the Iperf utility. */


  /* Allocate the memory for HTTP and Iperf stack */
  {
    const ULONG http_stack_size = NX_IPERF_HTTP_STACK_SIZE;
    UCHAR *http_stack;
    const ULONG iperf_stack_size = NX_IPERF_STACK_SIZE;
    UCHAR *iperf_stack;

    if (tx_byte_allocate(byte_pool, (VOID **)&http_stack, http_stack_size, TX_NO_WAIT) != TX_SUCCESS)
    {
      MSG_ERROR("Allocation failed!\n");
      Error_Handler();
    }

    if (tx_byte_allocate(byte_pool, (VOID **)&iperf_stack, iperf_stack_size, TX_NO_WAIT) != TX_SUCCESS)
    {
      MSG_ERROR("Allocation failed!\n");
      Error_Handler();
    }

    MSG_INFO("\n##### Please open a browser window with the Target board's IP address\n\n");

    /* Application body. */
    nx_iperf_entry(&IperfPacketPool, &IpInstance, http_stack, http_stack_size, iperf_stack, iperf_stack_size);
  }
}
程序运行起来打印的日志:

浏览器访问返回:



5、与模块相关的配置:
mx_wifi_conf.h
#define MX_WIFI_USE_SPI                             (1)


#define WIFI_SSID                                   "SSID"
#define WIFI_PASSWORD                   "PASSWORD"
6、网页内容定义
nx_iperf.h
#define htmlresponse    "HTTP/1.0 200 \r\nContent-Type: text/html\r\n\r\n"
#define htmltag         "<HTML>"
#define htmlendtag      "</HTML>"
#define titleline       "<HEAD><TITLE>NetX IPerf Demonstration</TITLE></HEAD>\r\n"

#define bodytag         "<body bgcolor=\"#000000\">\r\n"
#define bodyendtag      "</body>\r\n"

#define **_area                                   \
    "<table border=0 align=center width=90%><tr>"   \
    "<td width=30%><img align=left src=ms**.jpg>" \
    "</td><td width=33%></td><td width=33%><img align=right src=nx**.png></td></tr></table>"

#define hrline          "<HR SIZE=6 WIDTH=\"90%\" NOSHADE COLOR=\"#FFFF00\">"
#define h1line1         " <H1><font face=arial color=\"#FFFFFF\">NetX IP Address: "
#define h1line2         "</font></H1><br>\r\n"
#define tabletag        "<table height=50%>"


最后

由于个人能力有限,而且例程篇幅过长不做一一解读了,如果有兴趣可以通过MX生成代码解读。

SPI接口WIFI模块不常见,而且ST在实现上运用了ThreadX、NetXDuo等技术,而且封装了和模块通信的协议,再加上防御性编程,感觉远比驱动一般串口WFI模块复杂,甚至可以说不比直接通过WIFI模块二次开发简单。

终于跑通了,再无心魔,念头通达,修为又可以提升了。



使用特权

评论回复
沙发
地瓜patch| | 2025-5-26 16:51 | 只看该作者
的确spi接口不常见,一般wifi模块都是串口+at指令实现,多快好省,开发简单

使用特权

评论回复
板凳
tpgf| | 2025-5-27 08:32 | 只看该作者
我们可以利用STLINK-V3E的串口调试功能,结合STM32CubeIDE的断点与变量监控

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

121

帖子

3

粉丝