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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE: X( J8 e$ h/ l, D3 p! G5 s
PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。/ i2 M4 H% I! Q: h
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。4 R; F- P. Z9 r9 L8 M
该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。$ w3 g4 M$ n  D7 B5 |$ K
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
; T: d% U2 A% Y7 J$ c8 F3 H+ t4 |: R; V( g
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!
8 `! |* l1 [; U! c% o+ K1 u& K& H
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】
, b$ ?3 Y- T* a0 h! h
  1. #include <stdio.h>
    " B4 s# Z& o9 \, X
  2. #include <stm32f10x.h>
    ( Z3 Q1 m4 f3 Z8 B8 i
  3. #include <string.h>
    1 H, W) _- p1 B( m# j" L% _* R8 y
  4. #include "lwip/init.h" // lwip_init函数所在的头文件
    # i$ {& l3 R2 P/ F0 X
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件
    ) t% ~+ ~" _; c
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件
    , ?' S3 T% s: \' f+ m4 Y7 _8 N  u
  7. #include "WiFi.h"& Z7 x% r& Y! y' }  q

  8. + y, \2 }8 K3 S
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明- @$ W( m. o( r
  10. err_t ethernetif_init(struct netif *netif);2 A) o* I* T# ]
  11. void ethernetif_input(struct netif *netif);
    1 i/ P! b; n, \" P1 w/ S
  12. 4 d9 A4 y: K! l) y" k8 n1 H1 q/ N
  13. // httptest.c中的函数
    ; }' p7 S" N4 O! n
  14. void init_http(void);
    ) ~. I4 N% z6 Y

  15. . S8 d# e; h' T. M' A9 `$ G
  16. // 延时n毫秒& w4 e5 b: [1 r: q
  17. void delay(uint16_t n)- e, l5 F$ J9 f1 Z( V
  18. {- l+ w4 |" G  f# k; B/ u4 U. J3 H
  19.     WiFi_PrepareTimer(n);
    ' O3 ]9 w8 c% v5 [0 c5 W3 d1 p+ K
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕9 l$ R' z; c8 |0 S, u  v% T6 t
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志2 s5 `4 j0 Q' E3 y
  22. }0 B- Q4 O; s# g
  23. 4 t' A* F6 ~% _/ a4 Z3 l
  24. void dump_data(uint8_t *data, uint16_t len)
    / F, I. m* u9 v6 b# V" d
  25. {
    0 F) m) \* Q/ w  e% q( i
  26.     while (len--)& X( }/ j5 A; y0 h/ {
  27.         printf("%02X", *data++);
    : K. c4 i3 |8 p; F: H) ~. X5 U
  28.     printf("\n");
    3 r! T8 E9 @% z
  29. }$ D& T1 d* V+ X' L+ n0 r

  30. / B2 Y7 {9 [9 v2 C% V1 [" r
  31. int fputc(int ch, FILE *fp)
    # u4 O3 H! I, W, ~9 M; b, r5 F: m
  32. {
    : g( G  Q' O9 v  `. l, x/ M
  33.     if (fp == stdout)+ J# Q5 ?6 [& p" Z& g
  34.     {% o# v% J% ?9 l5 C! s
  35.         if (ch == '\n')
    + a" E( B$ D4 m* g: V- ]' }% N) R0 |  ^
  36.         {
    & ]* v# T7 V% y  [
  37.             while ((USART1->SR & USART_SR_TXE) == 0);6 V3 n6 f! F. Y- d) f9 r5 O
  38.             USART1->DR = '\r';
    6 @- f( {% d1 I2 N' Q) `
  39.         }
      I, |2 Q8 ?6 k: F  X: C* v
  40.         while ((USART1->SR & USART_SR_TXE) == 0);) |7 j# f: P4 h* }' I& Y
  41.         USART1->DR = ch;# X) t% ]7 _% \  t  [( F2 U+ Y+ }, n2 Y. O
  42.     }
    , P- ]4 O, d# H% x7 ^! ]. |. N
  43.     return ch;+ P7 e& b) Y- v$ y( |& k
  44. }: w2 N; }+ }8 v; F6 L, J0 Z/ }2 P
  45. 5 m. T$ `. h, d$ _) ^
  46. // RTC时间转化为毫秒数1 ], Q9 X5 D/ K2 P+ k$ s' J
  47. uint32_t sys_now(void)8 `2 f( n2 X- Z' o
  48. {
    9 u3 x! n. d7 G* `! E+ y* C1 w
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒% l" }" p2 w+ l, ^
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒* r# J! r/ H" o2 J( s" J2 D
  51.     return tmp;
    ' V! K4 O# Z# j2 U. [# Q4 i, e+ P
  52. }" D3 A1 y* w) U" H+ c
  53. 9 c2 B0 q  }; T& ?  u
  54. int main(void)( h! z# G: N! d8 J" f, p
  55. {
    * I: L6 w/ y3 g, L. u5 D; P
  56.     struct ip4_addr ipaddr, netmask, gw;
    & G- Q" H% r+ k/ U5 C. P- p" d
  57.     struct netif wifi_88w8686;* X  }! O; q5 F4 z
  58.     uint32_t last_check = 0;# \- h/ I4 L$ g& L
  59.     / H( `5 E9 b0 A
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;
    & N3 x; c2 t. N* b7 K% f& w) F  N. ]
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;1 i+ E! F; c) G
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;
    9 x  r7 X5 Z9 F: ^* v2 k
  63.    
    ) k8 G4 V: D  a3 q, k
  64.     GPIOA->CRH = 0x000004b0;
    , M4 O! r4 d; J0 s* F5 o* h# n+ n
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块
    ; O3 ?) C  u- Q: }* I, I
  66.     GPIOC->CRH = 0x000bbbbb;
    7 a1 N7 V5 Z% @; l- R
  67.     GPIOD->CRL = 0x00000b00;
    ( u: Z+ E, N" s3 b% r3 H
  68.    
    / k# H; \1 g9 M0 ]+ W4 }
  69.     USART1->BRR = 0x271; // 波特率: 115200
    & i0 ~! G2 N# l2 B! {
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    ' F' a$ F3 h8 q
  71.    
      G% J3 I2 P/ s1 U$ Z* {
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器1 q% q' ?  h1 J" D+ r, b( H# C
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)  p9 V# h" m4 `; g+ J! V
  74.     {
    * T9 U' R8 Q) I
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI
    $ m) M0 e2 f8 E
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);: F/ y8 [3 N8 P' U' G- G
  77.         //printf("LSI Ready!\n");. V. a: c  a$ A
  78.     }' [0 \' _4 n4 Q( {5 A1 V) ~
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)# E) Z. V3 l6 h# A* f1 `/ Y) E* U% I
  80.     {- g; V. ~% Q  M& `/ x9 g* Q
  81.         // 若RTC还没有打开, 则初始化RTC
    4 n) a2 b+ ?$ a$ H2 f
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时# _9 U- j$ A" t; _
  83.         
    2 w, a4 C7 [0 v* a7 ?+ Q5 ?1 R
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式, w6 ~1 J; j# x, F% E0 O
  85.         RTC->PRLH = 0;
    ) E: ^% w, R, @% x. a
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
    ! t5 R" }; A4 A  l/ M2 j/ k0 }% T
  87.         //RTC->CNTH = 0;
    : b7 O& a  q# f
  88.         //RTC->CNTL = 50; // 初始时间* w/ ~1 J2 m% {* T* M' D5 R
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置
    - H" s* Z& `3 T" m; l
  90.         
    ! H0 O  l0 N+ ?+ s1 F( o/ |" d
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
    6 x% F& ~: x" X( U% \! `
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效
    6 L! K. u: m- `, _
  93.         // RTC从此处开始走时) b- t; \/ o9 s
  94.     }
    " R+ Y* D+ n9 c" R1 H$ ^
  95.     0 o! ]% O: K7 Z: ]5 k
  96.     WiFi_Init();$ L# L/ ?  M# C/ k
  97.     WiFi_Scan();
    $ t5 e0 |" J! L) T* V+ p% b
  98.     ' V( x3 M, F4 G9 }# @3 X1 s
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点( f0 u7 v9 n+ M, T, ?8 }
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    1 I! Z9 o. _: k6 F
  101.     2 e$ S* {* f( Y
  102.     lwip_init();
    3 ~1 A1 O' [& c" O2 ^
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址; Y" i# ]& z2 O  b+ u
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码5 n6 Z. d2 D. u5 `7 z
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关" u' a) y% L. Q+ b/ p  i& q
  106.     + M1 q) ?) E' z! O
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    ' P) F7 C* p; o2 I' z( H* U
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡
    , }' k, |/ e% W# P, t
  109.     netif_set_up(&wifi_88w8686);
    7 m: L% I8 ~: K. m8 ~4 T' L
  110.    
    - {. ~* G& G. T7 k0 w
  111.     init_http();8 q7 _4 w, D. G' N' f' J. N2 E7 U
  112.    
    ( `. i+ b& L- w* J6 i
  113.     while (1); Y$ s- H7 t5 N0 g  d8 }1 F
  114.     {
    % T* }7 p4 s7 a$ V
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())% k1 G+ D* ^9 {8 ^: P
  116.             ethernetif_input(&wifi_88w8686);
    / I1 W! ^+ R* i7 `
  117.         & z6 g$ t" x: l% j
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)( T2 I% a8 N7 U- p
  119.         if (sys_now() - last_check > 200); _' \& V; P* i$ ^# l! [/ V' i
  120.         {- F+ ^* A6 v" z8 @; e2 F0 w
  121.             last_check = sys_now();
    4 G3 F6 E! f6 j2 o
  122.             //printf("Time: %d\n", last_check);
    + O. D# B: J( F7 K, p
  123.             sys_check_timeouts();$ v3 e* Z3 _$ ?. d* T/ c
  124.         }
    $ }6 x6 `) o! h
  125.     }
    " {1 H3 I. b, Q, I0 G
  126. }
复制代码
【httptest.c】! u9 [$ i) e* h1 a6 J
  1. #include <string.h>
    6 Y4 d3 i6 e3 e- J- o9 r
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件
    5 s; F! w! |/ W- R! J1 s
  3. 3 W5 }) ]; U. b; u/ i
  4. #define STR_AND_SIZE(str) (str), strlen(str)- X) u! Q; Z4 u3 n( V' g5 g" {
  5. " Q( E4 g/ z6 d" z) i8 J; j
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)& q& t; Y& {2 g( ^; n, J
  7. {( [* c, s& ]& D; P2 r
  8.         char len[10]; // 存放HTML内容的长度* c% w9 S2 {5 ~( |
  9.         char str[200]; // 存放HTML内容/ E% `. Q6 ~0 W) |
  10.         
      j2 ~; ~5 X- f) e" p- M' d
  11.         char name[100];5 f  p' K1 `$ F# h
  12.         char *pstr;
    * y1 n. x$ r1 p' `& o4 N+ s9 c
  13.         uint8_t i = 0;
    ! k/ a- z3 [* Z9 ?' {* F: w
  14.         if (p != NULL)6 E2 ~- b& l: l+ E; }% c
  15.         {
    # r2 S+ N6 C: F4 g
  16.                 // 提取页面名称' _% B: j+ |( `1 {2 J. @
  17.                 pstr = (char *)p->payload;/ ~; g2 n' j# }* H1 Q3 q$ ~
  18.                 while (*pstr++ != ' ');' D' a( I, }. u! g
  19.                 while (*pstr != ' ')/ {, O) `+ v! w
  20.                         name[i++] = *pstr++;
    0 H6 D* t% X, T) F) T+ A( i
  21.                 name[i] = '\0'; // 不要忘了结束name字符串" u7 G/ r; F: e3 d2 q6 f/ V" Q: j
  22.                 tcp_recved(tpcb, p->tot_len);) e; j) ~/ S/ d: G
  23.                 ' J' Q# d/ U5 d9 v- y
  24.                 // 生成HTML内容6 [% o" i5 D% {  \  D2 s
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
    5 x) I& b. _* N, w7 v/ i8 ?4 O
  26.                 & Y% C7 {5 E* v4 ]: E1 n
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度) M) z% Z0 P& x; j4 m1 V8 z
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
    # `. S' j9 a( O  Q* |5 u
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
    . l0 j* e6 N' }4 K/ J- {
  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);
    . b, g: m7 j" U  l4 X
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容# X7 D) N6 Q0 X; g' J1 X, Z9 W
  32.                 pbuf_free(p);
    " z  I* O3 {- ?
  33.         }
    ) ]2 b2 i2 ~: s6 {' ]: Z
  34.         return ERR_OK;
    0 A/ h) L0 G  [" n" w! f
  35. }0 F4 u+ R* S$ K6 `! y

  36. * N/ {: t* C& p8 k0 z$ O7 T3 L
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    3 q1 n, h& Y" F6 G! S) G0 s% o
  38. {- t1 t' ^8 Q+ s3 s/ ]1 i& I- L: j
  39.         tcp_recv(newpcb, http_recv);) x$ o& U: C6 [/ n0 d) P
  40.         return ERR_OK;$ k1 a, q3 g( M1 m3 f5 U( ^/ w
  41. }
    - l3 H& I2 W! U; |1 ]
  42. 3 H' Q( N% [% ~( k; G7 t0 O' x
  43. void init_http(void)& G5 W7 q4 h6 E5 C1 {
  44. {7 `) P2 Q# V6 A* u5 m
  45.         struct tcp_pcb *tpcb = tcp_new();* L, d6 \5 l( z: p7 ~9 d  m
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);- r; F; F7 q5 V, v
  47.         tpcb = tcp_listen(tpcb);
    . h7 |  L! ~" v# J; L
  48.         tcp_accept(tpcb, http_accept);
    8 K( {% y/ w1 M! K  c) A5 |$ c) _
  49. }
