STM32驱动Realtek RTL8189ES WiFi模块读取MAC地址并下载固件

news2024/11/25 11:54:40

单片机:STM32F103RE
接口:SDIO
Keil 5工程下载链接:https://pan.baidu.com/s/1yIgUJUZcwWOL7xnwA9Rw2Q?pwd=ftxd

Wi-Fi模块电源引脚的连接方法:

【RTL8189ES读取片内MAC地址的代码】

/* 显示WiFi模块参数信息 */
void WiFi_ShowInfo(void)
{
  uint32_t temp32;
  WiFi_EFuseInfo efuse_info;
  
  temp32 = WiFi_ReadReg32(1, WIFI_SYS_CFG);
  printf("SYS_CFG=0x%08x\n", temp32);
  printf("IC version: %c_CUT\n", 'A' + ((temp32 >> 12) & 0x0f));
  
  WiFi_ParseEFuseTable(&efuse_info);
  printf("eFuse section count: %u\n", efuse_info.efuse_sec_cnt);
  printf("eFuse data size: %u\n", efuse_info.efuse_size);
  printf("eFuse usage: %u%%\n", efuse_info.efuse_usage);
  printf("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", efuse_info.mac_addr[0], efuse_info.mac_addr[1], efuse_info.mac_addr[2], efuse_info.mac_addr[3], efuse_info.mac_addr[4], efuse_info.mac_addr[5]);
}

/* 读取并解析片内eFuse数据 */
void WiFi_ParseEFuseTable(WiFi_EFuseInfo *info)
{
  uint8_t table[36][WIFI_EFUSE_SECTION_SIZE];
  
  info->efuse_sec_cnt = sizeof(table) / sizeof(table[0]);
  info->efuse_size = WiFi_LoadEFuseTable(table, &info->efuse_sec_cnt);
  info->efuse_usage = (uint8_t)((info->efuse_size * 100) / WIFI_EFUSE_CAPACITY);
  memcpy(info->mac_addr, &table[35][2], WIFI_MACADDR_LEN);
}

/* 读取全部片内eFuse数据并解压缩 */
uint16_t WiFi_LoadEFuseTable(uint8_t table[][WIFI_EFUSE_SECTION_SIZE], uint8_t *sec_num)
{
  uint8_t header[2];
  uint8_t i, n = 0;
  uint8_t section, mask;
  uint16_t addr = 0;

  memset(table, 0xff, *sec_num * 8);
  while ((header[0] = WiFi_ReadEFuse(addr)) != 0xff)
  {
    addr++;
    if (addr >= WIFI_EFUSE_CAPACITY)
      break; // 头部字段后没有更多数据了, 退出

    if ((header[0] & 0x1f) == 0x0f)
    {
      /* 扩展头部 */
      // 低5位为01111, 说明头部字段有两个字节
      header[1] = WiFi_ReadEFuse(addr);
      addr++;
      if (addr >= WIFI_EFUSE_CAPACITY)
        break;

      if ((header[1] & 0x0f) != 0x0f)
      {
        // header[1][7:4] -> section[6:3]
        // header[1][3:0] -> mask
        // header[0][7:5] -> section[2:0]
        // header[0][4:0] -> 01111
        section = ((header[1] & 0xf0) >> 1) | (header[0] >> 5);
        mask = header[1] & 0x0f;
      }
      else
      {
        /* 无效头部 (数据出错) */
        continue;
      }
    }
    else
    {
      /* 普通头部 */
      // header[0][7:4] -> section
      // header[0][3:0] -> mask
      section = header[0] >> 4;
      mask = header[0] & 0x0f;
    }
    
    if (n < section + 1)
      n = section + 1;

    for (i = 0; i < WIFI_EFUSE_SECTION_SIZE; i += 2)
    {
      if ((mask & 1) == 0)
      {
        if (section < *sec_num)
          table[section][i] = WiFi_ReadEFuse(addr);
        addr++;
        if (addr >= WIFI_EFUSE_CAPACITY)
          break;

        if (section < *sec_num)
          table[section][i + 1] = WiFi_ReadEFuse(addr);
        addr++;
        if (addr >= WIFI_EFUSE_CAPACITY)
          break;
      }
      mask >>= 1;
    }
  }
  *sec_num = n;
  return addr;
}

