你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

Marvell 88W8686 WiFi模块创建或连接热点并使用lwip建立http服务器

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE" l" H! R3 I5 P- {$ [
PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。
* |) J. J  q/ ]) x5 X7 t# a注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
9 Q- J- u: R' K2 S8 K9 R该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。
0 \( J, K" p& e4 y' F1 M: L- [4 v固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925  i. q* i8 P& j" R! G
: M/ D/ J& Q2 C! M; w7 T& ]
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!
. E  l  \- a1 ]
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】
! `2 M0 o; X1 D, e
  1. #include <stdio.h>
    ( J) `6 F* L' L1 u
  2. #include <stm32f10x.h>
    4 Y" b' |- H/ f6 |/ s* N# r
  3. #include <string.h>
    $ g) S  R  A3 A3 O  G
  4. #include "lwip/init.h" // lwip_init函数所在的头文件
    3 g5 d! v( S* S3 R( a
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件0 x+ l$ V, }; }' ^
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件9 d% s, \! a: Y6 q9 \8 [- s: Y
  7. #include "WiFi.h"
      `* @. u; G, Q, I7 i1 J' S

  8. 4 F% |& D" ?9 F4 v
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明
    / V2 J7 b8 x( D
  10. err_t ethernetif_init(struct netif *netif);
    6 u5 q" {% ]3 ^% E" i
  11. void ethernetif_input(struct netif *netif);
    ) i. k: p4 g) S0 F% [, f
  12. 2 x3 o8 x& x, L; v% z0 Y1 n4 Q' R
  13. // httptest.c中的函数
    # P8 V: ]3 X8 [
  14. void init_http(void);
    1 Y. _  w/ J4 A4 I

  15. 3 p0 w& L- i" z' C7 a* T1 Z
  16. // 延时n毫秒
    : u' M% T. y' r! a" ~+ \# p
  17. void delay(uint16_t n), c+ D- B7 N4 t. M* B7 k' |7 B
  18. {
    0 y; T6 f  |% n2 |# k
  19.     WiFi_PrepareTimer(n);) c) u$ {( a7 w8 i7 l) t" |
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕2 M6 w) H6 a5 {2 g- Z6 p9 f
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
    * X9 G( x6 S8 U( H5 E* U
  22. }; I: f( ^) H1 F0 m# u+ W6 l

  23. & k6 r! d9 ?9 ?5 |% e3 C
  24. void dump_data(uint8_t *data, uint16_t len)
    % ^: z6 q' N; O
  25. {( y! T# x7 k( N: {
  26.     while (len--)
    $ J5 B& k6 G5 b) C2 v
  27.         printf("%02X", *data++);2 S* Z* M) j8 a: n3 {) a7 l
  28.     printf("\n");
    - |  j3 d7 B- o. h& ^
  29. }
    / w+ k! @# O- M; R* D# N/ J

  30. : d  @# j  C7 K
  31. int fputc(int ch, FILE *fp)
    9 ?3 P, S' v% ?9 _, s' A& i6 P8 y
  32. {& t# X2 X5 i7 V( I( t
  33.     if (fp == stdout)" v: H+ s  F% h1 A& _
  34.     {
    ; g! Q3 K, ?4 v" v* N
  35.         if (ch == '\n')
    / @7 I4 f4 p$ H
  36.         {& d: C9 m6 y9 e5 I0 C' b: l
  37.             while ((USART1->SR & USART_SR_TXE) == 0);
    0 v# p0 y" X1 K. `5 g2 u) z" m  ~
  38.             USART1->DR = '\r';
    - o* X, g- o5 ]+ S- L; D
  39.         }
    ) d( }9 {! S: h" ~0 v* T' ~, J1 P
  40.         while ((USART1->SR & USART_SR_TXE) == 0);
    $ G; U7 D, e3 P) _: e' e$ V" {
  41.         USART1->DR = ch;4 r1 d9 A+ h- U+ E
  42.     }
    ( r' K: A3 D. D( L
  43.     return ch;
    * U. j/ V) S: N9 R" Y  A: X. m$ ]) b
  44. }
    2 O* Z$ s( Y' t! K

  45. * T# w0 H# I' C
  46. // RTC时间转化为毫秒数
    ; I1 B% t. M5 S! T
  47. uint32_t sys_now(void)9 A+ e/ q8 W* @6 g5 L! H; N2 W
  48. {
    1 t: v2 G9 r! L9 o' ]
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
    & ^2 m+ b) M5 f1 x0 \: A
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒# M( u* L* {, Z' J
  51.     return tmp;
    " y$ N5 g  E  O9 z7 d
  52. }
    - T# w* @% {% @3 u2 H

  53. ! _, |. [8 {4 Q& j6 ?1 d
  54. int main(void)! b( z) X5 d- W' n9 {
  55. {& t; _- c1 H  j( }
  56.     struct ip4_addr ipaddr, netmask, gw;
    9 T3 t4 K! e+ h# f& L; G. E2 O9 {- k
  57.     struct netif wifi_88w8686;* s# r4 u, [& e  n
  58.     uint32_t last_check = 0;
    ' o5 |: p; O0 Y+ W' {& K3 H/ P
  59.     6 g# y  C8 j/ u% m$ m& A  [6 E
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;, i- `1 r/ S: s* I0 m4 Q
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;
    2 d" |# O8 u+ \0 A* z9 z
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;
    ) D$ V. n% S' _5 ]; l+ r5 q- q7 U- h
  63.    
    7 e$ ?, j* A# s. M$ z
  64.     GPIOA->CRH = 0x000004b0;1 {! }7 |! y  b& ^! P- F' a
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块$ h+ h8 e/ j5 X8 z7 W
  66.     GPIOC->CRH = 0x000bbbbb;7 V  z* E  a0 V6 ^* q+ a
  67.     GPIOD->CRL = 0x00000b00;
    8 f: x* ]8 R5 D, w
  68.    
    - O6 M; b, }- }/ l3 m: ?
  69.     USART1->BRR = 0x271; // 波特率: 1152008 `' o& E/ B6 M7 w
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;1 S: M/ F# I$ n# o4 @
  71.    
    : u/ S' M- w% n% z6 i) V! s
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器" Q4 @, @7 F3 u
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)2 \0 D, X. F  A! b5 N0 n  p$ X8 F
  74.     {
      q4 |$ D8 K% r8 Z4 M* j
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI
    . n1 J$ c, w1 N3 N/ x2 I
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
    " E' a! Z  q5 |/ }6 ~
  77.         //printf("LSI Ready!\n");
    ! K2 d4 ?2 P& T1 H4 ?$ {
  78.     }  ]; @' Y. r: v, N( i
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)2 p# m# N  l4 Y$ m+ e
  80.     {- G' }$ l$ U% X0 I3 n; U
  81.         // 若RTC还没有打开, 则初始化RTC+ _4 U, {3 l5 f7 k" f$ @! m  U
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时
    1 U3 O5 b1 d) {% f" L7 M
  83.         
    5 p. k! n* |" r* P9 [
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式
    6 f* T3 J* ]* \2 K
  85.         RTC->PRLH = 0;. e: a; a' D( e. @
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
    * \; l2 r. W( b
  87.         //RTC->CNTH = 0;$ W6 ^2 p& W* D; A
  88.         //RTC->CNTL = 50; // 初始时间
      j; g0 L$ r: N0 _3 R) R
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置
    ; T: y$ \$ e4 f* S" S
  90.         
    + ?( P. \: j2 ]6 r3 ^$ M5 d" l6 T
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
    ; H& C( H0 C0 |9 f' t5 x
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效. u5 h: U; L) [' N
  93.         // RTC从此处开始走时
    2 ?$ l! V, V1 C- ]& U
  94.     }0 e& A) G; x( @
  95.     7 }% s% y$ m, J- z
  96.     WiFi_Init();; C$ h! a7 Z& g, G% b
  97.     WiFi_Scan();
    + l' V2 _# i/ Z4 z' B
  98.     ' _+ _* {( Y2 ]7 h; g$ r9 G* W
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点
    $ M* z0 t2 D% m: ~# {( S
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    % U6 t# P/ a. `6 w  [
  101.    
    ! Q4 x1 |) j4 V7 U5 S
  102.     lwip_init();) h) f% {+ Y2 G% z! Z
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址
    7 c- h& i* ]: E' D1 j$ \6 J0 E3 d
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
    7 a+ G3 b. P4 R4 T& ~+ w# z
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
    0 q0 x5 k5 u$ o6 K
  106.    
    6 P1 a/ M- y5 h
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    7 \- _* F# ]' m5 Q& s# V/ x
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡
    * F% w! C2 q3 O  i  j7 ?/ q8 |
  109.     netif_set_up(&wifi_88w8686);2 ?( n; E4 n" p. Z4 F; L# N
  110.    
    1 M  ^8 j3 o9 Y# d+ }, f
  111.     init_http();' {% [! v, d3 W$ M8 M$ G
  112.    
    + k; R9 ^& v: E9 _
  113.     while (1)
    # r4 ?. N8 r! s3 o, G
  114.     {
    0 e( Z; i1 }* W
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())" p( s! q' }+ n% P+ u
  116.             ethernetif_input(&wifi_88w8686);
    5 c* h3 E* E2 w' [
  117.         % U4 m+ I( S( L5 k5 K+ z) Q* e/ x
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)( a2 K) {  X* x7 X. z. ~
  119.         if (sys_now() - last_check > 200)
    - p- p. m3 ^" ?, d5 ~
  120.         {) _4 y7 a1 i9 q6 Z- e
  121.             last_check = sys_now();. I8 x3 g: `. l6 W  C2 j9 z. S) G
  122.             //printf("Time: %d\n", last_check);" X+ |1 T% p, D: i: b
  123.             sys_check_timeouts();3 b6 d  U( @: @
  124.         }- o" i! ~, O8 |( u
  125.     }# {% i& Q/ }" H7 U; a" U
  126. }
复制代码
【httptest.c】
, B1 v: E- a" }% u
  1. #include <string.h>
    0 R- E! C0 I, b. s' `; s
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件
    2 i  @: ]+ R5 C' |( v7 z% ~

  3. / P* E7 D- o' l! f/ r( m0 T
  4. #define STR_AND_SIZE(str) (str), strlen(str)# u6 C. A& e% T/ b! k% b# @. B# W
  5. " F! n8 E' C5 N  M( P9 {
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)! ]' ^5 j0 _) k3 B0 ?& V
  7. {
    % |6 {9 B3 {" J, T3 c
  8.         char len[10]; // 存放HTML内容的长度
    % d3 n$ O& E) Q. e
  9.         char str[200]; // 存放HTML内容9 `7 `6 B* r" g
  10.         
    9 I7 b( A& W9 G' V  A
  11.         char name[100];
    % T& h" {. B, b+ ]
  12.         char *pstr;
    4 S; u8 Q3 L, T' @* \, r9 d
  13.         uint8_t i = 0;
    ; E# I1 ^& [1 l
  14.         if (p != NULL)5 L" c! t& C) O0 `/ F
  15.         {2 ?9 c5 v$ }9 O- ]# a6 D
  16.                 // 提取页面名称
    5 B& r' H$ i* ~7 B) j$ p
  17.                 pstr = (char *)p->payload;. L7 g1 ^; h% P. K5 _: p  h
  18.                 while (*pstr++ != ' ');
    . n/ O$ t% g" a# c* G" J, Y
  19.                 while (*pstr != ' ')
    & O; I/ B7 Z4 u' }
  20.                         name[i++] = *pstr++;
    5 \6 Z( Q( ~/ b8 r/ w0 m7 n
  21.                 name[i] = '\0'; // 不要忘了结束name字符串1 ?8 i% |* N. H
  22.                 tcp_recved(tpcb, p->tot_len);0 Y, j$ T& g7 D6 v! q2 V% \
  23.                
    , v& Z; t& J9 i
  24.                 // 生成HTML内容
    + j" g% {/ Q3 g+ i4 g( x( S+ J
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
    ( `, S- B$ b0 w- ]  V1 Z7 Y8 S& w) i
  26.                 : r' E( x1 E4 O7 r" u
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度
    ) h& @: c# E$ i- p: R
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
    - p7 C9 d- H7 E
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
    8 c4 F* D6 X) D; `
  30.                 tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE);- L: R* J. ^6 n
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容9 e$ \! m$ Q1 {5 j) T- o$ o
  32.                 pbuf_free(p);. E: y) u9 K, Q# j/ @% G
  33.         }4 S0 S& M2 o: ^- x3 e. N( i( o
  34.         return ERR_OK;
    / Z7 z% h; b/ |' f% ?
  35. }% S  j& h9 H0 c0 O* a

  36. 8 V  f. t( q8 s8 I* p+ J$ y
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    ! {0 p) O" l3 c# C
  38. {
    1 V. v. g- {) L. I/ m$ q  F- T
  39.         tcp_recv(newpcb, http_recv);' V( f, I1 s# u2 B. Q9 ~; @
  40.         return ERR_OK;
    ; @$ |- o. Q3 ~' V
  41. }
    1 F1 t0 l8 x5 e2 p! z
  42. 1 ]! M6 L$ u( i1 K, L
  43. void init_http(void): g* _4 Y7 j8 T
  44. {* |) \" g0 c* X3 z
  45.         struct tcp_pcb *tpcb = tcp_new();0 L9 K, G9 b0 N, g$ r! |4 U
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);
    ; h; \  x/ E- y( r% b: g$ X+ ~
  47.         tpcb = tcp_listen(tpcb);/ Y4 Q: I4 x0 ]6 w6 Y2 ?2 b' t
  48.         tcp_accept(tpcb, http_accept);; l; P: B$ u4 v
  49. }
复制代码
【WiFi.h】
" t1 `# b4 `) d" W1 v4 P2 C* l) ?
  1. #define _BV(n) (1u << (n))
    + _& R& z" i5 p" O8 Q+ e

  2. 0 M! z8 k. @7 _- o3 X
  3. #define CMD52_WRITE _BV(31)
    , L# C2 V' _1 F3 }. k0 z7 k) N" M( Y
  4. #define CMD52_READAFTERWRITE _BV(27)
    8 h+ c2 t5 V, L% x6 u

  5. . e# u1 W1 H) |
  6. #define CMD53_WRITE _BV(31)' e5 {, |8 C! U( i& M' J' A( N
  7. #define CMD53_BLOCKMODE _BV(27)
    7 [$ P5 }3 @4 j7 F, A4 S6 o7 e
  8. #define CMD53_INCREMENTING _BV(26)
    ' {" a* [3 h1 e/ [" e

  9. ) s, J6 U! K5 @7 {0 Y% \
  10. // 16.5 SDIO Card Metaformat# R3 P" W' Y; s  n. a+ G  ]
  11. #define CISTPL_NULL 0x00 // Null tuple
    3 |0 Q$ p2 {2 l8 M: q
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information
    8 p4 h* N4 h9 B8 Y3 w
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    6 \  Y7 Y! v+ s; t  A9 b
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple
    3 o& B4 _9 c" H  ]1 G( O
  15. #define CISTPL_FUNCE 0x22 // Function Extensions
    * H6 U9 A; `7 n2 o
  16. #define CISTPL_END 0xff // The End-of-chain Tuple
    # `' E5 T$ v$ y$ ^
  17. 6 a% Y4 [. B* i  T/ \3 D7 J  w
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)1 c  y8 I9 a# S5 @) H

  19. 7 c1 V& ~7 {7 x! g" M. P
  20. #define WIFI_SQREADBASEADDR0 0x10% m6 C8 N6 m& h7 \' o3 r2 I" L
  21. #define WIFI_SQREADBASEADDR1 0x11) B& C. N) i6 R# W# U. r9 H$ u
  22. #define WIFI_SQREADBASEADDR2 0x12
    / K6 q  Q. z; h( E, B3 s% K) ^2 w5 Q
  23. #define WIFI_SQREADBASEADDR3 0x13
    " R1 Z" W2 E$ Z! ]0 {) }; x2 X: {
  24. ' ^5 ^9 T8 Q: E, H
  25. #define WIFI_CARDSTATUS 0x20 // Card Status% {) a2 v& c3 g' }
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator4 f4 ]$ z+ k& ]. ]8 I  x6 B8 [
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    / @) J5 e0 Z" z$ d( `8 |
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
    ; n3 k. w& g5 t
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
    1 t1 `# v4 k! j9 a5 u# }# {

  30. - c) N$ T+ o' |+ d3 }5 b
  31. #define WIFI_CAPABILITY_BSS _BV(0)) m- u7 s6 Y1 O
  32. #define WIFI_CAPABILITY_IBSS _BV(1)
    7 `0 l! n0 a* I$ v
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)
    " \) j9 C) m7 w
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)$ B2 f1 ^# `1 m; y* V3 q5 b
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)
    ; W: l3 _$ Z8 x0 J
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)
    1 ], L( X4 M, i; D3 I
  37. #define WIFI_CAPABILITY_PBCC _BV(6)- H. [* H8 x$ h$ G9 v' q$ [
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)
    ! `. x7 V- u$ t4 ~" J8 X
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)5 V/ c* ]( F2 c9 E' p
  40. #define WIFI_CAPABILITY_QOS _BV(9)
    0 ]3 B# t! C+ w& }
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)7 M# x/ b2 i) M( h% F
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)5 f) E, f  Q$ W0 i( {2 U
  43. : o5 P0 {/ A8 C4 [# ]+ t
  44. #define WIFI_SDIOFRAME_DATA 0x00! x* q# T1 E% m3 \9 P1 W7 O: \) r2 b
  45. #define WIFI_SDIOFRAME_COMMAND 0x01# x! c9 M* d: A! f
  46. #define WIFI_SDIOFRAME_EVENT 0x032 d! ~$ k% e0 l" P# P
  47.   M5 O5 H; @+ r" e8 b) W( G) w
  48. /* Command List */* X0 w. ]; ~+ W! M" ?
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    & V; l1 m! ~/ O) @5 K8 \
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP
    6 O% R* C9 r. e( D1 ]
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC, Z7 Z5 V; E9 E( R
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
    1 B7 K) D2 K2 W8 k. M+ O
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address
    1 ~4 {0 d' R% P; t0 j$ O& E9 I
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption
    & ?. l6 Z& f4 O( _
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration+ \+ I: z  K8 a+ b# Y
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results
    6 y9 f( L1 l( g% ?
  57. , V5 ?: v. w: F  |+ r" Q& i. X
  58. /* Command Result Codes */+ b  C! z% q6 t& |8 M
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error
    - V! x0 u. e7 S5 S/ e- J9 C
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed! n5 `, \" v+ Y( N, a, K
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported
    ; {! b. w$ f" J. q# F/ N+ M

  62. 6 J* S5 W% n) T) H/ j" Q, I+ Y( O
  63. #define WIFI_ACT_GET 0) S, t3 [# b( z/ m* l/ l$ r
  64. #define WIFI_ACT_SET 15 _$ ~: B  _$ _, i3 K

  65. . j* [7 ~" o8 Y. W8 o
  66. /* Authentication Type to be used to authenticate with AP */
    ( x6 |: |, _5 a. r
  67. #define AUTH_MODE_OPEN 0x003 b# l9 {0 K: Z1 H
  68. #define AUTH_MODE_SHARED 0x01
    $ G# |# s- q0 j* t9 q* o
  69. #define AUTH_MODE_NETWORK_EAP 0x80
    / _* g$ o( _8 B" I, O1 u* |

  70. & S( E2 u3 e3 X$ z& a9 \
  71. /* WiFi_Associate return value */
    4 w- ^9 l0 r" S4 k$ Z
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe1 B( L3 ~9 p0 w( g! q
  73. #define WIFI_ASSOCIATION_ERROR 0xffff8 I1 B5 H6 G/ m
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功
    + I3 [3 S/ _1 J0 x
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101
    & c( ~9 T& }3 U6 |, X, a, ]
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧" M) K0 w6 p# K0 t
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213/ B' e6 G. }/ Q3 U* z: J1 p
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214/ r. ?& ?1 l+ X* Z# o* ?5 h9 z- C
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败) M4 l# s! b2 b* u( j, e
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时
    2 R# p) D2 M0 s
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时
    ' U4 C. [% y$ `  `, A. Z
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时7 ]( K5 W8 ~2 @/ `6 ~9 l& \
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
    7 F% o3 d  g. S* Q" ]9 i! ^

  84. 9 s3 p' B4 |; A( M6 G5 g- R
  85. #define WIFI_KEYTYPE_WEP 09 S. w+ y, A! k3 {5 q& R
  86. #define WIFI_KEYTYPE_TKIP 1; Z9 L! o: m/ \' [
  87. #define WIFI_KEYTYPE_AES 2
    ) J; a1 O+ u1 |  ^; |* I

  88. 2 {- i! u' R- l! k
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2): U* }2 z  `, I
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)
    : r! x! w. y+ W9 C
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)4 Z; r- o" i5 U3 F( Y) B1 f

  92. # ]' r3 x( n; [- ~
  93. #define WIFI_MACCTRL_RX _BV(0)
    - R8 }. c% y" r& m' z; b+ s
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!+ t. G5 B$ z5 k, D
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)! Y, ]3 c! e& q* W0 B, Y  T* l
  96. #define WIFI_MACCTRL_WEP _BV(3)2 _  c% g0 R5 u& Q
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)
    ' }! q/ I1 d& u2 V
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)  Q3 o# G# v7 \8 V+ n3 h4 X
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)/ }$ t# F* V: I  n9 k' R2 a& l
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection: f$ i# {, z" g. r% L0 ]2 W
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode& `& F( M- O+ K4 e
  102. $ |8 `. q  K6 |8 Q" R0 ^- P6 a2 x4 @
  103. /* BSS type */" W$ a5 G3 @4 Q& ~7 R
  104. #define BSS_INFRASTRUCTURE 0x01" ^& v/ |$ l# M+ G' O5 U% u* f
  105. #define BSS_INDEPENDENT 0x02
    ; Y6 r9 f  q/ G& P: Q4 G1 D! M
  106. #define BSS_ANY 0x03
    & a0 T: Y& S. j. Z5 I# q& O6 f' z6 L
  107. ! b! n' E3 D2 o
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */
    9 g7 b' V& m* t4 [
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */  J6 v4 y3 X* C+ e, u3 ?
  110. #define MRVLIETYPES_SSIDPARAMSET 0x00006 C3 G$ p' v7 T, i4 c1 V) Y" j8 R
  111. #define MRVLIETYPES_RATESPARAMSET 0x0001
    , [& m& U$ c) O6 W3 f# C+ ^0 W  b
  112. #define MRVLIETYPES_DSPARAMSET 0x0003( E# w9 P# Z2 V5 g& e4 S
  113. #define MRVLIETYPES_CFPARAMSET 0x0004
    " q4 R0 b* R( I
  114. #define MRVLIETYPES_IBSSPARAMSET 0x00069 _& f# E9 T4 H! {" Z; ~. {% I% d
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030
    " ^4 d% r& ~. a
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd2 t+ [, ?, R4 o/ M7 Y' U' I$ ?

  117. + a) c$ [2 G9 `8 q8 t7 R
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100- O* n% o/ S# Z3 i
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101
    5 w- l) ]1 H! Y- i% F8 h0 m; G
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x0113
    - K/ |& P3 ~8 k# }
  121. #define MRVLIETYPES_AUTHTYPE 0x011f8 K) V! H/ I2 s( Y

  122.   a& j, h) t/ Y" c
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小2 k+ o3 N4 L+ f1 J7 u% ]
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小) r% P0 Z  N" J! f$ o
  125. ( P$ A- O0 J, W9 @( t' u2 O$ X( c
  126. typedef __packed struct. c5 Q* _7 h7 E& n0 e; S) |
  127. {
    ' u$ v' _2 T/ o2 h9 \1 P
  128.         uint8_t type;
    3 @; C6 h- _: }9 j
  129.         uint8_t length;
    , G  \6 j" e8 Q8 \
  130.         uint8_t data[1];# h, _. h. ]8 |) B
  131. } IEEEType;  Z9 a- O" d+ H- L: x$ m# e0 b
  132. : l5 `* K& t3 i7 ?: R) U
  133. typedef __packed struct
    2 F; X3 p. D9 S) ^5 |% u+ o
  134. {" U2 D: q0 a- i7 T: K
  135.         uint16_t ie_length; // Total information element length; E6 x9 o& y, T/ i& P
  136.         uint8_t bssid[6]; // BSSID' N/ e9 _  [; p/ _, R: Z0 Z+ A: n  }
  137.         uint8_t rssi; // RSSI value as received from peer
    % i3 m4 B+ z3 B% w4 U- V' a! S
  138.         
    " g) x' {; m/ ]8 i$ U
  139.         /* Probe Response/Beacon Payload */% s3 k7 o! W2 B' L( g) ~; {& D
  140.         uint64_t pkt_time_stamp; // Timestamp
    ( Z0 ?0 j  S! f1 P7 ~
  141.         uint16_t bcn_interval; // Beacon interval1 E5 d7 w( a8 C9 J: u
  142.         uint16_t cap_info; // Capabilities information1 p3 T$ a6 k( ^% X" I6 I- {- \
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据  \" Y& v- m9 Z) L- k" D) M. h
  144. } WiFi_BssDescSet;3 F. B" k7 r1 c: m  |% y( T/ a

  145. ( w3 X. m& w5 N: e, p
  146. typedef __packed struct9 _/ Z) q9 [* T3 d; i$ C1 Y0 v5 ]2 v
  147. {+ J0 |( s4 h& H3 ^" V9 f
  148.         uint8_t oui[3];
    + p/ r  c  w% B2 ~
  149.         uint8_t oui_type;
    / s: `3 `, C: b& f7 f
  150.         uint8_t oui_subtype;  H7 i. Z! h1 v& v' g8 j
  151.         uint8_t version;: _. D1 \) C- m4 {5 j" U
  152. } WiFi_VendorHeader;  Y8 f/ X- H) d( K1 }4 i2 z
  153. . T" U6 @# T7 H0 e% |+ S  T% K
  154. typedef __packed struct, T$ d  Y5 o0 @  k8 k+ t- T1 ^7 U2 F1 k
  155. {3 l. ]% _$ e) K: s
  156.         uint16_t type;# N# s8 R0 p; {' C' V' u
  157.         uint16_t length;3 j3 f0 }8 @& V4 r& ~6 \
  158. } MrvlIEHeader;# R+ c2 z  b: Z! R9 R9 o" F
  159. . P* w' _& Q% f4 e0 V
  160. typedef __packed struct2 ]4 ]2 `, s4 E% @
  161. {3 q* u; ]5 {" t! k
  162.         MrvlIEHeader header;
    " k, M4 T% m) x$ b4 J2 w! o, f9 g
  163.         uint16_t auth_type;
    : j' w! L% D; ~2 x* p$ m
  164. } MrvlIETypes_AuthType_t;
    ) j9 m# j6 u2 }
  165. 5 c( t- f* ^+ a; B; j$ u0 B3 k
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec
    ; b! n! N3 L& g9 \% d0 Q% ?
  167. + X6 s+ f7 |* X3 N9 o; m; l' R" E
  168. typedef __packed struct
    - t$ T5 ~2 q8 A; o  K, A
  169. {
    ' a+ \5 N' m& ^% I. ^
  170.         MrvlIEHeader header;
      K' ~# {% n4 x; s+ C
  171.         uint8_t count;( T2 s' V9 B$ D: [9 J6 G# \
  172.         uint8_t period;& e  [$ E% O0 }- g1 h
  173.         uint16_t max_duration;
      b( K' {! B$ |7 F9 g
  174.         uint16_t duration_remaining;: ^9 S5 Z6 c# m9 }1 b! n2 t: _
  175. } MrvlIETypes_CfParamSet_t;, L3 k  x/ n; O% }4 G

  176. 1 W* p3 h/ E. x+ E& ]
  177. /*typedef __packed struct
    6 R: \0 C0 [  ]- r# U" T
  178. {
    - I" }- S' _, `" J. n
  179.         MrvlIEHeader header;
    - n, i# y1 A" G
  180.         __packed struct
    * O: M$ w& ]- X
  181.         {
    0 M* Q" V& P9 u: p$ [4 w
  182.                 uint8_t band_config_type;
    ! v% z* Q! r" Q7 P8 v
  183.                 uint8_t chan_number;
    & ?. V* T% u! Q0 j
  184.         } channels[1];
    9 h) e$ G7 q+ J' Y* i8 _1 p; \
  185. } MrvlIETypes_ChanBandList_t;*/) V) o6 s+ k5 a. K

  186.   C. S3 l9 @% Q. L/ k" u
  187. typedef __packed struct
    / F$ w, A4 \7 c- C2 {
  188. {+ U1 B$ O/ S# p9 a! V7 u3 ~* A5 n
  189.         MrvlIEHeader header;
    2 Z7 h( g; g8 q& x6 Q
  190.         __packed struct' Y- M6 p* D, \+ q) D9 s: [& t
  191.         {- ^' V: p1 g$ h7 S7 k
  192.                 uint8_t band_config_type;( a4 t8 s. c) U) [1 N
  193.                 uint8_t chan_number;' ]8 b( e# l. b. @2 f4 f  S2 K
  194.                 uint8_t scan_type;
    " ~: v/ [6 |0 \9 t0 k' s# R" ~% }
  195.                 uint16_t min_scan_time;+ a6 y$ o9 Q1 r: b# _. R5 `
  196.                 uint16_t max_scan_time;
    ) i9 t. u: P1 P  E' s9 k
  197.         } channels[1];" Z9 u$ _* K- o  P9 ~8 p& u2 x3 C
  198. } MrvlIETypes_ChanListParamSet_t;9 S: E7 x5 s1 u- ?# P+ q

  199. ! F  c2 }( [) C# T! M0 s
  200. typedef __packed struct  D1 p# |5 O7 C
  201. {  u$ F$ Z5 T, n: T
  202.         MrvlIEHeader header;
    8 y+ G4 z* w7 ^% u+ W8 }) d
  203.         uint8_t channel;5 `$ g5 p, l8 L. R6 v! T3 |" ?
  204. } MrvlIETypes_DsParamSet_t;
    / k1 ~1 s6 j' h" L; A

  205. 9 Y4 ]: O; K8 n6 ~) i+ z5 e, G7 X' v
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
    . _/ E) ^  N* b% {% s8 W0 ]5 ]4 A
  207.   T8 O4 p0 n" K, i) i( M5 b
  208. typedef __packed struct3 E9 r2 [9 [( w7 |- O
  209. {
    ( S7 b0 _% x6 R6 w8 Q
  210.         MrvlIEHeader header;9 `% z2 B, s/ H* J
  211.         uint16_t atim_window;
    0 `1 i- [" v$ b; {
  212. } MrvlIETypes_IbssParamSet_t;0 V, H$ e7 D3 |

  213. - X! g& r. b7 U3 t, o( O4 L; X
  214. typedef __packed struct
    0 I+ d, |& S/ C- y# v
  215. {
    : Z3 o$ X4 J2 `7 _
  216.         MrvlIEHeader header;) l! ]% D9 n) V& L) s; o
  217.         uint16_t key_type_id;9 X. B% Z" E. J+ F# j) s
  218.         uint16_t key_info;8 C; B5 P) A' s7 m
  219.         uint16_t key_len;8 {# U9 `. c. _
  220.         uint8_t key[32];8 h% i. O) r9 W7 q. a
  221. } MrvlIETypes_KeyParamSet_t;6 x9 e: G4 F! X7 I/ s0 Y; Q. t
  222. ) W6 N1 j  }6 w4 }) W( {
  223. typedef __packed struct
    ; @, N% P' C8 m0 Z5 |9 J
  224. {
    1 C2 L. C9 x8 a, Y" D; ^3 N
  225.         MrvlIEHeader header;
    + ^/ B1 S* O, a9 n+ \+ A) t
  226.         uint8_t rates[14];! c  H+ H- m  Y
  227. } MrvlIETypes_RatesParamSet_t;
    / o( i; i/ Z  q& n/ D2 m( x
  228.   o/ O# V- P$ L) H: K
  229. typedef __packed struct
      v! `9 ~4 v5 J+ }- Z9 H
  230. {
    ' ^. j3 F; x) V9 f8 Z
  231.         MrvlIEHeader header;# _. J0 s$ Y1 A! N8 C$ V) r
  232.         uint8_t rsn[64];
    % N( `3 Y! q. z& m0 g
  233. } MrvlIETypes_RsnParamSet_t;/ E- N% G$ A5 @
  234. 8 i1 C6 ~% N3 i* s: z  b
  235. typedef __packed struct
    8 O" }6 g  f9 A. Y( x" T
  236. {' S* l) H  W( r% @
  237.         MrvlIEHeader header;
    * ^1 f( M  Z3 W; g) k
  238.         uint8_t ssid[32];1 G6 d9 J/ ^1 ]- z2 B1 e/ W, `
  239. } MrvlIETypes_SSIDParamSet_t;* F$ T2 m% i- z$ k1 E

  240. & D  \) X1 E/ y
  241. typedef __packed struct5 A6 O( [2 j6 {* Z" `+ L+ {
  242. {
    6 @3 h8 j( t% F3 m% {8 A9 I
  243.         MrvlIEHeader header;- U- m4 |$ t& h
  244.         uint64_t tsf_table[1];" g& E4 n7 T# ]' i( ?
  245. } MrvlIETypes_TsfTimestamp_t;7 M. h  d4 o5 _6 |6 V

  246. : R) _3 ~. f$ Q+ X5 p2 v( E- r0 g
  247. // 整个结构体的最大大小为256字节5 @1 v: n/ S& x5 K2 ^7 p: @: J
  248. typedef __packed struct
    . `9 n' A4 ^6 Y( a" h' N  X$ i
  249. {
    9 K  V$ w/ m0 w; S7 r3 `. G
  250.         MrvlIEHeader header;- S6 D& E# e1 {
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够4 ^; X' F8 R( I2 A& ^0 E' e- P
  252. } MrvlIETypes_VendorParamSet_t;
    , H1 J1 s& k) P$ w1 ~6 F$ w7 b

  253. # t& R: E6 W( H  m/ X; W
  254. typedef __packed struct
    8 B, j" u5 T  d4 M9 s
  255. {
    1 m4 ?+ R) _& [- A" X$ I
  256.         uint16_t length;$ [5 u8 s) ]1 v" C8 m4 \
  257.         uint16_t type;
    0 r% S4 j3 R. x2 q
  258. } WiFi_SDIOFrameHeader;
    3 ?' B) Z- t% v: f% A6 @5 M1 Z
  259. . f/ @# y8 v7 [6 q" J9 v. R
  260. typedef __packed struct
    / V" X+ L0 N$ P! m# K2 a
  261. {/ p# m1 f1 M/ I+ Y4 D# C
  262.         WiFi_SDIOFrameHeader frame_header; 5 K3 K! K$ M8 T3 ?
  263.         uint16_t cmd_code;! }$ {& n$ @: b- b
  264.         uint16_t size;
    % q6 f0 w8 @* r. I. S! h
  265.         uint16_t seq_num;& j, T2 I3 W1 N' g# \" U; l) r
  266.         uint16_t result;
    $ J) q* }1 v$ d: [5 z! p2 J
  267. } WiFi_CommandHeader;& n, `0 N  v) U7 K

  268. " d. R6 f, e$ T  P
  269. /* Table 2: Fields in Receive Packet Descriptor */0 R: R, m3 v+ v# v1 [1 r
  270. typedef __packed struct+ l9 `, L  s/ a- V8 f5 b3 ]
  271. {2 {1 I6 Y0 k+ P/ N4 a
  272.         WiFi_SDIOFrameHeader header;
    - X- S, c$ n% S: a6 z5 K5 ]5 t
  273.         uint16_t reserved1;
    6 B% Y$ O  D1 c  i6 b5 D/ X: ~  J/ S4 K) X
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)' y/ C1 _& h0 k" U: ]# x# X
  275.         uint8_t reserved2;3 p0 R1 n( m7 h+ d
  276.         uint16_t rx_packet_length; // Number of bytes in the payload
    - V: \- B2 U6 W; {3 M
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.8 o- O0 w* w7 t9 g
  278.         uint8_t rx_rate; // Rate at which this packet is received
    , d0 j) G0 a+ D& H
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet
    : I4 y& c  m6 \6 C* B5 F1 ^
  280.         uint32_t reserved3;+ w  r* n% h8 U1 V
  281.         uint8_t priority; // Specifies the user priority of received packet
    " v% F% T* N' Z1 s0 _7 J) z
  282.         uint8_t reserved4[3];
    / \8 s( W  D! g/ e- q
  283.         uint8_t payload[1]; // 数据链路层上的帧4 {& z9 [, @) V  e) o0 T7 T
  284. } WiFi_DataRx;8 h! N0 A0 F4 N
  285. / k( B3 v& V1 h5 y6 K
  286. /* Table 3: Fields in Transmit Packet Descriptor */! z  Q* @1 h; `
  287. typedef __packed struct% q0 ?" B1 f" D# e! V
  288. {
    9 X5 X- m- o! e+ f0 V
  289.         WiFi_SDIOFrameHeader header;
    * |7 s- d% a9 J4 M" N/ p
  290.         uint32_t reserved1;8 h$ H4 U9 |6 L3 F! y" ?9 }) o  k
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings/ o! }) a, l! C4 V0 y
  292.         uint32_t tx_packet_offset; // Offset of the beginning of the payload data packet (802.3 or 802.11 frames) from the beginning of the packet (bytes)
    0 Z6 M( J$ k; v, d* W5 l
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame# @. r! t9 Q) Y( Z9 X/ j7 N. M9 w
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5$ A0 o( Z6 A" H& H8 x
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3
    " b1 b/ B( _. }5 x# s
  296.         uint8_t priority; // Specifies the user priority of transmit packet" q2 J: X, R+ V9 Q
  297.         uint8_t flags;
    2 A7 a6 L/ ]( W* [' |& E
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations! O' n" d8 J" B. W
  299.         uint8_t reserved2;% g3 c; h+ K( @( u+ C, h
  300.         uint8_t payload[1]; // 数据链路层上的帧
    0 S' T. m1 ^1 L! K/ Q/ u4 Y; Z
  301. } WiFi_DataTx;
    ( U: d! c( @/ E, A0 _7 A) a
  302. % W; g, |( S0 h$ S* d! Y4 W# Z
  303. typedef __packed struct) d& J4 |* G0 S
  304. {
    : R$ S( t1 T9 b4 R* e
  305.         WiFi_CommandHeader header;: n( A' p+ w0 B: ?* U
  306.         uint16_t action;: M) S) y9 D% z& w, v9 I
  307. } WiFi_Cmd_KeyMaterial;" s9 Z4 ~. J  s& C% m# L2 w! T( N: u; h
  308.   q% R; P, E7 c5 N
  309. typedef __packed struct
    + ~5 X; n! x' n4 R) D' U1 s4 I4 R4 X  G
  310. {" Y; ]. i8 L# H
  311.         WiFi_CommandHeader header;
    2 L; G; t& _1 ~+ Q1 G
  312.         uint16_t action;
    % {  p6 d0 J1 l  [% T
  313.         uint8_t mac_addr[6];& _/ l0 ^6 _7 ]% ~
  314. } WiFi_Cmd_MACAddr;
    ' C9 b2 A( Z- j9 g/ M# W

  315. 0 D1 M  H' J7 C& [
  316. typedef __packed struct
      [5 D4 z, \# Q( N
  317. {2 l) B" T$ @* n; w
  318.         WiFi_CommandHeader header;' x, j* G6 q. T9 ], C% x
  319.         uint16_t action;
    4 N$ Q# }9 ^1 p) k3 o5 S
  320.         uint16_t reserved;
    ' }! a8 `1 n& e
  321. } WiFi_Cmd_MACCtrl;
    & @# P! q/ F! S

  322. & J. @1 y3 c# Q: g( Y
  323. typedef __packed struct
    ! ~6 I% _2 ~: @7 v1 N5 G
  324. {
    0 l* R. k) Z( G7 X* \/ u: y" t
  325.         WiFi_CommandHeader header;
    - u1 Q* q+ a  `/ n. J
  326.         uint8_t ssid[32];
    $ x0 I9 c3 ^5 U# t, N
  327.         uint8_t bss_type;
    , J8 o) y& o( U/ P9 C% A
  328.         uint16_t bcn_period;1 `( J0 Z7 {0 b
  329.         uint8_t reserved1;
    0 l9 U8 \, @* k) n0 \
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
    * S1 y1 K2 H. C
  331.         uint32_t reserved2;
    7 s6 K3 I) h* e" Y
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network
    % r" Y3 R4 V" x+ z
  333.         uint16_t reserved3[3];  t) E  q. z0 P& [7 s/ X1 @  T
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information6 l- Z  ^8 q  y
  335.         uint8_t data_rate[14];
    - f! b; |8 u7 y0 T* i9 s4 D: r
  336. } WiFi_CmdRequest_ADHOCStart;0 R' N6 X% h* ]* o. w9 ?, H

  337. ; ^# i0 c2 s! d3 Y& w9 r+ `2 |: d
  338. typedef __packed struct* W0 u- x8 P) F4 L
  339. {5 K( g+ ?- Q, L/ r6 F5 `
  340.         WiFi_CommandHeader header;
    6 h, D* z0 U5 e# k! m; I! v
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address$ l1 \' V7 t6 o0 ]# w1 D
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information# t2 M3 Z5 I- R! p
  343.         uint16_t listen_interval; // Listen interval
    * {& j0 {$ ?3 i& g0 K
  344.         uint16_t bcn_period; // Beacon period
    & j! J% w2 k2 t+ Q/ Q8 z
  345.         uint8_t dtim_period; // DTIM period) b4 R# s/ V, q9 N4 f; y
  346. } WiFi_CmdRequest_Associate;
    ; ]2 N9 p! b, C+ W$ k& J9 o( Z
  347. $ F8 a3 ]$ b! L" l$ }; U* o
  348. typedef __packed struct
    : Z) [, h' b9 I  Z4 r0 I6 S2 u* a1 H
  349. {
    ' o6 K% o3 y4 ?; e9 z6 l
  350.         WiFi_CommandHeader header;
    9 a& n( N& X5 P2 h% r) q
  351.         uint8_t bss_type;
    : A% R4 v6 T7 L4 D+ M: J1 p) E; E7 }
  352.         uint8_t bss_id[6];
    & Z. p3 }( e9 o8 u5 ?' u, x
  353. } WiFi_CmdRequest_Scan;( T9 C: O3 j0 _4 S; c3 a& L4 w
  354. ! ^* P- k2 m6 \. O( O
  355. typedef __packed struct. M' i& F' y7 t
  356. {9 T9 d* w: H  ?* d
  357.         WiFi_CommandHeader header;
    . J) E& d( a. x2 ?4 U
  358.         uint16_t capability;
    % d8 V# `& e; N! Q6 h, ^
  359.         uint16_t status_code;
    + u" x; R# `0 Q! j2 X/ b3 n
  360.         uint16_t association_id;8 C/ O5 c! s( U8 ?% A
  361.         IEEEType ie_buffer;" @' c" ^9 C7 S" Y- y' m( b
  362. } WiFi_CmdResponse_Associate;
    4 ~* C3 F. ^) b+ |# ?
  363. # J8 ^# B  V0 E* |6 Q
  364. typedef __packed struct  J. @# D) d' h! j: _
  365. {
    . }7 L( d4 F5 b4 b2 b  T' m
  366.         WiFi_CommandHeader header;
    $ a/ g1 j* N2 R) n( {: u3 D0 T8 t4 g
  367.         uint16_t buf_size;' p0 h& W' V; m% n* T$ n8 v+ p# y; F
  368.         uint8_t num_of_set;
    ( A/ `# O7 }' |( F
  369. } WiFi_CmdResponse_Scan;
    . m3 B6 B+ v: F8 {) i. k

  370. 5 g4 ^: H7 o# O6 a. s" q% l* q
  371. typedef __packed struct  s# A4 O* l1 k4 x& u
  372. {
    / R( x! a6 U9 ^8 Z& ^9 c  p
  373.         MrvlIETypes_SSIDParamSet_t ssid;( R: b# z, o' `7 y5 [4 w% X
  374.         uint8_t mac_addr[6];1 g9 l1 F/ P1 u
  375.         MrvlIETypes_CapInfo_t cap_info;& o+ c  U, Q' A& v  z* r- U
  376.         uint16_t bcn_period;* [1 f, I9 e; _4 P4 d
  377.         uint8_t channel;0 u8 r2 l3 B# M( k
  378.         MrvlIETypes_RatesParamSet_t rates;2 Z3 G& D* y5 w5 c* r; ^
  379.         MrvlIETypes_RsnParamSet_t rsn;
    0 n  d. }8 m% z; L7 W- h+ e
  380.         MrvlIETypes_VendorParamSet_t wpa;
    - s' _, U% _/ n# E+ e0 H
  381.         MrvlIETypes_VendorParamSet_t wwm;
    3 h- O5 R4 C. N+ K5 B$ r$ I) U% X
  382.         MrvlIETypes_VendorParamSet_t wps;
    ! D( E$ ~. a- d6 R7 j  E0 w0 u
  383. } WiFi_SSIDInfo;# E' l) H6 v: j0 i4 g, R; D/ o( l

  384. & Y* n5 d. F3 h4 r% Y! d
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)
    . g$ q* z1 o8 k# i+ o  J& u
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)
    8 F5 N6 o) S& e4 R6 U. o
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)
    / A/ @% b9 ?* F1 h2 u6 V1 k
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY); d! S, u  n6 O; S  U: I. v
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)  E" |3 Q0 t) [+ W: I
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)
    * U4 ?; `) c' b6 ^6 f
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)3 e; H3 _" L$ ?2 _0 z

  392. ! ?# _1 I% D4 o/ a7 L; O
  393. uint16_t WiFi_Associate(const char *ssid);
    + C7 e4 Q5 N+ f4 e
  394. void WiFi_CheckCmdTimeout(void);
    ' `" O0 t; v9 E. F8 w. m5 j0 h
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    & n5 x' N* D( F+ v3 g
  396. uint8_t WiFi_DownloadFirmware(void);4 p  q; K7 |6 {. J, R
  397. uint16_t WiFi_GetPacketLength(void);, Q$ R- E' I; c; ^) b
  398. void WiFi_Init(void);' D8 j) ?3 o( m
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
    3 o/ O% D# N( O# J" [' f  j
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
      S! n, S1 A* A; h+ S
  401. void WiFi_MACControl(uint16_t action);
    ! y: Q7 C' J* e8 s  Z) H5 }4 W
  402. uint16_t WiFi_PacketPending(void);
    ( l* B9 ]) a1 d5 E" S2 Z6 r! v- @) h
  403. void WiFi_PrepareTimer(uint16_t nms);
    + C- p5 b( U* a8 r% B
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);
    3 F0 P0 L. K  Q& Y( _
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
    % a8 u2 f" k$ J& f
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);9 Z3 e* M2 K$ A( l) @
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);6 i8 q! u0 [! N# K; v3 q' B* Y7 U
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);' a3 }: V  b) _: N6 L) O! i
  409. void WiFi_Scan(void);
    - C9 G9 d$ j0 x# K( X
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);
    $ [: g9 p  Y% ?& V9 x
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);) M- F5 y3 t: Q. N4 f
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    % j- H) @+ n9 Z" m/ N
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);
    , l* B+ b9 v5 S# I& F0 p
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);
      O9 p) }% O4 G9 \7 ~7 A
  415. void WiFi_SetBlockSize(uint8_t func);
    - k" O) a1 Z) V9 K
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);
    # z1 a7 |; Z$ `8 [6 x& m
  417. void WiFi_ShowCIS(uint8_t func);( Y' [6 i# q3 c5 x
  418. void WiFi_ShowKeyMaterials(void);
    6 U$ W  E' [# f0 g8 x- I& S2 [" m
  419. uint8_t WiFi_StartADHOC(const char *ssid);
    ( N3 a+ I0 Z% V
  420. uint8_t WiFi_Wait(uint8_t status);& E4 L# T! K- e; l6 S9 H
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);" n: p" z+ p- L' ]
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
    ' m. O0 E3 Z  G4 P" K  B5 l
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);
    0 Z" y6 U( _+ C8 `) ?