复制代码
【WiFi.h】2 t6 [2 u7 f& _- a- D
  1. #define _BV(n) (1u << (n))+ M. D/ f" x9 j' {. X- Z0 X
  2. : `3 s) U$ e9 k, x9 o# o/ F5 R
  3. #define CMD52_WRITE _BV(31)
    7 U2 V! X" n# E' i! a
  4. #define CMD52_READAFTERWRITE _BV(27)
    0 C# q9 s  T( {

  5. ) z# r; ^8 K' U7 W; ^
  6. #define CMD53_WRITE _BV(31)% K( @4 k1 C* P# y( h
  7. #define CMD53_BLOCKMODE _BV(27)& d" @+ z5 m$ r6 V& ]
  8. #define CMD53_INCREMENTING _BV(26)) W8 b; [% O$ X, q( y

  9. 1 ]: c# m9 P2 r. s( w" j+ }9 s) E# i1 {
  10. // 16.5 SDIO Card Metaformat
    5 B" A+ h/ w+ J5 w7 q
  11. #define CISTPL_NULL 0x00 // Null tuple( n7 a/ D& }! t  j; u; Q6 q
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information9 T1 c5 a- o6 A$ p- v2 |; Y
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple' m1 r4 |( M( s. ^
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple
    - Z& U7 P5 N" \' \- `
  15. #define CISTPL_FUNCE 0x22 // Function Extensions
    , M8 P5 S) y" g2 I  F
  16. #define CISTPL_END 0xff // The End-of-chain Tuple3 J0 @8 p. M2 v2 \$ h) y4 m+ M

  17. ( Y/ ?& A4 x& H# g  ~* j- m8 E
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)1 |- \+ F6 J+ t( U- ^6 y/ o9 ?6 c

  19. : D5 j% n  I2 l  b; a$ p2 {
  20. #define WIFI_SQREADBASEADDR0 0x10
    + k( H) J" h$ Z3 S* V; ?; p7 w
  21. #define WIFI_SQREADBASEADDR1 0x11
    + _1 A) f; P" J- A' e( Q
  22. #define WIFI_SQREADBASEADDR2 0x12
    + n4 P& {9 A" i, @
  23. #define WIFI_SQREADBASEADDR3 0x13
    ! u! S- o6 H% \: G8 j& b

  24.   r7 H8 ^+ B4 d( t
  25. #define WIFI_CARDSTATUS 0x20 // Card Status
    0 v% b* j0 ?) D/ `. H( M
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator# J" F. a& N8 i
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    ! o8 I+ K) _8 E$ K+ i
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready7 f# M% V! F0 i4 j/ E% l8 z
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
      p6 t* V/ _# _1 [% _

  30. 2 @. T3 d3 }6 }- {1 R# K/ G
  31. #define WIFI_CAPABILITY_BSS _BV(0)2 v* X* U# x( a
  32. #define WIFI_CAPABILITY_IBSS _BV(1)% M5 T) b' t' O! c/ D. B
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)- F9 W0 h# S' Y" Y) S5 y: a6 y! \
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3); r! J2 ?+ a  l# }% W% O
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)$ j! N3 u% m+ Z, j% r
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)
    8 j8 Q& Z( A3 X# B; L" {& s# m- ?# J
  37. #define WIFI_CAPABILITY_PBCC _BV(6)
    9 l9 ]6 P4 _  b$ N; G, N
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)
    4 A4 k2 C7 u" P" G0 y$ W
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)5 n2 v: f- p& @! w' x" J6 Y! o' z
  40. #define WIFI_CAPABILITY_QOS _BV(9)
    2 e- }& k+ M: M6 U/ O- x" O( x
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)
    ; L2 z: `- E6 `4 X& X: O/ j# _9 l6 b, W
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)
    + G7 E: X* Q/ H% |( I
  43. * @$ |) X$ D% P" B3 c
  44. #define WIFI_SDIOFRAME_DATA 0x00+ q, D/ s! P7 e7 Z
  45. #define WIFI_SDIOFRAME_COMMAND 0x01
    ) }% T, T/ H! {. O( `  `
  46. #define WIFI_SDIOFRAME_EVENT 0x03& h2 u# w) b- q& u
  47. 9 D: e3 h5 c! {- m$ ~7 g/ U- i
  48. /* Command List */
    & e1 O* ?) n7 }) @% v  ~
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process" e' i9 W6 F. p# N
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP' T  f1 ~% N" e1 m% s  [* e
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
    - r2 H/ h% s  C3 L+ ^
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network! I& R( \+ Y0 V8 J1 m% l6 u, y* e
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address: S8 J+ ^- Y1 n8 m8 B* A0 d
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption
    , C, ~$ J8 {$ N8 R5 b4 }# H  A
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration# Z7 S9 c- o1 L% n
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results% l: A- g9 M7 h

  57. & r# }. n* W8 u& m
  58. /* Command Result Codes */
    3 {7 _1 \7 F0 Q* e- Y1 r4 P
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error6 m( K& q* m3 W# V) l
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed6 m5 u# R0 T7 G2 d
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported
    , Z0 M! U$ n: _$ q- l7 K1 D1 R

  62. ' U; Z* A3 S  z% ~/ Z& C. u
  63. #define WIFI_ACT_GET 05 R6 b4 z' Q) C( e/ F9 |" V
  64. #define WIFI_ACT_SET 1
    : [- e; w# p+ d, ^
  65. # f; Q" s: ~; o) ]/ c' U  E
  66. /* Authentication Type to be used to authenticate with AP */+ V/ Z  o5 R9 [9 e5 b6 I- M
  67. #define AUTH_MODE_OPEN 0x00! l' G! s  `0 m. B9 d! A
  68. #define AUTH_MODE_SHARED 0x01
    * ^0 H' d: M- {& d, V% c5 f; D
  69. #define AUTH_MODE_NETWORK_EAP 0x80! _* E$ D6 M0 S

  70. ! B: m* Z# _# A1 ]3 q8 c. J
  71. /* WiFi_Associate return value */
    . H0 {0 s' e( l3 R& y0 S5 @
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe
    ; q0 t# P; X, l) Z1 f9 |* p
  73. #define WIFI_ASSOCIATION_ERROR 0xffff
    / I( E" ~1 _6 @7 @' [5 {
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功# @4 y1 |8 y; G* |& W: O
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101
    6 `- ]2 L+ I2 y9 Z
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧
    $ T. n8 u8 ?* h1 x  R- H/ t
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213
    8 V2 b, o6 J4 b5 h0 i1 M
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214; f6 |8 J* m4 C' B  g0 d
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败7 I# V1 H( o$ B5 S: j( [  c# j/ v
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时
    $ ^* C" L8 K! z" T+ X1 g/ e( L
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时! S2 j: \9 j% i7 J0 h; G
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时7 G' `, I1 K: [0 S0 ~
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时/ O8 n5 H! s7 ]4 r  S, C

  84. ( j2 I1 X# W$ r& D$ I
  85. #define WIFI_KEYTYPE_WEP 0
    9 }* t; k* g: S2 u1 ~2 D
  86. #define WIFI_KEYTYPE_TKIP 1: W  F, \; E/ R3 G0 t
  87. #define WIFI_KEYTYPE_AES 2  Z! W9 ~" w. z; x; z; E# }7 m

  88. + g# F. ^* J5 E, z* ~: G/ M( H5 H
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)
      y) I& M- `& Y+ O3 r( C5 w! Z
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)3 y8 {# @" p2 S. @" _
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)
    ; P- [$ K3 e1 {. t
  92. 5 m0 u4 {; I) `9 U' s% A
  93. #define WIFI_MACCTRL_RX _BV(0)
    , ]6 s' a9 y* F7 t; _* w+ b& g
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
    . H, X" m0 m* S3 Y! H6 \
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)- ]+ a6 W5 q; T/ W2 G
  96. #define WIFI_MACCTRL_WEP _BV(3)
    ) p, D  P8 f% G8 z
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)
    + U& J2 G+ c" u4 |( }( @
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)
    # C/ B" L+ g; l5 Y3 D* c( \
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)
      |" j- v3 g+ u
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection' O8 N6 {0 S% m1 K* I5 _
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode
    0 a, v( Z% R4 P0 n( W

  102. / i9 a  S# f  i5 e7 m# I# g
  103. /* BSS type */4 B" p) `) g- R4 a
  104. #define BSS_INFRASTRUCTURE 0x01
    * @! j( `: M: B: y  A% \
  105. #define BSS_INDEPENDENT 0x02  j! w! V, f" d8 P+ ]2 ?
  106. #define BSS_ANY 0x03
    : p. l# j# H/ V( N! w0 f8 N
  107. 8 B& S1 E' |/ n& A0 `1 O. I! Q
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */
    ; V. r% \2 c7 h1 p& a
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */* K* Q  {3 ?( b3 ?% A+ ?* e$ T
  110. #define MRVLIETYPES_SSIDPARAMSET 0x0000
    : C5 n' d2 p1 {2 Q  o! t
  111. #define MRVLIETYPES_RATESPARAMSET 0x00018 ~5 i/ @4 B' t7 S: g8 H& w
  112. #define MRVLIETYPES_DSPARAMSET 0x0003
      U, u5 F; o$ }2 n1 N/ \
  113. #define MRVLIETYPES_CFPARAMSET 0x0004
    ; K, @1 n5 M  m  |. d" b2 O5 ?
  114. #define MRVLIETYPES_IBSSPARAMSET 0x0006
    % L$ L, H& v( u& Y
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030
    - ?  C5 a9 j; Q+ K" j
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd
    ! N! _6 `5 L: E& L! d

  117. # Q7 e2 n- v/ L! t" W2 z2 u& |
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100
    : O% K0 N& g$ y7 }( J
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101
    2 E- x0 l0 }! l% A0 [
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x0113# k3 b  N  c& Z* x2 J
  121. #define MRVLIETYPES_AUTHTYPE 0x011f  q6 t( _+ c* K1 f7 v
  122. 0 F6 T  c: \$ x% Q
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小
    2 N% q- o. C( d
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小
    & C/ b* r# [. t$ i, v

  125.   `% x+ S5 g2 S3 e/ b/ e; m% h
  126. typedef __packed struct
    # Y; c" m2 b1 h. w' ~9 V) J4 {
  127. {1 W% T9 X0 i* z( R
  128.         uint8_t type;
    + C0 b9 X8 T7 T: D, n
  129.         uint8_t length;
    5 b9 L  h2 F3 R! i: n/ @0 e- f% B
  130.         uint8_t data[1];
    - A8 ], L" r" \& m; [7 F( z
  131. } IEEEType;
    5 D- t. u8 W7 |
  132. . D5 v; g. W2 A* S6 D# v
  133. typedef __packed struct
    9 J8 m# a) p7 q% W1 f* w+ u
  134. {
    $ N3 P, u- e' p$ ~8 O5 ]
  135.         uint16_t ie_length; // Total information element length
    ' S% q+ M3 b: B2 \. d
  136.         uint8_t bssid[6]; // BSSID+ M3 L7 F: P% h% x
  137.         uint8_t rssi; // RSSI value as received from peer
    0 z, f, A' l# P5 l1 Y/ E/ `, s
  138.         % F' O" ^! L( K; x8 G
  139.         /* Probe Response/Beacon Payload */
    ( r# H8 \# |! G# R
  140.         uint64_t pkt_time_stamp; // Timestamp
    6 f0 w: H9 K+ t1 F! \
  141.         uint16_t bcn_interval; // Beacon interval
    ) E' U1 o/ o9 n; ]- j, f
  142.         uint16_t cap_info; // Capabilities information7 I$ H( V) z$ ]2 Y- }7 G- R
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据( D( {+ X! C3 o7 W+ ]: j) q
  144. } WiFi_BssDescSet;
    + E" G( B; e# c, A
  145. + d& N4 X- n0 r% B( L4 z* e( U; F9 P
  146. typedef __packed struct
    2 I$ L+ l7 ~+ g3 {* i' l* @3 u
  147. {5 V0 |  J& q( z
  148.         uint8_t oui[3];
    % V. R4 v3 N4 p9 V
  149.         uint8_t oui_type;
    0 j1 F: u7 y; }& O6 F1 H
  150.         uint8_t oui_subtype;
    / ]# Z, W, o0 a( O" \. w
  151.         uint8_t version;5 l* u8 [& _; [+ t3 X, l3 ~
  152. } WiFi_VendorHeader;
    $ L* Z. j, h2 D( D  e
  153. * y9 V% p! c& s# ]
  154. typedef __packed struct2 n  `* S- d* f$ \# H
  155. {- y7 C. I# y/ ^! q; K3 y& Q
  156.         uint16_t type;
    6 I6 |7 m$ d! I+ t1 @, b( [6 N& ?
  157.         uint16_t length;3 L5 G7 d; |9 g0 h5 p5 F
  158. } MrvlIEHeader;, l: ]5 |! }2 l% N1 r: c6 I5 K

  159. ' p) F1 o/ j# Y
  160. typedef __packed struct
    9 K4 ~9 l$ B, R& }* t6 G/ f
  161. {7 m, f7 N+ U( p- |2 R$ E: r
  162.         MrvlIEHeader header;9 t' g& K  @4 M* H" t6 e* U
  163.         uint16_t auth_type;
    % w4 N' H; \; G6 T' W: K
  164. } MrvlIETypes_AuthType_t;
    : Q3 a! z" k4 [$ O9 A$ H7 Q
  165. 3 X! \; n2 W" H0 z( D4 y
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec
    $ m7 `/ x+ o: M0 X) r$ V

  167. ' i% C9 L& \4 ?+ ^/ g1 r  C5 [) U' C* R
  168. typedef __packed struct
    : o4 r5 m% j% r+ _1 x
  169. {& F' w6 u3 O1 H
  170.         MrvlIEHeader header;
    + Y. v0 B% Y3 ^. R( P
  171.         uint8_t count;
    9 u+ x& c4 Y' K! L$ _
  172.         uint8_t period;5 o1 ~% U4 \# t' r7 f
  173.         uint16_t max_duration;1 b2 D( C, t# z
  174.         uint16_t duration_remaining;
    ' [: f* b7 u1 B& I7 J  k$ h  z4 p
  175. } MrvlIETypes_CfParamSet_t;# Z- c, E: s8 B* e& L# n

  176. ' f, h# ^3 m# S  O% G- u  r1 q. Z8 S  B
  177. /*typedef __packed struct
    5 `1 b; W: M( C$ x8 o; Z3 ?; s3 w
  178. {
      n6 l0 D7 z' w6 u2 L
  179.         MrvlIEHeader header;
    9 c! }2 Y  L5 `3 Q- t
  180.         __packed struct
    . q& D* U8 y( V1 W& d
  181.         {) e& }: N+ m3 _! m  O- f- x
  182.                 uint8_t band_config_type;
    ! M6 ~: l! m$ h. s
  183.                 uint8_t chan_number;
    " g3 D# K. C/ q( {5 h# b' a
  184.         } channels[1];$ h' C) s$ k$ B$ O" `) \( g
  185. } MrvlIETypes_ChanBandList_t;*/
    # u0 K" N0 B% e( Q. r: O, M- q

  186. 8 J4 G9 O* Q+ d6 b) O2 O1 N
  187. typedef __packed struct6 X8 p- t& w- J4 V8 V
  188. {
    3 p! J% p2 i! k+ L# n
  189.         MrvlIEHeader header;- u) D* l' }) g
  190.         __packed struct
    3 X5 K" L! A# g
  191.         {1 r: r+ c& X1 ~5 D
  192.                 uint8_t band_config_type;, x+ l. g! |8 A
  193.                 uint8_t chan_number;
    * s' J+ m7 h* c1 U1 N7 U* k& s
  194.                 uint8_t scan_type;
    1 v7 I0 M+ M7 R* m3 T
  195.                 uint16_t min_scan_time;4 P4 e) R  J/ K
  196.                 uint16_t max_scan_time;, ~7 X! D3 O1 W- W  z# f8 b
  197.         } channels[1];
    ( @: n0 G+ f9 j2 J4 C* Z
  198. } MrvlIETypes_ChanListParamSet_t;, j5 P4 b" z7 V' d- L
  199. , `7 t# n- `2 v5 {' U) ]8 T2 ~
  200. typedef __packed struct
    * Z+ @- c5 I3 s) {9 @& b2 p' F# f
  201. {3 P2 Z1 y1 r0 t6 d) m8 d. e
  202.         MrvlIEHeader header;( u1 \) a6 K2 V0 }2 P$ f
  203.         uint8_t channel;% X8 B0 e( L& {+ N7 `5 j8 a& l9 n+ P
  204. } MrvlIETypes_DsParamSet_t;- n5 E# R8 {1 N7 \& x+ N; {

  205. 1 [$ y5 {* ^& P
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
    , p$ s# j! i4 R( o% A

  207. ( ^* l! E' q1 n5 h
  208. typedef __packed struct
    - ?4 q( z0 [3 I1 b5 ?
  209. {
    5 U, Q; E# R. o' ^! @+ K
  210.         MrvlIEHeader header;5 W$ N1 ^9 f' L
  211.         uint16_t atim_window;
    1 U# q' A3 u! q: f1 L# f+ s
  212. } MrvlIETypes_IbssParamSet_t;
    * I6 p, A3 u" h+ R* @8 i2 [
  213. ) B. Y9 D8 x  W+ D
  214. typedef __packed struct4 w" t$ j, b5 H: Q- c# v
  215. {7 J3 V; x( M9 H: h2 Y
  216.         MrvlIEHeader header;4 K1 t4 o6 T5 V/ }
  217.         uint16_t key_type_id;9 w7 C0 c, }0 C( N# B) U! j2 d6 d
  218.         uint16_t key_info;5 }8 h" [! b5 ]8 [8 t; _5 C
  219.         uint16_t key_len;* h$ [6 L, T- G; p( c  q  D, [
  220.         uint8_t key[32];
    " a" I4 n* `3 _
  221. } MrvlIETypes_KeyParamSet_t;. l# y$ X1 q: }; L( ]+ k
  222. % `! |/ @1 E# O' `: @0 `! v& q
  223. typedef __packed struct0 f. A* f$ e$ f7 E( |
  224. {) W8 t& M; B5 i; }2 K( ]
  225.         MrvlIEHeader header;9 |; t9 [1 J! s# d2 F  o
  226.         uint8_t rates[14];2 P) }  @, f% S. f
  227. } MrvlIETypes_RatesParamSet_t;
    8 C  z4 ]# k# _8 r

  228. : ^1 |1 t7 V4 H
  229. typedef __packed struct) P$ h+ ]  V! y% m3 n' \
  230. {
      Q; V4 g  {  u' l  `
  231.         MrvlIEHeader header;
    3 B1 ?5 L, j. L8 y. j, X
  232.         uint8_t rsn[64];
    / C- q3 V* n  w( W
  233. } MrvlIETypes_RsnParamSet_t;
    3 U5 K. g* m" ^9 w0 j& ~
  234. ! E" G5 u2 x. _* c* G; p
  235. typedef __packed struct1 N2 Y8 Z- ?/ V& G7 T# F
  236. {9 q: u6 o  _# x0 [( S, F
  237.         MrvlIEHeader header;2 ]: V3 H3 f/ A/ a* m8 l0 _
  238.         uint8_t ssid[32];8 K, X4 z8 v! H, p
  239. } MrvlIETypes_SSIDParamSet_t;9 B( x' j  d; U9 M: O$ E2 \' K8 O

  240. 4 ?# L8 A: x" B. ^
  241. typedef __packed struct
    1 O4 c, k4 N" b+ C$ ?5 I
  242. {
    & X2 j0 \* D, @, \7 A5 K
  243.         MrvlIEHeader header;* z$ t# r8 T1 `0 u* `' P( R& j" k
  244.         uint64_t tsf_table[1];
    - a% a# \. ^* h7 g' M6 x
  245. } MrvlIETypes_TsfTimestamp_t;4 I$ Q( k  J0 L, h7 v9 h8 K

  246. 4 g  _- m' l8 o* ~, y* G. u
  247. // 整个结构体的最大大小为256字节( T+ Z1 B: G6 h, Q% p" p0 m
  248. typedef __packed struct
    : p+ e" x, m! @
  249. {( B1 C; L+ i8 o  P+ J. d6 M
  250.         MrvlIEHeader header;4 \' Q% U% q# l0 r+ e) H
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够* B5 L, f; m& K* L" g7 ]
  252. } MrvlIETypes_VendorParamSet_t;* f# `2 j$ X% @- l/ L' W0 h
  253. & o$ y+ d6 T5 G% P; F1 |! Q. s7 O
  254. typedef __packed struct
    / O4 j- n- w# s
  255. {' E7 k; L3 N* e) m
  256.         uint16_t length;8 Z$ p! f6 w" K  [9 `
  257.         uint16_t type;1 f' Y2 I9 N5 P" k# X8 n  h
  258. } WiFi_SDIOFrameHeader;* b* [  G8 a( o
  259. 4 Q/ T7 L2 R4 G0 l* z! {+ n* @
  260. typedef __packed struct
    ( l4 W3 X' t: x- U
  261. {. K$ S2 K1 {. |. r& o" t
  262.         WiFi_SDIOFrameHeader frame_header; . J, w* w# M& Z7 c, Q. l
  263.         uint16_t cmd_code;
      E( m; [( N: z: s* G* `8 j( i
  264.         uint16_t size;
    " d3 Y: a- Z& [5 b, s
  265.         uint16_t seq_num;
    : Q2 y* Y1 x5 w; H" |
  266.         uint16_t result;
    8 Y6 n! b- }) E* _% d
  267. } WiFi_CommandHeader;
    4 e  o9 J! b5 E& h$ K: W( j. p! n

  268. 2 K  |4 c2 y; J
  269. /* Table 2: Fields in Receive Packet Descriptor */, v5 R/ p) H/ y* T: P$ ~
  270. typedef __packed struct7 u: T$ s  q" a9 F& H7 p7 |8 d
  271. {: {  c2 Z- J, k/ s
  272.         WiFi_SDIOFrameHeader header;! D& N8 _4 E0 k0 Q
  273.         uint16_t reserved1;
    - @( D9 F" }( Y! _
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)9 X2 V0 i' A" @: M3 t' ?7 A' b
  275.         uint8_t reserved2;" {8 K( {/ u) F
  276.         uint16_t rx_packet_length; // Number of bytes in the payload
    & r, [, c  t5 ~. {
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.* M% K4 \  h% |  Y. i- M4 [
  278.         uint8_t rx_rate; // Rate at which this packet is received3 ^3 h" c% Q1 O% {5 {/ p
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet( A! }9 _% E$ w$ T  y
  280.         uint32_t reserved3;
    $ @- @. U# j& M, H% m
  281.         uint8_t priority; // Specifies the user priority of received packet1 q8 R) \; g; k" Q. x+ t! @
  282.         uint8_t reserved4[3];
    + j' [& N' `/ N& z; B
  283.         uint8_t payload[1]; // 数据链路层上的帧
    " a0 x* Q' `- {, k# n" {( `9 G
  284. } WiFi_DataRx;
    + F, Z) F  e+ P( \( C

  285. 3 `9 |# q4 i5 f  Z6 j$ t: n
  286. /* Table 3: Fields in Transmit Packet Descriptor */
    # N- c7 A/ {2 _5 B
  287. typedef __packed struct
    6 R  u& K* A- ]- }7 Y/ K
  288. {
    2 D& H4 G& V) _  g
  289.         WiFi_SDIOFrameHeader header;
    9 n5 x+ L4 h. m# [" {  |* Z: K
  290.         uint32_t reserved1;
    - ^& [; q4 q' x) t4 W
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings  f  \! v2 X: {% z% G
  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)7 p- c2 q4 R( s
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame" p) e1 M% Q8 M0 }
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5) L9 Z0 f9 l! S" @! ?+ B
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3
    / R5 ^% ?' ]. ]3 g
  296.         uint8_t priority; // Specifies the user priority of transmit packet; S" h& o7 ^, O, U$ j8 u- u+ u" u' Y
  297.         uint8_t flags;" R+ y8 U' j1 \
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations  d4 T! |. O2 |- V" u7 v/ D
  299.         uint8_t reserved2;
    9 \7 f" G+ r! M2 b  _
  300.         uint8_t payload[1]; // 数据链路层上的帧+ _7 s* f/ ^9 U$ q. J# P2 d  B
  301. } WiFi_DataTx;+ O. L3 |5 e# F# G, }; G0 q1 C4 V: Z) V

  302. $ B5 s: }0 N7 I0 k' w
  303. typedef __packed struct
    / }8 t% r( e; f- g, E
  304. {1 ]. z$ p: r1 O+ S% W  d- \8 u# a
  305.         WiFi_CommandHeader header;9 \# f! S! x1 g) q, [, ]8 L4 P
  306.         uint16_t action;- E+ B& D* H; }% a3 R
  307. } WiFi_Cmd_KeyMaterial;
    9 V- o" y1 h5 N
  308. ) _* x3 Z# i7 j+ P+ B9 z
  309. typedef __packed struct
    0 c5 M/ ~. G% h# @$ Z
  310. {
    9 E7 n+ @2 f+ G& q; _1 b+ y
  311.         WiFi_CommandHeader header;3 \  i, G7 L0 w5 x
  312.         uint16_t action;* X1 F7 H; `, q) }1 m2 Q2 f
  313.         uint8_t mac_addr[6];8 f5 ~7 v3 x6 @( l3 r- T
  314. } WiFi_Cmd_MACAddr;
    1 |$ e1 m" N4 f2 F2 o8 \/ z
  315. 5 W5 o7 x2 h" p9 ]. u* U
  316. typedef __packed struct
    " p& ]' Q' @! r- m, U0 E
  317. {
    # ^( I( T) w, l2 J! ?2 U( P3 t0 N
  318.         WiFi_CommandHeader header;
    " |& x6 k* s, B: P
  319.         uint16_t action;; d2 o0 h5 W; s( y5 h
  320.         uint16_t reserved;* N9 r) ?% @4 v) i; y1 c
  321. } WiFi_Cmd_MACCtrl;. R; w* L! R# {$ D' X6 X

  322. 0 Z; L0 o5 }6 Q0 {1 C
  323. typedef __packed struct
    9 }! V  |! X5 w9 b0 g
  324. {
    - f, ^) ]6 Y, i; l
  325.         WiFi_CommandHeader header;
    3 k7 H9 P* i  F: `. P( ^0 y
  326.         uint8_t ssid[32];( w" F0 E7 H9 B) J. l
  327.         uint8_t bss_type;
    2 t- Z( ?2 g. K* a9 {- [2 w# S
  328.         uint16_t bcn_period;2 D' f5 M- b4 _) ?2 F5 l
  329.         uint8_t reserved1;6 `% j8 k  X$ T+ G- c4 b
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
    9 X8 ~5 U, K8 V9 p
  331.         uint32_t reserved2;  c& v& l( I( _5 q1 F
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network0 c8 m7 p8 A% t' Y" R7 ^
  333.         uint16_t reserved3[3];7 ?: b+ F7 _$ P# f7 s
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information+ u' R7 b! W8 e: ^2 I# _: [* e8 ^
  335.         uint8_t data_rate[14];9 a9 Z- B4 j* t& |6 Y
  336. } WiFi_CmdRequest_ADHOCStart;" Q8 T% n1 ?3 r5 @: N

  337. ( u/ a7 @% l* n( C9 M+ a
  338. typedef __packed struct
    * b  @$ m' v9 X) U. y; @2 }
  339. {
    , C+ o3 o! f, t8 u$ ^
  340.         WiFi_CommandHeader header;
    $ {' B- l' B3 v; ?! f' t5 O
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address( M' w' P- m8 Z! F+ A; G
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information
    6 a$ e, E6 M+ F1 R7 O
  343.         uint16_t listen_interval; // Listen interval
    2 [8 [. B2 X6 x# H) O
  344.         uint16_t bcn_period; // Beacon period/ Q/ j0 r; G4 ~* U" u& R5 Y5 ?
  345.         uint8_t dtim_period; // DTIM period# E/ ^% h1 z/ x% Q' e+ T' X# B
  346. } WiFi_CmdRequest_Associate;2 r" K3 q5 }7 y  t+ Q5 `

  347. + H- K/ v$ k+ ?0 b0 V: O
  348. typedef __packed struct. o/ H: J8 x9 u! o$ ^
  349. {
    ; K$ K& P# a/ V, V) k" ~
  350.         WiFi_CommandHeader header;
    " @2 a4 z+ q) Z2 S; e  U7 _
  351.         uint8_t bss_type;
    $ w+ J1 b4 k$ I
  352.         uint8_t bss_id[6];
    ) a$ k# `1 J. e5 L' D! h
  353. } WiFi_CmdRequest_Scan;
    + Y; c& n, P# c' Z/ q2 q3 Y
  354. : |  D9 {! K. V4 l5 U
  355. typedef __packed struct1 k1 M+ r- ]" [9 Z5 |5 [
  356. {! q2 [9 g; S+ d4 G
  357.         WiFi_CommandHeader header;
    0 l( V8 [7 ]" }
  358.         uint16_t capability;( H( O' f# W, l/ I  u8 [8 W
  359.         uint16_t status_code;+ Z6 H. U0 t% b' Y  ~
  360.         uint16_t association_id;
    ' v* S2 J9 j4 x$ N
  361.         IEEEType ie_buffer;
      N) ?& g+ H# `1 `2 @
  362. } WiFi_CmdResponse_Associate;, E# L/ [; c7 [& ?1 ?, k' H% E
  363. ' S9 \0 a- a# }
  364. typedef __packed struct
    % w9 K' G2 A% A8 q4 Z# g( F' \
  365. {
    8 T* z" L5 I. Z; I" {) n9 _
  366.         WiFi_CommandHeader header;
    6 A7 n4 K' c& P& [' A4 ]
  367.         uint16_t buf_size;
      A  Z7 Q0 X% O
  368.         uint8_t num_of_set;
    ' F. z- _, R! |' v# l( K% |
  369. } WiFi_CmdResponse_Scan;/ X) }3 C% n6 p' D0 ?3 ?6 A* }
  370. ) P& C5 c! f. _( s/ L6 n
  371. typedef __packed struct
    % z3 ]( s# f$ D( f
  372. {. y) |  z/ M( X
  373.         MrvlIETypes_SSIDParamSet_t ssid;
    " Y" I; w4 G! ^8 Y2 k
  374.         uint8_t mac_addr[6];" o  ]8 j  n/ [( }0 t# T
  375.         MrvlIETypes_CapInfo_t cap_info;
    4 _- s& y/ p' }6 w5 @2 A
  376.         uint16_t bcn_period;1 g+ |& ~$ h& x
  377.         uint8_t channel;
    * f' m. A4 L# ]
  378.         MrvlIETypes_RatesParamSet_t rates;, t1 U' t1 d2 M% T& s
  379.         MrvlIETypes_RsnParamSet_t rsn;$ E% f0 Y% \+ |( j4 j$ d- [' u
  380.         MrvlIETypes_VendorParamSet_t wpa;
    , j4 C/ _% y; R/ {2 R' E' f
  381.         MrvlIETypes_VendorParamSet_t wwm;
    ( W- d9 r" z% g) ]2 T
  382.         MrvlIETypes_VendorParamSet_t wps;
    $ F) B- Q; p6 s
  383. } WiFi_SSIDInfo;
    / `- U) R- U" P4 J7 w5 [$ ]

  384. 3 Y' V$ E; H( C' D, t6 }5 Y; @
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)
    . h7 [# Q0 H- k
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)
    0 p' O: n- X, \( C
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)+ O; G" A3 {2 ?7 p7 B
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)" z4 s- P4 g% q2 D$ L' |+ I5 ~
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)' M. H, {0 e0 Z
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)
      M5 O9 L% {4 u* Z( ^3 P' ]
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)  S" e  ]$ e8 ^( J) {0 D

  392. # f( c! T% ]+ ~* ~0 W' L
  393. uint16_t WiFi_Associate(const char *ssid);
    9 N" A, n1 N1 Z+ k: Q% }, W4 i. @$ s
  394. void WiFi_CheckCmdTimeout(void);
    / P+ o; I3 f" a! p& k
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    - M& z) g8 z4 f  E: T
  396. uint8_t WiFi_DownloadFirmware(void);; ?" W& Q7 i( p- O7 n% y
  397. uint16_t WiFi_GetPacketLength(void);1 A4 U/ k  k  X5 I" N6 v" o. a
  398. void WiFi_Init(void);
    1 p0 y+ p# n1 _: ?7 u1 K
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
      t, T: B; ?( j, o0 w5 Z5 p
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    - i& ~3 a% K( O5 {
  401. void WiFi_MACControl(uint16_t action);6 }' s; \& ~7 m% P
  402. uint16_t WiFi_PacketPending(void);
    & c$ m% K- l* V9 H3 I6 e7 O& @0 D
  403. void WiFi_PrepareTimer(uint16_t nms);, b$ |/ b8 e- Y* d8 Z
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);! @# P9 i5 \% I9 [
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);% x/ v! }1 ?+ X# O" J
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);  t# p$ l$ L9 a4 \8 K1 y
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);
    - M% [0 i  d3 ?: C" Y/ o. \+ E, B
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);
    6 W- ^  Z2 {$ k
  409. void WiFi_Scan(void);7 I8 E, r8 V- \2 ]+ h0 t) g
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);0 h. m3 N; i) _/ F: D+ ~. @! K
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);
    $ i) x( b9 m* q0 m8 O7 ?
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    # A6 G0 }9 x6 Q5 E$ k
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);
    5 C' F3 a5 D# S6 ]7 d
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);. N/ o" O" s7 |( A' Y8 x1 x9 @- h7 r
  415. void WiFi_SetBlockSize(uint8_t func);
    . R! n4 q& V+ Y8 T
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);5 E* Q: H0 r" q, c7 R
  417. void WiFi_ShowCIS(uint8_t func);
    4 ^/ [& b( y* N+ h! K
  418. void WiFi_ShowKeyMaterials(void);
    2 Q3 u# X* e4 ]2 K/ L5 k
  419. uint8_t WiFi_StartADHOC(const char *ssid);
    * L) P- \+ y! e* ~
  420. uint8_t WiFi_Wait(uint8_t status);
    " d1 c; X2 N2 C) l1 {
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);
    9 o3 x; h0 o4 a+ l
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);# o. Q  t: j. U: G
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);- A, r: S9 Q" h& R, u
复制代码
【WiFi.c】- B3 s4 F$ `: \( F# u5 I
  1. #include <stdio.h>4 G/ _4 B: V: o
  2. #include <stm32f10x.h>
    7 l, ]0 f, l8 Z7 Y5 I
  3. #include <string.h>
    * N' P2 W$ q0 h  @0 I) ^6 G' _
  4. #include "WiFi.h"$ g8 Y7 ]4 E% @/ G
  5. + f7 E) |" }0 a6 K+ Y
  6. extern const unsigned char firmware_helper_sd[2516];
      l# l* }2 J  R. b
  7. extern const unsigned char firmware_sd8686[122916];
    ' x! Q7 G4 h! Q" K- l" n
  8. : t* @' C# k4 |6 G, W; W
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址1 o4 `7 K) s& G0 \4 L
  10. " x! O( [- q5 [. b8 t% ~: S3 {
  11. static uint16_t rca;) \2 n) r1 K# C
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;5 a* h4 `, J( `0 ^! p& r
  13. static uint32_t io_addr;" U8 A4 u  w) C0 Z
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小
    & D) @* z: v  Y& R! G  B
  15. / X1 ~+ k* g: v! k- @: x/ A
  16. void delay(uint16_t n);
    / z8 W0 v8 j# A% T6 u
  17. void dump_data(uint8_t *data, uint16_t len);; E! D5 n6 J# x. `2 n( q
  18. 9 Z* {8 U$ c& j1 W" w8 o
  19. /* 关联一个热点 */. h0 J' D. J5 O7 b2 [8 \# L3 _% ?& J
  20. uint16_t WiFi_Associate(const char *ssid)
    8 B, ]) K4 B0 T* R5 f- i. o
  21. {
    . C& D' i8 `; i9 x/ d
  22.         uint8_t buffer[2048];
    0 j/ y/ v4 H: g% I8 T
  23.         WiFi_SSIDInfo info;
    % P1 Y6 |( i, t0 u3 Q- j5 `$ B( ~
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;* e& A5 c7 A- v% H
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
    ) i% `1 i3 B! w5 x& ^
  26.         MrvlIETypes_DsParamSet_t *ds;
    * ^4 M! E& C7 m# c1 q- S- g
  27.         MrvlIETypes_CfParamSet_t *cf;
      Z. B0 \& _( j8 N; N* T8 F
  28.         MrvlIETypes_AuthType_t *auth;& w, a" K2 J, Z3 z; H
  29.         MrvlIETypes_RsnParamSet_t *rsn;
    * }* H9 U- H% _
  30. ( ]) h7 J% D# f9 R0 S6 Q2 U
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))
    + o* ^& q- U, ~8 A9 t
  32.         {
    9 q) v7 U% f3 p0 B
  33.                 printf("Cannot find AP: %s!\n", ssid);
    7 X! G! U" [3 V
  34.                 return WIFI_ASSOCIATION_NOTFOUND;' i7 K1 M+ B. j& i+ v
  35.         }
    / e9 ~5 w6 d3 C+ q8 H0 z4 n
  36.         
    . j* a4 t3 x, S- n$ Q
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));% E% [9 z9 G2 a
  38.         cmd->cap_info = info.cap_info;
      ^$ g% G7 f1 O/ d9 _
  39.         cmd->listen_interval = 10;) d1 p) m: A( P7 o# f  a
  40.         cmd->bcn_period = info.bcn_period;
    5 K6 O3 L( n" P
  41.         cmd->dtim_period = 0;2 Z2 U5 X& _* D; ~
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));% v; B$ `1 l3 Y$ o6 m% a
  43.         
    - V% P( a# M& l$ O2 l6 |1 f6 S
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));
    ; a5 O# O' O+ G
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;
    $ s" N, a+ m9 A4 P+ p
  46.         ds->header.length = 1;
    " F- h& G9 M  W( P& J1 B
  47.         ds->channel = info.channel;
    / C+ |8 {& p( V2 Z0 K% \
  48.         
    7 R4 Z0 ~8 H$ K" C$ l
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);' T. [) `$ H6 u* M# a5 p& \
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));: q3 X1 E: [3 C, _
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;! L. E- a! c3 \0 F0 z4 U0 N7 ^
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);9 K6 s/ N! O+ ~# _+ ^/ M" ~
  53.         
    7 X) \& ~% h% {; g8 O0 C/ G
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));
    - ~: X( s, b  a$ z; l& L, x
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    : O$ N4 P2 k, f- @
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;7 s0 p7 k8 j$ K
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);# e+ u; ^) W( L) ^( K- C
  58.         auth->auth_type = AUTH_MODE_OPEN;
    9 O  o# K! w, L% M/ V
  59.         0 s* G/ a: a5 h! @. o, V
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);+ [5 M9 \  |/ r7 W4 y4 b* f: {' c4 K
  61.         if (info.rsn.header.type)& {& k. ]+ e1 {/ i" A! O
  62.         {% L& [* c3 J: l8 T% v
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接. T: k8 }* j2 C7 Q/ `& O
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
    ; f+ t" u$ j9 n4 k( J0 i* ~: }
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));6 R& h; V$ e0 q5 j' F/ p. w( Q
  66.         }( g1 l8 A6 T' G# l
  67.         else
    & P- x* S: A7 ?1 ?+ E, U
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数( ~4 c1 B7 _+ H" |/ J/ P: @
  69.         ! V# c4 o5 E3 }1 p# O( h
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))
    . \3 g5 R" \! V: J( D4 M
  71.         {7 Z7 d/ S' B7 _! O$ A% _
  72.                 printf("Association with %s failed!\n", ssid);$ O$ B$ n: z' ]1 I) b! G7 i5 f
  73.                 return WIFI_ASSOCIATION_ERROR;" G5 @( x7 I4 E! y  F
  74.         }
    * M2 Q: c6 Z% z# _
  75.         / w3 C5 d3 |- I. R. N+ n3 r
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);
    " w! u* v7 l2 i
  77.         if (resp->association_id == 0xffff)
    / S9 ~/ S; w* j. U
  78.                 return ((-resp->capability) << 8) | resp->status_code;
    + E: a* b6 S. m' H/ Y' |7 _
  79.         return WIFI_ASSOCIATION_SUCCESS;
    7 ~8 w. m* O$ B8 Z7 _
  80. }
    & Q, K. `$ h  f" R, V: i
  81. ! e8 K* D% S7 v2 Z2 h4 U
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    8 m7 s# w% J1 V$ F. {- c
  83. void WiFi_CheckCmdTimeout(void)
    ' e$ {; w* o+ l8 O
  84. {
    ! f! x+ @2 V( w6 p0 d$ g
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)
    + u5 d6 e4 \& G
  86.         {
    6 G# R( I6 H4 J) n1 m
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志) z  \2 I" T0 u! x
  88.                 SDIO->CMD = SDIO->CMD; // 重发
    , J8 n' B* A5 ~# o' f
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);
    * L* e: G; b4 b$ {9 [9 l. W, [
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);$ ^" g" X/ [" j# D. p" B
  91.         }5 p" C6 T) U7 R
  92. }2 j3 t- s) {0 a) j

  93. ' o/ d. D, V( H4 o1 [# K
  94. /* 连接WiFi热点, 并输入密码 */& T+ h$ c; t0 t! I0 g
  95. uint16_t WiFi_Connect(const char *ssid, const char *password); c! g& c5 j1 [% {
  96. {
    8 w& v, T- U! a! C3 z" H
  97.         uint16_t ret;/ ]5 k* t: [! m4 P, S( ]
  98.         do. Y8 Y9 x) B, j+ h  _! K9 `- w
  99.         {% W& A* a2 ^" O1 g# G
  100.                 ret = WiFi_Associate(ssid);( J/ E1 I( n, Z
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)
    % }- U8 R$ ^/ u3 m
  102.                 {
    ; C+ v7 S. `; K' |; ~# G2 N
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);
    ! ]# D5 z/ q# q- s: t
  104.                         delay(2000); // 等待一段时间后重连
    / ], ?7 U! M4 f: _; c' I; ?
  105.                 }
    # S8 Z' ^5 h! X9 f) d  g- m2 q9 _2 H) C
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连
    6 U6 o( h2 s6 H0 w
  107.         
    0 n7 Q7 W9 t" W2 N
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)7 b: E4 @' I3 M" R" b  ]5 G
  109.                 return ret;
    7 L) [5 C1 B4 a4 K# P% }1 J
  110.         4 j: h& j- y) L
  111.         printf("Connected to %s!\n", ssid);
    % S% F* U1 B+ g+ n
  112.         return ret;
    , K7 g) [& I8 C
  113. }5 z0 W# t8 j; N! g7 U4 x3 i# d
  114. 4 o; Z6 M  d6 m( S
  115. /* 下载固件 */
    " z2 e1 s" M! x; y9 _% q
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc
    : U. J' `9 v! i3 E5 t: u* |
  117. uint8_t WiFi_DownloadFirmware(void)
    4 v0 Y2 D+ p/ \$ N
  118. {6 p7 N8 l, y* e  C; E
  119.         uint8_t helper_buf[64];
    " B: N8 i$ ~2 p
  120.         const uint8_t *data;5 F4 F! T; D2 O- W, V* K
  121.         uint16_t size;6 ^7 f! l- @6 E
  122.         uint32_t len;
    7 [/ |2 q* h# _! n4 ]9 j* @4 K
  123.         1 L+ c  O* u3 ?2 }% ^0 o) {
  124.         // 块大小设为320 a) P! b. `* w5 O  s$ _- T+ i+ j+ y
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;5 a7 \* j! i& o3 X1 W" Q8 l; e* V" o
  126.         WiFi_SetBlockSize(1); // 应用到Function 15 f% z! |" n9 [7 I6 S9 `8 R( x1 [
  127.         
    " B7 ~" k* k! S7 D5 c# l% {1 H
  128.         // 下载helper7 a" T+ @5 X# B, J6 c
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);9 t+ D# p, d% g! C8 S6 K) Z. F; U
  130.         data = firmware_helper_sd;
    7 j  _( h7 u+ b5 \9 h- ]4 S
  131.         len = sizeof(firmware_helper_sd);& h7 o3 G; D: l
  132.         while (len)' F) n! ]' R! R4 k; q: E
  133.         {; V' y. q- t, Z8 @7 T6 ?
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量* B0 F$ X/ B, d  G# b( o: U+ H: I
  135.                 size = (len > 60) ? 60 : len;" a: K9 U% I2 i* y
  136.                 *(uint32_t *)helper_buf = size;
    ) A. M8 g9 |+ h
  137.                 memcpy(helper_buf + 4, data, size);
    / R# `! U! \0 q% ~5 Z& ]
  138.                 ' d0 s: H, w+ c% G5 N
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    2 u: X; C9 B2 s; {  X
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));, d( o; q+ y; w& c, z* d5 D6 h2 l3 P
  141.                 len -= size;
    2 F3 Y* k. j3 r1 n9 O
  142.                 data += size;7 m) V3 D0 h% m! F
  143.         }
    ' ]& L! K; y* v2 ^: x
  144.         *(uint32_t *)helper_buf = 0;
    ! Y3 t; N+ b! T1 @, e  ^0 K+ R
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束# |% ~4 A3 M" A/ K8 c* l
  146.         
    . I. G2 h, ~: q% h
  147.         // 下载固件
    + p; a5 k3 O% ?9 X
  148.         data = firmware_sd8686;+ |- A6 j/ l9 l, }: A
  149.         len = sizeof(firmware_sd8686);
    : {) p4 ]' U. S* k+ v
  150.         while (len)
    . ^' l7 I6 S5 B& [& p( }
  151.         {
    0 d" t  [  I6 G/ S5 S$ Q% ~
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);! V; S+ I1 B: ^5 y. }6 D( }
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数6 U, e1 t! }5 B: k1 q
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);2 Q0 e9 Y& S: }* e/ R
  155.                 ( `" B) ?/ O# E1 @
  156.                 if (size & 1)/ U# k* N- C9 d
  157.                 {0 r$ Z( C8 L$ e+ q8 I% \7 S' T
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)
    ( B1 U9 c* ?- B. y/ H2 v; @8 L: ?
  159.                         printf("Error: an odd size is invalid!\n");9 a3 V+ c, x% d" Y. e: J1 n
  160.                         return 0;8 K( a& S4 @& E% d, N9 g  \) `
  161.                 }
    1 J5 `7 S2 T$ N0 s
  162.                 if (size > len)
    ( Z9 ?5 W5 i; b; r* \7 r* H
  163.                         size = len;
    % B9 R& N9 {$ t- U! [7 z
  164.                 6 r9 R- E' D* \8 \" V
  165.                 if (!WiFi_WritePort(data, size)). i  d+ t" L; C" O0 L
  166.                 {
    % g; L$ @1 I6 s1 r
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);
    $ {! {6 }5 A! {
  168.                         return 0;
    1 z; `3 m5 O* c( q% H
  169.                 }
    0 I- `( d) M/ v3 b: J
  170.                 # k/ }# l7 E7 J1 ]' ], A
  171.                 len -= size;
    ; Y' J4 D  r1 \9 [5 z
  172.                 data += size;1 L) Z6 A2 l- {7 e1 ]- a
  173.         }
    ! Q( |! `  x) O' v
  174.         ; M: [) U) {0 S3 T
  175.         // 等待Firmware启动
    , n1 e5 ~% ]& f2 H( m- _2 e
  176.         while (WiFi_GetPacketLength() == 0xfedc);
    . s" X/ T  M! i
  177.         printf("Firmware is successfully downloaded!\n");4 j! i5 m' L% c1 R% t! |- K' ~7 S
  178.         return 1;
    4 v  V' {% [  n5 }3 X* i. \
  179. }
      E/ n, l) c9 C3 I8 [. o' A9 E
  180. ) ~% ?* i; e; N! Y; a/ v* m
  181. /* 获取数据帧大小 */
    6 d- _& v$ Y/ g/ y) G7 G1 o
  182. uint16_t WiFi_GetPacketLength(void)# d- s2 ?7 S& M# X1 e: ]- z
  183. {8 v" P. T* c+ x2 A! R- w
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);
    ( I$ C9 i' J. J  I; A  B2 f5 _8 E
  185. }5 d  W* p* r0 G4 x( @- o; ?" b3 f
  186. 8 L; Y4 E3 t( y# h2 M
  187. /* 初始化WiFi模块 */2 m7 h" W* j# w6 r9 h6 j8 c
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization
    ; F( y1 ?9 `, g1 A5 y9 i. b
  189. void WiFi_Init(void), t9 N0 c) \5 H6 y7 b
  190. {
    % w  }+ g/ i& T) y; D" S8 o2 c: ]
  191.         printf("Initialization begins...\n");
    ( a6 ^  T' Z- g, j
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;, ?! {7 E! D# c
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz% C, c2 `1 Q0 d5 H* c: k
  194.         delay(5); // 延时可防止CMD5重发
    ; R0 s  O  D; z$ H( P1 g
  195.         
    $ R* \, I7 G1 S4 J; K
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52/ z4 I4 T1 ~; N7 o5 w1 P
  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)
    0 w2 D1 L9 @  ]! V
  198.         
    ) A. b- X$ H  I' k/ r7 T, ~9 c
  199.         /* 发送CMD5: IO_SEND_OP_COND */
    ( L/ ?' z( B2 V: ~2 G
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;
    " n# L5 Q2 h& d* j- U+ ]0 X0 S8 F
  201.         while (SDIO->STA & SDIO_STA_CMDACT);6 z; U  j9 V4 [: b8 C- ^6 m
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令: c' ^' _8 T6 w
  203.         if (SDIO->STA & SDIO_STA_CMDREND)
    : V! x: C0 Z( H* U' S
  204.         {
    1 I6 h: e/ W. x2 T0 w5 r
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;7 i/ S3 J) G5 [% H4 ^1 X3 _* x
  206.                 WiFi_ShowShortResponse();
    2 J! U1 a$ Z1 N- ^* a7 k
  207.         }- Q: X: k( e' y1 }: ?
  208.         , Z0 `$ M. D( K  D& y+ a
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */$ z  U$ `2 y, A" d$ f* b
  210.         SDIO->ARG = 0x300000;
    " ~, R, o' I1 Y& H% S4 F
  211.         SDIO->CMD = SDIO->CMD;& d* s. T( C; D1 ~) l# H, `5 ]
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
    0 @! Q1 v* H7 ^% @+ @( p
  213.         if (SDIO->STA & SDIO_STA_CMDREND)
    8 n- I) H; X3 y' w
  214.         {
    : K3 N" G+ E! j: ]7 Q
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    0 |7 j) d' B7 c" J: H3 x
  216.                 WiFi_ShowShortResponse();
    ' @+ l& }' j( ~  s7 P0 Y
  217.                 if (SDIO->RESP1 & _BV(31))
    * P1 ]/ Y! }  R6 ?8 S( T, K6 q
  218.                 {# w* R; i) Q5 s. \0 O
  219.                         // Card is ready to operate after initialization
    & U' N/ B% _& \* P0 t6 P& C
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);- D! r9 g; x7 K1 n- V
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);
    ) L5 `' m1 N( c) n
  222.                 }0 D* S2 c5 y2 z$ o9 q
  223.         }
    . r( w, r# l$ n) ~4 I
  224.         
    4 C0 o, H$ L& \2 V" }9 q
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */5 k* M8 X! m; u9 g
  226.         SDIO->ARG = 0;
    " X; r3 T! [  m
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;
    : a+ z" s; y% P; v4 C
  228.         while (SDIO->STA & SDIO_STA_CMDACT);& x0 }2 i) B: i! R8 u
  229.         if (SDIO->STA & SDIO_STA_CMDREND)
    : N/ z2 J5 G0 U! a/ a" m; l9 z" j
  230.         {
    & N+ u- I; ?+ p% {6 a" c
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    & Z' M3 O# u, a) O3 G
  232.                 rca = SDIO->RESP1 >> 16;
    ( o3 Z  ~4 q0 m2 b- l8 K
  233.                 printf("Relative card address: 0x%04x\n", rca);- b! s8 d0 Q- h- a) Q, p+ t' D: z9 r
  234.         }8 S, x9 z4 U3 y7 ^
  235.         
    % x& F" {. L! a/ ^" D6 ?
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */. N  b: @$ q$ [$ l+ z
  237.         SDIO->ARG = rca << 16;7 F- B: p9 `- U+ p& p& W8 u
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
    * C% K0 Z* \9 n
  239.         while (SDIO->STA & SDIO_STA_CMDACT);! O. h. p9 g+ N7 B# R2 ]# k1 E
  240.         if (SDIO->STA & SDIO_STA_CMDREND)$ U& u7 N/ B. V6 F2 D/ }
  241.         {
    0 {$ \) X/ ^9 L; e+ F5 [! R
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    * ]9 z9 s0 B# c% o4 o! B+ i0 r
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);; z2 H) N* U3 v! h5 h
  244.         }
    ) e3 [$ B" [1 M4 b
  245.         0 O; \2 N! e3 J! C/ J: }5 \
  246.         // 提高时钟频率- _) Y, Q7 Q/ e9 Q
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz) m6 o5 N* w) {* ?! V* B, }4 [
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒: V* v+ O. n) x+ i
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
    . L& W2 j+ P0 W2 G' c# O: c
  250.           x+ r$ L5 t  r$ [
  251.         /* 选择总线宽度 (Wide Bus Selection) */
    4 B6 k5 j% b$ z+ b3 w: @; ^
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)% X; ^7 m8 b+ s; `
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
    ! o. x. t' v+ {# H
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus  C! {+ Q& K! \+ k" p2 G1 R
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;4 `5 W  j7 z# |/ [7 G
  256.         / @3 x- C2 v% G+ U' N
  257.         // 初始化Function 1+ G+ Y9 m' k/ Q) {& ]
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)
    5 M* c6 r% p: U! d3 m
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)& {& Y# ]& w5 D
  260.         
    8 V, B0 o3 U$ u5 a4 w
  261.         // 显示CIS信息, V% f; q. ?9 z# \5 x( U( b
  262.         //WiFi_ShowCIS(0);5 t& g0 F9 @6 V* u# v% R6 W/ g
  263.         //WiFi_ShowCIS(1);8 V( l3 u3 A6 @4 j4 w
  264.         % G8 M/ P3 M  H  w2 @
  265.         // 下载固件6 T4 z! K/ p) ]$ [, v/ H) L( v  k  u
  266.         WiFi_DownloadFirmware();) S8 L! c, y) ]) T
  267.         
    5 N2 a) J$ O' [7 c
  268.         // 设置数据块大小为256字节4 |( c- i6 C" o: R" A2 q
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    ; D, ~1 O1 G& Z' w7 z
  270.         WiFi_SetBlockSize(0);
    + q) Y) x5 m* q/ @% b' W, \: a7 y
  271.         WiFi_SetBlockSize(1);
    2 ]7 Q. m. L# j& M. X* T9 y0 f$ u
  272.         " X' m& j( G& {# i# ]3 }
  273.         // 允许发送和接收
    . }1 u+ W3 r' T
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间
    . B. q7 r1 _+ j" C- S* m: h
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);' I; r3 W8 q! O6 O9 R
  276. }
    # l6 X8 W" Z) z) g! \# s
  277. 9 e) W6 P: F2 |" |0 e
  278. /* 获取或设置密钥 */
    ! C) v) @9 Y/ {
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)
    - W- j2 T" A" z$ o+ l
  280. {8 [7 q2 T6 f1 Z- `$ A
  281.         uint8_t buffer[256];
    - B) N7 F6 I, ]& m1 ]. J) X0 J( B( b
  282.         uint8_t ret_size;
    * Q6 y. g9 ]6 k+ \* [+ F. O& e) R' D& s
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
    5 n$ K2 d* S' k: A! `/ d0 m
  284.         cmd->action = action;) u5 ?- x/ G0 ?2 }
  285.         if (action == WIFI_ACT_SET); w, p( A0 n, ^1 K8 j. s! r; L
  286.         {6 z# f+ ^; T- ~/ I/ A
  287.                 memcpy(cmd + 1, keys, size);
    * `. m! ]  A- {
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);
    $ y) A- _0 ]* @( Y8 s/ o
  289.         }0 Z/ n- s  F* M1 t- T: X* B
  290.         else0 a+ \& w2 K; b) @/ l- v) e2 a* B
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));6 M% y& P" h$ D! h  e5 @
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));6 v& v- e! n1 ]
  293.         ' |' e; W/ _& N$ c
  294.         if (action == WIFI_ACT_GET)' w" \% j) _& o( e3 X
  295.         {9 w$ d) t; ~7 k* J  n
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
      }, G1 Q! T+ N- N! G% h' m
  297.                 if (ret_size <= size)2 F2 j" \' r" n( H8 @5 a
  298.                         memcpy(keys, cmd + 1, ret_size);
    ) s4 ]/ p9 F8 k% ~% n" y) V/ Q' {
  299.                 else
      L3 W3 F' v) h( Q1 e
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);. X$ [" D) z7 Q+ [3 D: c. @! z
  301.                 return ret_size; // action=get时返回读取的数据大小/ O) I  h4 {8 k3 N+ D% T$ S( W1 r
  302.         }) X7 i+ V8 D3 o
  303.         else- W5 q" e' Z% R  }1 f
  304.                 return cmd->header.result; // action=set时返回命令执行结果值
    ! K9 k/ u: G" u
  305. }
    9 k+ X, O7 q2 e3 |- ?
  306. 0 s2 t. a- `+ Q3 b# l: D
  307. /* 获取或设置MAC地址 */
    * F  ^$ r- U9 c1 U7 o; E
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action): y1 r0 B1 X% b. O
  309. {- d6 m. @! O$ F( Q5 G6 }* _$ O
  310.         WiFi_Cmd_MACAddr cmd;2 a8 ~# Z, ^- m# D9 i/ K
  311.         cmd.action = action;
    6 m7 ~  U. b4 l" I
  312.         if (action == WIFI_ACT_SET). p' v: o$ V& f3 M/ K" \8 Y( T
  313.                 memcpy(cmd.mac_addr, addr, 6);
    1 d& L1 A" J( y* p
  314.         
    2 m( P6 ^" W( D2 w% b
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));. M  v5 L, D8 ^8 e
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    $ a, S; i' @- F  p4 w- f
  317.         if (action == WIFI_ACT_GET)
    ) N+ w+ a# t1 B& u1 z% A2 c% e
  318.                 memcpy(addr, cmd.mac_addr, 6);% I7 x5 y: ~9 J( ]4 ^! O
  319. }% C1 p# b* u- O" H1 C2 t/ Z
  320. $ }3 p/ t0 }, l" i0 Q
  321. /* 配置MAC */
    7 o  l+ g) e3 b: x! s- ?  r
  322. void WiFi_MACControl(uint16_t action)4 Y: a/ R; M* k* h
  323. {1 k  H* l# ]. B
  324.         WiFi_Cmd_MACCtrl cmd;! s9 s+ y4 t7 j' T" J
  325.         cmd.action = action;8 [2 n  H0 j' q4 J1 Q
  326.         cmd.reserved = 0;
    ; j9 Y' q7 L$ C+ U# G
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));! D, {1 {2 t8 w: H4 w9 F& e8 C
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));5 Z. i& ^. r* v! G9 C( r
  329. }
    3 Z, B9 Q4 d; ]0 [* c: a5 d$ }. Y: t

  330. 2 w4 ]4 u: r6 f7 ], [9 t. W
  331. /* 获取滞留的数据包大小 */; u4 m6 w# g  h$ M1 g; a. R
  332. uint16_t WiFi_PacketPending(void)
    9 n% A7 ]! c- ^3 L- K9 Z! t) }
  333. {0 A# ?2 z( I" G; Z. C
  334.         return wifi_pending_size;
    $ A0 W. S: o. j2 k; |
  335. }
    8 j3 a# P5 m! N% o7 b: b' f8 v
  336. 6 i- \9 T3 |: \2 C
  337. /* 准备好超时计时器 */6 t, A8 _, s8 @! F+ u: @
  338. void WiFi_PrepareTimer(uint16_t nms)
    6 e- E8 M1 e6 K0 A3 U
  339. {$ E% ^4 j) l8 ^
  340.         TIM6->ARR = 10 * nms - 1;0 Q& j6 H" z- P
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz6 c5 y  k& L' F$ U
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置
    0 l  ?/ h4 A& \3 W
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位
    + ]- c0 L, |  u; x( l
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式, H& H0 |4 C3 ^, C) [
  345. }
    $ }4 `2 X, y. M' {# e1 p+ ]+ h" e

  346.   \6 g. Z4 K7 O6 h7 }
  347. /* 读寄存器 */1 u. ]; L7 Y3 O2 [* v0 k
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr)
    " ~* ~! y4 l- h# G/ U: B
  349. {$ f6 R  K6 G' Y: _
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);
    . `- C6 ]7 r* a2 E% O/ @! B. t
  351.         if (SDIO->STA & SDIO_STA_CMDREND)
    , M! d, A! v; _
  352.         {
    $ P3 L$ {9 ]0 L. f; X$ ]& S4 `) m
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;/ A0 D! a' e/ W" p& j! X
  354.                 return SDIO->RESP1 & 0xff;
    ) [* C% {2 \" M2 d2 v" O8 p6 w
  355.         }8 c. J1 f8 _% M% A  E$ V3 h
  356.         else2 V" S1 s' m$ x6 U! R* P
  357.         {0 T$ u: e: y8 B7 t! L
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);
      p" |" Z! t& M
  359.                 return 0;
    , `* h6 F: K7 c6 ^( ^" l9 ]
  360.         }& a$ c( u  B  C- R6 ~3 r
  361. }6 X" Q" b5 R; t. ^: u9 o

  362. 5 b- z8 F) j9 m, y6 r
  363. /* 读数据 */# g* g; t3 e: C! q# s4 r1 }
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小1 A, @* N$ l( H7 N
  365. // bufsize=0时, 只读取数据不存入缓冲区- `% B  N! e1 r
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    7 _* n; N7 V# {1 E* \1 v5 s! B
  367. {
    8 G7 [/ H3 Q/ z4 o6 w
  368.         uint32_t len, temp;4 P* p# k1 h, Z3 j9 d
  369.         if (flags & CMD53_BLOCKMODE)
    ( C3 t. s- w# r0 w! f+ h5 v3 A
  370.         {
    4 X: Z" j' o, d, b3 m
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数! _. y- x# n! I7 s# ~
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式+ j4 j. K0 O  G
  373.         }2 X0 Y. F; W+ B% E6 e) G- m
  374.         else5 I/ U- N* M# `8 ^2 ^2 P
  375.         {
    " Y  D9 |5 {; Y' m
  376.                 len = count; // count表示字节数
    " _( p+ E" U( j2 D' p+ I% F
  377.                 if (len % 4 != 0)
      T8 J3 d8 _$ }' R. [9 D
  378.                 {5 e8 t7 }% g- z% @) j: ^! \- I
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    + I6 @& K& Z; F' O$ t$ m" Q
  380.                         count = len;
    / U3 _/ Z( [. [' ?) l! F% y
  381.                 }
    ' M$ |; @3 v/ @& Z6 m) j7 ?) Y
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式, }5 N" D' z7 F
  383.         }! D/ P$ a9 `) Y
  384.         SDIO->DLEN = len;1 A# E# X$ |4 p, y
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机$ O; c) N- v: A' Z
  386.         ! F$ m' P$ v; [% Q- ^1 ?: v) ~0 H
  387.         WiFi_SendCMD53(func, addr, count, flags);1 {; k5 |& x% I! X" i* i
  388.         while (len)6 r) s9 p% I7 d' i
  389.         {% y& Z2 _6 j2 W  L6 o
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)
    5 `0 X1 N8 _; u3 C
  391.                 {0 i7 o6 C# Y: M4 U  X+ T
  392.                         // 若有数据到来就读取数据
    . b, W7 e3 R2 B; f, k
  393.                         len -= 4;& F# @' ~' g6 D4 f
  394.                         if (bufsize >= 4)
    ' y# {8 ^; z. ?6 ^4 I8 U
  395.                         {. k% ?6 K3 v8 C
  396.                                 *(uint32_t *)data = SDIO->FIFO;
    8 P# n& H4 `' D5 p' `5 G' V" Z7 |
  397.                                 data += 4;1 t7 `9 Q% r9 m) ^1 s9 ^
  398.                         }4 ]8 `$ T$ \, A; I
  399.                         else
    ) Z% x- {. @( d4 m  u& u
  400.                         {" G0 r+ A0 ?* F# k" S. _
  401.                                 temp = SDIO->FIFO;/ x& x3 C- j2 I2 n
  402.                                 if (bufsize > 0)
    + g0 H+ `; E' ?( v  `  {' d
  403.                                 {
    , d, ~/ F/ Y- D- R4 y, l& q8 R
  404.                                         // 写入缓冲区最后1~3字节
    6 a% [9 g3 R& y  N3 B$ a
  405.                                         memcpy(data, &temp, bufsize);2 i; h1 g0 n) H* O/ p. b$ n  U
  406.                                         bufsize = 0;4 ^" w2 {8 k9 z; r( ~
  407.                                 }
    * k& i1 b# f7 ~2 n' c2 N- w0 D9 O
  408.                         }
    . u  Z2 M: \$ @2 q& u
  409.                 }
    ( n) x2 Q7 d# O# C$ O7 k9 g
  410.                
    ! Z7 u" \. H) h% E
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)0 x% [/ U/ L* i3 S
  412.                 {
    4 ?# J0 O9 a  d+ a  Q' {2 w
  413.                         printf("Data Timeout!\n");2 u; e2 V8 T( B/ E9 I
  414.                         break;1 B( _" Y5 V- {$ E# ?" s! T
  415.                 }
    ) v' x  G0 o7 ^  U% Q
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)
    5 d6 @2 `2 D- S9 Y+ z4 `2 v  ~& ?
  417.                 {
      q# S% E2 r, N& i( X! ~% F
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    9 W, b) @5 N2 B. r1 M/ U0 V1 K
  419.                         break;
    " F) u$ G( t& \: R5 l
  420.                 }
    * g) t& H" n  `% D0 K
  421.         }
    / A& T9 \. q  A
  422.         
    * J$ V5 _* I7 Q/ E, m+ N8 E" F
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));4 O7 G" p) g& a7 f  H7 ~( {
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;) e1 o" j+ G* L! i* A0 Y, {
  425.         3 |3 c) t+ [! p2 L( P
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;5 U5 }- F7 E, r; m
  427.         if (flags & CMD53_BLOCKMODE): i5 O- f1 ^7 U4 Q5 x; \* Z
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;8 A# M; ~' i8 ]9 I# [5 f9 a1 w
  429.         
    * e* y+ V$ ~8 t1 R8 F: l: A4 G4 t
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功
    2 A1 d. X8 i9 P( u/ M
  431. }
    7 W& U! p9 K( I1 m# o
  432. * w2 z: N7 Z& X
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize), o% s& @! b7 B) V. K) l
  434. {
    % }) z% [. u) h
  435.         uint16_t block_num, block_size;$ x. B# t1 e0 M) N' r: C
  436.         block_size = WiFi_GetBlockSize();
    / j. |% z! N) n
  437.         4 P- S4 p1 E( S( F+ ?: k# P
  438.         // 读取数据9 I+ x" G1 K9 P
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
      f' `% z2 ~; D  n
  440.         if (size >= 512 || size % block_size == 0)
    1 M( q2 d0 E$ m' X7 i) d
  441.         {
    # l/ ^$ O' A% d
  442.                 // 采用Block模式传输
    ( e. L0 W3 O! d8 t/ N/ F
  443.                 block_num = size / block_size;
    8 ?2 y1 z/ s+ p, l3 v2 X% Q
  444.                 if (size % block_size != 0)& C2 R; u: Z! `& g6 Z2 H
  445.                         block_num++;* Y4 e" |* E( K$ l& J1 t: ]
  446.                 6 I1 n, m3 K/ B
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);: E) d! x% c! R* S8 ^
  448.         }' h' M- L. h/ N+ q6 H
  449.         else
      Y. ~0 R" X3 V' Y& `
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);  Y: e# @6 ]. d3 B) m3 J( a
  451.         
    - `. e8 P2 \6 L. m. ?9 W8 e
  452.         return SDIO->STA == 0;; k& d% I% u3 Y% A
  453. }, N/ g4 S& v! j% |9 S3 v

  454. ! _8 s, z. T$ G! u) Q% \7 U! q( S
  455. /* 接收数据帧 */* }$ e7 o1 t9 e" I8 R
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)
    7 A# z" L5 s& P/ r2 o# N3 L6 {
  457. {" Z" C5 x9 Y. H
  458.         uint16_t size;; i4 |3 Q1 @; Q8 Z  [- i. {
  459.         if (wifi_pending_size)& G- D1 Q4 N8 ^0 v' l* N
  460.         {
    % x1 |4 e9 D8 Y, a# m. t1 C
  461.                 size = wifi_pending_size; // 先读取滞留的数据包7 {- i1 X; x' V  |( i; r
  462.                 wifi_pending_size = 0;7 t6 |7 {, W5 ^1 |
  463.         }+ n1 z) E8 x1 F0 d9 m  Z- j% o
  464.         else, ?2 c8 H8 {3 i, \
  465.                 size = WiFi_GetPacketLength();
    5 [% M9 W- s3 N
  466.         return WiFi_ReadPort(buf, size, bufsize);$ n/ X" `3 D5 F. t4 v- ]" k0 y
  467. }7 {, a$ I& V$ e/ r5 T

  468. $ L) x4 n+ L! F
  469. /* 接收WiFi命令的回应 */
    ! K5 O2 N# }, l7 j
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)
    - A! [" E/ |' K
  471. {
    ; m- i/ G6 ~* _5 V8 U, ^$ X  M9 i5 y
  472.         uint8_t retry_cnt = 0; // 重试次数
    2 B% ]/ ?: ]! [% i: j* @7 E# L2 x
  473.         uint8_t wait_status, resend;* {4 g# R! }  L
  474.         uint16_t size;" N: I7 j! b- S7 J
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;5 {; F  v$ G  C* N& v3 m% i3 ?
  476.         WiFi_SDIOFrameHeader temp;
    6 n* L: [, J! O% U1 `  I* l( j6 m6 j
  477.         ( t/ s4 K# K* R
  478.         // 等待数据准备好
    0 G- T+ B, q8 E/ U1 N7 N
  479.         do) {# ^+ I: g/ B4 e8 a& p
  480.         {
    # i+ G+ n# l" c" _, z, w
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);% B5 N) q. h% ]4 W
  482.                 ' N  L( M5 c- C, O# [6 e
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息$ x0 v6 i2 _* y  a
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
    . L% I% ^, W; ~
  485.                 {
    ( N; G1 L8 r$ o  y+ O) }
  486.                         // 若读到的是一个数据帧, 不是命令回应
    # g+ L+ V, |+ r5 e+ s8 C
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功4 F' D9 F6 q7 @
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);
    $ _( U6 K) L- Q+ Z1 _  [
  489.                         wifi_pending_size = temp.length;
    - H+ `8 O; e- ?" A/ y$ w
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算+ {; z6 w1 D" k' k5 P" f  C
  491.                         resend = 1;
    7 P* }4 I# j7 i1 X; t* i4 w
  492.                 }
    * E; B; ^! ?/ |+ o5 v
  493.                 else if (wait_status == 0)
    4 M% u/ M/ W' @& b( j% C
  494.                 {
    $ ^: \4 q; k# k7 W
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)- g5 K! d) P2 ~# C  }
  496.                         resend = 1;) x9 y( O! M  M! x3 a" L4 W! L2 v
  497.                         retry_cnt++;
    & y. y8 t$ P! f( a" B; U! z* @0 A
  498.                         if (retry_cnt >= 5)
    : A7 N) S& Y. o! [4 e' t
  499.                         {
    2 v) e1 e$ W2 x, n6 S5 \
  500.                                 printf("No response!\n");
    - x( {2 ?; |  p
  501.                                 return 0;9 h& O2 C' e! ]: W, g
  502.                         }
    ) @' T! W& E2 E. H, T7 C
  503.                 }
    : F- }3 a& _' X1 N9 }
  504.                 else0 _/ W6 L- T9 K8 f" D
  505.                         resend = 0;
    1 r; }, m$ B$ |- T3 l
  506.                
    ' R7 m) c* s7 u9 v7 i* U  H) o
  507.                 if (resend)$ K, `* B1 q3 L' D- ^5 ~( k" {
  508.                 {' i( j6 k. r' `0 }, r) |
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND); ?* W" a, L, H* q
  510.                         {
    " b, B1 M: b2 e# `4 [
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait- I! ^- v9 k5 j+ Q
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);
    2 _- A% g' n$ q! z0 d  s& l$ M
  513.                                 WiFi_ResendCommand(buf);
    0 s$ h+ ~+ Q: |1 I' ^
  514.                         }
    9 [% ?( e, y8 f9 b$ [, P8 Q
  515.                         else$ x) b  ^4 w) \
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出! m- n; e& n# ^0 u; T6 n. N5 x
  517.                 }
    5 N0 Y6 ^; G/ C1 h
  518.         } while (resend);* f/ I5 J% Q& }0 X
  519.         * m7 x- ~) g6 r3 e- {$ V& a
  520.         size = WiFi_GetPacketLength();3 ~' s1 f. B- e3 |% f& F4 h
  521.         if (size > bufsize)
    ; ]9 H% L2 ]& ]& z0 [
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);6 N# ~5 l3 c9 \( H
  523.         return WiFi_ReadPort(buf, size, bufsize);
    6 ^4 q8 R  h+ K" Z3 w
  524. }, s% Y9 c% W2 p

  525. * V) q3 M, s% z& C  b1 T
  526. /* 扫描全部热点 (仅显示) */
    / `. ^. A& |# j& N! h
  527. void WiFi_Scan(void)
    . B  P( Z9 I4 U. y
  528. {& _& P9 E* v; F. o$ I% t
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组( c3 U) p6 H7 Y: T0 q
  530.         // Stack_Size=0x00000c001 o3 \. H5 y% J0 \$ v( K
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
    & s: L' y3 U# j
  532.         uint8_t i, j, n;
    / a  M7 b) f# ]) R; M6 c3 p
  533.         uint8_t ssid[33], channel, wpa;
    . V1 D6 b' k- t9 w' J* T) _7 F
  534.         uint16_t ie_size;
    ) n, o6 D! t' r" D8 d0 R1 Y* H8 ^
  535.         
    4 V& w6 n! D2 U) h6 O6 M9 p9 e, H4 j
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
    ; B8 x1 E( v  e0 n* [( M% ]
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));
      k5 g% O9 T1 o! E9 J* E3 M
  538.         : s6 ^# m' ]% M1 j' P" a; Y) P
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;
      D1 `' h7 J- n  B( e2 \% l
  540.         WiFi_BssDescSet *bss_desc_set;
    , o7 g" f+ q6 y# ^1 w
  541.         WiFi_VendorHeader *vendor;3 M0 Z# M  |8 K) p
  542.         IEEEType *ie_params;6 m2 L3 j# V$ n  N2 O
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;
    7 p0 `+ A$ Q8 N: `
  544.         5 n1 J$ f/ k' o+ c  S
  545.         // 分4次扫描14个通道4 R- [9 v/ z2 h. K* j$ }
  546.         for (i = 0; i < 4; i++)
    ' B: Z, q1 ^2 u, s, |3 ~' c
  547.         {1 G. {6 d6 F! w, w* v7 _! v  g
  548.                 cmd->bss_type = BSS_ANY;
    ; s2 V! G7 F9 Z9 c" \8 T7 B6 k
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));4 C; k. x: ~" ]. W0 v) T
  550.                 # ?1 {5 c; ?  I+ l3 Q! h" L
  551.                 // 通道的基本参数! g- b* E0 X6 k! s  ^2 u
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数
    5 @) n. ~' ~1 Y6 {
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    7 p4 x* c2 f' t& }
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);
    + _2 T! g! X5 q* I
  555.                 for (j = 0; j < n; j++)# |' U9 Z7 P1 G9 p5 T7 c
  556.                 {
    % ^1 z) j' Z4 W# [% [! C
  557.                         chanlist->channels[j].band_config_type = 0;
      w9 _* W* t1 f+ T8 H/ p
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号! ^% Z6 U- D# s) e- Q
  559.                         chanlist->channels[j].scan_type = 0;5 ]1 d" T5 I. c) g) |# x( `  X
  560.                         chanlist->channels[j].min_scan_time = 0;7 b3 E' o/ z( k/ z& g
  561.                         chanlist->channels[j].max_scan_time = 100;: x9 g: {$ r8 ~& v5 R- S& H
  562.                 }" \$ t* d# A- P1 ]( V4 D7 c6 y5 d
  563.                
    1 @2 p& z  b: r. @: K* ^. X2 l. w7 G
  564.                 // 发送命令并接收数据
    5 O; u& `( ^! E0 B) p5 F
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);$ l) F6 T! D2 ^0 `# ?- G9 z; t
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉2 |: Q. b* @0 h( p, I
  567.                
    5 b: q: k3 R9 x$ I
  568.                 // 显示热点信息, num_of_set为热点数
    3 P1 o% Q# @5 e- p8 D/ q3 x+ ^
  569.                 if (resp->num_of_set > 0)
    ; `  o" D+ v5 Z7 Q1 j! h& _4 I3 z
  570.                 {4 L4 d5 s8 N# Q7 R
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));1 R; {0 v# [9 O! d# X, W; E5 @
  572.                         for (j = 0; j < resp->num_of_set; j++)
    % d9 \, k/ Y5 v5 A  U
  573.                         {6 r- f1 L& G. U+ c+ n8 R: W7 V) C0 X
  574.                                 wpa = 0;
    ' F9 s' B" r" \+ M2 T
  575.                                 ie_params = &bss_desc_set->ie_parameters;
    ! p# i6 I$ N. x; p6 F, m
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));9 m4 p* B' p, c$ @7 j3 O2 E
  577.                                 while (ie_size > 0)
    : t! E" ~" o/ z5 b  y
  578.                                 {  _% {9 v1 M( u! A; b3 U
  579.                                         switch (ie_params->type)) E; w; I& _2 \6 I
  580.                                         {
    : c" {% H+ @9 R' `! `: w
  581.                                         case MRVLIETYPES_SSIDPARAMSET:
    0 j% k+ |( J; z. T  e
  582.                                                 // SSID名称5 I7 C' F3 s: R# f1 `( F  V
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);
    9 L5 K7 N) y; b' i$ \0 t# U; K7 |
  584.                                                 ssid[ie_params->length] = '\0';* E# V, x  z3 F
  585.                                                 break;, C+ J9 U" a1 R  ~& N( ?$ p$ _
  586.                                         case MRVLIETYPES_DSPARAMSET:
    8 u9 k6 l& ?1 @
  587.                                                 // 通道号
    ! k6 H$ a/ k( C9 x# N
  588.                                                 channel = ie_params->data[0];
    / Y6 w' K' M3 N7 A, T. c; r0 k
  589.                                                 break;" L/ M5 c  h3 a6 j3 D% m
  590.                                         case MRVLIETYPES_RSNPARAMSET:
    % d, {" n( i. _% w3 E0 `0 A7 c
  591.                                                 wpa = 2;
    ' T; `/ K+ j* Y- N; _, h, g! k  x1 ?/ A
  592.                                                 break;7 O# o4 C0 ^/ O5 i
  593.                                         case MRVLIETYPES_VENDORPARAMSET:
    4 t& x( k& K% K+ N- c
  594.                                                 if (wpa == 0)
    3 D, b) ]3 }( o/ ]4 v: P
  595.                                                 {$ Y: h, x. |3 G6 ^* T* z5 I5 ~" ]
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;
    & V* h2 H( L5 s% q9 S$ h5 b! _2 q
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    3 n% W8 [& s$ w  ^6 Y
  598.                                                                 wpa = 1;
    ) t: j, Z9 V! n8 G6 W
  599.                                                 }
    & @/ S. G, g+ T7 s
  600.                                                 break;
    5 X1 x2 j: N9 ]" Q8 L% O
  601.                                         }9 C" s) C0 N5 k
  602.                                         ie_size -= ie_params->length + 2;
    ) `) u! W, I) d' Y  }9 p
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);$ k- m$ z! G( m  s7 E
  604.                                 }
    / E6 T) z7 f. m4 D
  605.                                 if (ie_size != 0)
    - |/ S; a1 i2 @; E! N8 N) n
  606.                                         printf("ie_parameters error!\n");
    0 ~& e, W# M, \8 `
  607.                                 
    + M' ]: f6 e7 r
  608.                                 printf("SSID '%s', ", ssid); // 热点名称- n( c9 ]4 }3 E" M( P5 d
  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地址; L; O( |# J5 u# t$ t
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
    6 v/ w" @& ~0 Q) D' d
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);
    7 N7 E( R5 p$ [" ^, U/ @. O
  612.                                 
    ; b7 \! E8 r6 Z6 W8 Y! d2 N4 Q+ Q) r
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);  B* p4 B  X; P
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)  s8 l6 d( z% M* a6 G7 Y
  615.                                 {
    " D) a6 d  ]3 n- Y
  616.                                         if (wpa == 1)
    2 E. G1 D) F6 O! d" ]8 s  Y! E1 `
  617.                                                 printf("(WPA: ON, ");4 ?2 {5 }3 f# ~. U1 j
  618.                                         else if (wpa == 2)  y; c( B$ @/ c
  619.                                                 printf("(WPA2: ON, ");! R0 h' ~2 O2 V4 @- T5 s: ?; T
  620.                                         else
    1 s1 D7 U% S6 e# z+ x0 D
  621.                                                 printf("(WEP: ON, ");
    7 V% X3 G- @. a7 J% g
  622.                                 }
    2 w$ d+ P0 ^% N7 n" B
  623.                                 else; s% l9 H8 v6 }; ]* z/ [
  624.                                         printf("(WEP: OFF, ");5 U4 m6 E) v+ P3 f3 E
  625.                                 0 X- K) v6 V( X8 V( a2 `+ s% y
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)& ^$ e9 t/ ^" C3 \/ @4 N
  627.                                         printf("mode: Ad-Hoc)\n");& Z9 ?4 X' n! ]7 F, w  b
  628.                                 else
    ; D1 j$ J3 E% N3 y0 \9 ?
  629.                                         printf("mode: Infrastructure)\n");
    ) T& G0 I" k! F5 v" K
  630.                                 
    8 t7 T( i) Z3 u5 X
  631.                                 // 转向下一个热点信息+ s0 l8 o, U. r
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);
    ) U/ P$ ~% \, |9 I! N+ t
  633.                         }
    : p5 j, w# A% I* h5 L7 ^( Q) b
  634.                         9 b& M% Y+ R  `. X/ Q1 m7 n# b
  635.                         // resp->buf_size就是bss_desc_set的总大小* s6 ]+ u, z' z$ q# Y" ~
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size
    - U* F' L. Q: t) H# J4 `
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
    ) m5 W+ g2 Z  F; |0 a
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))8 t# ^( M7 f. K7 M5 v+ q) R
  639.                         {
    7 E9 K* u. R0 P# L0 i, l
  640.                                 printf("Timestamps: ");! C1 A5 |% Q, f0 X3 f9 o  P7 @
  641.                                 for (j = 0; j < resp->num_of_set; j++)2 M; E- g# O8 W% b7 x
  642.                                         printf("%lld ", tft_table->tsf_table[j]);7 P2 E; g6 \# n! _7 Y
  643.                                 printf("\n");* X( u6 e6 x5 s) S- \
  644.                         }*/
    $ L' d; g0 a$ V5 e3 [7 r8 v! I) N
  645.                         6 ?2 @3 E  W5 a1 ]' w+ z" t3 p
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table
    & W/ H. C: C9 `
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)
    ' }4 k# O9 ~9 \3 u
  648.                         //        printf("data end!\n");% t$ l# g' l# }4 M
  649.                 }6 t- t$ y% g; V
  650.         }( J' w9 \: X5 p  B. \4 j( S; \
  651. }1 g3 V* H# ?# R' I! h8 c
  652. 8 l# }! k$ T" P. |" p: s3 _7 b8 {
  653. /* 扫描指定名称的热点 */
    $ J+ A. C! Q# ~; h
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大
    0 t: T2 E1 }* w4 [- y
  655. // info用来存放从buffer中提取出来的一些常用信息
    2 C9 g$ ~# M  t8 Q( i1 i
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)
    ( ?+ {* [+ J9 D2 R
  657. {; G+ d8 N. L7 r) @- y, |
  658.         uint8_t i;/ V* D- V& p( F8 ]% V2 q
  659.         uint16_t ie_size;) d- |( n* M! i: w& U
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;; h6 [0 O% y$ N. _5 i, X7 `- _
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;2 v, I0 H+ ]# t
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);
    1 o4 S* b( B5 L
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;+ X- {, ?; F  y" G' [- e: r
  664.         IEEEType *ie_params;4 B. \& p  u6 _" @: V7 s; l4 W
  665.         WiFi_VendorHeader *vendor;
    ) H7 `  ]! Y6 |& x  x% X
  666.         
    6 a7 H" S# k; |: {, k* F
  667.         cmd->bss_type = BSS_ANY;$ ]5 `3 _" F* r- Q) h
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));- \6 L; O. R" |0 S$ ^# U: X- x
  669.         . ?- {; i6 g. e, z0 R& g
  670.         // 添加ssid参数* D. a2 A, B- e8 x$ T2 J
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;: N- a) N3 r+ b" O7 O$ y4 h- r  d
  672.         info->ssid.header.length = strlen(ssid);, V7 j2 R) o# E) H* I' D( B
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);) ~# T& E$ b& w, U7 q& ?. N# G
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    4 s  ]  c: n* L- ?; ?$ I" u
  675.         4 F4 N( l+ E8 m* a0 a
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));
    " w* B9 [1 ?, ^, R" `! _( w5 }
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    0 n0 W5 B( ]" E* F& @" G
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    3 f( ^; @4 q: b) X& k6 s$ q6 y
  679.         for (i = 0; i < 14; i++). e9 P- s5 s2 g; I; x
  680.         {
    ) ?  Z6 R; h1 O/ `$ G7 w* h
  681.                 chan_list->channels[i].band_config_type = 0;. t; ?8 g7 C, U4 O0 a
  682.                 chan_list->channels[i].chan_number = i + 1;! t8 A/ U! _' s! M9 [
  683.                 chan_list->channels[i].scan_type = 0;
    3 Y# {+ O, M# {+ r4 z. A% X9 q
  684.                 chan_list->channels[i].min_scan_time = 0;
    $ T4 {: ?. Y( a3 A
  685.                 chan_list->channels[i].max_scan_time = 100;
    0 j# u- g" K  @0 O" @
  686.         }0 a8 x& m' p1 x
  687.         8 n7 w% {2 U3 q. O" T! r$ O
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));! n8 K- `5 G( g2 d% ?
  689.         wifi_timeout = 3000; // 延长超时时间
    1 ]7 O5 G9 F2 i5 w
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    % j1 A' B6 C% o9 [
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;" ^! V+ u  u/ h6 ~) P
  692.         8 j; Y5 P# C9 u  o4 I3 h/ q
  693.         if (resp->num_of_set == 0)
      [# t- D2 ^- M' m
  694.                 return 0; // 失败
    / l% u  X- ]% ?( _: A# i3 i- V! [
  695.         ) L5 e) i& u& u4 d/ U+ V
  696.         // bss_desc_set以扫描到的第一个信息项为准
    : Y# e* [) Q" v1 |% [& t
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));! N/ G# X) i6 v) b# R" v0 E
  698.         info->cap_info = bss_desc_set->cap_info;
    ! t1 P! O+ ]% p2 ]2 z* ?2 u
  699.         info->bcn_period = bss_desc_set->bcn_interval;
    ! d- s3 n! [  r$ ?( J" v
  700.         . a' H2 P% @. r; N8 v8 P5 i. \" }
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)
    # B4 `: x5 W5 c
  702.         info->rates.header.type = 0;0 h/ P- k7 f' H2 B, E7 I
  703.         info->rsn.header.type = 0;) ]/ T8 Q0 ~. I; ^& R* S+ y8 o
  704.         info->wpa.header.type = 0;
    / s/ E# z% P1 B; G$ v6 X: Y" ?
  705.         info->wwm.header.type = 0;
    % f' B, A" f0 Z% j- C9 {" z
  706.         info->wps.header.type = 0;" i1 r; a2 }3 y
  707.         4 W% B8 T: h9 ]" S
  708.         ie_params = &bss_desc_set->ie_parameters;
    - G/ V0 i7 o+ a. z
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));+ N+ j, O5 c$ R
  710.         while (ie_size > 0)
    9 w1 l$ }  ?. d
  711.         {
    2 W0 f8 N! @$ ?+ C8 B! ?
  712.                 switch (ie_params->type)
    7 ?+ e' |3 B, p* L( J  C
  713.                 {
    9 s* E/ D2 E( D; F0 U9 x5 S
  714.                 case MRVLIETYPES_RATESPARAMSET:
    ( M# h. u7 a) a) j
  715.                         // 速率
    $ F0 k: g3 }) c7 l) T
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;+ t% X% E) h4 |) X8 d
  717.                         info->rates.header.length = ie_params->length;8 S6 F& l; t0 [9 ?& v0 z
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))
    / w2 C  Z  a1 |/ [
  719.                                 info->rates.header.length = sizeof(info->rates.rates);
    0 }5 E5 p, B3 Y* n
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);
    , l3 l4 d2 `9 e3 j) ~5 @) B
  721.                         break;
    . `) e. `  u0 r  h+ J& l
  722.                 case MRVLIETYPES_DSPARAMSET:
    : X0 O# |( H& O4 z, {
  723.                         // 通道号7 ~2 s, s* f1 R6 F8 z- P
  724.                         info->channel = ie_params->data[0];
      a& X# _, F: x4 t) u
  725.                         break;2 I7 y$ V- |! j5 q# s3 h
  726.                 case MRVLIETYPES_RSNPARAMSET:% l3 Y6 h" ~* S) k6 G# I2 I' l, U
  727.                         // 通常只有一个RSN信息 (与WPA2相关)
    $ t) i8 e% I7 ?! `1 A3 U' Q, }
  728.                         // printf("RSN len=%d\n", ie_params->length);* T) V& y! S0 b1 v
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
    $ |9 n1 a+ G: {/ n/ ^( N% `
  730.                         info->rsn.header.length = ie_params->length;, }) g0 x: [5 K( U7 X) B; P
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))
    ) T! P6 F( r, ~) d
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);: ^6 e, k- I7 c
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);+ t5 m- @7 i* W% n+ T! x" n4 T$ f
  734.                         break;# v) \, m2 s* d. g
  735.                 case MRVLIETYPES_VENDORPARAMSET:2 d; x# |0 ]  w5 _: C. ?3 \7 ]
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)9 M' d: u; U- Q
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;6 z5 U0 {. ?5 J! b# }/ l) {* v' Q8 n
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)5 j2 Z% B) X6 G* _( x
  739.                         {
    6 y0 U# V( Y, X- u
  740.                                 switch (vendor->oui_type), R) R( F  c; H
  741.                                 {
      v8 v& `% q2 g6 S5 N1 d# {
  742.                                 case 0x01:: O" p# A; V8 T1 P4 C0 W! M( E
  743.                                         // wpa_oui
    7 a% q: H4 w+ x1 x8 R: b; L5 k
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;
    5 o8 c$ R* P) S3 T
  745.                                         info->wpa.header.length = ie_params->length;$ c) r/ f; t( n# _* v' B
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))( ^- F- b; U2 [2 k1 b
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);# ]5 M( N' B/ R/ B/ u+ ^& e: P
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);
    , T. @9 F. G9 r" Y$ P4 k/ U7 o; y
  749.                                         break;
    . J% k) s4 l$ v4 [
  750.                                 case 0x02:
    ( L# i$ F' E* O: ]- A
  751.                                         // wmm_oui& I8 u$ p6 i/ M  Q" N
  752.                                         if (ie_params->length == 24) // 合法大小' i0 g2 @. A( {; t' K7 r# ]9 d
  753.                                         {
    * s" b  R/ k$ C" L; x7 @6 C, v
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;
    ) j6 P( {# p; r. ~+ v
  755.                                                 info->wwm.header.length = ie_params->length;0 c3 b9 i1 y) @# s4 e. H9 E
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);+ e0 [/ M; v  S$ S' A0 L
  757.                                         }
    ! q# u9 [8 ?9 c5 x! }
  758.                                         break;
    * u9 }5 J2 l% O  q: A2 O/ d$ r
  759.                                 case 0x04:
    8 P# v& w. E- u% J4 G
  760.                                         // wps_oui
    3 w) t3 ^. x( t5 m$ I" g3 s
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;$ F( f! _% s" D( m0 c
  762.                                         info->wps.header.length = ie_params->length;
    $ F! H& k) P# O* b2 X
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))
    ( x7 h0 {5 H/ w9 X
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    ; D0 [( B' C' Y2 A9 |
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);
    % {2 m( N, R/ C% v; w
  766.                                         break;
    . p) y( d' D4 W3 c
  767.                                 }' B* }, `' h1 j7 u7 M8 p
  768.                         }6 H: k' q, Y  U8 L( x, w5 X
  769.                         break;
    . y) y) R, B9 U8 E* Q3 o/ a: s
  770.                 }
    3 A. Q2 q/ n2 X# C5 D2 Q. {+ n" o4 l
  771.                 ie_size -= ie_params->length + 2;
    * y- V* d' ~$ m. }% \! n' i
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    ) P: e& ]; ~9 P) M0 S2 l
  773.         }
    6 a" q% a1 y) A! P! J; p& h
  774.         8 Y. N2 p- w) A
  775.         return 1; // 成功. o( ?5 ~8 m$ W9 I
  776. }/ ?  g& Q3 e6 k8 ^
  777. 5 `, O) [4 r+ I: w
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags): ~2 X3 l5 }7 U. G- j
  779. {
    - Q6 |. w( K4 k* s6 F+ {  g
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;) _  h4 x8 p! t) _# }
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;
    5 O$ y! b9 a; [: ?1 g9 ?" F1 T% S
  782.         while (SDIO->STA & SDIO_STA_CMDACT);
    1 K  L/ W& e7 a" _4 ~. ~6 V
  783. }! t0 n5 W; t  X

  784. 6 H2 i7 ~3 h& ~7 z" z
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)
    0 \# q9 [2 ]& `8 N. K
  786. {
    ( D& i$ ~) d9 {% W  ]
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求
    5 h' ~# v7 S& [+ T2 \. d
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;
    ( M; }- T) b- D  \* T* v* t
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;$ n/ ~, Y; q/ F
  790. }
    / r: `: X) _+ ^/ `) p# q

  791. 5 Q) e- J, f% u) K4 m" j
  792. /* 发送WiFi命令 */
    " o* v3 C; r6 I* W2 m* ?3 V% R
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)
    , X. p. G" w( q  h0 I- ]# Q6 y
  794. {
    ) o- W1 i* s" X/ ]1 P$ |
  795.         static uint16_t seq_num = 0;' G6 g# N8 {( P7 {) g$ n
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;) u6 E& J! o1 U  d/ L* y9 Z
  797.         + }+ S7 P& J' r$ m( E+ y+ N
  798.         if (size != 0)
    ; X& V# @3 u  |7 K# B, c1 Z5 b
  799.         {3 m2 s( E, A7 S0 J( U' d2 x* [
  800.                 cmdhdr->frame_header.length = size;
    6 A3 t. s4 ~* i0 W  b/ w, Q6 f
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;; c: C, }. j8 \1 [9 @
  802.                 cmdhdr->cmd_code = com_code;
    - G0 ?' {  M8 x" ~% J) H* \& M+ h# n
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部
    ( a% F0 e, j9 q! H0 k0 _* [
  804.                 cmdhdr->seq_num = seq_num++;
    4 Y4 G) k% e( q* v5 J
  805.                 cmdhdr->result = 0;
    ( q1 z* u# r  D
  806.         }" A0 s$ a/ j2 K# O% t, O
  807.         else! y/ B8 j; [- d- d
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr  e1 l, k; A( y  U$ O
  809.         6 p7 N5 s) n' q5 n# u( Y: T
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃( r1 ^+ j! s+ O# q2 s
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())6 @- t- m! B# E) D! k9 i* j' ~
  812.         {
    . z7 k+ ~4 n+ T# p3 F
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");. S  Y5 X0 T  j6 Y: g1 O! `) q9 [
  814.                 WiFi_DropPacket();
    1 g7 m9 ?5 `8 s; c# _7 R) @% x: q
  815.         }. Z# i) i) x. L7 V& f
  816.         2 B+ h. m. N: m7 g- P" f( Z% I  g
  817.         WiFi_WritePort(data, size);
    * U( I5 d& }& ?; ^- p
  818. }9 c/ F2 n! G5 ^2 L# @# s* s

  819. & x6 f* m6 ?0 e2 u4 _: Z# n' z. I. ], F! x
  820. /* 发送数据帧 */
    $ L6 C6 H$ D8 r! g4 c7 Q
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)& g+ A, y8 l% ^1 J) {  i4 h" R
  822. {
    2 R$ N$ i; E" e
  823.         uint8_t ret;
    ; M( T% a% S, D8 v6 G
  824.         
    : E' f" b5 S9 {% q0 }: k' O
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
    . b2 ?0 v" _; O/ R
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
    5 |7 Z2 v* _# k5 `1 {4 N2 s( E
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;" Z$ n4 Q2 a" ]5 q8 U5 ]
  828.         
    + ]: S2 h, x! f% P
  829.         packet->reserved1 = 0;
    + e  W! A  ~$ C4 U* _  m8 w, D
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings0 M- B  M! `$ T( f# c3 T
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader1 E' b. Z- f: J
  832.         packet->tx_packet_length = packet_len;
    2 e9 ?8 f" B( i: B% _
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);! H. B' x2 i  u5 Z  o
  834.         packet->priority = 0;
    % D- G6 A$ ^3 B( k2 z+ s
  835.         packet->flags = 0;# E% [' q3 |0 l! Y7 k2 u
  836.         packet->pkt_delay_2ms = 0;0 ?. X# ]8 |8 Z% G- _! ^$ h$ @
  837.         packet->reserved2 = 0;/ J+ O; u# A4 y& T
  838.         
    9 h% F# n; f0 r8 s: _8 `% A/ V
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小; O  q- v( _- i
  840.         // 未读取之前不会收到新的数据帧
    # W' p- M$ s5 m; T! W- h+ V
  841.         if (WiFi_PacketArrived())
    3 ~, [5 X& E2 f
  842.                 wifi_pending_size = WiFi_GetPacketLength();( j7 z8 b" {! y, N2 s2 U) Z
  843.         + M4 {1 n( I1 l1 s$ c8 Z( k: q
  844.         ret = WiFi_WritePort(packet, packet->header.length);
    * Y/ u" s7 x$ [1 ~
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
    6 l2 [/ M) @+ Y  P' q# a
  846.         return ret;
    ; z5 t7 o5 u! D, H$ ~- A) w7 i
  847. }8 h0 \7 M9 G4 l' b0 |
  848. 2 P! U; O% U' a
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */( s* K, a  q& D
  850. void WiFi_SetBlockSize(uint8_t func)
    7 S8 ]1 G6 i3 ~& p% m, g
  851. {. U: w, F1 R2 C% G' q" T
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)+ R3 A3 {# c& x
  853.         uint16_t size = WiFi_GetBlockSize();( C( T! ?: @2 h$ g# s
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);0 X6 A' O4 b1 ~# \* ~* y! R' p' s
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);
    3 Q7 u) Y4 k2 U" \0 P- S
  856. }
    % k7 B( F; L* d& ~% U: W2 k
  857. ! [  S; p3 d7 k, r1 \
  858. /* 设置密钥 */- `0 i) {: x0 b& T
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
    $ `" a) A1 A: k' c
  860. {1 @, R$ d4 M9 A  `1 f& L
  861.         MrvlIETypes_KeyParamSet_t key_param;5 \( d. u: A$ ~+ |
  862.         if (len > sizeof(key_param.key))
    2 V- M4 U2 @/ F8 x* q
  863.                 return CMD_STATUS_ERROR;4 L2 i2 W: o$ k
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;& y4 T6 O1 n# {9 e5 j8 _
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
    8 v$ h9 K2 C  V' j' h/ a
  866.         key_param.key_type_id = type;
    # H# G. C% t  I, [1 J
  867.         key_param.key_info = info;% N7 q) a- G/ \6 N
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
    " I7 w4 z2 R, y9 F9 j
  869.         if (len)
      R5 }  A# l4 v
  870.                 memcpy(key_param.key, key, len);# q1 [( S/ z0 [/ T
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    ) F; \) T! r; \% _. f9 I% g  m' J
  872. }; N5 ^* Z0 U& i- C9 g

  873. 3 d3 }; m# K- {! x% H
  874. /* 显示WiFi模块信息 */" Q, I1 {; r, p( N: Y
  875. void WiFi_ShowCIS(uint8_t func)* i' Z8 h1 P, }# }/ S* D( Z6 M4 u
  876. {( b! C$ \& M0 s2 r) |
  877.         uint8_t data[255];
    * ]( V3 T' |8 b* ~" c! b: V; Z
  878.         uint8_t i, len;
    * [+ y6 A# H/ {  J& G9 T+ Z
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure  @' u" d" J0 ^# K) R9 }7 t" i
  880.         uint32_t cis_ptr;
    3 h6 |4 L$ |8 ?
  881.         
    1 \; y" t- [. p" Y/ X: x
  882.         // 获取CIS的地址
    ( W& w8 C2 g, h) ~  t
  883.         cis_ptr = (func << 8) | 0x9;3 R( @3 R& J) g( M
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    $ W. U6 \! v! O( p
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);3 H5 Q6 Z2 V# u) l$ a
  886.           T% b# v) e6 f
  887.         // 遍历CIS, 直到尾节点
    8 g1 G* ^: a! B" q" u" l8 e
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)
    9 w" y. n5 X/ R! Y! A
  889.         {" J: B  h2 b/ L6 ~# F
  890.                 if (tpl_code == CISTPL_NULL)
    * ^, r  ], ~: d5 |3 N, g9 F  Y0 r; K$ E
  891.                         continue;) \9 Q$ {) |6 ^: h+ {4 Y& n5 ~* @
  892.                
    & ^! B. m! Z6 |& x
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小
    ( S% T5 [0 G3 J1 ~5 t1 H
  894.                 for (i = 0; i < tpl_link; i++)
    / T8 P! b5 E0 g  `$ z. X  y
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);" S+ Q( o1 n3 |
  896.                
    $ i& q9 k$ g& a7 l$ P, U
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);
      ]& r8 f. L, J) P! x) j! I
  898.                 dump_data(data, tpl_link);
    $ Y; E( R% u$ a& m' _
  899.                 switch (tpl_code)* C) u0 h) `+ {
  900.                 {* s# u3 N# [. d! _/ f
  901.                 case CISTPL_VERS_1:
    2 d* N5 t# w5 S) S
  902.                         i = 2;
    7 _1 Z, K4 P/ U4 D
  903.                         while (data[i] != 0xff)
    ; V7 v6 s: A) [6 [, }; u* \* \- t( M
  904.                         {! D; h  A. F+ r4 m( L. F" R7 W+ e
  905.                                 len = strlen((char *)&data[i]);
    ; o$ f/ \7 a2 e3 H0 \; f% k4 Q
  906.                                 if (len != 0)
    ; @1 {! z# d8 J- \
  907.                                         printf("%s\n", data + i);
    ; [- v! I; w7 O2 x% k
  908.                                 i += len + 1;% H, D4 l* B2 I/ w8 W% P
  909.                         }: z" G" i8 ~, C
  910.                         break;& U" E  L2 e& x  z) z: D
  911.                 case CISTPL_MANFID:
    1 j6 F( t6 g0 y7 }9 L0 g# Q" ~: U
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple, ]; h; \; |* N6 Y; _  U
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
    : x( p; @! ^3 ]
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD. T0 z$ M" n5 }2 S' c
  915.                         break;
    4 W  k2 S2 U! i; L. C; Z( E7 b: w4 ?
  916.                 case CISTPL_FUNCID:" W. S3 E7 D5 i0 V- Z" Y) t: t
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
    & B) E2 [* `+ Z
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
    % Z  P$ Y! e: b! N
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT$ Y, `0 {' \0 M* L5 q: e6 C
  920.                         break;
    ( d8 c/ a7 m$ ^. U1 z1 c
  921.                 case CISTPL_FUNCE:
    / a" f% J2 X$ z/ l2 Q0 S
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple( L$ _7 G8 D  e
  923.                         if (data[0] == 0)
    ( N0 W& T0 u  Y3 O% }8 R
  924.                         {9 S% g% u( L) v+ `4 o
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)0 e+ i0 W8 L8 r8 v# {
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));8 O' B1 E% \* c. |7 ?# ]
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);
    + r, S( ?. n8 H7 _  l" v9 V5 n+ _
  928.                         }' `" I, G# x6 o: y7 r" C2 }$ {
  929.                         else
    1 _( T, S6 c6 I
  930.                         {
    0 p" j3 ~& g% T  U. k! U8 _, j+ t, F
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)! A( b: D! q# C& y
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
    ' G  @1 l8 q5 E* \( g" S8 I3 H3 u
  933.                         }7 C( K. F: m- J+ C% X+ `* q
  934.                 }
    8 n$ H  y9 N1 `9 n( Z
  935.                 5 I# ]7 q% N: S* u/ ?+ K: U2 I; }
  936.                 cis_ptr += tpl_link;: X8 T  S0 m# I* Z" F
  937.                 if (tpl_link == 0xff)- y7 h) ~% a$ x) c# b' n
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点
    ! h6 U+ C! |( A. f
  939.         }5 ?% B2 {  E( I: t1 c- f0 t
  940. }' L3 x  \* f5 L# E) ~1 r1 A& F5 ^

  941. 6 ?  a1 P* A  d& {1 u' K- i
  942. /* 显示所有密钥 */
    * H5 m1 h3 ~& m7 u
  943. void WiFi_ShowKeyMaterials(void)
    4 @& K" V  [* _
  944. {/ p6 ?+ r) [8 G7 T" \) k# N' B4 Y
  945.         uint8_t buffer[256];
    ; `: L8 w: x- Y7 e2 J: t/ f
  946.         uint16_t size;) g; D2 V; h  f7 i) W0 D" y, U
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;5 F  x& ^- p# d& F5 p1 X$ W: c& Q
  948.         , D! u5 U5 _7 o( [0 w1 P) F) f
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);
    ! Q  l3 ^9 N4 O8 Q, o# v
  950.         while (size)
    , g" k  M' i- j0 X) D6 h  S
  951.         {
    3 X" O; R: W; G3 s+ v! j
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
    6 w1 c6 R$ @3 i  i( o
  953.                 dump_data(key->key, key->key_len);
    8 V1 \# s% A" J  z) M. u* X
  954.                 size -= MRVLIE_STRUCTLEN(*key);2 _$ u9 _/ Q: c2 t) O
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));& `6 l  X2 ^& x0 b3 `; e
  956.         }
    / p! T" J" i" t5 y+ T
  957.         if (size == 0)
    4 J, F' ~8 \, o% k) h9 A
  958.                 printf("data end!\n");$ l9 y! i4 h7 E& n8 H
  959. }
    3 M# P0 }. j6 h; X, w

  960. 7 ~  W+ o2 A. h3 s8 B" o# s
  961. /* 创建一个Ad-Hoc型的WiFi热点 */  ]# F* {2 f- F5 {, N' l& Z( q
  962. uint8_t WiFi_StartADHOC(const char *ssid)
    + Z, b5 B( }8 V3 [, ?+ z
  963. {% T  b+ M7 M( U# ?* T9 _' D+ E
  964.         WiFi_CmdRequest_ADHOCStart cmd;
    % a1 k9 t7 L% H+ I
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
      B& M  f! w- d) T8 S
  966.         ) j- i8 O3 a/ {1 Y- o% z
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));2 u0 c/ A+ T8 \! j6 \
  968.         cmd.bss_type = BSS_INDEPENDENT;
    . F( D8 g( J* V
  969.         cmd.bcn_period = 100;
    8 C7 C) r! k. `# b6 ?& T
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;  M" m8 \/ Q1 B, T- g+ h  A
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);  }- N- M1 s% d" i/ c+ V! J
  972.         cmd.ibss_param_set.atim_window = 0;# T# H+ W4 X; D# d
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;
    % _$ Y% {8 R8 V" D2 u( G
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);
    + [* R5 ~6 ~* f1 ^& C5 G
  975.         cmd.ds_param_set.channel = 1;
    - s- {* |# e. ?% t. V7 _0 X
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;3 u5 {& B8 c6 k" g" o
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;
    / S! f; a' S& k. s
  978.         & I0 N* X' }! N, |4 F
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
    . o* ~' F# H% {3 O- R
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    * e6 _5 x, S, B' |4 O
  981.         return cmd.header.result;
    9 R6 W. D( E- y! u0 E, ?. R6 B
  982. }" E. v0 |; P8 g9 A! H" p. {3 M

  983. & |, S+ ^- ]" O6 R' L. u0 p
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */
    , y+ f8 |; r1 k2 h& }+ O
  985. uint8_t WiFi_Wait(uint8_t status)
    + `# h8 A7 f" t9 t6 R
  986. {+ Z. n) E3 s; B2 X
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    + p/ U  E$ P$ E: u+ o9 g" t) l# @, V
  988.         WiFi_PrepareTimer(wifi_timeout);
    , ?5 V9 J/ f' t2 R, j8 ?3 V0 V
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)
    ; y8 m, \5 W$ Z& \/ T
  990.         {  K, Q; [  p  S& D9 o
  991.                 if (TIM6->SR & TIM_SR_UIF)
    5 e3 _" Q; A+ l8 v5 D
  992.                 {  @  {3 |! }3 ^6 k2 M
  993.                         // 若超时时间已到( P7 T' x% u/ R, f9 l
  994.                         TIM6->SR &= ~TIM_SR_UIF;
    8 F% Z$ _/ h* V$ q
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);
    * {, u/ `# |/ O7 L" b
  996.                         return 0;
    ' N. D, _: X% O1 \' D
  997.                 }
      H: i" V0 s) B+ g& u
  998.         }$ e, u: v. P/ f& R* W3 t
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器
    ( m- O, X& R$ L; v/ i. X9 @
  1000.         return 1;( U( f1 V4 K/ U& f
  1001. }
    ! j' }% }8 O: M
  1002. 2 |- b6 D/ ~- G& X( d4 j
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */
    # |) y# f! v/ R1 d, G" U0 Z
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)
    ' M' L7 s( J- k2 o! a
  1005. {
    - j( o, b* F+ \4 M: t
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);2 s6 {6 A: O  D
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)
    : p$ @0 D' v( P! M1 ^
  1008.         {
    ( `/ m1 M& Q/ U1 C- ]5 y+ N% o
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    ( |! \! f( }% }% O+ ^# O& x" d' k
  1010.                 return SDIO->RESP1 & 0xff;$ k* Y& T& s/ }4 h5 D
  1011.         }
    ( D% w7 s% e: o$ {8 u) @  u7 [6 V  u
  1012.         else
    9 n% l/ E: Y: u3 k0 }
  1013.         {
    8 s  v  e/ ?- \0 j
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);5 p2 y/ ]2 q5 ?) ^$ h
  1015.                 return 0;
    , ~' P' g0 I5 A% m. f
  1016.         }
    1 j# |6 r9 s$ u$ P1 \
  1017. }
    ) Z8 W7 R4 {% U! ^' m
  1018. & `1 k2 j8 T; F' j/ ]
  1019. /* 写数据 */, e$ B# s. ]# |& E
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小, @4 p& Y# v- J  |
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    ) N: [4 M2 X$ s  ?7 k1 O
  1022. {
    6 d" O6 {8 H2 A$ ]" a
  1023.         uint32_t len, temp;
    5 N. Q0 G4 p2 a( z# O& k+ D9 s
  1024.         if (flags & CMD53_BLOCKMODE)
    ' W. G) r: B; }$ ^
  1025.         {! U& s' Q+ U8 a2 p
  1026.                 len = count * WiFi_GetBlockSize();
    " r# p/ i% B& q8 g! W
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;
    + g. q7 J( v' n( @
  1028.         }8 _) ~% E( V) g5 r8 N
  1029.         else
    / Y1 i6 ]: P: o% O1 e2 r" A
  1030.         {
      q5 a% B5 h9 m! r8 X
  1031.                 len = count;& f; [( _+ I. G& A1 v- }  `
  1032.                 if (len % 4 != 0)% z* U/ ^7 I' r$ g3 o7 s
  1033.                 {
    . N! D. h$ L4 ~1 e- E; v6 |
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    9 \9 I+ t% w; v- S% V! W7 q
  1035.                         count = len;
    / ~* |! L, a, _# S( B+ f" J
  1036.                 }
    8 i$ l. K0 w: \
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    0 |1 h" j( v! M' w# ^5 G1 x% }
  1038.         }
    ! |+ \: u) d' Z# {" X' M- D, l
  1039.         SDIO->DLEN = len;6 g2 `+ T0 ]! r* n( _0 s3 T2 B) c4 A
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块
    7 P! N5 Q; h4 w! \1 g* z( m
  1041.         $ H( ~' q( h' V: U* \8 |! ?
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);
    # ]; l  h: \5 ]
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);- `! u0 I. c' }5 |- ~/ L4 ^7 v
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0)8 X) @* a$ `) r) w
  1045.         {
    * h: V, G7 [* S5 R
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");$ e9 R) @' s: T3 B* b( x: K$ Q
  1047.                 return;! p) ^* ]0 v. L( W( T7 ~& O8 V
  1048.         }* a3 g. B1 k. S
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;
    0 M$ i- j  N; w- x' B
  1050.         3 [3 L, Q* _' c
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据7 X4 {, {+ b; X: h, B, j
  1052.         while (len)6 u5 [  I1 v  h- K$ T" |
  1053.         {2 u- m, i& u+ Q9 q* B2 I
  1054.                 len -= 4;) p/ f. t: s5 i  u
  1055.                 if (bufsize >= 4)
    5 T3 v7 y9 ]8 I1 r* l
  1056.                 {
    $ r% {- T) b3 `2 A$ J5 I* O
  1057.                         SDIO->FIFO = *(uint32_t *)data;
    3 ^6 a2 C3 u0 R, k5 K
  1058.                         data += 4;
    $ v9 G" `4 j* `) h
  1059.                         bufsize -= 4;
    / }! ]( i3 x2 `1 O# y- P, Y
  1060.                 }
    + `/ ~: L$ b. g
  1061.                 else if (bufsize > 0)
    0 k2 y8 Q: i5 m
  1062.                 {0 a7 Z* S6 T! V2 Q+ R9 {
  1063.                         // 发送缓冲区最后1~3字节
    9 L0 m3 P' f! h, o
  1064.                         temp = 0; // 不足的位用0填充& ~/ Y3 h* V& T# }
  1065.                         memcpy(&temp, data, bufsize);) {4 G$ Q/ p! t) j  E' L
  1066.                         SDIO->FIFO = temp;
    0 u" H& ^. x4 E; J+ v
  1067.                         bufsize = 0;" m4 k! G1 U+ I
  1068.                 }5 d- X! j0 J. Y
  1069.                 else
    4 v; t# Y! ^- [( X- ~# `
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0
    1 H! X& ~; C: z9 i
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待% r/ u2 }5 k+ p- k
  1072.         }9 [" D( M* ]: i4 `. j) V
  1073.         0 O& k; h! b. @5 R/ i( N
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕! [; h( _, y8 l% N9 Y! A$ `' [/ m
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
    : t2 U9 h- h- @. f2 ~# u, i
  1076.         
    - M9 [6 r3 P1 i
  1077.         // 清除相关标志位8 d' h4 D0 G+ C& q( u: f1 @* g4 M7 z
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;
    # _0 J6 d5 f- R' T( }: E5 m
  1079.         if (flags & CMD53_BLOCKMODE)
    7 L3 f8 h- Z  k" u
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;) ]7 t  k& Q' d* v
  1081. }
    ! m8 \0 q: p- M4 q- L
  1082. 9 ?* q  f9 v! g1 V, d
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)2 w3 ^" x5 x; \$ e9 ~4 H2 R6 A" G" S
  1084. {8 c) x' U: M+ R/ _
  1085.         uint16_t block_num, block_size;
    % w7 i3 ^" N; [$ u4 K
  1086.         block_size = WiFi_GetBlockSize();1 b" d" e( e1 w/ M; g+ p' y
  1087.         
    8 V" C4 @# l4 r/ C6 {- l
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1; b; Y8 p* y& S" b2 _
  1089.         if (size >= 512 || size % block_size == 0)
    * @) _  ^& K, }; }
  1090.         {
    " s0 n$ H  l; M& w/ ?# z
  1091.                 // 采用Block模式传输
    ' h0 F9 K0 a: C' @% l  S
  1092.                 block_num = size / block_size;
    1 I& G1 w; i  S9 q5 |/ C
  1093.                 if (size % block_size != 0)
    6 h, y! q% S6 D- K; u- V. U5 j
  1094.                         block_num++;2 V9 A* x3 p0 d  a
  1095.                 4 S8 {4 d" O& @* G
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);/ j) ?! i; f8 M! }: E) Z
  1097.         }
    ( G- |( {2 a8 [; l8 [1 X
  1098.         else4 J0 [$ k0 O. c% k
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);# g, \+ N3 c3 U$ }  |: \
  1100.         return SDIO->STA == 0;
    % h- m! I' b! \2 G7 A
  1101. }
    / z! e5 o5 `3 x4 O4 i
复制代码

& O  m5 ]$ P+ H. J! p1 b4 S# w7 S3 ]6 x" P: U
在工程的所在文件夹创建一个lwip文件夹。' M3 v" A3 x' u- O; I8 l8 Z
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
) r1 t4 a0 _6 u& G% }9 c" f. v7 Q+ {. k* x4 p" V
core/
  Y, H9 K4 [; ^6 T% O: Wcore/ipv4& y7 \4 N* v2 w/ Y" }. }7 e3 _
include/lwip
; _! ~* _$ q9 finclude/netif
( N- `1 a* Z0 Znetif/ethernet.c
0 E9 G; I" s6 O/ ]# Vnetif/ethernetif.c* {* V& X) |6 Z3 R# b' a
1 P" y" c# {; h; f
解压后,将里面的c文件都添加到工程的lwip分组下。
6 [  \; f' `5 `: z% P& W8 o. P具体添加的文件请看下图:
1 e& M7 k! }7 z1 }4 t$ y
' m) F7 W2 s, \7 i; F/ b7 Y0 ~* k3 g9 H3 U/ @# O- `( j3 P5 q& R
接下来,创建lwip/include/arch/cc.h文件,内容如下:
5 u; Y. z8 ~$ \. c, E( a
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:
" o* s( @' Z2 b
  1.     #define NO_SYS 1 // 无操作系统  
    0 t: b% ~2 }( C  J2 b
  2.       
    6 W9 [, k+ \$ a, s, \/ B& C- g5 k
  3.     #define LWIP_NETCONN 0  - z8 J3 Y" b1 j, N
  4.     #define LWIP_SOCKET 0  
    9 E; B- F# w6 |& \6 h, V
  5.     #define LWIP_STATS 0  ' h% c1 o0 M9 r: R: Y9 n$ m/ F
  6.       - [( O$ u1 [4 m' ~( C1 [) Y
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  
    / A" C  N" Q' |7 Y" v
  8.       
    3 W' ?5 q9 v# ~" k1 i" F$ w
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:4 W) ]. u% s% T5 c& P
  1. /**" w2 L2 v: B+ s+ s. J1 w
  2. * @file7 v/ \3 y& |# s4 Q
  3. * Ethernet Interface Skeleton
    . P4 ?# A- J6 w* a. ?- q
  4. *
    7 H1 U! ^' G3 w
  5. */" K, y  ?3 F. N
  6. ( V8 K5 t/ o( E. i
  7. /*9 {6 B8 z$ j& [
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
    " i* l' r9 u. o
  9. * All rights reserved.( J5 k' T& {1 s" N( B
  10. */ W1 U! m% `% I) J
  11. * Redistribution and use in source and binary forms, with or without modification,. ~) c8 Q: M5 f# t) g. D0 g
  12. * are permitted provided that the following conditions are met:
      o! g1 f: L9 n
  13. *
    7 W$ N& y0 m6 {7 W
  14. * 1. Redistributions of source code must retain the above copyright notice,; c5 [9 g) {+ g! I
  15. *    this list of conditions and the following disclaimer.8 ~4 ?! Y# k9 @
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,+ H3 u0 D, {6 `/ T' Q. E
  17. *    this list of conditions and the following disclaimer in the documentation
    " x" C; j1 ^% I! w9 n; X+ y* `
  18. *    and/or other materials provided with the distribution.
    * ?+ ~" y- z, R# J2 S
  19. * 3. The name of the author may not be used to endorse or promote products. G8 t1 h. t: Y
  20. *    derived from this software without specific prior written permission.
    $ G3 _  }0 |0 @6 p- o6 o
  21. *; r$ q& ~4 |$ e) a! a
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED, X) Z0 I) h0 X& s! v! i$ m
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    9 z4 g4 W4 ~! E8 f) P
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    / k8 K7 E" `+ x* c+ K. Q
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,( q1 w& E, W) x" Q. [2 o
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT+ _1 _& @/ u+ c# T2 C
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS3 Z- }( I! I  b
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    4 h- o8 }! P3 S7 v4 l3 c
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    & z  ]+ u  {& s7 A% u( F  n- v
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
    * n0 t) s; n+ O2 H8 f: @! _: Q
  31. * OF SUCH DAMAGE.3 w- H# \+ R) H
  32. *
    3 Q8 x- X. F$ |/ Q
  33. * This file is part of the lwIP TCP/IP stack.+ X9 S3 H7 T" g7 g8 L
  34. *
    - g, y. T# J" X
  35. * Author: Adam Dunkels <adam@sics.se>
    , _! X9 @# i7 z3 i7 q% ?. k  }
  36. *+ |; M8 g- \2 r/ F& M0 f* F
  37. */
    " {* V9 R9 H8 N4 |  `" e  x8 X2 A1 u

  38. / ]7 }2 M, B6 L$ j3 J( d
  39. /*
    " T1 P# F  J) ?3 x
  40. * This file is a skeleton for developing Ethernet network interface4 n" P: ~; ^* r7 I+ P
  41. * drivers for lwIP. Add code to the low_level functions and do a
    7 I, k% e8 g- o' ~9 h: y* p
  42. * search-and-replace for the word "ethernetif" to replace it with
    ( _7 x$ ^6 P! d0 w+ ]# t* k
  43. * something that better describes your network interface.
    , H2 R, z" ]7 Q6 }& b5 a" _# e9 o$ D
  44. */
    3 o; F6 }( g7 m' f6 U5 }0 |7 q
  45. * ~3 r; i, C" B9 ~& E
  46. #include "lwip/opt.h"2 W7 l% [2 B' o- y- p3 q0 z3 j
  47. 5 L. j& x  [4 i% U6 f$ ?
  48. #if 1 // 允许编译器编译该文件
    ! ~$ a6 p) x: r9 _' H; `5 @" L

  49. 7 G8 F' z; @9 l6 a1 Z
  50. #include "lwip/def.h"! Z! {1 F( H( x2 O+ R2 K+ Y1 r
  51. #include "lwip/mem.h"
    9 @$ n: C! @$ z3 P. M( a& l* m
  52. #include "lwip/pbuf.h", b3 A+ E# U8 z* o
  53. #include "lwip/stats.h"
    & T# u. ~. y1 u
  54. #include "lwip/snmp.h"
      c. L6 n+ X; a7 n: @! E9 ^
  55. #include "lwip/ethip6.h"
    2 [* H* Q& o1 {! F# V
  56. #include "lwip/etharp.h"* s" s4 h- F3 G) t! [7 _, R* V
  57. #include "netif/ppp/pppoe.h"
    # F* h5 K2 Q  ], u) m

  58. 2 \' k0 [, J5 o0 c3 S- p& k9 q3 w
  59. /* Define those to better describe your network interface. */2 t. w+ s: T0 e) ^% `
  60. #define IFNAME0 'e'; a% b# y" A* j9 y7 k
  61. #define IFNAME1 'n'
    $ \* n- i8 o) G. k% q6 E: n7 E

  62. % Q  s' x1 H- C! u
  63. #include <string.h> // memcpy函数所在的头文件' V0 H8 x9 P  b! _
  64. #include "WiFi.h" // WiFi模块驱动程序头文件9 @1 ^1 q1 r7 C2 }$ @( J* G

  65. 7 m6 U& j- _, I
  66. void dump_data(uint8_t *data, uint16_t len);
    5 f2 v7 L1 w1 ]; q% I

  67. : _5 F5 |9 `2 E
  68. /**# Z; Q! H! i  o, _5 \4 H
  69. * Helper struct to hold private data used to operate your ethernet interface.
    + k$ k4 s4 I/ n" q
  70. * Keeping the ethernet address of the MAC in this struct is not necessary% j' a( L& M7 ~4 g/ y- w
  71. * as it is already kept in the struct netif.' b0 j* S) B' G% ]6 U
  72. * But this is only an example, anyway...
    ! s6 P) |+ @5 Q; }% m
  73. */
    5 I- v# d$ c% r
  74. struct ethernetif {
    $ L/ V' F6 R- H0 E: }" ^, p
  75.   struct eth_addr *ethaddr;8 M7 Y4 E$ @% p; `: ]
  76.   /* Add whatever per-interface state that is needed here. */6 X& j8 X) a$ Z& H) a
  77. };
    ; q2 O, h" B* k1 z) V/ C- j' V

  78. $ b1 [( f5 Z( ^8 B0 S
  79. /* Forward declarations. */6 N% ~0 V/ x1 f4 ^! ~" d, }
  80. // 这里必须去掉static/ e5 p' k. n5 R
  81. /*static */void  ethernetif_input(struct netif *netif);/ O) g( e' m- _, b) u3 g

  82. $ b4 ?- N5 N4 z0 @0 _6 E
  83. /**2 K# Z0 V. }! ^
  84. * In this function, the hardware should be initialized.$ [2 _, I+ {% O* \5 g
  85. * Called from ethernetif_init().
    : q/ r# E) Y7 k$ \
  86. *+ M' j/ H# H/ p
  87. * @param netif the already initialized lwip network interface structure* `" D8 z+ Q2 A, r: D! r( ~
  88. *        for this ethernetif3 J2 f7 ?) k. y2 `
  89. */6 }. ~7 w2 y7 D
  90. static void
    8 ?1 Q" M$ M2 f1 U
  91. low_level_init(struct netif *netif)% \7 I/ ~6 Q( g' M6 [4 k
  92. {& ^$ w" ^0 Q9 \$ n, O# d
  93.   struct ethernetif *ethernetif = netif->state;
    # m1 _: C% h! \

  94. ; N' ?( J% k5 b6 A) w- X* N/ Y
  95.   /* set MAC hardware address length */
    " z1 L! q( \6 z9 y# V/ ^
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;
    : J; P. o% j3 I; F/ Y* W2 M) C- X
  97. $ P' d7 D+ A/ B" n
  98.   /* set MAC hardware address */
    / ~' s9 r8 c% ?
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
    4 H: A* O. Y# a# I5 L) j
  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 l+ I( ^2 }& v3 F& X7 D* _  V" \) }

  101. % U1 ^+ L- G/ ]0 K
  102.   /* maximum transfer unit */7 x# p6 C/ j1 }, z
  103.   netif->mtu = 1500;
    & Y$ |6 d' f" n" I8 e; K% ]7 J

  104. & h* p/ m! e8 g7 O$ x
  105.   /* device capabilities */+ d+ [3 ]4 G/ j
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */8 Z& t0 V8 ]+ c/ w, U
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;- }% J  f) N6 F; G4 c
  108. ( \% F/ `7 C7 |: y: g9 o) s% A
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD
    " V) k, ]. i. G
  110.   /*8 N+ P1 A" Q2 D$ n8 K) g2 [6 C
  111.    * For hardware/netifs that implement MAC filtering.
    9 y3 R2 |. m: _# x0 D/ [
  112.    * All-nodes link-local is handled by default, so we must let the hardware know, ]* N6 q7 e/ @! F# n6 e
  113.    * to allow multicast packets in.6 v) Y' o/ m. O1 t# i( ]
  114.    * Should set mld_mac_filter previously. */% p% s2 p4 @. M
  115.   if (netif->mld_mac_filter != NULL) {$ e. b7 U8 C, j5 L
  116.     ip6_addr_t ip6_allnodes_ll;& C  j% Q. ?; x' _9 l+ @; O7 U
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
    3 L( O# S8 @4 a
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
    2 X$ |  T2 j/ `* S
  119.   }
      R% J' Y5 _% s) E% E  g3 l
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
    8 k3 S3 L/ i5 q$ I2 M
  121. 3 ?! A, g- c% t, D
  122.   /* Do whatever else is needed to initialize interface. */
    ; X2 }2 p" Z* o8 n# E6 _+ J
  123. }' n% F/ `, Z7 I; j1 b) J: w

  124. 1 X' a0 ~! @. R: k% Z! W7 w- O
  125. /**
    . ^, _) K/ }1 v0 O% y( k
  126. * This function should do the actual transmission of the packet. The packet is4 R7 L# B! B2 Y
  127. * contained in the pbuf that is passed to the function. This pbuf! I+ ?5 ]) ]) A" G
  128. * might be chained.) \  w+ a# y& j9 I
  129. *# J8 k5 Z$ ]# D" P3 {+ O* b: X' H
  130. * @param netif the lwip network interface structure for this ethernetif& `6 `8 d2 O. U0 W! I( l: T, R; v+ x2 ?' x; k
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
    0 i  {0 y  i  k& ?6 j8 y6 M$ J
  132. * @return ERR_OK if the packet could be sent
    8 D) ~( \" a  B! U- x( ^
  133. *         an err_t value if the packet couldn't be sent
    , i# |1 E8 v' ^
  134. *3 S. P1 E) ~6 h  b
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
    - ?$ l4 B5 j. `3 H. O
  136. *       strange results. You might consider waiting for space in the DMA queue8 y4 `2 {* g$ i
  137. *       to become available since the stack doesn't retry to send a packet
    . {7 c; `! ^" F, a. w' ^
  138. *       dropped because of memory failure (except for the TCP timers)./ ]. W7 j! c  g  y1 p7 x
  139. */
    6 k# }9 R# W" F2 [2 y$ G8 Q4 N/ _
  140. 9 k( b' n' J7 f" I" C! ~
  141. static err_t/ W9 G) o, M0 @3 V9 a$ G$ Q: T
  142. low_level_output(struct netif *netif, struct pbuf *p)
    2 k! o# m3 b8 L* F
  143. {  j3 R5 z% {/ I
  144.   struct ethernetif *ethernetif = netif->state;
    + A. W/ v( s: i" Z2 L! v7 u/ {
  145.   struct pbuf *q;0 f" d$ Z. L' k; g
  146.         5 Q9 t. I; ~6 }4 E! S
  147.   // 添加的变量  c- h; @+ Y8 R' c
  148.   uint8_t buffer[1792];+ h4 E3 H4 _3 D6 t0 T4 \4 P
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;
    0 _( J: E9 [" U% s, l
  150.   uint8_t *bufptr = packet->payload;7 [. m' L) D0 ?; `' Y: f
  151. / Y$ l$ |) O* @: M% j3 }
  152.   //initiate transfer();/ h+ h4 t' l3 y; V* Y
  153. ' u9 \" J! T4 c0 \1 |+ `: g* p5 k
  154. #if ETH_PAD_SIZE, z: J1 r8 X! Z
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    % o4 a& ~& a  M4 A5 Y. V" m, ]
  156. #endif' A" _: h! ?* G1 F- r2 q

  157. 5 J2 H5 s* g" ?: H
  158.   for (q = p; q != NULL; q = q->next) {
      x# d8 c1 y4 m3 p0 l. D
  159.     /* Send the data from the pbuf to the interface, one pbuf at a
    / f( M9 P+ ?1 y5 s8 h3 V! ^
  160.        time. The size of the data in each pbuf is kept in the ->len" }  f: h1 `( u4 c, W7 w! e, f
  161.        variable. */
    4 e1 }+ R; r  [
  162.     //send data from(q->payload, q->len);; g: S/ u8 a3 p( o7 G: e# Q1 R
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容$ J2 _* r$ i/ ]" D) r, s! H( A4 j! w$ L
  164.         bufptr += q->len; // 指针前移" B) F/ u  {( b7 u& h* f8 R
  165.   }% c: z: x: o( [" ~( f
  166. , ?9 v- P# n* T6 }6 T( _
  167.   //signal that packet should be sent();
    ) x1 J0 v2 w* O/ C# G# w
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包
    7 g! z5 _& [4 E* c% [4 \
  169.   
    + \# u. p1 ^# F
  170.   // 打印数据包内容/ X5 ?3 D: w, Z" \
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);
    ( n+ ~7 a/ Q+ h0 L
  172.   dump_data(packet->payload, packet->tx_packet_length);$ @) J+ M8 G; D. H
  173. 2 g+ u: M+ M8 [$ i
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
    5 ]1 M4 X4 K3 p
  175.   if (((u8_t*)p->payload)[0] & 1) {
    8 U+ s$ [1 X5 L9 R/ n
  176.     /* broadcast or multicast packet*/
    0 M7 N5 ?, [, D9 S: k* I
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
    : x- E. E* F# n
  178.   } else {$ S! ^( G4 G3 T5 a) M7 p
  179.     /* unicast packet */- ?  a* S+ U# g# b) l, S, Z; r
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);  }+ s$ n4 m' N) c5 d# A. E- T
  181.   }7 t! `7 t, A6 y% y% t- ?
  182.   /* increase ifoutdiscards or ifouterrors on error */$ y& p  @( h9 Z, l* E* z
  183. 3 a$ C9 i: p6 n9 k( s
  184. #if ETH_PAD_SIZE9 g6 }5 v8 E, E: `% m& x- z
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
    % b1 Q% n; s# |* z. n" ~
  186. #endif
    0 v/ g: U5 ^4 @' X( ~  `! `
  187. / R# o& e$ Y+ E
  188.   LINK_STATS_INC(link.xmit);2 |, s, e$ z; _# D/ i& X; k) A; o

  189. ! I5 o, X( v9 t; x& m
  190.   return ERR_OK;% ]4 z6 G( n' X( x" k2 o) Z2 O! c2 F) ]
  191. }
    4 `4 L+ |% P  A/ O
  192.   n1 L& ?; u& M' k  Z! w2 n
  193. /**
    " N1 V" g+ M6 l' ?
  194. * Should allocate a pbuf and transfer the bytes of the incoming
    % W3 h7 y0 Q: ?
  195. * packet from the interface into the pbuf.
    2 }% _" d8 D" p" B
  196. *
    . w+ V2 ^, A9 F+ a9 i, ~* t7 X* w9 h/ E
  197. * @param netif the lwip network interface structure for this ethernetif
    " A: Z% v/ z+ i8 _* I5 d: W
  198. * @return a pbuf filled with the received packet (including MAC header)
    * U* L$ W; T0 p8 k/ y: r7 e# b
  199. *         NULL on memory error# }" B" h3 k$ X# l9 w1 W
  200. */
    # P% ]& M2 l2 A) _" c
  201. static struct pbuf *
    / A, b' H  q$ e0 }. q! p% ~0 d
  202. low_level_input(struct netif *netif)3 A1 E/ m9 J" Y) T) f
  203. {: ^2 T) E) P1 b3 W/ E2 m3 [: A
  204.   struct ethernetif *ethernetif = netif->state;
    6 }- s3 d0 T: |$ ^1 B3 |
  205.   struct pbuf *p, *q;
    * I7 v# t4 k) d/ I/ a& ]
  206.   u16_t len;
    $ u8 @. m' T! {/ a6 `/ t! B3 @
  207.         6 h; G+ M& z( M6 Y5 K& X
  208.   // 添加的变量
    " S5 _5 S) \" P+ w9 q! L
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完
    # t; w& R" s( P6 [9 y
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;! [8 Q0 o; S( @$ \2 b7 k
  211.   uint8_t *bufptr = packet->payload;
    " z$ t2 z9 a2 f1 Z' h! C$ B0 B
  212. 5 W5 E! [$ r( i* t/ g5 Q
  213.   /* Obtain the size of the packet and put it into the "len") z8 d3 F; |# O2 ?! S0 I% M
  214.      variable. */2 P8 g- J! o# Y+ A
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
    1 Y& _" e  t' p3 V, ^! C
  216.   if (len == 0)  `/ c3 \% r/ w  ]
  217.   {. ^/ @. [5 G$ w7 S3 q' S) x' P
  218.           // 若读取失败, 则不分配pbuf, 退出本函数- f8 Q  i" x: ?: _4 g/ D
  219.           p = NULL;+ p0 x( n7 {. C1 e" h
  220.           goto after_alloc;
    + y4 Y1 G( R. H2 S0 H, ~
  221.   }
    % j7 v, P) w! j. l' C
  222.   len = packet->rx_packet_length; // 获取数据包的大小7 w2 r. h8 U: }8 c
  223.         % O# Q' J; ]" w# }; f+ b
  224.   // 打印数据包内容
    & P* {6 Q6 ]. s' e% `$ j
  225.   printf("[Recv] size=%d\n", len);
    ( ^% @2 A" l- |) [! \! H+ ~0 n! J
  226.   dump_data(packet->payload, len);0 V6 |/ F  I9 N' i( _

  227. ! U7 A1 q) s0 N) o& t
  228. #if ETH_PAD_SIZE
    ! c  `5 |8 R2 f) E7 T% a8 U7 k
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
    0 x, G( `! f+ G4 p' I& e5 G
  230. #endif3 c, ?2 n& c/ n% T" h

  231. : z& E; S1 p& p" E3 g1 ~. f
  232.   /* We allocate a pbuf chain of pbufs from the pool. */) d- e- f% ^6 o
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);& g% r3 |- H4 d7 W
  234.   
    2 z; n- Z! k9 h# B
  235. after_alloc: // 添加此标记- i, m9 u3 z. }; I

  236. " r/ g" ^' h- M
  237.   if (p != NULL) {. C. }( W) G. @4 y; \1 Q
  238. - i  I  j5 L- _) b) R' l# f* h
  239. #if ETH_PAD_SIZE" i8 f2 j+ |& Y4 E  M  M7 S  }
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    4 ^9 U, k0 ?& G# l9 w3 C2 E+ [
  241. #endif
    8 d, }# {6 i2 V9 s* {$ q

  242. " h9 k/ M* z7 q! Y
  243.     /* We iterate over the pbuf chain until we have read the entire
    & w" i( h' m  X$ M5 G! B, q/ `8 S
  244.      * packet into the pbuf. */. W. ^$ U. G6 d5 n& i8 t1 F
  245.     for (q = p; q != NULL; q = q->next) {+ M7 `# D8 z2 {+ h& {( _
  246.       /* Read enough bytes to fill this pbuf in the chain. The5 _6 F  Q# o1 T2 f: x8 Q' x% ^
  247.        * available data in the pbuf is given by the q->len
    / r6 _4 z( ~! O: D! P
  248.        * variable.
    ; o1 Z. B. b: i& K: J( y7 n
  249.        * This does not necessarily have to be a memcpy, you can also preallocate3 Y2 t# c& k! i7 p7 }5 S, |
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
    " @) v, R3 `. E
  251.        * actually received size. In this case, ensure the tot_len member of the9 Y5 O5 t7 M. e9 ~3 }" u8 H$ F& p
  252.        * pbuf is the sum of the chained pbuf len members.: X# `1 ?1 T& k) }- A. E
  253.        */+ K/ h. {  u0 _3 C. T
  254.       //read data into(q->payload, q->len);8 ?. K( M7 g' ^) a8 g
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容
    5 q1 r$ L/ [2 [
  256.                 bufptr += q->len; // 指针前移! ?; e! a. ]- N, {) K
  257.     }
    & ~; T, z& h& z: o4 S4 {% v; ]6 M2 [: R
  258.     //acknowledge that packet has been read(); // 无需确认
    1 ?6 I, v" Q: m+ J9 M

  259. 3 e4 F7 r4 J4 D* ?9 y* ?' Q$ C
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    ( B$ J# X+ P( u
  261.     if (((u8_t*)p->payload)[0] & 1) {% G5 y0 Y; ~5 P- a1 G: ?$ p
  262.       /* broadcast or multicast packet*/! d( x2 [; O% d, ~
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);$ \) d6 |; v3 L' }% w- O
  264.     } else {0 V: x& U, S+ N, [) c* q& |  {
  265.       /* unicast packet*/
    $ {) C( G* e: @* O* G- J* y! |
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);3 `* G$ O/ |. N' w8 p' _1 Y. Z& s
  267.     }7 T2 J4 r9 J$ R( X2 E! Z
  268. #if ETH_PAD_SIZE
    0 u5 }, X5 V6 V# Y! k: v% k! |
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */2 ?+ V& ?7 l( a
  270. #endif9 e/ t6 R1 c1 Q7 V; m% y4 b. M

  271. 8 p9 k5 G5 F  P$ q7 Y. _
  272.     LINK_STATS_INC(link.recv);/ W' _9 _6 G5 l
  273.   } else {0 K8 `+ v/ Q% m0 Y% ?0 H
  274.     //drop packet(); // 注释掉此行
    ' N" |: i, l* G) d; O
  275.     LINK_STATS_INC(link.memerr);
    $ N4 ?" c0 N( b/ E$ Q" A+ W
  276.     LINK_STATS_INC(link.drop);
    " [+ T. @5 T1 B  d
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);
    1 p3 I7 _2 w% n* u9 n6 q0 R4 y
  278.   }/ W: L/ E& C9 F0 t
  279. - A$ ?2 b0 T1 J; f
  280.   return p;
    ; K" P! n2 Y. d* e$ H8 j
  281. }
    4 B0 O+ m$ t3 r+ D4 A+ l. ^% F

  282. 1 m; u4 h# n. [9 Y: E
  283. /**& a& z" O& l" m6 D
  284. * This function should be called when a packet is ready to be read% L& u( i2 f. t9 W8 O: b+ o
  285. * from the interface. It uses the function low_level_input() that
      D0 A& g& ^4 U" d( p  ^2 x8 a% J8 Q
  286. * should handle the actual reception of bytes from the network; f8 ~: q6 N5 Y
  287. * interface. Then the type of the received packet is determined and1 N. a" r& b; l$ g! Q
  288. * the appropriate input function is called.
    & g: o1 V1 x/ M  F" X, Z
  289. *
    5 o& j  e: {3 r- Y
  290. * @param netif the lwip network interface structure for this ethernetif5 i8 D- y1 ^9 G; p
  291. */( d' a2 }. V( @& G% R
  292. // 必须去掉static
    ! f9 H0 e# U( ~4 g: `$ d
  293. /*static */void* Z: Y0 r( l* h8 X
  294. ethernetif_input(struct netif *netif)! V1 G, }" P+ U8 W- }
  295. {; i# U+ v1 b) h+ B6 t
  296.   struct ethernetif *ethernetif;
    ! H" E# n  X6 g( Q! Q9 j. Z
  297.   struct eth_hdr *ethhdr;
    0 `3 I3 o; D+ U6 ^1 E; p( y) i4 N0 a
  298.   struct pbuf *p;" f/ q/ v% x/ p& x% P; M% o

  299. 3 X& Q8 O9 e. Z, r
  300.   ethernetif = netif->state;
    $ d4 |0 T: x/ V+ |! a. z. |

  301. ' D  I' q$ i* y. Y  X" @1 a0 |
  302.   /* move received packet into a new pbuf */
    7 K5 E& Q+ e3 _4 H* t& `9 Z) a
  303.   p = low_level_input(netif);
    2 k& _/ e( j* m5 h
  304.   /* if no packet could be read, silently ignore this */
    " |- U, p8 [! [4 T3 i
  305.   if (p != NULL) {+ c5 X% e! @$ n) s& w( q; S5 N
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */$ @3 k0 f4 u. d( o% l  Y
  307.     if (netif->input(p, netif) != ERR_OK) {& ~/ T+ H, R# r9 N9 E3 r# J
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    : E* h2 S4 ]& I! o# Q7 q
  309.       pbuf_free(p);
    , P& V0 |2 c+ S: T) ^" I
  310.       p = NULL;
    $ C/ k& H# ]- ~3 R( X9 _. C
  311.     }
    , J0 ^1 Z3 N+ }8 |
  312.   }
    8 A" V" J. A! F& [& J# Y1 q2 I4 e' J
  313. }
    8 M+ |. c& G2 m" f

  314. # `" A7 J7 r" F5 s8 P, I
  315. /**
    2 r" x$ m  V  [8 O# p. b2 j& E; e
  316. * Should be called at the beginning of the program to set up the
    8 w/ L* t6 t# F2 w! P$ ?& b/ ?/ |
  317. * network interface. It calls the function low_level_init() to do the
    / Q, T9 R. n, ^3 a9 p
  318. * actual setup of the hardware.8 c/ t: h& {& i0 K" i1 I
  319. *& ]' v5 D& V2 e
  320. * This function should be passed as a parameter to netif_add().1 X$ M/ X+ ]2 W5 G
  321. *8 Y4 l) s% t2 I1 o
  322. * @param netif the lwip network interface structure for this ethernetif0 @; H5 C  V- l( N; g! d2 x
  323. * @return ERR_OK if the loopif is initialized- u+ C0 a% f# I+ B
  324. *         ERR_MEM if private data couldn't be allocated
    4 ~7 S/ Z/ X: o' H/ a( \
  325. *         any other err_t on error
    & M5 ]* H& ?) x, M- B
  326. */7 g3 c3 d$ L. L# f
  327. err_t
    9 r; c& Y5 O9 D5 u, @* U: ?
  328. ethernetif_init(struct netif *netif)
    5 t* i# n4 }- e7 ^
  329. {
    6 I7 S0 `  m/ U# S& @1 Z. v
  330.   struct ethernetif *ethernetif;
    7 E7 l2 Z# v+ q  y, t/ [
  331. % a4 }/ k+ }; ~* i7 U$ ?% q' H
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));8 g1 f7 ~5 c6 r7 E0 r+ V! O
  333. & \1 `4 k. G3 r1 s; Z
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));) P8 ~# Y/ h  X& N0 {) a
  335.   if (ethernetif == NULL) {2 ]1 @! n0 Z. l! _/ [7 q  O
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));2 D) ^4 q) n3 w: H3 P
  337.     return ERR_MEM;' B$ G" s5 R6 ~, e: Z: U
  338.   }
    , T6 c3 M0 e' W2 A- F: k
  339. 2 L. s7 V, X( G( i6 ^* r, _6 }
  340. #if LWIP_NETIF_HOSTNAME' w# @9 J5 @/ u! J  E" [5 G9 p
  341.   /* Initialize interface hostname */; k  k! {; h0 {: g& V
  342.   netif->hostname = "lwip";
      E1 T8 E; W+ \+ X$ ?0 R! I
  343. #endif /* LWIP_NETIF_HOSTNAME */
    . {1 m" j& D& k$ a

  344. $ w' x! y6 [) V1 {) C3 C/ \
  345.   /*0 ?5 ^$ _  z0 u8 e. {+ D
  346.    * Initialize the snmp variables and counters inside the struct netif.6 \% f- j* r' ?1 S0 W; @
  347.    * The last argument should be replaced with your link speed, in units+ C; Q1 W9 z3 X1 t
  348.    * of bits per second.+ J7 B& K) a- P8 A# ]0 P" B
  349.    */) f. H+ r6 ]; E% l$ Y. g% U
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);2 \3 r$ a% E/ U9 F6 T
  351. # w1 Z! S: x3 o  Q1 b% d! m6 V
  352.   netif->state = ethernetif;
    8 Y" a5 Z$ m/ P9 _; ~3 X
  353.   netif->name[0] = IFNAME0;. d: V* s! c. L# K6 U8 a
  354.   netif->name[1] = IFNAME1;& X7 m' N% ]7 R3 j& ]6 A9 q
  355.   /* We directly use etharp_output() here to save a function call.
    , t: C& X, L. P/ a1 f3 P# u: A* }
  356.    * You can instead declare your own function an call etharp_output()9 l9 U, s( X8 G7 G, V
  357.    * from it if you have to do some checks before sending (e.g. if link
    0 ^) ?! O  w9 b) S
  358.    * is available...) */
    5 W+ C9 R; i% [+ D8 S9 l; g
  359.   netif->output = etharp_output;
    # M3 o+ P: }2 `! R7 t
  360. #if LWIP_IPV6! W( _) Z( w7 u6 i9 q
  361.   netif->output_ip6 = ethip6_output;* f& R- l. |$ V3 x" S
  362. #endif /* LWIP_IPV6 */( c' A3 C, H: D' V
  363.   netif->linkoutput = low_level_output;
    , {! T1 u4 z0 a
  364. , G9 b+ k; x6 Q+ ~+ N& Y
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
    9 A4 C. Z$ J, o5 \7 Y/ R

  366. " {$ ^8 U. w$ P: _/ M2 V) U
  367.   /* initialize the hardware */$ F6 d& o, b, |8 L" v8 m
  368.   low_level_init(netif);) B6 i! b- M3 A9 C$ z' ]1 {
  369.   I; B5 e5 r' w7 w; W
  370.   return ERR_OK;
      ~% r. N$ C: C( ?6 v
  371. }+ _, @! J) ~# s( O1 b
  372. 3 o5 s) g2 c: E2 \! ]  n
  373. #endif /* 0 */
    - L% c/ E/ R3 I8 ?. w, r3 ?, }. E
复制代码

6 Q! s; N/ |- w在项目属性中,设置Include Paths为:.;.\lwip\include
* Z/ C1 h- U' V9 h- h其中点表示工程根目录。
0 U6 A$ i7 @4 z: N: m% F
# ^  U; H0 |) s. t7 q3 y4 c$ d另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
# \: M. z% W8 }" q. l  o6 i7 y2 H
! L# @! {1 W( |# e6 F! X编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
% N, y: |* C7 l电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。, S+ h; \8 l: G% h; V" J2 B1 A
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。/ e& @* S" R3 ^$ Y; P2 |5 d

评分

参与人数 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....
* G0 q0 e6 J( B  X8 U  }- g9 s  j% [! U( j9 o. z- {5 w: ^
多谢分享
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 手机版