/* 读取单字节片内eFuse数据 */
uint8_t WiFi_ReadEFuse(uint16_t addr)
{
  uint8_t temp;
  
  WiFi_WriteReg(1, WIFI_EFUSE_CTRL + 1, addr & 0xff); // 地址低8位
  temp = WiFi_ReadReg(1, WIFI_EFUSE_CTRL + 2);
  WiFi_WriteReg(1, WIFI_EFUSE_CTRL + 2, (temp & 0xfc) | ((addr >> 8) & 0x03)); // 地址高2位
  temp = WiFi_ReadReg(1, WIFI_EFUSE_CTRL + 3);
  WiFi_WriteReg(1, WIFI_EFUSE_CTRL + 3, temp & ~_BV(7)); // 清除read-ready标志
  
  while ((WiFi_ReadReg(1, WIFI_EFUSE_CTRL + 3) & _BV(7)) == 0); // 等待read-ready置1
  HAL_Delay(1); // 延时, 防止读取错误
  temp = WiFi_ReadReg(1, WIFI_EFUSE_CTRL); // 读数据
  return temp;
}

【RTL8189ES固件下载代码】
先EnableCard,再DownloadFirmware。

/* 执行WiFi模块上电操作 */
void WiFi_EnableCard(void)
{
  uint8_t temp;
  uint16_t temp16;
  
  // Call power on sequence to enable card
  WiFi_WriteReg(1, WIFI_RSV_CTRL, 0); // unlock ISO/CLK/Power control register
  
  // RTL8188E_TRANS_CARDDIS_TO_CARDEMU
  temp = WiFi_ReadReg(1, 0x86);
  WiFi_WriteReg(1, 0x86, temp & ~_BV(0)); // set SDIO suspend local register
  while ((WiFi_ReadReg(1, 0x86) & _BV(1)) == 0); // wait power state to suspend
  temp = WiFi_ReadReg(1, 0x10005);
  WiFi_WriteReg(1, 0x10005, temp & ~(_BV(3) | _BV(4))); // enable WL suspend
  
  // RTL8188E_TRANS_CARDEMU_TO_ACT
  while ((WiFi_ReadReg(1, 0x10006) & _BV(1)) == 0); // wait till power ready
  temp = WiFi_ReadReg(1, 0x10002);
  WiFi_WriteReg(1, 0x10002, temp & ~(_BV(0) | _BV(1))); // reset BB
  temp = WiFi_ReadReg(1, 0x10026);
  WiFi_WriteReg(1, 0x10026, temp | _BV(7)); // schmit trigger
  temp = WiFi_ReadReg(1, 0x10005);
  temp &= ~_BV(7);
  WiFi_WriteReg(1, 0x10005, temp); // disable HWPDN (control by DRV)
  temp &= ~(_BV(4) | _BV(3));
  WiFi_WriteReg(1, 0x10005, temp); // disable WL suspend
  temp |= _BV(0);
  WiFi_WriteReg(1, 0x10005, temp); // polling until return 0
  while (WiFi_ReadReg(1, 0x10005) & _BV(0));
  temp = WiFi_ReadReg(1, 0x10023);
  WiFi_WriteReg(1, 0x10023, temp & ~_BV(4)); // LDO normal mode
  
  // Enable power down and GPIO interrupt
  temp16 = WiFi_ReadReg16(1, WIFI_APS_FSMCO);
  WiFi_WriteReg16(1, WIFI_APS_FSMCO, temp16 | WIFI_APS_FSMCO_ENPDN);
  
  // Enable MAC DMA/WMAC/SCHEDULE/SEC block
  temp16 = WiFi_ReadReg16(1, WIFI_CR);
  temp16 |= WIFI_CR_HCI_TXDMA_EN | WIFI_CR_HCI_RXDMA_EN | WIFI_CR_TXDMA_EN | WIFI_CR_RXDMA_EN;
  temp16 |= WIFI_CR_PROTOCOL_EN | WIFI_CR_SCHEDULE_EN | WIFI_CR_ENSEC | WIFI_CR_CALTMR_EN;
  WiFi_WriteReg16(1, WIFI_CR, temp16);
}

