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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE
" |7 }) z# d& ]  U: TPB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。, G1 |  t4 P% A/ V" c/ ~0 S
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
. X- Q3 |/ o: q% a+ A% P' i该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。* _  B- ~5 d6 ^& r/ u0 }
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
" z( M7 V  ~9 G0 l5 Z/ E- Y1 v8 B& ~" M
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!& s0 \' \/ j7 C+ }
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】
: ^0 [  g" u1 D: e# l
  1. #include <stdio.h>+ P0 [+ T! d6 K7 h4 @6 ~
  2. #include <stm32f10x.h>0 n9 ]/ j+ Y: p) I1 p
  3. #include <string.h>8 b8 j$ t. J' @* I4 Q3 M
  4. #include "lwip/init.h" // lwip_init函数所在的头文件) X, b' h* d1 ?0 p
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件. a; X$ e: \7 I+ K5 `; X5 Q/ H* O9 {% J5 o
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件& O& c8 B2 @9 l0 @; u4 c( O8 B
  7. #include "WiFi.h"
    6 E, ?% j$ n% Y/ [  V- R9 O

  8. 5 k) I5 Y/ `+ m: y4 u6 q
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明) q0 Q9 k# i. y* U3 Y9 p+ l/ d
  10. err_t ethernetif_init(struct netif *netif);. k8 P2 Z2 }8 F# c8 {
  11. void ethernetif_input(struct netif *netif);- I& ~6 C, g+ N. ]# O7 }4 K
  12. 7 i. ]: D" z4 A( W6 k
  13. // httptest.c中的函数6 z, z6 D  u3 ]0 n/ ^* o
  14. void init_http(void);) o# q, `# p; ]
  15. 6 g3 s0 I$ |" D8 V6 e. @
  16. // 延时n毫秒. O& j3 o$ ]- y5 {9 A
  17. void delay(uint16_t n)
    8 O$ F3 H% \0 d
  18. {+ f+ y. v6 j6 G0 v% g
  19.     WiFi_PrepareTimer(n);
    9 T. v/ w% N3 q0 G) J5 y9 `
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕" ^( ]8 J4 {! R2 e+ m8 {
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
    * M( K5 ^: d+ x1 U) h' w5 W
  22. }6 \. ^* z" J4 [9 \( y3 }
  23. - Y0 [) j! W( [7 T
  24. void dump_data(uint8_t *data, uint16_t len)' M: Q& S+ {/ z/ C8 A
  25. {( v! I5 H- x# M1 e% N0 V& d
  26.     while (len--)
    $ R) _4 G3 h' W$ r- I* c$ j
  27.         printf("%02X", *data++);" G& n1 D$ L( i9 W; [
  28.     printf("\n");
    8 C' m! P3 t0 `
  29. }
    9 t6 ^0 ?* e, p4 X6 ?) ~! ^
  30. - K  R/ C4 A' F# h& a
  31. int fputc(int ch, FILE *fp)
    ; n5 C, X0 j( G; ~- L
  32. {
    / x6 Y0 l. C7 D- ~6 ^
  33.     if (fp == stdout)& Y9 E7 U3 k' s3 E: N/ L; a3 p
  34.     {- C5 U0 k! k" q& H$ T0 _
  35.         if (ch == '\n')/ Q8 |+ e3 U; _$ V" p0 M0 e& U
  36.         {
      L/ D1 c$ Z3 [9 X2 h& i
  37.             while ((USART1->SR & USART_SR_TXE) == 0);. G( W3 n% V; ^  _: l1 p
  38.             USART1->DR = '\r';
    9 D" _# }- n; e  G4 `
  39.         }
    ' |2 D: ]- Z2 J, y
  40.         while ((USART1->SR & USART_SR_TXE) == 0);& ~$ g' S& O9 K8 P
  41.         USART1->DR = ch;
    0 S8 k0 Z6 }2 _. [) b8 `
  42.     }  C$ ?+ z! {" T0 m+ [" {
  43.     return ch;  e+ c4 q) [/ A& z. H$ x
  44. }% c, w% U5 X0 @
  45. ( Q: u( u, x0 E0 ~8 _7 w5 }
  46. // RTC时间转化为毫秒数; K4 d+ q% P- H
  47. uint32_t sys_now(void)
    " D/ ?4 l7 R, x$ x. ?
  48. {
    - ?( a& ]$ }! \
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒0 a, ]$ o4 |. V- G
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒) K& w1 F7 s& K4 E
  51.     return tmp;! `9 a! \* A! ~7 [! z1 f
  52. }6 J9 w3 E/ ?6 z6 C: m1 O' a) R. _1 z
  53. ! x# N+ C8 h' I0 O# }; a
  54. int main(void)" G( I2 _- e' Y/ D0 @! A3 m
  55. {7 q7 Y- R' G. Z2 i; S& j
  56.     struct ip4_addr ipaddr, netmask, gw;, ~" N# V  r5 n/ ^
  57.     struct netif wifi_88w8686;' e  R; z% }) E! m2 Z$ a
  58.     uint32_t last_check = 0;1 o$ o% o2 b+ V0 k! N- ?& u* F
  59.    
    2 i  a% G9 u/ h
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;
    ' S/ E6 I$ C4 W" E0 E
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;4 @) u& L$ d, W# J9 f6 @
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;9 D. h9 K) x9 W/ L; R7 R
  63.    
    , L4 a" c: O% d  s
  64.     GPIOA->CRH = 0x000004b0;
    2 F$ _+ I2 c6 {$ Y- {* L
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块
    " e  h4 a0 o6 y3 R# C- V
  66.     GPIOC->CRH = 0x000bbbbb;
    6 ?& a8 [. G3 s. H& L$ G
  67.     GPIOD->CRL = 0x00000b00;
    , l0 F0 D- o- m5 P/ x6 q6 R
  68.    
    + y/ S) h- Z- r% x5 L  j$ P6 ~
  69.     USART1->BRR = 0x271; // 波特率: 115200
    9 G+ M7 n0 U% z; T  t+ n
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    % G$ j* q, _) Y( m; p
  71.     7 q% f( q5 Z; K9 c7 M4 u! E: V
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器' Q; H* e5 W4 F
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)
    5 p, O8 H% C2 i) l+ ~
  74.     {/ l4 y; F1 q* K1 }* C
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI$ L7 y. O+ l5 o( q" X" f- ~
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
    3 n& m7 h  B1 S; R2 K
  77.         //printf("LSI Ready!\n");
    # B" D. [$ j8 \0 H' u6 M1 t
  78.     }
    & G/ Z3 {8 q5 X; B; k7 R) D
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)
    ! G% [" u' J$ G% x/ f- ?
  80.     {
    : L! ?' j  _4 {5 Y2 D, R& G
  81.         // 若RTC还没有打开, 则初始化RTC
    & r9 D0 p3 @4 E8 W% N2 N, {+ l9 V
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时- F/ g6 R  o( X( Z; U3 L1 I
  83.         
    ; }0 I  V6 U  |9 L; e
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式: Q. W) U) D- H4 t1 A
  85.         RTC->PRLH = 0;
    5 t7 i6 d9 I5 ^. Y! }- z0 r
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)# Z3 B6 C( y" o7 n. E: m, z
  87.         //RTC->CNTH = 0;+ M9 t* v$ {8 q& p3 l* Z
  88.         //RTC->CNTL = 50; // 初始时间
    ! P9 N+ S) e& O: e
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置/ G. K$ S3 s+ I. d
  90.           c7 C" A/ `  ?7 {" k( w& h
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时( x) \4 X4 O5 u
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效: n; ^; C0 x9 t5 L1 |/ P. p3 O( {
  93.         // RTC从此处开始走时
    6 N3 J# `( Q+ x: T2 z1 o6 O
  94.     }
    , a1 }( r9 e' R& T- [5 t4 S
  95.    
    / A, Z/ `7 d5 B4 v$ F1 N, O% M
  96.     WiFi_Init();
    9 |) T3 ?' Q1 t5 h7 }* x
  97.     WiFi_Scan();2 B9 O, U" e+ L+ a) [: |
  98.     5 V  C# ?) q, k7 E3 O
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点6 @& z" b) V  U, t0 ?
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    9 Y3 K/ r7 S4 w- |! ]1 i! _0 J: K
  101.     8 s; M1 i  p2 k! k1 V. e
  102.     lwip_init();4 U. F; O- j  B7 R) Z
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址
    % W) B0 j5 C) V/ P0 v, c, N' P
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码5 \+ l% b# ~: V/ p1 x
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
    * B9 u% o/ T8 p
  106.    
    - _# ?+ y1 O1 m3 @& F
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    $ }4 J  L3 V' N5 b
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡/ b' r( z# l3 N  U  {( _& \/ A
  109.     netif_set_up(&wifi_88w8686);
    0 i/ l5 X7 W. r
  110.    
    6 Y  P4 G2 U0 Q4 ~# v, P8 M/ ]
  111.     init_http();/ ]# W: W0 ?) R# L, c6 E
  112.    
    9 w/ M: q. L8 w* j# P, F! J( t" N
  113.     while (1)
    8 L; B& Z4 P2 p8 e
  114.     {
    ! i: e2 f/ \$ r: d0 y
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())- D. A/ D3 O3 P, f0 e* z
  116.             ethernetif_input(&wifi_88w8686);% G% \- d6 S! f3 k" j+ Q6 t8 R% _
  117.         0 W5 G- u: c9 e: v6 w! `" X
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址), _' M; g% ]$ p0 i2 \6 x
  119.         if (sys_now() - last_check > 200)' Y# O1 v; V4 G3 E9 D
  120.         {. G" f# w! }( {3 u. D" x0 l
  121.             last_check = sys_now();' X* L" u8 t; u0 f) X+ \
  122.             //printf("Time: %d\n", last_check);! h6 y8 n2 s, ]1 p% Y6 |! _
  123.             sys_check_timeouts();- i* t5 I$ k3 \9 f: p* y7 m2 T5 N
  124.         }
    + h% q  E6 v- \4 P5 ^
  125.     }
    ; b7 B7 T& v- E& X+ Q
  126. }
复制代码
【httptest.c】
! ]9 h4 B( F% K
  1. #include <string.h>
    : w! ^' n3 K/ g* _1 u
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件
    # g5 Y  t% T' H
  3. . d! V( T9 s- a' \4 F' o5 \0 z
  4. #define STR_AND_SIZE(str) (str), strlen(str)
    7 ]# C+ L2 I! o: X
  5. ) V; K: h, \- j% `
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
    6 t+ K, a3 P* T" u
  7. {
    , _7 H& r6 ^+ M* I# P
  8.         char len[10]; // 存放HTML内容的长度
    ' D5 o3 y: E  [
  9.         char str[200]; // 存放HTML内容: O7 T' Q  U# Y! h* w. ~" r
  10.         
    7 r; |9 X; a: a3 e1 ?
  11.         char name[100];9 K7 b, G4 e1 _$ _; a
  12.         char *pstr;
    3 Z4 \) b1 T9 H
  13.         uint8_t i = 0;) X( s1 v+ p4 @" ?% ^- a/ [) T
  14.         if (p != NULL)) o3 @! i* \% t& y* N6 b2 m
  15.         {
    " N2 l& z; a" N# S2 v" G
  16.                 // 提取页面名称1 q8 J) a+ x8 V* A! e, N: M0 f
  17.                 pstr = (char *)p->payload;
    9 e6 N0 _5 t$ X1 C  r3 p, F1 c
  18.                 while (*pstr++ != ' ');
    9 k$ @. y7 K* p' m, Y  t; z( z
  19.                 while (*pstr != ' ')
    & H% J& z6 P. |' |7 z* D# V' d
  20.                         name[i++] = *pstr++;1 Q) {5 ^# h& ?! ]
  21.                 name[i] = '\0'; // 不要忘了结束name字符串
    , j3 _+ y5 }! \' @  _1 P1 n
  22.                 tcp_recved(tpcb, p->tot_len);
    4 N4 W6 p4 I3 n! @9 s
  23.                
    . Y+ P) g$ ^  M  P; D8 |
  24.                 // 生成HTML内容
    ! p2 b8 n1 P; z* b1 t3 O$ ^! @; Z
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);/ L' v1 S3 ~; |: Q1 _5 N( d: L
  26.                 : s: G" k' U5 _4 G, {
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度& a4 U) w; z% c8 x  d, {, ~
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
    ' C; z6 G% j8 @4 U' X8 `& _
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);) e% Y- Z7 |' T4 v. A- _6 z
  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);% r' ]: |! H* q  p8 X6 L9 v
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容- _* ^- z9 p1 a, ?9 i: K
  32.                 pbuf_free(p);
    : c" J9 m* x/ d% c, ]' h
  33.         }
    9 F0 @" t: ?0 ^9 A& U  C
  34.         return ERR_OK;/ ~$ p: l5 T) Q1 k
  35. }
    ( v/ F! [+ j. X/ n8 T/ F

  36. , w4 R- A2 |" U8 x! c( P1 H! E
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    ) n- Y2 V1 B6 T- f% f! n' |
  38. {
    , E* r5 T# r5 ~- a3 F% M8 z# R" V/ ?
  39.         tcp_recv(newpcb, http_recv);
    ! Y  M( n$ V4 p0 N! b: F
  40.         return ERR_OK;
    : G; X8 A$ @3 m3 E  M  _  j) Y: B
  41. }
    ' D. P9 f8 F* h% ~

  42. ' G# ]7 d& O3 K* Y. a! h4 e
  43. void init_http(void)
    4 i0 V9 ]( T) d
  44. {" @4 u3 E5 V3 r1 @1 I
  45.         struct tcp_pcb *tpcb = tcp_new();
    7 B) r4 x  ]+ x! V6 k! m2 j6 }& s
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);8 t( `5 Z2 ], ^# i
  47.         tpcb = tcp_listen(tpcb);
    % [6 j$ w: F! U% q9 u7 v0 K
  48.         tcp_accept(tpcb, http_accept);/ R9 g/ p- D! c3 z
  49. }
复制代码
【WiFi.h】
: o& P( D- x, q& `" V
  1. #define _BV(n) (1u << (n)). k8 R/ u5 \5 t( S+ M( e2 o
  2. 0 c# p4 K' q/ t& j/ O
  3. #define CMD52_WRITE _BV(31)
    8 U8 S' B4 T4 x, h. Q% }
  4. #define CMD52_READAFTERWRITE _BV(27)
    ; \4 Z0 V: F7 }

  5. 1 k* N! _. i0 E2 Z. N8 w* ?3 ~3 N
  6. #define CMD53_WRITE _BV(31)
    3 |: v) }2 Z( g) P; O
  7. #define CMD53_BLOCKMODE _BV(27)
    1 \8 u5 |6 D3 w0 v& q* P$ ]
  8. #define CMD53_INCREMENTING _BV(26)8 f! r: g: [1 }4 B4 N& Q2 L
  9. 3 r( H$ G7 a1 ]
  10. // 16.5 SDIO Card Metaformat
    / \5 g8 @0 q2 `2 E7 t& D) I
  11. #define CISTPL_NULL 0x00 // Null tuple, H9 B9 F/ J6 d! c
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information* x4 I/ v# z1 d- g
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    + e% M. B3 S/ `; c
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple" o* C" W  x4 [# K) u( |$ e8 x
  15. #define CISTPL_FUNCE 0x22 // Function Extensions: |" E) v5 t! m+ W
  16. #define CISTPL_END 0xff // The End-of-chain Tuple: p/ Z- I8 a" [! f

  17. + g' r, @; r9 F( b* {+ B
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)
    2 @; X. H' j* L. q9 |% b& B
  19. 2 F. z: H- m% }! S, q, `7 i
  20. #define WIFI_SQREADBASEADDR0 0x10
    % X% Z8 i4 i8 K" m4 M/ T
  21. #define WIFI_SQREADBASEADDR1 0x11& D; N2 t7 A% V8 u4 Q
  22. #define WIFI_SQREADBASEADDR2 0x126 y7 T4 U: |. U/ L, J
  23. #define WIFI_SQREADBASEADDR3 0x13
    . @2 X4 F/ {$ B2 k! Q
  24. . q- K' O& R6 t8 |- v, L. X$ b8 K/ G
  25. #define WIFI_CARDSTATUS 0x20 // Card Status
    & r2 R- x% U7 P, e+ s/ l
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator% V/ }* l* C. x( ~" Y  I( _
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    ' D* W6 l: b" f
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready# Z4 @% Y! l- n1 L- {6 m4 r
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
    2 q  Q' l- c; G' y! S; X4 i

  30.   p0 g! S9 ]* `& j% k
  31. #define WIFI_CAPABILITY_BSS _BV(0)0 M0 s1 M4 \- W0 E
  32. #define WIFI_CAPABILITY_IBSS _BV(1)
    ; K; b3 u% ^" i( {  l
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)
    4 a: u6 D! G4 k
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3), v6 L; M- C& r
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)8 C2 N+ @( o% D  v
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)- ~* V" S1 X( v
  37. #define WIFI_CAPABILITY_PBCC _BV(6)
    5 @( `" |8 x; [6 d
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)' M4 c4 p7 O# g7 d, r
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
    ! d" d4 J0 H& L  A7 F
  40. #define WIFI_CAPABILITY_QOS _BV(9)
    6 I% c4 m/ [2 a* D* }& `' F" _
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)
    3 s2 k3 }% _3 ]- u
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)% H7 s  h3 Q8 t2 e
  43. 3 N9 m) ~- U0 S! L: U
  44. #define WIFI_SDIOFRAME_DATA 0x003 J( y' N6 w3 j8 T4 V8 t% P
  45. #define WIFI_SDIOFRAME_COMMAND 0x013 f- d0 o5 t$ N  C* z+ D
  46. #define WIFI_SDIOFRAME_EVENT 0x03- `1 t/ T0 }; u1 u) b3 z. f0 z

  47. + S) ?9 N( @& K/ e6 u  b
  48. /* Command List */
    ' L6 n8 i5 A& t' E# r+ f
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    1 [# G: J2 @; ~" s! \& M
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP/ H$ F6 b4 m$ W  ]3 R+ b- x! s
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
    ( x9 Z. J/ X5 r# W4 `2 l7 t4 K
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network+ L. @- T& I, b* M1 Z
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address) n5 X- l9 Q  k' l0 S- K6 w$ k, r
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption
    9 m( g8 w4 e5 T6 e$ `1 h
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
    2 G5 R  e* }; I, D* Q
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results
    0 A# A# X/ p5 y' X! P) C

  57. 4 k" J' Z% G" M. W: G
  58. /* Command Result Codes */
    1 n& I' t8 i1 t1 N& X  X4 N
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error" I0 L, v: v6 I
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed
    " X8 {" Z# h: g8 p$ ^1 s% u
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported
    6 A) V$ C6 ~# n& ~2 A

  62. - J: F, H$ R0 {* a* i& G; n
  63. #define WIFI_ACT_GET 0
    * {, g+ |' }& A8 [# h: p" A" B  v
  64. #define WIFI_ACT_SET 1
    ( w4 M8 i* s9 t6 X' g
  65. 1 {0 {# F* g1 o1 X
  66. /* Authentication Type to be used to authenticate with AP */- ~' Z1 L( g3 C" L, P- g2 G/ T
  67. #define AUTH_MODE_OPEN 0x00$ T) D) S! W  u3 O) I
  68. #define AUTH_MODE_SHARED 0x019 j+ I) Q; y1 [$ |
  69. #define AUTH_MODE_NETWORK_EAP 0x802 y0 N) y9 R( U
  70. " U- ^& }9 N/ P6 Q/ y( O7 _$ I' I8 e8 J
  71. /* WiFi_Associate return value */% s' R; o. p6 }1 z: x0 d8 {1 Z" w
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe  ?# T9 C( V1 m2 l% a* E5 \
  73. #define WIFI_ASSOCIATION_ERROR 0xffff" S0 m# S3 K8 h! B) @: e* ~
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功
    - U. E8 g" o; s/ L
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101
    ' n! H: {. V0 e# A) R8 k
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧- G* s" Q  i9 C5 x
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213, i% T  Z& ~! k/ E
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
    7 }3 B9 ^/ S: [7 @$ q* Q2 n
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败/ O( n- c/ K' u
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时$ p2 |& U$ z' Q) U5 t* x- s6 `
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时6 v* b5 M1 q+ T/ v
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时
    $ i; i  \. a) g* `# [# F- }/ d# U
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时7 S1 v+ @( M4 M3 M5 `- E8 r0 e

  84. + e# R6 W$ P( @- Y$ V/ w8 a" O
  85. #define WIFI_KEYTYPE_WEP 0
    2 V1 I# s! P5 q8 q: F6 c
  86. #define WIFI_KEYTYPE_TKIP 1
    # i8 T9 [0 T$ {1 ^' s
  87. #define WIFI_KEYTYPE_AES 2
    ; f  P! d! Q0 i8 H6 J0 Y# d

  88. # i: G: a3 `. o- u4 ]
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)* l3 D7 m- A  J' v+ V
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)
    , p2 z! u* ]' w. D4 I0 R
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)
    ! d. i+ _1 C- d  {
  92. 9 _. p% ~# F; V6 j) a- ]
  93. #define WIFI_MACCTRL_RX _BV(0)6 B; @0 Y( n: u, O0 k
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
    9 J7 z2 m& [: k! U
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)! {- B. ^6 b3 D, @" O
  96. #define WIFI_MACCTRL_WEP _BV(3), d" [! ?7 Q' w% I' u6 \
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)
    $ a+ T$ W, O5 U0 Y# Y& [  |
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)
    , h: ^9 F3 l8 i9 g( x8 }
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)
    + q. C  [+ h; j
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection
    % \$ j$ g/ _( r! K  G2 p5 j
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode' Q3 C  f- q( Z) z  R5 h, _# L
  102. ( V! x; e9 s* R4 @, r9 I, m
  103. /* BSS type */2 h; o5 w0 {% ^# v$ g1 ~" R
  104. #define BSS_INFRASTRUCTURE 0x019 k, Y( P3 z- Z6 a" _# V0 a* x
  105. #define BSS_INDEPENDENT 0x020 q# [; S3 j+ a6 w8 v
  106. #define BSS_ANY 0x03) Q9 t7 g1 r' |$ j, j% V

  107. ( p2 b" G2 z' M! u
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */
    3 {  I% x+ g# c7 U. z1 W1 Y: P
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */  W3 Y  E/ T5 u6 }; H1 o) n
  110. #define MRVLIETYPES_SSIDPARAMSET 0x0000
    2 w1 T* g* Q8 K' t+ k+ B1 _4 q
  111. #define MRVLIETYPES_RATESPARAMSET 0x00017 Y* ]1 d. W- B
  112. #define MRVLIETYPES_DSPARAMSET 0x0003! B, h+ L. E7 `2 l0 _
  113. #define MRVLIETYPES_CFPARAMSET 0x0004( I- J1 X, I, N, {
  114. #define MRVLIETYPES_IBSSPARAMSET 0x00062 O! p* [! Z1 u. A2 M3 U; l* S
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030
    1 U# L4 x  @+ F) W& A( h) p- s5 ~
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd
    - P; Q: C8 `4 ]2 O/ c2 i, p1 E, |. ]

  117. 0 P; u+ O5 R9 ?* v2 g4 J
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100: j$ v! p$ \; m! U, r2 _- c8 R" }6 D
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101% n" \! W5 |9 Y  B( D0 Z- |0 d
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x01135 y# [) E1 T% d4 I# H4 A
  121. #define MRVLIETYPES_AUTHTYPE 0x011f( P! |0 j6 r9 a+ F! y: ?
  122. 2 R! Z  f' W) O3 _
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小
    9 v( @+ o' v7 |8 H
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小; {1 V7 d( U6 O/ I( O) \! [
  125. & M4 R4 j: d: p0 o0 e; S. h
  126. typedef __packed struct. U# M1 c6 l3 _
  127. {/ f; c2 D6 I' t: Y& r6 t
  128.         uint8_t type;8 c$ H  R% J. S  z2 E
  129.         uint8_t length;! O8 N+ Z: H3 F2 J# [
  130.         uint8_t data[1];
    , g3 s: z/ Y$ y2 }" R" o9 {
  131. } IEEEType;( b) @, i$ u8 O2 S9 ]
  132. ' ^; w# H8 S3 b- _0 L+ w
  133. typedef __packed struct
    * {3 T$ e& w1 j8 ~, f# B
  134. {
    8 J0 p3 ?7 f; e# T" N! \
  135.         uint16_t ie_length; // Total information element length
    4 E) b3 p& Q' {$ P4 N) J
  136.         uint8_t bssid[6]; // BSSID
    * j& N! l# I4 U
  137.         uint8_t rssi; // RSSI value as received from peer
    9 z8 L* U" O9 B3 |* R
  138.         
    ! Q& M, z" o/ w
  139.         /* Probe Response/Beacon Payload */
    4 g% t3 C3 y+ `9 Z4 W+ l
  140.         uint64_t pkt_time_stamp; // Timestamp+ ]: z5 l: B+ y# s0 y! N
  141.         uint16_t bcn_interval; // Beacon interval- c3 G* t0 [/ h. y6 h1 E9 ?$ h# W
  142.         uint16_t cap_info; // Capabilities information
    6 s) h4 Z) Y+ v/ H2 \1 L
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据  v( k9 Z* _( B% n/ n2 i
  144. } WiFi_BssDescSet;0 m# e5 A* Y6 ^4 o- q# V" Z

  145. / C: V% u/ b- n% c, k3 J
  146. typedef __packed struct
    % u/ ^& G6 I) H& E
  147. {
    5 R  T, r9 x8 w* X
  148.         uint8_t oui[3];
    # U' u. Z- \1 W4 P5 V/ }
  149.         uint8_t oui_type;
    5 `; r0 z4 w, {3 O7 }
  150.         uint8_t oui_subtype;7 R/ s# b: m% S( r
  151.         uint8_t version;: i1 x- y; t, p( N2 N* U
  152. } WiFi_VendorHeader;
    4 r( y. V. j1 [& Y# a
  153. 8 s+ _4 i% R) ^, S/ m
  154. typedef __packed struct3 N+ e+ ]( {* s2 i
  155. {
    ( H0 v4 ], l4 N% f  }
  156.         uint16_t type;$ x, C7 H; \  P+ j- y4 o0 @3 h" a
  157.         uint16_t length;8 \5 O3 k2 c0 z# H9 f" {2 d" E6 J
  158. } MrvlIEHeader;/ E- L: C* A3 w& T! Z' l2 `# E

  159. 3 X. d- \/ ]  k6 T
  160. typedef __packed struct
    ; S7 v, U7 n2 x
  161. {2 q+ \1 J7 G8 M. q# {% T
  162.         MrvlIEHeader header;
    2 F, g$ V  U* ^! |, F# \. L
  163.         uint16_t auth_type;7 k" a1 _) [& ?# V, @
  164. } MrvlIETypes_AuthType_t;' c& R/ S# x  m' x
  165. 6 ]! y1 S, O% S9 \! z6 f
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec
    & j. q) g( G# r, R
  167. " p: J0 E+ d5 k+ E
  168. typedef __packed struct2 h/ K6 j3 z7 ^+ C) j# g: t
  169. {
    ( V1 b4 u: ?: J7 o" v0 t/ Z
  170.         MrvlIEHeader header;6 b1 W$ r7 ?& z( X- M
  171.         uint8_t count;! v7 c$ w; K9 |4 f9 m, ?
  172.         uint8_t period;
    : H' f5 w4 ~. b) ]2 `4 S# w+ t
  173.         uint16_t max_duration;" t- @# M7 C. k, o: ?# W0 B( c
  174.         uint16_t duration_remaining;+ L1 `. v. y3 {' Y, n
  175. } MrvlIETypes_CfParamSet_t;/ M9 I) l! f( e0 }0 X4 ]! T

  176. * U+ n- a# g7 Y3 B0 f, q
  177. /*typedef __packed struct* D( _- r7 }' O  y' H* c( O* p& z5 c
  178. {
    % F" d# X8 F5 b; {  I. @! W0 d
  179.         MrvlIEHeader header;# b0 L7 z* b  Q  L6 k6 L
  180.         __packed struct9 r/ q; U1 N. h& z1 ~
  181.         {' C& q) t5 F  \) e' A
  182.                 uint8_t band_config_type;
    3 s( ~, I- _7 k. ]. L3 {2 {( q
  183.                 uint8_t chan_number;: v$ k/ ^; U- a' w' ]  E
  184.         } channels[1];2 \; [/ S! ]2 h. {$ A3 D8 Q
  185. } MrvlIETypes_ChanBandList_t;*/
    1 a6 f* T2 N' u3 V" D

  186. & J3 M" l9 [' {4 p
  187. typedef __packed struct  P* w* y& \5 I1 {6 {
  188. {  r; I, W; Y" `3 a; i5 ?5 V
  189.         MrvlIEHeader header;
    7 J9 t2 i$ w6 I  V5 }$ R0 u
  190.         __packed struct0 N5 M, \7 p: w: _
  191.         {
    + K2 {: G7 Q9 m: m: z) ~. k
  192.                 uint8_t band_config_type;
    7 [) `9 L2 G9 F8 _7 d# r
  193.                 uint8_t chan_number;
    " ^3 o0 @3 e2 E- \  q# z, U! d! K
  194.                 uint8_t scan_type;- S* L# n) g; m- _, I7 _
  195.                 uint16_t min_scan_time;
    1 k; ]/ {( J# S( W
  196.                 uint16_t max_scan_time;
      `0 W5 a. {% {0 Y
  197.         } channels[1];! H  o3 ~  C2 P% I. u, I3 h
  198. } MrvlIETypes_ChanListParamSet_t;- Y' J% N& B5 i2 d- Y2 z! t) x

  199. 7 z8 D. E1 @) A  j& c
  200. typedef __packed struct
    2 Y) B! \: ]3 v, H2 p0 p
  201. {- z9 X2 M5 `8 J# v# N" h
  202.         MrvlIEHeader header;
      g) K2 @' f  |; Q! i; g
  203.         uint8_t channel;
    4 F; F4 Y& D: ^. e' ~$ m  J/ ?# [: K+ i
  204. } MrvlIETypes_DsParamSet_t;
    ! Z' w9 k+ B9 d# {
  205. $ l( s1 I% K; H8 m) O6 d& y
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;: }9 R5 O! S% |6 E  E3 h) w, j
  207. & k$ V* C! G9 B$ m% z4 C
  208. typedef __packed struct
    : t) Y/ e# k  u
  209. {) b" s8 x( j# q4 g4 {( m6 a
  210.         MrvlIEHeader header;* u1 L) H: G' i6 Y$ B6 Z6 N
  211.         uint16_t atim_window;
    ; i' U) u; [1 r/ R4 x3 G% U
  212. } MrvlIETypes_IbssParamSet_t;
    ; r% P! t. A& d& z5 `3 y( s
  213. . h, G8 z5 ?  J
  214. typedef __packed struct
    + D- i0 M0 F' K0 t
  215. {$ F$ A9 d! f* J4 S
  216.         MrvlIEHeader header;% b7 G, C% p$ o
  217.         uint16_t key_type_id;
    ( S/ m0 N2 j4 ~* k; {8 A# t* G7 H
  218.         uint16_t key_info;) [. X! |5 j: O' Z: G
  219.         uint16_t key_len;
    , m) \$ U% U/ U7 O+ L- O# |
  220.         uint8_t key[32];0 \. P$ q) W' C# _: }  g- u$ S
  221. } MrvlIETypes_KeyParamSet_t;, S: r" ^& S6 C8 H

  222. 5 `* k# z1 c- G/ q; }+ i
  223. typedef __packed struct, c4 Q* L; P  B1 {5 j) @
  224. {6 e* Q( Y6 n/ ?9 L6 M( K
  225.         MrvlIEHeader header;' e/ v' n; a# D- x) k
  226.         uint8_t rates[14];
    ' m: R( U( P5 c
  227. } MrvlIETypes_RatesParamSet_t;
    - ~- ^2 \. T+ L, f+ M
  228. . K+ i/ W' g; Q2 z0 g; m/ J
  229. typedef __packed struct
    / f  r. g, R: v8 I! ^, K5 J5 l
  230. {2 i: f4 d; O0 S1 t6 s6 K9 Y
  231.         MrvlIEHeader header;5 r) S! t# M( W* z$ Y# \
  232.         uint8_t rsn[64];
    0 z4 ~+ R, d" g% T% ^
  233. } MrvlIETypes_RsnParamSet_t;  C. o- B0 ]2 F! A" K7 K8 q
  234. , q: c4 Q* I4 {) v
  235. typedef __packed struct# K8 R5 g3 u4 L1 B+ B
  236. {0 V; Y# p( Y: o2 B: {* Q
  237.         MrvlIEHeader header;
    % ]0 H* Z' n7 \
  238.         uint8_t ssid[32];
    + {0 I7 |3 S% w4 o" I7 `! c
  239. } MrvlIETypes_SSIDParamSet_t;
    + h, f, A/ ?3 {0 w
  240. " ]3 s% V9 t6 ]0 v! ^
  241. typedef __packed struct" B. F0 w" C3 E. _+ v4 a4 _; ~
  242. {
    + l( Z' x2 e+ H' d0 K2 O% U
  243.         MrvlIEHeader header;* ], ?6 C0 q8 r1 G% D& P8 O) g8 I
  244.         uint64_t tsf_table[1];% R; X- W+ q" f  N8 E2 r) [) n5 g
  245. } MrvlIETypes_TsfTimestamp_t;
    % K" ~9 z" q3 E1 e- _" x
  246. 2 L" |' Q! y" ]- S" n0 e
  247. // 整个结构体的最大大小为256字节" ?4 p9 c( e2 w9 m' K& W/ @! d
  248. typedef __packed struct
    " ~/ h& p, A# q% w% E
  249. {4 i6 E/ ~( _% |) W( G1 }* Y
  250.         MrvlIEHeader header;9 }; F- g8 t5 Q0 Q
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够3 L2 U3 c$ e) T) Z
  252. } MrvlIETypes_VendorParamSet_t;" ~4 Y& @/ x  Z; V' u- {' V5 _

  253. " ]* ]9 t( M- `/ B6 ~, e
  254. typedef __packed struct
    5 B/ m. m# P9 q1 a& a" G2 D. V* V) B
  255. {8 {& d/ X. M9 a, Y" |
  256.         uint16_t length;
    0 P& O' J! _/ S1 \; H
  257.         uint16_t type;# g! Q, B* O) K
  258. } WiFi_SDIOFrameHeader;
    3 t% `  ^" ]3 L' T
  259. 7 b( @/ f+ ?& l9 l) s
  260. typedef __packed struct" ?! B6 X$ V% I7 z- O
  261. {# z; a; _2 F: H! r
  262.         WiFi_SDIOFrameHeader frame_header;
    3 s/ b/ g: f% i  p
  263.         uint16_t cmd_code;
    " Y' O  S. J" e
  264.         uint16_t size;, i8 T, o4 k% t3 ]% n5 h* W
  265.         uint16_t seq_num;: b0 j# I  X" ?. r( V- u  h' k5 o
  266.         uint16_t result;% _7 l' v2 Y0 e
  267. } WiFi_CommandHeader;- Z. V9 T+ B0 z$ s. M2 C) d4 q

  268. + F1 ?' l) M! g0 \/ ~
  269. /* Table 2: Fields in Receive Packet Descriptor */
    4 O6 v6 }3 B( V  q8 E6 W: C. B
  270. typedef __packed struct
    ( P/ E- ~; ~; C3 [. J8 h/ d4 J; l! B
  271. {# t$ [' A/ V. Y  K
  272.         WiFi_SDIOFrameHeader header;" N5 y7 A; |4 }; j
  273.         uint16_t reserved1;. u5 X  r  Q4 A2 F* X
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)6 k# y3 r6 J8 d7 E
  275.         uint8_t reserved2;
    " n1 R8 v; S0 G
  276.         uint16_t rx_packet_length; // Number of bytes in the payload  O! ?# ]. R+ F4 Y8 k$ W3 e9 W, |7 V
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.: i6 U% G+ q2 ]  L" B4 ~$ F
  278.         uint8_t rx_rate; // Rate at which this packet is received
    , r4 g, ~  }) v" P
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet7 v/ C7 h0 r7 I9 l! P5 r3 e
  280.         uint32_t reserved3;
    9 e& c+ O* M% w) M1 C
  281.         uint8_t priority; // Specifies the user priority of received packet
    & k- T' R+ }  i3 F8 ]$ p2 t% d4 |
  282.         uint8_t reserved4[3];0 F6 f; Q' t8 V; `. y
  283.         uint8_t payload[1]; // 数据链路层上的帧% _7 j- F- o+ S' s# b0 l
  284. } WiFi_DataRx;3 s9 d! Z" W# C1 m; [7 Y$ R6 E; n

  285. 7 x% [( l8 |) x* S* d
  286. /* Table 3: Fields in Transmit Packet Descriptor */
    " T- k9 R3 }% x- f+ R( s6 O
  287. typedef __packed struct/ d& m, C8 a, r, B6 e, y
  288. {' N/ y( N, z/ _6 `' u: Y
  289.         WiFi_SDIOFrameHeader header;
    2 {9 x  T% Z' K, s; G5 ~
  290.         uint32_t reserved1;
    & P! E% H: W  |8 r! h
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings
    1 ?. O" H/ h# F( u* R* r0 z  @
  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)% `. ^: W& m. L; i1 p
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame
    , Y4 b# b( N0 K& |9 b1 N& Q
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5
    9 J, x- ^8 ^0 ]. I
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3
    5 X( d% j3 A( `$ z/ X
  296.         uint8_t priority; // Specifies the user priority of transmit packet; S0 E& Z& k* G2 @3 u1 z, M7 \
  297.         uint8_t flags;- K) I7 w0 f- U4 l! M/ u+ I
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations' B8 l4 C8 U4 R$ C
  299.         uint8_t reserved2;
    4 k5 t- b0 `- p
  300.         uint8_t payload[1]; // 数据链路层上的帧
    & [. G4 v( ?4 A  J2 ^( k
  301. } WiFi_DataTx;# D0 w/ I: u8 T; c$ z# G3 R

  302. 2 b( J* _* H& G" n& X" f  A% H
  303. typedef __packed struct
    & K% X8 E8 B3 E3 u9 M! e  C$ r1 u
  304. {' d$ F0 P7 a' O  U
  305.         WiFi_CommandHeader header;( R6 e/ m! r* X2 j- T; o3 c' C( ~
  306.         uint16_t action;# W. O# K) P$ S- ~
  307. } WiFi_Cmd_KeyMaterial;
    + ]- _0 i  n; {( L- y$ O+ P

  308. + O* J/ E. k2 \
  309. typedef __packed struct( @! @* Q& S' X9 A
  310. {7 x! q8 V$ o" c+ Y6 x; b: q- K9 W
  311.         WiFi_CommandHeader header;# u; G. y+ ^1 O6 h5 |9 u% L. Y
  312.         uint16_t action;
    # ]& a) E/ `/ v6 p6 T! {# P( I
  313.         uint8_t mac_addr[6];2 Y+ A) m% H  q7 j! c+ s4 o
  314. } WiFi_Cmd_MACAddr;
    7 W, [. V$ g/ M. Z/ S& K. k9 `; O* ?7 w
  315. 2 Z8 r% A: E- v4 h/ H+ |
  316. typedef __packed struct
    & J8 H, W; Z7 d6 F$ N/ A
  317. {) d, s  g  ~8 p
  318.         WiFi_CommandHeader header;
    6 w# _* c5 u: t5 Y
  319.         uint16_t action;- N# l& B+ n6 o5 m6 Z6 l) i
  320.         uint16_t reserved;
    $ V% f3 A3 ?! K+ V( j/ }
  321. } WiFi_Cmd_MACCtrl;
    . E0 I- T) ?4 W7 k0 I- j

  322. 1 l0 b. g" q, A4 H' h! J
  323. typedef __packed struct% o( a: D! E8 H4 [# S
  324. {7 C0 {% {( n. c' H5 t
  325.         WiFi_CommandHeader header;' H7 N! [* O1 s- p( N: Q
  326.         uint8_t ssid[32];
    : l3 O) C: e0 H+ k+ N  j9 r% G) M
  327.         uint8_t bss_type;3 @& Y' P  f  D; }$ t
  328.         uint16_t bcn_period;
    ( G/ U+ i# Q3 R7 Y' e0 m/ t
  329.         uint8_t reserved1;! t  }. x3 k$ D5 g$ Z
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU* [3 k/ M8 F$ Z# {: n1 Y) ~0 H& f
  331.         uint32_t reserved2;
    ! w) J, i# t+ e% c- u
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network1 k, n9 n/ B- V6 b/ _% Q6 J& ~/ ^
  333.         uint16_t reserved3[3];
    : S& Z$ n$ d" a3 s% C' I, I/ \, V
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information, A- l5 }6 @) Y3 H
  335.         uint8_t data_rate[14];
    : K" D$ R7 f4 H! T! w0 f
  336. } WiFi_CmdRequest_ADHOCStart;' N; L$ B9 L) ]' c

  337. * p( ^% m/ X7 D( [  p
  338. typedef __packed struct
    ! L! S4 c. m" M$ J) N# L; V% B
  339. {
    : r9 I( u) z# D3 n1 o+ ]6 w
  340.         WiFi_CommandHeader header;* U6 W) }! Z; [% Y  {$ j$ j( G; x
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address
    * f6 s% C4 D0 b. K  ^* O: q
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information: N# v  s/ S' k3 }7 e
  343.         uint16_t listen_interval; // Listen interval! Q, I  o& Y5 r, n7 s1 V
  344.         uint16_t bcn_period; // Beacon period
    ' ]1 F) s2 L( h/ E" T
  345.         uint8_t dtim_period; // DTIM period
      M$ ?( R% B1 Z
  346. } WiFi_CmdRequest_Associate;6 A9 R" G( v  _! y9 }' m1 K
  347. 8 a7 x4 j9 h5 E6 W' b7 j4 a- @  P
  348. typedef __packed struct
    0 m  ?4 s1 L* {+ _; H7 Y  t$ B
  349. {! w3 v! j$ V$ R
  350.         WiFi_CommandHeader header;: E3 s, k2 r" ]! [! l5 u7 a* h* i
  351.         uint8_t bss_type;5 M( Q* j$ F% h/ B( M- N# d' L6 Z6 u1 c
  352.         uint8_t bss_id[6];
    * ^+ |1 j6 ^/ s: g; S; c, `* z8 k
  353. } WiFi_CmdRequest_Scan;7 ^( y  e9 F2 V5 d, |" t& d! j: ?
  354. 2 w) L: R) o  W' z; v1 A
  355. typedef __packed struct( z7 }8 o) ~6 o6 I
  356. {" T1 a5 H' t: l
  357.         WiFi_CommandHeader header;! b* P- O5 X. [& k
  358.         uint16_t capability;
    / B% I# v$ h3 N6 q0 {7 t
  359.         uint16_t status_code;2 G: M6 ?7 C' ]7 I
  360.         uint16_t association_id;  D2 a* S4 M2 z3 c/ m# c
  361.         IEEEType ie_buffer;  x% I8 Z' j5 M" Z
  362. } WiFi_CmdResponse_Associate;
    ( H, i1 s/ Z* p7 A# @9 B
  363. 3 E9 T+ S3 t+ m, O1 P
  364. typedef __packed struct1 J) n5 \+ D. U* a  h; q$ y) |
  365. {
    : u: @' b0 u& @
  366.         WiFi_CommandHeader header;! q( b  Q2 a+ m
  367.         uint16_t buf_size;( y  m: Q% ?2 A* _4 I8 Z5 C3 q
  368.         uint8_t num_of_set;
    # ~. R. a& ?' S5 Q0 x0 x- V2 Q
  369. } WiFi_CmdResponse_Scan;
    # I' S  ~; l5 v6 y

  370.   @7 l* m# Z$ y* J2 h3 V0 W5 r# u- m
  371. typedef __packed struct: M% [9 G+ C' q$ [3 }" X3 k7 [
  372. {
    . D% `% n" H. H3 o) k% z9 W
  373.         MrvlIETypes_SSIDParamSet_t ssid;
    " V& e8 ]$ X+ x
  374.         uint8_t mac_addr[6];9 z) D% g( a* C5 [0 N
  375.         MrvlIETypes_CapInfo_t cap_info;
    $ s0 J' \5 M$ {" Q9 ^! P
  376.         uint16_t bcn_period;8 j0 z( j8 @. B( v7 d2 r  X+ N
  377.         uint8_t channel;
    " r4 A8 g+ m1 T: }6 i8 X0 i$ w. h
  378.         MrvlIETypes_RatesParamSet_t rates;  p9 S) r$ E; n4 T  T( O% l
  379.         MrvlIETypes_RsnParamSet_t rsn;
    % D& f. o8 Z2 W4 b& a; o& U
  380.         MrvlIETypes_VendorParamSet_t wpa;* c! t: I' T9 P2 ]8 C
  381.         MrvlIETypes_VendorParamSet_t wwm;% f$ E0 p# l0 E. u7 O) E3 Y
  382.         MrvlIETypes_VendorParamSet_t wps;
    ( @5 w) c" K1 {( {, v' z# b
  383. } WiFi_SSIDInfo;
    6 }9 g/ E; T! k" R
  384. ; `8 z  \0 B( z7 J
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)# [0 d- o1 c4 S' y$ r7 c5 B
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)& }. V! W7 {5 b
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)3 ?! v" \8 x8 `1 e
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)2 m. t; {5 |# `; g. ]  ~
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)
    4 D& o; o9 K5 E5 T' l
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)7 o6 t; N& X7 j  w
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)
    2 e; p: O( k. d

  392. / u1 e6 v% ?, T) p7 w
  393. uint16_t WiFi_Associate(const char *ssid);+ n- l& W; R  V3 Y8 p9 i
  394. void WiFi_CheckCmdTimeout(void);
    - a1 P) b* M. p* g1 o
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    ( `, P. ?% q& H" [' ^6 i
  396. uint8_t WiFi_DownloadFirmware(void);6 p& d8 Y! X" w$ j! I. ^( c. ^
  397. uint16_t WiFi_GetPacketLength(void);7 z/ x  K- j) x9 }9 T
  398. void WiFi_Init(void);7 l8 o! o  u0 s5 M7 Q6 G& C
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);/ ~# d8 Q" M2 `
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    7 p/ ?8 Q. `' {  a# A# G
  401. void WiFi_MACControl(uint16_t action);
    3 G6 V) e( g! q# \0 r  k; H
  402. uint16_t WiFi_PacketPending(void);6 G4 n2 Q9 s9 J7 I& x- c% R1 G
  403. void WiFi_PrepareTimer(uint16_t nms);. m% p5 g6 _1 B  J0 x: t
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);% |  U% N' {+ b1 T
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
    % {' `& U( [) t% d6 z
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);2 T0 D/ |* u* p) t
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);) S; T2 ]0 c  r+ v# u2 r
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);. ], }  r4 ~( ?1 o6 ]
  409. void WiFi_Scan(void);. v( `) O( a  N# r
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);
    ! s4 b' L. v0 k
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);7 _0 f, R6 N5 _" D5 {) l4 ~
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    * u4 w" `/ Y; l; Y2 k: ?
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);5 M, i( j( s* d1 |2 D/ Z
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);; h! F) J  e. r
  415. void WiFi_SetBlockSize(uint8_t func);) \/ ~  `1 U  t- X/ S6 @+ q& J& L
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);; s0 h: X& c% }3 R; _  N3 X
  417. void WiFi_ShowCIS(uint8_t func);
    8 L* E2 T) G( k" i
  418. void WiFi_ShowKeyMaterials(void);
      @" F3 C/ v. I6 M
  419. uint8_t WiFi_StartADHOC(const char *ssid);
    8 o. w. i1 p, y, w) ^( y9 s. o7 S
  420. uint8_t WiFi_Wait(uint8_t status);
    9 c5 Q& f9 K/ t/ r& z3 Q
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);+ N# z' v' T% w, M% u5 a
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);# b/ C3 W  [3 V) P9 `8 z2 O! \
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);" a& P% [& z1 U6 X
复制代码
【WiFi.c】
; c+ x& y! e3 J+ `
  1. #include <stdio.h>8 r7 I1 [' Z: v/ d9 O, z; @7 `
  2. #include <stm32f10x.h>
    ' _, Y% G7 p3 _* O9 p& r
  3. #include <string.h>
    ) j  _1 p) d5 f. }8 ]6 ?/ I
  4. #include "WiFi.h"8 v6 y# B/ k+ O( P; s% @
  5. ( k0 w6 S& E" H6 c) }5 O
  6. extern const unsigned char firmware_helper_sd[2516];( X0 s. m, l/ i* K$ u
  7. extern const unsigned char firmware_sd8686[122916];% l9 K' A/ @4 y8 C* V

  8. 8 w3 \" p8 ]' y4 R8 \7 p: }
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
    . j) k/ B5 _$ {$ @7 S
  10. & x4 l& q0 _( [; Y$ I5 a" f
  11. static uint16_t rca;
    ! l& }- M8 }2 O9 F9 \
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;
    % W2 j3 d: S( K% ^% p0 X
  13. static uint32_t io_addr;
    2 m- k: x9 w7 k: N
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小; m7 V$ x+ I' e& }7 |& f1 x8 Y# }$ w
  15. * M, g- m) h5 H8 x, S
  16. void delay(uint16_t n);
    8 }/ l$ ~3 X4 a* l( s
  17. void dump_data(uint8_t *data, uint16_t len);
    ( ], v8 K7 d: I0 ^+ [

  18. 9 R- y% {: r3 j+ `8 y, M3 f) {
  19. /* 关联一个热点 */; x# t$ h' B( g5 i5 ~  Q
  20. uint16_t WiFi_Associate(const char *ssid)
    + a: z& [8 i' ?. s2 t0 ~2 u
  21. {* f9 M" _& [* v. M+ l; F# n7 v
  22.         uint8_t buffer[2048];" f4 Y4 D5 W) y# A
  23.         WiFi_SSIDInfo info;
    8 s) u# Q+ Y/ m% T' T
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;1 w' ^- C2 q& P4 k1 K7 V* s+ h
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
      {9 |$ x/ ]: u! m& D6 o3 Y
  26.         MrvlIETypes_DsParamSet_t *ds;
    4 q& O7 |) C1 M  u, {: ]
  27.         MrvlIETypes_CfParamSet_t *cf;
    $ B/ F; T' x! y; B0 x
  28.         MrvlIETypes_AuthType_t *auth;
    : K6 p3 h6 f; ^  |( j8 S0 p
  29.         MrvlIETypes_RsnParamSet_t *rsn;
    5 l' \+ T8 z! L' C; [3 a0 y

  30. 0 c& `; z& S/ V) w
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer))); C, B% k7 o: \0 x! c, S9 E% o8 m
  32.         {) P! h0 b! E3 _, o
  33.                 printf("Cannot find AP: %s!\n", ssid);
    * r4 H( w: ?1 x! `9 h
  34.                 return WIFI_ASSOCIATION_NOTFOUND;2 }- V: `0 H; o; b# Z. H7 k5 a
  35.         }4 X" J! p! y, w5 G
  36.         5 B5 L! ^' m! S) W6 h1 I; x# q
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));
    1 W! E4 i+ B: t' u6 V/ X% ~
  38.         cmd->cap_info = info.cap_info;
    + d( c& G+ q" D) z4 @
  39.         cmd->listen_interval = 10;- {6 E0 Z# S' E6 w, U
  40.         cmd->bcn_period = info.bcn_period;7 T" Z% O* ]+ b9 J8 }! n
  41.         cmd->dtim_period = 0;# V9 D! ~7 u: F$ Q- j8 N
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));8 J2 `6 o" ^% I7 ~) X! U( w
  43.         
    : M! L7 t( R/ g( U
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));+ \; ?' K+ a1 E
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;- l5 R7 c: p" Y+ A% E
  46.         ds->header.length = 1;
    7 ?$ i& I# P2 o" e5 q
  47.         ds->channel = info.channel;
    4 l: z# Q3 w* W( A- @  K$ u
  48.         
    5 B5 p9 |( Y! A" N3 w* w# ]
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);  Y& e; B& Z. W9 u9 M$ j
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));" A& [' H) |, H$ G
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;9 o6 |1 b7 g( q* m5 s& A* e
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);1 A9 [+ B8 _: A9 }5 ]1 }
  53.         
    9 q" Q) H7 o7 X& u4 Y6 S. c! G9 S
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));  s3 z( E3 E; d6 B& m2 e
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    1 ?, u) i2 G9 e1 P" _) N# h6 j
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;1 O# `/ A  _$ `1 U! n9 d  x, P4 ?
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);
    : y+ {( y$ U) {! A
  58.         auth->auth_type = AUTH_MODE_OPEN;
    - z8 F: `" x7 _
  59.         ) B& [& [) s: W9 C2 J  }7 H
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
    ; W5 b, t3 O" n7 h
  61.         if (info.rsn.header.type)
    ( p9 m1 f+ [* o- F3 X- E# D
  62.         {) f, G0 r0 w3 `" U+ P& R4 o
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接! d2 V- a& x8 U# T6 b$ e# M2 z% P
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));- ^" _% `9 \4 Y
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));/ e) G6 F8 z+ h0 B6 [& W
  66.         }8 X& {* y+ {) v: ~( s* M
  67.         else4 ^6 g9 p$ e& ~3 j- }( I3 \
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数+ M% z2 z" L; w8 y6 O
  69.         
    , p* B% Z7 ~) O8 p! n. j
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))) u# x& @/ U5 D1 S5 }
  71.         {
    9 L" s& u8 v) M' ?
  72.                 printf("Association with %s failed!\n", ssid);
    0 j9 x$ ~" v4 I
  73.                 return WIFI_ASSOCIATION_ERROR;
    ( c1 F3 y2 Y$ c' X) L4 f; V' T( s
  74.         }' w9 T' V, G, r
  75.         ( z$ p& u, U, W
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);
    . g* o) i  W+ ~& m9 \/ T8 D
  77.         if (resp->association_id == 0xffff)
    8 g' _& u/ L0 h  @2 t  k, ~; M
  78.                 return ((-resp->capability) << 8) | resp->status_code;
    5 _( ]5 t, \$ l5 o
  79.         return WIFI_ASSOCIATION_SUCCESS;
    , Q3 _& ]4 J/ |& V! E: }7 y# b
  80. }' i: [0 M+ y+ Z1 ^" z& j
  81. ! j. Y) K' ~& t
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    0 t" w0 k/ ?7 m% j+ U0 [
  83. void WiFi_CheckCmdTimeout(void)
    6 d: K5 m  t3 L& k- `) w
  84. {
    2 C# X9 r* ~' T7 z7 k
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)
    1 F6 I* s# r, W1 N9 y- c8 ^, J
  86.         {. p* U- e7 H6 o, G! Z; y! s
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志
      M. _1 m: O9 L, U% w0 C) y8 w& a  M
  88.                 SDIO->CMD = SDIO->CMD; // 重发4 J$ V% N% P: v" a$ X! G6 Q( D0 t9 {
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);1 q% |" O6 Z: T; S; |/ ~
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);
    " @! Q+ b; e! \8 T- D! R. h
  91.         }
    , f% Z4 l* X$ v& t7 x  O
  92. }
    7 S( K& u9 W+ c" G7 a+ K

  93. 2 ]% M; n; F0 s/ b" I, _
  94. /* 连接WiFi热点, 并输入密码 */
    4 h9 b4 r1 s; \+ @7 M2 h
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)5 v' U' t( `4 _1 X$ l+ Y( D
  96. {5 [# ~4 L6 m, c/ C+ |7 W
  97.         uint16_t ret;' S, x6 P; V5 l+ w
  98.         do
    , l0 Z( M( n* {& x
  99.         {
    " x  Z7 @. m0 j9 e7 p
  100.                 ret = WiFi_Associate(ssid);
    % L: Z- y9 L; P2 x7 j
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)/ w2 D# v  c/ c+ m. q4 H. ^" n2 |" M# ]6 \
  102.                 {
    2 S( @! s5 y6 s1 \3 |
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);6 U  O# @2 h1 [1 S+ M  E' D
  104.                         delay(2000); // 等待一段时间后重连
    : X& |+ ~8 B* K% P# ?
  105.                 }7 c: |  j3 i# X6 ^/ X% ]' B/ X
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连
    + Y% U1 p( s* N. l# m3 _3 N4 Z
  107.         
    4 D( h& x$ t7 U+ w; P% ]
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)
    2 N, c. T, x" P4 i8 m" E
  109.                 return ret;; ^; h( f) W3 j( n, g3 @
  110.         . E( }. e, O) d" @) ^
  111.         printf("Connected to %s!\n", ssid);1 h! V" U" u& m7 o7 |
  112.         return ret;
    * P* F  M. n/ O8 d# v% k$ m. b
  113. }
    5 d7 @7 Z1 e+ n7 b7 q3 ?
  114. 9 |3 Y( a8 \5 V( v! k: {9 i# @
  115. /* 下载固件 */- y0 s1 b0 V" {# |' c4 Y
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc" I2 L3 O. {/ f3 C
  117. uint8_t WiFi_DownloadFirmware(void)
    2 O& a7 y; o8 P% f) ^$ D2 o0 u' q
  118. {. L& w9 P6 l% m( Y3 ]) Y7 ~
  119.         uint8_t helper_buf[64];
    $ f* x* h, m, A- Q0 z! G' V& R
  120.         const uint8_t *data;8 H5 ~+ a( d% M" I1 b* {0 W/ V
  121.         uint16_t size;: j" t8 X6 @/ b8 H3 i
  122.         uint32_t len;
    3 U' s  B1 R( e+ ^
  123.         
    : @* Z' s; U; b' D8 i  O( f
  124.         // 块大小设为32
    ; J7 m5 X1 V5 ]2 o* [# U6 k2 n
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;
    5 {- ^1 o  |3 M, }
  126.         WiFi_SetBlockSize(1); // 应用到Function 1
    . a0 I# c( I4 `* ?/ |% {# b# D. b
  127.         # Q( V+ Q$ y3 f
  128.         // 下载helper7 F* M& w. o$ V4 H) o# G: |
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);9 \* c9 @# ]) [$ _6 p
  130.         data = firmware_helper_sd;- Y) E: m0 ]6 G3 F7 s) o
  131.         len = sizeof(firmware_helper_sd);; @- C$ g' l( ^! ?( ^3 |
  132.         while (len)
    3 o" Y+ e; @0 f; S" m3 d
  133.         {
      ^! G  e6 F6 ~  z8 N& H
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量
    2 w) x. i4 u, n! M- z8 S( K
  135.                 size = (len > 60) ? 60 : len;
    " n7 h* }* a4 E8 E0 q, Q
  136.                 *(uint32_t *)helper_buf = size;$ |; u" }8 ~2 q( l& A
  137.                 memcpy(helper_buf + 4, data, size);
    & ~+ ~; R& s: `) f; @
  138.                 8 W5 _  \$ ^0 R. E
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    * f  l) ^8 K; f. E$ e1 Y% d
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));' j- j$ O% _; W- ]' B4 ]2 c
  141.                 len -= size;
    2 x- J, P& s0 `- ^& t
  142.                 data += size;
    9 t1 V+ ^0 S+ ^% q# K& V6 ^
  143.         }
    ! n! S$ y! Z1 _. \- \9 H$ ?
  144.         *(uint32_t *)helper_buf = 0;) T5 w! t9 @# R
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束
    # X  A0 N' H8 z9 r$ T
  146.         
    : W( }0 j' e' X$ D1 _% Z
  147.         // 下载固件1 T, A. s, Q. @1 k
  148.         data = firmware_sd8686;
    5 O& C$ e2 y. D3 V- X" _% {1 D) ^
  149.         len = sizeof(firmware_sd8686);  a" H) c7 i) [. |
  150.         while (len)
    # Z0 D7 C' N( F; S( q) |
  151.         {
    5 s+ Z, e4 T8 ^3 ~# b
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);! f! }3 v& I. V" U3 i
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数. R, M- O! p* K7 b
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);( L8 f) B# V" G
  155.                
    * n& I! w+ u- M% v8 b; _4 _
  156.                 if (size & 1)# G; l6 c! C6 Q& p; A. H8 l
  157.                 {0 O4 [) h! V; b) e$ {) O) `+ ?
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)
    ; b0 \  Q/ a: _
  159.                         printf("Error: an odd size is invalid!\n");  U4 V- F" O. F3 l
  160.                         return 0;
    0 d: E$ F4 w7 V' b$ [8 I* S# a5 ^
  161.                 }
    " a) Y; p% j- z# Z: \
  162.                 if (size > len); t8 o, G5 l" x
  163.                         size = len;
    7 a; e% ?/ H! P6 R* q- D3 i
  164.                 7 I! j$ ], k- D7 Z
  165.                 if (!WiFi_WritePort(data, size)): |7 @4 I+ X8 d$ q( @# G, e. W
  166.                 {% j) i% i3 y. m* O- j# f+ H. G! K
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);! K5 N9 u2 Y* b6 O* r% ~
  168.                         return 0;8 N* i) [+ e( S
  169.                 }
    ' C8 v. b/ |; b( n6 {' K: t
  170.                 6 L5 C: n2 J3 e
  171.                 len -= size;
    : f- F: [. H3 E: K4 m6 B- l
  172.                 data += size;  F8 N2 Q  I* k5 X  f& ^
  173.         }
    ' F4 L0 e5 K  M/ D! R
  174.         " m7 L; W1 B4 S4 _# [7 V  e
  175.         // 等待Firmware启动7 P- S6 `1 U! M  T$ Z' Z
  176.         while (WiFi_GetPacketLength() == 0xfedc);% u4 J/ H, c1 }  s6 o
  177.         printf("Firmware is successfully downloaded!\n");
    ' x( z$ U& s6 t
  178.         return 1;
    1 G5 e  ~  o* K9 U4 V+ j
  179. }
      b6 k9 x: U7 j- D# ]
  180. / x' Q# S$ L: s% T7 n
  181. /* 获取数据帧大小 */; d! t% E; a: a& V9 g
  182. uint16_t WiFi_GetPacketLength(void)& I, m" C. \' Q" k5 m
  183. {
    0 U! ^/ B/ g% A6 ^2 q
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);& U- L. k- f% X9 e. B1 y2 _3 O- t: ?3 L
  185. }$ z5 A/ b- V  P& Q& s% S

  186. 5 `+ d' }: Z4 T0 ^
  187. /* 初始化WiFi模块 */) C7 p, _$ r1 O* I8 S
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization  n+ m5 B( W. X# Y& ]& w
  189. void WiFi_Init(void)2 h0 k' Z; q0 N! i, F7 l3 e
  190. {  B1 t8 `. k* P0 C& ^- _
  191.         printf("Initialization begins...\n");0 m6 D$ |( l0 P
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;
    ! k  h6 u6 G8 ~* r- c
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz
    6 D) j! z1 f4 [
  194.         delay(5); // 延时可防止CMD5重发
    3 X; p( p6 Y, \! O* L7 q
  195.         6 b: i9 Y' @4 H$ J! M" X0 K& M
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
    ! S! }  B3 v7 O$ X; T
  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), x( e8 _3 Z& b: \% L# {
  198.         3 p- b, k7 @2 d/ A
  199.         /* 发送CMD5: IO_SEND_OP_COND */- H+ O; M; J  s( L
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;! K! O% e9 i6 E6 M) u
  201.         while (SDIO->STA & SDIO_STA_CMDACT);  H5 F& c: e  e* O
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令$ F+ O/ v' g( Q& X9 f
  203.         if (SDIO->STA & SDIO_STA_CMDREND)( z- f- S; K$ U/ y' H7 A0 [. v
  204.         {# ^6 m+ _% i; \# ^
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;3 k: D  Q0 K# X" k& P9 T+ t$ R# Q  h
  206.                 WiFi_ShowShortResponse();
    0 V3 T7 h* D; D2 ^. x$ f1 o5 a
  207.         }
    + R8 R1 x( ~' H# e8 k, k
  208.         
    ; `5 i8 R) o7 ?
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */
    # k" A1 j( J. W7 [, J% g
  210.         SDIO->ARG = 0x300000;
    3 h; m8 ]* ?" x& `' ]
  211.         SDIO->CMD = SDIO->CMD;
    5 b7 S5 c  V3 o) d9 f
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
    3 h% E& j. u1 ^# g: J/ E! R
  213.         if (SDIO->STA & SDIO_STA_CMDREND)% P) S$ S- _  E" {3 V( D( Y6 f
  214.         {0 D/ y: M, @3 `7 k" ~0 U6 K( T
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;( _  H0 F7 K0 I$ u9 q4 x/ y: F
  216.                 WiFi_ShowShortResponse();
    ) ?/ c4 {5 T6 y$ w1 C$ ]
  217.                 if (SDIO->RESP1 & _BV(31))' p4 K1 a: C  i/ z/ _& p
  218.                 {' V% n$ Y. [) U% T3 f6 ]: K: d
  219.                         // Card is ready to operate after initialization
    & u# @" N/ h4 r  }4 v: d( [" G
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);2 \3 |. f' \5 L& c0 }* T
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);6 T' m8 S- x* i! M" S* W9 ~$ T
  222.                 }
    4 V, r$ @2 {$ p, j7 I! O
  223.         }3 q- t) V* X: s2 j+ _
  224.         
    , a# P, b) _; ^
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */
    ( `) b4 x; g6 L6 P. E  U/ ?
  226.         SDIO->ARG = 0;! d7 K" w  r4 h9 T0 E8 c
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;
    ; T8 O4 q1 d( o) A4 ~
  228.         while (SDIO->STA & SDIO_STA_CMDACT);: \# a+ x* o$ R; }
  229.         if (SDIO->STA & SDIO_STA_CMDREND)
    5 {1 V6 x' d$ G+ ~
  230.         {
    - G* `+ R! t/ v+ P) q
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;/ |4 J4 r: k+ U7 `- A
  232.                 rca = SDIO->RESP1 >> 16;+ J  ?/ K/ o/ ^2 e5 I( K$ e' G1 Y# e
  233.                 printf("Relative card address: 0x%04x\n", rca);2 m8 H  C$ y$ X! O! y$ Y4 n! _* @
  234.         }; W3 d& p9 u* c
  235.         
    ! c: o1 d- \5 H) m' ~$ R1 W1 I
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */
    & V* x5 K: ~$ ?+ K! K/ M0 l7 G4 t; j
  237.         SDIO->ARG = rca << 16;) N4 u& T+ \" n% e
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
    " y" `$ y/ G; E% a: O
  239.         while (SDIO->STA & SDIO_STA_CMDACT);, o# W& C- R3 Z  g- ^7 A0 N
  240.         if (SDIO->STA & SDIO_STA_CMDREND)
    4 U9 `  ~' w8 k  }
  241.         {& l" f  k& \; T7 F3 b7 D& O
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;0 D0 M$ G" \4 D  V+ D1 L
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);6 K1 ]( U5 l& z; G* }
  244.         }, R- I0 ]9 L# l: g
  245.         
    2 g0 {. G8 a0 |+ @. `& Z# N
  246.         // 提高时钟频率/ C9 N  K) C6 y% R8 ~0 _2 B0 C
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
    6 ^8 x0 }5 b4 }; g# K6 t  b
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒
    ) U  m% N: a  ?8 Q4 _8 n" Y4 C5 u
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
    % U% n* ~, Q! r1 Q/ w) j" }% v
  250.         
    * n; Q$ j1 d5 k. x( F
  251.         /* 选择总线宽度 (Wide Bus Selection) */
    9 V, Y. K* l* A6 }) y+ k! c
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)( u$ i# B) Z+ ~  |. ^9 S9 R
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers  |# w( C/ m2 B' r
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus0 |# O* l9 e; c1 h
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;8 w1 T6 m: G/ m* t' ~
  256.         & V+ T. j) V9 g  j- B
  257.         // 初始化Function 1
    * ^: U6 |: B/ b+ E0 @! |9 B$ A
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)9 O" J) ^3 N" j1 M
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)
    6 W, p% q/ q8 M% |
  260.         
    ' j7 O& T  e( v# \8 B  D/ w; D
  261.         // 显示CIS信息
    0 E* v2 U9 U1 j+ R( t
  262.         //WiFi_ShowCIS(0);
    + k- v+ T. A" G: h* L& u
  263.         //WiFi_ShowCIS(1);
    + S& M* Z8 Q, {- U
  264.         
    ! ]0 j' B6 h. e# g7 K9 k. a
  265.         // 下载固件
    % y+ E7 i2 s! r6 X2 z# p
  266.         WiFi_DownloadFirmware();
    . i* J# Y- [% y) u* ^4 c
  267.         
    ( s$ P' R% T$ V; {5 o0 u* X
  268.         // 设置数据块大小为256字节6 m2 k/ t2 ]( o2 L; I! q9 Z
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    # T3 [4 x; \5 u- l5 b, \
  270.         WiFi_SetBlockSize(0);
    ' v8 y, K# K) [0 ?! b- P
  271.         WiFi_SetBlockSize(1);
    2 |/ U+ W& l7 T0 f
  272.         
    % J8 k3 a' @+ O' ~
  273.         // 允许发送和接收3 `, {* H& e, D# u7 R
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间; ]5 G! P9 G5 W0 o  G1 Z
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);0 v1 l! N: _& I6 d. s: f
  276. }- A; Y8 A3 U8 Q5 r

  277. ) B" w( F/ F' o, M8 P
  278. /* 获取或设置密钥 */. X$ _( ]) J- d
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)2 d% R0 m1 j: `! q$ }' z
  280. {
    " t6 B6 R- F* z" k" f$ a
  281.         uint8_t buffer[256];
    ' X6 l6 l4 D' o* U7 ?9 {5 |0 q* _
  282.         uint8_t ret_size;
    ! F! `( o: d# I" L0 I, o6 Z+ V
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;5 V( f4 Y7 @( G
  284.         cmd->action = action;
    7 _, m& o1 J  i8 A
  285.         if (action == WIFI_ACT_SET)
    - h7 x$ V- }( x
  286.         {
    3 P* d4 p# |" y& O3 w) s
  287.                 memcpy(cmd + 1, keys, size);
    ( t5 U3 N* V6 l: K! k% [
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);
    , A5 z* `" ^0 q& k9 o) b8 R9 T
  289.         }
    # L8 ^- J, R, H; c0 y, O
  290.         else! }/ w0 v+ s, C  N$ h. ]
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));& T  l1 l4 f+ q! _
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));% s" k5 m3 Q2 M/ z! S
  293.         
    5 s5 X) A( ~" Y2 Y
  294.         if (action == WIFI_ACT_GET)# t+ P: T$ \- d; s& r9 r6 G
  295.         {
    + r8 C, x3 [% P  }% n- e- c" o
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
    2 f* Q5 N) n: A4 \' @
  297.                 if (ret_size <= size)
    ! i9 E1 \# e* q  o* q6 G1 S
  298.                         memcpy(keys, cmd + 1, ret_size);
    + Z: m" W2 R& B) b7 v# J
  299.                 else, O) |# U" O% h
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);+ J$ C$ }: a/ [0 m6 c
  301.                 return ret_size; // action=get时返回读取的数据大小
    ( z1 p5 l5 b. ]9 f( L1 N4 N, ?
  302.         }' D9 i& {- S) k9 t. \  U- {+ ^
  303.         else
    $ _* _; k! ~0 s: I6 {! E
  304.                 return cmd->header.result; // action=set时返回命令执行结果值
    # r, }" S; r2 n+ _! E
  305. }$ I+ I) q9 j1 c$ {) g

  306. - p! \* w& k. ?7 ]$ B7 J! k! d
  307. /* 获取或设置MAC地址 */0 M2 S8 J8 ?) n' m/ P
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)- u% w: P, A% H, x7 }2 z; g/ n
  309. {
    / r; S/ L  T4 v
  310.         WiFi_Cmd_MACAddr cmd;2 c% v' E( u1 }7 `, _3 V5 o
  311.         cmd.action = action;
    " O% P! l$ X, Q% Q, ~/ O" t5 z
  312.         if (action == WIFI_ACT_SET)
    $ b1 u! S/ ^4 D( a
  313.                 memcpy(cmd.mac_addr, addr, 6);% R2 k4 W! s+ {- M( O7 O
  314.         ; L- ^" _: \( v. k/ u% _
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));: h7 k, {: ~* m. g  F
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    9 U9 [2 T' O2 b7 e7 w7 i
  317.         if (action == WIFI_ACT_GET)
    & q! u8 U# P9 r$ Z6 M! c5 L
  318.                 memcpy(addr, cmd.mac_addr, 6);2 n. s) s5 f" {' k7 r* A+ h- X
  319. }
    ! K. Q9 Y" Q3 S+ i3 l

  320. 5 o/ \$ ]% C) `4 D8 a% m! c* a9 X% h
  321. /* 配置MAC */+ k) W8 J4 K6 i
  322. void WiFi_MACControl(uint16_t action)
    / j" J5 D# E7 r! x! P# m8 E1 I
  323. {% {: Y+ R8 z  [9 S$ H2 R
  324.         WiFi_Cmd_MACCtrl cmd;* x$ H% |# W7 Z  _8 W. f, H
  325.         cmd.action = action;
    ) q* H+ f' J! |3 e9 W+ ]" q, O
  326.         cmd.reserved = 0;+ G+ v2 O! e9 x
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));
    " s- c& @' N& W7 T) E
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));: y% J% |0 v1 I( [6 J5 k' V" J" V
  329. }! P/ E, K& Q+ f) Y6 n& d

  330. & {1 o, |% ~' R
  331. /* 获取滞留的数据包大小 */
    # {7 \" y: \! y% i/ }
  332. uint16_t WiFi_PacketPending(void)' U/ k2 V0 p: x5 Q" ]
  333. {# ]0 n; X: @$ r$ H. D( i& ^# }+ r
  334.         return wifi_pending_size;
    : P) X, |4 a" o) c
  335. }/ q; ?3 W/ \5 S5 |+ C

  336. 7 N2 {) x6 C5 A' v/ y6 `! x) T
  337. /* 准备好超时计时器 */9 _' S) ^1 r! n7 \5 i
  338. void WiFi_PrepareTimer(uint16_t nms)
    5 {- j7 t2 Q' B5 N& Z
  339. {
    # W' j1 K* X. Y7 c! g* S; v+ z
  340.         TIM6->ARR = 10 * nms - 1;2 f0 @, s7 u8 o) p0 V1 |5 x* Z7 k5 w
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz
    - R3 X4 }: x# [) {
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置" I+ `4 f+ `; M
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位- L* P" w6 `2 L0 h% N
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式
    ) H) Y1 X2 W# u: L" I. J/ m
  345. }! ?) D& G4 M. ~" r0 p. ?$ Y4 d

  346. , ^3 o/ D5 G/ U" \" J% j6 u
  347. /* 读寄存器 */
    + Q( P. S7 G& ^5 G3 j, l
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr). N: g& S3 n5 j4 b& j' {
  349. {+ B7 |$ l( X' t# V4 k# m
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);
    / D/ x: r8 W5 S' z* q& I$ @
  351.         if (SDIO->STA & SDIO_STA_CMDREND)3 t" y" ?+ P' c. ^
  352.         {
    . Q0 L) ]! T( y, _$ w7 L- Y+ w
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;7 C( D0 U) E, k. g3 k; H6 s# N
  354.                 return SDIO->RESP1 & 0xff;8 V! E3 A" k2 Z* ]$ @) R
  355.         }
    0 W) H2 H/ T; c  b+ R. v
  356.         else
    9 ~- |3 B- q* o1 E; Q9 b% N& r8 ~
  357.         {' p. e8 J! P9 P! v- a  M0 g
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);& e1 ^1 Y3 G) p1 w" [
  359.                 return 0;
    * k5 U+ H& q) p7 x4 x3 Y- h7 c
  360.         }
    ' [6 b# k3 w) b5 m
  361. }
    / ^& y& {4 J+ C/ R  o7 J

  362. $ l4 w2 b+ {/ I. @) n. K% M
  363. /* 读数据 */7 f9 G7 O6 F8 r) s! y2 Q
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小# X0 C" H4 f1 H" i+ O# {5 w5 c9 a
  365. // bufsize=0时, 只读取数据不存入缓冲区- V+ o/ ^0 ^) G! m* y
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags). T5 D) v: n* u
  367. {
    ( A& u; Y8 u. i3 R* I! s7 h
  368.         uint32_t len, temp;+ I( d4 Y9 I( o5 [% o. K; e
  369.         if (flags & CMD53_BLOCKMODE)" u; k5 y4 b. l9 j5 H! D8 T, ^
  370.         {$ ^# [$ w$ g2 w. O
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数9 d7 ~) Q% E3 Y+ F
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
    0 Q& J: Z% p! R9 s/ G, K& s
  373.         }
    5 D9 r6 m9 I& B4 F
  374.         else
    / c* H5 w7 |$ V# J. j8 c
  375.         {1 \( Y' d7 ^8 j* P7 W8 |
  376.                 len = count; // count表示字节数4 Y& X. D3 Q3 f
  377.                 if (len % 4 != 0)
    " g, @9 W+ D" R# Q' u6 @2 W
  378.                 {
    ( x# V8 c  _8 u8 Y/ A
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    / \  g' X) ?: y5 r/ X; C
  380.                         count = len;+ f, w6 v# q1 ^, E$ D! ^' O* |! {
  381.                 }0 v. `6 {3 @! \3 b( _8 V% H
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式8 x( p, a. {! r+ R9 D8 K- g! N
  383.         }3 }$ R' W$ g# V. U1 s- N4 _" @
  384.         SDIO->DLEN = len;
    ( K+ l3 b& I! h+ H6 l3 {, j9 c) _
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机+ J0 Y* J6 R! Z# |  m7 A/ |( _8 U. E& a
  386.         * M0 X& ^) P) a- c6 M4 b% R, G
  387.         WiFi_SendCMD53(func, addr, count, flags);
    + U' U) m; A: d9 t% S* m
  388.         while (len)
    7 T2 t2 p% E! m% E7 r2 x/ U
  389.         {
    6 p' S( u' i8 n
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)
    , e8 }+ o6 P/ ?  s; `
  391.                 {
    - W# a3 A. p0 _% S+ m8 M3 @8 `: n( S
  392.                         // 若有数据到来就读取数据4 b! P! ?$ M- g9 ~) e
  393.                         len -= 4;
    + l% P% F2 K+ ^: J* l. T" u
  394.                         if (bufsize >= 4)
    ; k- e7 R) T9 ?5 Q: ?# x+ p
  395.                         {1 g" Q( k$ {( o) L& {
  396.                                 *(uint32_t *)data = SDIO->FIFO;
    ) j1 u7 j1 V" o
  397.                                 data += 4;6 R/ y2 h2 H$ `4 p
  398.                         }+ g6 X% Q" g* I; a( ~' X- F
  399.                         else
    / t9 C9 U% K; c
  400.                         {
    4 _8 I7 O, G5 j5 w6 k* {1 y7 O
  401.                                 temp = SDIO->FIFO;  Z9 k$ f, z  E; S6 L+ G. _  r
  402.                                 if (bufsize > 0)" q! }; i9 f( A
  403.                                 {
    6 p. K: a0 P9 }% `# @  b9 T& b! m, o3 d
  404.                                         // 写入缓冲区最后1~3字节
    $ Z. f2 T: m2 j
  405.                                         memcpy(data, &temp, bufsize);! ~( O, E) q0 ~' b  X2 V9 f$ C
  406.                                         bufsize = 0;% ]% U/ X/ p8 B1 _7 l. D
  407.                                 }
    5 V1 p+ X, L$ l  Z' O9 n& T
  408.                         }- |  t4 P& L, p' S) h, I8 c2 `4 s
  409.                 }. D9 W- T& \9 k
  410.                 ' |; H/ M# G; o6 O: }: i) [
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT). E- m; _9 q6 S" e* f7 J* H9 ?
  412.                 {
    6 A9 u0 R& z6 ~) W( L" L8 ^; i: h
  413.                         printf("Data Timeout!\n");
    : @+ g9 u) [3 _( w/ m
  414.                         break;
    0 l, C0 U; a2 ]
  415.                 }: x6 e' _0 b# Y# `, X% G
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)
    2 Z# Q5 O) p9 h6 [7 d' Z' i
  417.                 {4 C! y, n' `' {( t8 Z
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    0 _$ |: I$ h3 j# _
  419.                         break;  {" M1 m; U' ]1 O: x9 F, i
  420.                 }
    8 t( L; x$ k; @* b) o
  421.         }6 z* l! M5 ^: o7 m9 Z
  422.         8 T/ _3 ]+ v0 O
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));
    - G6 {5 N- _2 m# W+ w  e) _( a
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;$ V6 t: N* |" f7 {% ]
  425.         
    3 B# w9 r8 T" p
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;
    - j' o- N: u, {5 W7 Q& ~4 d8 G
  427.         if (flags & CMD53_BLOCKMODE)
    + v! H  P9 c* ~; v; M( t( }
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
    + x  I2 {- p( I, Z0 ?. z
  429.         
    & ?" n  j: ?6 @* V' C. m3 j8 A
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功
    7 u6 g) `% C% {$ d3 \+ r+ y
  431. }
    ( z" R. p; N, a% s3 F& h. _

  432. 1 F3 j! N, i5 ~- _2 m% i0 J2 e& k2 ^) B' [
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)
    - W9 [7 x& L0 A& _
  434. {& d! F( l, p# T" g
  435.         uint16_t block_num, block_size;5 f2 `, x8 G  y$ s( |
  436.         block_size = WiFi_GetBlockSize();: z, x% T; w6 k' [1 L
  437.         - d" i" K1 h8 L
  438.         // 读取数据
    + M4 v$ R5 h9 |" R0 k. Y
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1* H: A. q8 r, x3 H1 g. s/ {) [0 }
  440.         if (size >= 512 || size % block_size == 0)8 \- r( k3 g0 K0 h& k3 n' J
  441.         {; p$ a/ K! X) e2 a# g1 V* P
  442.                 // 采用Block模式传输
    0 `9 G+ L. ]  p
  443.                 block_num = size / block_size;
    9 }) M% h7 Z, Z4 }4 _8 y" \' i
  444.                 if (size % block_size != 0)
    & g3 R/ h  g. a+ s7 n% V& e7 T
  445.                         block_num++;
    2 \# W. f- n0 S6 P
  446.                 0 Y. q4 n* |; l" ]5 P/ d+ X
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
    5 S8 s! r; d: C, Q  t1 f! t
  448.         }
    : A2 j( r; |( ?0 R4 c1 _) m9 u
  449.         else
    , `& \  j& M/ B6 u6 @0 {7 v& a1 S* L$ j
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);
    9 s- B, I* K# y+ o! I
  451.         
    6 f- G5 \& Z9 k& G+ J0 [
  452.         return SDIO->STA == 0;- w" t9 l2 J8 _2 X1 I4 F
  453. }
    : k( ]. a4 l3 `

  454. % k9 {4 @* R/ ?3 V4 K) }, L$ D
  455. /* 接收数据帧 */
    . x, Z: A6 K* p- G: i
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)0 Y- `) X# J; J# p0 g
  457. {$ |0 z/ I3 _1 v- @1 b' F7 T
  458.         uint16_t size;$ C  y# R  E# `* ?2 o# f" I5 y
  459.         if (wifi_pending_size)5 M8 m& z: a4 q# R% x6 G! S
  460.         {2 b7 w' Z/ z) g$ `$ D
  461.                 size = wifi_pending_size; // 先读取滞留的数据包1 j! z8 o* X& C, }! B  ^
  462.                 wifi_pending_size = 0;
    7 Z) S, Q* I; K4 K1 p' K' g' W% {
  463.         }
    0 T; E& S: l$ T/ u$ y
  464.         else- b3 _2 \7 o- a- j
  465.                 size = WiFi_GetPacketLength();1 D9 n6 t9 h. x/ X( |9 l
  466.         return WiFi_ReadPort(buf, size, bufsize);- P. C; O" ~* a) d. `# Y0 p
  467. }
    3 g$ U0 M# k( g- o

  468. ( u0 s7 k& H2 }6 Z9 j* B
  469. /* 接收WiFi命令的回应 */; K$ }) e4 v% K# k. ^- C
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)
    - r. g& C3 L1 L" r& p
  471. {
    ) \9 @( J% y7 k7 ?6 X8 g8 i
  472.         uint8_t retry_cnt = 0; // 重试次数
    & V. \; G! S# U2 m. d: S. X
  473.         uint8_t wait_status, resend;$ J# i- K4 V! J# ]
  474.         uint16_t size;* u; ?7 W$ v# X+ ~4 Y
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;4 v) Z: g+ [- C4 @; c
  476.         WiFi_SDIOFrameHeader temp;! @7 I! Y6 P! a
  477.         
    3 w: T1 \. x; r  Z5 f" U
  478.         // 等待数据准备好* `) X1 Z& e) h$ i* s
  479.         do
    ! l( y# d& h4 e& K1 K* Y  u6 Y
  480.         {( e% t7 e1 O. \) V% c5 m
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);
    % G3 j9 c) n* e* r) {1 ^
  482.                
    9 f( U) u2 V: q+ U7 n
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息. c  z2 A: M, Q* X' h, n3 E
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
    2 k9 l# _" \9 d' p# K/ c8 ^. G' K
  485.                 {
    / T6 l5 V7 J+ O0 q* ~/ H* N" ?
  486.                         // 若读到的是一个数据帧, 不是命令回应
    ; ^' C4 T" ^, d3 c8 Z
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功
    ( g7 z( y9 V/ A
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);, H9 C4 p2 [0 X+ S  P0 e
  489.                         wifi_pending_size = temp.length;7 v$ |/ `, x& U1 o0 f5 m+ m+ v
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算* o8 }+ M" D& |
  491.                         resend = 1;
    2 W  K& }5 `8 `6 e1 A
  492.                 }
    0 m. e# I6 k; o& ~( A0 ?! y9 ~
  493.                 else if (wait_status == 0)
    1 U4 I4 f* Q* `+ [
  494.                 {( c0 f2 a- n0 @& [1 v; j
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)/ H* r. b; \7 g  j9 h% A0 P& I9 X0 N
  496.                         resend = 1;
    2 \+ u0 i& |( b$ X3 k3 N* }8 s; [
  497.                         retry_cnt++;1 A  O" s& @& r9 B0 d9 J
  498.                         if (retry_cnt >= 5)$ q: I+ h& ^, e5 T" G
  499.                         {
    " `$ |' l. f$ C: W& Y8 |
  500.                                 printf("No response!\n");% t; o- ~  n5 p
  501.                                 return 0;
    + n0 w9 R) o( {$ w/ R0 V
  502.                         }1 w0 g: @- H- i( t2 u6 b( R
  503.                 }/ T$ x! r- L1 f- f$ I& Y8 _+ F  y4 \
  504.                 else
    % [# J2 U. ]- z7 V. M
  505.                         resend = 0;
    4 o5 N3 K! h) R$ c. j
  506.                 1 N: Q0 {: G$ w4 W
  507.                 if (resend)
    % M! X1 ?" K2 n( l0 j
  508.                 {, b" Y9 t! d/ ~: g2 u
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)& T* ?$ s7 V; E& A7 S% b
  510.                         {
    ; O7 U/ n; P8 @( v) u) l
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait  @& V0 R" I) t  V* h
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);- \8 r0 `/ S- c0 ?7 n
  513.                                 WiFi_ResendCommand(buf);
    ; q. W  W5 R1 ~) H5 m. z
  514.                         }/ M" m) T  h% u8 T4 n  c$ o0 T
  515.                         else
    $ m% Q1 P5 r+ l( |: B$ O) H
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出  \6 a  F* K- i$ [3 }( M' x8 q
  517.                 }; E( o5 S' T/ [& J
  518.         } while (resend);: X' O: o4 Z$ v7 L, v
  519.         
    " H, h, d, L+ b  L. k
  520.         size = WiFi_GetPacketLength();" A, v, H% `( {  P. t+ n
  521.         if (size > bufsize)( o/ h  B  j# z- \' A( p
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);% j; X) ?% I6 v% c# s2 Q# N8 ]& }
  523.         return WiFi_ReadPort(buf, size, bufsize);
    : {, C1 e; ^% A, k
  524. }
    * `$ _. t( v2 ]2 W  Z4 u0 p

  525. , y0 {- \) T" O5 W0 l
  526. /* 扫描全部热点 (仅显示) */
    7 P5 H& S1 S: E- m5 ?
  527. void WiFi_Scan(void)
    ( A, o7 t! \, y
  528. {
    : a4 N6 ~* y8 N
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组6 y: r% O8 U' _( f# c8 P0 K
  530.         // Stack_Size=0x00000c00
    2 c5 V* f, L- S$ @6 Q. X$ ]
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
    . c* Z5 n1 f2 ^. Y) N- n# e
  532.         uint8_t i, j, n;
    ' _( t8 a. k- K; i% S, G
  533.         uint8_t ssid[33], channel, wpa;
    3 t# t& {7 y1 ^2 P, S
  534.         uint16_t ie_size;
    ' @( e3 H3 j- H  g, I. K2 D
  535.         8 t. d2 g! k: p* H
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
    ( V- y8 T  s- Y  f4 q
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));+ k4 {- I$ u% J. l( B# l5 G1 E. O, e
  538.         : `, S1 V2 I0 O
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;6 h: [, Q; d& M$ z( p! v
  540.         WiFi_BssDescSet *bss_desc_set;3 m9 k! |2 b+ g
  541.         WiFi_VendorHeader *vendor;! p) \1 u# p) B+ v4 P! c
  542.         IEEEType *ie_params;9 o8 m: j" q* W+ _) o
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;
    ) w: b; E) o7 x" ]0 W: U  H& R7 `
  544.         . L* A, r' h& K
  545.         // 分4次扫描14个通道) U8 p' ?  n* A- _* O5 U
  546.         for (i = 0; i < 4; i++)
    3 m" G2 v+ J* u6 O
  547.         {
    / y0 K" e4 p! k' M# r' ]
  548.                 cmd->bss_type = BSS_ANY;
    0 Y6 z0 a4 W  [  v; \3 q
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    % G, o$ X$ h6 g. h- Z
  550.                 , D% N. g' ~  q  H0 x
  551.                 // 通道的基本参数7 p7 S' x: [! p
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数( n4 m: b! G; M
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;1 c9 n. y6 {, w) [
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);) K3 {; P! w6 W5 q" f
  555.                 for (j = 0; j < n; j++)
    2 d* h$ C  e  R7 |: W
  556.                 {1 w# P8 k1 F  s5 i
  557.                         chanlist->channels[j].band_config_type = 0;# F" _. p1 Z9 G/ i7 q
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号5 U: K  Q  O3 U8 s- p
  559.                         chanlist->channels[j].scan_type = 0;# A; W4 ^# ^  A! n+ n
  560.                         chanlist->channels[j].min_scan_time = 0;
    3 \/ p! z* L" P6 k
  561.                         chanlist->channels[j].max_scan_time = 100;0 j3 k, i$ X) F: h8 y3 t
  562.                 }% }# r9 _0 S7 m, T( Z
  563.                 $ n3 ~+ e% i) B: f' K
  564.                 // 发送命令并接收数据
    $ X% u4 C; p/ K7 A! @
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
    ( e3 R# w) l/ f7 Y; c( w
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉
    / v0 \# m( _8 X! W4 ]
  567.                 # y6 B' v$ {) e4 G
  568.                 // 显示热点信息, num_of_set为热点数6 n3 A' Y0 ^4 }# ?8 Z: E, Q& ?
  569.                 if (resp->num_of_set > 0)
    4 G2 c0 T+ _' s  Y
  570.                 {& g* x% q6 O3 t; x, c; f
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));
    # N2 G+ y, q6 x* ?9 T
  572.                         for (j = 0; j < resp->num_of_set; j++)5 P6 }0 h9 N3 T" \
  573.                         {
    2 o& F" K. g$ v- x
  574.                                 wpa = 0;
    : i1 h6 K2 k% `2 Y" S0 D; u
  575.                                 ie_params = &bss_desc_set->ie_parameters;
    & R+ u9 Q! B* @, O# n
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));. N" J: F2 [$ p) |: f4 {
  577.                                 while (ie_size > 0)$ Z3 |& ^3 G! J) |
  578.                                 {
    7 I/ A6 B" X- E6 K2 N
  579.                                         switch (ie_params->type)2 @" F* z$ U; c# W5 A& C' Z: H
  580.                                         {
    $ b/ ~" ?& F6 b, N& }) \
  581.                                         case MRVLIETYPES_SSIDPARAMSET:, a- d- ~$ I8 d6 x5 H. u- w
  582.                                                 // SSID名称
    9 K. b5 C& ^: }. P$ F
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);+ u3 G5 G( ]4 e
  584.                                                 ssid[ie_params->length] = '\0';5 k2 m3 {$ x, e' h, a8 u" Z) G& l8 h
  585.                                                 break;
    " i, c" L4 @. J7 v7 ^
  586.                                         case MRVLIETYPES_DSPARAMSET:) ]* ~9 K' f1 I5 O2 E$ L
  587.                                                 // 通道号
    $ Z9 H. \! c& a) u5 S; n
  588.                                                 channel = ie_params->data[0];; z6 A# \& |, l' G" a
  589.                                                 break;1 Y& K) \6 \8 s; I8 Y. E% a
  590.                                         case MRVLIETYPES_RSNPARAMSET:
    ; [6 ?9 X! s( T; m3 A; }' R, Y
  591.                                                 wpa = 2;; g; U% k6 A0 U1 ?1 L% p
  592.                                                 break;
    8 B/ L2 a! Y5 c! V# Z, C' f% f
  593.                                         case MRVLIETYPES_VENDORPARAMSET:
      X1 }& f" `- s  E) g# V
  594.                                                 if (wpa == 0)* q3 H. H, W4 o- g: G; Z
  595.                                                 {; i+ ?" f; F1 U7 N0 C. m" R% M
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;' z9 V$ b* G" F& x# @# l! q
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    + a/ X$ l. d4 T4 r, T$ ^
  598.                                                                 wpa = 1;
    + `% x! m4 |" V
  599.                                                 }- a# @9 t2 T7 |/ c" g+ {
  600.                                                 break;
    5 i3 z1 O* ^& Z% s3 v! J' I
  601.                                         }
    ( ], d4 W) O5 O$ S, }
  602.                                         ie_size -= ie_params->length + 2;( y6 R! V9 V( K" j! P1 b
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    2 q8 R% f, z' g% N8 S* A( H; c: {1 Z
  604.                                 }
    2 S  J: c" Y; a: P0 \
  605.                                 if (ie_size != 0)& i% }' Q( q6 y; N1 p, \
  606.                                         printf("ie_parameters error!\n");, y4 K4 X) j/ i7 P- B5 M2 G/ X% x
  607.                                 
    + ^/ b& g' J5 L* ~3 J
  608.                                 printf("SSID '%s', ", ssid); // 热点名称
    . V7 D2 D% [" R# w
  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地址, ]2 E4 y, v8 ^8 n" S- ^9 f3 {
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
    4 v; k/ U! T7 M
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);; |' i3 _! L( l6 P: S( H7 U
  612.                                 
    0 ?* K8 W% x& \
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);* R9 }5 t: @$ o( r5 K
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)7 y  V6 C; j  r0 g9 B4 c" Z
  615.                                 {
    8 J0 V  B! V6 p' E, `5 t
  616.                                         if (wpa == 1)2 s  ]5 H( T& ]6 L
  617.                                                 printf("(WPA: ON, ");3 B9 Z' M. y$ O: a/ p/ b9 d8 S
  618.                                         else if (wpa == 2)
    ( e: d0 f0 y2 X3 i- ]! x
  619.                                                 printf("(WPA2: ON, ");( A- l: c* ?& B7 A1 P- G) a8 K7 g" D
  620.                                         else
    1 S4 n( @/ |, F5 _% ?3 T% L- m7 m( c
  621.                                                 printf("(WEP: ON, ");
    8 C$ A! M( E& W/ ?! X) @2 o1 j& h
  622.                                 }
    / ]5 A: n: _% B' C
  623.                                 else8 b: P7 r! [5 a
  624.                                         printf("(WEP: OFF, ");* e) o) F( u/ ~6 h
  625.                                 - a! z' z$ v: c6 Q
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)* S5 I# }/ ]! [" @+ L  _
  627.                                         printf("mode: Ad-Hoc)\n");
    $ I* K" r, T2 T& I4 E9 S5 e
  628.                                 else( U" J1 l. V+ ~  p$ F/ Z. h
  629.                                         printf("mode: Infrastructure)\n");8 {, g& j7 t8 U1 C) }
  630.                                 
    ( R2 Q+ @7 x. H' ^6 o
  631.                                 // 转向下一个热点信息' C  m" I* W+ w5 y8 [. V0 T
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);& A$ f% \! e% z" S2 K( A
  633.                         }
    1 U2 Q, {! T1 F" @
  634.                         
    1 [2 n4 `" x* F8 P7 g
  635.                         // resp->buf_size就是bss_desc_set的总大小; w! g. F) E& }8 c
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size
    ; k' d$ y9 p# }
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;  Z4 ~/ X2 }6 q4 F) S$ t7 Y
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))  J# s, C- X/ o0 L; E
  639.                         {
    2 z3 s4 n+ p, G& `' {
  640.                                 printf("Timestamps: ");/ _( p2 T0 C5 A% F+ }: j5 z/ D
  641.                                 for (j = 0; j < resp->num_of_set; j++)1 s  ]0 t7 T% s% f* \
  642.                                         printf("%lld ", tft_table->tsf_table[j]);% u& U8 h& |8 \! z
  643.                                 printf("\n");
    ) x# N8 T4 n! R
  644.                         }*/
    / Y$ j0 z% Q3 `2 p
  645.                         3 a* ?2 `  K- x) Y% q, N
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table% S3 @9 Y) M" A4 P9 `- L
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)4 l/ x3 o. w  s8 B
  648.                         //        printf("data end!\n");1 _* H, Q0 N1 u" |6 p
  649.                 }
    6 \% a2 ~$ l/ F( Y
  650.         }
    5 t4 @' I3 T+ h" ~
  651. }& z" q: @2 ]9 `, K( e+ n
  652. ) l9 H: N- I  _+ `! y% A
  653. /* 扫描指定名称的热点 */
    . ~- n* r3 g% o3 `/ J# C) {
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大
    : C1 a8 ~' R) H& i% K
  655. // info用来存放从buffer中提取出来的一些常用信息4 i0 E& {5 L% |- i8 _3 A9 A  \
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)4 N6 O+ _+ r6 z* C
  657. {% Z9 b" M% W8 ?
  658.         uint8_t i;
    ) P) z5 X* M( Z) M2 M) `
  659.         uint16_t ie_size;
    9 n! g% `, C8 q  a; b5 ~
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
    7 v/ {8 {4 n9 R( ]7 y1 I5 j
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;  O+ l0 i" a- W) U  d
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);# j, {2 s: A8 Q- O3 ]/ Q6 ~
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;
    - p2 g5 Q) ~  q; h+ y& I6 S
  664.         IEEEType *ie_params;1 k, d# K1 H$ K* s
  665.         WiFi_VendorHeader *vendor;
    1 r1 \& g3 o' e6 l; r
  666.         ) w2 ^( Y7 f. N8 R# A, G; `
  667.         cmd->bss_type = BSS_ANY;7 E. Z2 s) a6 A7 e1 L, @+ \4 `
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));$ K. c: O/ f  Y# f! d
  669.         
    $ {; S. R* q' ~2 ~. R4 e
  670.         // 添加ssid参数; T( A. U' K% P4 y' N2 ]7 \& @
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;$ C" Q" S  t# q% ^, v1 K
  672.         info->ssid.header.length = strlen(ssid);) O( D/ g0 j4 [* o3 ]
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);: e, Z" V/ E! y6 P. b: m( [# ]
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    0 ?* Q5 {! K, D/ h
  675.         0 t0 T& D% {' j! g; _
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));
    7 T1 ~6 E6 d! G
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;: M% ]& K  P! Q$ `0 L& x" b
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    7 x" C$ g+ W! x* z9 f* l! `
  679.         for (i = 0; i < 14; i++)) N) w* J; i' D
  680.         {. X  l( D$ a  o: s* Z, v' T/ a- F
  681.                 chan_list->channels[i].band_config_type = 0;
    # c' G) }4 w& q+ k
  682.                 chan_list->channels[i].chan_number = i + 1;
    % J; Q6 u  p  x" R6 u: t0 ?
  683.                 chan_list->channels[i].scan_type = 0;7 o. i1 i+ v1 F5 @
  684.                 chan_list->channels[i].min_scan_time = 0;
    8 A0 {* z; Q7 P2 l, l. r
  685.                 chan_list->channels[i].max_scan_time = 100;
    / U3 V6 `+ K* N: ~% F
  686.         }6 I2 j4 C$ f" {4 w$ |
  687.         
    8 O# Y1 I7 |) D( c4 N: x# ?. g
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));2 z2 \) g. x: _3 x5 P! r
  689.         wifi_timeout = 3000; // 延长超时时间
    ! m! {& {( ^& t+ z8 U5 E
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    2 v8 t6 d6 a2 f* \9 p" r. A
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;
    # a. `, m; H% r  Y1 C- ~3 K4 [
  692.         
    5 y2 k  s* E0 `: v- P4 K
  693.         if (resp->num_of_set == 0)$ s% h6 `$ a1 V
  694.                 return 0; // 失败
    : Q( m# R2 Q: z) v  I
  695.         ! Y- [; _% K3 W6 ~& x4 m+ B1 T
  696.         // bss_desc_set以扫描到的第一个信息项为准" I2 I7 D: |2 G# u
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));% o% h" e& `$ b9 ^2 C3 R& U) H
  698.         info->cap_info = bss_desc_set->cap_info;5 U- ]" K+ M* F/ b$ c. W) O# c1 r$ x& D) n
  699.         info->bcn_period = bss_desc_set->bcn_interval;, }7 }3 Y! e) Q2 _" f
  700.         
    & Y4 Y2 A/ h  ~6 D
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)7 o4 G$ U4 o; V+ x3 [
  702.         info->rates.header.type = 0;
    ' w4 l; T2 x* k7 y& a. n9 @. v. [5 |
  703.         info->rsn.header.type = 0;# N% \9 a* l, t1 o- g* l
  704.         info->wpa.header.type = 0;
    ) n# X4 ~6 ]9 X; [# B
  705.         info->wwm.header.type = 0;
    5 b4 p+ t$ L' U! r+ D8 }3 M  U
  706.         info->wps.header.type = 0;
    2 R" s2 o* }4 t5 F2 Z& Y# J# ~
  707.         
    # p5 z9 c2 E' m
  708.         ie_params = &bss_desc_set->ie_parameters;
    7 K  v4 K/ t# h3 n# \
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    - p/ B) G2 `6 q
  710.         while (ie_size > 0)
    1 ^( q$ w8 u4 J2 Y* e' X; |
  711.         {3 R  W( H4 u6 b0 N6 j
  712.                 switch (ie_params->type)
    4 h2 F$ B; m' Z5 L# R' u* p
  713.                 {6 a9 ?- J( @/ v7 X8 x, ~
  714.                 case MRVLIETYPES_RATESPARAMSET:" D+ {- \$ M3 Q+ B; G5 R5 ~" [
  715.                         // 速率
    7 @+ s! E7 p0 T* e; F
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;" Q5 I/ d8 Y/ H+ t& U
  717.                         info->rates.header.length = ie_params->length;* Y7 y! R$ N5 T3 r, C0 p
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))% ?2 U) j. c2 ^' o7 T1 t" Q8 l
  719.                                 info->rates.header.length = sizeof(info->rates.rates);* c9 o6 y5 f" x  U1 _" \1 @
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);; l( B+ O$ w$ r7 E. x* h
  721.                         break;6 j5 Y7 Y. g9 U4 t, o* {: t
  722.                 case MRVLIETYPES_DSPARAMSET:
    + B: z- `- F  G7 P1 P
  723.                         // 通道号6 [8 g  Z9 y% t. [
  724.                         info->channel = ie_params->data[0];
    % b# x/ m; H4 ^5 q: Y
  725.                         break;- e2 O: O# Z$ E5 C* y
  726.                 case MRVLIETYPES_RSNPARAMSET:
    6 w1 q; K1 G- n, R3 j3 @
  727.                         // 通常只有一个RSN信息 (与WPA2相关)
    4 l) H5 ~# @# i0 I' Y" w- W
  728.                         // printf("RSN len=%d\n", ie_params->length);
    7 |' s2 h3 }# t7 C6 Z
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
    ! `+ @8 K! V( c: ~# W
  730.                         info->rsn.header.length = ie_params->length;; F% _4 K; z& S$ [* I# `0 l
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn)). Q- Y: I9 b. W) L! i
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);6 K; ?+ o% F) Z7 `4 t) Y
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);4 P$ R& ^! V: c2 g* y3 E5 I6 D
  734.                         break;
    $ m5 M$ [% t- A, g. g
  735.                 case MRVLIETYPES_VENDORPARAMSET:
    4 H/ K$ T* H1 F+ [
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)) W/ _# T, o% L4 H' `5 z! Y: a0 \
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;2 W# n. x- T; V! O2 e$ d; V. J
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)
    ) C- W; r+ W9 q" m- c, ^  T$ M
  739.                         {
    3 C- t$ a' r7 M( W  q" p3 B
  740.                                 switch (vendor->oui_type)
    / |) Q5 H/ H$ R1 m6 J. f) y
  741.                                 {9 x: m/ w7 n) ]3 q6 ?( x" [
  742.                                 case 0x01:
    0 O) r1 T5 ^, O, k
  743.                                         // wpa_oui
    & y! b6 B- a) g" M8 J& n% K
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;
    ' b! u1 F9 X: w9 {
  745.                                         info->wpa.header.length = ie_params->length;
    7 n$ @$ `" x. f8 r0 o7 y; g& i) v
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))) q1 h! V3 A9 [( Z
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);
    . h3 F" [4 B* R6 Z$ w- M& N
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);
    ! @+ s7 K( J0 z3 l+ b! w$ k# r: `
  749.                                         break;8 C4 M1 c2 i$ U6 l
  750.                                 case 0x02:
    4 I2 V$ X* X7 j' X! ~/ u
  751.                                         // wmm_oui" P' |( e' G+ P
  752.                                         if (ie_params->length == 24) // 合法大小
    7 ^* [% U' F& g( x* @2 x( ^
  753.                                         {
    ' ^6 O* }  q# c' {4 D/ q8 Y2 }
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;
    0 L0 h( b- M6 X$ j$ A: z
  755.                                                 info->wwm.header.length = ie_params->length;
    / Z; h8 J0 g9 o: _% q$ |- M% a
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);
    9 u) s: G! r- y1 a; {1 r# r7 {
  757.                                         }* O9 J- a3 ?6 {
  758.                                         break;
    # V: Z0 b3 _' k0 U. h9 y  l( \
  759.                                 case 0x04:+ s# ~( M/ E' R8 W
  760.                                         // wps_oui
    # ~$ s! d* n1 U( c1 F
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;" s' r( r3 a. g
  762.                                         info->wps.header.length = ie_params->length;
    % B: [2 d* Y" M& g/ ]+ g
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))
    ' v* {' F% l+ u
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    . U  L3 B' [1 `8 A+ @1 F
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);
    ! H, c# A+ p! f# H2 t9 c9 r7 N7 N
  766.                                         break;
    / {* a' d6 j: h+ u7 f+ H! L
  767.                                 }  `. @' e: X" Q- z, L
  768.                         }
    1 ?" C. D+ L( C
  769.                         break;) e+ l  P. m; Q; h
  770.                 }6 ~' ?8 R- I8 y
  771.                 ie_size -= ie_params->length + 2;
    4 |" Z6 l# Z1 Z
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    6 ?/ X9 B" z1 L8 u9 Q  f9 o, h+ |
  773.         }8 l: ~+ d8 n- d6 ~& \# l- J
  774.         
    ! C' l1 C' `6 s
  775.         return 1; // 成功; U5 M* p, _8 K' }$ m
  776. }+ w2 s" ?' e0 p; v
  777. / E5 r8 {8 S- W
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)3 J7 {& A$ \: w( ~) V
  779. {. ~! V. q1 L# U  i; l# N
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
    6 `* p7 e! K; K2 v" f0 J4 h
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;& {. Y  @4 O6 Y; i% X# n* Y
  782.         while (SDIO->STA & SDIO_STA_CMDACT);
    # `3 Y$ c% F- l5 X6 B7 Z' w: ]
  783. }; _& d1 ?! q2 m1 U" ?

  784. , h- J; Q+ j/ Z. H: c9 |
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)
    4 {# N+ Y" N/ u6 [+ R
  786. {" r3 w' @+ s# b, Y
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求
    ( b, q; E7 d% \) K& x1 F
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;
    - N2 Z, \) Z; r! {
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;9 h9 N$ ]! p4 S) m2 |" J0 R6 q
  790. }
    3 ?+ a% w! g+ C3 c- f

  791. 8 Y7 z, v1 V) v7 |: v  I7 P
  792. /* 发送WiFi命令 */  m) W( `& ^+ q. a% Z9 V6 q
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)! X4 \; V& B6 I$ c6 I
  794. {# N" m3 X: ^3 h6 ~9 ?6 F2 J2 y
  795.         static uint16_t seq_num = 0;
    " {& N5 R' r% w& _& ~& p
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;$ J# k0 X# j4 {. m% S2 b: e( S
  797.         ! w: E1 I$ O1 E9 E
  798.         if (size != 0)
    & L  b6 K, }& t/ F* c
  799.         {; ]* b1 k3 M  ?  ~6 |* |
  800.                 cmdhdr->frame_header.length = size;7 g3 }% N( C# ]/ m6 v1 l
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;
    + K$ I$ i  q$ G- x* A6 B
  802.                 cmdhdr->cmd_code = com_code;
    5 O4 t2 Y" n& I: w) j% s, `3 W
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部
    2 X1 ?) h& ~# ]1 a' P
  804.                 cmdhdr->seq_num = seq_num++;
    ) b; p- W$ N6 z* D
  805.                 cmdhdr->result = 0;* Q6 k, K; W( G, D  d& R4 J- v
  806.         }
    % [+ t0 ?' k3 @! L# \- l: H$ p8 R
  807.         else$ r( k3 ^$ I1 M# X/ H
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
    ) K5 H* t% c  `0 ~7 ~
  809.         % R/ Y) y# [5 \
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃
    1 X0 V0 B0 v& F4 `. W
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())
    & M' {7 |$ h/ D
  812.         {7 L: t& D& |* G( D8 o9 G- i1 t7 }
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");
    - S0 ?2 {! K6 g* B8 g  X
  814.                 WiFi_DropPacket();* W- }2 u! o: ?
  815.         }/ l1 c" x* d& U6 t, P2 M& U& Q
  816.         
    2 H& o9 ~( ?& x  t; o& T% \0 C
  817.         WiFi_WritePort(data, size);; C8 Z' J) E, R5 y8 U& L: b
  818. }5 ~' X4 V" M7 {  Y  j7 |! A! W! p
  819. 1 C' N% \  q5 L0 l2 J7 c: |) r% Q
  820. /* 发送数据帧 */
    2 i) C+ l0 d! u3 O
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)
    ' e. m4 P8 G- p, q5 ~8 L- J& V9 B
  822. {
    1 v' h  R7 }, O* Z) S
  823.         uint8_t ret;% z3 R% V% }* T6 f$ G6 W
  824.         
    3 S6 U6 ?+ J1 B0 i1 w+ X# P
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path: r- G7 i( n% q( r- w' E0 g
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
    5 I& b. h, L  a2 B" P! _
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;& w8 h$ S$ }: x, G2 v
  828.         
    ) w+ w) C( }' t; ]+ u
  829.         packet->reserved1 = 0;
    " h4 m6 s; D! o
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings+ R: j0 e0 I+ R; f' Y
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader6 X9 }& n! W/ e. D% Z# n+ f/ @& k
  832.         packet->tx_packet_length = packet_len;
    0 `; c2 Z$ R1 e0 i
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);
    " g. O6 e* z! ?4 {; [
  834.         packet->priority = 0;
    2 G3 T' j: d$ |- x9 K, g  g
  835.         packet->flags = 0;. P. [& C! X6 M, u5 R1 r8 |
  836.         packet->pkt_delay_2ms = 0;$ |1 f# Q$ }+ ]+ K: Z1 W, e
  837.         packet->reserved2 = 0;
    ! q7 }* i) a" N: x
  838.         
    & g) l( B6 t1 E) G6 N8 q( }+ _
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小* O- ], ^: c6 Q9 w! T/ D" B
  840.         // 未读取之前不会收到新的数据帧
    0 c" `( B7 c' _8 J
  841.         if (WiFi_PacketArrived())5 I6 I3 ^0 r. M3 v
  842.                 wifi_pending_size = WiFi_GetPacketLength();
    8 ?2 \; ~  w# s3 ^  v/ C  L7 I2 r
  843.         
    1 B6 I+ {; j) d" U6 V& u
  844.         ret = WiFi_WritePort(packet, packet->header.length);
    6 c* `8 x) w/ L% \2 v
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
    ' {* ?  g8 Z& d
  846.         return ret;
    : ?2 z- P7 D  c+ U
  847. }
    ' ~% i- M9 j9 }- }

  848. ; \/ L+ d' Z( n; c
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */0 D4 ~/ I! f* G& I- H* X( t
  850. void WiFi_SetBlockSize(uint8_t func)- K5 V0 q. {" D$ J2 ^
  851. {' V- f/ M9 h, l1 m: J
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)
    / t/ D0 T( t& j6 j
  853.         uint16_t size = WiFi_GetBlockSize();
    " M+ j' y' X& V2 K
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);
    ) i5 K4 T4 h+ v( C# B; m: w
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);! j8 X& O5 _# E5 Y% `& e4 O- K/ G6 A
  856. }/ [+ U' |0 r: `/ C, p9 K: D4 ?7 }
  857. - T5 P  K9 N/ m! S
  858. /* 设置密钥 */4 E3 R( s7 f9 G
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
    - p) W: w3 j* J' f: h& I8 @
  860. {) d$ k7 c5 |" h; _
  861.         MrvlIETypes_KeyParamSet_t key_param;
    6 z4 p7 Y: {  t8 q7 l, H
  862.         if (len > sizeof(key_param.key))
    # O- h; \8 U$ W' B) {1 S, ]8 R
  863.                 return CMD_STATUS_ERROR;
    % {& r3 |1 T1 E7 \5 [1 b
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;3 J" T+ \2 I( u3 P
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
    : E" Z% ~% Q, R4 B, V/ O4 S( e
  866.         key_param.key_type_id = type;/ l* ?2 Z% D' l
  867.         key_param.key_info = info;1 C8 c" c9 {  `  m
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
    # C; `8 _; g. B
  869.         if (len)1 ]# d- B/ Y/ O7 G* {- H0 _
  870.                 memcpy(key_param.key, key, len);& R. V5 P* z' T4 U0 N
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    ( c7 J, v1 ?6 o% t3 u5 ?: o" T6 q
  872. }5 G3 a9 O; h& `$ g. r! C6 x( \, F

  873. : m. j, y) b* z; j" f
  874. /* 显示WiFi模块信息 */# O7 K: s* F# y. R8 |
  875. void WiFi_ShowCIS(uint8_t func)! Y9 D" A/ O' X$ n, r. i$ {" C: `
  876. {
    3 w5 Q( T% Q) z* h
  877.         uint8_t data[255];4 h# g3 {& p2 }- Y
  878.         uint8_t i, len;
    : C" Y7 {! L% j; Y9 m
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure  [; p9 z( `& |/ P* N% ~
  880.         uint32_t cis_ptr;
    ! v9 W4 u* _* t
  881.         / y" U) ^+ A: X# K/ [' o
  882.         // 获取CIS的地址
    & h8 E' x. _3 S& V, N& G
  883.         cis_ptr = (func << 8) | 0x9;
    2 j. w8 i* B; o: O$ g
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    . \8 @2 t: ?% ^, H% W
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);
    ) z$ A) B" Y( {3 U7 b2 x: I
  886.         
    * L) i3 h9 j# h  u
  887.         // 遍历CIS, 直到尾节点
    ) ~: O# K8 I- m- n; s
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)- |# ]$ y5 h! ~6 Q: l6 f
  889.         {( _3 D9 \1 i- R5 M1 N* N: b# @% y
  890.                 if (tpl_code == CISTPL_NULL)
    2 ]" r- V8 G$ S7 D, S5 L$ `; |
  891.                         continue;
    ) I+ w+ s0 H" m" l" U( G, q1 f
  892.                
    3 w; A) e* T0 k+ Z: p) E5 n/ K2 }* b
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小" X' b8 A7 T: [2 u5 [' q
  894.                 for (i = 0; i < tpl_link; i++)% N- }4 W. T. {
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    9 U) R/ x$ w" x! `$ _) o
  896.                
    7 p: K/ H; m5 h0 W. k  c$ M* V
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);6 g7 c: V  A% R; S) D9 n9 n
  898.                 dump_data(data, tpl_link);% ]2 W& I, t% T
  899.                 switch (tpl_code)
    " E7 i: O* n, _8 T( I/ w
  900.                 {: }0 g, T! K) O* l0 t( }+ \
  901.                 case CISTPL_VERS_1:
    / x0 e5 N& H) x, m. Z5 X
  902.                         i = 2;) e  A' x6 q7 r. _" U& d7 b
  903.                         while (data[i] != 0xff)6 L6 S6 [- E( c, Z
  904.                         {1 |! g% S# `1 c3 x- L" ?/ ?  n6 r2 t
  905.                                 len = strlen((char *)&data[i]);
      Z' p! }+ `  M/ |: T8 X  l$ Y9 J
  906.                                 if (len != 0)5 [& A* J9 Y0 V+ Q& R" _0 z
  907.                                         printf("%s\n", data + i);
    " T* d* P' u2 a
  908.                                 i += len + 1;+ X* H2 O9 g$ r
  909.                         }
    % Z" H- Y6 j5 v+ Z1 M( B; m
  910.                         break;9 f2 ]" F4 m; [1 b' ?
  911.                 case CISTPL_MANFID:: d  I2 D: i6 E  k
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple1 t  i8 @' ?; ]) A
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF" S, t, V% h, e8 ?8 h9 o
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD7 R/ x$ N" C1 H# R4 p; l* W
  915.                         break;3 ~8 R; @, E: b/ ?
  916.                 case CISTPL_FUNCID:
    4 X# q! S, z- N) D' z+ V
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple4 h  s3 U* f3 z) o7 `
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
    5 T0 k2 I1 E7 s, f+ B
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT; D! e; d! ?9 E+ g9 L
  920.                         break;# c' N) R9 B. x3 A2 x
  921.                 case CISTPL_FUNCE:
    ' ]6 V3 r' c3 ~8 w4 t# x( o
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple2 c1 n2 S% O. Q, g( p  L
  923.                         if (data[0] == 0)
    5 |5 F0 i/ Z8 }) K- p3 E- I2 ~
  924.                         {! g/ j- F9 O7 D: U
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)
    3 d1 r& v/ C( o9 c5 V
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));
    2 I) O$ ^4 y$ i+ {* w( H' ^) N7 Y
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);
    # j, n/ ^+ B( v; q$ C$ r
  928.                         }# F" Q$ E. H( w" g) k$ T+ \, v4 K
  929.                         else
    % v- P! H; Y7 x, y$ Y/ n) ]
  930.                         {
    ( H0 b) t0 l- h" D5 b
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)1 I% @& A1 h2 |# D0 ~0 ^6 H2 C( S
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE" @, ]" X2 U2 l* n& d+ o" j
  933.                         }
    3 w: }  q( \: b0 e: g2 V. e
  934.                 }( h$ e6 X2 r8 C! ^) g, o
  935.                 8 d. T) }  s) o( v. P5 u
  936.                 cis_ptr += tpl_link;
    5 r# I: C5 ]' n' N) M  U% {% U1 U
  937.                 if (tpl_link == 0xff)
    $ z+ K" y. \! x6 c4 B4 l) ~4 P6 m0 S0 ^
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点- l8 }1 ]) v2 `! B5 k' j
  939.         }
    ( ~' q  v, c9 C' @; f! C
  940. }$ i$ l  a. I! P9 g. |/ r8 U

  941. 2 W5 U, H+ X1 `7 M# |9 z" q6 o5 a
  942. /* 显示所有密钥 */
    ) j% S4 o# P8 R6 N7 }' U
  943. void WiFi_ShowKeyMaterials(void)9 P8 L& {3 y/ O9 z+ m* M
  944. {
    3 i1 z3 I- }$ Z2 y! T" ?5 K
  945.         uint8_t buffer[256];7 S; A2 l2 N% z  a& z
  946.         uint16_t size;7 y) Y1 ~; E- q% P. h' e4 s
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;6 A) W! X# u4 U; w+ c) H8 T' e( C% s
  948.         
    : j8 U* H) _& f1 v! h
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);2 D+ h3 b  o7 V" z, Y0 e7 G; Z9 q
  950.         while (size)
    ( X2 K7 `9 y6 u2 n( {/ @# @
  951.         {
    " r% C% \' c: V/ S+ F# T7 u
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);) t/ s& Q% {2 M) B4 I8 x
  953.                 dump_data(key->key, key->key_len);' r9 K5 F7 P* i+ L! t1 b0 i" E
  954.                 size -= MRVLIE_STRUCTLEN(*key);4 P9 O9 Y  _5 d# n1 ~
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));% c$ X* c9 ]. J
  956.         }, w8 Y* O2 C% p' K+ @; M, z
  957.         if (size == 0)1 y; W; L0 n7 }. |4 g) K; l& s0 @) }
  958.                 printf("data end!\n");
    " @# x# G) c5 B/ X1 K* e
  959. }
    " N6 c" z2 R3 m# F" r4 Q* M

  960. " @6 S# T9 ?5 T" [! p: f. M' e
  961. /* 创建一个Ad-Hoc型的WiFi热点 */
    ) T) F; M! p9 |# ]- X3 J2 d
  962. uint8_t WiFi_StartADHOC(const char *ssid)
    * W5 S% Q% Q: i, q1 o. b
  963. {
    2 J6 r9 Z  M  [3 t
  964.         WiFi_CmdRequest_ADHOCStart cmd;! o2 e% c; w/ d
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
    5 }8 N2 O$ }% W( C- a2 l
  966.         8 c# d" k6 @) {5 d' y; G- s
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));, N8 n+ M- S$ T( H! i& V( G% c
  968.         cmd.bss_type = BSS_INDEPENDENT;+ D9 P0 S+ I) H# P2 \5 i! R: j
  969.         cmd.bcn_period = 100;1 o5 D: {* }  O; W+ ~
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;
    4 M2 K- E1 |7 Y- M1 Q: n# v
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);1 H8 @* b& V+ T4 A  D
  972.         cmd.ibss_param_set.atim_window = 0;  n, o" ~/ `/ E
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;
    + I5 C1 `2 Z  n  D( M8 B& h
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);( W2 ^+ j3 J: r! |5 y
  975.         cmd.ds_param_set.channel = 1;! ^$ U8 a" q9 ]4 n0 w  M
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;* ^% B- q; t4 `9 |  N1 ]
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;5 }3 x; m2 d/ p# b' L1 Y
  978.         5 h9 ^5 r' }! F6 `" p" Y0 O! u8 S
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));6 e. B/ q9 a! i& a. t
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    5 @) q4 S- P" v: r" y9 P( D6 @
  981.         return cmd.header.result;
    " c  b! [, Z5 G; b6 r
  982. }, [& a! Y# V" l  L* X: w" W% |

  983. / w8 G. j. a1 Y7 G- V
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */
    / R$ }6 S+ g2 m( {
  985. uint8_t WiFi_Wait(uint8_t status); G+ J/ I, ?9 C5 j# b
  986. {8 Q: X. u6 ~4 B  }
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    # e4 O& p; L7 A  y! T/ c
  988.         WiFi_PrepareTimer(wifi_timeout);3 Y9 m: j: s7 Y& a6 l
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)
    0 P1 d! J$ V0 J9 ]( X
  990.         {( |) _; X8 X2 t- U) D% a( o: |
  991.                 if (TIM6->SR & TIM_SR_UIF)5 z1 e" r, }$ ?2 \, }* I
  992.                 {
    ! e! m5 i! T& G8 Q0 c' M
  993.                         // 若超时时间已到
    ! l& V' b- z7 `5 n) q1 {. s
  994.                         TIM6->SR &= ~TIM_SR_UIF;5 [9 j; R9 P4 b0 Y2 \9 V) n/ q9 V1 B: I
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);% l2 g; O! q, J  M) M: v5 o# O
  996.                         return 0;
    2 M# T6 J3 a/ r, M
  997.                 }
    / U* y$ ^; `( v4 R6 j! x3 D& w! f1 w
  998.         }5 S2 h; ~9 [0 b+ L; d
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器5 T9 L1 N9 f! D  I4 p% E: K
  1000.         return 1;
    7 y* P9 N1 c9 _' C+ o4 ^
  1001. }
    1 [$ \- t  [# f& q! O6 S8 v2 K

  1002. ; O3 p$ Z, P. r
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */
    # D8 a0 L4 E1 l- c+ k7 B
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)$ N3 s$ P# `: O7 V, {. O5 R
  1005. {" D; [, c+ K6 h% L( p
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);3 W& d; _" m; `* r% N; z! J
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)9 c" [1 u; D0 ]& b# {5 P3 l4 A
  1008.         {
    2 B: Z- Y7 V$ _6 h. O4 o
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;& h8 ^: p- \( K. [
  1010.                 return SDIO->RESP1 & 0xff;
    1 S+ y5 T$ j2 \" ]  p% @5 h
  1011.         }
    ! q% V1 O$ I1 P; @0 x& ?
  1012.         else% c; E7 R; A' c. F& u! X/ I) o
  1013.         {  t) R8 S1 {+ |5 j% p
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);8 q/ J9 _+ F. U; ^' E" V! q$ m& M
  1015.                 return 0;$ q& e2 k8 S1 Z& P
  1016.         }
    - A: K1 Q# r' x, r5 P2 J& n
  1017. }
    " Q6 O" x- b6 h. a. f* q6 J/ H$ y
  1018. 3 f' P( z- }7 U
  1019. /* 写数据 */" C, O. i, k# T1 `6 H+ E6 B# s
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    ; Y+ n  c. O+ T& ^% n( s( _
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    1 Q2 u! [! B+ q) }+ I
  1022. {1 g2 E/ ?9 {/ D% w, u$ C2 `
  1023.         uint32_t len, temp;- t0 m5 l) J- N& e4 K
  1024.         if (flags & CMD53_BLOCKMODE)
    9 P& H0 l3 v3 E7 }
  1025.         {
      w- M  d, b( T4 y+ i& E5 c: w
  1026.                 len = count * WiFi_GetBlockSize();" L! w0 W6 ]! s4 _9 f# Y
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;* r0 n- P8 f) }+ F2 H' r  s
  1028.         }6 h/ U0 M, }% Z* K" }
  1029.         else
    : X% |- K! d* Z/ w. o9 v, j: |9 I9 e
  1030.         {
    & n( C% }3 y9 N  j: R5 |$ M: d
  1031.                 len = count;1 P' _6 x3 b: Z' V
  1032.                 if (len % 4 != 0)
    ; W% o, x" y2 U& m4 O
  1033.                 {
    ! r/ u. c3 t) H* B
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    1 _5 N6 W! W7 ~  S
  1035.                         count = len;
    $ Z6 |+ X% c& C& ~0 R3 _
  1036.                 }
    - r+ f% [" v8 V
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    # N- w: \, L3 ~, O$ S
  1038.         }5 B/ c# K9 J, t% ]1 m4 q
  1039.         SDIO->DLEN = len;% P3 N' S$ x, ], C/ r! Q4 Q, L
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块
    ! H; o% y7 r/ u& Y9 }
  1041.         
    ; E+ h# f8 C& @* y
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);. p8 H* j5 ^8 r2 N! r
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);
    , i5 Z6 y- W" r
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0). B8 `# F# W7 y" q
  1045.         {
    1 K- \5 r: T8 g; e4 Z) Z
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");
    , d3 i. N  U3 |! N# R# w
  1047.                 return;  W! H: _% c* n# z6 S" N/ X
  1048.         }; x2 L% C7 m* C6 t+ C8 B
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;! d2 p% K* i- d% W1 q- @
  1050.         8 |9 x. [$ s7 F4 M2 m* p# ^
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据
    ( A5 `5 a: I$ h& @) H
  1052.         while (len)
    $ l0 l) f$ r3 Q3 d1 q" M$ s+ S8 w9 X
  1053.         {# J) f! N: }4 v* Z
  1054.                 len -= 4;
    ) R6 u+ J& z9 Q1 A
  1055.                 if (bufsize >= 4)+ a5 ~! o4 f/ q; `0 m& C
  1056.                 {& s0 A) q2 C5 W/ ?3 o- l
  1057.                         SDIO->FIFO = *(uint32_t *)data;
    * e, N; v: _' Y& d9 P' r
  1058.                         data += 4;
    0 ?" g: }8 p8 X5 q
  1059.                         bufsize -= 4;, _( v% y' }/ ]$ l8 q- F1 W
  1060.                 }
    & g! T2 z. T- n- h0 `5 b
  1061.                 else if (bufsize > 0)* C8 ?+ K( M6 G' f7 t+ o; \
  1062.                 {2 I! q- }( b* v6 \; F3 b
  1063.                         // 发送缓冲区最后1~3字节
    . |; x  J1 I) \4 v
  1064.                         temp = 0; // 不足的位用0填充
    ( f0 O& ]3 j4 \6 T9 j
  1065.                         memcpy(&temp, data, bufsize);9 {6 c. L. L# f0 O
  1066.                         SDIO->FIFO = temp;
    1 A* I7 x7 z/ B9 F4 N9 o. d7 U! T4 J
  1067.                         bufsize = 0;
    . C+ ]* {. f; a# u# K
  1068.                 }" o6 z) Y- g1 N/ [4 M2 g' b3 @
  1069.                 else
    * P" M7 c& @0 Y/ C" d! L
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0' i/ v) [0 o$ [: C* y; x
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待
    % d/ Z0 f8 R. \" p
  1072.         }
    2 E. ~9 H2 N, H0 Q9 h1 V5 r
  1073.         6 u: H/ T1 V1 O& [0 b" x" ^
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕, q6 f- D" M0 M( o
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误. U$ o; ]( y# }) G" ~
  1076.         
    2 e- F5 ]5 ?+ x2 @0 z
  1077.         // 清除相关标志位
    6 T: j2 P1 W% O: r
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;' f$ ]7 M% g  f' F( y2 V$ m. S
  1079.         if (flags & CMD53_BLOCKMODE)
    ! t0 \2 I, ^* \( E
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
    + [7 V; V- N& [# L- ]
  1081. }
    2 b7 @  n7 d2 _: L: H* R( m1 M
  1082. : E5 h1 l( z7 X7 z
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size); K: P/ n1 U; {1 X
  1084. {
    $ M" ?7 o; X% I; B* d
  1085.         uint16_t block_num, block_size;- U% g5 U0 f: \2 z3 F3 E( W$ J
  1086.         block_size = WiFi_GetBlockSize();0 B  V& e8 F4 C; O' e/ q" I: {
  1087.         ; Z! v8 S8 C6 |- E0 \2 @
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    1 m1 Q. S7 F1 H  v  `5 ?- B
  1089.         if (size >= 512 || size % block_size == 0)* m- E& d+ ]# I/ y% T
  1090.         {, a% [9 R3 t* R5 `, u
  1091.                 // 采用Block模式传输+ j' @0 T4 W9 [( j3 o
  1092.                 block_num = size / block_size;# R+ I) A7 G1 \) C. }
  1093.                 if (size % block_size != 0); Y2 [1 t3 [9 W+ f4 v# O% q
  1094.                         block_num++;
    7 }  [8 j+ }) h  V
  1095.                
    / W3 p8 ^# h5 O6 ^0 D% Y
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);
    0 M: u; K3 u: y, y+ A; T1 q
  1097.         }
    4 G; |  W: ?% e6 l8 R
  1098.         else
    ; }# }" [% K' u( x' z1 S
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);0 X* b- P- k0 R# n3 L
  1100.         return SDIO->STA == 0;
    " l) P' y5 W' \! N7 ^! Z' g
  1101. }! L, U/ P. W- `' j  o" R, k
复制代码
8 x2 w# W7 Z5 S& m. b

& I* o# Q0 t' t" {在工程的所在文件夹创建一个lwip文件夹。" B- O/ \/ p; p" j
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。) g8 A3 b* p4 f4 T) H' u

4 m/ a; Q; x& Z3 Y# W7 b1 p. i- @core/1 N/ u$ ^3 f3 X- Y
core/ipv41 C1 t2 P) A5 t8 X. E
include/lwip
' _- Z0 H& c7 \0 F% h$ U" Q. kinclude/netif1 a8 C  k, T5 `# |+ v, w1 t/ }; [3 X
netif/ethernet.c
0 C  N2 C3 Z' i- n( n4 P$ [netif/ethernetif.c
, m( y5 P. \; l8 @* ^
3 W3 u5 O. `/ p! b9 A解压后,将里面的c文件都添加到工程的lwip分组下。2 \; ~6 q( q# N8 @
具体添加的文件请看下图:$ \* g( Y6 w' ]$ a

6 c, {$ D* O1 S' T5 V0 X! W/ q  e4 d8 _7 f
接下来,创建lwip/include/arch/cc.h文件,内容如下:
" i% K) h* c: o3 T7 ]! S, K8 D7 q9 L
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:
' f% W. B' i$ I- }1 B$ q  x
  1.     #define NO_SYS 1 // 无操作系统  
      i! \; F1 v) j, E$ Y
  2.       2 ]) T' b, W6 J
  3.     #define LWIP_NETCONN 0  , V8 I& J/ x  E0 |$ d0 W  [
  4.     #define LWIP_SOCKET 0  ( @$ f! x: G; m
  5.     #define LWIP_STATS 0  $ D1 J' q: E1 ^8 J
  6.       . ?. [) w+ r( {4 K# j
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  
    ' P, U1 t+ C3 l8 s; |9 i8 r+ c
  8.       
    $ O! X/ G' U2 J6 d1 C  }1 Z
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:
5 Y5 H, g  V% V
  1. /**
    # S1 O% r- f# V4 E' d
  2. * @file) d  r: r& I7 F2 l
  3. * Ethernet Interface Skeleton0 j- q. L% I3 m. e/ O
  4. *; F3 G7 c$ z3 k
  5. */& X9 @3 |/ [0 C- A' @$ M; p; R

  6. " L5 e: }& k2 u+ ^9 c: |$ q
  7. /*
    1 S& X# I8 M5 G/ k# E
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
    1 ?  g% j, j9 O2 P) I. z
  9. * All rights reserved.
    " n5 r$ j: e% q5 e" p2 y
  10. *
    ( S. f- h- o+ y" n: i3 H5 ~
  11. * Redistribution and use in source and binary forms, with or without modification,
    ) v6 s" s# L1 Z# P+ f& ]7 X
  12. * are permitted provided that the following conditions are met:* o7 U( Y* ~8 ?0 C" C
  13. *$ {& V' c6 v4 L1 N. m) w
  14. * 1. Redistributions of source code must retain the above copyright notice,
    " [5 N6 k& Y( b7 W
  15. *    this list of conditions and the following disclaimer.
    * l% a# h0 o7 V1 w0 l, A: O
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,
    + Y/ u* B' @" F7 Y9 \: c1 S6 N  l
  17. *    this list of conditions and the following disclaimer in the documentation) d$ N7 N* T6 ~8 r$ i# C$ J0 U
  18. *    and/or other materials provided with the distribution.1 u5 p! T% k1 W- X: ^3 Y: J
  19. * 3. The name of the author may not be used to endorse or promote products
    3 T8 H7 _& J- c+ Z1 i# X, A+ {
  20. *    derived from this software without specific prior written permission.
    0 W4 J# l. ~3 i; m/ `& g$ @
  21. *8 F9 P, t( V$ v
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    ' {* X# H; W6 }) N8 g( C1 k4 \! t& k
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    / B, y: ]. s; s: d2 `9 Q
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT3 @$ W2 f3 U9 S3 w# w$ d8 M- n4 X5 H
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      @, ~* t- B7 B1 D# e! u# A3 [
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT+ K' d3 w3 o; |
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    3 b3 m% a7 S5 y' G
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN# f0 x, f6 @1 l) I
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING# L) g2 V# G# ]! h1 B( Y
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY- y8 ]3 ^( O9 Z; ]. n- q
  31. * OF SUCH DAMAGE.9 N' l& [& d! }. [. f$ n/ F9 ?
  32. *
    & a6 g3 o9 y! n2 d
  33. * This file is part of the lwIP TCP/IP stack.
    & H2 [: Z$ T4 N# o1 s' s
  34. *+ q  r" L! B: {7 L* t+ h
  35. * Author: Adam Dunkels <adam@sics.se>
    0 ^6 {% Y6 r) L' n9 j4 t
  36. ** ~0 \4 j$ C& r  G4 x  C0 ~7 _* s1 L
  37. */
    8 ^  l( E3 g* H/ e

  38. 4 W& L2 A) _2 n5 U4 F
  39. /*. b- I! H' e7 z. l: x( J
  40. * This file is a skeleton for developing Ethernet network interface
    9 ^* M, I" l9 M+ b3 o
  41. * drivers for lwIP. Add code to the low_level functions and do a
    ) ]6 I+ G/ f# q* W8 m4 n9 n
  42. * search-and-replace for the word "ethernetif" to replace it with) ]" U! s6 |) Y3 W1 X
  43. * something that better describes your network interface.
    ! e' }7 g& h5 N* K
  44. */
    " g/ D7 ]2 r, N1 D" X# @# g* B1 f

  45. 2 o( p0 `& ]% g! h
  46. #include "lwip/opt.h"
    . J) e* m! O+ C# [2 U
  47. 1 z# Z/ y. j9 q3 |5 E
  48. #if 1 // 允许编译器编译该文件' v2 T7 D9 G1 D$ r

  49. % |4 p5 h  d  s8 ^% O5 _
  50. #include "lwip/def.h"
    ! s! g( N; Y+ T  q3 s
  51. #include "lwip/mem.h"$ E+ W  R+ Y+ _0 _
  52. #include "lwip/pbuf.h"
    & s- H. ]0 d( F! D) s) ~0 b
  53. #include "lwip/stats.h"
    $ M* J6 d6 r% D1 z9 C
  54. #include "lwip/snmp.h"3 V6 R* I6 a- n5 S4 r% k. i3 m
  55. #include "lwip/ethip6.h"! r, K2 z! E7 ~# O/ C& a7 M
  56. #include "lwip/etharp.h"
    + w3 _5 _" }0 ?7 Q/ G
  57. #include "netif/ppp/pppoe.h"
    : Y+ |; S+ a% |4 U" X3 v' G+ q5 G
  58. ; ?; A3 I! J+ ?# C' j  ^& Z
  59. /* Define those to better describe your network interface. */
    ) i. }; f* l- g
  60. #define IFNAME0 'e'
    . N% E/ N( C3 R* ]! t
  61. #define IFNAME1 'n'5 Y, ]% _" c1 x3 ?

  62. + S! S) Z) t. `5 @' H! P. q
  63. #include <string.h> // memcpy函数所在的头文件- ^' Q6 `7 i: n9 I
  64. #include "WiFi.h" // WiFi模块驱动程序头文件6 j" C5 V, I* a' S& v

  65. : N3 j- ?8 [% J' p& S, j' J
  66. void dump_data(uint8_t *data, uint16_t len);# N0 X/ H" h$ l8 J. I

  67. ) C4 j8 U! J% F) ~( M
  68. /**& a! Z* Z. Y! q& I8 `9 |9 z) h$ h
  69. * Helper struct to hold private data used to operate your ethernet interface.
    & f4 M1 [3 Q; Z/ l9 {" ]! ~
  70. * Keeping the ethernet address of the MAC in this struct is not necessary  K! t* a4 `# Y0 S: `
  71. * as it is already kept in the struct netif.
    + N7 A! s6 h, ?0 E& k$ V% X
  72. * But this is only an example, anyway...) z+ s2 N- k9 G; f& I; Q4 o0 i
  73. */3 V3 \% h! J/ j# t6 q( S
  74. struct ethernetif {
    1 }* I# {4 T. S* b' D8 U( p
  75.   struct eth_addr *ethaddr;! \7 y% R( ?( e" k
  76.   /* Add whatever per-interface state that is needed here. */4 }7 W) Q' ^0 w
  77. };8 V' _/ F6 u8 B, t

  78. % U+ N$ G' R4 I+ i0 \
  79. /* Forward declarations. */" K. @! C4 m& H
  80. // 这里必须去掉static
    . e: e3 i- @* Z, `
  81. /*static */void  ethernetif_input(struct netif *netif);
    ) t+ ]5 N/ N/ A! d- P- V' S9 V  n9 t+ o
  82. ! g  {0 y& L0 J. n7 f/ q7 G
  83. /**
    $ i, [. b1 _% x$ g5 A+ u& Y
  84. * In this function, the hardware should be initialized.
    4 r5 a' `. _' E. \/ M7 J% ~2 C
  85. * Called from ethernetif_init().! i5 b0 g! r' a) F+ e. Y+ ^# N
  86. *- Z- S& K1 N5 l. g1 A, c
  87. * @param netif the already initialized lwip network interface structure1 C; u6 y# v6 S3 h* M- S- J
  88. *        for this ethernetif
    + o# q- V; q0 ]( M' v5 r. t  h
  89. */( v: z% r( j5 ~5 h1 U
  90. static void, T/ Z0 k- \- j; |# l8 R* O
  91. low_level_init(struct netif *netif)
    ; k7 x! C5 _( I$ U/ p4 N
  92. {7 X. [9 ]6 B  \# \2 A0 M
  93.   struct ethernetif *ethernetif = netif->state;
    5 z! ~( E9 l6 b1 i7 k

  94. 2 M* ^  i0 o3 m
  95.   /* set MAC hardware address length */
    3 x. \+ m& X2 P6 w( W0 j2 M, ~
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;
    " M/ ^# p6 \1 u8 `" n. X# [0 O
  97. " w: _1 A. t8 b0 H2 l$ O9 P
  98.   /* set MAC hardware address */4 a# Y5 c$ ~2 B7 l) r
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
    ( l$ t) v5 ~% l  t8 O! o' V
  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]);
    & S5 d4 N7 r" H# ~& [8 Z
  101. 4 }" z1 c; I$ B6 p. Q! V# Q
  102.   /* maximum transfer unit */. w3 W# `7 Y6 f$ g$ _6 [& Z
  103.   netif->mtu = 1500;
    # P$ R/ P3 H* P1 o# \
  104. 6 ^/ V# t4 G, a2 e) M( @: v
  105.   /* device capabilities */' P' a, r  q0 v5 C& L' R
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */( [( b" l3 P+ N) W( N5 J
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;$ x# {5 i& y  F6 ~% @/ b
  108. $ p& s0 j3 o  ^' e5 }8 q- k3 m
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD" x7 N4 s6 g: i' ?
  110.   /*
    , J/ w5 ~( I, t/ ]+ ~# c* s
  111.    * For hardware/netifs that implement MAC filtering.& }5 ^! t# d, {4 A2 A, A* B) x
  112.    * All-nodes link-local is handled by default, so we must let the hardware know1 r$ m$ q2 Q2 n/ P  l4 e# p( h9 h
  113.    * to allow multicast packets in.# ]# p; ~* @8 i1 I& ?  p2 J
  114.    * Should set mld_mac_filter previously. */2 w1 q, X& O" _; p* x6 u/ b6 O
  115.   if (netif->mld_mac_filter != NULL) {8 e9 t3 }- D! {+ U7 Q) O
  116.     ip6_addr_t ip6_allnodes_ll;3 Q; v7 M2 O7 d0 O- R! S0 B
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);& O( q, P; K* T. t4 ~
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);" e7 S' d4 Z" N7 a* ~+ i
  119.   }
    ) k! z5 x* I) K/ N& e  Y" d
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
    ; ]" s0 e2 d, k

  121. : b" K+ U/ l/ i9 ^$ b: `
  122.   /* Do whatever else is needed to initialize interface. */9 S: n& k) ?  {5 w: U
  123. }3 r$ _' l) `5 s4 `9 q3 C% ]
  124. 7 C+ J; }; b5 p/ {/ o  g' g. q
  125. /**1 [, T" V1 v- E7 p* v0 J
  126. * This function should do the actual transmission of the packet. The packet is
    % L5 s& M; M* z% ~! ~% f- m4 Z
  127. * contained in the pbuf that is passed to the function. This pbuf
    7 ^8 R$ T: D& P( \6 ]
  128. * might be chained.
    3 J- j) m7 s1 ~; B7 x4 _
  129. *
    5 e4 G9 Y- c% v+ J8 K; T: j& d! w
  130. * @param netif the lwip network interface structure for this ethernetif  O$ ~7 M8 D+ T  d' m
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
    7 [* U) r% u8 J) }. a
  132. * @return ERR_OK if the packet could be sent
    1 _# Q& x2 b2 y& X/ _& X5 v
  133. *         an err_t value if the packet couldn't be sent
    . x$ c  q, j7 C" w: B7 w! i! z
  134. *
    . C% P( e5 }& J. W) f
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
    7 U* N9 H3 F" B, G, \) s
  136. *       strange results. You might consider waiting for space in the DMA queue
    ' K3 W; h) X" F
  137. *       to become available since the stack doesn't retry to send a packet. X+ X6 l/ B) @) B8 n& U5 f
  138. *       dropped because of memory failure (except for the TCP timers).& g* O: N8 e& H! b: R7 b% t
  139. */
    , [2 F' a7 O, B6 o- k1 v! `( D
  140. ) V1 \6 Q5 D, S" `# K# v
  141. static err_t
    3 W8 Y" h) S6 V9 X
  142. low_level_output(struct netif *netif, struct pbuf *p)
    ' \# n5 E' O: c7 U* `
  143. {
    $ y' @; q6 {5 b0 C
  144.   struct ethernetif *ethernetif = netif->state;" U7 \/ m, y- |( ~* X
  145.   struct pbuf *q;6 F" I- ~, ]! t- Y, V" k% h
  146.         , W  o1 S& f- k- E
  147.   // 添加的变量
    . M: b8 B" c' V) L$ M; d
  148.   uint8_t buffer[1792];0 Y' U$ f  b. f/ g, m* p9 w' ]/ |
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;: n$ J$ L9 y7 z. d
  150.   uint8_t *bufptr = packet->payload;
    8 O8 q+ E# F3 {
  151. 4 `3 h/ P* P) S  k4 h3 w: v7 d
  152.   //initiate transfer();
    $ c6 h/ l( V9 z/ ]0 X6 O
  153. : b; K; }6 B) a8 b0 T( C1 I) x
  154. #if ETH_PAD_SIZE
    0 Z5 X8 X5 f# ]) G; B2 e( y, k9 g
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */2 b/ F7 U; y$ P
  156. #endif5 K, u, j: p  g  q" ]
  157. 4 ?6 `- I7 P. Q8 b% R4 D* U( ?
  158.   for (q = p; q != NULL; q = q->next) {8 [# I' {$ K8 u" A! {& c
  159.     /* Send the data from the pbuf to the interface, one pbuf at a
    : z! R  }4 ?) L; `) c2 ~, f
  160.        time. The size of the data in each pbuf is kept in the ->len
    / S. C# Y5 n: S0 `9 }' Y; g2 d  k
  161.        variable. */
    ( S6 E  `2 A% Y8 n5 j3 g
  162.     //send data from(q->payload, q->len);
    - B$ v3 e4 i) ]) t% p
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容
    + }' c9 T* ?9 f5 {  i
  164.         bufptr += q->len; // 指针前移$ G! p9 _7 m5 d
  165.   }
    + Y" I* U5 n4 d! \: x' |! e2 X5 v

  166. 9 N& F# `  Z+ _4 t7 P4 `2 H
  167.   //signal that packet should be sent();
    , K( m0 h4 i8 \; X  m7 m+ L
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包+ {$ z$ m$ j  F% `' H$ r% o; h3 R
  169.   
    8 o8 [4 h; c6 q' c$ ^6 {, C
  170.   // 打印数据包内容9 @1 y- {$ c) O, J+ c/ T
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);
    5 I- a* J; x$ ?! N" y! F
  172.   dump_data(packet->payload, packet->tx_packet_length);& K5 t. h& s# ]/ u3 c- y

  173. 5 k2 |8 |# x$ J0 L/ k
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);! X# X5 ~3 x1 g, D- ]  m
  175.   if (((u8_t*)p->payload)[0] & 1) {" ?+ I% C, N0 C7 A0 h; e- E$ o( @
  176.     /* broadcast or multicast packet*/
    ! w, H& e: ^/ c4 r. P
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
    ! u+ y# s+ x# g; ]: |- B- F+ x% u
  178.   } else {7 g, n  R1 l- C- i$ N, o4 \
  179.     /* unicast packet */
    1 q, }; H2 Q3 H% l. c2 `6 K, e
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
    & `8 x2 b$ W: b3 U0 m/ `
  181.   }( t' Y+ u* m0 d; B
  182.   /* increase ifoutdiscards or ifouterrors on error */
    ' U. l4 b4 v1 T& f

  183. ' n8 z9 a: ^/ r% K6 x2 O& _; v
  184. #if ETH_PAD_SIZE
    5 N3 X, b# ?+ D
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
    , E2 _/ B, F! n) N% ?
  186. #endif
    ' Q4 @1 M. K/ c* u* L
  187. ( r" N% M$ u% y: C# _
  188.   LINK_STATS_INC(link.xmit);9 Y  J$ ^5 o  [8 D% [
  189. 2 r) {& n; M* f% c
  190.   return ERR_OK;6 A/ W: Q* e3 `" ?, Y1 g
  191. }5 ?8 S2 ~: q' x' g9 r; S
  192. 4 E/ Q% `+ V, ?4 F# z1 W
  193. /*** {. h$ f. r# n& j8 N* o4 F. |
  194. * Should allocate a pbuf and transfer the bytes of the incoming
    0 m) y( _, `  M9 _& n
  195. * packet from the interface into the pbuf.9 X: A2 W, |* ?1 c/ X
  196. *
    ! S8 C6 x7 V* R+ K8 u) s& E) k
  197. * @param netif the lwip network interface structure for this ethernetif6 M, _! O1 q5 R. V: H, v7 @
  198. * @return a pbuf filled with the received packet (including MAC header)& C; c: A) B( H9 {1 y
  199. *         NULL on memory error
    + f- V& t( x5 R0 G9 Z  s. Z* q: H8 Z9 \
  200. */
    4 r8 O: y- |( `- M  `! f# x+ x$ o
  201. static struct pbuf *
    ! g! R# A1 L8 ~) J0 X
  202. low_level_input(struct netif *netif)
    8 B2 P' W8 g9 i3 P8 m' T* L; k
  203. {. Y* l8 X3 b) I; X0 O, \; _
  204.   struct ethernetif *ethernetif = netif->state;) _4 H* E' ^; m
  205.   struct pbuf *p, *q;4 \8 d5 c  ^+ {7 R: l
  206.   u16_t len;
    5 ~5 J$ l& S9 V0 K
  207.         5 z8 W0 n& k0 ~: V
  208.   // 添加的变量& k. E/ C0 k3 F" y8 R
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完/ _6 X8 y( ?, ~3 o& w- f. q
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;
    3 u2 w) O: Z+ t4 Q0 }5 r3 R) |
  211.   uint8_t *bufptr = packet->payload;
    : J& h9 J* |1 x" h2 [5 d# B
  212. 9 G5 F5 O5 A! {8 @( u, T
  213.   /* Obtain the size of the packet and put it into the "len"
    ; y: e4 `( }  G* A& M) y; r8 T
  214.      variable. */
    # @2 H# @5 ?! H
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
    1 C2 A6 f, s# W; V) |6 x
  216.   if (len == 0)
    0 a2 Z  L6 F1 o  B( G
  217.   {! i" }5 _# c( i8 [! P1 P( d  V- G
  218.           // 若读取失败, 则不分配pbuf, 退出本函数7 W6 U+ W: E# c( H
  219.           p = NULL;' R3 i& G5 N3 C% v6 W! C8 q* e
  220.           goto after_alloc;8 K6 [# b! D% R
  221.   }
      r+ v  S" }$ l* P+ o# E5 t
  222.   len = packet->rx_packet_length; // 获取数据包的大小5 t# [$ e  p( c- K" Q8 ]9 Z8 X& Z
  223.         
    5 g( L3 |, k6 i- D- r6 m9 P
  224.   // 打印数据包内容
    . u2 G0 r$ ?2 p5 n/ B! ^# \6 a
  225.   printf("[Recv] size=%d\n", len);0 }$ Y1 s! x# y
  226.   dump_data(packet->payload, len);4 F0 k4 v" x" Y; S
  227. * l( {5 w7 X6 e5 s! h
  228. #if ETH_PAD_SIZE
    ) f! Q: P/ F: B
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding *// f# {& X8 Y. A4 I* E6 _" ?6 Y
  230. #endif' w% S' w+ r" x
  231. + J; s( E4 }# O' a+ x! m# J
  232.   /* We allocate a pbuf chain of pbufs from the pool. */
    & ?/ E1 Z. g* N9 ~
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);& h9 Q8 g2 S+ r! m% \$ `1 P8 m
  234.   
    ' E& j: v$ V) q! U. F/ r# I
  235. after_alloc: // 添加此标记
    % w; Q. H1 U, M2 R: q% ^4 V8 i: m( J
  236. ' R! t4 u8 A. I! u, B5 s8 h. `% a/ E
  237.   if (p != NULL) {' z2 N6 b# Y7 h- B9 ?# y

  238. 9 C9 f4 g- j  B' @/ h
  239. #if ETH_PAD_SIZE# M, |# N8 D; u. T% e! r% v0 T
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */+ S0 \8 Y( g8 n1 z$ f
  241. #endif
    * e+ ~* L; t2 |7 V% y( v3 C
  242. 8 F0 N! t4 G+ b6 G! [0 L
  243.     /* We iterate over the pbuf chain until we have read the entire2 X3 K/ H( \0 o  E
  244.      * packet into the pbuf. */3 \+ w" E- U6 f% l2 a$ z  p
  245.     for (q = p; q != NULL; q = q->next) {
    7 q, }1 r, `; ~) _8 O) ?
  246.       /* Read enough bytes to fill this pbuf in the chain. The
    - k% Y+ J" s8 I1 |7 u, E
  247.        * available data in the pbuf is given by the q->len/ e" V# Y: l4 C: e
  248.        * variable.
    % A0 U" D. t& w8 l9 f
  249.        * This does not necessarily have to be a memcpy, you can also preallocate
    8 `) I8 v5 K( P$ T4 t) b# m  w
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
    - C4 s. p$ ^7 ]  L  c1 r. q" R/ \
  251.        * actually received size. In this case, ensure the tot_len member of the' j/ I: R2 O' r/ q8 f, g- Y# N
  252.        * pbuf is the sum of the chained pbuf len members.
    ' S6 E0 m1 V2 ~! w# d
  253.        */2 h2 B! O- X; d! b, f, @
  254.       //read data into(q->payload, q->len);
    , P2 }5 x7 ?; Q0 P9 U# Z. B
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容
    9 U+ l; ?4 I& _! p8 L0 F6 m
  256.                 bufptr += q->len; // 指针前移
    2 W" `9 |; L! x: m0 K$ b
  257.     }6 p- u; v9 w( b4 h  M
  258.     //acknowledge that packet has been read(); // 无需确认
    ' ~$ o) M, z2 K+ V# H
  259. ; R& ?; d. l5 S' |4 h* e
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    4 z& @. a1 E+ L
  261.     if (((u8_t*)p->payload)[0] & 1) {' `  F) y- ~. {% k0 ?/ E8 r
  262.       /* broadcast or multicast packet*/
    $ _, x; }2 J7 r8 [
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);- [* ~8 C0 x! d
  264.     } else {
    ; x4 j0 |! }' E0 e4 V3 t5 _
  265.       /* unicast packet*/
    3 p* b6 u( {1 N7 o, R- T# c9 i
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);3 `7 ]- N" \' @! j$ u( f) t
  267.     }
    ! L# l) B* L9 X
  268. #if ETH_PAD_SIZE) h, `( h# N4 T0 ?3 x) c/ s( j" U3 E
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */! I# m& O0 z# s) M& h8 l2 x8 U
  270. #endif
    / O" W, C" D3 x

  271. " l/ d0 L9 i. y0 i" P. {$ M2 T4 u
  272.     LINK_STATS_INC(link.recv);
    % [5 \+ h2 k% S' E! V
  273.   } else {) l  G4 ^, t# J% q2 W+ A% d
  274.     //drop packet(); // 注释掉此行
    $ U; m: f5 _, E) O% y" i6 S& C
  275.     LINK_STATS_INC(link.memerr);
    4 B8 L7 U0 C6 c8 z
  276.     LINK_STATS_INC(link.drop);
    0 B$ ?! W( o% r  ]
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);  m' Y. q. G; ^; N$ G# ]
  278.   }& U3 z9 m# r/ c* E
  279. # `3 E% h5 c8 b3 s# k2 N! ~
  280.   return p;
    , o- z* }1 C' L5 r
  281. }
    4 W9 I5 [4 i, @# @4 I5 |2 u+ B
  282. " e1 c$ G3 q6 W! g/ C8 E
  283. /**
    ; J$ `1 c' l5 s6 e: r0 C% M+ C
  284. * This function should be called when a packet is ready to be read4 Y- v) O' u4 o: m0 G
  285. * from the interface. It uses the function low_level_input() that
    # M  z, z: U) H; h7 N  O
  286. * should handle the actual reception of bytes from the network
    2 k% S+ c- y6 y$ P2 w/ p! Q8 R
  287. * interface. Then the type of the received packet is determined and
    5 c9 k1 W& e( k: I
  288. * the appropriate input function is called.
    8 @7 a2 U3 {( t& N0 ?; o! T
  289. *
    ! ?+ M+ t+ Y! k" I$ u
  290. * @param netif the lwip network interface structure for this ethernetif1 ]9 ]) [* z2 K
  291. */0 n# G; ]) \  z
  292. // 必须去掉static
    , T0 q3 r3 T1 F( c9 k+ q
  293. /*static */void
    ) G5 q1 v! O4 o
  294. ethernetif_input(struct netif *netif)' e4 R2 x1 D4 ^+ l+ y7 ?3 m* w, y
  295. {. W2 b, X+ s/ a/ Z; `' k5 t
  296.   struct ethernetif *ethernetif;
    1 c) U7 m3 m" o4 a# p3 h6 z% l# s
  297.   struct eth_hdr *ethhdr;
    1 ?7 z! _% ~3 A
  298.   struct pbuf *p;8 `" @% g# U, \# j

  299. ) q, e! n0 U' Q2 J; t
  300.   ethernetif = netif->state;6 Y1 V3 f1 A, _& ^1 U
  301. 5 n1 p& G6 y/ ?; e" N
  302.   /* move received packet into a new pbuf */2 P; h7 D; v$ z( G8 W5 I
  303.   p = low_level_input(netif);$ K6 ^# b$ d' c* t# S5 \# A3 n
  304.   /* if no packet could be read, silently ignore this */
    & U7 B; c1 ~/ O. ~  R
  305.   if (p != NULL) {/ V9 e, Z! \! u* Z
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */# B0 u& s$ N6 U- x8 S9 _% w
  307.     if (netif->input(p, netif) != ERR_OK) {
    6 H" F! ?! p$ i/ n+ @1 I
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));% e' _4 T7 h( t) n2 Z
  309.       pbuf_free(p);  p+ @  {9 Z5 U4 R* P% X! Z
  310.       p = NULL;
    , u: L5 _& M! e1 n
  311.     }* i3 x7 X4 f* w% r1 f7 H
  312.   }
    ! }; H% W+ k# {
  313. }- H& b1 b+ }8 ]2 d$ `8 ]
  314. 4 j+ m  }& a) p( R" Y
  315. /**6 ]; F) c2 y* R( P2 v
  316. * Should be called at the beginning of the program to set up the' j- f8 z' |2 D# D' R3 `6 y
  317. * network interface. It calls the function low_level_init() to do the- ^2 o$ ~% Y) |) d% t
  318. * actual setup of the hardware.* b) u: g3 q! y, H
  319. *
    / ~( E9 i! S( d
  320. * This function should be passed as a parameter to netif_add().
    $ b( @' z( [0 b1 j9 X
  321. *
    7 y4 r% p9 K! t& J' n# @7 N2 U& X
  322. * @param netif the lwip network interface structure for this ethernetif
    1 u9 u& w9 B" ~# K7 v# K
  323. * @return ERR_OK if the loopif is initialized0 d/ q- b& `3 w; R8 ?% @* T6 X
  324. *         ERR_MEM if private data couldn't be allocated
      j# ~% T, h8 s# `( v
  325. *         any other err_t on error
    ( K7 D$ k; [* w5 ?/ q
  326. */
    , j) u) Y) m( y' L5 n
  327. err_t
    1 p9 M( p7 P. t. M1 X' j$ I
  328. ethernetif_init(struct netif *netif)
    $ b# y# N% J' {$ ]* v' a- |
  329. {0 m+ c* j# \' @9 s
  330.   struct ethernetif *ethernetif;( R* Y7 {' [8 L  I, t$ e

  331. 3 G+ _% @- K6 g$ x* G( Q
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));
    3 q( X# R" X6 v% C( y# g' T6 b
  333. " C: e, O& n# @7 x  F9 i
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));) [( x; A: ]+ K; _, I1 I$ }
  335.   if (ethernetif == NULL) {/ ^3 I6 V$ U7 c6 R$ C
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));4 A9 v  i: s; j, b# K# z9 W) |9 C
  337.     return ERR_MEM;) D* j6 y3 J3 g- Y9 L- z, _
  338.   }
    ) ]) Q$ k# ]$ P, J. y) j
  339. ; l" }2 j# \) A: {+ U
  340. #if LWIP_NETIF_HOSTNAME  [9 I+ o% A/ F1 Z
  341.   /* Initialize interface hostname */
    3 E, h# O) k: _3 k+ j1 J3 T0 ]
  342.   netif->hostname = "lwip";
    0 K! k% |" p7 B: {  d
  343. #endif /* LWIP_NETIF_HOSTNAME */
    $ m) e6 y' A7 n* u' P/ y4 ]4 {
  344. 0 R' z  j5 {9 U+ t/ g
  345.   /*
    9 M* Q* ~+ s' j  o
  346.    * Initialize the snmp variables and counters inside the struct netif.  V% l, x' D7 J+ @( I) m: b
  347.    * The last argument should be replaced with your link speed, in units! Y  |9 W/ D3 m( c* d
  348.    * of bits per second.( c9 C% k+ m3 o" ?" j; T8 Y+ y
  349.    */
    8 I( I5 n% h0 y; P  U/ ?( j3 W" d
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
    ! ^" e, I/ N6 W. @" w

  351. + J' b" b/ Z5 x: n" I- Z- q
  352.   netif->state = ethernetif;
    . G" ]# K  R- @5 G! c: I; B
  353.   netif->name[0] = IFNAME0;! Y' D+ f7 j7 R9 A2 I
  354.   netif->name[1] = IFNAME1;/ j8 G7 @3 k/ l" s7 T
  355.   /* We directly use etharp_output() here to save a function call.
    2 q# G$ A  D0 t9 R
  356.    * You can instead declare your own function an call etharp_output()
    0 e- T% e4 M+ B, Q% u; N
  357.    * from it if you have to do some checks before sending (e.g. if link6 c' a" @  K- @; Q# ]. H1 D0 M
  358.    * is available...) */: J. x, D/ e- m5 ]+ N
  359.   netif->output = etharp_output;
    & S7 b$ t+ R/ b: q* H9 c- J6 h
  360. #if LWIP_IPV6: y! A  }& }9 q- `/ V% K' n
  361.   netif->output_ip6 = ethip6_output;6 V8 b5 N3 b  w) e! `) k0 |
  362. #endif /* LWIP_IPV6 */
    2 K& w, c$ m/ ?9 ~, U+ R. C
  363.   netif->linkoutput = low_level_output;- Z% d% Z- }" g

  364. 9 d% u, t' a: p: A
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
    ( I* S: r8 r, u
  366. ( U6 M4 M9 Z7 h$ f! K; T" N: b
  367.   /* initialize the hardware */. X: w4 w* }! v9 l- z
  368.   low_level_init(netif);7 p: I: L& V- \; q% Z; ?5 D

  369. 0 T1 L# A) ?& k  c: g0 o% C
  370.   return ERR_OK;! h+ R& s# ?' l3 }
  371. }  c5 T% \1 p3 a& Q  k# r

  372. 2 v" `$ I2 Z& n
  373. #endif /* 0 */
    ' V5 ^$ l0 h# G! L
复制代码

6 [1 {3 r, H! F* q在项目属性中,设置Include Paths为:.;.\lwip\include
& i6 [5 h4 L" C5 x- g3 P! D4 v其中点表示工程根目录。1 ]! j6 r4 A$ p1 u4 |

7 A4 ~8 M6 |7 ~0 j6 l( Y: N另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
1 W+ ~. R+ i) a. H9 C; i" a3 z- O
编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
5 y9 d, m9 v1 [+ p7 \$ t电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。
1 p% Z% f* d* v, J/ ^/ J9 G5 k配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。, g. R% Q: G8 i3 V! q5 w/ s

评分

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

查看全部评分

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

举报

4个回答
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....
0 D$ V+ h8 M' g+ j; a: B" c2 P0 _7 m, o) f5 y2 n% _
多谢分享

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版