复制代码
【WiFi.c】
! e- [, I* U! M/ e; }1 E7 ~/ M
  1. #include <stdio.h>4 a* \8 ~& _5 p( A
  2. #include <stm32f10x.h>! `: m) H1 X/ r: c: J
  3. #include <string.h>
    ; x; y4 F, B1 x  L1 b4 G$ {
  4. #include "WiFi.h"
    3 t. y0 Y. V, b  d1 k1 y
  5. " u% h  ]$ B. ~" H4 g& ~9 [
  6. extern const unsigned char firmware_helper_sd[2516];/ c$ b+ P1 B+ t; f0 @3 Y
  7. extern const unsigned char firmware_sd8686[122916];7 R* |3 l! Y# M, m

  8. 8 S2 D. L0 h7 Y  S: o
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
    $ K! N) D2 {( m: K4 M1 B

  10. 5 v4 G4 o! u8 n6 Y. g
  11. static uint16_t rca;4 q  \4 d* _6 F% w5 k
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;1 u1 B0 Y6 N  a- f' {/ O! _0 B
  13. static uint32_t io_addr;
    5 b; _2 e! X2 B  K( E
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小
    7 a' ?: N/ T. y7 e3 ~

  15. - v! I& V; _1 U9 b
  16. void delay(uint16_t n);' \7 Q' s; S& e7 T* B
  17. void dump_data(uint8_t *data, uint16_t len);! Y) c6 r2 t: k# a$ K5 _. l
  18. 7 B# F! m4 m/ n% c% Y
  19. /* 关联一个热点 */' Z8 ?5 o0 ~4 Z2 w
  20. uint16_t WiFi_Associate(const char *ssid)
    / @7 T) f. F' @( a% J, N- e, |
  21. {
    ( O' y3 L. w1 V8 _' D/ A8 n
  22.         uint8_t buffer[2048];% M! S( q% V6 X; }5 I+ H4 A# u- _
  23.         WiFi_SSIDInfo info;7 |3 T1 t) q/ b3 j' W( x$ F8 ^, ?
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;9 q. y! z' ]# F- O4 b
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
    5 X9 u" R0 ~6 C; E% T! \" G
  26.         MrvlIETypes_DsParamSet_t *ds;3 z# y0 Y! @- a( _; I, _
  27.         MrvlIETypes_CfParamSet_t *cf;3 |- ~# V& r/ `& P
  28.         MrvlIETypes_AuthType_t *auth;
    1 o2 n) {8 e, `2 {# ~
  29.         MrvlIETypes_RsnParamSet_t *rsn;
    / H2 Q3 W( L/ n4 R& H4 W, M, o
  30. % @$ {0 r& u' c# Z. O8 z! p
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))9 ?$ \; l; j9 P/ C7 S; A
  32.         {/ r$ c. R( x- W$ F
  33.                 printf("Cannot find AP: %s!\n", ssid);
    4 g7 a* z0 j: o
  34.                 return WIFI_ASSOCIATION_NOTFOUND;
    # V+ \5 `0 _$ n4 g: x9 L: L  ~
  35.         }
    ! v: q* i3 U8 L  \: C
  36.         
    % F' N9 `) m! ]
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));& L" f$ _5 c: O; x$ j- h( f
  38.         cmd->cap_info = info.cap_info;
    5 _6 S2 t) m- y0 I
  39.         cmd->listen_interval = 10;' k, Z3 r7 @" H( J2 \5 s7 H
  40.         cmd->bcn_period = info.bcn_period;( D6 n8 J# `' ^0 h7 Q) M
  41.         cmd->dtim_period = 0;
    % A* i" d1 V1 r: o& R
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));4 h4 a+ T9 J5 }0 t) g  ?" {0 N+ ^
  43.         2 o, w' e  ?6 z7 ^
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));- S0 L* w2 S1 b+ I. @& K
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;& t  v- X& F, z  e* c
  46.         ds->header.length = 1;
    7 u% s, V* W* o3 B. Z3 }/ y* ^
  47.         ds->channel = info.channel;
    # ?. ^: }' F" b. A- R6 {8 U4 l
  48.         ( {1 J+ S) I- E: i$ L) A
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);2 y1 w4 s: T( N; q  D
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));
    ! a- `1 G( `* h) Z# W) A1 L1 _
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;
    9 s# b1 M$ R! t$ U" E* i
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);" n( U3 ^) H8 J% U  w1 S2 C$ ?
  53.         
    + V; `) X/ t6 E
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));8 A  ]2 q) g1 h; v
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    ! Q. ~4 X( V& ?2 G4 S  A
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;
    1 a$ C- J' e+ w- z" @2 \9 Z
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);
    $ w( T( M0 z* S3 d
  58.         auth->auth_type = AUTH_MODE_OPEN;4 t6 P% y. D, T& |
  59.         7 i" [/ s& l: I0 i) V
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);* w4 o7 w" o6 X) H  ?
  61.         if (info.rsn.header.type)' `5 U4 A# ]) T6 V) T; D2 ]0 L# n
  62.         {4 Q% T7 V2 d  t  o6 h
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接4 q& |* Y6 A* k2 T  ?8 X" B
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));4 f( J9 \7 `8 X- F
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));
    ( y& k7 u7 X& c3 ]
  66.         }- U# b: n! j) b( [" S
  67.         else; B9 U1 E' Y5 `8 z& A* ]2 _" u
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数
    + ?2 }5 l* ]6 u6 D0 q  r7 N
  69.         
    ) ~5 J% ~2 w4 ^) {( ?/ l
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))& V5 Y! g9 d( l1 W
  71.         {- F. h! e6 S* Z$ G
  72.                 printf("Association with %s failed!\n", ssid);
    , s8 r( M3 ?/ q
  73.                 return WIFI_ASSOCIATION_ERROR;
    2 i! Z, k; j. o; T' z+ @
  74.         }
      @1 f5 N+ b9 Q8 d
  75.         
    9 B( C; j) J5 g- M1 u$ @
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);$ z0 |6 l) R1 D+ ]
  77.         if (resp->association_id == 0xffff)* C6 m9 ?( m: c# s' c0 W
  78.                 return ((-resp->capability) << 8) | resp->status_code;9 N1 n6 p7 t% _1 x$ j
  79.         return WIFI_ASSOCIATION_SUCCESS;* i) X8 Z7 u* Z& h' O
  80. }
    & g5 d* m" a6 p, T, x2 f( x2 I

  81. 0 L' v0 b  C: a. z* i/ A+ g
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    2 [) p2 |/ e, n% m, y2 M+ z4 F
  83. void WiFi_CheckCmdTimeout(void)
    + q3 d* f6 \. h  I+ C) E
  84. {6 B7 _* E9 x% f6 d
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)& A% I2 M3 D+ a# y4 P/ q
  86.         {
    - R2 f& Y+ A) f& ]7 O# O1 H
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志
    # a1 f5 U& I2 c1 m1 ?
  88.                 SDIO->CMD = SDIO->CMD; // 重发1 {% }1 f" R5 ]
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);. j0 [1 [; w- D0 l0 N( {) j
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);
    8 L( f- F! j3 F0 T1 g3 `7 G
  91.         }  h) f7 G0 @8 B/ c3 g" z
  92. }
    4 N0 G* `9 \/ J- q7 C* G
  93. ) m* b. t& V) \  k
  94. /* 连接WiFi热点, 并输入密码 */9 _9 l, \& T$ C0 k# B
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)" c5 X5 K5 {. \* p& i
  96. {+ S0 X7 m+ Q0 F; G4 o0 |: w1 I  ^
  97.         uint16_t ret;
    / E, o' J) {3 A, x7 }% ~: w3 w+ e! k- ?# n$ X
  98.         do% P. n8 F; P0 |" x
  99.         {
    0 t* E  g" A) g* F2 J; I. p$ _
  100.                 ret = WiFi_Associate(ssid);
    ! |( x6 h/ l. m9 k- p
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)
    $ V2 B4 f) O* S: R9 w
  102.                 {: e2 n" t5 \- R7 \; R- L- N
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);
    6 ~5 t. X6 n3 r4 H- i2 {
  104.                         delay(2000); // 等待一段时间后重连1 g0 G$ E$ x5 x6 _8 b
  105.                 }1 p+ R8 g9 B& h0 J& S
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连+ G+ a( S5 \2 z( [
  107.         
    7 K' G# t! K8 v, F
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)0 L8 E2 B+ `& t7 Z% C" T
  109.                 return ret;
    * e& \$ Z' ^% J5 t9 r4 j
  110.         5 x6 ?6 |9 X& \
  111.         printf("Connected to %s!\n", ssid);
    " e+ ]9 o! i+ P
  112.         return ret;
    " ~  W! Y5 B; [; c; ~
  113. }
    % X( T: a# M! R. w
  114. # I% x% a; j% j% D8 [
  115. /* 下载固件 */
    , X( ~6 ]0 V7 y# v/ U- t
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc7 t7 e( t$ I8 E2 j4 W& o( U1 g
  117. uint8_t WiFi_DownloadFirmware(void)
    5 c# @4 R, s; p) j
  118. {
    ( f' k! Y+ A- ^! @' t' v, `
  119.         uint8_t helper_buf[64];5 Y3 o) b% B6 ~
  120.         const uint8_t *data;, e8 s& ~7 r: T* C/ b/ V7 T0 }& e
  121.         uint16_t size;
    / {  B# p5 k" ]& S
  122.         uint32_t len;
    3 a9 Z( G4 }, y3 O5 ?/ `( R% l1 t
  123.         
    - E4 T4 |& e) P: {7 `4 {5 h
  124.         // 块大小设为32
    ) F, _! {0 F& D
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;
    1 \1 O) c, ~  O5 C8 W' {, ?- L
  126.         WiFi_SetBlockSize(1); // 应用到Function 1- B1 v, o7 \  [$ t
  127.         0 d( ]. {' n+ t' h4 `0 b' Q
  128.         // 下载helper4 M) c& y$ X5 V1 v0 h, k0 t$ Y
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);  N: P+ o2 K5 v2 J
  130.         data = firmware_helper_sd;) K. Q# D5 j. V( t, s8 e
  131.         len = sizeof(firmware_helper_sd);, Y9 ]; }+ F4 E9 t/ R( \
  132.         while (len)
    2 A- M# w) v2 w- o# W9 A8 R
  133.         {
    8 V" H/ S0 n; }# i8 @
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量, f4 g, ]+ h# g6 {6 }3 d, M# E
  135.                 size = (len > 60) ? 60 : len;
    / U( p! F2 P2 I% y
  136.                 *(uint32_t *)helper_buf = size;% _) l9 C6 D  E' F/ o2 I
  137.                 memcpy(helper_buf + 4, data, size);
    " R- G" e# y- M3 A7 n# u7 ^
  138.                 / T( m6 ~9 P, g& Y4 n
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    6 e! O6 L1 C; g
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));
    7 t' o. h4 D+ a1 j* h
  141.                 len -= size;  v: @& E+ b; M1 O7 n
  142.                 data += size;
    / w; t1 ?% Q+ l; J
  143.         }
    " R) ?) g1 T' q) {6 w7 E+ g
  144.         *(uint32_t *)helper_buf = 0;0 D4 {7 o% A8 j/ z0 Y
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束% u& ^% b/ F3 Y- ]
  146.         " Q! {. o1 L  @$ M2 T8 b
  147.         // 下载固件
    5 D2 m% ]* q9 Y) T: S
  148.         data = firmware_sd8686;
    , z1 r3 f% S) l0 I
  149.         len = sizeof(firmware_sd8686);$ u  _% ~4 Y6 h4 U5 p* @" \
  150.         while (len)
      \, W* w5 o0 n% {* b* c1 q
  151.         {" v* o# N9 ?# S3 j/ B) U
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    $ W* z. s' y$ h- ?
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数
    # b% T- V8 s1 D6 Y2 I
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);
    : X) y3 M- ^& e6 o' R
  155.                 + f" V, k, J& m! e  {9 o
  156.                 if (size & 1)
    * O  Q- n2 v3 ]9 K
  157.                 {" T' U( ~* n& c; I6 V- [
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)
    # [7 q% M4 v/ _; Z7 g7 w8 b' o
  159.                         printf("Error: an odd size is invalid!\n");
    ) I; `" p5 s6 _+ b+ ]/ n7 ?
  160.                         return 0;3 r7 F& c$ W7 l! \9 j
  161.                 }( y0 x* k  i+ H5 t3 _& G: N
  162.                 if (size > len)
    0 n8 Y! D! D$ R) y/ o
  163.                         size = len;
    ; y% z/ {! t$ Y6 T8 l$ @7 L
  164.                
    # I/ G% c' p4 V. H
  165.                 if (!WiFi_WritePort(data, size))
    5 O% `( B+ w5 ]" x: {; m) L
  166.                 {
    ' \  J6 n1 e# b" \
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);6 P! [, l! H: Z+ p* L
  168.                         return 0;
    3 Q  ]5 C5 y; H
  169.                 }
    ! n5 l+ t0 G$ {. H5 l  O
  170.                 ; K7 A8 q6 Q% i# u7 Y
  171.                 len -= size;
    2 ]( I" u# {# o, `' u6 X0 r" j
  172.                 data += size;3 _3 k  [) o$ v8 Q. O
  173.         }
    ' ^# K! x# i+ q( ?! }' i  Z! R
  174.         
    % y5 u! |! ?/ h! [$ q3 Z8 w
  175.         // 等待Firmware启动
    / F$ M6 _- s8 y" s. j$ B  [# o; A* L
  176.         while (WiFi_GetPacketLength() == 0xfedc);6 _" f! Q' ?% @, [- ]' u7 W
  177.         printf("Firmware is successfully downloaded!\n");3 o4 \/ R% ^# g* J; S0 k9 S
  178.         return 1;- Y; k$ x# \& j
  179. }
    7 ]& ]6 P  j3 ?% g+ p
  180. # c  l" k% Q4 q, J- H4 u" s
  181. /* 获取数据帧大小 */, s* I4 R( ]" M3 C  v3 w5 d) S  y
  182. uint16_t WiFi_GetPacketLength(void)1 c  c9 }( I. }: [2 u
  183. {+ r( s: Z7 u" r' K, |5 b
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);
    4 U2 N. \! o. u% r
  185. }
    # R. ]8 y! o- K- }
  186. 1 b/ a2 \2 @( f  |+ P6 w
  187. /* 初始化WiFi模块 */
    1 W$ }5 |! U! d* ~8 l0 Y: c% t3 m
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization$ K3 [) j; h: h$ p+ p4 y7 ^" F# H2 v
  189. void WiFi_Init(void)
    0 X( `8 l; K/ u
  190. {
    ) V$ V0 X7 S' O( k3 A
  191.         printf("Initialization begins...\n");
    + T: T/ P8 r9 y
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;
      [4 E0 s4 Q& d9 }9 y& M& p
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz
    3 ^( }. Y6 O) C* {2 i" G
  194.         delay(5); // 延时可防止CMD5重发! h( `. @( {. f
  195.         
    5 Z$ i! w  b- {3 s1 E; x- q7 \0 I7 ~
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
    ! q6 P9 z. F7 u" Y
  197.         // An I/O only card or the I/O portion of a combo card is NOT reset by CMD0. (See 4.4 Reset for SDIO): S  p0 X) t5 i4 r/ D5 J8 [% P4 _/ o
  198.         
    / f0 v3 x9 [# V. I+ c/ z0 K
  199.         /* 发送CMD5: IO_SEND_OP_COND */. j% y2 k& f, v& a' O  m8 y. C: s! ^
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;
    8 ~+ u4 [7 `+ Z: y- ?4 W6 @
  201.         while (SDIO->STA & SDIO_STA_CMDACT);
    / i4 i# {; ?( l/ z+ M! i
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令$ h! d* {6 {& J. D# n
  203.         if (SDIO->STA & SDIO_STA_CMDREND)+ M  O: w& q# u$ y. J& G0 V
  204.         {
    9 f- @2 `  G' S5 K! C
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;. T% P4 V( z& ^& U$ L% D7 H: {
  206.                 WiFi_ShowShortResponse();/ k) C$ l# H* |3 C9 Q0 s
  207.         }
    0 |3 ^6 D  [- L2 Z. ?& k3 B3 B& ?9 }
  208.         ) i. V! l1 K; l$ x3 Z: o0 W& d% u1 j! W
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */
    / V7 O3 O) E7 I$ a& \, e* X
  210.         SDIO->ARG = 0x300000;. s1 L+ K- n: V* ]' g( ^) ^
  211.         SDIO->CMD = SDIO->CMD;; T3 \/ z0 A% X( E7 j4 b
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
      I, U/ y1 X! t# _. o) `
  213.         if (SDIO->STA & SDIO_STA_CMDREND)% j$ ^1 A" @. g) G: p" I# e$ e
  214.         {9 X7 J- P- u1 X) K6 B1 a* C
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    & ?) V/ S% ^8 N$ r
  216.                 WiFi_ShowShortResponse();+ ?, B5 h" [, c* W+ J
  217.                 if (SDIO->RESP1 & _BV(31))% N3 e( {$ L# N6 ~9 z$ G
  218.                 {
    ; b2 n+ Z- t5 s: K5 T2 @; @4 @( I
  219.                         // Card is ready to operate after initialization3 O0 Q+ ~, Z) k5 u% K
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);% x/ b+ j. f% _9 ?! y8 Y! E2 T
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);
    5 e9 L6 s3 @% x; L/ a
  222.                 }+ ~% T( w  x. g
  223.         }
    . h5 ^/ |5 X2 w( ?
  224.         
    + `* G+ e- j/ T" I  r+ t$ x
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */
    3 J# |1 ]7 O6 a% J# i6 i* R
  226.         SDIO->ARG = 0;5 F9 r$ e! w& @
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;
    9 Y# A+ g$ K/ D8 D' [' {+ L- m2 s! J
  228.         while (SDIO->STA & SDIO_STA_CMDACT);; x) q3 s/ j# G, e
  229.         if (SDIO->STA & SDIO_STA_CMDREND); L  d: |( n: Z- H0 L0 K
  230.         {$ D/ u% L$ g1 N% t+ a
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    ' D/ W( D* A8 S( v$ T; i' M
  232.                 rca = SDIO->RESP1 >> 16;
    # ?) _; B) P& R& c! [- Y: ?
  233.                 printf("Relative card address: 0x%04x\n", rca);3 y0 z8 Q. `+ ]. Z* h6 B
  234.         }' j. k9 R5 N2 I
  235.         + r- D, C* x7 W# j
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */% c) e/ s1 j6 d  P# s
  237.         SDIO->ARG = rca << 16;
    0 M9 I/ S( M+ T: ^
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
    : O( n3 N$ B: i* W8 B( C9 Y
  239.         while (SDIO->STA & SDIO_STA_CMDACT);  t. X% l6 u. I! R( \
  240.         if (SDIO->STA & SDIO_STA_CMDREND): [5 M4 A+ h) p- q7 m  [
  241.         {
    : W; z" F" a: k7 e) c5 J
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;$ U) g8 s0 T" ]$ x& b, g
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);
    / n3 s: W: O, q  Q9 D2 Q
  244.         }
    9 \3 p; w# q. u+ ?% G
  245.         2 N% r+ h5 }( ?# Y* e0 ~$ j
  246.         // 提高时钟频率
    ; ~* g1 X1 u8 R. @
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
    $ |; O- |  i: C) I! r$ b; e% ^
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒
    2 h, H, A; u# i4 Y- S* d
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz; W, o/ f- V( q( A
  250.         ( |% [0 ?+ B. x3 M; I3 E# W2 t7 x3 c2 i
  251.         /* 选择总线宽度 (Wide Bus Selection) *// }0 b' }' O7 C* N6 ]
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)( O# K- e: O% a2 x2 p) C0 a4 o
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
    5 V# W0 [8 _$ G2 ]( |8 q, S
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus
    7 y4 [0 w; n1 U! I1 j
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;  \4 u; A$ Z5 y, e* W6 w! X: c0 L
  256.         ! b8 ~  ^1 O. C- |
  257.         // 初始化Function 1
    - S' ?8 C; \+ T
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)
    3 I1 s) N( f0 p( ]* K1 _
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)
    ' e" u  E/ b2 `/ g4 ^8 Z5 f: K
  260.         
    : _. k" {! d: H/ E( l) V
  261.         // 显示CIS信息
    5 x8 Y5 W6 e9 B3 U# \- a! |9 [9 g. ]
  262.         //WiFi_ShowCIS(0);# }$ {5 p* g/ F4 g% q
  263.         //WiFi_ShowCIS(1);
    # p  @9 {1 _" Q
  264.         
    - Y$ \4 o2 g. W. j- f% Y0 _
  265.         // 下载固件( o0 w& ?% B* d8 S) j
  266.         WiFi_DownloadFirmware();& R1 E+ n/ V' a5 ~+ m! ^: y' r5 q
  267.         
    - F! V2 G$ c$ P; p
  268.         // 设置数据块大小为256字节. |! G8 k% l, ]( o# r
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    ) ^' W! j% u5 g; x
  270.         WiFi_SetBlockSize(0);
    ) s, E. g+ ^8 n, J) w
  271.         WiFi_SetBlockSize(1);+ o% P% A( I& B- [0 B; o4 U: h
  272.         : E+ j: P" l  l5 o
  273.         // 允许发送和接收* r+ R) M2 P. E0 w
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间) {( W4 O$ m& I% A
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);" ^4 ]: k, g9 `, o1 m2 F
  276. }
    8 X- \2 M* d% K* u% Y/ E0 S

  277. % c6 J4 U6 [& {- d6 V$ L
  278. /* 获取或设置密钥 */
    % B# Y/ ?) }& z6 P' S/ L
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)3 l, a, N9 E# L
  280. {" X- z( n7 \& I
  281.         uint8_t buffer[256];! ]; a$ n7 r- |
  282.         uint8_t ret_size;- p- F' {4 G+ I: ~
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;& U( C; m8 d7 m0 H" ]+ h
  284.         cmd->action = action;; m( g9 ]7 f6 `- g, T& r; x
  285.         if (action == WIFI_ACT_SET)
    # r. d' N1 B% |& |
  286.         {
    & T- c; u( T" P) k0 ]
  287.                 memcpy(cmd + 1, keys, size);) ^" G. P# g. G% E. e3 ?/ H: Y2 x
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);! A' y2 c( a2 I4 O- A1 a
  289.         }! ~8 w" G0 R+ f% n* U
  290.         else
    ' j2 B+ p; R9 t# Z  S" n' r
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));
    9 W; q4 J, v3 B% v
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));
    $ G. \/ z7 J+ G" S1 k* Z& ^
  293.         8 [) \' R- c  ^0 A2 E2 R) M
  294.         if (action == WIFI_ACT_GET)( f; i2 s* O  ?
  295.         {% h0 g% Q# }# P( o. V! F5 r
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
    # d, H& h* |% F: a% ?! c
  297.                 if (ret_size <= size)- S8 O) b6 ?  s& s( i
  298.                         memcpy(keys, cmd + 1, ret_size);
    ( r7 W$ }/ \+ c, P  s
  299.                 else- E% x( m# M! {  P
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);# z& ~" y7 @; O
  301.                 return ret_size; // action=get时返回读取的数据大小2 I, h% |& h  \( l
  302.         }
    5 k1 d2 q. ?/ S% o0 H3 e
  303.         else5 _' [7 T0 t7 h1 Z$ `% W: A6 q
  304.                 return cmd->header.result; // action=set时返回命令执行结果值
    + X( |' u, }. Q7 c' P( K* o
  305. }
    . G1 ]9 r4 j1 _9 ]" v
  306. " Q/ C, ~8 h) U3 j: }+ d
  307. /* 获取或设置MAC地址 */( F; g* ]2 y$ N4 ?) x) v6 v0 k! q4 X2 b, v
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)
    1 s. i* M* u* l% p) Y
  309. {. T% X+ K/ I' f1 W
  310.         WiFi_Cmd_MACAddr cmd;
    6 D4 q1 M, m, a) Z( o( w* z
  311.         cmd.action = action;
    - o0 j* d/ u7 q
  312.         if (action == WIFI_ACT_SET)
    0 G, j: e3 D; \
  313.                 memcpy(cmd.mac_addr, addr, 6);
    8 a0 j$ i( ^2 p. \# y( S: _' P# ]! M0 ?
  314.         
    " D9 ]+ Z3 ~3 a/ Z
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));
    # ?1 _8 F" s. K
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));8 h( G0 z6 `9 K( y! W6 e
  317.         if (action == WIFI_ACT_GET)
    5 M$ x# R& E% s# n
  318.                 memcpy(addr, cmd.mac_addr, 6);
    ; o. o! ~- h- s. n2 i; l) `
  319. }6 C  ^1 w/ N7 A/ B! H! L* x6 J) b

  320. 4 Q# e. Q! }" R+ P7 ^' J
  321. /* 配置MAC */7 f. P. c! {1 a3 C3 h
  322. void WiFi_MACControl(uint16_t action)
    4 b) G4 M8 e2 x* R+ H
  323. {& b* j0 D- @1 b3 {! T& R
  324.         WiFi_Cmd_MACCtrl cmd;
    & z7 J  ?; u4 {0 ~
  325.         cmd.action = action;
    $ K: _$ u* B3 i
  326.         cmd.reserved = 0;
    / i5 b- q+ f. d9 @( L/ `# i
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));  E% B4 e# v9 j
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    1 `2 B0 l7 H+ v- |: m( Z
  329. }
    9 X+ f! q! B- v

  330. + a, y3 b& o) ?% _/ x( x+ G% X
  331. /* 获取滞留的数据包大小 */$ x: i) \4 I" q/ t
  332. uint16_t WiFi_PacketPending(void)
    $ g* y- a# O0 O3 ^& Q7 n3 y5 s
  333. {6 F7 K# O) S. X
  334.         return wifi_pending_size;1 h0 O& D4 g6 g5 w( E# N+ |
  335. }& @7 t5 I/ L( d4 ~, o7 `
  336. 8 ~4 ^: M# s( u- q
  337. /* 准备好超时计时器 */$ l- C) p5 F" E  t- r, x3 h
  338. void WiFi_PrepareTimer(uint16_t nms)
    ' _9 S# \( d$ y/ Z9 |
  339. {
    : F0 J. p' `6 l6 Q" O# J
  340.         TIM6->ARR = 10 * nms - 1;
      W2 e3 }" a- q7 [) u4 B2 a+ H
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz# V3 |1 D, U3 q) {. q  S( S
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置
    0 X/ ]% a( r  q4 j- ^9 c
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位5 T; Y' x) C0 c0 d) V/ j5 S
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式. c/ J( J+ o" h$ L4 P
  345. }
    ; ^: f- t  j5 r! J) k
  346. ; L/ J- j# |$ i# [, W
  347. /* 读寄存器 */4 ]9 z% b$ Q" Z' M
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr)& Z* ?: B" u: c8 Z9 y
  349. {
    , \0 K6 N, v' p) i
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);+ ]6 S  o3 y7 I4 ]7 T
  351.         if (SDIO->STA & SDIO_STA_CMDREND)) c. R9 r# V% \. P2 m$ p4 b- m" _
  352.         {
    $ H; g1 z3 S" u; O1 c* c& S8 r
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;+ F$ ?# R0 t8 [
  354.                 return SDIO->RESP1 & 0xff;: {' V8 t, |1 [3 R' A
  355.         }
    % p) V/ n# c( v! E- q
  356.         else* ?+ q) [) J6 F  @8 l
  357.         {9 x4 O3 `1 G) Q% x# L$ {# }& J
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);. r: I/ |, E. H! |9 M9 ]3 ~
  359.                 return 0;+ G9 K3 S; W+ y' z% _6 q
  360.         }
    / Y6 a" ]5 p0 V, }% D2 @
  361. }: D8 b  x9 R1 c7 c# h

  362. $ \3 X+ \. N2 O0 S9 d- d/ r6 a
  363. /* 读数据 */; e' A/ k% Z' y" a
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    & O* L9 d! m8 k& ~$ [0 \
  365. // bufsize=0时, 只读取数据不存入缓冲区! m1 B) p' ~- g6 b) k9 _
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)8 R9 P1 |7 A& _% E
  367. {& X) A/ |. q$ z! G
  368.         uint32_t len, temp;0 B# ]6 d# A" X1 r, E
  369.         if (flags & CMD53_BLOCKMODE)7 z' y, s, y8 h: N
  370.         {
    ( H2 Q. f7 {* T
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数* ^; s- o# O% D) a- q7 X* C
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
      k0 R% R3 C5 Q: P* V5 l5 u9 s
  373.         }. |! b/ U+ I0 o: j1 Z- P
  374.         else; s& j3 M4 d. o7 |! V* S1 C/ @
  375.         {
    3 V# C+ k& b5 B9 w5 Q! ?8 R' u; }
  376.                 len = count; // count表示字节数; T3 o* ?7 y- t! G  j% h! T9 M5 r
  377.                 if (len % 4 != 0)7 L1 t0 R  |6 R
  378.                 {
    1 F, K* S( v- G1 D: _3 V
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    6 ~6 }  D! s  f1 Q
  380.                         count = len;
      [% F/ ^! A* J. I
  381.                 }
    - y2 t. z8 d0 E. P. T. J: Q/ m
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式
    7 ^- M8 ~( w5 O: k0 \
  383.         }+ L8 l  ~( U1 H5 n) n3 y' B  q" U% u
  384.         SDIO->DLEN = len;
    6 \: }+ v) n& J+ [' H# `+ v) F' H
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
    1 O+ N2 Y8 {: k* I6 V. _, @
  386.         : K4 B; U) {  ^* g: j! j
  387.         WiFi_SendCMD53(func, addr, count, flags);
    1 x8 o% w! ?2 y8 |* f! p
  388.         while (len)- u' y+ T- H9 X
  389.         {5 z! J( I& Q8 @* h4 P% J
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)
    & \& ]' O9 o5 H4 O) Y2 P5 |) i
  391.                 {
    5 j9 y3 ?! h8 F4 M' `
  392.                         // 若有数据到来就读取数据6 r  ^  E# G" w2 G
  393.                         len -= 4;8 M7 W# Z/ x, B4 j2 x. N9 u
  394.                         if (bufsize >= 4)
    6 ^; V- F% V8 Q; Q5 ^2 b2 m
  395.                         {8 C' j2 g  [( m
  396.                                 *(uint32_t *)data = SDIO->FIFO;5 g) J; F& {/ X: t% ?. h
  397.                                 data += 4;8 B2 s4 q' j. {6 E( C
  398.                         }( q& U1 E" }. r* @5 |/ }; S
  399.                         else
    . w  U2 i1 J' r  L
  400.                         {+ i4 t+ P' n" n( G( L
  401.                                 temp = SDIO->FIFO;
    $ ^- m. J! g8 e# v" W0 ], N% j
  402.                                 if (bufsize > 0)
    2 D3 Q9 y% W5 e+ U3 z" m
  403.                                 {, b0 }' x" \- Z- n8 e" ^
  404.                                         // 写入缓冲区最后1~3字节, j9 ]/ M* ^6 v6 a  D: V
  405.                                         memcpy(data, &temp, bufsize);" L. i  x# K4 Q( d
  406.                                         bufsize = 0;& }5 M' c6 c7 P/ e9 p! D& x5 P) {
  407.                                 }
    & q0 V  Y% `# W- @8 y: R! _5 m
  408.                         }
    ; h% }- ~3 {$ a! ?
  409.                 }  x! @/ H0 Y7 _3 Q/ _- \
  410.                 ! s% L9 E4 c# W
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)3 ~0 S( F9 L- u& c
  412.                 {
    $ }! D+ N6 n/ n/ ]. |+ U% Q0 P
  413.                         printf("Data Timeout!\n");
    + I2 ^! Y& H+ g  Z+ d& f2 n1 L
  414.                         break;% r) h9 ~" }% `. N. J
  415.                 }6 B( V4 N8 e7 I' s( ~) f) W
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)
    ( f. u9 i, G5 h+ E0 ~
  417.                 {( @& U6 C2 M% `2 u
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    ( `- z/ {1 t, b$ A7 C
  419.                         break;
    & R1 z" N& M3 H' C
  420.                 }0 ^! H9 O" @, i  B, A
  421.         }
    9 B5 J2 T7 r* `$ }1 \
  422.         
    ; f, A# T5 L$ A) M
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));" q  g- D# F" }! j$ E3 O0 b
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;. u% a6 b- x# k  U% D# \
  425.         4 C$ T9 h5 n8 o0 e
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;9 _* h1 V1 f- y
  427.         if (flags & CMD53_BLOCKMODE)
    6 ~, _& f5 ?) U# ~. C8 n: H
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;( v7 b* T! O; p1 D
  429.         
      @, V$ ?, D( D
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功; ~2 _( Y9 _: m# L6 _9 q# |
  431. }
    " k. S7 M1 q/ Y8 P8 E' H

  432. ' l8 b2 L/ H& ]. F
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)9 p4 h- B8 p4 j1 c! k3 e
  434. {
    % R5 q( C. P1 l& |: i
  435.         uint16_t block_num, block_size;/ t0 T. Q7 c' W  j' T
  436.         block_size = WiFi_GetBlockSize();& g( _; o& }# D
  437.         - C# K# ?' K7 @
  438.         // 读取数据% W4 I, O! R/ M3 e( T" I
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1$ z, B3 N8 f4 f7 P
  440.         if (size >= 512 || size % block_size == 0)5 r( x$ b; O5 s- z' [% m
  441.         {, D5 K/ h8 S  o0 P
  442.                 // 采用Block模式传输
    4 B7 C% Y" e& }/ f" O
  443.                 block_num = size / block_size;5 m7 V9 W6 m& I, s. k  S( P
  444.                 if (size % block_size != 0)" U; r2 ?9 F1 ^8 h7 ?. [# @+ ^& A; l
  445.                         block_num++;
    2 [+ K9 B+ e) W/ L+ J7 [
  446.                
    5 I- Y, |' O& b9 V/ C7 N( A7 i
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
    7 i% g7 s+ ]  g6 H
  448.         }; y0 Z( V0 ]: s
  449.         else
    / q# w1 [$ U7 l2 ~* E4 h( L
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);
    & p/ U& Y$ t/ t. k7 a! z
  451.         
    $ C0 ~/ Y( t9 m4 c# f" L
  452.         return SDIO->STA == 0;3 z/ V! ], i, v# K) ~/ E
  453. }
    , _# m% Z! z- |: e7 A- b4 A
  454. 5 H3 S- J' M, c% W
  455. /* 接收数据帧 */
    9 O: f# K2 K5 Y+ b( E5 h3 y
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)
    # }2 R5 j5 m9 E' r4 @6 F
  457. {( h) t6 q& U2 i" k7 g
  458.         uint16_t size;9 d  R; ^, `3 z6 e+ h
  459.         if (wifi_pending_size)8 P) s# d% Y$ ^/ Q2 G
  460.         {
    * U4 J$ _) r4 @% C
  461.                 size = wifi_pending_size; // 先读取滞留的数据包
    - n5 U8 ^9 c* }4 W+ [' ]% P4 y/ B! ]
  462.                 wifi_pending_size = 0;
      G6 g6 o+ p4 A2 C
  463.         }3 Z8 b9 M  H; k
  464.         else- w& M0 ?3 j" {, N/ g3 x
  465.                 size = WiFi_GetPacketLength();
    $ [7 [, O, U1 s  e- C6 Y
  466.         return WiFi_ReadPort(buf, size, bufsize);9 d8 t! C1 C3 A5 F* h. ~' ~
  467. }, p0 N8 h. b$ ]2 q0 a$ d6 ~% O! r$ ]# j

  468. 4 X: P/ P* J7 u; c
  469. /* 接收WiFi命令的回应 */
    + m$ p5 }: j4 Q! B
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)4 t$ m/ r) ?& {8 M' l; c! l. e8 u
  471. {
    5 |' T8 M9 }- T4 t
  472.         uint8_t retry_cnt = 0; // 重试次数) h& @: ~* j- y" h
  473.         uint8_t wait_status, resend;
    : }. q  m$ _( ]& v9 _
  474.         uint16_t size;
    1 T  A; ?/ n: N6 B2 u
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;2 ~. Y7 E! [9 b' F; [3 w+ w: q! q
  476.         WiFi_SDIOFrameHeader temp;" X$ u8 }/ N9 W' H( |9 \, p
  477.         : t. v% F& V. O, R: P4 y- ?+ d
  478.         // 等待数据准备好
    ' `$ ^! j2 K0 V$ U
  479.         do9 @: U, ^5 y$ \- o4 f
  480.         {1 m. Q) ~6 @7 a: L9 }, x
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);/ c( `1 P( ]: H6 b. M- T
  482.                
    " t8 [: q- |- \$ D, E- @
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息& V* c) T+ n3 y, H( d- v) p5 ^/ R
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部! P; r+ ?) r5 d- [) a1 I! F* s
  485.                 {
    1 P# t' l, y% M" A! D
  486.                         // 若读到的是一个数据帧, 不是命令回应
    ) t! }8 s0 z. h- ^6 p# _, g
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功# W) _& G) @4 R$ ^' ]( k
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);3 [& K2 |  p$ |5 P8 R; j, K
  489.                         wifi_pending_size = temp.length;/ X5 H% X6 R5 W; L& {3 `
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算
    0 x6 w1 O4 k1 O# {, I. w
  491.                         resend = 1;
    6 b, J: g- j- e# Z( X* s
  492.                 }
      d: r& u$ i2 V5 J
  493.                 else if (wait_status == 0)
    1 u, c6 ~' M3 V  v
  494.                 {
    8 L  G& s' P9 {4 _) u
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)+ i% V' k) j! ^! E
  496.                         resend = 1;
    ' a6 M. N- r; }4 x5 F0 ^
  497.                         retry_cnt++;
    # E8 }  `' }% R0 R( }' n  O8 o
  498.                         if (retry_cnt >= 5)" A! Y% P5 W6 f9 h9 u7 Q+ m6 @
  499.                         {
    1 x! a# U+ F# k3 A# Z3 ~# ?" a
  500.                                 printf("No response!\n");
    & i+ ]) H6 F) T' k: y4 Q+ d' \  U
  501.                                 return 0;
    & x3 U) X9 W7 N+ ~# q# p
  502.                         }' r9 U! t6 f8 `/ V
  503.                 }8 m( S% G5 o4 w/ r$ y: C% ]
  504.                 else: w  d. _; o$ Y+ R" A3 C, X
  505.                         resend = 0;
    " J2 ^1 K# Y* I( K
  506.                 9 Z0 G2 G- H1 s3 \( @
  507.                 if (resend)
    / q4 z7 Z7 D  ]! `
  508.                 {1 L3 o! L# ^2 C4 V+ o
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)
    : t- o' f2 l2 {2 s! u
  510.                         {
    4 l5 k. Y$ A& _
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait" F7 X% Z3 L# u: C, W" A; k
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);( k* O, U5 d: x9 X$ P! }
  513.                                 WiFi_ResendCommand(buf);
    4 U1 g7 Q# e( R# l5 _  O- G1 p
  514.                         }$ A- F- _. d4 F7 |' R! y
  515.                         else
    " d9 F! Z2 R. m0 o2 j9 d8 r1 B! f
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出6 p% P, I/ e6 j" p# K) V# W* j
  517.                 }
    6 v* A& [$ b( }0 |1 V
  518.         } while (resend);% ^8 m+ N! g, _1 ^
  519.         ! w7 R' n- O9 t  g
  520.         size = WiFi_GetPacketLength();
    5 l) B' e! M* R- @: Q$ j( X  V; ]
  521.         if (size > bufsize)
    . N% a& w4 ^* d" m
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
    % `+ ~! `' K+ j# E" \& I
  523.         return WiFi_ReadPort(buf, size, bufsize);
    8 a1 B6 _( Y$ v: e) }& G  c
  524. }
    + F+ q/ V4 E( U" r  d( \

  525. 9 u% H# A' L' f1 p( h. K4 X% y
  526. /* 扫描全部热点 (仅显示) */
    , T* J7 `  W8 j$ j& H2 W4 X
  527. void WiFi_Scan(void)& _3 z  A8 `# h9 k; W
  528. {& Q: ~- g5 W2 Z) ~& ^
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组! Y5 f( _; R4 v2 k* w3 ?' O
  530.         // Stack_Size=0x00000c00
    ( y7 D( ^, B3 E3 H/ R2 k
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
    0 w# Y' p- n6 L; O. Y
  532.         uint8_t i, j, n;4 A( c7 W# K% E8 J
  533.         uint8_t ssid[33], channel, wpa;$ h( J  o# f8 t" ]
  534.         uint16_t ie_size;
    . i* h# j, P9 v
  535.         ' z1 r8 i7 ]7 H+ A% m* Q/ |
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
    ; t) M( S( Z5 H$ |
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));: Q' c  r  `: s+ X1 Y5 y2 C
  538.         $ g5 x' \' b- m( z( ^6 W) D# m
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;# b+ m( D$ @$ Z9 b
  540.         WiFi_BssDescSet *bss_desc_set;4 x1 k) L5 T+ O: q& z' p* b. w
  541.         WiFi_VendorHeader *vendor;
    8 A1 o7 j; a; k; o
  542.         IEEEType *ie_params;7 K; n6 u8 m# z7 w; R& g0 t% \5 ^* X
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;7 t! Y/ h) b- h- ?
  544.         % q% D3 ^, N% {+ ^7 Q
  545.         // 分4次扫描14个通道. M( Q6 K+ h! r
  546.         for (i = 0; i < 4; i++)
    * h$ s' G; I) [/ n
  547.         {( U. U1 E1 o9 V; \% C
  548.                 cmd->bss_type = BSS_ANY;: E4 r$ Y0 `; y% H, a4 ]/ a
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));6 y" A2 d3 B6 G' G3 p
  550.                
    2 _$ G8 O" {' j! o6 ~# r+ T0 E& G
  551.                 // 通道的基本参数
    + O' Z! D! A; E8 G
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数1 p  z: c0 i* F# s- C. H6 b! I
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;. ^& T0 a2 _8 ]6 p2 I
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);
    5 a! G; s! r; m, h' Q
  555.                 for (j = 0; j < n; j++)
    5 @$ W" K2 d! j2 E) r; _8 c. ]
  556.                 {% P) g& T$ \) ?0 o" F9 ~
  557.                         chanlist->channels[j].band_config_type = 0;$ l; z1 w0 W6 v2 j; O5 V; |4 r( o2 l
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号
    7 Y2 p1 R2 K+ n2 m& z
  559.                         chanlist->channels[j].scan_type = 0;
    , X, ]  p8 W% J) m; r  l% H
  560.                         chanlist->channels[j].min_scan_time = 0;
    * D6 d/ r$ e! b
  561.                         chanlist->channels[j].max_scan_time = 100;: w; c. [7 h# G% p5 E
  562.                 }9 n- a1 T, l9 D; R
  563.                
    * M  X# W( i8 E# O# o( d
  564.                 // 发送命令并接收数据1 Y2 _/ O8 N$ p+ C0 j" u
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
    $ Q$ U+ r6 c+ J
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉1 A6 E4 s" V1 W" q: @
  567.                
      b5 m0 H; C$ a4 G+ s- V' w$ y
  568.                 // 显示热点信息, num_of_set为热点数
    1 s$ q1 b2 {' W/ v( @
  569.                 if (resp->num_of_set > 0): Z) a% t4 M6 r& `( w; u1 N- X
  570.                 {" b4 G4 y+ ?' H& g9 }" k3 C
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));. G7 V) f/ ~( Y6 l
  572.                         for (j = 0; j < resp->num_of_set; j++)
    0 D0 U* x$ C! S0 n
  573.                         {' Z9 T/ a4 L! P; u- f
  574.                                 wpa = 0;
    + e; I: \" S9 `8 ?9 p- y$ k
  575.                                 ie_params = &bss_desc_set->ie_parameters;7 m  n. \: {3 R0 I- {1 ]
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));0 T, B8 B' C1 S0 k; ~/ h* U
  577.                                 while (ie_size > 0)
    . i% S% w( d5 s" T
  578.                                 {$ r" `* p& }# W
  579.                                         switch (ie_params->type)' d- I/ Y# `$ F# L( Y
  580.                                         {
      I0 n4 z0 M5 D. }7 W* L, Y
  581.                                         case MRVLIETYPES_SSIDPARAMSET:
    ; X! x  \# B" H( Z4 Q8 V
  582.                                                 // SSID名称
    7 W  X$ ]6 W$ X& _2 S
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);$ O, |9 x1 N$ K6 d7 [$ G$ X4 D
  584.                                                 ssid[ie_params->length] = '\0';
    5 i6 r5 h% O/ L- p) {- Q
  585.                                                 break;# B" y2 y8 J6 O+ B9 |6 A
  586.                                         case MRVLIETYPES_DSPARAMSET:! z5 ^, S* K$ x' B0 f' [6 ?
  587.                                                 // 通道号5 K5 O5 D. h0 C% I1 Z5 a7 Z2 {( t  m
  588.                                                 channel = ie_params->data[0];8 v, v% c1 I, I" ]5 S# `& V
  589.                                                 break;
    / h. W" A7 M% D7 P* u1 l6 i
  590.                                         case MRVLIETYPES_RSNPARAMSET:
    2 T2 W7 E1 x8 Q6 i" o
  591.                                                 wpa = 2;- l6 S) T7 Y: [* w( q1 E
  592.                                                 break;) l: l# O5 `) W$ l; n
  593.                                         case MRVLIETYPES_VENDORPARAMSET:' \- S( ]! N2 f3 A
  594.                                                 if (wpa == 0)
    " y) d9 X7 {3 H4 F( U( V( k4 s% ^( |+ e
  595.                                                 {
    4 ^1 p3 H: n1 d6 T
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;
    " o3 \* z' R( U
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    $ r1 x/ z8 O& b- P2 K
  598.                                                                 wpa = 1;2 a# B" f% F0 ^7 t
  599.                                                 }+ \; }" x9 ?0 ~
  600.                                                 break;
    $ P8 ~4 X6 u% w
  601.                                         }
    4 D) L" H8 A4 c# ~2 q0 \& N; c
  602.                                         ie_size -= ie_params->length + 2;0 M) L7 p9 X4 `- R" k1 v9 ]( s1 v
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);1 K/ K3 }8 V: }2 A- c9 Y. W4 I8 Q5 j
  604.                                 }
    ( O) C1 p. G- E6 Y
  605.                                 if (ie_size != 0). A" I& H1 R2 y& D: d
  606.                                         printf("ie_parameters error!\n");4 I$ Q) L+ x' {/ F& z1 T* S  R% J
  607.                                 $ s4 f1 i$ f% T( t
  608.                                 printf("SSID '%s', ", ssid); // 热点名称
    7 U0 G6 B; M2 z) y% P
  609.                                 printf("MAC %02X:%02X:%02X:%02X:%02X:%02X, ", bss_desc_set->bssid[0], bss_desc_set->bssid[1], bss_desc_set->bssid[2], bss_desc_set->bssid[3], bss_desc_set->bssid[4], bss_desc_set->bssid[5]); // MAC地址) x7 |* F/ D1 z0 C
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
    3 v- ^2 q3 ?6 \* p. i0 }8 `
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);
    4 R, x) B3 C& t# r0 B6 O" s+ m
  612.                                 4 ^  q( |: P  Z/ ?9 |( b* P
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);) `+ W6 I5 @) }
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)
    4 A7 m- J# y5 G- N
  615.                                 {1 e* h+ v" l" a6 v" Q$ E
  616.                                         if (wpa == 1)
    # c& x9 w" }8 V' K
  617.                                                 printf("(WPA: ON, ");
    1 q& c4 y  M" b- l. a9 L4 K6 S
  618.                                         else if (wpa == 2)
    , T; J. h: O  ~* p  |
  619.                                                 printf("(WPA2: ON, ");& q$ f8 {* P% ]2 i8 F
  620.                                         else
    " E) a2 f7 }7 _7 u$ I7 H
  621.                                                 printf("(WEP: ON, ");1 l% j3 O, S1 N8 |5 a; i! L
  622.                                 }% X# k3 R6 |: h' P" @: H4 ~9 `
  623.                                 else
    / w. q; b0 s6 M
  624.                                         printf("(WEP: OFF, ");
    5 ^- ]/ n) I* P" ?8 C  r8 D3 z+ @
  625.                                 4 J5 j9 i# q5 n6 y" `% j
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)# J% I6 i! H! l8 k
  627.                                         printf("mode: Ad-Hoc)\n");
    5 h/ C# f( X- ]5 P! F9 M
  628.                                 else2 l% N5 Q9 v! c8 ~, y
  629.                                         printf("mode: Infrastructure)\n");
    9 ~/ o! c  p  G
  630.                                 # r0 _3 p" M$ c! H
  631.                                 // 转向下一个热点信息% v* I8 S7 d( ^3 v! e- p
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);
    4 I9 ~+ u' F; Q
  633.                         }
    , O6 i, G& M0 P
  634.                         
    1 _7 H* z! d6 a7 Y" B
  635.                         // resp->buf_size就是bss_desc_set的总大小
    6 Z1 ?0 ~6 S; D7 ?
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size
    ' p$ L$ n; m7 F2 j5 j
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
    % W' R0 s7 G- B( f
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))8 q; j2 Z( V& y6 g& m; T' n
  639.                         {
    4 ^# i5 u& {5 |6 o
  640.                                 printf("Timestamps: ");
    6 {' P$ d; m& ?$ t. T$ y6 y
  641.                                 for (j = 0; j < resp->num_of_set; j++)% i4 R7 W3 H  t0 m( F
  642.                                         printf("%lld ", tft_table->tsf_table[j]);$ g3 o/ |  ]# s, P' r' S
  643.                                 printf("\n");0 c' m* [  D2 @- F
  644.                         }*/
    5 I" X% |# k3 z$ M
  645.                         8 F$ C! r! U6 T% S" C0 u( |3 j
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table
    + F1 r* f! J+ y) k) L) e3 }
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)
    $ T) U& L1 z; f7 l8 ], w
  648.                         //        printf("data end!\n");- \0 U4 P/ p+ P8 r. ]5 F$ }
  649.                 }
    : Q5 ^! i5 F+ ^1 {
  650.         }
    ' e- g1 x" p5 G* Q
  651. }5 G* l, M6 j" s8 i
  652. & L2 e8 h7 n0 @3 r3 T
  653. /* 扫描指定名称的热点 */
    + Y, D6 g  |3 L& P5 M; [
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大
    ( H5 D  o) E1 J! K/ H+ X- p
  655. // info用来存放从buffer中提取出来的一些常用信息
    / b1 j6 I9 A; W# w
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)6 J. _+ C  U* x4 d- S
  657. {: U. p. l# `; I. ?6 R6 \
  658.         uint8_t i;
    ( I. y+ {; e+ R& n5 s
  659.         uint16_t ie_size;3 H+ n" U! W3 {: S, v' z' l
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
    . d% ~) o# \& w2 b+ n0 r. x# F
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;  r7 A% c0 r" @: O* {  R/ W  o
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);
    3 b% y1 }) B$ Q. w0 _% t. H- \6 `, C
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;
    - s* u9 D" N0 q6 s. @4 _
  664.         IEEEType *ie_params;4 |1 D0 V' i2 t" M- W0 q& D
  665.         WiFi_VendorHeader *vendor;, p7 J  u/ V) J8 a
  666.         
    & ]8 H* K4 R: g; h7 P7 v
  667.         cmd->bss_type = BSS_ANY;1 Y  a* z/ R( S4 o8 s. g/ d
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    4 I: a% u* _6 i
  669.         
    6 b! y* L3 C0 @8 D( j3 o7 ~) L
  670.         // 添加ssid参数( y2 K( v% A* z' }
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;
    ( _* R7 {6 s- n' b9 u% U, c0 \
  672.         info->ssid.header.length = strlen(ssid);
    $ j! F$ `5 n7 z' I5 M
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);
    0 L& t# p& E( Y) @
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    9 u: M8 f/ c( C/ b
  675.         
    3 g8 r1 c( c" X8 p! N- Z" P3 a
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));
    9 }, z0 A; D/ Y- u. x( D% Y. f: q  Q
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;8 u! f3 C4 Z% E8 s& n( o' d7 i- a
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    , T+ g+ L" s) X* A3 v5 c9 z+ Y1 t
  679.         for (i = 0; i < 14; i++)
    6 r1 G4 }# M( r3 ~8 q# l% R2 k, _
  680.         {: Q, G8 U5 ^5 E4 ]
  681.                 chan_list->channels[i].band_config_type = 0;
    - H; i/ z! }1 [: R4 y8 a" }: y
  682.                 chan_list->channels[i].chan_number = i + 1;; n! P/ ]! ~2 e0 T
  683.                 chan_list->channels[i].scan_type = 0;
    9 y' {& o9 a, P& z3 P
  684.                 chan_list->channels[i].min_scan_time = 0;+ f# A9 F, t# d! F+ |; e- S0 a' j
  685.                 chan_list->channels[i].max_scan_time = 100;/ R" J1 }: l! C5 ~2 P1 I% a) c
  686.         }; W8 |! I9 I$ ~0 @
  687.         + z" |5 U/ s. }
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));. `0 v% |$ ?  l3 L
  689.         wifi_timeout = 3000; // 延长超时时间4 d" O9 Z2 j1 `1 o0 g; S6 y
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    ; K# X& `5 ^0 X1 @7 w
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;2 M# a6 h6 J: n) |
  692.         
    6 g$ E) W: E3 _: q" A8 Y3 Y
  693.         if (resp->num_of_set == 0)
    % b- l9 T+ n( d+ m% r
  694.                 return 0; // 失败
    ( z8 f1 F, e/ l4 p& v
  695.         
    " C7 M* `; c. m: ?- R7 B. F
  696.         // bss_desc_set以扫描到的第一个信息项为准
    + k: w0 T& [3 u
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));5 \2 u5 m$ d  m+ m/ A
  698.         info->cap_info = bss_desc_set->cap_info;  Y9 \. t' W4 j9 i: d$ a/ N
  699.         info->bcn_period = bss_desc_set->bcn_interval;, U8 i6 ~! k8 c5 G
  700.         
    : X2 t6 j! f2 _* i2 c
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)
    7 B3 r+ I* j9 V7 f3 f9 [" O$ `
  702.         info->rates.header.type = 0;
    8 A- `. r4 R1 l0 `8 y0 _2 y
  703.         info->rsn.header.type = 0;% A2 h0 N6 S2 @9 F
  704.         info->wpa.header.type = 0;/ l1 Y0 V# z0 N7 r* B, \
  705.         info->wwm.header.type = 0;# D0 _* [- P( T* L9 z0 ?6 E
  706.         info->wps.header.type = 0;$ I( i$ i4 a" L- y
  707.         ( h" L8 u- C; n' N# ^
  708.         ie_params = &bss_desc_set->ie_parameters;
    + G, \) R$ m: S# R: q
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));7 G# U% {8 h9 m7 X0 q- P
  710.         while (ie_size > 0)  l% `8 _4 S) y) c+ d0 f, G
  711.         {" c: V1 C, K, q1 _( A
  712.                 switch (ie_params->type)7 J6 k8 z" W) y9 c
  713.                 {
    2 |2 A4 p- e* g* \9 G0 e, j
  714.                 case MRVLIETYPES_RATESPARAMSET:8 p  R. r9 \. t0 o+ W
  715.                         // 速率( C' E4 f3 A9 a5 s7 D0 |: s) A
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;+ y2 [+ w( l5 [# D1 L/ ]. y9 u
  717.                         info->rates.header.length = ie_params->length;; s+ x2 V0 A. [7 |( C* D) h& i4 d
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))9 Z  C1 m5 b( j/ i4 l# A; h
  719.                                 info->rates.header.length = sizeof(info->rates.rates);% W, M* f' G  I: |, h% I' [
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);$ d: f  x6 z( Q% g3 q/ |6 _
  721.                         break;; V7 P, ?% ]1 {$ s& O. g) A
  722.                 case MRVLIETYPES_DSPARAMSET:
    7 D6 t  J2 [& d9 ^6 n# ^
  723.                         // 通道号* R0 X& ^- n- S. B3 p9 M
  724.                         info->channel = ie_params->data[0];
    $ U( \: _6 V) G
  725.                         break;
    9 d1 J" A$ X- `% D* q
  726.                 case MRVLIETYPES_RSNPARAMSET:# h$ ]5 a+ a' C2 b
  727.                         // 通常只有一个RSN信息 (与WPA2相关)% p$ t2 t+ V/ e+ u8 D
  728.                         // printf("RSN len=%d\n", ie_params->length);$ l% H. `- w) c* z% g% Z5 ~
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;% D6 m7 C0 O; ?
  730.                         info->rsn.header.length = ie_params->length;( U, g% T) F3 n1 y- v) R2 q6 G" @
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))
    * y- D2 x  T! Q6 C& i  F
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);
    # \- |: J* A& V$ T5 n! G
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);
    6 e4 X$ e3 o& b- C0 L8 {# Z
  734.                         break;
    2 l3 ~- ~) V# o6 ^, L
  735.                 case MRVLIETYPES_VENDORPARAMSET:6 C5 E( w2 A  B( J% S
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)
    3 p1 @: P" p% Z) G1 g# w; d; j
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;
    8 I3 Y2 P' j  J8 M3 Y
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)
    4 M8 t$ Y( `# [6 \
  739.                         {
    ; e! `: w6 @9 D! a/ A4 v- M
  740.                                 switch (vendor->oui_type). _3 f  S( C! m: K
  741.                                 {
    ) {/ Q$ I$ K6 Y$ C
  742.                                 case 0x01:1 i; ]. e# s# N; _1 ?5 m
  743.                                         // wpa_oui" K1 v( ]. \6 T' q1 c1 b% \% @
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;
    / t; {1 B) r: F5 N. D
  745.                                         info->wpa.header.length = ie_params->length;  k) I2 L; g; d$ p: s6 U: \3 `
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))5 V6 y' W& M& p$ b  e
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);
    ) p( b7 m8 d8 `' Y: j: ~
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);
    0 z# T4 B  H% `$ I: u' |$ s
  749.                                         break;3 O2 g7 u, {, s3 `
  750.                                 case 0x02:: b" P: Y+ p" ^6 s+ p. g( s; f
  751.                                         // wmm_oui- t0 i# ?9 i# C9 j1 c
  752.                                         if (ie_params->length == 24) // 合法大小/ g# O! T# A7 I/ u3 }
  753.                                         {
    6 a: B: I; }8 m9 {! ?
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;
    / A5 v! B3 l( n6 j, }4 x( A
  755.                                                 info->wwm.header.length = ie_params->length;( B1 r6 h# X1 |, v; O! l0 i
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);$ P$ V( u. Q: j3 I# p4 R, U# k8 d: U
  757.                                         }" C' {) }. f0 O( Q( a
  758.                                         break;
    ) h- m4 y0 @, @6 F5 p
  759.                                 case 0x04:- |3 ^. E) o% @5 x8 S: c1 w5 e
  760.                                         // wps_oui
    8 c$ [3 E, s: G& K! X
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;% {) C1 h: y& |/ N' [
  762.                                         info->wps.header.length = ie_params->length;( U# [% A# N, j. [+ Y; S
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))  h  G$ v8 O) `
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    # ?1 e+ C9 m6 I& c8 k, ]
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);- e3 r& J: _9 d9 o* P6 T2 v
  766.                                         break;/ G' ~+ X, V9 c# X: R; ?3 p
  767.                                 }
    9 t( U) }9 }+ w5 V# U, `
  768.                         }$ p" o8 u; @. s' d# \
  769.                         break;+ p, y1 m4 k6 X, {
  770.                 }
    ( o  R- X! ^% A+ Q
  771.                 ie_size -= ie_params->length + 2;; |% U. a2 ~6 K0 D6 E) N2 x" ~
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);2 ]6 y; E6 b3 k3 y& W
  773.         }3 e4 Y( ~- G/ D
  774.         
    & L' }5 f: O9 H5 D! J
  775.         return 1; // 成功$ p2 `# x; s" V2 n4 x/ x
  776. }+ \* \' r7 a, ^) X
  777. ; _$ Z' _9 @5 j: w. v  S. A
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)
    * }  m: \* I/ ~- F
  779. {" ?; L7 m1 O" W0 S  s* P* X
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
    " q* c) B; K( `
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;
    ! `$ [6 V& A, \; K2 w- S6 {
  782.         while (SDIO->STA & SDIO_STA_CMDACT);  J! M( r9 v- b" z
  783. }6 u8 ]6 @7 L$ R/ w4 Z

  784. 4 T! h9 H& t* I4 Y$ y/ t! U! ]
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)% `$ g  ~/ Q2 y
  786. {. h7 T3 _7 L" b& \! t  }
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求+ x& p* a/ z3 K: V: d. h5 G
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;! ]. K  n! \7 F
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;
    + x8 ?- u  P, o4 G1 j+ r
  790. }
    - X# B, e5 h0 j) t# O6 v1 }

  791. 6 j! r. `, d4 K) Y4 x
  792. /* 发送WiFi命令 */
    0 R, J8 c& s  c1 t
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)
    ( @( V% _7 m2 i# ~, I- d. L
  794. {
    $ ]8 O; p7 v1 j
  795.         static uint16_t seq_num = 0;
    : L- B. W7 T# m2 k' r! h% H
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;
    9 S" ]5 W7 T9 d& L  d" Q5 P! r
  797.         
    1 `" x3 G, O2 f0 S# j6 y' |
  798.         if (size != 0)
    0 j2 Z# n. }4 N" B
  799.         {
    ' l6 o8 Q! g. T0 ?. ^
  800.                 cmdhdr->frame_header.length = size;
    ! p& G7 m! R- x% v9 H9 B
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;
    - i* o  E' }: b! X; q
  802.                 cmdhdr->cmd_code = com_code;' X1 A" |% o5 m" B+ j9 ^
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部
    7 Z7 g  y9 [. f( \; l- N$ V
  804.                 cmdhdr->seq_num = seq_num++;
    ( i! m7 a- N( ^& c5 S0 c  B
  805.                 cmdhdr->result = 0;
    9 s0 A# a! R1 t  a, u
  806.         }
    % t/ }$ z! ?$ r5 I" V  i- C
  807.         else8 w/ R6 G$ W& e/ r: u# c
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr' H4 ~- K4 y9 @+ W2 B4 C& h
  809.         8 P" F& Q. O( Z4 E9 h
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃; |. L. H  q1 g
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())
    # s& j6 s, w0 j" J0 y- l
  812.         {; @9 E9 p! U, c: N4 {* y
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");
    5 h# g+ I! `( o2 l- z# V, F
  814.                 WiFi_DropPacket();
    % I7 K" X- |* a0 z& F4 }
  815.         }- h8 [) J- D$ n5 i: z% r
  816.         ) ~9 u  ~: ^$ N( V: x
  817.         WiFi_WritePort(data, size);
    # k2 k5 ]1 E; f2 ?9 I8 x
  818. }
    + ]& c& \! r. v4 O6 S

  819. & ^& f7 J& e6 @
  820. /* 发送数据帧 */
    - X- d) M# Z' \" V; U2 M9 M- H8 c
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len), D" q: ~- }. }% E
  822. {
    ' I' @7 w( z, f- ~$ {0 Y
  823.         uint8_t ret;
    5 H0 K& C. U9 u) u
  824.         
    + ~/ {( \% A3 Q# p( i6 E
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path7 O/ }; o: \  z( E
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;! s+ v& N- l! d3 I$ q1 p0 o6 _/ \
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;( Q3 }6 }2 W' \  O* V, D: a! W
  828.         
    - {9 H1 l  M1 v' P
  829.         packet->reserved1 = 0;" P2 N! L9 s' w6 v4 k
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings
    $ P: t+ R0 a2 U9 E8 a2 ?2 l. z9 L
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader% w$ }. }/ w3 r+ j& g
  832.         packet->tx_packet_length = packet_len;
    7 X' N7 x- ?$ n% `7 b/ `
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);
    + B( P8 N  ]! i6 Y
  834.         packet->priority = 0;
    2 `; @) X' s& {8 a
  835.         packet->flags = 0;
    4 L$ k" d- U5 c8 q
  836.         packet->pkt_delay_2ms = 0;
    * I5 [6 u; S7 [5 E6 f
  837.         packet->reserved2 = 0;
    7 V$ ^; n- U. z- C
  838.         
    5 c4 v6 c+ S  d% r
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小+ \0 E# _9 M& `  F3 x, p4 Y
  840.         // 未读取之前不会收到新的数据帧
    % {$ [7 d7 V- `/ ?: r. V/ A$ _" y  s
  841.         if (WiFi_PacketArrived())
    # N. A, j8 P7 z: x" _
  842.                 wifi_pending_size = WiFi_GetPacketLength();) h. x- c5 `4 |
  843.         
    4 u% A4 i$ q, d, j( D) \0 S7 N& v( M
  844.         ret = WiFi_WritePort(packet, packet->header.length);
    + Q" ]  Z7 C: K2 b1 ^' B
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1- l0 X0 f/ r  P
  846.         return ret;! C: ]  |3 |$ R+ {* Z$ Q
  847. }/ I" }7 h) ?% l* |  g$ K# z) b: @0 r

  848. $ L* V* q0 d/ y0 x' u9 V
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */" u4 X$ H1 ^; J. O4 W. }- ?+ t) ^
  850. void WiFi_SetBlockSize(uint8_t func), n5 h0 e" G1 c- {' _! R) U7 W
  851. {
    9 j) `/ B+ }" h  K
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)9 x$ |3 J9 V9 Q; q* Y% ?
  853.         uint16_t size = WiFi_GetBlockSize();
    9 y: T5 y4 Q* M$ ^, A; C
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);# t% W+ X2 {8 N" h5 i" x. z* l' L* o7 m
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);  S+ ~% ^( G4 z/ l9 d1 g
  856. }
    ) j: Y% @$ \& e; U

  857. & V7 j$ `8 r1 U
  858. /* 设置密钥 */. y0 g( u! M, P& O
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
    / @9 r- L' i, B4 Q( k
  860. {
    9 R4 g9 ]5 T& h% Z7 y
  861.         MrvlIETypes_KeyParamSet_t key_param;5 ~$ U0 W+ M( {' X
  862.         if (len > sizeof(key_param.key))
    0 ^- E( p! D1 O0 K" k9 ?' H4 H
  863.                 return CMD_STATUS_ERROR;* y/ m6 d- ~8 w
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;9 a: L& E9 i* |( S$ G6 @8 I
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;4 I) o3 s3 `' E& g8 q/ E& \
  866.         key_param.key_type_id = type;
    : _8 x6 M2 [9 ~2 D& k1 w1 |; q5 K
  867.         key_param.key_info = info;
    " k% {1 m$ {  L4 O" l8 j7 h0 E$ s9 z
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
    9 z( S4 W3 }6 r4 g- u3 M6 D
  869.         if (len)0 d+ c" ?4 I/ g3 |- F4 N4 B. h
  870.                 memcpy(key_param.key, key, len);
    5 y/ f; z! P) l8 C6 k. n
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    ' k  ]3 ~2 f4 x
  872. }
    ) p6 x# {! v1 u( r  z
  873. " z7 H0 E7 [. ~. R9 \. W. p9 E7 U
  874. /* 显示WiFi模块信息 */- B9 C' y9 `& w. I# S; x7 r3 k! C
  875. void WiFi_ShowCIS(uint8_t func)! O7 N! i0 c/ ~( i: i  C. w
  876. {' e; ^! b* W4 V
  877.         uint8_t data[255];
    4 |/ V+ J" e, b6 o3 ~
  878.         uint8_t i, len;
    2 W- ~* `1 H! p2 @: J: N
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure4 r, o0 S- c2 f
  880.         uint32_t cis_ptr;! j6 X2 g7 d( T+ k+ c
  881.         
    ! ~' C) C6 {* {) S- K" S
  882.         // 获取CIS的地址
    1 `2 J' e2 `; C* U; F) K
  883.         cis_ptr = (func << 8) | 0x9;
    ' {9 W3 K' `" v) Q( U
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);* h. _5 R, O7 F% B2 K$ T3 O
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);
    * u4 _3 ]$ b) \/ h$ v: a" k
  886.         
    0 n& D! P% |: m: q
  887.         // 遍历CIS, 直到尾节点
    2 R3 H1 p3 M, w: e, {
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END); w( p# P& H4 s4 Z1 n# ^3 p7 N' l3 u+ `
  889.         {
    1 p$ O) z+ W" i" B  I3 ?
  890.                 if (tpl_code == CISTPL_NULL)
    * V$ I5 s1 s+ q
  891.                         continue;8 a+ p7 a6 f+ B2 \: l
  892.                
    * w  ]- A* A( c! s
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小" O8 I3 M- V: h, ?9 s1 S- r0 s/ o
  894.                 for (i = 0; i < tpl_link; i++)
    - O% B" k: G. s* o0 X$ G5 @
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    2 O5 n) `7 A, G( b5 _$ c
  896.                 " [1 e0 e2 f( ]  \3 ?7 ~2 ]) r
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);6 A7 J9 Z) j2 ^. S
  898.                 dump_data(data, tpl_link);
    . {* i, l+ ~7 }* T; l& D3 ^: \
  899.                 switch (tpl_code)
    " y/ o! g& K+ N+ d) z
  900.                 {& [: |, R) W- J. e/ L; }7 O
  901.                 case CISTPL_VERS_1:8 d7 S0 j: D  }+ \/ S
  902.                         i = 2;; K8 j0 T8 |6 F* w8 n0 ~
  903.                         while (data[i] != 0xff)% o7 n% y5 m* p9 d6 y" @8 j- e
  904.                         {
    $ e" J8 A. F8 T+ y! t
  905.                                 len = strlen((char *)&data[i]);( A% o  ]  ]9 e4 K6 i6 f. `
  906.                                 if (len != 0)8 y" v9 q* i: T) G% m- Q$ C8 b
  907.                                         printf("%s\n", data + i);. C! m5 u% s- i% G" a7 x
  908.                                 i += len + 1;/ z; l3 C6 G, y
  909.                         }; r+ y6 ^5 V0 K
  910.                         break;; D& J8 a/ G8 F0 a. H3 ]
  911.                 case CISTPL_MANFID:6 P' S8 g/ D6 h  P4 E
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple7 `4 s# K9 @; u  F6 k" j5 Q
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
    6 i$ F! s5 k1 f
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD
    / o# V4 ]" U, K5 B4 q9 u. x. F
  915.                         break;0 f# `, e" l4 z  m8 i* m# I! W3 h: o
  916.                 case CISTPL_FUNCID:: E: p% c# ~! P! o* w$ z
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
    8 F+ a/ o; a7 D5 W, w% v" X$ J
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION5 ]' `% D+ j& ?  Q- @( ?6 ?( L8 c
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT
    6 s& m2 P) n9 R2 C$ \& X' l+ W5 y
  920.                         break;9 m$ G5 y# h2 P8 \. Y
  921.                 case CISTPL_FUNCE:+ h. p8 H3 h. {, i: e) E
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple# K8 X! H6 [0 C' \# Y
  923.                         if (data[0] == 0)$ Y1 M" o6 @  A/ u3 R
  924.                         {
    # r2 X2 g# a' Z& H! [1 m
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)3 [1 |5 [- @" V1 h" @6 q. }; `- I
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));
    0 }: G! b* e0 u4 z( D# O0 g
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);1 M0 a0 i3 c/ ~8 F3 n/ u
  928.                         }- [) p% F5 p4 n! c! V+ W0 B
  929.                         else
    + U) n. C( E0 @5 p9 l
  930.                         {4 U, P3 R5 W/ x+ j* ?) D1 e
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
    - `( T/ {& F' F" i
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
    / B3 ?; O& ?6 Q% p3 _) O' o- n, l
  933.                         }
    & e7 [. ?# S4 A; p2 {+ J+ a
  934.                 }  d3 L( \+ _' F' u' s0 i$ W( A
  935.                 " n. \9 ]" j1 W0 ?6 F
  936.                 cis_ptr += tpl_link;
    5 N; p' J- A6 S8 x7 {  ^
  937.                 if (tpl_link == 0xff)
    7 N5 h4 Q' C& q7 a# I! }
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点. ~2 L4 n& i  f; s7 E% Z
  939.         }
    . Y' l9 Q1 w0 x5 V' G% Q3 J
  940. }
    2 |1 u& H9 k' i  s/ D

  941. : N7 u8 d& _* x0 q
  942. /* 显示所有密钥 */
    7 f! x& i# f' b: j" j
  943. void WiFi_ShowKeyMaterials(void)
    ' m6 ?# e6 s3 n5 a
  944. {+ ?8 D: t8 Z: I3 Y
  945.         uint8_t buffer[256];
    9 [& q& f- i. K# t3 ~3 r+ f
  946.         uint16_t size;
    1 k. S9 O$ Q6 f$ j$ P3 T) G
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;
    " v& f1 D/ ~9 A' v6 V
  948.         0 e' n3 J0 s2 e3 n6 I- v2 w
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);: }! `) q" R# g( Y& z
  950.         while (size)5 L9 W& [) [6 {
  951.         {* E' v; H* j7 t
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
    7 u& K6 g$ t$ Z
  953.                 dump_data(key->key, key->key_len);
    % B, L) D  R+ ^+ H
  954.                 size -= MRVLIE_STRUCTLEN(*key);
    / @) J  ~& m8 q: Y. T) L
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));* K8 w# {" E5 a$ ?* K' D
  956.         }% m. K# ]. E) t0 @
  957.         if (size == 0)
    5 H6 |- P6 `$ M# |. w
  958.                 printf("data end!\n");  d' q& W& U7 r' L1 J5 l) {& g
  959. }
    & b  s$ x* q$ ~* e/ }9 M
  960. , }6 r; j  j) h% f
  961. /* 创建一个Ad-Hoc型的WiFi热点 */
    * i  y# {" U6 u$ z4 y# x
  962. uint8_t WiFi_StartADHOC(const char *ssid)
    & T6 F& N; w- Z! S) p
  963. {
    " p- P' a4 j2 E. s
  964.         WiFi_CmdRequest_ADHOCStart cmd;
    0 L# q; [: S" x1 e9 b
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
    ) c7 ~+ Y: B, h; P# |$ O9 C
  966.         ( ]% q8 ]; ?1 @, @- ]
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
    ( ^8 S- N3 m" S  S! k
  968.         cmd.bss_type = BSS_INDEPENDENT;: z2 E- ?. O' C8 z' A
  969.         cmd.bcn_period = 100;6 d' Q2 ?/ o; i+ t5 d+ P) }
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;: u; M4 c) ~2 S* N* |
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);% x" Q% T* [; M2 x" s: y
  972.         cmd.ibss_param_set.atim_window = 0;( [# e' B% F! U0 f
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;. s1 D2 ]2 U0 v: t( N3 ^2 I/ n3 B' m
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);5 ?. u6 T. Q/ r; c$ o
  975.         cmd.ds_param_set.channel = 1;) {0 R2 m9 v1 s- |* X
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;& Z5 d' s+ A" y, H8 |9 u7 t4 T/ Y
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;
    2 A% x/ f) a# _8 p9 c
  978.         & q7 u& M/ N; J5 D
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
    ' k2 L. M: D' P8 r
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));% ]7 y5 H! @: U7 O* C
  981.         return cmd.header.result;5 r0 M0 `: l* @0 j$ s8 r  \
  982. }$ |% ^* l5 Q4 |8 A6 h3 L

  983. . L/ W# L: Z# Z& a5 G- B
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */
    # t1 D0 t  k" G- ^" x  j
  985. uint8_t WiFi_Wait(uint8_t status)* N# t4 r8 P) b2 |  a' ]; r1 W
  986. {% L2 Q# Q  }& K
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    $ d$ Z; e( |  T! ?
  988.         WiFi_PrepareTimer(wifi_timeout);/ B/ {+ p" w5 S( ^
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status), \) Q, v5 W7 D9 ~6 g
  990.         {
      q, M2 ~  I, C' {
  991.                 if (TIM6->SR & TIM_SR_UIF)
    6 D. d, \. ]3 Z
  992.                 {
    ) W/ u) I: L* j, l  P* l+ O
  993.                         // 若超时时间已到6 P5 \  X5 |2 L
  994.                         TIM6->SR &= ~TIM_SR_UIF;+ d0 O$ U- E! v
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);+ k2 I8 B7 M2 |" \( P
  996.                         return 0;
      F; m. \) ?& q) \! h
  997.                 }
    ' T" @& N$ q# L
  998.         }
    . e: u* e" Y: z) f. ~) ^. L  g- V( P
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器
    / }9 k7 T1 D+ w) k$ `' m2 Q( b
  1000.         return 1;! ^- e/ `# g/ _0 K5 v& y% _
  1001. }( M+ q- t" k8 O# V7 O/ q3 G5 C* Y

  1002. $ _) k/ y" n1 _1 x* F
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */
    6 A$ r9 y0 B2 a+ f3 f
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)5 ^! O* z! W9 U* t( c: m8 K
  1005. {
    7 u+ s9 g5 {$ d$ y' @" {& A
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);
    & g; v& b" B: c' A8 Q8 Y
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)8 W( G3 Z/ e3 R; n; x- @2 M
  1008.         {
      X. |$ u# u2 s$ y$ W2 p
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    + y5 D# Y: Z" y0 {
  1010.                 return SDIO->RESP1 & 0xff;
    # L% E' {; Q; e; F
  1011.         }  L9 s* Y- K/ v* [0 h2 p
  1012.         else
    1 a! G  |6 m/ R' |
  1013.         {! c7 M4 c+ C' o3 |1 F. j5 h: W
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);
    5 G# l1 I: e; a6 G, j$ c
  1015.                 return 0;
    ! m9 c% O( ?5 _- R
  1016.         }, R  ^5 J: B  M* M" g9 d
  1017. }% f- w+ [1 ?9 ?. M# L3 B6 e3 J5 e! l
  1018. 5 \" ?% k' Y' s4 r' ]
  1019. /* 写数据 */% N, T! A: R. R) S. s
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小# p* D( j4 E, @0 D8 T- `# Y
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    , q' }* b5 |+ Z9 J% w" R
  1022. {
    0 Q2 q3 @2 I5 S# C8 d& G3 l
  1023.         uint32_t len, temp;
    ! X; e" ^) ]; F9 }9 E, K3 n8 B
  1024.         if (flags & CMD53_BLOCKMODE)) w& @3 p6 ]6 @4 ~/ V+ F8 D
  1025.         {6 [9 b9 F/ A8 F, w) m
  1026.                 len = count * WiFi_GetBlockSize();/ z+ M7 L1 o5 ]/ A; G
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;
    1 \8 p7 P9 ?, T; {: ]6 o
  1028.         }
    $ B4 Q/ H) M4 g1 |
  1029.         else( e8 m6 z3 `& b* s
  1030.         {
    & g1 ~7 F1 N4 Z& a0 v
  1031.                 len = count;5 C8 R! D, ~, t* z/ M) _1 z
  1032.                 if (len % 4 != 0)1 u# L6 ^- O/ ?1 z. a( f
  1033.                 {
    ) ~: D3 H, O" b; G. @* }5 C2 `$ y1 z
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    5 ?2 j4 ~% M3 X* T- [
  1035.                         count = len;
    2 i5 G& e/ N" B' T
  1036.                 }
    6 t$ Z; R6 o1 ?, s# ~1 b
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    4 L! x, F' @& X/ t5 r* [, [
  1038.         }
    ) @/ G" C: l, u7 R2 T5 [! R
  1039.         SDIO->DLEN = len;4 C6 x0 j' r4 V( \$ R! @
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块$ E4 o+ f+ Y/ W4 {2 y
  1041.         
    9 }$ i& L; U# A3 R% q' ^4 P
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);  F% r. H! R6 ^1 s/ }3 V' i* H
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);
    ; W% u) y2 b; L
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0)
    9 m% |6 F, k1 y1 v1 h
  1045.         {1 R- W$ T. D. ^3 C9 F
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");- H1 x, j9 Q3 v
  1047.                 return;
    ! F5 ~2 N/ P7 n& u  C
  1048.         }
    4 C" _9 W1 p8 Y. t  D' w0 s5 S
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;; G& @8 O, b1 W+ y; d; H2 `& F! p
  1050.         " ~# I& k2 z/ g- j9 C% A9 v
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据
    7 C8 W1 x% D8 z* f
  1052.         while (len)
      D4 [3 A0 y9 A  X$ P2 w! B; @
  1053.         {9 }( I$ ]: t$ n  @! G! v
  1054.                 len -= 4;
    . {/ w) z' ]  ~0 Z' O
  1055.                 if (bufsize >= 4)
    ' X/ U  `4 t% T/ D$ Y1 L6 c) Z
  1056.                 {. ?" b5 O0 W! G1 ^( C5 H& S6 }
  1057.                         SDIO->FIFO = *(uint32_t *)data;
    ) G4 A# D3 c; ]& X! o
  1058.                         data += 4;9 r( E/ j$ w4 f
  1059.                         bufsize -= 4;2 K& j" Z, k8 A1 M3 n) o
  1060.                 }! g  E3 ?( O2 H5 F2 U( V
  1061.                 else if (bufsize > 0)
      u0 \+ N7 }3 d
  1062.                 {
    ; ]" M/ U2 T4 x2 R
  1063.                         // 发送缓冲区最后1~3字节+ k8 k( ]" K4 `* {/ H. c
  1064.                         temp = 0; // 不足的位用0填充" w; V$ z4 a, a6 z
  1065.                         memcpy(&temp, data, bufsize);
    ' I1 F0 }: }. y' {
  1066.                         SDIO->FIFO = temp;5 K. `1 \* b' m# ~
  1067.                         bufsize = 0;
    5 j5 S4 B8 R' m8 P) }; m
  1068.                 }
    3 F, _7 c( Y- q$ m9 c; s8 ~, N2 p/ A
  1069.                 else
    ) O8 i% U; @* Q5 o* h
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0
    . G1 T6 ^$ T. ^7 n; z$ F
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待
    8 B3 B2 s2 U5 H: B8 S7 r6 r8 L
  1072.         }
    , _# g4 u) y: j& d2 t  f, K
  1073.         
    5 R8 L+ _: v% l
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕
    4 h% O% T. m# K! K
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
    2 K2 H( a" o2 y7 T
  1076.         
    3 R" }9 z/ T! x5 h  \3 M9 w
  1077.         // 清除相关标志位/ X+ A/ g5 o! W+ N% V* K
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;  E6 u  H7 e6 [( v
  1079.         if (flags & CMD53_BLOCKMODE)
      Q9 K; _/ F. P- n
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;  Y8 C$ D! F# Z, v" S) O, D
  1081. }% f# A% G8 P. @7 i) G' p

  1082. ( R' d' k0 |; Y/ `. g$ p
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)/ I0 {& v" ]$ L7 j) z$ I. J
  1084. {! T& w7 p2 O& M. Q6 K3 T5 Q1 k1 }
  1085.         uint16_t block_num, block_size;
    . Z+ A; ^; L9 W$ c3 I  h3 Y( Q
  1086.         block_size = WiFi_GetBlockSize();; x, R6 F' |9 D& ~
  1087.         4 _2 \% Y7 Z+ Y2 y( @* t: l! X
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    6 Q8 D% u5 R! h/ i
  1089.         if (size >= 512 || size % block_size == 0)8 Q4 E: a1 K; }. g/ H, ~
  1090.         {& u6 _* `* C1 _( Y
  1091.                 // 采用Block模式传输! n- J9 E0 C/ N4 x3 c6 x
  1092.                 block_num = size / block_size;
    5 l: F9 f- D5 J) ]- `
  1093.                 if (size % block_size != 0)) v* }7 c# R3 f1 X
  1094.                         block_num++;
    6 C5 `7 t' ^* W* l6 V3 e
  1095.                
    1 F6 `$ I7 {+ ~8 {9 n
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);  X5 L$ c+ E8 u
  1097.         }1 q' T! x4 e" b, X
  1098.         else
    . c0 t, G. e' q* N  u7 x- D. i6 `
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);. a) E  r4 e3 X$ V# B+ i  f
  1100.         return SDIO->STA == 0;/ n* V( `, }0 U/ S- W5 Q
  1101. }
    7 }7 C- {9 b& p1 S
复制代码
. D9 d  D- S4 @& D4 l, g; t. z
; v8 u! N* q0 ?
在工程的所在文件夹创建一个lwip文件夹。& s; q; p2 k* \9 X# I  W4 [
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。/ f; r0 m; Y: Z' [3 G% s

/ F/ i; s  }( P% X0 E# J& @$ Kcore/: f; |" M9 v$ [# z" V+ M
core/ipv4
- q6 o+ e5 |0 t& x& Winclude/lwip
; G4 V+ g5 F" Y/ a2 ]include/netif
6 W2 a( X6 Q7 C- s7 i% e" {! t3 enetif/ethernet.c. v( ]1 G* B# l7 c6 u
netif/ethernetif.c
: @& j# k, _7 h6 z: G, E; [/ Y+ e: J+ F
解压后,将里面的c文件都添加到工程的lwip分组下。# T$ Q) C# d- K
具体添加的文件请看下图:9 e$ C3 K; Q3 y  Z' N0 c

6 d5 x! z7 Q) `" ~. d' ]% _* |
; }' `  p# @: U6 u) G接下来,创建lwip/include/arch/cc.h文件,内容如下:8 K7 [  n* k! [) g* D3 Y
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:
- Z$ x/ ^2 w' Y1 b6 [/ N2 t
  1.     #define NO_SYS 1 // 无操作系统  6 G8 l- Z6 Y9 H; c& s& |
  2.       
    1 M  K9 o: p' Q% M( Q: o
  3.     #define LWIP_NETCONN 0  
    ; p9 b; ~. r4 W
  4.     #define LWIP_SOCKET 0  
    ' V. c3 [. M. E
  5.     #define LWIP_STATS 0  ; W2 I9 T2 K$ U6 k
  6.       
    * R" p1 l6 x- e4 B
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  4 T1 b7 C4 L7 }  Y6 J% T
  8.       6 ]  n7 W/ N- [5 \7 Y) v* X- [. Q$ r' v
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:
5 E1 ~! j2 K$ U5 G' g
  1. /**; Z0 \- y+ }( U% _  m
  2. * @file
    % m/ L1 ?  B" }! W3 V9 p
  3. * Ethernet Interface Skeleton* k- [" j* i2 t8 R. J/ S: A
  4. *3 h& B# X7 F# w0 c
  5. */
    # B9 S! K, \- p2 q. L
  6. + n4 m$ L5 n2 \3 m6 b+ e6 n6 P
  7. /*
    / _2 _! |, L1 f) U
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.( N; f( P; z5 ?3 p9 [1 l! h7 E% I* ?4 H
  9. * All rights reserved.1 [4 `5 ~% w1 c
  10. *
    8 ?/ B7 Z! T6 I+ {( A
  11. * Redistribution and use in source and binary forms, with or without modification,2 o4 ^6 s+ }3 _! Y- d* i! X; u  C4 _
  12. * are permitted provided that the following conditions are met:4 t; w/ Z$ T$ F( F1 P8 B8 B, s
  13. *
    * o* t+ y' m# A! o! m- O# a
  14. * 1. Redistributions of source code must retain the above copyright notice,
    ; v$ V' v4 {% j
  15. *    this list of conditions and the following disclaimer.& E5 j' O6 H  c% l6 j5 z; V
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,
    $ l6 Y) `% L6 F# @8 G! I2 ?9 r- B( k5 H
  17. *    this list of conditions and the following disclaimer in the documentation
    # O2 ^" e( S2 o
  18. *    and/or other materials provided with the distribution.
    $ Q3 n& U0 e- Z, c7 I! ~+ R+ `
  19. * 3. The name of the author may not be used to endorse or promote products9 U$ P6 p; r( ^2 q/ u5 Z
  20. *    derived from this software without specific prior written permission.3 M# f, T! l: U
  21. *) M  p3 h+ Q4 p% [4 @
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    0 J" @/ G8 X, d- k6 H7 z& ]
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF$ w; l% z) H3 p) H
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    1 P0 n* A' X" k- A2 o
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    , S- o! l" Z# P. {6 p
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT' Z. P0 G; L. w" {
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5 O% T  _' D' ]6 D, [
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    ! q' o; j2 T* w( U3 P
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
      B* v# ~) u. S% ?+ z
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY8 P- g  C) a/ w0 q3 Q' B! Y% D/ u2 o
  31. * OF SUCH DAMAGE.
    / b$ m1 S1 t( o/ U& L
  32. *: w1 N) t0 e( ]% t. G( A; l2 w
  33. * This file is part of the lwIP TCP/IP stack.
    / s. }0 }$ U+ N
  34. *
    7 O8 r* k& {' W  q  z8 T
  35. * Author: Adam Dunkels <adam@sics.se>
      ^' H3 Y# k: n7 B4 h3 o
  36. *  k. ]8 v' @6 ?7 I9 W
  37. */
    6 e1 h- |" `, i% l; u# a

  38. 1 }  i0 b2 H9 ^6 }5 T& ~: h
  39. /*
    ) d9 @) s4 x- _, D; l3 g
  40. * This file is a skeleton for developing Ethernet network interface
    6 M5 U5 U0 w% _: d8 g5 R
  41. * drivers for lwIP. Add code to the low_level functions and do a; _) p+ O- |, h+ S, r% |
  42. * search-and-replace for the word "ethernetif" to replace it with1 I0 O6 f, M  ~- {8 x& Q+ H: m
  43. * something that better describes your network interface." @* \; k  Y3 }7 w3 Q% D
  44. */4 x* n" m' _% e) L7 o# E
  45. 4 S1 A$ N0 t, t2 O% c5 O4 `
  46. #include "lwip/opt.h"
    4 P' ^8 ?% f1 _- o2 R

  47. $ ~! [7 i4 Q" k) I4 t* e
  48. #if 1 // 允许编译器编译该文件* j) N) Q/ I! }

  49. 5 m5 F& X  ~( r) N
  50. #include "lwip/def.h"3 G: w. O$ I; K0 L% a) s3 [
  51. #include "lwip/mem.h"
    . `" ?: g8 M2 E( q( z* P( w
  52. #include "lwip/pbuf.h"! v- i0 B2 m+ q  m: y% Q0 V6 d4 I1 W
  53. #include "lwip/stats.h"3 _9 _0 g" _( B2 p% A% T7 {
  54. #include "lwip/snmp.h"% L; b( _$ R) S& e+ K' M4 B) |
  55. #include "lwip/ethip6.h"8 B, q4 b# `& @! R
  56. #include "lwip/etharp.h"
    " c  t+ ]" x# N
  57. #include "netif/ppp/pppoe.h"# F* z1 ]3 `, h/ d" a7 H9 Z
  58. * x' W4 \% V: ]( _
  59. /* Define those to better describe your network interface. */
    8 W$ U0 O$ A2 t& ]+ y( d: q. V
  60. #define IFNAME0 'e'* R! b: a2 g" s
  61. #define IFNAME1 'n'0 r, s# E* O: Z, I  V
  62. - G/ H, z! {$ i) N
  63. #include <string.h> // memcpy函数所在的头文件
    0 g3 e0 }# w& v
  64. #include "WiFi.h" // WiFi模块驱动程序头文件
    ( L  R. e$ y9 B* n! i. X

  65. . r; V9 k( b( a1 ^
  66. void dump_data(uint8_t *data, uint16_t len);
    . O0 `/ X1 ?/ S1 ~- M1 [
  67. + O. t3 j: F' h4 k7 H
  68. /**- G; M; V& K$ [
  69. * Helper struct to hold private data used to operate your ethernet interface.. P2 A8 |2 o3 N1 l
  70. * Keeping the ethernet address of the MAC in this struct is not necessary
    7 P: F2 x! J3 a9 x! Q7 C' |/ r4 D
  71. * as it is already kept in the struct netif.# N9 {+ s) f3 }) G4 s
  72. * But this is only an example, anyway..." h* U. V9 n9 L5 {* A
  73. */
    7 e' \) w( X% g6 @2 |" F
  74. struct ethernetif {6 Y( V  y3 k4 W8 I0 c" W' m
  75.   struct eth_addr *ethaddr;$ \# M! Q4 n* _3 q& h* Y+ d
  76.   /* Add whatever per-interface state that is needed here. */
    " f- U1 ^3 t$ S7 @
  77. };
    ! T# U# D8 W/ N) K

  78. 7 b2 z3 H0 \6 I
  79. /* Forward declarations. */
    " R+ C9 Z  w9 }0 ]. g
  80. // 这里必须去掉static* q& ~, c; g6 I
  81. /*static */void  ethernetif_input(struct netif *netif);, C( B/ ^0 g+ P1 y6 {

  82. ( X5 S; O. L1 w& V
  83. /**4 Q; |& U. P& `; i2 i7 u
  84. * In this function, the hardware should be initialized.
    2 I: _9 Y& ^6 `; Q9 O8 J8 M
  85. * Called from ethernetif_init().
    1 Y6 p6 d) N, c* g  s3 u
  86. *' C) h3 f( `: z7 z
  87. * @param netif the already initialized lwip network interface structure
      t! ]" p. U* Y. s' C
  88. *        for this ethernetif
    * @" u# l5 G! L! `( b  u
  89. */
    ) j1 Z- b7 x( V+ r- q
  90. static void6 G$ r$ z4 I$ W$ T+ c
  91. low_level_init(struct netif *netif)0 E2 D' Q$ C; Q) z- {# Y! W* P
  92. {
    , H$ `' J/ w3 c" Z5 d* P
  93.   struct ethernetif *ethernetif = netif->state;
    ! E* D6 t0 I& E2 {. q. C) p' w, v

  94. - b! H& S) w9 x' q* [3 J4 k# L
  95.   /* set MAC hardware address length */
    3 |( Q. A6 S( X$ c
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;
    . W5 ?# B- p, E  H8 M2 v5 w7 R6 H

  97. 4 w! q; L) {& R8 o! j1 ^$ t+ Q7 p
  98.   /* set MAC hardware address */
    3 {+ H8 {! B6 d3 ]7 v1 y0 v- @
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
    , T: w& J5 T$ u$ S* ~: E
  100.   printf("MAC Addr: %02X:%02X:%02X:%02X:%02X:%02X\n", netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);1 r3 Z0 Y+ @+ t7 O

  101. 6 J6 Z- `8 c. h* S  K5 V# u
  102.   /* maximum transfer unit */- m3 }7 z# T2 ?9 r
  103.   netif->mtu = 1500;
    " I; n3 s5 s" V( {" \

  104. ( m7 f  g- Z# r9 C
  105.   /* device capabilities */8 n9 x& b' k9 o/ D6 Q7 h  E) P4 t
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
      I7 B  C# o6 m  G; E3 X
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
    5 {3 d# F) V: e
  108. % b$ i3 {) t/ l/ ]/ a
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD7 Z5 `6 ?' }0 x1 o: }" q& ~% k1 ~
  110.   /*8 l. u# t" \1 P! Z* G
  111.    * For hardware/netifs that implement MAC filtering.
    7 s7 v3 W2 c: z9 w4 Z, J
  112.    * All-nodes link-local is handled by default, so we must let the hardware know
    6 N; m, M) @+ p, j' M
  113.    * to allow multicast packets in.
    0 J" b) I+ h3 v* I
  114.    * Should set mld_mac_filter previously. */, [2 E# v% ~+ R9 r/ w7 x7 q
  115.   if (netif->mld_mac_filter != NULL) {$ Q- S; K# M/ v* U, F+ ?
  116.     ip6_addr_t ip6_allnodes_ll;" f% Q6 X1 V6 p: G
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);4 T5 n( K: J7 ?( q) K, S2 a
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);+ \. c. m+ s6 c9 s
  119.   }% M  {/ ^% X3 R  b5 x
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */$ z4 |$ ^; P+ z4 R

  121. , \5 A; {# n: w# Q/ }  c; v
  122.   /* Do whatever else is needed to initialize interface. *// Z5 l! s+ L. B+ q6 l$ r
  123. }& w1 l1 o/ a) I5 ~  c
  124. 1 F; y" l* N: e% f9 T- Y
  125. /**
    0 T* H% C2 r, I* [* \# S
  126. * This function should do the actual transmission of the packet. The packet is
    6 r! v0 Y( N  M, _7 r+ A) ~
  127. * contained in the pbuf that is passed to the function. This pbuf
    8 x7 [: |0 ^! }1 b) \% \" l0 M) L  F
  128. * might be chained.+ Z. e5 D( l1 \* B
  129. *" _" c' Q- [8 o
  130. * @param netif the lwip network interface structure for this ethernetif$ D: m0 N8 e$ L" z5 T& Z
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)7 ^$ N, @4 k# m3 Z% b( U
  132. * @return ERR_OK if the packet could be sent& J  |4 N+ l, q6 x
  133. *         an err_t value if the packet couldn't be sent
    $ ]" m6 ]/ U" F8 Q$ B
  134. *$ g7 T7 S% e8 \0 F1 E
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to# a  J5 _; I- W0 \" V! p! j3 u; `
  136. *       strange results. You might consider waiting for space in the DMA queue/ P8 u  s9 M) Q* k8 `( `9 R
  137. *       to become available since the stack doesn't retry to send a packet
    ( X7 D& O2 P+ a4 b& W
  138. *       dropped because of memory failure (except for the TCP timers).
    ! ~3 S  ]# v$ ^0 p
  139. */" s7 f. C" \4 h) S

  140. 2 e# {2 |& {1 M7 {" \8 H
  141. static err_t' P5 ^2 U/ O" R& }
  142. low_level_output(struct netif *netif, struct pbuf *p), Q; u. o7 G! {4 ]/ o! n) }% p
  143. {7 u' c; `# @+ h- Y) x) Z
  144.   struct ethernetif *ethernetif = netif->state;
    5 z+ z* b9 M/ q0 U* x( z5 f3 n
  145.   struct pbuf *q;& |$ [# y" Y8 v6 S  p
  146.         
    & ~1 H. a4 ~! A1 R
  147.   // 添加的变量( L* C( P& `0 I- v6 O
  148.   uint8_t buffer[1792];
    " m' P5 F; H* \) k$ W2 G
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;
    ' V8 d- x: S2 }' v) [9 J! j
  150.   uint8_t *bufptr = packet->payload;8 _$ M( W+ @- h( H$ \

  151. 2 |) R6 d' K+ F5 x4 d
  152.   //initiate transfer();& F9 m4 N" v3 ]' U) S, q" }

  153. # V8 h3 Z  @6 H
  154. #if ETH_PAD_SIZE
    ; @# M  c* |+ H  J6 b* o) x
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    % `  ]# q$ c/ |1 H* x9 |
  156. #endif6 r7 z2 [8 B. s

  157. , V- N9 ~8 \# z/ M
  158.   for (q = p; q != NULL; q = q->next) {
    7 p0 k: a, Q# {5 w0 ]
  159.     /* Send the data from the pbuf to the interface, one pbuf at a6 h! {; d0 z4 t, F
  160.        time. The size of the data in each pbuf is kept in the ->len) `+ U2 g" c/ l$ g3 J3 N
  161.        variable. */! s' ]& y. |/ y! i- H, X* U& p
  162.     //send data from(q->payload, q->len);# v$ H  r  g3 ?& a3 e) C
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容; A6 Z3 R% v  i: f  |
  164.         bufptr += q->len; // 指针前移
    ; z  T2 q7 i1 @
  165.   }
    ( z+ R2 ^3 Y2 n" F0 f8 m

  166. 6 G: H9 O( l6 r; [: X' Q+ z
  167.   //signal that packet should be sent();7 v$ x: i1 q% s
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包0 V) j( g" \& ~  F9 E
  169.   
    . b: P# R5 k6 g7 a1 w1 }/ u
  170.   // 打印数据包内容
    ' v  y) N+ }6 S  _) ]- o7 \
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);1 h4 w- E; `9 n% u
  172.   dump_data(packet->payload, packet->tx_packet_length);- `7 [) l  E0 n$ V8 K6 h# {
  173. ) }+ T# O7 M3 C& e+ P4 I6 F' G+ P
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);; }) ?$ q2 l5 a
  175.   if (((u8_t*)p->payload)[0] & 1) {
    5 W3 r1 N2 p0 u: Z5 m; k; G
  176.     /* broadcast or multicast packet*/  C# M% b8 j8 h2 f
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
    / v) [3 y. H* K! v
  178.   } else {
    - U2 ?9 t1 L' Y  b& ?. E7 ^
  179.     /* unicast packet */1 t% E) n, Y! m" J' j, K! m
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);0 x* `0 j* K8 C# ]- z+ q" u
  181.   }
    " o( U; x/ I/ |) L
  182.   /* increase ifoutdiscards or ifouterrors on error */
    5 s: m. @% K' d# E9 V

  183. 2 K4 s$ @2 u- O- R( G
  184. #if ETH_PAD_SIZE
    * z2 I8 g6 e( ?; t4 O
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */9 e* i1 W% @3 t
  186. #endif
    $ o8 t( }3 Y1 l1 x" i
  187. 3 D! d+ r6 c) f% U: O
  188.   LINK_STATS_INC(link.xmit);1 J1 A5 q. o, E' c
  189. ' v5 x% ]% {7 g2 S
  190.   return ERR_OK;
    . I, A5 ]; [& q4 k9 i8 l5 B- a
  191. }
    + d4 ]$ {7 f0 n8 l# Q; i$ u
  192. * L7 ~+ G1 Q5 o/ \
  193. /**5 c- n- E7 [- q9 E( q3 r
  194. * Should allocate a pbuf and transfer the bytes of the incoming
    4 X. M# W/ q3 l3 }4 \2 P( m, w6 L
  195. * packet from the interface into the pbuf.8 |5 t6 k, B! e4 s" C
  196. *( m& p: D3 t) H2 X2 q, h! n  r. G
  197. * @param netif the lwip network interface structure for this ethernetif
    # l+ t" X6 P$ W& ]' v2 U
  198. * @return a pbuf filled with the received packet (including MAC header)' b2 O) E6 N2 }. A. w8 `( J
  199. *         NULL on memory error7 [; A5 \# A. o% a6 T
  200. */
    0 O4 H$ @2 V# z7 `: O. l
  201. static struct pbuf *
    1 @" ]4 P6 r6 F5 j  S
  202. low_level_input(struct netif *netif)7 N; U( D$ Q- e% j! o! \# [( ~3 e. T
  203. {$ `" q1 q1 b& S4 e  {1 z
  204.   struct ethernetif *ethernetif = netif->state;
    : L9 a  x- \7 i. _
  205.   struct pbuf *p, *q;
    $ z) Y4 b# U# L3 A+ p9 v. z
  206.   u16_t len;
    * N+ b+ F# ~$ ?) r: ~7 V: ^$ p" p
  207.         # j; p6 |3 A5 m% c' J3 m  t/ K! n
  208.   // 添加的变量+ `7 _. E: h  E4 |1 f
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完
    7 T( M5 j- z& T, Q" H5 h& A5 A
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;8 W* m( s) E& p8 @
  211.   uint8_t *bufptr = packet->payload;
    & C6 z5 Q# M2 T4 I
  212. ; n4 z* T! i) O) x
  213.   /* Obtain the size of the packet and put it into the "len"
    0 W# x4 `" ]/ V7 }: G- z
  214.      variable. */  x- a/ m% B( H
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小$ D' Z2 W3 q7 Y
  216.   if (len == 0)
    ! O2 M0 s3 Q/ [; S: g6 N9 l( f
  217.   {
    + i: C. Y, Z5 y% H3 D
  218.           // 若读取失败, 则不分配pbuf, 退出本函数6 {4 X+ Z! o6 i  [6 z
  219.           p = NULL;$ F$ K. I# Z. d- o5 i6 K- ]
  220.           goto after_alloc;
    7 l" C/ G! G' d3 P3 [. t
  221.   }" C/ Y- x3 t# P2 B/ |
  222.   len = packet->rx_packet_length; // 获取数据包的大小0 H/ q/ Z' I2 r) W0 G+ X; x& d
  223.         
    2 P8 o* B3 r5 M% [2 [: b
  224.   // 打印数据包内容
    9 O/ C; w; L% k+ h! V+ G  y) N& L8 Y
  225.   printf("[Recv] size=%d\n", len);3 L' k6 v3 h3 S; t% c( s
  226.   dump_data(packet->payload, len);8 P# p2 {) r' ^/ S  z

  227. $ F5 S1 g# p+ d; v
  228. #if ETH_PAD_SIZE, ?/ t" i% |4 B# ^) F
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
    1 [8 r8 I& q. E' i& Y
  230. #endif$ m" h" f# ^0 {3 h3 i+ U9 t% I) s: ^

  231. # {: F' ?4 G, `8 a  p9 B0 l
  232.   /* We allocate a pbuf chain of pbufs from the pool. */7 a* j3 ?) @: r& B& h) ]2 f
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);; }! U' E+ T/ p' {
  234.   
    9 J: V! J" C* z, {& k' h+ Q: ]* @
  235. after_alloc: // 添加此标记
    5 n% i) ?6 `! O3 u
  236. % S" c) f7 R) H2 y
  237.   if (p != NULL) {8 B, x6 E6 f0 s8 F

  238. : o& O' A4 x2 e6 C  u$ t" p
  239. #if ETH_PAD_SIZE  n7 l$ @9 i; Z4 ?& B8 _4 D
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    ' k. u9 l( _. n4 H
  241. #endif
    - a4 [$ Z" l* @6 B( g

  242. 5 V! T# c. r5 [
  243.     /* We iterate over the pbuf chain until we have read the entire
    ( t9 R1 Q1 ?; _, x8 @
  244.      * packet into the pbuf. */% T) e2 C9 U* ?. ?* @& v6 i' N' J
  245.     for (q = p; q != NULL; q = q->next) {1 `: w+ q8 d" x% n( K5 U
  246.       /* Read enough bytes to fill this pbuf in the chain. The+ b1 g6 K" ]. X# m! B$ m
  247.        * available data in the pbuf is given by the q->len! z! u7 y! a) L2 P+ G
  248.        * variable.
    % B' v" R+ p( d; w% |
  249.        * This does not necessarily have to be a memcpy, you can also preallocate
    1 o3 h; L7 \7 l% i
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
    8 M# _9 X! p6 D
  251.        * actually received size. In this case, ensure the tot_len member of the  ]% Q  T( |5 n8 u5 x( w- {
  252.        * pbuf is the sum of the chained pbuf len members.9 o9 D  I# g1 V; P$ H
  253.        */* u& ^/ \4 Q, |* H) {3 O2 u4 S
  254.       //read data into(q->payload, q->len);. V; h; l; s3 _4 L7 f3 ]
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容* I; @  W7 r7 Y% n7 w( Q# h
  256.                 bufptr += q->len; // 指针前移
    1 t/ p/ z* J( O' T8 S7 S
  257.     }
    5 M2 A' V4 K" p4 G4 t- q
  258.     //acknowledge that packet has been read(); // 无需确认
    - _8 @0 H6 B' s4 k

  259. $ C6 Y3 p! F4 o7 y9 s2 d+ ?
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);0 t9 p3 [( h9 R! [2 t6 d8 ~
  261.     if (((u8_t*)p->payload)[0] & 1) {( r1 ]7 U+ n1 w+ w$ Z
  262.       /* broadcast or multicast packet*/  w! N+ G6 U1 C$ F( Y0 {  v) c) {
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
    + A+ u3 m$ }5 f( A/ k
  264.     } else {# A6 b* }8 I7 W9 f/ r2 [5 H
  265.       /* unicast packet*/$ v& I+ k% k2 E8 y. g
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
    ; Z/ O4 Q1 r- F2 c. F0 x
  267.     }
    5 y8 j: {' Z" x
  268. #if ETH_PAD_SIZE- m9 n& K7 z$ j' `3 ~
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */5 R* ^' L% t! Z9 U& ~  G& o5 }5 _7 b
  270. #endif# k/ ^" R$ Y5 S( P

  271. 1 i  }: h% o: l
  272.     LINK_STATS_INC(link.recv);
    - p& o3 j# |/ e$ c3 `2 p
  273.   } else {3 f; P8 Z8 U9 w/ g, [
  274.     //drop packet(); // 注释掉此行
    : F( w/ R4 ~1 N! x5 B3 u
  275.     LINK_STATS_INC(link.memerr);
    ( K2 {! X" H3 l# W" q7 S
  276.     LINK_STATS_INC(link.drop);
    - ~1 |1 D5 Y; g! s
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);
    ) e. _' O5 `/ s! z! i# y8 R( i
  278.   }& F) a/ P4 T* M+ F- v% C

  279. ( |1 R: K, L& {+ q) |$ p
  280.   return p;  u1 o, U2 X# u# y( V3 c1 b% M
  281. }% t& ]3 q2 {: Y
  282. 3 `8 t) ]/ W4 H+ r# `
  283. /**. N0 `, g  P; q; H/ o
  284. * This function should be called when a packet is ready to be read
    3 v: c' i9 f' {6 a4 w3 O" n
  285. * from the interface. It uses the function low_level_input() that
    8 r& Q' {/ D0 z, J5 z1 x1 S; |: |" r+ }
  286. * should handle the actual reception of bytes from the network, d0 ]- B! r- ^; N5 Y! O
  287. * interface. Then the type of the received packet is determined and! @$ A: S. Z* D3 c; m; d
  288. * the appropriate input function is called.
    ' m$ [: o8 [/ V; L$ Q
  289. *
    6 W0 |# n, z3 H5 f. W( X$ N
  290. * @param netif the lwip network interface structure for this ethernetif: V* l2 A( h, F. r- q
  291. */' H/ j+ g: S' i0 ?9 J3 t2 P
  292. // 必须去掉static3 q( Q: r  ?. |+ t; ^3 H9 o: q/ A3 V
  293. /*static */void6 Z# n& D4 B+ m2 y! F1 w
  294. ethernetif_input(struct netif *netif)0 l  j3 w! X0 j& p
  295. {
    ; x" i$ U4 @0 @  V; Z6 C+ F. i4 M" J
  296.   struct ethernetif *ethernetif;7 T0 X4 ?6 n) |' z
  297.   struct eth_hdr *ethhdr;
    , I3 g+ U; M7 V# ^5 Z
  298.   struct pbuf *p;$ R5 {0 C( X4 X+ c# P& f5 d
  299. . u3 [- ]. x8 M6 g, Z8 Z
  300.   ethernetif = netif->state;
    , V. \) _. ~& u, [- ~  ?+ q
  301. & ^& c- w$ P! H
  302.   /* move received packet into a new pbuf */, X/ I) f' j5 G0 F! U) }8 a
  303.   p = low_level_input(netif);
    , z# n0 V5 K! D: D& N) t
  304.   /* if no packet could be read, silently ignore this */
    6 R) |1 H. ?$ h% }0 y4 T2 T
  305.   if (p != NULL) {
    + R: r1 m' W( ?4 u2 D
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */
    0 B" t% }7 C- C! s3 K; X
  307.     if (netif->input(p, netif) != ERR_OK) {8 P( T% t0 t* G8 z
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    + n+ ?7 i$ x7 u8 R+ O" h0 G
  309.       pbuf_free(p);
    # g% ^1 |$ S/ `$ y
  310.       p = NULL;, x2 w6 \% H/ d/ V  A
  311.     }! b" R8 w9 K6 U- Y! k/ v  p+ g
  312.   }; ]0 a/ ^. `! D* R" Y; s3 u5 m
  313. }/ c( c: c, d' U  C' I" ~
  314. 0 ~$ ~* \" @) o- F0 w+ q+ j# q
  315. /**
    ' X2 A- @+ L' Z# H7 ^
  316. * Should be called at the beginning of the program to set up the3 \- Y4 M. A! ?& G1 s; l- P) V
  317. * network interface. It calls the function low_level_init() to do the
    5 Y* l* J. R! u# a! j
  318. * actual setup of the hardware.
    9 K4 M  M5 Q  X: M. ~
  319. *
    ! N) \2 J" b6 r, T0 ]
  320. * This function should be passed as a parameter to netif_add().3 I* R. B  Y7 t6 ]
  321. *% T# o) U( Q0 S6 ?( H+ @, d
  322. * @param netif the lwip network interface structure for this ethernetif
    8 h. H' C( O, h
  323. * @return ERR_OK if the loopif is initialized7 {1 D- V+ V1 i6 f) ]2 |9 u
  324. *         ERR_MEM if private data couldn't be allocated0 N) y7 }9 R1 V. p; ~3 |" R
  325. *         any other err_t on error% Q# I& @0 {0 E9 I' n7 _+ o7 c
  326. */
    - T% {: _+ E/ k3 l& O) L
  327. err_t
    ) n2 y, p+ n- J1 \
  328. ethernetif_init(struct netif *netif)5 U9 w: o9 S: ^+ C9 d% P; |7 d) N
  329. {
      M6 Q8 `) m4 C* e8 @
  330.   struct ethernetif *ethernetif;
    . u) a+ x# W! L; Z/ i  Q
  331. 4 d* q- x: v/ V  w9 O- [4 ]
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));( w* j2 M1 }7 y2 H2 L

  333. 7 H* Y1 P. B1 Y% a) X( ~
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));! {& D' B% Q: a+ U# S4 {
  335.   if (ethernetif == NULL) {
      e7 n2 l7 F7 F+ [- }" w* d. f
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));; n  W6 }0 D2 U* K
  337.     return ERR_MEM;1 M% @- I3 Y( N
  338.   }, O6 u+ k, U# r, n; L$ R

  339. $ i5 G! _% Q- C7 _" t0 [# K) ]
  340. #if LWIP_NETIF_HOSTNAME8 h: P5 c; j' q
  341.   /* Initialize interface hostname */
    9 r1 K9 t, Q7 J3 V8 U: W) O
  342.   netif->hostname = "lwip";
    6 y0 ~" w6 y% K' s0 k0 i5 H1 Z) U
  343. #endif /* LWIP_NETIF_HOSTNAME */
    , ^( ?; U8 m* e! u
  344. 4 `% V. _) X' g9 h. r$ F& J
  345.   /*
    # i( r% ^1 m1 n4 C- S
  346.    * Initialize the snmp variables and counters inside the struct netif.
    * M" }! J# b; S# T4 E5 V
  347.    * The last argument should be replaced with your link speed, in units% C& ^* @% a+ V) v
  348.    * of bits per second.
    - W9 ~. v6 K. Z  T5 j+ S
  349.    */
    # B* `* q% n6 [8 a6 V% ]
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);; w3 U% v! p: A

  351. ! H/ e( s9 p1 p0 W% o3 X5 w: r
  352.   netif->state = ethernetif;: R" ]8 N% _9 A* d4 r" Z
  353.   netif->name[0] = IFNAME0;
    - Q4 H* q8 w6 u! t/ f0 ~
  354.   netif->name[1] = IFNAME1;
    6 F7 G  U9 Z% y# ^( a
  355.   /* We directly use etharp_output() here to save a function call.9 D0 P2 b( d0 E4 Y: ]" i1 ]) r1 P
  356.    * You can instead declare your own function an call etharp_output()
    8 j2 G/ ]) H" X  D: F8 O
  357.    * from it if you have to do some checks before sending (e.g. if link6 e) a! I# }$ g; M2 [
  358.    * is available...) */  |3 R  g  p, Z6 ?- z7 J
  359.   netif->output = etharp_output;
    " N6 i. h0 Y4 f/ P8 S6 [  E
  360. #if LWIP_IPV6& R0 ]+ k4 r& N. W# H
  361.   netif->output_ip6 = ethip6_output;
    1 o  n4 \9 o/ H; [2 p8 s7 Q7 x
  362. #endif /* LWIP_IPV6 */' r: [/ x5 h; V2 b4 n3 `6 `
  363.   netif->linkoutput = low_level_output;1 O! z& d) M7 T3 b% a" \# n! L8 C
  364. 6 F; h) S6 U" f
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
      j7 V3 g( Y" ?( ?1 W) r5 d: R

  366. / n: u& I* m  L/ Z$ ]
  367.   /* initialize the hardware */
    # t, G) S7 J3 Y3 ]
  368.   low_level_init(netif);
    & S: q/ @6 x( A* X% w3 ]# X( _+ o

  369. 8 e" C# {" l: X( g2 I- p3 t
  370.   return ERR_OK;) R  a/ K" G; {% z
  371. }
    5 k8 O) I2 J+ C. D# U) Z
  372. 5 L% G2 `8 k# M9 D" ^5 r
  373. #endif /* 0 */) ~- N& m/ T- i/ `- v# P, E