/* 下载固件 */
void WiFi_DownloadFirmware(void)
{
  int curr, page;
  int i, j;
  uint8_t value;
  uint32_t value32;
  WiFi_FirmwareHeader *header = (WiFi_FirmwareHeader *)firmware_mp_8188e_t_fw_nic;
  
  // 显示固件信息
  printf("Firmware version: 0x%02x\n", header->version);
  printf("Firmware subversion: 0x%02x\n", header->subversion);
  printf("Firmware signature: 0x%04x\n", header->signature);
  printf("Firmware release time: %02x-%02x %02x:%02x\n", header->month, header->date, header->hour, header->minute);

  // 复位8051内核
  value = WiFi_ReadReg(1, WIFI_MCUFWDL);
  if (value & WIFI_MCUFWDL_RAM_DL_SEL)
  {
    WiFi_WriteReg(1, WIFI_MCUFWDL, 0x00);
    WiFi_Reset8051();
  }
  
  // 开始下载固件
  value = WiFi_ReadReg(1, WIFI_MCUFWDL);
  WiFi_WriteReg(1, WIFI_MCUFWDL, value | WIFI_MCUFWDL_EN); // MCU firmware download enable
  value = WiFi_ReadReg(1, WIFI_MCUFWDL + 2);
  WiFi_WriteReg(1, WIFI_MCUFWDL + 2, value & 0xf7); // 8051 reset
  
  // 重置校验值
  value = WiFi_ReadReg(1, WIFI_MCUFWDL);
  WiFi_WriteReg(1, WIFI_MCUFWDL, value | WIFI_MCUFWDL_CHKSUM_RPT);
  
  // 发送固件数据
  page = 0;
  for (i = 32; i < sizeof(firmware_mp_8188e_t_fw_nic); i += curr)
  {
    // 设置页号
    value = WiFi_ReadReg(1, WIFI_MCUFWDL + 2);
    value &= ~WIFI_BYTE2(WIFI_MCUFWDL_PAGE);
    value |= WIFI_BYTE2((page << WIFI_MCUFWDL_PAGE_Pos) & WIFI_MCUFWDL_PAGE);
    WiFi_WriteReg(1, WIFI_MCUFWDL + 2, value);
    page++;
    
    // 计算当前页的数据量
    curr = sizeof(firmware_mp_8188e_t_fw_nic) - i;
    if (curr > WIFI_FW_8188E_END_ADDRESS - WIFI_FW_8188E_START_ADDRESS + 1)
      curr = WIFI_FW_8188E_END_ADDRESS - WIFI_FW_8188E_START_ADDRESS + 1;
    
    // 发送当前页的数据
    for (j = 0; j < curr; j++)
      WiFi_WriteReg(1, WIFI_FW_8188E_START_ADDRESS + j, firmware_mp_8188e_t_fw_nic[i + j]);
    printf("Downloaded %d bytes of firmware (%d-%d)\n", j, i, i + j - 1);
  }
  
  // 等待固件校验完毕
  while ((WiFi_ReadReg32(1, WIFI_MCUFWDL) & WIFI_MCUFWDL_CHKSUM_RPT) == 0);
  
  // 结束下载固件
  value = WiFi_ReadReg(1, WIFI_MCUFWDL);
  WiFi_WriteReg(1, WIFI_MCUFWDL, value & ~WIFI_MCUFWDL_EN); // MCU firmware download disable
  WiFi_WriteReg(1, WIFI_MCUFWDL + 1, 0x00); // reserved for fw extension
  
  // 启动固件
  value32 = WiFi_ReadReg32(1, WIFI_MCUFWDL);
  value32 |= WIFI_MCUFWDL_RDY;
  value32 &= ~WIFI_MCUFWDL_WINTINI_RDY;
  WiFi_WriteReg32(1, WIFI_MCUFWDL, value32);
  WiFi_Reset8051();
  while ((WiFi_ReadReg32(1, WIFI_MCUFWDL) & WIFI_MCUFWDL_WINTINI_RDY) == 0);
  printf("Firmware is successfully downloaded\n");
}

【程序运行结果】

STM32F103RE RTL8189ES
[Clock] freq=400.0kHz, requested=400.0kHz, divider=178
Ignored CMD5 CRC error
RESPCMD63, RESP1_90fc0000
Ignored CMD5 CRC error
RESPCMD63, RESP1_90fc0000
Number of I/O Functions: 1
Memory Present: 0
Relative Card Address: 0x0001
Card selected. RESP1_00001e00
[Clock] freq=24000.0kHz, requested=25000.0kHz, divider=1
[CIS] func=0, ptr=0x00001000
Manufacturer Code: 0x024c
Manufacturer Information: 0x8179
Card Function Code: 0x0c
System Initialization Bit Mask: 0x00
Maximum Block Size: 8
Maximum Transfer Rate Code: 0x32
[CIS] func=1, ptr=0x00001100
Card Function Code: 0x0c
System Initialization Bit Mask: 0x00
Maximum Block Size: 512
SYS_CFG=0xc4403710
IC version: D_CUT
eFuse section count: 36
eFuse data size: 160
eFuse usage: 62%
MAC Address: 30:1B:97:41:C6:65
Firmware version: 0x1c
Firmware subversion: 0x00
Firmware signature: 0x88e1
Firmware release time: 05-05 14:27
Downloaded 4096 bytes of firmware (32-4127)
Downloaded 4096 bytes of firmware (4128-8223)
Downloaded 4096 bytes of firmware (8224-12319)
Downloaded 2942 bytes of firmware (12320-15261)
Firmware is successfully downloaded
SDIO->STA=0x00000000