复制代码

( h! e3 @9 N3 s2 G! y& P) O5 k在项目属性中,设置Include Paths为:.;.\lwip\include# E: _0 y$ \7 E2 G# l
其中点表示工程根目录。; }$ _5 i% H$ j, s& p! A

; `; {9 B1 o7 o  w$ E另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
& _, b% d  l! @4 l' d% K" n- i
- G* w0 y4 J& X7 m编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。3 h' J2 c, Q3 h4 f+ l
电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。  N8 A3 z& t" x! c* f7 x. q$ ~. t
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。7 |% C. n, m+ p' Q; g

评分

参与人数 1 ST金币 +6 收起 理由
MrJiu + 6 赞一个!

查看全部评分

收藏 3 评论5 发布时间:2017-7-20 16:34

举报

5个回答
lijain 回答时间:2017-9-11 09:32:08
楼主你好,我最近也在做esp8266数据传输。做了一个stm32控制的tcp server可以传递数据,但是传递时间有点慢。可以和你讨论一下吗?我的qq是1632401541
MrJiu 回答时间:2017-7-21 11:10:56
个人给个建议,大量代码最好用文件的形式...然后将一些注意的地方,和自己整个开发过程的经验!!!!
zero99 回答时间:2017-7-24 15:03:19
版主说的是,不过还是谢谢楼主分享
wofei1314 回答时间:2017-9-11 11:09:22
Mark....% ]/ n, D0 j+ X2 K( Q  k
$ P& W7 n  G$ g3 e$ A/ k4 s
多谢分享
zlk1214 回答时间:2025-4-8 13:55:18
while (WiFi_GetPacketLength() == 0xfedc);
写错了,应该是
while (WiFi_GetPacketLength() != 0xfedc);
才对。
L

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版