【兼容最新的只有AC6编译器的Keil 5.38a版本】
1. 在ST官网下载en.stm32cubef1.zip(V1.8.0版本),将STM32Cube_FW_F1_V1.8.0/Drivers/CMSIS/Include/cmsis_armclang.h解压到项目的STM32F1xx_HAL_Driver目录中。(https://pan.baidu.com/s/1_tM1bBlx2Brg9mDPDWdVUg?pwd=sx6t)
2. 在项目属性中Target选项卡的ARM Compiler选择Use default compiler version 6,然后在C/C++ (AC6)选项卡的Define文本框中定义宏__FILE_INCOMPLETE=1。
3. 把WiFi.h里面的typedef __packed struct改为typedef struct __attribute__((packed))。
4. 把common.c中的#pragma import(__use_no_semihosting)改为:
// 禁用半主机模式 (不然调用printf就会进HardFault)
#ifdef __clang__
__asm(".global __use_no_semihosting\n\t");
#else
#pragma import(__use_no_semihosting)
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/644192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【力扣刷题 | 第八天】

前言&#xff1a; 本章将利用栈与队列来尝试解决实际问题。 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&…

chatgpt赋能python:Python批量删除:简化SEO优化的过程

Python批量删除&#xff1a;简化SEO优化的过程 SEO&#xff08;Search Engine Optimization&#xff09;优化是网站运营中不可忽视的一项任务。其中涉及到对内容和网站结构的优化&#xff0c;而这些工作也离不开对数据的处理。其中一个常见问题是需要删除一批旧的或者无用的页…

《统计学习方法》——条件随机场(中)

引言 这是统计学习方法第十一章条件随机场的阅读笔记&#xff0c;包含所有公式的详细推导。 条件随机场(conditional random field,CRF)是给定一组输入随机变量条件下另一组输出随机变量的条件概率分布模型&#xff0c;其特点是假设输出随机变量构成马尔可夫随机场。 建议先阅…

chatgpt赋能python:Python怎么持续输入?

Python怎么持续输入&#xff1f; Python是一个高级编程语言&#xff0c;它的简单易用性让它成为程序员们心仪的语言之一。在Python编程中&#xff0c;输入是一个非常重要的环节。 在这篇文章中&#xff0c;我们将讨论Python如何进行持续输入。我们将介绍几种不同的方法&#…

计算机图形学与opengl C++版 学习笔记 第10章 增强表面细节

假设我们想要对不规则表面的物体进行建模&#xff0c;例如橘子凹凸的表皮、葡萄干褶皱的表面或月球的陨石坑表面。我们该怎么做&#xff1f;到目前为止&#xff0c;我们已经学会了两种可能的方法&#xff1a; &#xff08;a&#xff09;我们可以对整个不规则表面进行建模&…

【期末总复习】数字图像处理知识要点

【A卷】 【选择】 1、计算机器显示彩色图像的格式 2、灰度反转后&#xff08;一副图像灰度级&#xff09;的灰度值是几 3、灰度图像浅色背景下加圆环会导致什么后果 4、图像平滑的模板有哪些 5、γ矫正指的是什么数学变换 6、一阶锐化空间滤波器有哪些 7、图像复原、图像增强…

运维(SRE)成长之路-第1天 搭建虚拟机(图示)

1.Linux安装前准备 虚拟机&#xff1a;用软件&#xff08;如&#xff1a;vmware,virtualbox等&#xff09;模拟硬件,方便实验的灵活配置 虚拟化软件&#xff0c;建议使用 Vmware Workstation 虚拟硬件配置 CPU&#xff1a;2核或更多 内存&#xff1a;1G以上&#xff0c;推荐2…

chatgpt赋能python:Python中如何找出最小的2个值

Python中如何找出最小的2个值 Python作为一种高效可靠的编程语言&#xff0c;拥有出色的处理数据和算法的能力。在数据处理中&#xff0c;常常需要对数据进行排序并找出最小&#xff08;或最大&#xff09;的数值。本文将着重介绍如何在Python中找出最小的2个值。 方法1&…

编程比赛 (ACM竞赛)常用术语

比赛相关 AK&#xff1a;All-Killed 通常指在信息学竞赛中获得满分&#xff08;即 AC 了所有题目&#xff09;。 由于在中高级信息学竞赛中&#xff08;如 IOI&#xff0c;NOI&#xff0c;NOIP&#xff0c;ACM&#xff09;&#xff0c;想要获得满分普遍较难&#xff0c;甚至根…

java三大特性之【继承】

概念 继承就是将多个类的共性抽取出来&#xff0c;提出继承的概念。就是在进行共性抽取&#xff0c;实现代码复用。 提高代码的复用性&#xff0c;方便进行子类&#xff0c;子功能的扩展&#xff0c;将所有共性的内容放在父类&#xff08;基类&#xff09;&#xff0c;子类只…

裁剪lua5.3.4

在 Lua 5.3.4 中&#xff0c;有一些宏定义可以缩小 Lua 的资源占用&#xff0c;包括&#xff1a; LUA_COMPAT_5_2&#xff1a;该宏定义可以将 Lua 5.3 的行为与 Lua 5.2 兼容&#xff0c;缩小 Lua 的资源占用。例如&#xff0c;该宏定义可以禁用一些 Lua 5.3 中新增的语法特性&…

在线协同办公小程序开发搭建开发环境

目录 介绍 开发环境说明 虚拟机 原因 VirtualBox虚拟机 VMware虚拟机v15 安装MySQL数据库 安装步骤 导入EMOS系统数据库 安装MongoDB数据库 启动Navicat&#xff0c;选择创建MongoDB连接 创建用户 搭建Redis数据库 配置Maven 安装IDEA插件 Lombok插件 …

基于Java+SpringBoot+Vue实现前后端分离美术馆管理系统

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【哈佛积极心理学笔记】第15讲 完美主义

第15讲 完美主义 A person committed to excellence can still be as ambitious or more ambitious than a perfectionist. The difference between the two is just their approach toward the journey. There is no straight line toward success. Perfection vs Excellenc…

CMake入门(1)

背景 目前很多大型框架都是使用cmake去构建&#xff0c;如果看不懂cmake, 在实际修改框架&#xff0c;添加新的模块时候就会受制于人&#xff0c;为此需要了解cmake的相关基础支持&#xff0c;避免被某些装逼大佬卡脖子&#xff0c;同时也进一步提高自己的业务水平。 变量 c…

Hello算法学习笔记之数组与链表

一、数组 线性数据结构&#xff0c;其将相同类型元素&#xff08;链表就不一定要存储相同类型的元素&#xff09;存储在连续的内存空间中。。数组有Index 数组的优点&#xff1a;访问很高效&#xff0c;O&#xff08;1&#xff09; PS:元素长度是单个元素占用的内存空间&…

CSS基础学习--13 Display(显示) 与 Visibility(可见性)

一、定义 display属性设置一个元素应如何显示 visibility属性指定一个元素应可见还是隐藏 二、隐藏元素 - display:none或visibility:hidden 隐藏一个元素可以通过把display属性设置为"none"&#xff0c;或把visibility属性设置为"hidden"。但是请注意&am…

Aprioi关联算法

国际权威的学术会议IEEE International Conference on Data Mining (ICDM) 评选出了数据挖掘领域的十大经典算法&#xff0c;他们分别是&#xff1a;C4.5、kMeans、SVM、Apriori、EM、PageRank、AdaBoost、KNN、Naive Bayes以及CART。今天就让我们共同探讨一下十大算法之一Apri…

红黑树的插入和删除

红黑树&#xff08;C&#xff09; 红黑树简述红黑树的概念红黑树的性质红黑树结点定义 一&#xff0c;红黑树的插入插入调整插入代码 二&#xff0c;红黑树的验证三&#xff0c;红黑树的删除待删除的结点只有一个子树删除结点颜色为红色删除结点颜色为黑色 删除的结点为叶子节点…

【OpenMMLab AI实战营二期笔记】第六天 MMDetection代码课

0. 环境检测和安装 # 安装 mmengine 和 mmcv 依赖 # 为了防止后续版本变更导致的代码无法运行&#xff0c;暂时锁死版本 pip install -U "openmim0.3.7" mim install "mmengine0.7.1" mim install "mmcv2.0.0"# Install mmdetection rm -rf mmd…