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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE
6 P1 r5 ]6 N3 O! y; X3 ~. TPB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。& m% Q' X% h! q# x
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。. D( d# M7 h5 M4 u6 @
该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。
! U$ C. \( h- Z, _9 j; i固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925- D4 `1 `8 l0 U1 `, i& c/ N- T

# r7 Z! m8 [% D0 |7 x注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!
3 e/ o" G% f* [8 ?0 F* ^9 F# n1 N
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】
3 p) W0 g- N& c5 r, |) t1 s! |
  1. #include <stdio.h>
    7 K' d' d0 }3 j8 h: x7 D* Y* w
  2. #include <stm32f10x.h>
    , ?: }7 v# `0 ]6 B4 j
  3. #include <string.h>6 {. Y9 J4 c) l7 |
  4. #include "lwip/init.h" // lwip_init函数所在的头文件
    + G! S) d7 t% S
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件
    - `( U/ g, F( Y9 `( D
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件. S& [, f/ H4 {2 H& v& O' z
  7. #include "WiFi.h"
    * g) I: U) P* T

  8. 1 R2 _# i; I/ S" p
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明
    * b$ I8 f2 j* Z; V$ h
  10. err_t ethernetif_init(struct netif *netif);
    4 n' a* C2 O% C5 H& O7 O
  11. void ethernetif_input(struct netif *netif);
    ) L$ @5 t. }! m- n8 V0 y
  12. % |) x7 A& F& F/ S: D
  13. // httptest.c中的函数1 I: c, [1 E+ y) {
  14. void init_http(void);
    - B/ S/ g* g$ |* y7 u& F0 D

  15. 6 ?1 z$ b# l* Y
  16. // 延时n毫秒
    4 p: T5 ^& `  Q+ l% R6 G4 p# m1 B0 W
  17. void delay(uint16_t n)
    - u. ?5 L. a$ Y" |/ O* J. a
  18. {
    # x9 ^6 V' j) p* P
  19.     WiFi_PrepareTimer(n);
    9 S" X9 a- N. }% k, [% m6 V; c: G
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕
    , A( O/ a3 l: Y! I- O! d9 J) U' V
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
    ! v( p2 ?8 e; s* V
  22. }* i8 U  c" ^! E, m& m6 c

  23. 0 v/ `* _: n- s6 M; f
  24. void dump_data(uint8_t *data, uint16_t len)* u$ K# N4 S* l+ e, W. b" V
  25. {
    + A! v7 `4 c% d1 ]7 ]5 C
  26.     while (len--)
    0 S% Z3 n& _4 O$ ?
  27.         printf("%02X", *data++);3 ?3 M0 f8 ~  C: u& i: @* N; |( J3 A
  28.     printf("\n");6 f( x2 @. v1 w  T5 a
  29. }
    8 l3 `7 F9 l, |$ @  H: |! S7 n9 y

  30. 2 X: e8 M. [8 k4 B8 D0 A$ f+ n/ d
  31. int fputc(int ch, FILE *fp): e1 H3 F0 N* ^% L7 z
  32. {' k1 c# M6 ^: ?4 a  A
  33.     if (fp == stdout)1 U8 g) q1 q" C8 m1 ~! e4 [
  34.     {/ F2 C: W3 ~) w7 Q
  35.         if (ch == '\n')
    ) O6 U& ~5 h0 O& n
  36.         {
    / ~. I" |9 u- E* x8 `8 H
  37.             while ((USART1->SR & USART_SR_TXE) == 0);
    " z; m  _8 w0 z: E! a- n7 A
  38.             USART1->DR = '\r';
    7 y- {: w( ~+ Z7 P$ C6 S
  39.         }3 l2 M/ l6 o% i  C' y( P$ \9 k
  40.         while ((USART1->SR & USART_SR_TXE) == 0);. @& x4 O& M2 @7 n3 P5 [/ C
  41.         USART1->DR = ch;0 [  W9 q) l0 T& T/ ^" y; A  E
  42.     }
    / m" @, e( ~% R7 X2 u- E5 m
  43.     return ch;
    1 w3 t4 I& f) t  O, L0 M& }
  44. }+ ]1 {# f( q2 I: @, S
  45. 3 t# S& p+ m+ X8 W
  46. // RTC时间转化为毫秒数0 |: y/ l2 M1 D7 {, A+ U
  47. uint32_t sys_now(void)
    # n* g5 n6 Q) W0 M
  48. {# e* U* c4 D" f0 c2 ]
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
    ' c9 S8 n, T- a9 r5 Z
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒, g2 c; e% M: K+ q2 D
  51.     return tmp;
    - E4 ~; O$ a9 U; E- z; M# K
  52. }
    0 r; j* w7 l5 S# ~
  53. 4 o9 x/ S/ n' D
  54. int main(void)8 [% w' @8 v& }
  55. {
    ) h/ H% {: A* C7 m( ?  g" d
  56.     struct ip4_addr ipaddr, netmask, gw;- s6 |2 U+ w) `5 Z4 r- m
  57.     struct netif wifi_88w8686;& x# J" ?$ G, B# H9 I
  58.     uint32_t last_check = 0;0 r3 w$ l8 T: {3 L" _# k; _, ^& U& ~
  59.    
    7 W& o; N/ J) L1 t8 R3 E' O+ C
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;& @- A: z* W3 @& X: F" A4 D
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;
    3 b; ~4 |! `& G0 U* o, c1 D
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;, @% t# J6 |) V
  63.     6 m6 P) [) }$ V
  64.     GPIOA->CRH = 0x000004b0;+ O5 Y1 ?: v6 V# y/ V; l; j& p8 X
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块
    8 O9 R# H! `8 e3 A/ x
  66.     GPIOC->CRH = 0x000bbbbb;
    + o. `# p  X* S% h" R
  67.     GPIOD->CRL = 0x00000b00;
    & I. `% Y9 |% ^
  68.    
    + V5 I3 `* H* j& Z
  69.     USART1->BRR = 0x271; // 波特率: 115200
    2 N; R# f6 K$ R
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    , ?$ \! J2 m7 A4 v+ a- }
  71.     , m  Y1 V  G: H( f/ F$ t
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器
    / n0 `& E7 D* P
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)
    " B3 X1 e6 @6 q- a. `/ T/ V
  74.     {1 X" u3 a$ C( v) g4 [2 ^
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI
      s  f  i4 `) G, f
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);) t3 D: ]& p) Y* ~# \9 j
  77.         //printf("LSI Ready!\n");; a% E* M: G% \/ ^. I- X
  78.     }
      d+ Q8 Y' F2 j
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)8 F' U! t/ X' y2 e* u
  80.     {
    & Z1 I) s. x' o2 T+ p
  81.         // 若RTC还没有打开, 则初始化RTC
    6 i( a; m3 Z6 q) m: W+ U  c( }
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时
    " O) W/ e4 M) w* D; @) y& r0 m* f
  83.         
    4 B. j5 e. _4 \; B, {, ~
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式, ~- E* @" a/ v* U) Q; p* h. Q6 h
  85.         RTC->PRLH = 0;
    5 [% z* }* \8 e( D
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
    . @! v: F( Z# I6 \
  87.         //RTC->CNTH = 0;
    5 K6 d" e( B' d0 h1 H8 w
  88.         //RTC->CNTL = 50; // 初始时间
    9 X: ^8 E' I% k# I5 `
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置) R& o: q0 B% @- f0 w
  90.         
    9 w. {* T, \6 ?4 w, U* L: \
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时8 u: i- N0 V3 E) B! |, s1 Y
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效& O! `- }$ p' D2 o( Q5 ?
  93.         // RTC从此处开始走时3 Y& n/ O8 x# e; R4 R# B& m
  94.     }& j7 o' R1 x0 K. `5 P$ u3 [1 B
  95.    
    + @3 C1 [1 y8 {1 I1 h& r; V5 L7 W. g
  96.     WiFi_Init();# Q$ ?& T: k6 r/ a: ^
  97.     WiFi_Scan();
    3 r* P$ N9 A- P. ?+ U! t0 U1 b, |2 G! e
  98.     0 a! C- O7 }- m" B
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点0 `, R; J! i) t4 t  O0 x: R0 k
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    ) F, u2 ~# ?4 q% v
  101.    
    " o( P4 d+ h7 v% X% f
  102.     lwip_init();
    6 @+ [6 Y# A$ k/ N7 @
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址# L4 u1 z9 g$ D$ e+ O
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
    ! Z3 r& ]. O7 M1 O( Y
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
    " B, u- k( V1 k
  106.     3 Y" P! z: y# ~, J2 t1 G
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);7 d- z0 \& w+ [/ R  B6 X8 i8 R' l
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡
    4 H* T+ B8 f' J1 P
  109.     netif_set_up(&wifi_88w8686);
    6 J, D; Z. h: Z0 H6 W
  110.     ; f! g$ \& Q- j, D: V1 r# K
  111.     init_http();6 N6 |, N7 ]( z  P, X, b/ \# `# P
  112.     : }, v' b! S5 t2 s% b8 C; }( Q% o" O
  113.     while (1)
    0 x7 X; D) R" P, T" a; _
  114.     {9 K* D1 R% c, i5 [9 i( m
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived()). p. F0 h  y9 j  \4 y) E
  116.             ethernetif_input(&wifi_88w8686);! H" c! @) c) G+ \" p$ w" ~
  117.         
    & P. C' t* k3 Q: i; I% x; T
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)
      s  O9 l3 ^! F, w$ m  A  ?! w- J
  119.         if (sys_now() - last_check > 200)
    ; p$ z9 D  y6 R+ Q
  120.         {
    6 j* v7 w# q5 w8 a. {
  121.             last_check = sys_now();
    ; ~' U+ D+ z9 ~; U, v" j  Q3 |
  122.             //printf("Time: %d\n", last_check);" U& \9 ]5 P: }) P- q+ n
  123.             sys_check_timeouts();. q: u$ G* R; b2 \0 @: ]: }
  124.         }! x2 p. P! H# ?
  125.     }
    ) `3 m3 e5 A3 [2 n6 j, C& N
  126. }
复制代码
【httptest.c】3 t  D8 Z, @; u0 ?9 S8 K% }
  1. #include <string.h>
    * @. C$ o4 R- y. h1 {' c
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件6 P9 M7 Z* N6 `( n' J
  3. . ]; g9 }/ F  c
  4. #define STR_AND_SIZE(str) (str), strlen(str)
    $ k4 H/ b: |" r6 s  i; `7 E* v/ v7 S
  5. ! I- S0 x, W5 z; h8 d' i8 p
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
    % K& A6 b0 Y: ~. k6 p
  7. {  ^8 u1 A( q" h6 G
  8.         char len[10]; // 存放HTML内容的长度; e% S/ Z4 q# l8 I" l$ Y1 q2 }
  9.         char str[200]; // 存放HTML内容
    * h% ~+ k9 e3 d6 Z" U6 R- w
  10.         
    & U& J* ?; D1 X3 @: F
  11.         char name[100];
    - `7 L  [/ M( \. @7 s& A& O
  12.         char *pstr;
    ( I9 g; \+ O  l$ g
  13.         uint8_t i = 0;
    2 j! l' q: h% R9 U7 _6 M& d. D
  14.         if (p != NULL)
    ! Y0 N; {8 o, F# r: U# }5 p( S
  15.         {+ y* C, w5 [, f; K
  16.                 // 提取页面名称. O6 _. p  i6 x$ {  e( K3 {4 D3 H
  17.                 pstr = (char *)p->payload;: q) O9 k  I9 X
  18.                 while (*pstr++ != ' ');
    ( H* @7 _/ ]8 f( _9 N5 p
  19.                 while (*pstr != ' ')! i" C/ S, C; ~0 n1 Y- X
  20.                         name[i++] = *pstr++;
    9 r6 G( g: i: \. D7 l) M" D
  21.                 name[i] = '\0'; // 不要忘了结束name字符串
    ! q* N, u# u: Z$ R! D
  22.                 tcp_recved(tpcb, p->tot_len);/ P+ ^5 |. f$ x' y& F
  23.                
    ) X* q4 |+ W9 _; Q6 e, F9 h
  24.                 // 生成HTML内容
    ) ?& z/ g, h. Q9 i, b$ ~5 j+ z
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);/ Q. u% K  B1 J# y6 |
  26.                
    2 @% J  U  U, @$ k
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度* z4 I2 i# I. G' C: X6 \
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
    / m4 P/ \  i( @, C$ ~
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);3 t5 v) Q) N" ~& M* L
  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);$ w. Q  X6 Y7 V) ]2 h
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容' f) V3 y3 B. W- \2 u$ b% E
  32.                 pbuf_free(p);
    7 B% ]9 d- x5 `1 R& }- d
  33.         }
    , g  f7 }6 \% n7 S
  34.         return ERR_OK;, \9 Z( t5 B+ Y4 B5 \1 B
  35. }
    5 p- B9 e5 H6 n7 |4 N) _
  36. / h! \8 n6 ]8 C8 Z: h; c9 G
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    ; |4 p2 l" D7 E7 k- r- E0 U
  38. {& k& v+ y& t: |- U) b
  39.         tcp_recv(newpcb, http_recv);
    9 e! f, r" y1 m7 U# j  j
  40.         return ERR_OK;
    , Q) S6 g. c* y
  41. }
    ( G  W/ }& e( u  {3 m
  42. ( F4 E, T$ S+ m( e7 j. H
  43. void init_http(void)
    , c5 J$ q; j4 b  Y, a# j' b) B2 {; e
  44. {
    ! i, V4 }4 q8 o8 ?+ k
  45.         struct tcp_pcb *tpcb = tcp_new();' I* |3 B9 D0 N( I, j6 T
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);
    2 d6 Y4 M( a0 D5 H1 M! O: }8 {
  47.         tpcb = tcp_listen(tpcb);
    4 j) I) Y4 q6 S- {8 v+ e8 s
  48.         tcp_accept(tpcb, http_accept);
    9 i( t1 e( g$ {- c# }
  49. }
复制代码
【WiFi.h】7 M/ `, ~6 g; V) u! D& L
  1. #define _BV(n) (1u << (n))5 O9 s: J: J2 |5 H8 V
  2. 7 y( e0 y' J. @+ ], m
  3. #define CMD52_WRITE _BV(31)' B- S3 H6 n0 a7 Z. a% t0 U
  4. #define CMD52_READAFTERWRITE _BV(27)% l9 ]& Z! K: l6 ^2 B

  5. . d' J& a' n# X) |. T1 }6 q6 L* {! ^
  6. #define CMD53_WRITE _BV(31)5 l5 b3 l! Z. y4 ~; L9 B1 S
  7. #define CMD53_BLOCKMODE _BV(27)0 o9 M/ b& \. G' P, j2 x; z
  8. #define CMD53_INCREMENTING _BV(26)8 I8 [3 c/ L% F! N: Y

  9. 7 l) A- I2 b. z5 `6 q) c
  10. // 16.5 SDIO Card Metaformat$ ^& j* M4 ]( o0 _$ @' d3 n5 }
  11. #define CISTPL_NULL 0x00 // Null tuple
      G/ G. \! E% ^3 h" _$ ~. B, S
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information0 W, Y" i, g7 I$ v
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    - L' F. [- o' z( c: W) O9 A; R! w8 Z
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple( V5 s4 {: P! P* s. F6 t, K
  15. #define CISTPL_FUNCE 0x22 // Function Extensions
    ' D# X! b8 L& G
  16. #define CISTPL_END 0xff // The End-of-chain Tuple
    . [  l& i3 P5 Z3 y+ s
  17. . M& Z% t' `0 t/ x5 G3 [
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)' H) J0 R2 Y; h

  19. 8 Q* _7 l! k) `: X) p
  20. #define WIFI_SQREADBASEADDR0 0x10  W1 R8 E, \9 c7 s. Q6 F' e
  21. #define WIFI_SQREADBASEADDR1 0x11
    1 P" K; d# @% ^9 X& T
  22. #define WIFI_SQREADBASEADDR2 0x12
    4 S1 S; _' m( E9 z& a) N
  23. #define WIFI_SQREADBASEADDR3 0x13
    6 c7 A( ]5 H# d# ^9 }! X; o

  24. # W6 ?, H4 T! H2 Z5 J
  25. #define WIFI_CARDSTATUS 0x20 // Card Status
    ; a& H& J0 X; G0 t
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator
    0 A* f( D( c; p! x
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready4 K( D0 w' E& k, f
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
    ' Y' K1 j  H( ^# u1 B0 d9 J
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
    6 X1 C$ U$ @7 r7 V# d* Z. E0 N, c

  30.   i5 v. X: N0 A" [, M
  31. #define WIFI_CAPABILITY_BSS _BV(0)
    ! i, t. `( U% u
  32. #define WIFI_CAPABILITY_IBSS _BV(1)
    + _% l. e: N( J) j
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)+ `( n; i: `6 S9 a
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)
    7 j% w/ P% ^* n* M3 X( k( }
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)* N3 q( V" ^4 |5 `& g- t! J
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5): W2 y4 v( L1 j4 E) |/ E
  37. #define WIFI_CAPABILITY_PBCC _BV(6)! c  j( v* L  D0 g
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)
    : p1 o$ j" G4 z
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
    & ~2 _, F. p8 O$ b: W* W
  40. #define WIFI_CAPABILITY_QOS _BV(9); i% w( N3 B; r" @; P7 b
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)
    , c' t- ~+ D$ P$ h# K- k% R
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)
    - R& g( U. d) W
  43. + i- R% ?/ a. c7 c" |4 f0 p& a
  44. #define WIFI_SDIOFRAME_DATA 0x00) k3 @/ i( L+ g6 i! D6 @
  45. #define WIFI_SDIOFRAME_COMMAND 0x011 J' e: n# ?3 v5 w# x3 o
  46. #define WIFI_SDIOFRAME_EVENT 0x03
    $ s8 S; n. ]' \! l9 l; {

  47. 2 R4 j6 k. Q; S# G
  48. /* Command List */
      t8 n" z4 R# n0 O7 }' Z6 f
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    $ z" \+ d; H' m# ]8 p
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP
      h. T6 f1 W( h3 t9 A
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC0 N2 {3 g- F, `: Q' r" r$ H
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
    - H4 |$ x4 I( ]5 e5 j
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address
    ! i( U6 A3 }2 K1 [
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption
    1 W( Z" E- p- v1 r
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
    - l) ?, g2 z$ K
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results+ l3 ]9 w- y; W- _6 N- \9 `8 c! _; H

  57. 9 f# j' P1 s3 W0 [# \" o8 }
  58. /* Command Result Codes */
    & O+ \3 b8 S# y$ W' K) _) g
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error
    % V$ F) A8 A8 B3 s
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed
    " |! }& m+ L3 F
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported- S8 c; E0 r% C8 W" O8 p, Z

  62. , K7 j% F5 F  {; a/ M) ^2 X/ Z
  63. #define WIFI_ACT_GET 0
    ) T" h/ D& V5 M1 i" z* ]
  64. #define WIFI_ACT_SET 1+ F' [' V" y+ L- }( x, t
  65. 2 M7 K6 L9 {  I/ g  Z. Y
  66. /* Authentication Type to be used to authenticate with AP */
    * P1 B& k% W* [: U1 @- j
  67. #define AUTH_MODE_OPEN 0x00
    2 ^) w; \4 u) `% y* }* g
  68. #define AUTH_MODE_SHARED 0x01" R$ E' ~# ~7 q( M; c5 f, {1 |- }% a
  69. #define AUTH_MODE_NETWORK_EAP 0x80
    ' ?  N+ C0 D& O# b
  70. 2 [7 y9 C+ e$ ~1 n
  71. /* WiFi_Associate return value */2 A: @4 z; e. M0 X1 h# \- Y
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe
    " T: ]: k7 v1 Q( j
  73. #define WIFI_ASSOCIATION_ERROR 0xffff/ V) s' I* Y' N+ Q3 j
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功' z- w! `: K+ q: n7 [8 p: U6 X* \
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101& q! d" `8 x; Y) S, I
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧
    7 d* S: E* M& |
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213
    / n! m) ^: p- J1 x
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
    ) V3 z4 y; A5 S" C* `( t
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败
    % l& ~# \$ f/ L& o* M& T4 y
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时3 j0 L& O: W- l8 \- i1 u
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时$ L, j) Q7 i7 Q! G
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时
    0 J! F6 ]# U$ D& s" ]
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
    & r, z, b  f% L$ H

  84. ) C/ f: i) I0 D3 j* ~
  85. #define WIFI_KEYTYPE_WEP 0" e8 r1 F! Z( n, O' w  b. p6 {
  86. #define WIFI_KEYTYPE_TKIP 1, w# G7 ]% s$ c
  87. #define WIFI_KEYTYPE_AES 2+ n3 Z  P, ~# W! V$ Z  Z% [* u
  88.   C& [4 f; a- l8 N% |; }$ {0 ^
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)
    3 z' W, W9 f! p
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)5 f0 Z0 E* {% y6 p5 r8 N6 o: D+ j
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)7 a8 f8 T8 c% K

  92. - j8 X0 K2 M( }& o  G- x* ^9 \' F* C
  93. #define WIFI_MACCTRL_RX _BV(0)
    & s' w/ {5 V, s+ s
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
    $ v. K: H& q2 R6 ]; @( n; l
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)
    ) V/ k+ X( N2 a/ r
  96. #define WIFI_MACCTRL_WEP _BV(3)- H6 H  |4 u! ^0 v& L8 @
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)
    : x( Y3 a% T0 M! }' W
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)
    ! Z. l6 c- E( f! a( r% ~: }/ q0 P
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)& t! E' M6 z2 [" C. I
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection
    $ E, U( `3 I+ T/ C$ N! R  a; b
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode2 B/ j* S* x1 u* Z
  102. 6 ^7 }* b  K+ e7 E
  103. /* BSS type */7 ~0 h# f. Z2 h6 b( |0 u
  104. #define BSS_INFRASTRUCTURE 0x012 T1 N: A! H4 T  s, }
  105. #define BSS_INDEPENDENT 0x02
    4 D8 Y1 w3 N3 d% L
  106. #define BSS_ANY 0x03/ m4 U8 R) C2 T; Q5 |& S2 Y
  107. $ o6 `5 j  z. r" O% k4 D- z+ N3 i
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */- U( d: D6 U% N2 p" O
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */
    ! d9 q* V* p* u9 z
  110. #define MRVLIETYPES_SSIDPARAMSET 0x0000, ~+ t) w( R  C# G7 W3 Z, `
  111. #define MRVLIETYPES_RATESPARAMSET 0x0001
    , N" F4 `6 n2 J' a3 L" @
  112. #define MRVLIETYPES_DSPARAMSET 0x00033 o' {" L/ H: V: ], O. j' X" G; V0 @
  113. #define MRVLIETYPES_CFPARAMSET 0x0004' q' f( Y# U) q3 l
  114. #define MRVLIETYPES_IBSSPARAMSET 0x00067 p; z' G) a+ U1 ]/ _1 W; b
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030
    3 h" w" d/ x, O8 C2 J7 `
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd( T) f2 \, Q; ^  u5 o

  117. 3 [( F, w# R- x
  118. #define MRVLIETYPES_KEYPARAMSET 0x01004 Q" y5 L/ D; Y9 P$ e
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101* ^6 G; E0 \3 o5 D, v) R; B
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x01139 ~# \: D0 ^& m; g1 ~' {
  121. #define MRVLIETYPES_AUTHTYPE 0x011f3 p, E3 m" {5 |- \! x* n7 ]. `9 S

  122. ! P( _! L+ N9 p/ K5 F  @
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小/ @4 y1 S8 `8 R% z; X
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小
    1 s: i8 a& j1 Q5 i- p& ^4 l
  125. 3 o( i0 ?$ G; Y: K! t' X  |% f6 T+ _
  126. typedef __packed struct
    6 r3 x( k6 S! P* Q8 ]
  127. {
    & r8 F& S) {- h( V7 [
  128.         uint8_t type;( Q+ z; N3 q  V5 c
  129.         uint8_t length;, S* l$ x5 j) |5 t
  130.         uint8_t data[1];1 [( w! T& P! R
  131. } IEEEType;/ }" T# j9 O1 W3 d/ s! v
  132. / I! ^0 `6 i0 K1 L' P
  133. typedef __packed struct& S  j2 M( O- @/ i3 T
  134. {
    0 O* o- R; f1 h( w
  135.         uint16_t ie_length; // Total information element length2 n6 x+ t4 d3 f  ?# I' L+ O* v
  136.         uint8_t bssid[6]; // BSSID
    / l7 X1 K9 E( q* J) G) |0 p
  137.         uint8_t rssi; // RSSI value as received from peer2 j! k  E. w& P, V( C9 k3 X- ]' y
  138.         ! {9 a! L% ^6 O2 `
  139.         /* Probe Response/Beacon Payload */9 d3 t6 S$ F8 @% h' m
  140.         uint64_t pkt_time_stamp; // Timestamp, n7 C+ ^% @, M& F. V! F
  141.         uint16_t bcn_interval; // Beacon interval
    2 g! m0 c* F9 D, V1 T; v
  142.         uint16_t cap_info; // Capabilities information
    $ \8 H7 {2 I6 v) G' V: E
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据' h; A% V& ~# f: m  j
  144. } WiFi_BssDescSet;
    7 M# f: J6 k$ u) |& Y

  145. - k4 J: f# v: e* H2 _. @* A; q
  146. typedef __packed struct% H+ O' g- u6 J: [
  147. {
    * i4 D! @  z" k9 ?% \+ ]
  148.         uint8_t oui[3];
    2 n" g8 B+ O3 ~  C  h/ C& O$ _
  149.         uint8_t oui_type;5 q$ {5 {1 F* ?) q. E5 B
  150.         uint8_t oui_subtype;* }; o, J# K3 c8 Z% |
  151.         uint8_t version;
    2 W5 o& c! Z2 V$ D: y. j
  152. } WiFi_VendorHeader;
    " v! A9 X& D* b5 C

  153. 8 ~7 D1 O$ g+ f+ [: d* j  e* c2 O$ e3 ^
  154. typedef __packed struct
    4 |2 M/ |, u8 r7 P1 @+ }$ V8 S
  155. {
    - ]$ T2 \8 {: Y$ |; c
  156.         uint16_t type;' P, |1 Z. q7 Q  J, ^
  157.         uint16_t length;" Q3 N3 S9 u/ r4 s
  158. } MrvlIEHeader;: y1 l. b6 N. z/ x
  159. * h/ q$ y' S' j
  160. typedef __packed struct
    9 ~; C. e+ @" ~. ?. P  |: I7 V" f  q. t
  161. {
    " _* U, D" x( p7 M/ Z
  162.         MrvlIEHeader header;
    + n4 I/ g& ~% W
  163.         uint16_t auth_type;
      y7 E0 _% {- V1 u* T3 V# p
  164. } MrvlIETypes_AuthType_t;
    # E! X8 @4 u9 x. C' ^- m- J" G
  165. 6 p. Y; l. B" ^( e7 K
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec
    - K' q) {, J$ b& w
  167. ; M9 Y) r3 _/ \
  168. typedef __packed struct
    # x5 z. W" `, M7 j5 s9 u9 `+ |
  169. {
    0 n& s5 l; s3 ~" C+ d( W
  170.         MrvlIEHeader header;
    : d7 q+ F9 `( x9 Q9 o
  171.         uint8_t count;0 P- ?5 ~& Z4 U+ E) ?( z  e- W
  172.         uint8_t period;4 c: ^4 l9 k& e: f3 X/ K4 k
  173.         uint16_t max_duration;
    , Y2 s6 Q6 U/ ^0 J# Y! N
  174.         uint16_t duration_remaining;6 ^& w* p- }/ F1 W! `
  175. } MrvlIETypes_CfParamSet_t;
    4 \# w+ V3 e* }) e
  176. $ W# ]: p% P$ k: [  j  R) P# D
  177. /*typedef __packed struct$ f" v( E3 y( G) m8 A" Z- R
  178. {7 u) u! L) e1 }
  179.         MrvlIEHeader header;
    7 j. t1 m$ |  f1 q: w
  180.         __packed struct
    ! G+ e+ N6 Z! I2 [; M! m
  181.         {6 a0 J2 ~9 T) d; C
  182.                 uint8_t band_config_type;/ F4 [6 S1 Y+ w+ L5 E
  183.                 uint8_t chan_number;0 }0 J8 t) T4 y- B
  184.         } channels[1];
    - d& }2 N4 ~6 h8 A
  185. } MrvlIETypes_ChanBandList_t;*/; M3 ~) r) V/ S' Y) Q

  186.   d2 _0 K. S7 e. {
  187. typedef __packed struct
    * u% M  j! z6 ?
  188. {
    ; }, P! [. w8 i$ ?" g* }) u
  189.         MrvlIEHeader header;" n. K# b5 U  p" P0 P+ L
  190.         __packed struct
    : @$ O4 L5 u+ s" o7 A
  191.         {6 W$ P* x( G( ?+ d
  192.                 uint8_t band_config_type;
    ; w) d3 u# [4 n  w1 H0 G' {
  193.                 uint8_t chan_number;/ P2 ?6 x+ D: e1 C( w
  194.                 uint8_t scan_type;
    ' n0 @& N: R: t# l  Z" h
  195.                 uint16_t min_scan_time;
    . V1 `& v. N3 |2 r
  196.                 uint16_t max_scan_time;
    $ n; m4 J+ {* }" f0 ]9 N/ i( F7 X
  197.         } channels[1];6 n2 S7 G1 l$ X) N
  198. } MrvlIETypes_ChanListParamSet_t;& n! `; v! J. D$ w! q: ]
  199. 7 @0 f6 K. c" Q7 P3 ^% O. W
  200. typedef __packed struct3 d" ?7 p/ G; `2 [7 q
  201. {
    7 G2 P- y% T! q! X
  202.         MrvlIEHeader header;5 y, T) L+ D0 z
  203.         uint8_t channel;+ D: G9 v6 b/ B  U0 I: Q
  204. } MrvlIETypes_DsParamSet_t;) K; G. u. Q" F# i& O

  205. + @7 P' {, b# O, {  }
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
    ' ]: v. l0 q" c' E* {5 H, B

  207. + W, L# {4 R1 m3 C! d) x- _
  208. typedef __packed struct
    ; h$ q2 Y6 r1 t0 G5 ?' U5 F$ w
  209. {7 h" X3 T# r) _0 c' U
  210.         MrvlIEHeader header;0 ]. ^4 p5 T3 ^7 [6 R
  211.         uint16_t atim_window;+ T0 V* U$ j0 i1 g! h- e
  212. } MrvlIETypes_IbssParamSet_t;
    1 G0 ~2 o) ^6 q+ y( H. O

  213. 6 B' A+ \! o8 `
  214. typedef __packed struct
    - [! {/ @& T- p6 W/ [$ h  @
  215. {8 `5 ]- w' i5 _0 O/ e# Y
  216.         MrvlIEHeader header;
    ( p, A$ N7 u8 I: [1 W
  217.         uint16_t key_type_id;
    * H. I& M7 {/ g' d2 n% V
  218.         uint16_t key_info;
    ; B/ G. ?  S" |' i8 Y  m. g
  219.         uint16_t key_len;* u" B. ?% p; M; ^% J9 N
  220.         uint8_t key[32];
    + C* g( r# }/ I6 k' j: f
  221. } MrvlIETypes_KeyParamSet_t;
    - G4 Q! p% D) z, V" L* k. O8 T8 H
  222. ( K; z8 }+ {. W* i5 u. A  L+ ]% B- _
  223. typedef __packed struct
    6 g- L0 q0 N0 D9 k  [) }1 Z* J
  224. {
    % z; t4 v' w& C. ?6 K
  225.         MrvlIEHeader header;; S3 N0 j4 P9 r) n0 V, i5 B- k) o
  226.         uint8_t rates[14];
    , b6 p) u# [+ D2 U7 n
  227. } MrvlIETypes_RatesParamSet_t;
    . t  A. U/ X' ^9 w5 N

  228. ( V6 B2 G2 f( S3 }9 [
  229. typedef __packed struct
    9 H. i) E/ c$ u2 x# B1 Q
  230. {
    3 C$ I! {, }) d' }
  231.         MrvlIEHeader header;
    , {7 u" f6 Z* c% b& M  D
  232.         uint8_t rsn[64];+ P$ ~2 P$ L/ [  i1 |$ N8 c: n
  233. } MrvlIETypes_RsnParamSet_t;& @. ]0 e4 R0 [  S/ |

  234.   p. d3 V5 Z' C: e5 a, L* Y
  235. typedef __packed struct
    ' Z3 G' y, R% Z# e
  236. {
    0 t( o7 t0 |2 w% u% ^
  237.         MrvlIEHeader header;
    7 H2 j5 ~) W5 T
  238.         uint8_t ssid[32];& u" P; D9 j* o! Z2 w& M
  239. } MrvlIETypes_SSIDParamSet_t;
    ) }  \6 g: A: w
  240. : Z; W) f  A# z; P* u
  241. typedef __packed struct( A5 V2 K4 a! `$ b! d
  242. {4 Q& D- J+ j8 U
  243.         MrvlIEHeader header;
    % O' s( N2 |( C3 U$ h) H
  244.         uint64_t tsf_table[1];
    2 H( I0 {; ~5 o. q- F: Q
  245. } MrvlIETypes_TsfTimestamp_t;  [1 r$ j  r4 f) n* z3 S& u! d2 Z
  246. ' B, [( z1 b( q9 Z
  247. // 整个结构体的最大大小为256字节( b- M2 A2 b: s+ b: @5 k! b
  248. typedef __packed struct
    , E. _% D& ]: N2 W9 m
  249. {2 ^; D7 E! S) U( o! c
  250.         MrvlIEHeader header;
    : a( \" C5 F0 e2 l4 z
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够
    4 k4 d2 D( D( I  Q& [  \) {7 C
  252. } MrvlIETypes_VendorParamSet_t;
    8 O8 ]  d1 i2 f; E$ X8 v

  253. 8 `: c$ U4 B% b+ P
  254. typedef __packed struct8 S6 \6 z0 g, q7 a. p
  255. {$ g6 ?( Q$ U* q! X  z+ j! e/ o
  256.         uint16_t length;( H8 G8 J; A; Z, _# g- ]
  257.         uint16_t type;" g3 b# P* o" M1 D7 d( z: S; w" a
  258. } WiFi_SDIOFrameHeader;
    2 f6 F" t6 s1 O" [

  259. - z/ S% g  ]) Z# v- X: _. Q, F
  260. typedef __packed struct
    ' {. \! c8 Y( d
  261. {
    + t) ]8 A2 k0 c$ H- c$ G' v
  262.         WiFi_SDIOFrameHeader frame_header;
    5 P8 \- w7 X" V3 R" J
  263.         uint16_t cmd_code;
    & R* y" Q7 [' o* V
  264.         uint16_t size;- H# v% {( `* X$ A
  265.         uint16_t seq_num;
    8 X3 c% x2 }& [' Y! k' I8 n
  266.         uint16_t result;
    ; k* `2 e6 I9 t8 ]) \* [
  267. } WiFi_CommandHeader;8 J0 _" @$ V2 h0 y( N% u
  268. & k3 A8 k8 w+ W7 c1 @* X3 j( M
  269. /* Table 2: Fields in Receive Packet Descriptor */4 g6 i8 ~! S8 Z  ?* |
  270. typedef __packed struct- L9 S/ U, f+ [6 [
  271. {  ]* {0 B* y8 Z9 w1 F
  272.         WiFi_SDIOFrameHeader header;/ w! r5 `& z7 K) B  v* I; S( T/ e
  273.         uint16_t reserved1;3 P, @1 _" W! L8 ]4 x
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)9 g+ c2 C& A* E* S- ]0 m' Q
  275.         uint8_t reserved2;
    7 ?2 v. u" c) ~& n$ ]4 t! }
  276.         uint16_t rx_packet_length; // Number of bytes in the payload' ]$ d3 c  s" E% r
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.8 s, `! {1 ~; y/ q
  278.         uint8_t rx_rate; // Rate at which this packet is received
    . x) y- Y4 L) L3 f3 O
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet
    6 F8 n: l2 i) M0 G6 p
  280.         uint32_t reserved3;
    3 G0 `) @$ g* t
  281.         uint8_t priority; // Specifies the user priority of received packet
    7 T" V$ Y% J' \  L7 o( \: [
  282.         uint8_t reserved4[3];
    & V2 a# s$ k- f
  283.         uint8_t payload[1]; // 数据链路层上的帧
    3 ~$ }2 F1 U, B$ g. A+ S$ h& \
  284. } WiFi_DataRx;. S% ?% V5 ~1 }: i

  285. + z7 f! \' m$ d  l
  286. /* Table 3: Fields in Transmit Packet Descriptor */3 O; g; D( f% l7 m& t
  287. typedef __packed struct
    4 w- f  o) V9 ^5 M) O8 R/ p8 z
  288. {: U9 o9 k) }. @- z! ]" H
  289.         WiFi_SDIOFrameHeader header;
    . A4 Z1 R4 [: h% ^; ?* q# }( R
  290.         uint32_t reserved1;9 b& E- N/ V; `% R! O1 w
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings
    9 n: S% t$ y" U; c, {' k5 O8 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)
    " Y7 G) y$ U2 }8 {
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame
    # w& V4 n0 D8 G6 m5 n# w! w
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5! o; Z) t8 l& n1 j- l
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3$ X" c% v- q8 ^! I2 f% v6 e# ]! X2 m; o
  296.         uint8_t priority; // Specifies the user priority of transmit packet9 Y! _# w. o5 h9 c/ K% Y
  297.         uint8_t flags;
    ' r$ E6 h  Z& f7 o
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations
    7 ^' q* ^" s/ v3 X) F+ z9 q! W) W
  299.         uint8_t reserved2;# m9 v; J# Z  P- d5 ~/ c9 C+ C
  300.         uint8_t payload[1]; // 数据链路层上的帧
    ' p; y- k% {. T5 }- E
  301. } WiFi_DataTx;
    " ?3 C6 ]- _' N' Q/ U

  302. . F& @" e3 A4 F  T6 o. u2 F
  303. typedef __packed struct
    " h$ |: H- m9 _" X) c7 s8 x
  304. {
    ! S& L; u1 S6 ^" `
  305.         WiFi_CommandHeader header;; D- W# d/ j$ Y! v( z1 ]
  306.         uint16_t action;
    + j  {% G6 @4 t; s0 `8 q% Z
  307. } WiFi_Cmd_KeyMaterial;; D# Z; T2 K. u1 a: I# y! q  @) p
  308. 8 b4 q9 L$ ]6 t- f% W
  309. typedef __packed struct9 w! z9 D0 n& f4 O7 F4 a) ?
  310. {% Q% X8 a% f. W
  311.         WiFi_CommandHeader header;' V, C& ^5 T1 v  a+ R, O! a
  312.         uint16_t action;: @# }+ ?3 ?9 W# Z( h
  313.         uint8_t mac_addr[6];% P2 w7 u+ a- R9 o* }, L0 u# O
  314. } WiFi_Cmd_MACAddr;) D$ Y9 ?+ z8 h7 Z5 t: u) l
  315. ' Q& ^' Y" ]7 g" t4 }' U6 x
  316. typedef __packed struct) C) v/ x: Y; P- C3 \
  317. {
    : o7 |$ `8 b: Q- q+ B+ j! g3 ]4 ~
  318.         WiFi_CommandHeader header;# |+ S" e& d5 g' t4 `
  319.         uint16_t action;5 x, z& p1 j' [, d! d8 [& l
  320.         uint16_t reserved;
      p. `$ \+ `: [' b! j% u" t7 `
  321. } WiFi_Cmd_MACCtrl;1 ]8 Z1 _. ^+ M0 T, Z* }6 m) J

  322. % M1 h4 i2 f: W8 f3 U* [/ X
  323. typedef __packed struct
    ( m! p: v) p6 j. n! Z4 w; a1 |
  324. {
      x* C3 C+ u* Q8 j  {
  325.         WiFi_CommandHeader header;
    " r( K# g% z) G( b
  326.         uint8_t ssid[32];
    7 |/ |) Y/ l* J2 l! F8 g1 N
  327.         uint8_t bss_type;# g* s) t% H  T7 D' Y- }7 V+ A
  328.         uint16_t bcn_period;
    0 o; X, D6 E. H4 O$ P" e3 D: |
  329.         uint8_t reserved1;
    4 h6 Q* \& j. o" ~5 L
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU: K$ p6 r5 a6 L, f/ h( ?4 O
  331.         uint32_t reserved2;! F5 |6 w. a8 F
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network
    0 h  ?5 O$ I$ @" Q6 e
  333.         uint16_t reserved3[3];
    . D- Y+ H1 q9 J6 X: `* F
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information
    * G# b% E( V: e) A: S; s
  335.         uint8_t data_rate[14];1 h: d8 B8 _4 U  T2 J! d5 G
  336. } WiFi_CmdRequest_ADHOCStart;, I/ a. Y: ?8 q1 l

  337. 6 U  j: ^# f4 s: q" R
  338. typedef __packed struct
    . b1 ]$ x( W9 D+ t2 b+ Q
  339. {
    3 u  w! [* e* X8 N/ T7 T
  340.         WiFi_CommandHeader header;
    ( y* f5 O# G3 Y. b. a0 d
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address: i5 }5 C) S4 B2 e& w
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information+ g$ M/ @8 ~5 G5 g# v
  343.         uint16_t listen_interval; // Listen interval
    : _% z' Y5 C+ o# M9 k5 M3 |$ O
  344.         uint16_t bcn_period; // Beacon period6 m& g; p4 i/ G1 @& Y# B0 N
  345.         uint8_t dtim_period; // DTIM period9 B  x, z* ^" ~) M& C! H) W
  346. } WiFi_CmdRequest_Associate;& }1 J5 d! j( R" ?! `- u$ D- h
  347. " s, t! \, D6 |% ]1 Z
  348. typedef __packed struct3 \& N# t+ A7 m" M/ _6 z" t1 |
  349. {$ K4 Y) Y. J* F
  350.         WiFi_CommandHeader header;. v5 Z* T$ @: k" L. e
  351.         uint8_t bss_type;
    & a$ n/ t& ]% ~, V
  352.         uint8_t bss_id[6];* Y( B' L0 }5 w, }* S( V
  353. } WiFi_CmdRequest_Scan;
    ) p+ Q6 @) v$ j* Y

  354. 2 o5 S0 l* H4 S+ l. n
  355. typedef __packed struct
    3 U5 Z! J0 V" e$ e; G1 Y
  356. {
    4 z0 p9 @7 R' ^8 Z- F
  357.         WiFi_CommandHeader header;
    & k6 `& N& b+ I# k- H( P) m
  358.         uint16_t capability;* h- R6 S; z7 N; E0 s8 U7 ^6 B
  359.         uint16_t status_code;' K  z$ P, n% p5 p0 c2 ?* G
  360.         uint16_t association_id;
    0 ]2 S& m* L! Q$ ]! q
  361.         IEEEType ie_buffer;' i; s2 b" v( Y( K+ ~
  362. } WiFi_CmdResponse_Associate;
    2 Y; S* R4 P3 ?7 C6 X0 o' N
  363. + Y5 T, V5 j' j) ^0 s  i+ g
  364. typedef __packed struct
    , ?& c2 k2 W% q4 d0 i( D# T5 s
  365. {& h% W! R4 M; Y- n
  366.         WiFi_CommandHeader header;
    0 n  e0 L+ S/ N$ l' h/ J
  367.         uint16_t buf_size;
    3 F. U9 P' G' z3 h
  368.         uint8_t num_of_set;  q4 U3 v  T5 `9 V- ]8 c# r5 r
  369. } WiFi_CmdResponse_Scan;
    + x3 A  _" |$ r
  370. " h! S: e- x3 v5 K8 S( ?+ L
  371. typedef __packed struct: }5 S' P! ?; G  t8 u( P
  372. {- }) ?1 h" J3 [- k0 Z/ w4 g
  373.         MrvlIETypes_SSIDParamSet_t ssid;) F1 b1 _3 S; U4 p$ l. g
  374.         uint8_t mac_addr[6];
    & D% C: j  c+ ^8 o8 C: p) X+ U( v! m
  375.         MrvlIETypes_CapInfo_t cap_info;5 j" n/ ^. |0 L5 f
  376.         uint16_t bcn_period;
    0 G9 ^% m- O9 Z0 h
  377.         uint8_t channel;4 l: c9 g3 p* P1 H# M
  378.         MrvlIETypes_RatesParamSet_t rates;
    2 ?0 _) b: n4 U4 @% H$ W& |
  379.         MrvlIETypes_RsnParamSet_t rsn;
    * ~. i4 T! c" s8 w  z! V
  380.         MrvlIETypes_VendorParamSet_t wpa;
    8 P1 @% ]/ ~9 {
  381.         MrvlIETypes_VendorParamSet_t wwm;
    ( }" i% k. E" V* B2 s6 r2 B* `
  382.         MrvlIETypes_VendorParamSet_t wps;2 K! o4 g, X; E3 O. f" a
  383. } WiFi_SSIDInfo;  ]7 D* H. H2 W9 h  f6 |

  384. % c4 y) f9 V2 ?5 h: K% o3 G
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)# ^( I* E0 m4 p/ u5 s
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)
    3 T% b# {* ^: v; B" ^; D# V; A
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)
    ( i3 S$ u3 e& R7 |
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)
    . e  c, E0 e7 B4 C: s6 C5 w. B
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0), j8 J8 t0 Z# f) D2 @7 T
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)+ H" V7 I4 b2 R
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)! A+ D- X8 W4 c% ?3 P9 Z
  392. 1 {$ Q7 Q! c. ^1 x+ G1 d, D
  393. uint16_t WiFi_Associate(const char *ssid);& V- d) v. b5 u& \$ A* F4 N
  394. void WiFi_CheckCmdTimeout(void);
    6 G! {5 ?& n, h; z5 b; a. F
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);  R+ X0 _4 \9 e& L, E
  396. uint8_t WiFi_DownloadFirmware(void);; X: q1 M' Y' n% k: o
  397. uint16_t WiFi_GetPacketLength(void);
    9 J& {$ R% j$ Z. s2 f
  398. void WiFi_Init(void);
    2 ^0 |0 }" i# u9 t2 s
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
    ) q6 T: q% w6 Y  I& I' u/ y
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    3 H1 Y5 Y) d" l% l) z) l. h5 z
  401. void WiFi_MACControl(uint16_t action);$ n' Q, J$ W, {+ i" w
  402. uint16_t WiFi_PacketPending(void);& h+ o" p# z; [; r9 H0 l
  403. void WiFi_PrepareTimer(uint16_t nms);
    $ A# ^5 g1 E8 z5 d- H" a
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);
    & f- A; `3 d4 U5 e$ U; C3 A
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);9 ^/ M6 ~: s  ^8 q, T
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);( U) {" A- G  _. A/ Y
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);7 ], ^$ P$ I. `1 a. r
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);5 l6 }5 f3 z6 e, }5 h
  409. void WiFi_Scan(void);- o8 A. O. O" L/ T! h
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);
    6 Q$ h, N% V7 M: Z8 y3 M7 [
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);
    - w' J8 z, a# A0 y' D0 y3 F3 y
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    + @0 s5 K. W# z) ?
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);0 t) j. U  a  ~8 ~" o- U2 C
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);: N0 o( X$ i" F6 Q7 U3 P
  415. void WiFi_SetBlockSize(uint8_t func);
    & L5 M8 T1 {' G+ s) O3 l( F
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);9 s, {9 E' }! M3 X; u* ?: o
  417. void WiFi_ShowCIS(uint8_t func);
    9 q+ Y5 R6 q- ~4 C. O
  418. void WiFi_ShowKeyMaterials(void);0 p5 G( R8 ?  x, D
  419. uint8_t WiFi_StartADHOC(const char *ssid);, n! j% h& W2 _4 ]% p
  420. uint8_t WiFi_Wait(uint8_t status);
    # p4 E2 H( p' b- l2 l. M' P
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);
    9 m5 q- J& P4 ?! p
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);. v$ n& m, o+ N5 x) A& P/ S
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);3 h5 U0 V! u( c. v; Y' s2 t
复制代码
【WiFi.c】/ c, f* E+ ]4 P
  1. #include <stdio.h># k# W1 E# L4 ?5 |; w
  2. #include <stm32f10x.h>
    0 U! Z% N$ c5 U/ i( N1 L7 ?$ I9 P2 ]1 x
  3. #include <string.h>* {* I- D  z( s/ F% \% f# e
  4. #include "WiFi.h"( N7 N& N; F5 X: G8 I2 W1 M
  5. $ J) l9 m* X# U& J
  6. extern const unsigned char firmware_helper_sd[2516];1 ~6 P+ x8 {% M) ^
  7. extern const unsigned char firmware_sd8686[122916];: C4 {! D3 s3 R" o7 _
  8. " L' T) A! j, m- U% r
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
    " \2 W. U, h4 C
  10. 8 }+ N! H& C9 [/ _2 f& C; s' l) {. _
  11. static uint16_t rca;
    & e2 f+ k& D( t1 I7 g3 n, B6 Y* `
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;
    ' p# U: [" K! m! Z) A
  13. static uint32_t io_addr;
    2 q3 u% t! J+ O3 J* F' D6 d9 I0 X) V! ?
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小+ _0 W2 k# c" _0 ]* c2 \! e

  15. ; X* Y% H- h. A$ M) X" T5 ^
  16. void delay(uint16_t n);' Q* n' }+ K$ K8 T. G' \( D. K
  17. void dump_data(uint8_t *data, uint16_t len);
    - m/ h9 V: r4 y& m6 u% v

  18. 8 ]) C+ w' F4 u% E
  19. /* 关联一个热点 */
    6 I$ l! U( L4 ?
  20. uint16_t WiFi_Associate(const char *ssid)
    2 O: y6 C; B& @" N
  21. {& ?2 ]4 W' f4 S  o8 V! ^; f
  22.         uint8_t buffer[2048];0 C* l/ E& `) a2 I% \& v! {2 `
  23.         WiFi_SSIDInfo info;6 m4 @9 w  t# p' @' B
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;0 a9 l9 |* A$ D' w2 F0 \) j; y  s- _7 j
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
    , E4 \, f0 {9 ?+ N0 \
  26.         MrvlIETypes_DsParamSet_t *ds;# w, ?2 K9 [+ D, |
  27.         MrvlIETypes_CfParamSet_t *cf;( E' P' n  m" P
  28.         MrvlIETypes_AuthType_t *auth;" V& ^) K* ~8 o& K2 j
  29.         MrvlIETypes_RsnParamSet_t *rsn;
    ) q6 v8 u7 ^- |% C0 S# e# k' d8 d
  30. 8 D, E) Y3 K; Q% ?  V' B+ F
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))
    # A/ Z0 O6 F8 b2 ]
  32.         {$ X3 c4 N3 b- O
  33.                 printf("Cannot find AP: %s!\n", ssid);6 S9 N- I0 u$ ?6 d  L( R2 S
  34.                 return WIFI_ASSOCIATION_NOTFOUND;
    ! a( ~1 X1 E3 j% s! P5 V: _
  35.         }
    ; b3 w* w0 ~, b' L$ b1 m" m
  36.         
    ! T% d' g, b2 D
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));, r2 |7 o) {! g
  38.         cmd->cap_info = info.cap_info;
    " L$ ^; `+ {$ E/ _+ m  `* G
  39.         cmd->listen_interval = 10;
    6 N0 S" c" O  Q, L1 `6 T" O5 J3 @( C
  40.         cmd->bcn_period = info.bcn_period;- A9 ^8 _! B3 `$ Q
  41.         cmd->dtim_period = 0;
    # U# Q/ F8 ?8 }2 W% D4 t
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));: z' F1 }6 e0 F/ Q: j
  43.         
    " W  u# V9 X" U+ _
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));7 v* Q+ p% |! j! W
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;
    - `" k0 l9 U) W/ H" ?6 Z( v
  46.         ds->header.length = 1;
    1 u, C, W1 y2 k/ H2 d! S' O
  47.         ds->channel = info.channel;
    ( e7 K( s, P# C5 G
  48.         
    0 Y! P6 Q4 T0 C) G6 B- o$ }, \; e
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);
    , s& S: Q5 p2 H% T1 W
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));
    ' e7 N% G2 C% [. p& o8 w" ?
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;, V3 {) T% D0 k* k
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);
    4 Y/ t. x. z3 A- v0 W
  53.         
    9 z7 M# {( z! {6 M1 [+ P
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));+ }: Y; l4 h4 ~# J
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    ! D1 g2 x  q6 t6 I( l: ^
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;# `  E( e# X5 W1 c9 I4 X7 v" T2 w- ]8 _
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);
    6 X6 H, g5 u; U9 h: Q5 T. s
  58.         auth->auth_type = AUTH_MODE_OPEN;
    , I4 L* e! ~' p
  59.         1 t# V$ u( |& }: S0 C
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
      R" \9 V5 @% n& @8 Z
  61.         if (info.rsn.header.type)' D6 x! ~" ?- G$ E- v) o# l, g, X
  62.         {
    8 ^- K( s/ j* X. J6 w. N
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接
    2 b0 P  i- @1 p( ?/ K9 }
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
    ! W* U7 O2 |" \8 @6 f; H7 z$ n
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));
    1 y# Y" ^6 [6 _3 i; q: ]
  66.         }
    ) U) n# ]) T5 N& e7 @5 ]
  67.         else" c( v' w3 L- o' Y
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数1 d, i2 Q& H* `, L! w: c# H
  69.         # K) x) C, M' n& [$ p& q
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))7 K  \1 c' G6 s6 o4 \' ~
  71.         {9 O4 E4 V% ?' N# A
  72.                 printf("Association with %s failed!\n", ssid);
      e8 _$ y) [  F, t) z0 j2 w" P
  73.                 return WIFI_ASSOCIATION_ERROR;7 k* A: z4 n6 |5 v3 D0 x! U
  74.         }+ ?1 ^2 j9 q1 \) _
  75.         6 A8 ?: L7 `& y& o- |7 G
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);
    2 b; l* J- K. b5 V- {
  77.         if (resp->association_id == 0xffff). T! J! n3 j5 k& e9 t9 A; d
  78.                 return ((-resp->capability) << 8) | resp->status_code;$ E7 v- i: s6 p9 d2 W  ^
  79.         return WIFI_ASSOCIATION_SUCCESS;
    0 U$ r  L( ~8 p$ @* y
  80. }6 g/ [9 Q9 x- T# u* [
  81. ' H, u9 X3 b: Q5 q! v% S
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    6 u0 @3 r! h6 R: B3 t. I0 i$ C
  83. void WiFi_CheckCmdTimeout(void)
    , R9 E: ~) b7 D# n2 R
  84. {9 a& i; ^/ F3 I
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)0 M/ i! I9 Z) Y3 Y
  86.         {4 q8 e3 m; M3 y, C
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志
    + O& S5 N8 O( w! Z0 A: I! U
  88.                 SDIO->CMD = SDIO->CMD; // 重发
    0 [( u. C: j/ j$ E5 X
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);6 Z% G, Q. z5 W0 c; c; @8 ~
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);
    $ H! C& K) R4 X# b5 i/ N# Y/ s3 V
  91.         }
    / `0 T3 x/ N5 j! O
  92. }
    * _4 S! O; i' v, R

  93. ! q0 S! s* E3 V9 w' w  @
  94. /* 连接WiFi热点, 并输入密码 */
    + e* y2 j3 A3 }( P' Z/ L
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)
    - u% i% v. |8 Q2 g5 O6 D5 e
  96. {: U( B) c0 h3 B5 o. p( w  @
  97.         uint16_t ret;& b) X: K3 l5 ~9 g+ f
  98.         do, X- ^( X9 Z7 c' z
  99.         {: D: c; v. L1 Z% ~: t. a/ I4 l. n
  100.                 ret = WiFi_Associate(ssid);
    ( j1 L% a; V. C
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS), j3 \: b6 Y/ r8 m$ X0 j) ~1 `
  102.                 {  Y1 Y4 `0 j8 l# J: a; `
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);
    2 R5 G% S5 f( q# G% E* G9 Q' S: x3 U
  104.                         delay(2000); // 等待一段时间后重连6 `7 ]5 Q2 `7 A6 o
  105.                 }( T3 T' l, V( `& w* w/ X: q" q0 k
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连, K; P: @6 y: g3 w5 H; m5 z
  107.         7 {. v% H2 R% E  k# E0 J
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)( U1 |2 x. C: A7 e. h8 t
  109.                 return ret;
    % {6 i& l( v5 s9 s  j' h' I6 [, Y3 @
  110.         
    % F* C- r* X, Y! G
  111.         printf("Connected to %s!\n", ssid);
    8 q) r9 `8 ?* z1 Z+ y; j2 P7 s" `$ y
  112.         return ret;
    & i) P/ y5 z) u
  113. }
    ( d8 _8 E' y3 W. B% q3 Q2 L3 p
  114. 8 g, X! W( E/ E$ R& q  i
  115. /* 下载固件 *// M+ I% C8 Q. e; J' A
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc8 p" D+ G, l1 f1 j
  117. uint8_t WiFi_DownloadFirmware(void)9 a; A! }! {' j3 x! \$ w2 _
  118. {! S5 t/ ^' V0 K; T
  119.         uint8_t helper_buf[64];( v6 |  {4 O- f
  120.         const uint8_t *data;; S. X4 ^) A5 B! y+ `
  121.         uint16_t size;
    ( t2 ~( n+ Q- |. ^; L  Y, e
  122.         uint32_t len;
    ; _; [" f- q& r, y0 P
  123.         
    - g, u- w6 K$ [) k9 U# x0 C
  124.         // 块大小设为32
    3 A: F6 h- N% m; [) D* t* P
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;" {: x" s3 T8 z9 G# X  c
  126.         WiFi_SetBlockSize(1); // 应用到Function 1
    . w( W8 ^( z6 ?2 o5 K# _; S
  127.         
    2 z5 ^+ Y, z& d& o4 S( N
  128.         // 下载helper; v- F0 ~; c. i3 J# C) P+ I
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);) r5 c9 O# S, v: e* S) ?# ^
  130.         data = firmware_helper_sd;2 T8 ]% y& a& N/ p; X9 W( b
  131.         len = sizeof(firmware_helper_sd);
    2 ?" S* v3 D+ x
  132.         while (len)2 O3 H- W) t2 ?* |
  133.         {5 A  N' ~! `% w( F" a( b
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量
    ! u: n" F1 ~# z$ {- i' y2 m
  135.                 size = (len > 60) ? 60 : len;
    , @# s5 z! h  `! M; ?0 ^* l& g: ~2 @
  136.                 *(uint32_t *)helper_buf = size;  I9 _; V$ _& \* I7 Z
  137.                 memcpy(helper_buf + 4, data, size);+ f9 M8 j$ V! X$ l5 @( U
  138.                
    % J$ ~' k0 Z" b  _6 D8 j' Z
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    . [, @8 d! O5 l
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));: e4 K6 b! @5 g, O+ e! k
  141.                 len -= size;) ?" W* w" m1 N0 o& J8 v
  142.                 data += size;
    $ F9 f8 F0 a8 c1 B4 `2 p
  143.         }3 Z: L5 x% V( `" T+ {7 x
  144.         *(uint32_t *)helper_buf = 0;: f) v4 e( I0 X& Y
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束
    , M* V) |. W/ W  f4 l! Z0 {! S
  146.         # U" Y5 A' V% i+ a: S
  147.         // 下载固件: Q7 U/ g( g) z
  148.         data = firmware_sd8686;: `4 |3 ?& X' K- L* @7 ^: f
  149.         len = sizeof(firmware_sd8686);
    5 K1 f1 I) G2 \* n, J5 w
  150.         while (len)
    * C8 O* v% G  H  L: z
  151.         {+ |7 J" f4 z  ^5 s' J3 |
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);* n: `: M8 D* s) w
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数- _2 h6 ~  @, b6 U" M5 h& h8 P% S0 Z& m
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);
    ! V5 A2 M8 [) @2 j1 e- F6 |( [
  155.                
    2 i8 U( ?  v* b( F" a7 N5 Q9 r* f
  156.                 if (size & 1)# g; [: H  k& ?5 Q
  157.                 {
    % S9 w& `0 g3 Y6 a0 Y
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)
    5 W/ O- t; l; B# t8 `
  159.                         printf("Error: an odd size is invalid!\n");9 F4 |% A' r1 v+ s! Y: R1 _
  160.                         return 0;' E+ |0 s0 N( O( n( `
  161.                 }! j* a/ T( u* ]& F8 }
  162.                 if (size > len)" {' [- [5 b( b# `8 n) v
  163.                         size = len;
    5 I/ j- N( v- ]! R+ A: o9 W
  164.                 2 m; S3 M( a; O
  165.                 if (!WiFi_WritePort(data, size))' P1 F3 l+ b- n& S' ]# w4 ~. `
  166.                 {
    . \! h2 x+ h  J- ]0 n
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);
    & U/ h3 z1 m9 V, }$ `3 S
  168.                         return 0;& [' f# d$ d' z5 ?
  169.                 }, ]9 B* i- k" }$ W4 H
  170.                
    7 p  I/ |$ N) t. m5 P2 I# G
  171.                 len -= size;% Z1 f& u# |! ^( S1 `: e2 C" F
  172.                 data += size;
    7 T! R' W" O$ H4 w. ]% ]( E
  173.         }
      Z8 Q" B! [6 [+ b# @4 B
  174.         
    % ^+ K1 G* I0 {0 W* F3 Q" ?8 @6 ~
  175.         // 等待Firmware启动
    " ?" C- {% |* X1 @1 ~
  176.         while (WiFi_GetPacketLength() == 0xfedc);; V; c! E* b& w
  177.         printf("Firmware is successfully downloaded!\n");
    0 s3 L! s4 B1 \8 v) ^
  178.         return 1;
    5 ~) ?" W! f( e' P3 J
  179. }
    . d, V: Y* z* u( H
  180. 1 Y- p2 C. p9 a4 }/ f$ m2 y) E
  181. /* 获取数据帧大小 */
    4 n  G6 k- u( q$ w; X* x2 e
  182. uint16_t WiFi_GetPacketLength(void)# O5 d2 I$ G6 ]$ _8 }
  183. {
    3 P# K5 s4 ~* b
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);( z2 w3 A# e% p* r
  185. }5 f0 Z$ ?4 m  ^

  186. # H- p! L1 U9 R" C( s
  187. /* 初始化WiFi模块 */
    # @# \6 P6 Y- T/ X! x
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization) e3 Y% r: C/ u
  189. void WiFi_Init(void)
    ! R) P) D5 N5 T. x4 M3 o* t6 w
  190. {( ?! x% m# F! j" Q/ \; D
  191.         printf("Initialization begins...\n");9 U# _  \# y* o7 e5 a
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;
      r: ?6 ~' I' ~7 @
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz
    8 D" D3 v, o" e7 Q0 R5 W0 k
  194.         delay(5); // 延时可防止CMD5重发$ j" |$ O2 y% {( B  Z; x5 p0 m) E9 s
  195.         , `! [5 G% \/ n0 i! L, \0 ^" U
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
    9 Z. S1 _& q: u* A! Y: d
  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)
    9 d- \# O+ z' M4 h. M
  198.         0 @- {: o$ X* Z* r4 v5 g0 }# x+ p
  199.         /* 发送CMD5: IO_SEND_OP_COND */; x9 Z/ w* b1 T1 ~% Z( h
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;' v" b: k: Y6 B% T' r; g  ~/ y+ {
  201.         while (SDIO->STA & SDIO_STA_CMDACT);7 G$ b9 Y* Z' `# A$ Q) t  o6 d- _
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令* f1 B9 z- C- Q! E4 G
  203.         if (SDIO->STA & SDIO_STA_CMDREND)4 }/ ?/ m. M' f
  204.         {
    . V( `& X9 D; U( T, Y2 f$ F+ c
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    6 P# H2 ]- ]5 J- }9 V
  206.                 WiFi_ShowShortResponse();) [, z+ e* Q2 n+ ~
  207.         }
    7 K- |2 I/ A9 V* @4 Y
  208.         
    ' r2 E3 `2 n% Q
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */7 h: N, o9 F. k. B- c9 ?
  210.         SDIO->ARG = 0x300000;0 }2 j; P4 }- q+ D
  211.         SDIO->CMD = SDIO->CMD;% W6 R8 \9 Z  ^2 u: T- I) x
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
    & |: g/ k* }# c# f1 Q6 P
  213.         if (SDIO->STA & SDIO_STA_CMDREND)  Z' z4 ]2 y; \7 ]  [; j  ?
  214.         {5 {& P; {3 ]+ C' N  M0 `
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;$ c- g9 c' l+ k* [0 y* s
  216.                 WiFi_ShowShortResponse();
    & A2 p+ {* U% \! y& O: |
  217.                 if (SDIO->RESP1 & _BV(31))
    : G  ~3 l) @* Q1 x
  218.                 {' S# ]+ ]/ z4 A
  219.                         // Card is ready to operate after initialization
    9 h# Q* B) |7 `8 J% ?9 f" o
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);
    % l" N. c& J# X$ g
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);
    % l. }: C1 K, D6 I/ k$ e) X
  222.                 }
    4 y! a. X) V! p. G; N
  223.         }, N$ l5 r2 e! K1 q1 L
  224.         ! }% k* k- i) ~/ X- _
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */5 X% c, r0 T1 w7 r, l* R& ^
  226.         SDIO->ARG = 0;; t* a  a' X- f5 d0 S- h0 I) `8 n
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;5 G/ u. B/ ~! h# I
  228.         while (SDIO->STA & SDIO_STA_CMDACT);! M' |. i. ^& h0 G# J
  229.         if (SDIO->STA & SDIO_STA_CMDREND)* t( ?, k- a. J8 Y5 C
  230.         {
    9 g6 l( H. t+ H. Z, h& K
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    4 d. h% d% p) @. y( s' ]
  232.                 rca = SDIO->RESP1 >> 16;
    ! }8 N- @$ V1 r3 R! Y8 S! T1 {
  233.                 printf("Relative card address: 0x%04x\n", rca);
    0 b8 j. R  e0 z" Y  S8 e
  234.         }
    & ?: n; t- t0 s; |; B5 v7 ~
  235.         4 C6 Y5 |3 u7 s3 k0 `' H
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */0 O( V6 ?: _+ m+ h/ H5 o: A
  237.         SDIO->ARG = rca << 16;
    ! S( T9 ?# s0 k5 @7 ~8 c, s
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;. V4 S4 A% U  j/ b; e8 o
  239.         while (SDIO->STA & SDIO_STA_CMDACT);7 L' Q' k8 M( x" S# f# B' k$ ~8 @
  240.         if (SDIO->STA & SDIO_STA_CMDREND)5 _* Q5 n( }4 @1 e' f% ?
  241.         {
    $ |& z2 k2 d( K3 |! e: K" p% g' p
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    1 J. q1 ^3 i. D% w5 x; \
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);- w# N& t9 I1 }. ~! x
  244.         }' \* V, t! s5 ?& z6 k
  245.         
    ; x: S" b" t& m+ t
  246.         // 提高时钟频率) [& R9 j; }( @* J$ z! y
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
    6 O" i8 N  {; A1 Z7 {; p
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒' S. _' ?& v  G  u; O6 I
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
    & {! T+ A4 k  M# Z1 f- ?1 ~
  250.         
    1 x3 @1 S* F( z  Q
  251.         /* 选择总线宽度 (Wide Bus Selection) */8 ?: O) \7 n( _3 a
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)' B, t4 J+ M5 i+ @& F
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers2 f# E; B/ u3 g8 _3 O" D: I. `
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus* I9 F3 ^+ s5 s, S* r
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
      b! R9 H' n5 A0 M9 r5 F/ Z7 M6 {9 C
  256.         
    / h4 T1 \/ s9 E2 ^! A
  257.         // 初始化Function 1
    . ?1 \4 [  z7 ?$ m% k# ^4 m; W
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)
    ! s- I. U$ c4 |; c7 W( U
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)
    6 E6 m$ n- v8 \- I# R$ s$ a; d5 H0 \
  260.         . Y7 w8 ^( I1 C1 d
  261.         // 显示CIS信息
    5 L( a2 x/ {* j6 ~* D  w# `
  262.         //WiFi_ShowCIS(0);
    ) b, v9 n* [4 i2 U( I
  263.         //WiFi_ShowCIS(1);
    7 J) F/ o0 B) d4 C+ ]6 ], T
  264.         
    $ o! Z" h1 W! l( l
  265.         // 下载固件$ z  _1 {6 p! @- I+ i; C" o
  266.         WiFi_DownloadFirmware();
    , f& O% V9 t" ?* o3 i( e0 _( G7 X
  267.         
    4 F$ P6 J! a" K/ }
  268.         // 设置数据块大小为256字节
    / v! f' A% @0 P- F( \: r+ F" A
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    9 U" K; l: d9 ]
  270.         WiFi_SetBlockSize(0);0 d+ R1 G, G7 v, Y2 G! ^
  271.         WiFi_SetBlockSize(1);" m( [/ t. @4 F( H
  272.         
    + q2 B7 _  _- |5 }: O
  273.         // 允许发送和接收; E8 n5 Q7 c5 V% r
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间, N5 _% ]% e; x" P
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);
    ( s! ~( Q4 c+ P, ^# s# ^- u) i5 p
  276. }
    ! C( m4 Z' W' V; |- ^

  277. 7 m4 C# e# c" H8 m
  278. /* 获取或设置密钥 */$ u# C5 f# P5 _1 Z! Q( H
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)
    0 F* g9 h* N, L
  280. {5 i: O, |3 V* x  [1 M5 l% T
  281.         uint8_t buffer[256];
    : j0 }# L  L* t' q7 q3 K
  282.         uint8_t ret_size;
    4 T+ f* Z; R3 V- Y/ G
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;/ [3 w9 G$ J* d* l( Q/ _; t  V/ p
  284.         cmd->action = action;' \6 V. K% l2 v7 Y, Y2 L) D$ a
  285.         if (action == WIFI_ACT_SET)8 D- i, {1 @6 _% M" n
  286.         {
    & z: W0 V5 D! d- }  E* K, ~: H( Q
  287.                 memcpy(cmd + 1, keys, size);$ r/ b% X( T3 m$ s& O: d, E$ B: B
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);
      \2 A2 \# Q3 B
  289.         }$ `5 ]. [9 _% n' l* t: j6 U
  290.         else
    / {' p6 b( C' M1 y( E3 h" D
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));" i& B5 {9 a+ L  Y
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));
    & ^/ s5 o3 Y2 @* P8 E; m
  293.         
    / j+ n: n' \$ v5 |
  294.         if (action == WIFI_ACT_GET)
    3 n: R" U' T6 T, t
  295.         {
    - \9 }, ?; h) X7 @- n
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
    % E% X& u% ?9 z) o" X2 P
  297.                 if (ret_size <= size)
    ) ?  A/ D5 V- V; F! u6 Q
  298.                         memcpy(keys, cmd + 1, ret_size);( Y; S( Z1 D3 Z9 ?4 c6 _- \3 G& d5 A
  299.                 else9 G" F$ Y+ q; X& W0 E6 B/ F; q
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);: m+ ?0 L1 k# ~3 h/ R
  301.                 return ret_size; // action=get时返回读取的数据大小
    + C3 r1 ?3 }- j; L* J7 ?0 ~' a3 H
  302.         }) D, ?& P1 r+ w. ~& U* O9 y* \
  303.         else: q1 L. i9 l1 a6 H1 Q
  304.                 return cmd->header.result; // action=set时返回命令执行结果值2 i4 t' f; y& n, i3 w; ]
  305. }
      V  I# d2 Z6 L6 [4 F9 v% d
  306. " S: t) A) y' @0 s, M8 a
  307. /* 获取或设置MAC地址 */1 o4 A, g8 h9 o2 s" p$ Z0 {
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)
    , i: C" V* s( A
  309. {: D, X5 V. }5 ?
  310.         WiFi_Cmd_MACAddr cmd;3 m$ C- Y& P, A  a/ e  y
  311.         cmd.action = action;
    3 \% d& s) k0 ^
  312.         if (action == WIFI_ACT_SET)( G8 H% X. q- w* y6 C" i& l- b. d  b
  313.                 memcpy(cmd.mac_addr, addr, 6);# @/ M2 h7 Y& n% J4 x
  314.         3 ]; \6 C, C  \% f3 C
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));; ]2 ^2 l. _) t; @
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    : Y' K9 t; Q1 S" s
  317.         if (action == WIFI_ACT_GET)
    " i6 d% k9 }% W9 ^
  318.                 memcpy(addr, cmd.mac_addr, 6);' r, s$ l) I$ z3 F2 v
  319. }
    0 M, v0 d3 K& b- w- m& B; z

  320. . T6 Y3 A% h1 q# y9 o
  321. /* 配置MAC */  V) O7 W- I: z5 u8 T+ c
  322. void WiFi_MACControl(uint16_t action)
    6 {7 E( x* h/ L0 B
  323. {+ D& q  \' ~1 m( _/ Q! l0 v; K6 q% Y
  324.         WiFi_Cmd_MACCtrl cmd;
    % i' `  B0 z% P# D
  325.         cmd.action = action;
    8 K4 o" {2 r/ [: h/ \
  326.         cmd.reserved = 0;' G4 w) W6 B1 G
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));3 ^7 }* e* G! S8 k' E
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));3 d. ?/ n5 b# C
  329. }
    $ e6 i, Z! d& |$ P7 k# d0 Q

  330. 9 y0 J6 z  M1 x, K
  331. /* 获取滞留的数据包大小 */
      k+ F; ^3 p5 N5 X) ?6 ~
  332. uint16_t WiFi_PacketPending(void)
    & t3 C) w9 U. z. N; j7 z# E
  333. {
      X8 ~7 U! [' K6 B
  334.         return wifi_pending_size;
    ) K# D# i+ G/ k5 z+ q
  335. }
    ( s* V: \* C1 P, R
  336. $ I5 u$ [! y2 x& w
  337. /* 准备好超时计时器 */5 Z2 G+ l+ |3 ]5 u- P
  338. void WiFi_PrepareTimer(uint16_t nms)
    # m! t) p2 g+ g. r+ `# o
  339. {9 R" W5 C# ?5 O' P
  340.         TIM6->ARR = 10 * nms - 1;$ ^! p" \' p* F7 y) `
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz, V6 ^1 I9 z1 c$ }- G9 b& ^
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置
    . _4 D- {* Z; V" w. h$ a! ~
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位
      e0 y4 ~% ]$ J: T# i
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式8 [6 g! x8 `5 {6 _
  345. }" }/ Z) V# |% j# u, O
  346. * U: d, Y- ?6 n9 w% C0 {* L- Y
  347. /* 读寄存器 */9 p1 ~$ W. a. y- u3 U- N! G
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr)
    $ J8 [7 q& F* F6 Q
  349. {
    8 O( g" `' \' H" z. N4 X
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);' b2 B% h6 o7 i( T
  351.         if (SDIO->STA & SDIO_STA_CMDREND)' ]) ^* B- Y5 ?0 o& T& M
  352.         {8 k' T1 O1 x( E8 I# u+ a
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;- {4 a' k; V; u
  354.                 return SDIO->RESP1 & 0xff;/ D/ Z$ y4 M! [* b2 `9 f
  355.         }
    , ^$ f+ b3 x9 R! I
  356.         else2 a+ G" ]5 A7 `" r
  357.         {
    7 t' P' p8 @0 l! b. z
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);7 `3 `& ~$ E6 {& C4 u/ G
  359.                 return 0;
    0 Q  c$ s5 g7 }+ M
  360.         }5 Y- c1 v& T; X  v/ B3 T
  361. }# N- h: S0 [" I9 x% X( D; q, O
  362. 3 t/ h2 Y/ i$ G4 ~1 K
  363. /* 读数据 */! k" D$ M: w. C4 O+ Z5 P$ O: K2 b
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    1 A# i% ~# e% K( H3 @* q4 K- S
  365. // bufsize=0时, 只读取数据不存入缓冲区
    # @9 x3 c9 h$ ^2 Q9 G. T
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    ( U! n' Q, P/ c  P# f+ O9 W! w
  367. {0 M' f/ B( Z  e% m. S" _1 J7 O
  368.         uint32_t len, temp;
    5 N( S5 `) _) e7 ^
  369.         if (flags & CMD53_BLOCKMODE)# `6 Z* L) Q8 }* R
  370.         {
    + U* m1 F2 X, z5 F
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数. X" s- ^( p" S% S, k6 X6 B
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
    7 F2 A( Z3 H& K! t4 R5 a$ @
  373.         }9 u1 U% q5 x1 i
  374.         else% [/ E, c5 }! H9 q0 L
  375.         {  y+ T# }1 t& s5 u
  376.                 len = count; // count表示字节数+ g6 |" I3 X& K3 E
  377.                 if (len % 4 != 0)) b% k% c1 z" f2 l/ [, c
  378.                 {
    + f' ]7 r# h- l% E) h) D
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍7 z- l+ |$ ~& u/ W" o/ d3 `
  380.                         count = len;
    ! K, {. r7 l( l# I
  381.                 }6 `0 Z9 R; }; N. V, T' T  t
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式
    ; u) N) E* T- _  B; \
  383.         }
    2 F4 ^2 Q* P+ p) i2 x
  384.         SDIO->DLEN = len;; l6 t8 T) E+ ]. Q7 T
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
    * t% f& x) O! |& V5 Y% y7 G. E
  386.         
    6 E, Q& h9 r" }, l9 l8 n
  387.         WiFi_SendCMD53(func, addr, count, flags);
      S( w' V& w# d* ?
  388.         while (len)  ]8 D3 G- F" |, q3 y7 Q9 R! h! p
  389.         {
    ' {" }" K" [# T: g0 ]" }8 [7 e
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)7 a/ {: i- I4 K6 [; C/ X* L
  391.                 {( o! x* w, g  U' e+ y6 O9 }3 @
  392.                         // 若有数据到来就读取数据+ n- E8 O( @, L
  393.                         len -= 4;
    & A0 ~8 e9 J2 y# X  Y( s- I
  394.                         if (bufsize >= 4)7 p* s! X. A% y  j9 W+ N+ R
  395.                         {$ g( Y  M- U$ z: Y" P5 f
  396.                                 *(uint32_t *)data = SDIO->FIFO;
    ! e( i. G  C1 }, Y) D. l6 M% D; f& T
  397.                                 data += 4;
    " r3 g2 w& e1 s5 |0 O1 F9 v$ e. I" X
  398.                         }" |3 T) h( C( {, i$ G
  399.                         else
    * \0 f8 ?1 i9 P; @$ g, W
  400.                         {
    & \9 X$ K( S' l! p6 s  Q5 t* [
  401.                                 temp = SDIO->FIFO;
    / B# N, D9 d3 ~2 O
  402.                                 if (bufsize > 0)' b' }4 q0 G& s! ~1 G, E/ F$ x
  403.                                 {
    6 ~% P/ {) r' s  V
  404.                                         // 写入缓冲区最后1~3字节( H3 B& B* t  N& e
  405.                                         memcpy(data, &temp, bufsize);, @* @1 F: I* X) q9 B' g" W" O
  406.                                         bufsize = 0;
    9 M/ d3 {7 b7 `/ k! c# ~* ~1 ]) `( H& @
  407.                                 }8 N% G, F; w5 R; Y
  408.                         }) y. p$ w4 r& X8 c( p& o
  409.                 }$ Y: b, o: Q! I* Z- c7 Y+ r# D& M
  410.                
    & \# G6 d6 Z) F* P
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)
    ( Y$ Q/ n" |7 A# F4 ?3 a! `
  412.                 {
    " ?; q. w' C! R: D
  413.                         printf("Data Timeout!\n");
    . c) M% P- b- g
  414.                         break;
      M* y8 \) X0 g# H' i& G# o
  415.                 }6 g2 b/ M) p, Y* ^% d" t
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)6 g3 ~  ^; T3 S0 i8 u
  417.                 {
    4 L; n( S/ }9 B' ~' N# X" V
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    8 }) D$ b0 I; A2 H; x' e1 Q9 g8 q5 u$ {. F
  419.                         break;+ M2 W) D0 N; H- X
  420.                 }
    - N1 R7 k0 y) P! ?
  421.         }
    ! [. w" |7 n6 u& u( ^6 }( {, }
  422.         
    # B0 c0 h3 u; ^, N+ K' ~: @* v9 r
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));
    * i$ W- B: x( d' G! J
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;+ D  |0 V; A! s3 ^. g& G, \
  425.         
    - L+ F  D  {% H$ _
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;: x- H. b6 r; i9 M/ v0 b, U) u& q
  427.         if (flags & CMD53_BLOCKMODE)
    9 P) N" p6 D" n3 T9 r% @4 m
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;; p+ o1 W/ l7 S' X  y! d
  429.         
    5 }1 h% g, v" \  o' a6 i
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功/ [; y  c: x4 P( U% O9 ]4 \
  431. }
    2 H% c4 v2 B5 |5 \4 a! ?) i8 @
  432. 8 ~  g4 N( o' r- B  j8 D
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)
    2 i& {3 c; _& [/ v4 J2 I% g) W
  434. {9 y$ }. D/ Z. a& H
  435.         uint16_t block_num, block_size;
    * {# r$ X: k1 U7 t1 p* q
  436.         block_size = WiFi_GetBlockSize();3 C9 i2 ?8 l# j5 g- U. W: [
  437.         5 D0 C0 P3 {0 V* w- m3 @
  438.         // 读取数据
    % v" K+ S0 @& q1 m; Q' `/ W
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    6 m* }5 @# {, i7 l" p4 \8 u" d
  440.         if (size >= 512 || size % block_size == 0)3 ^. ^' J& X4 s
  441.         {
    8 _7 [7 D$ U3 z3 C- U) ?! \
  442.                 // 采用Block模式传输. \* B6 l- ^8 g" z8 I
  443.                 block_num = size / block_size;% G# H( M/ d  u% ]2 q
  444.                 if (size % block_size != 0)
    8 D: b. G1 _( e5 C: v
  445.                         block_num++;1 J. u: y# F. I2 C* [: N+ V
  446.                
    7 h2 K7 D& ]; m8 J; H  L/ ]
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);; ?: [( u+ j9 N8 v* V/ b( `
  448.         }( S8 _. K4 J6 Y- U7 f; S7 |6 T+ y! Q
  449.         else2 A% S9 e/ ^) s  k
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);
    1 m8 `( j- X' x
  451.         
    ' x" G7 _- X# B* q2 G) [3 P2 ?
  452.         return SDIO->STA == 0;7 b! K7 B0 l1 y! E6 Q7 L+ Y
  453. }) {; x) h: u3 o( {8 N6 @
  454. % z5 ~8 u2 e7 h9 W5 H
  455. /* 接收数据帧 */! g+ q8 C2 D% T" e
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)% |  a) P2 E/ Q5 _4 _: Z7 o' r0 z1 u
  457. {( F, d1 r- Z. ?0 l+ s
  458.         uint16_t size;
    ( j; p% R8 K+ x
  459.         if (wifi_pending_size)
    $ C) y0 F: E$ I3 u
  460.         {/ `' ?8 m4 b. y6 @" E! m/ W8 @
  461.                 size = wifi_pending_size; // 先读取滞留的数据包( a/ F- n4 ~" o
  462.                 wifi_pending_size = 0;
    . [( t2 ]0 ?: d$ c) m( V- S
  463.         }$ g$ _/ O/ b! P. R1 b( p  |9 G* `
  464.         else
    . u3 \" n- k& g& o- C+ D, t: K7 l7 q
  465.                 size = WiFi_GetPacketLength();
    8 H0 K0 m% D5 x: f; S& g- O2 {
  466.         return WiFi_ReadPort(buf, size, bufsize);. V# w& N. M' E2 o: ?* Y* H+ R- h# L
  467. }- F% h, i' P5 g( k* T7 Q1 d5 }

  468. 0 |" J& D3 O" S1 p9 E( y! V1 g
  469. /* 接收WiFi命令的回应 */4 _/ b1 P* Q' u
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)
    & {- h& x, g+ c2 B9 O9 _. J4 _
  471. {
    4 F7 W: p1 c( m3 j: Z" L. O
  472.         uint8_t retry_cnt = 0; // 重试次数
    * d2 ~1 ^" f* p7 m
  473.         uint8_t wait_status, resend;
    # Y" ?2 \; m  H+ g2 Z9 A" p  x: `
  474.         uint16_t size;
    3 s7 d+ w- T( d! K
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;
    ! H8 |1 f' q, x) G$ F; e
  476.         WiFi_SDIOFrameHeader temp;
    * C! Y! x. `% c$ r
  477.         
    2 o: k: ~$ t' K, t
  478.         // 等待数据准备好3 ]9 p& m7 s# _5 Z# ^. P- p
  479.         do& x' Q. G) e% g& w: r" y8 ]
  480.         {, h; F+ D2 @8 {# N- m( W
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);
    : x- ]! e3 |3 {# P
  482.                 4 T+ s( s+ {7 u- I1 F( m* p' D+ j
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息2 g$ r, w5 t/ s! |; a
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部. c; W8 s1 _9 _4 ~( Q/ C
  485.                 {. U# M/ m/ K$ ?/ y  @9 ?' g% E
  486.                         // 若读到的是一个数据帧, 不是命令回应5 J5 L7 b9 E1 h- d, E
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功' j( U. Q7 J* w- p8 H9 {
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);
      a( c" r6 s* N
  489.                         wifi_pending_size = temp.length;2 m9 X1 v* g( J4 O2 {
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算
    6 V' z% X0 F- U$ T5 |+ z; i9 f2 P5 A
  491.                         resend = 1;
    $ N( y5 B/ x  z8 ?" ^
  492.                 }
    8 ^. o/ T1 B/ E2 j" n, [& @  A
  493.                 else if (wait_status == 0)
      v5 ]3 {% z) x1 x
  494.                 {
    # \% u) h% s, l* a
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)
    ; O$ U0 \* P0 t# A$ A) S
  496.                         resend = 1;. N# L0 J( W) N
  497.                         retry_cnt++;1 c7 X! J6 `1 q! I. X# Y
  498.                         if (retry_cnt >= 5)* f$ M  d; D: B6 g6 o* J+ q& d1 O
  499.                         {
    0 F- @9 @* i3 ^8 O+ z3 X
  500.                                 printf("No response!\n");. k7 i4 K. Z/ {# X
  501.                                 return 0;. Y" h: E& G: w8 I# i
  502.                         }
    : N& o1 k1 m. G% s0 ^
  503.                 }% o! V! ?: ]" h! Z
  504.                 else
    9 H# D7 s: `3 @
  505.                         resend = 0;6 ]; T, j  {8 s" j. Y- ]
  506.                 ) t, ]7 J: H# h' j1 {; d6 s9 B
  507.                 if (resend)1 e- r7 O- V" n; q; z) z
  508.                 {# {9 B  R" `  S+ K! p  q
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)& z) r) h. A" e
  510.                         {
    , Y; a& N( G! L" o( g! K
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait
    ! ^9 c5 v1 S) X8 O9 ]$ `
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);3 [* P+ `, [7 ~0 m
  513.                                 WiFi_ResendCommand(buf);
    ! A: |* M5 X8 _% Q
  514.                         }' v8 M' i/ l7 ^0 V6 @1 S
  515.                         else
    , J' n  f0 U& P
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出+ a0 [8 \7 m5 F' Y$ f
  517.                 }
    & M( A  q  z3 v5 }  ~
  518.         } while (resend);; e+ d+ X4 e7 V0 c. O6 G
  519.         
    + L* i/ ?( n4 M4 U: Z3 D$ }1 R
  520.         size = WiFi_GetPacketLength();2 c( t! `- Y) Z/ w
  521.         if (size > bufsize)4 E% W. I0 ^0 O5 l8 ~
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
    ! e9 P" V7 P6 h" N# C7 a& y# H
  523.         return WiFi_ReadPort(buf, size, bufsize);
    3 W3 d+ Z" q* k! K/ @# V- Y
  524. }
    7 v' O; n3 l+ Z' B

  525. & X" \  p  ]. @" m" n4 C
  526. /* 扫描全部热点 (仅显示) */0 T0 q8 C- H& c4 ]% r" w5 _
  527. void WiFi_Scan(void)
    1 r" _  C6 c* W* a+ e
  528. {
    : s6 v: m( ~" ]; ?
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组
    ! b& G; r8 e/ Q1 K, p
  530.         // Stack_Size=0x00000c00
    4 T: J, g( a' b! I- j' I3 M& a
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
    + R3 T4 b7 p+ x
  532.         uint8_t i, j, n;
    0 `9 B$ L" O! {  q
  533.         uint8_t ssid[33], channel, wpa;
    3 h( R2 C/ j! C7 |7 }$ `% H- n
  534.         uint16_t ie_size;, c' L! ]; j6 z7 C
  535.         
    ) z/ S# S. G4 M
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
    , z! t/ g4 \) p" [$ a- Y/ Z
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));- R  Q* m' C& g9 _) f/ Y
  538.         
    0 n  S9 V% G9 U
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;0 q% L" D( o$ t9 B2 H
  540.         WiFi_BssDescSet *bss_desc_set;
    # ^4 Q/ @2 D; o' i! q& H
  541.         WiFi_VendorHeader *vendor;7 b, l5 w  U7 u0 c+ H' Y. O: d
  542.         IEEEType *ie_params;5 W2 Z. B" f# O  f
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;
    " `! Q- G8 E  `) ]
  544.         
    + T1 F8 ^3 I' H: e+ h
  545.         // 分4次扫描14个通道* N  p# t. f9 c" u; {8 T
  546.         for (i = 0; i < 4; i++)
    & K4 L% _+ K% w2 V; T3 _2 e  i
  547.         {% M: h' v( _' f1 P5 r
  548.                 cmd->bss_type = BSS_ANY;
    & `  _$ {; y+ n9 s
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));! C6 D8 n7 m& i
  550.                
    ' q' Z4 x6 w' {7 J# t3 D# d- q0 c
  551.                 // 通道的基本参数7 }! _3 K, B$ h- C7 M
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数
    ' i/ X/ j9 `# P( n
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;0 v& s2 L6 ^1 c6 q
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);
    ; I! c: @2 p+ y/ e
  555.                 for (j = 0; j < n; j++)
    , l1 K" [) k/ C) m, X0 M0 Y2 t
  556.                 {% L3 R' ]) ]% o1 e8 n  a
  557.                         chanlist->channels[j].band_config_type = 0;
    # p: ^0 _+ I: i4 G4 \* b1 H
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号2 \) r! G- b: K9 }6 ]5 u* d# z
  559.                         chanlist->channels[j].scan_type = 0;" W1 M. \- D7 W* o4 X9 b
  560.                         chanlist->channels[j].min_scan_time = 0;1 l. |0 w8 |2 B! v6 S1 C) r" N  v
  561.                         chanlist->channels[j].max_scan_time = 100;" W$ Z; l5 h) t0 i* ^) I4 J
  562.                 }0 w/ d3 ]- p- k9 |
  563.                
    . z6 Q+ ?7 [9 L- ^* t. v
  564.                 // 发送命令并接收数据
    0 I- U3 i; v8 D+ x0 D6 s# s
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
    % _# N" n/ T6 s; c% ]
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉
    " I# z3 {' ~' \: s' B* L
  567.                 $ ~* O1 N. p7 c* X5 V
  568.                 // 显示热点信息, num_of_set为热点数
    9 o( S- Y/ e3 ^9 Y# J* r
  569.                 if (resp->num_of_set > 0)
    % {3 E( u8 L4 Y! o. W7 l
  570.                 {: t* A8 D. R+ K# [# _
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));
    ; _- d0 ^" t6 K+ N
  572.                         for (j = 0; j < resp->num_of_set; j++): U! @% u) v9 A8 O
  573.                         {) P9 z4 u" B- Z/ C3 p
  574.                                 wpa = 0;4 B7 H# }2 R) w) s: ^( M
  575.                                 ie_params = &bss_desc_set->ie_parameters;
      U$ [) G: w) t' Q
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    : L2 F" E9 t, v" u6 ?; v( t+ @
  577.                                 while (ie_size > 0)3 }$ m+ j9 F" j6 j% U3 n
  578.                                 {
    % s' c  p$ O0 j! W6 |( Y; y. T0 `
  579.                                         switch (ie_params->type)
    ) O3 @. {1 I6 M5 V2 F' J
  580.                                         {
    : @. |( v  n( |4 U, R1 }
  581.                                         case MRVLIETYPES_SSIDPARAMSET:
    1 i/ l8 m& i& ]4 g
  582.                                                 // SSID名称
    * _* x- @/ p8 O  b/ r* x
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);
    ' H, H4 ]  c) G- p
  584.                                                 ssid[ie_params->length] = '\0';
    + K  [4 N; |- T9 i; ^% P
  585.                                                 break;( p4 ]2 ^  E  f( \$ V
  586.                                         case MRVLIETYPES_DSPARAMSET:5 a) s6 y0 o( [8 e$ `; X
  587.                                                 // 通道号
    0 u3 q+ F6 k7 e# j2 v! p
  588.                                                 channel = ie_params->data[0];' g1 G# }& r4 A  L2 c$ L
  589.                                                 break;
    : O9 @8 ~5 u) k" P4 p/ r
  590.                                         case MRVLIETYPES_RSNPARAMSET:, Q. p8 A* C2 W2 R# m+ Z2 n
  591.                                                 wpa = 2;  ^5 }% f! g- ]7 r# ~
  592.                                                 break;
    % Q7 M; ^" J& ?# I
  593.                                         case MRVLIETYPES_VENDORPARAMSET:
    ; m7 o) ^9 G, G2 K. g( W2 N
  594.                                                 if (wpa == 0)
    % D+ m5 K; v/ V4 Y/ _0 O0 y
  595.                                                 {) l! i0 h0 u5 p- p
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;
    6 J: ~3 o4 x* p. `
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    & A! x% \! y. g6 F
  598.                                                                 wpa = 1;
    5 G1 a& C, Y+ ]2 [; K
  599.                                                 }
    3 }) _9 o( t' ^! Y2 _3 [9 y7 w& k( P4 }
  600.                                                 break;
    . m  n' {5 L4 R& L0 Z+ v' A
  601.                                         }0 i0 k% y# C9 Y5 ~' ~& |. n
  602.                                         ie_size -= ie_params->length + 2;9 ^" _! Z5 u, a: u
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    5 k# [4 E, g8 h- J6 B" Z' D/ h7 P5 M
  604.                                 }
    2 D9 _) S: n& h) f6 n! j
  605.                                 if (ie_size != 0)
    1 T  u* V' l; T/ Q4 g% \8 v
  606.                                         printf("ie_parameters error!\n");# O, ^9 l3 X, i3 t. X
  607.                                 
    8 s$ }/ v  M( [  M1 a8 ?$ @( B
  608.                                 printf("SSID '%s', ", ssid); // 热点名称( ?1 G8 a' x/ h8 E! a+ H
  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地址
    ) h6 K  P2 H, U! }9 t* g+ F3 i( p
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
      ]3 ?& t5 L9 X9 j' D6 ?
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);/ s  x) @0 l$ L6 S; {! e
  612.                                 
    3 n" |+ }. r" t" n
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);* |- T" t, C1 J
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)$ o8 P5 Z6 x7 n3 a$ f0 \2 k9 v
  615.                                 {
    & J. I3 H3 E/ @) _; \
  616.                                         if (wpa == 1)
    / s6 {% s. b# q( P* Q2 Z
  617.                                                 printf("(WPA: ON, ");; p$ J6 F9 B2 x" |- e7 c) N9 n
  618.                                         else if (wpa == 2)
    % c  L; V$ Y0 E7 |" E* |0 A, [
  619.                                                 printf("(WPA2: ON, ");
    ) F; v0 Z% Q& h; j5 x( s
  620.                                         else
    + t9 T  L) m1 x) a1 ]" p3 I+ L
  621.                                                 printf("(WEP: ON, ");/ I5 w5 K% L% e" o; X
  622.                                 }
    & |* }3 A. q: T. v7 C7 H9 U
  623.                                 else
    ( K' C& B: U& ~9 t4 I
  624.                                         printf("(WEP: OFF, ");
    / b' O6 e7 f0 W3 S
  625.                                 6 K* g% a$ j! g% G/ b
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)+ {4 p: u( p8 v5 T+ q8 D& V
  627.                                         printf("mode: Ad-Hoc)\n");% _) f& |5 g" d& r. t$ A8 `$ t
  628.                                 else4 j! W8 q  S2 |! p
  629.                                         printf("mode: Infrastructure)\n");/ Y, x, z* E/ R* |4 {! ]
  630.                                 
    ' M2 O, E1 j$ [5 ?
  631.                                 // 转向下一个热点信息
    ' i& ?- x4 e- ]  M6 R
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);
    ! d7 m: e/ b: g/ n- h6 Q
  633.                         }( |2 X% }9 F6 [9 i# I
  634.                         & w2 \* F7 Q/ G, K- q- k4 K4 L6 {
  635.                         // resp->buf_size就是bss_desc_set的总大小6 C) s; j) ], ^9 t; I6 H7 d
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size1 \5 O1 b( q# o! h  Y
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
    8 m4 U+ i) v+ d* M- E5 C
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))
    # B: e% X5 T9 [' u8 A% p0 v- {
  639.                         {4 P3 e3 F, H% R, G
  640.                                 printf("Timestamps: ");
      r3 n. ?, r$ ?5 K+ P* S2 F
  641.                                 for (j = 0; j < resp->num_of_set; j++)2 L, B4 C. _) D5 a7 r0 Z; y
  642.                                         printf("%lld ", tft_table->tsf_table[j]);
    $ h* o/ h+ ]9 l7 _7 R' M
  643.                                 printf("\n");
      p0 K) o$ s* ~5 z: H
  644.                         }*/
    + J- Z" x: G) a9 W0 Z
  645.                         ! @4 P. W1 p* H) u/ `* O7 S
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table% D: ^) H. Q1 ?% F
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)
    $ D. [8 H0 L$ F+ O% z1 }& B* C8 d
  648.                         //        printf("data end!\n");
    # Z1 i$ I1 N7 S3 A: ^
  649.                 }+ k( {; b+ R! t# E+ S
  650.         }
    , J7 Y( B& a% r
  651. }  ^( M$ ?2 ]5 F. _# Z

  652. - y0 V; Y2 C, K2 w
  653. /* 扫描指定名称的热点 */
    9 v1 }2 S0 Q# S6 R$ B: {
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大' p1 W/ r( W8 e
  655. // info用来存放从buffer中提取出来的一些常用信息
    1 f6 F6 I& V* D  u
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize). W5 s. O2 v. L" E8 q
  657. {6 h' G; E% J% ^5 n
  658.         uint8_t i;/ l( W% e; p, ~: r6 r; y
  659.         uint16_t ie_size;- k% M5 _5 }9 F& w2 d9 e
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
    6 ^+ `. j1 W4 L% U' s
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;
    , r+ ~* f' m8 K& w
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);/ k6 N! ]5 P& C7 r% R0 _
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;1 n% x+ y, Z" W0 Z5 y
  664.         IEEEType *ie_params;0 {; F6 U' l+ b: `7 w1 s" v
  665.         WiFi_VendorHeader *vendor;2 l. o$ y$ `" Z6 }
  666.         $ w# T8 K) s$ M8 @
  667.         cmd->bss_type = BSS_ANY;& q9 [, s9 o+ S
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    9 f  b6 J+ @+ c! q0 ~/ r4 f
  669.         
    ) T7 J2 R, {' t4 u" S
  670.         // 添加ssid参数- k" l" H3 Y; \+ {8 O4 u6 G
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;3 c9 Q6 y, @* N3 a
  672.         info->ssid.header.length = strlen(ssid);
    + d. g/ H4 a* R+ H
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);! m2 ^" }# _4 y
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    / o% I+ Y$ r1 ]$ a" q8 M8 h
  675.         
      y$ Q0 G8 Z9 o- t% E5 B
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));: A3 F0 \% T+ y+ J  W+ T' f
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    * b$ j: t9 }* Z2 |
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    ; B  ~/ c4 J* p, {
  679.         for (i = 0; i < 14; i++)
    9 Y7 k# f6 U5 Y% y6 y8 T" V6 V
  680.         {. n) o/ g' ]% y& a7 v
  681.                 chan_list->channels[i].band_config_type = 0;0 B7 D! c- R$ g9 o
  682.                 chan_list->channels[i].chan_number = i + 1;
    % O# {* }0 ?% O" k
  683.                 chan_list->channels[i].scan_type = 0;, J8 F+ K! M5 f
  684.                 chan_list->channels[i].min_scan_time = 0;
    % K  [" p  K4 A, t9 k4 B
  685.                 chan_list->channels[i].max_scan_time = 100;
    # v9 E  x  W7 R7 i& _. Y
  686.         }
    " }4 o& P2 I# m, C+ j) E
  687.         
    " p2 t! w0 j) s" v7 [' m
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));
    + A$ H  ~/ p. I* T) s
  689.         wifi_timeout = 3000; // 延长超时时间
    & m! c9 K* _- t6 v. g
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    4 t- _' ?) f6 J
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;
    5 W/ _9 P7 o" X1 h- B0 ]4 N; V& m
  692.         " W  k! z8 Y& o5 y4 `
  693.         if (resp->num_of_set == 0)
    1 y3 p! g. J9 r6 s# V6 X
  694.                 return 0; // 失败; v' j! k2 w3 H6 E7 V
  695.         
    % e) R: `: C( S0 l7 T1 ^8 k
  696.         // bss_desc_set以扫描到的第一个信息项为准
    + t# v3 S# o, P+ J3 A* a
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));
    ! _! ~, V1 x8 `  G6 q
  698.         info->cap_info = bss_desc_set->cap_info;$ \5 G$ S3 I( v( r% b
  699.         info->bcn_period = bss_desc_set->bcn_interval;# Q4 X$ r0 W* u) p0 M9 s8 e
  700.         / g/ ~, {0 c7 t" Z$ u
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)# C. N% ~1 C6 F$ G/ k7 k  l
  702.         info->rates.header.type = 0;
    5 D7 _" V+ M$ t* U& r& a# c
  703.         info->rsn.header.type = 0;
    6 l; k' a2 V3 L; {% ^
  704.         info->wpa.header.type = 0;
      N+ w: r$ X4 G- ^8 W
  705.         info->wwm.header.type = 0;
    ; W4 R8 [& b- W7 _
  706.         info->wps.header.type = 0;! V0 \3 n1 N6 h( A" C$ K& k
  707.         
    ; Y. W& d+ g# x% _! o: [; B
  708.         ie_params = &bss_desc_set->ie_parameters;3 [! ]* d8 P, e+ N- A
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));+ i+ ]6 R* A+ N1 L0 E) V, s- y
  710.         while (ie_size > 0)
    ! m& J2 n' H& W. S: ^& O
  711.         {7 z7 X  C$ V* |5 C
  712.                 switch (ie_params->type)
    ; k5 \6 j/ G" ~5 I( W
  713.                 {' t! E/ ^# c4 z  A: u) C
  714.                 case MRVLIETYPES_RATESPARAMSET:
    , V& l  K$ S# P$ z$ W* W1 m
  715.                         // 速率, F% c. r+ F- l- s, f4 a  b/ x: A" {
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;
    " Z. \/ R9 _  N; x- X
  717.                         info->rates.header.length = ie_params->length;# d7 P) i% a. [4 H
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))$ R6 M( g! k* X3 j8 i
  719.                                 info->rates.header.length = sizeof(info->rates.rates);- Q; d2 b* [" R. H2 b5 b# {
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);
      B# r& Z( ^$ ?* R
  721.                         break;
    5 v; ?6 b3 @6 n! M3 G! d5 W% [7 Q
  722.                 case MRVLIETYPES_DSPARAMSET:3 D* U: g! L8 D3 T
  723.                         // 通道号
    - A( z- u6 _! H% M$ G, l( y, k6 ~
  724.                         info->channel = ie_params->data[0];8 C. g( j4 ?5 d# c) \( p
  725.                         break;
    2 j# j! H9 e% `$ _; a! W( S
  726.                 case MRVLIETYPES_RSNPARAMSET:! A! K4 f9 y$ v/ t, a; _. C" C
  727.                         // 通常只有一个RSN信息 (与WPA2相关)8 \3 b) f& W1 q% t
  728.                         // printf("RSN len=%d\n", ie_params->length);
    4 H2 H. S4 `; {* g. E
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
    : h8 [1 L" c' [. C
  730.                         info->rsn.header.length = ie_params->length;+ h5 [0 T# [9 `6 [
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))# p; A! b( Y& C. V; c
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);
    7 t+ D3 W# R9 w" _) f* P
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);8 @3 E2 @! |7 O2 h$ Q7 M: R
  734.                         break;. W$ P7 Q, s/ H7 j1 i( p& x
  735.                 case MRVLIETYPES_VENDORPARAMSET:) ^2 z$ `( ~' c. I& k8 U
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)3 o( b0 h( i0 j; b
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;
    : G  L/ I9 Z' n) z+ k% ]2 q
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)% P1 t" m, G7 E' G# y
  739.                         {
    ) N& J; x' Q; e: Q: y
  740.                                 switch (vendor->oui_type)
    + x6 ]0 V1 g, ]# i& ^; O
  741.                                 {& D, q* {) ?( q- i/ T
  742.                                 case 0x01:
    6 B1 F7 Q! X% O# b
  743.                                         // wpa_oui
    ; K/ K( N# P. x0 S$ e5 O
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;/ N! z: {7 v( x* [4 d9 [- W) G& e
  745.                                         info->wpa.header.length = ie_params->length;# |9 ~" N" M+ b: G
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))
    9 J9 A. k% e5 }7 q4 N% i' e
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);
    7 `% E/ G; ]8 H- K4 Z
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);
    . C. e: {+ k+ U+ U( h
  749.                                         break;
    ! J  q0 p, N0 f+ z
  750.                                 case 0x02:
    6 j& l. |. n7 G! b4 k3 V& x
  751.                                         // wmm_oui( q$ {; {$ M5 P, o! I
  752.                                         if (ie_params->length == 24) // 合法大小
    : E6 L: O6 l4 q& P) e! r
  753.                                         {
    ; ?. z/ V+ z, `" ~$ {3 g/ @% l  u* }
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;" C, E6 |6 P! y6 `* L' ]
  755.                                                 info->wwm.header.length = ie_params->length;
    1 d3 V# C2 r) \% c/ |) f6 f
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);2 f7 z; L$ U0 D! ^
  757.                                         }" V% ^0 s$ N" V8 Y7 K0 O3 h7 R0 j
  758.                                         break;
    0 ~8 y! B7 a/ _) ]5 S/ y- E
  759.                                 case 0x04:
    ' g% ?. c1 r$ S( k. U
  760.                                         // wps_oui0 U* H# S/ y0 m2 {  q4 A) {
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;  M2 _6 C! ~* p2 l9 k! h! f% T8 K
  762.                                         info->wps.header.length = ie_params->length;: W" Y6 a/ ]! d+ n* M) |' G. A
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))/ _1 ^! f& j, a3 N$ f3 A2 }% N+ j
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    / I# j( {6 d3 K1 K" ~* T
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);
    - M" Z0 n. m3 h+ _. d
  766.                                         break;
    0 B# [* f! Q/ B( X) @7 o+ Q
  767.                                 }
    & ~, X. j) f) J, B- V4 ]
  768.                         }0 }5 Y: n) o! R' A
  769.                         break;
    & q; g5 U4 h0 g( U# Y. x
  770.                 }. I. `3 S; ^) _: ]
  771.                 ie_size -= ie_params->length + 2;2 J/ D! I9 U/ o6 N# z
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);( E+ {7 W$ l  j3 T8 ?
  773.         }
    2 w. j7 S/ b4 t2 D
  774.         
    - g. b7 j6 X' Z# i& _1 K+ i
  775.         return 1; // 成功( y5 F9 [7 J' F8 h( q6 Z- [# U
  776. }
    & C9 T. ?1 k1 X

  777. 2 a! S0 v" j) K. |1 M4 F! y
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)9 l9 B3 a4 G8 k' b; V& g, l
  779. {
    & \, B) q8 i+ f2 L/ s
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
    . x. P1 D1 u+ ]7 @" ~; y
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;; H, a. `7 {: K7 ]1 Y: w
  782.         while (SDIO->STA & SDIO_STA_CMDACT);- r- E0 D5 N6 m7 q) A
  783. }
    9 V3 p. f! p  \

  784. ! I2 [7 Z# |! X$ y# c
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags), Z- K! L$ F" R( {) S( `" @
  786. {3 p/ \6 r# }  Q# R
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求3 \' ~5 X: l* |
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;
    ' [1 J6 @2 T" P6 V6 T: F- t! _
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;
    " b6 z3 C8 |, ^$ m1 i" M
  790. }4 c6 t4 a& s; A9 z0 O1 E
  791. + R7 x. T: z) @' j' P% M5 j0 B
  792. /* 发送WiFi命令 */! P+ e: h: K8 x1 L' T. H' ~
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size); h. b' f2 @% w/ |
  794. {8 N" i& E4 P+ Y% k% f, j
  795.         static uint16_t seq_num = 0;7 W5 x. b4 J. b
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;
    * e" A) O* q! _7 [1 T0 T
  797.         
    ; b5 b- S5 c1 o) H
  798.         if (size != 0)
    0 {+ w/ T0 b1 f; X
  799.         {
    6 t/ Y7 K  w7 y# \" T5 b0 d
  800.                 cmdhdr->frame_header.length = size;. T) l2 t" Q5 h, s, R
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;
    1 {; ^5 y# B6 O
  802.                 cmdhdr->cmd_code = com_code;4 U1 x* g* u/ j5 F6 ^9 u
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部/ R& A- K' k. b! k% M. l1 ^
  804.                 cmdhdr->seq_num = seq_num++;
    , J, W4 }5 G2 y+ k3 u& H
  805.                 cmdhdr->result = 0;7 \% V, O+ e/ t; h, L" J7 W5 X
  806.         }
    5 S% h# b6 G2 O: _) e
  807.         else" g/ z- X9 r2 @3 ~
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
    , o& N* X- w2 x7 B$ l7 p
  809.         
    * y: Q1 m: |2 k/ m# o" \9 }
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃
    5 o5 V# t8 e% s  m# u1 u3 k
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())
    / _# H- S2 {( [, p
  812.         {
    8 \4 O) K% g; I0 O3 ?7 n$ C
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");5 r! V- j, f: g! j0 E) B; \  M$ X
  814.                 WiFi_DropPacket();
    + c0 t# `9 k3 P$ b
  815.         }
    $ _' W3 T* U$ g! a3 a+ S4 s
  816.         6 Y9 B' W9 T% z/ l; |  Z8 K
  817.         WiFi_WritePort(data, size);
    1 d& J3 ]$ ^' k4 D$ M
  818. }( I8 D3 D) k( [2 ?) _

  819. ; n& i* X! @# ^( H0 B/ r2 B
  820. /* 发送数据帧 */$ w; H- M. C6 b/ R. W% }# A& q5 H: z
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)
    7 V2 B% {( s5 A: @5 _1 }" f, {$ l5 \
  822. {; q9 C) D9 t$ \6 \
  823.         uint8_t ret;
    * r6 k" y! D, v% k7 ^1 }! Z" ^+ B
  824.         
    * |, T9 A, K7 r% W
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
    2 w/ }; }7 v4 P5 `* P, e6 x0 l
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
      ]+ |# j. |9 t, }  ~& a
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;
    $ t% f. G5 G* U
  828.         9 G9 b( ?' u0 t7 `- z0 g$ v
  829.         packet->reserved1 = 0;
    9 A* @: M+ y, U# u3 X  t8 J0 R9 c  e
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings& ~* ?- T! |! ]
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader
    . ?' j6 {$ Z# R2 w0 c1 m2 P
  832.         packet->tx_packet_length = packet_len;7 ?* X, A2 d, N4 N
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);
    ! ?( j" ]2 G) x
  834.         packet->priority = 0;# s6 E" p: A2 C% s+ J
  835.         packet->flags = 0;# c. t) ~8 Y$ i4 x. u: W
  836.         packet->pkt_delay_2ms = 0;
    8 U2 g% ]4 V( Y% D, g5 S) P8 `
  837.         packet->reserved2 = 0;( P: x! i, _; ]+ K% Z9 K. f
  838.         - I4 \  F/ n5 M' _
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小
    8 Z9 x5 d! H3 M2 D
  840.         // 未读取之前不会收到新的数据帧& [- u5 U( D' X( W
  841.         if (WiFi_PacketArrived())" M; K- S9 s7 U. V# x
  842.                 wifi_pending_size = WiFi_GetPacketLength();
    ; L) o3 P$ X) Z# w: G
  843.         
    7 Q- k1 L5 O  Y# l, [5 D
  844.         ret = WiFi_WritePort(packet, packet->header.length);
    4 D3 W1 a4 q# m! |- Q3 l2 X1 z
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置11 a3 K( O1 j) x% j* R
  846.         return ret;  x7 B+ `  {! f7 w9 V, @- `  ]$ b
  847. }& a* q3 \6 V- M- I3 w
  848. 1 q, i+ q  s" ?  F# x' }/ ~
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */" d- J: @( Q* y
  850. void WiFi_SetBlockSize(uint8_t func)6 _3 O# `) M9 b
  851. {4 P& d# V/ T* f
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)* i4 Z% a6 s* k: P2 i& f# m
  853.         uint16_t size = WiFi_GetBlockSize();
    7 G  J6 S# b7 D7 G7 j) ]4 C+ T! `4 _
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);
    ; R6 R) E2 z$ R- ?
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);
    5 ^9 ~- o/ T4 A) \
  856. }
    3 y/ u+ h0 @. Z- c6 `( {! v

  857.   A7 S. F  V" n3 f
  858. /* 设置密钥 */
    ( Q3 U* ^, D2 ?  Q
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)# E/ F) I/ @6 j9 I1 F& w/ k9 e
  860. {
    7 v! x% [2 B7 K2 E/ m
  861.         MrvlIETypes_KeyParamSet_t key_param;
    9 b% J  {' m' O2 |! ^! i. H
  862.         if (len > sizeof(key_param.key))
    % U4 M5 f8 X6 ?% F; j- m; s0 |# B
  863.                 return CMD_STATUS_ERROR;" Y2 v6 O" ?/ _6 p$ d
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;+ m: `+ m* K2 h/ r/ J! n. t0 Z! m
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
    . U5 \* X: f1 p  C: e" N
  866.         key_param.key_type_id = type;, a0 O" }( u# l( C) }! J; n/ ^$ \4 [) }
  867.         key_param.key_info = info;- B" U; V, ^8 ]. Y+ J8 l
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
    * @; C9 M- ]3 ^: h' h- y9 e" }6 n. ]
  869.         if (len)
    - U- W3 n1 h! K8 J* Y
  870.                 memcpy(key_param.key, key, len);1 U% c5 q: U$ M1 _& l7 C! K' Y
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);. q+ |7 @5 {/ g6 R* E: ?3 |) q8 K
  872. }! h" a- n" E/ h) m0 D& d
  873. , j. E( {4 q) G' ~
  874. /* 显示WiFi模块信息 */: L' [! [+ @4 e2 Q* z, y1 J# W( J
  875. void WiFi_ShowCIS(uint8_t func)8 K3 }% _$ c7 ]
  876. {
    3 O: S0 _, b: ?3 `) j, e# T# x
  877.         uint8_t data[255];
    ' b5 z( o2 v% M2 ?" Y5 B( ~) Q! a0 F
  878.         uint8_t i, len;
    / _# C: m8 j& c) q7 s) M- H
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure8 L1 y0 w, s0 ~8 z, ]5 d, Z
  880.         uint32_t cis_ptr;; b  H. G/ x2 s" k
  881.         0 a9 K4 d2 T8 n5 o; r% @
  882.         // 获取CIS的地址- k) Q9 [" y' b5 S5 Q- q) G$ B
  883.         cis_ptr = (func << 8) | 0x9;
      c( B9 O8 r/ `* N2 z; Z  }: b
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    / G6 v: p5 V) q5 w% B" ?, u
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);
    5 C# k' V2 H- D
  886.         
    ( l1 ]" S( k6 z) Y# w
  887.         // 遍历CIS, 直到尾节点) c* c3 ?( h" h/ S) s4 u
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END); s( c2 F6 }" g5 d2 Q
  889.         {
    2 P3 c. M3 M2 B) t
  890.                 if (tpl_code == CISTPL_NULL)6 a9 j. i1 q# R: R; J
  891.                         continue;! T' d: @: S4 t4 h
  892.                
    " Z+ C0 U1 c" T
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小
    9 H( u& ]1 x, W0 W, h
  894.                 for (i = 0; i < tpl_link; i++)
    9 A  P* Y* C# b" i. D7 W
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    $ c6 j. n9 W, J8 o5 l( l1 P  w/ ^# f
  896.                
    7 J2 R9 g" M, `$ m, F+ t
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);  _( l7 |7 ?# c& e/ b) y9 {
  898.                 dump_data(data, tpl_link);
    6 K- L6 H! G# L8 e& }3 X+ X. i
  899.                 switch (tpl_code)
      Q  e3 L: C- |0 Y
  900.                 {
    , u6 j/ B1 ?( F: Q# t, A
  901.                 case CISTPL_VERS_1:
    - |- Y# n! d( r/ `; T4 G5 ~
  902.                         i = 2;
    / h% R7 w. L' G$ C" a
  903.                         while (data[i] != 0xff)8 f2 O. }* g! L* D& f2 U. L
  904.                         {4 D, Y+ X" x- ?. b; r+ L! d
  905.                                 len = strlen((char *)&data[i]);1 u! v! p9 x  l& e8 {
  906.                                 if (len != 0)
    4 z! |7 _0 u# s3 y
  907.                                         printf("%s\n", data + i);  j& E2 w* C  s* ?0 A+ M- b8 r
  908.                                 i += len + 1;8 J- \  c3 H: N% V
  909.                         }- h% V1 y  {- b* t
  910.                         break;/ ~( `. Y7 `; O. L" t* Y! q2 @
  911.                 case CISTPL_MANFID:
    $ V  j$ J$ N9 z8 `
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple
    . R* H: s3 l6 p: B8 T! h
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
    + h) V$ e4 c3 a# a+ Q& l/ @
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD) j$ L* n& v+ ]- k
  915.                         break;& [, N8 O% {+ I8 F1 \
  916.                 case CISTPL_FUNCID:
    , x: [2 Q$ w5 _* [" p
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
    2 j* [+ s4 d5 ~; z# Y7 @( {* E
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
    ; r! _! R3 l- l; j! b& m
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT
    ) V, Q5 c0 J) s- K( l
  920.                         break;
    . D, f3 Y4 z* Z9 v) n1 W
  921.                 case CISTPL_FUNCE:
    7 x& _$ B; d; x1 [# V. _
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple
    & l. `+ s; w0 I4 h" M" ~0 n# v: g0 k- d
  923.                         if (data[0] == 0)
    4 p& I2 A8 l: m( `
  924.                         {% j2 [& L- u9 J, ?  p/ S
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)
    " X' l* |* \" ~- N# q
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));4 T& k8 ^& ~: y5 k
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);- o0 h9 q, _1 I& f  v$ y" X
  928.                         }4 j  K0 G+ r5 a3 j; ~$ n
  929.                         else
    * t- D, ?5 @2 d" M$ ?2 [8 J
  930.                         {3 z: c$ ]1 b1 s* i6 M- J
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)% [$ F( _1 M* U' ~
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
    ! w! P  _/ _+ b
  933.                         }
    ; \$ @8 H- w0 t' W. M; U6 ^
  934.                 }' X, J' d) x6 Y$ \: c- q1 n7 k* X
  935.                 9 [0 r1 d. H; M- |
  936.                 cis_ptr += tpl_link;' y# b3 V9 \$ A! `* i6 K  o  W
  937.                 if (tpl_link == 0xff)+ `% y$ F! N( X1 L, r
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点! D, N. M9 [! `9 S
  939.         }+ B2 g' y4 R* Q' l: i
  940. }
    % i2 B8 l2 A9 S8 @
  941. ) |5 h7 s6 t1 G/ l  o: D
  942. /* 显示所有密钥 */
    & `" u7 s# U( \& o
  943. void WiFi_ShowKeyMaterials(void)
    % x2 M# [3 ~9 ]1 b
  944. {
    & }( m* F! k6 M9 v. p* S
  945.         uint8_t buffer[256];2 E4 |3 f& }6 H/ E1 g' U7 b
  946.         uint16_t size;0 m$ P0 T7 T% y% l) b! r
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;1 R2 n) E# s8 ~! n# T  A5 m5 ]3 F
  948.         6 m0 `8 o5 l3 O* {
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);7 x5 s% g# A& q  H  S5 P
  950.         while (size)8 V! u% M; x% ?! u9 {6 A
  951.         {
    9 U8 |, E, W1 ?5 O- L  q* D
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);5 o/ _5 `2 X7 z
  953.                 dump_data(key->key, key->key_len);4 L1 i* ^( g8 d' z( x9 q& X
  954.                 size -= MRVLIE_STRUCTLEN(*key);) a  X& Q- U# V4 f
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));; E/ D/ ]: H& \$ T7 m, k2 z
  956.         }6 X& b/ \# X; `& I# x4 E0 j
  957.         if (size == 0)
    ' t  Q- |0 k* Z- C( m
  958.                 printf("data end!\n");9 r3 A( r: r1 g4 v+ d
  959. }$ G( g# h) o  U( |7 z- m; S

  960. : r; e4 ]+ `, e9 L5 v
  961. /* 创建一个Ad-Hoc型的WiFi热点 */5 f5 b. _& @4 {
  962. uint8_t WiFi_StartADHOC(const char *ssid)
    ' R& o$ d( X7 r, Q0 ^
  963. {
    - U4 N: U, o( P1 R' I4 t, Y
  964.         WiFi_CmdRequest_ADHOCStart cmd;" b7 i1 i& C9 G) V1 o; r
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零5 D# ?' N% Y( s, T
  966.         . N7 ^! C5 X$ H& a
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
    & `% `. t* y* H/ V3 R: \  G5 l
  968.         cmd.bss_type = BSS_INDEPENDENT;
    - b2 F$ p: f' K( r+ h4 a7 G
  969.         cmd.bcn_period = 100;
    9 X/ _! r2 Q' J
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;
    9 v+ b5 ]! A& \& P3 p& [
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);. _! @! T; ~- W" I: J0 t
  972.         cmd.ibss_param_set.atim_window = 0;- z- Z# r, Z5 d( d$ E9 u; L
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;7 ]7 k7 a, v0 Z& a
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);
    " l. l/ ?  A# `$ V
  975.         cmd.ds_param_set.channel = 1;  g# Y( @. q2 ~" v( l  \
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;- S- Z1 J) d. |3 _
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;  V: Y* W2 v% s3 ^3 H, i9 g9 U
  978.         
    ; |, f: Y" s1 [
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
    4 Q- i: G% X3 N
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));/ ~4 Q8 y9 D/ R+ c2 c
  981.         return cmd.header.result;
    , w* u5 K: Y5 V7 n7 C  V* d+ X
  982. }" a" U# q1 w+ g; @& j& m

  983. . {; Y4 Z1 `2 x& \) ?& [/ o( B
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */
    2 l0 \  G3 m' l8 }. s8 Y
  985. uint8_t WiFi_Wait(uint8_t status)
    . `' X# B- Z  L  J! i" C
  986. {
    $ a+ a% i/ h9 T# P% U2 y
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    4 I' }. @" P0 w2 f( F( x; S' |/ C
  988.         WiFi_PrepareTimer(wifi_timeout);8 _4 j1 r6 Z) m* k6 b1 A7 x0 m. B
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)$ a4 w" ~( b) \
  990.         {
    9 U! h+ v- f* O4 c6 x
  991.                 if (TIM6->SR & TIM_SR_UIF)
    - \( V3 u$ W! t2 h6 c  V
  992.                 {
    3 H3 C4 Y0 M9 N: K6 j2 |5 B
  993.                         // 若超时时间已到4 v  y! s" s& v) m
  994.                         TIM6->SR &= ~TIM_SR_UIF;- s3 J. ^! ~5 j* e/ C
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);/ W/ r. c% f) K* [/ ?" M
  996.                         return 0;5 n' d# ?& x) D
  997.                 }
    , Y6 G3 ^, ?& m0 g9 G1 H  _2 U
  998.         }! n" i) T8 ~6 @) o+ z, a
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器/ a& {' s( x( _8 s# K
  1000.         return 1;- D+ {. l  I& [: k. r2 u
  1001. }' \# q* e" a+ a5 B
  1002. # F: W- r3 `8 n3 j9 w# u3 ^
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */
    - Q1 w  `& k5 ]! r
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)/ s* P* N  m+ u
  1005. {) l$ U4 U- s- j4 q! U; C7 @
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);
    " H0 J6 W% e: B& k" o
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)
    + \. R$ R. _( ^7 Y0 q+ a
  1008.         {
    : C) `) `: V& X
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    : D4 ^, P$ L3 h
  1010.                 return SDIO->RESP1 & 0xff;
    ! _7 u' C, p" w( x
  1011.         }
    3 t  c4 A; V- T$ r8 \' ~2 u
  1012.         else5 w  a3 T8 P: L& y% ]- L: p
  1013.         {. M/ u- Z" {# x( ]+ u& {& i
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);
    . x( `  P, H: [" q8 B. M7 g* N
  1015.                 return 0;9 [  G. [6 }  j8 i
  1016.         }1 H# ?( D; W. r2 J  }# N: t! {
  1017. }
    * W% w- O" ?, i% [

  1018. 6 n9 V5 B# s; h
  1019. /* 写数据 */$ Z; n/ u. u: l. @+ O
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    $ s/ k. k" Z* K8 I2 {) J% \
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    . ?9 _# w+ O/ |* r" z  l& R
  1022. {/ w5 r5 ]$ S6 P4 ]( W
  1023.         uint32_t len, temp;
    0 E/ M4 Q5 I- H9 e/ t# o
  1024.         if (flags & CMD53_BLOCKMODE)
    . {/ k. P7 Q  n" y( Y6 z# \
  1025.         {
    : p7 a! l  A# f  e$ ]4 S
  1026.                 len = count * WiFi_GetBlockSize();: z5 a3 R* s) E) t( b8 U7 A! a
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;( }4 d6 D0 Q) C: _- C6 h! @
  1028.         }
    # A" T/ B3 i( F* w* T  j, L
  1029.         else
    $ K, K4 ^4 R! v
  1030.         {$ d% k: f4 Y: k6 ~) J3 T% |; L
  1031.                 len = count;
    , K8 U2 d; `4 e. R
  1032.                 if (len % 4 != 0)! ^' K& A6 t" v5 u
  1033.                 {  T, \1 e( h* M3 ^0 U- H7 v+ U& e: k
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    & t0 h6 v  @- \, J9 }$ u: [. h3 N
  1035.                         count = len;  O, I" X( J$ }  R' J0 y( A
  1036.                 }2 c3 F; ?+ u+ b/ u- a4 h& a! j
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    % \; Z3 e6 s5 Q% X6 _* W
  1038.         }
    " G8 F) O, o* X2 ^5 B
  1039.         SDIO->DLEN = len;% x" U1 Q; Z+ {
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块4 \# m0 t9 {5 A) z: }9 S* p; ~, L
  1041.         
    ' f% _  ?: r" I( ?
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);
    # @1 d& \* p: A7 ?2 L
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);5 i' _' m0 g$ }# I% e) ?
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0). ]' c- y' T) w4 F, S  s/ S' q! E
  1045.         {, I0 O! [+ X+ q* B# W) V( q/ z
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");0 t+ k: r% v! d* X. F
  1047.                 return;
    / u* V9 A5 s7 ?+ L( _, I
  1048.         }8 n: B- j+ c( o" f8 {
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;/ x  ?$ }3 g& h4 {
  1050.         
    1 b6 {* |: x% k- D& F
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据4 [7 Z% y. A" a. v& ]4 k' Q
  1052.         while (len)
    , \2 a4 n9 R( W# E5 v8 q
  1053.         {
    - R9 T; z( E$ ^
  1054.                 len -= 4;
    % S8 T2 R0 z4 |! |( F! {) C- [( T
  1055.                 if (bufsize >= 4)/ H4 z& G5 p2 x( Q
  1056.                 {% ^) L. G. }0 S2 k+ u
  1057.                         SDIO->FIFO = *(uint32_t *)data;0 l) A4 [6 B6 |
  1058.                         data += 4;, s& i/ h, g) `3 B, C8 I
  1059.                         bufsize -= 4;1 f% R* w/ R* R
  1060.                 }* N/ z; O8 {' b' I2 ?( e! Q  C, y
  1061.                 else if (bufsize > 0): m+ ~/ I- `; l9 A3 J, \
  1062.                 {1 L/ \, L' y! r
  1063.                         // 发送缓冲区最后1~3字节
    " P0 g$ y$ V: [; y8 l- w
  1064.                         temp = 0; // 不足的位用0填充" F/ }: B( t3 X$ d
  1065.                         memcpy(&temp, data, bufsize);
    , T) ^5 g% v/ M' G6 C' r
  1066.                         SDIO->FIFO = temp;
    6 A/ ?# G3 ~1 R2 N0 c. N
  1067.                         bufsize = 0;
    $ p- _  F, }3 a& F: Z
  1068.                 }
    # m% h' Q3 @$ u
  1069.                 else
    8 L& a6 \1 a, d# O
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0$ x# Y- Q$ p! ]" M+ p1 J
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待
    3 Q) A/ t$ s( `2 G4 V7 h
  1072.         }9 m6 H& ~) R- c7 E4 i& I5 l
  1073.         
    7 i) E! I, N! N& m6 `5 T
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕) E* L- F4 E8 Y( {
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误, j5 ~9 j* A! y1 a6 n4 T+ N' T! {
  1076.         " L' |4 t+ y6 P) t6 ^% `! r7 z# V
  1077.         // 清除相关标志位
    & ^& O1 A% ?- f, d) I
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;
    . b: J- y7 f' }* W1 F
  1079.         if (flags & CMD53_BLOCKMODE). H3 w2 H) ?1 g0 C3 {( K9 S. |
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
    / @) ]1 v2 S2 @0 K$ Q8 o" ?$ G
  1081. }
    % O' O9 j% e+ E- }$ D
  1082. , [; i: \# ]% D: x# e# a
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)
    & w2 r2 {, V; W9 N& u) t( M2 Y
  1084. {
    1 V$ r- @2 p. |9 ]: x
  1085.         uint16_t block_num, block_size;4 J) H" K3 e9 J6 P  S
  1086.         block_size = WiFi_GetBlockSize();
    . i7 t! C% [$ l. t! F7 F+ N: Q
  1087.         / d5 y+ C9 G$ X8 P+ H) ?6 z- w; s
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    . R4 J- f3 J! f: ~0 E& C' u
  1089.         if (size >= 512 || size % block_size == 0)
    , J. G9 D) i( O1 y
  1090.         {
    & i9 f* L8 s- y1 ]& q8 H
  1091.                 // 采用Block模式传输
    - L: u2 l1 k  Y$ k- K* ?+ J7 @$ H
  1092.                 block_num = size / block_size;* Z1 K0 {/ A# _
  1093.                 if (size % block_size != 0)( G3 L& @+ c- Q/ j6 `
  1094.                         block_num++;
    1 h5 e- E) o" Z2 J  `
  1095.                
    $ B$ C9 F, |0 U2 b8 U( Q
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);# N# A  r7 h9 l; d* J( K
  1097.         }! s5 E( z& D/ S; b
  1098.         else: `4 n- c' C8 _, H
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);
    ! @4 r. ~- x7 r" h2 \
  1100.         return SDIO->STA == 0;
    7 ]/ O+ y! A- J& }3 M
  1101. }$ Q9 @0 L- R0 t8 r9 W' v
复制代码

" T  w! j) \" Q) i" K  W+ B! |3 b6 J1 F0 F: V) c( j. c. E
在工程的所在文件夹创建一个lwip文件夹。: P. ]! `6 V  X- ?+ [6 j  L
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
1 n4 {* @& I/ Q% K3 M  }/ R  e" @; {4 J  P, Q& y+ {% I  o, U3 J
core/
. p/ }0 g* ~& v+ I9 t( g% v; {0 Ecore/ipv44 d1 c4 M  Q, p7 ^7 n  V
include/lwip* ]0 b* I8 A& C. s& O
include/netif% a: r( x; {% [) X/ s- f
netif/ethernet.c
% K* x; Y, T$ }netif/ethernetif.c
* o  @( H% v$ ?1 c" f6 N
4 C7 P7 m4 g; J* d- v: N解压后,将里面的c文件都添加到工程的lwip分组下。
$ V# L/ m7 `' t具体添加的文件请看下图:: ^% f9 u) M8 t/ k5 _8 j' L4 E
; d# A2 ~7 k" d3 n% I# }

2 i* h; @/ o- T0 N' b3 [接下来,创建lwip/include/arch/cc.h文件,内容如下:( q" k9 V3 D7 W/ @
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:
$ E( p1 z9 _& W  H9 K2 d6 y: X, ^
  1.     #define NO_SYS 1 // 无操作系统  
    / O- \# x  M, E* ?. r' x, C
  2.       
    + F3 [! J6 M1 W2 Y
  3.     #define LWIP_NETCONN 0  
    6 E  C, d" P/ G. G
  4.     #define LWIP_SOCKET 0  
    % F" \- I8 x* ~6 G5 m
  5.     #define LWIP_STATS 0  4 e  B7 p* a9 V5 g
  6.       
    + t# |  p3 b! D" n. r6 W: \
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  9 m; a4 w7 u% m5 Q  A, p
  8.       0 @* v6 S9 a6 l  ]1 ^9 T0 L1 K2 V
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:
9 S# x* f5 y5 T6 ~7 J" t
  1. /**
    ) C% [0 J0 j; ^% ?+ g) [+ G3 J+ W
  2. * @file
    1 O3 Y1 S1 n& Q4 J. K$ d1 y% S
  3. * Ethernet Interface Skeleton
    ) E; M% U7 L( M% q% f. O  O& U! a
  4. *
    ) |! a  R+ @0 a1 i& m2 l/ }
  5. */
    , Z; S9 p7 x/ f3 ]% R
  6. 4 [7 M% P1 U! _( ~# N6 \# e
  7. /*5 R3 H% s% m% b) s; O
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
    5 Z# d. w0 @3 y. \" [3 U
  9. * All rights reserved.' c+ k8 Q2 f$ A% s% G! G& b" s5 c
  10. *
    : x4 j; c6 A, L
  11. * Redistribution and use in source and binary forms, with or without modification,% |# ^9 ~/ q  k, K( W" X8 j/ ~
  12. * are permitted provided that the following conditions are met:! t! d, N- i/ W
  13. *0 a: K) q/ z* p: Y! ?) r
  14. * 1. Redistributions of source code must retain the above copyright notice,- l7 T% E  H/ Q' }
  15. *    this list of conditions and the following disclaimer.  Y- u% a; [5 X- K# v, _! O
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,1 G4 }$ q/ U# g' |# L/ s) ?4 @
  17. *    this list of conditions and the following disclaimer in the documentation7 O# R9 C5 B; c8 e9 z$ i
  18. *    and/or other materials provided with the distribution.
    1 z+ Z  x- F  T& b
  19. * 3. The name of the author may not be used to endorse or promote products, h( u+ S$ \' ]
  20. *    derived from this software without specific prior written permission.
    " k' ?( i! i: `) |$ m# f0 F
  21. *+ J! W0 c2 i7 H
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED5 b  v' {6 H/ }' d  x
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF/ b* Y; p3 w+ r
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    * c+ z2 O4 Z4 Q* K
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    4 G+ y+ \) G$ Y; Q5 m9 |
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    / C5 Q6 z8 A5 W: e# L7 Y/ ?2 c
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    + j! D, {. H; g" M1 U- R* {+ |+ y4 a
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN7 Q9 ?- I% m6 C, t2 K
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    ; T6 w( v- o9 {
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY7 H# d0 N3 U( A4 d
  31. * OF SUCH DAMAGE.
    ; G: P. B4 Z; s$ h3 a
  32. *
    / x- x* t" t0 h
  33. * This file is part of the lwIP TCP/IP stack.) }3 I) y* ]" C8 g# M$ x$ C2 j% B
  34. *
    ! K( l% w4 ^3 s: D+ i4 T" `" q
  35. * Author: Adam Dunkels <adam@sics.se>
    , {- u# I, h: K. i
  36. *
    9 M+ k+ @9 Z0 w3 @0 z1 a3 Z& o
  37. */7 C4 L. y- G' ?! j2 N

  38. 2 ]  F5 V1 s; e- S/ C  \% H2 ~
  39. /*3 y/ a7 f" y, G' G0 C" W
  40. * This file is a skeleton for developing Ethernet network interface. T0 m, r1 h4 }& i2 h' q& X
  41. * drivers for lwIP. Add code to the low_level functions and do a' t3 m5 T2 r5 t
  42. * search-and-replace for the word "ethernetif" to replace it with# g; |1 |1 W4 j! n
  43. * something that better describes your network interface.
    3 h, h+ i+ K" D
  44. */
    8 A0 z" m& d. C) b# l$ _/ c
  45.   i0 L/ x) ]( f% J  Z# V' L
  46. #include "lwip/opt.h"
    $ J% n* d* @$ J. t' o6 F. a1 c

  47.   U. s" ~( h. [" {) m
  48. #if 1 // 允许编译器编译该文件
    9 m$ p& {7 J5 t' R
  49. ! @. M1 h/ w- d$ |8 L- C9 p2 Q
  50. #include "lwip/def.h". b! r$ m! `# }1 a+ }$ O
  51. #include "lwip/mem.h"
    ! J8 F" O. e" C7 U  _
  52. #include "lwip/pbuf.h": T4 h. @1 t0 i" N( X
  53. #include "lwip/stats.h": r7 K7 h& v' `; i2 p
  54. #include "lwip/snmp.h"2 \8 C* q9 w$ C; M( B' Z% \
  55. #include "lwip/ethip6.h"
    ' ^# f2 N! {9 O' f  W8 w
  56. #include "lwip/etharp.h": r5 B- O" C/ s& h1 n( N) c: {/ d& w
  57. #include "netif/ppp/pppoe.h"# T: M( H5 o! o/ }, K$ V

  58. ' i! d' e7 L% ]2 T. L5 V
  59. /* Define those to better describe your network interface. */. Q- g# P3 H& U1 x, d$ P4 M
  60. #define IFNAME0 'e'9 Z' a  j: \! m) E
  61. #define IFNAME1 'n'
      j2 h: ?& Y4 J. @6 ~) ?: J
  62.   L6 A( W1 n# g
  63. #include <string.h> // memcpy函数所在的头文件+ L  P( k( X1 y' k* m) E
  64. #include "WiFi.h" // WiFi模块驱动程序头文件( z* T7 B1 `1 B4 N
  65. , n# r' {3 W" }
  66. void dump_data(uint8_t *data, uint16_t len);
    0 c4 W8 R, ]) D4 y3 f) R2 W

  67. & F/ Q1 B1 H/ x* L
  68. /**- p7 ]# j9 f1 {! o$ V. T
  69. * Helper struct to hold private data used to operate your ethernet interface.
    8 C% t8 m6 ~( H! m  m
  70. * Keeping the ethernet address of the MAC in this struct is not necessary: i( J) @( V6 L8 Q: d: k
  71. * as it is already kept in the struct netif.
    5 B7 y/ u. x) J8 J: N0 i" g, I
  72. * But this is only an example, anyway...' E0 D, Z8 x. q2 [) g6 O6 z: K/ O/ Y% C
  73. */
    * T9 R* f! }0 B8 n! a  J
  74. struct ethernetif {4 X) b& E$ C' a$ _. Q! U( I5 f& S
  75.   struct eth_addr *ethaddr;4 Q9 q* Q- A6 f; ]
  76.   /* Add whatever per-interface state that is needed here. */
    9 ~' b# V; ?# S' e
  77. };. F. I$ S" y" w1 a; _9 M0 S
  78. ! \+ X) B7 L7 L) I8 \1 C- |
  79. /* Forward declarations. */
    0 U7 K& X' ?* n% w/ ?/ T
  80. // 这里必须去掉static
    3 f/ L! P% n/ M4 a
  81. /*static */void  ethernetif_input(struct netif *netif);
    ! c9 w2 q/ h! @$ @' @2 F

  82. * s3 o2 f+ d/ k& g7 @% n
  83. /**( S/ ~' q3 L/ d$ w1 F* e
  84. * In this function, the hardware should be initialized.2 X9 O" ~% E6 X- a! R2 K
  85. * Called from ethernetif_init().
    + Q8 w  ^- j' Q. F+ b4 n
  86. *: j3 d, Z! J- ~9 t, _9 d# d/ u
  87. * @param netif the already initialized lwip network interface structure
    & h5 W1 r; @# Q/ G1 i4 \% y" [
  88. *        for this ethernetif8 g, O$ Q, C! e' J7 K
  89. */
    - H; I$ u- c8 N( m5 s8 g
  90. static void
    6 H; D2 F4 ]$ M% D6 [
  91. low_level_init(struct netif *netif)# c0 N7 H+ Y9 a# H
  92. {' ]8 m# B7 C6 \, ^  S! S% Q
  93.   struct ethernetif *ethernetif = netif->state;
    7 H- H' }. K1 K

  94. - L) t! @6 V/ e& D
  95.   /* set MAC hardware address length */" R5 V$ w+ x* `* {: N5 T# X! [
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;
    ( O+ r+ X7 M; W1 U" n) O: z

  97. / p% e9 ?: y' E
  98.   /* set MAC hardware address */
    / A/ l3 t1 N% }$ r7 P
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址8 P' Y3 V3 C. a5 v6 }$ }% N2 a* n2 r
  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]);9 y' }5 S* H+ z/ I4 h/ `

  101. / }% m" X+ f, b( T
  102.   /* maximum transfer unit */
    5 W8 S5 w$ W$ F6 n# x
  103.   netif->mtu = 1500;
    8 Q( {6 A5 T: n4 w) k- c, V% c( x

  104. 5 i2 K. O  ]  ]( ?" @0 G) [! }+ x: _
  105.   /* device capabilities */# a- R5 k2 Z7 v: u7 }' x: b
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */' z* |5 Y0 s5 Q7 M( V6 Q
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;8 K! F6 E4 |! [' H2 X
  108. 2 Q7 z% z$ j' T) N! U7 V. p/ O; F
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD
    % a# {/ d1 P" {: V( M5 A
  110.   /*
    $ j( ~% o" x7 `: b
  111.    * For hardware/netifs that implement MAC filtering.# T& `5 h& k$ i- a( k6 F7 N
  112.    * All-nodes link-local is handled by default, so we must let the hardware know
    ! s8 {8 c9 E/ J8 ]: f3 c# c
  113.    * to allow multicast packets in.
    7 [) Z" k# H- z8 C, z& J
  114.    * Should set mld_mac_filter previously. */8 e; }7 j: ?& ?& O- V) {, t6 g8 v8 L
  115.   if (netif->mld_mac_filter != NULL) {
    4 T) H! W7 v) A1 Y5 N# a! K1 ?
  116.     ip6_addr_t ip6_allnodes_ll;
    % _- s  x8 P" Y( ~" \
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);& h: k, S+ m$ s6 @: g) Y9 n! g" L
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);, |6 g, }( H8 d$ C2 d; F- v0 |
  119.   }
    1 v; [9 _* j" K& O) e
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
    & @/ q9 A/ V* m
  121. : I( G2 T7 p" ?; d( p, z' k
  122.   /* Do whatever else is needed to initialize interface. */
    8 ]$ y1 U% r2 F1 {  `
  123. }
    8 h& u' A& O& q, q, Q3 y* \  A

  124. ; {7 C0 t  K, R3 ~! t$ Z  Z
  125. /**: I: Z+ a; _7 ^$ h  g) q' v
  126. * This function should do the actual transmission of the packet. The packet is
    6 M% E: D/ \1 W4 y
  127. * contained in the pbuf that is passed to the function. This pbuf6 O& W) t9 r) i! P1 C0 h/ @
  128. * might be chained.6 K. h+ {& j1 H
  129. *' |! X6 ^# U5 F) D( |- L- M
  130. * @param netif the lwip network interface structure for this ethernetif
    ; W% l7 a0 Q& F
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
    $ I. p, |+ D9 M. b" o
  132. * @return ERR_OK if the packet could be sent) W+ g7 H9 M$ x. h+ }+ T
  133. *         an err_t value if the packet couldn't be sent2 n2 g% t; [% `# H3 L
  134. *
    / M9 O0 n, O! a  w
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to+ J5 S  x0 i& t, t4 @
  136. *       strange results. You might consider waiting for space in the DMA queue2 Y% |/ a. C3 H# _+ J. a
  137. *       to become available since the stack doesn't retry to send a packet
    : L' y" Q# m9 T; G# z  C
  138. *       dropped because of memory failure (except for the TCP timers).' d$ z3 h& h3 N1 T
  139. */: @! e- a' L+ b, I# E5 S/ ?

  140. : Q! V' n# U2 o7 I$ j  P
  141. static err_t  @$ b; \/ i8 c1 {+ K- i
  142. low_level_output(struct netif *netif, struct pbuf *p)& A1 G' N, a$ _/ W: }9 E4 R! C
  143. {
    * f% |8 }+ |+ P9 o: p0 w
  144.   struct ethernetif *ethernetif = netif->state;
    * w$ h& K) Y: F0 J. x; G
  145.   struct pbuf *q;- H; o4 F0 Q( h: e% j
  146.         " Z: H3 B. D# d! _6 C: R6 `
  147.   // 添加的变量
      E6 L& r8 \* X5 R2 k/ q
  148.   uint8_t buffer[1792];# `; h& h3 a3 ~
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;( X+ C) S5 m( D" x
  150.   uint8_t *bufptr = packet->payload;/ Y. F. i- l" ?8 @6 v: K

  151. / n# ]2 F, D& A, h8 ?1 q
  152.   //initiate transfer();
    , m' m: Y& N6 U( g3 F

  153. 6 w3 T( m* P, {: l/ z
  154. #if ETH_PAD_SIZE% Q0 w) z% m" O" i5 p6 A
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    & d( v7 U9 l" y) J
  156. #endif9 t! M5 e( l1 ]

  157. ; M4 t: D$ [9 G% M# n2 Z5 V3 N
  158.   for (q = p; q != NULL; q = q->next) {
    3 q5 b% f& V# ]1 b/ }
  159.     /* Send the data from the pbuf to the interface, one pbuf at a5 ~; a) M3 r, Y  R! ?% g
  160.        time. The size of the data in each pbuf is kept in the ->len
    % d+ ^8 M2 U. x- B- W6 Y6 K
  161.        variable. */
    4 }" F! Y' `) M' P7 _6 P+ T
  162.     //send data from(q->payload, q->len);
    $ C# w% W  G1 x9 b. v
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容
    : [( E( A% Z, f* G0 c
  164.         bufptr += q->len; // 指针前移9 k2 [3 y3 a  c1 k* F
  165.   }3 v8 x! e! O; [- D2 Z
  166. 1 [$ G- z8 q' W8 |- h/ Q" y
  167.   //signal that packet should be sent();' C8 P- e0 x. w' l# G
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包
    9 w1 K7 E+ e6 w" J; }8 A& [
  169.   
    6 w5 O5 s# o) k; J
  170.   // 打印数据包内容
    , C8 Q7 V9 |8 G. B7 l5 K9 `
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);# ^& q8 ?7 C& [3 q" `# i3 C' W
  172.   dump_data(packet->payload, packet->tx_packet_length);
    " o; T8 P. p; r; R/ V0 j

  173. & B& |1 J# U, y6 i5 I3 E, ?
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);5 h% [& }  W/ ~- B3 p
  175.   if (((u8_t*)p->payload)[0] & 1) {. T) X$ G- x3 Z0 V0 o/ _8 c$ T
  176.     /* broadcast or multicast packet*/. t+ ?5 Q# k( }; c4 \
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
    6 I1 O* b; A2 _2 |; c
  178.   } else {1 J/ l* n% ]9 C% n$ M+ D2 l2 F) h
  179.     /* unicast packet */; U0 u1 o  X2 i& _$ i4 I
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);# O7 E$ ?$ |; \# T. r( n" P
  181.   }; D( q$ i* y% j& T& J6 w; H% a$ {# _9 f
  182.   /* increase ifoutdiscards or ifouterrors on error */; y4 m, m+ W$ Q$ e

  183. % T3 R; F* T! Z6 Q+ B8 m
  184. #if ETH_PAD_SIZE
    . T" V3 u7 C2 `/ r3 e' l- `
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
    1 M$ b* O3 |# _& q( `
  186. #endif
    9 z! T# U4 e2 y4 h0 w+ T" E
  187. ; z, R' J( I! s/ g2 _4 e- p
  188.   LINK_STATS_INC(link.xmit);- C9 a6 s7 O$ A( Z
  189. / [# m3 |1 C. j% e
  190.   return ERR_OK;, n# z7 b: s4 ?) w. B* J
  191. }# |4 b1 u6 b  t. M

  192. $ l& ], D7 T9 ^9 D& L2 i: E$ O
  193. /**. a$ y) L/ o2 j* i& `3 M
  194. * Should allocate a pbuf and transfer the bytes of the incoming  R+ w( x7 {; ]+ R
  195. * packet from the interface into the pbuf.. _  z# y8 [* e1 @4 j/ B
  196. *- [$ Q; O. H5 `. Z/ J
  197. * @param netif the lwip network interface structure for this ethernetif
    ; G6 J9 Y; ^) x# u& r# @0 c% b
  198. * @return a pbuf filled with the received packet (including MAC header)
    ; H, Q' g5 b* l
  199. *         NULL on memory error. {4 N) j7 W3 _+ b4 @
  200. */
    & L$ i( E( p- }: s
  201. static struct pbuf *
    8 F- l* @$ x0 F! L" X8 t5 r
  202. low_level_input(struct netif *netif)' T7 B3 X* ~) h( ]) g
  203. {5 z5 `( ^5 z9 J5 C8 ^
  204.   struct ethernetif *ethernetif = netif->state;/ P1 K( ]+ C8 w, l4 v. `
  205.   struct pbuf *p, *q;4 |' `% w! C0 v& S2 Z' i& D0 e
  206.   u16_t len;
    % G" F4 K( n7 h5 C) g
  207.         # ?: [! E! [# d7 f3 ]% f1 S/ W
  208.   // 添加的变量. p6 U: a; h. c* ?  M
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完
    6 ^% \' Z4 k5 h7 E! g0 n
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;
    2 e1 q! V  ^9 g+ q0 f$ C2 n' A. S
  211.   uint8_t *bufptr = packet->payload;
    9 p( n2 Y0 n8 t' A+ S4 x

  212. " Y: k: N/ L9 T7 i. a
  213.   /* Obtain the size of the packet and put it into the "len"
    5 t# ^4 ?4 ~/ i' X
  214.      variable. */6 A7 s3 ]# k+ x8 w; q9 S' ~% Q
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小6 z7 U  n0 z. C3 G4 T
  216.   if (len == 0)
    7 p5 o, t5 O. Z/ h) V" `: M3 k: T
  217.   {
    3 h/ Q9 W! J# A# U  Y$ _
  218.           // 若读取失败, 则不分配pbuf, 退出本函数: S3 ^1 b) y+ o9 [! ^9 E
  219.           p = NULL;5 ~4 H! f' K) h- C: E8 H
  220.           goto after_alloc;! ^- B) e+ \( q6 Y8 M" e
  221.   }# S1 s5 Z0 d- [; b; u
  222.   len = packet->rx_packet_length; // 获取数据包的大小6 Y5 X; ^- W; R6 i+ M' P
  223.         
    3 z, K) p; {$ _: \6 {! \( F4 `9 X" o
  224.   // 打印数据包内容* W& ?! o1 h& T) `$ z
  225.   printf("[Recv] size=%d\n", len);
    " c4 c& i8 _. G5 J+ C$ M9 U
  226.   dump_data(packet->payload, len);
    $ M: t0 u" i! I, x( X/ _( Z; j8 w

  227. % k: _4 e7 c' ?: U; H
  228. #if ETH_PAD_SIZE
    . T# ]% D; A6 \  h
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */6 U! E) Z1 V  N& @1 C0 Z& [
  230. #endif
    3 h7 f9 d4 U' `* j6 d3 F* _

  231. . U1 [7 F, o3 \. B# Q: b
  232.   /* We allocate a pbuf chain of pbufs from the pool. */
    6 {0 x( g) B0 V/ v% ~
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
    + Y3 V; O5 o2 g3 B
  234.   / r; k' l9 \$ q6 s7 E
  235. after_alloc: // 添加此标记
    " L4 h7 ?# o0 M* \  w

  236. ; j4 W- D9 V& B* b+ S
  237.   if (p != NULL) {
    & R) p0 k: u' I  g& N3 |) m' c  S. z

  238. 7 }. E- g, d7 O/ k
  239. #if ETH_PAD_SIZE' n" O4 \$ Y( e* Q# g
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    % H7 F1 Y' |, \1 A- [" r
  241. #endif
    & S5 }& M- M; ?* R5 f( J" `

  242. * t! d+ u" _- M% C+ \* ~- n
  243.     /* We iterate over the pbuf chain until we have read the entire
    & F/ \2 v- S( i/ i- S+ e
  244.      * packet into the pbuf. */
    6 @% U, L% w6 ^/ z
  245.     for (q = p; q != NULL; q = q->next) {; P6 B- L% ]; d+ q8 `
  246.       /* Read enough bytes to fill this pbuf in the chain. The4 ]2 q* l% O* U/ O( z
  247.        * available data in the pbuf is given by the q->len
    9 p. C& z$ Z- J
  248.        * variable.
    # ~4 x  X" Y( _/ L9 z' B
  249.        * This does not necessarily have to be a memcpy, you can also preallocate: S) g" Q' H' g# j
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the' p7 Z) i' Q7 x7 J# m7 D: ?
  251.        * actually received size. In this case, ensure the tot_len member of the
    4 N3 I* c; q* X; ^: n
  252.        * pbuf is the sum of the chained pbuf len members.& V) {+ |7 X8 S
  253.        */) ?$ r5 X+ F$ A6 T4 D$ t% |" F) i
  254.       //read data into(q->payload, q->len);
    . X' R7 p/ _1 U; _: r/ K/ o
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容
    % i& L! K% B( |# t# U+ ?6 f
  256.                 bufptr += q->len; // 指针前移
    ' H7 w4 _* T4 g7 V: ]
  257.     }
    / b/ J% S+ j: h; p" y; g
  258.     //acknowledge that packet has been read(); // 无需确认
    & u6 T- o/ O% v$ Z7 y8 U
  259. / n* O& f) Z: j5 v
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);  g( j9 ]' V( F( c9 p
  261.     if (((u8_t*)p->payload)[0] & 1) {1 }- U* P7 S- j7 z/ @
  262.       /* broadcast or multicast packet*/
    / F2 ?9 Q0 _; e- V6 e
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);: ]% m% X; |: V! \- O2 D2 C
  264.     } else {7 Y: v: s: ~0 _8 y, C3 ~
  265.       /* unicast packet*/
    : P7 i, ~6 M2 O0 H" q
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
    + K/ K# m* o. P4 r, `$ j
  267.     }1 k/ H$ T) q$ p# t
  268. #if ETH_PAD_SIZE( }; p& q# i" W3 M) S- X
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */$ d* B# \- Z& U5 \
  270. #endif4 R/ D; l7 x. V$ [) V7 e
  271. " Y9 K: z$ s- p6 w& f+ x) D
  272.     LINK_STATS_INC(link.recv);1 n: L- t, g$ S# J5 ]" F
  273.   } else {. B9 A  P6 p( d& D" I2 ^9 D
  274.     //drop packet(); // 注释掉此行# q- e9 T. h; `/ O
  275.     LINK_STATS_INC(link.memerr);
    ; @" E0 c* v2 E) @
  276.     LINK_STATS_INC(link.drop);
    * ?- T  ?- T1 Y) d
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);
    2 R( R; i6 a2 |' p5 N. j
  278.   }9 t) T% d) {( v, y) w" e

  279. 1 O. ^, _8 B; f! n: L3 W8 k9 M1 O
  280.   return p;6 W; c8 k6 ]6 U6 W
  281. }
    . A% Y1 c! m# {) z% P
  282. . N! L$ x! w8 A9 d$ U
  283. /**
    + b: o/ W- {1 u' u6 r) {; R
  284. * This function should be called when a packet is ready to be read. [# t8 S  r, v% \4 t8 g! J+ T
  285. * from the interface. It uses the function low_level_input() that) ~9 R1 v+ t) G! A/ Q  J
  286. * should handle the actual reception of bytes from the network
    ) x$ G+ U* V; Y
  287. * interface. Then the type of the received packet is determined and* f3 Y1 ]& {" a) |9 ?- t1 |; k
  288. * the appropriate input function is called.
    / {. @% T& b. G7 n; M
  289. *
    ) p8 K" C( B) p# U
  290. * @param netif the lwip network interface structure for this ethernetif+ |+ e( d7 k8 Z
  291. */* ^1 y0 E+ R% b$ w6 l
  292. // 必须去掉static; L" k0 Z+ A0 q* Y
  293. /*static */void
    1 P0 d3 p- {) G% c# c
  294. ethernetif_input(struct netif *netif): P& P: R0 |# v8 Z, b  D$ V. k
  295. {/ E! l# L( P$ P8 t
  296.   struct ethernetif *ethernetif;
      w2 f; I, m7 K# j4 z
  297.   struct eth_hdr *ethhdr;0 f. Q& B6 R- P, U! ~
  298.   struct pbuf *p;; N$ ^$ Y7 [$ o0 L+ o

  299. , k" h% y6 l$ e  s
  300.   ethernetif = netif->state;
    3 ~+ H/ C2 L8 U1 Z7 h; m; y: l7 A$ {7 ]+ Q
  301. 8 H( J; u! D) R' j, w
  302.   /* move received packet into a new pbuf */
    1 @3 s5 m9 N8 @0 ^
  303.   p = low_level_input(netif);3 s- N& t# \* W3 Q
  304.   /* if no packet could be read, silently ignore this */# V7 F/ j( g% \
  305.   if (p != NULL) {
    & Y) N$ n! K5 K; S6 m. G7 N" Y
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */8 ?2 b4 O4 H* H+ h' a6 P$ O1 X1 I4 V' d
  307.     if (netif->input(p, netif) != ERR_OK) {
    ( N: ~0 f- k( `/ }( F; T( K
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    % r) \3 u# r, f! @8 d
  309.       pbuf_free(p);
    3 x" J; j" G) A
  310.       p = NULL;& {' Q! f$ i& O4 O. q% s# |! {
  311.     }
    3 |) p, M6 P/ S2 {9 a
  312.   }
    4 U; j3 o: L; U. \% [  R
  313. }/ o- t1 I+ Q; t/ E
  314. 4 I, ?& X/ ?1 w
  315. /**
    5 g8 Q! A8 w2 Z6 e3 a8 a, s) b
  316. * Should be called at the beginning of the program to set up the
      S$ C" A, x8 R: s
  317. * network interface. It calls the function low_level_init() to do the- m- k' @- Q* K- U9 E5 }6 ]
  318. * actual setup of the hardware.
    % z9 s# d2 i9 Z# ~0 R
  319. *" h. N- Q$ t! E: b- X$ O* x: y+ q$ Y; H
  320. * This function should be passed as a parameter to netif_add().- h3 P4 R+ \5 B0 p8 L( N
  321. *
    5 {6 y# u0 O$ |( O7 H
  322. * @param netif the lwip network interface structure for this ethernetif2 [0 }$ Q3 h6 N+ D3 O5 y
  323. * @return ERR_OK if the loopif is initialized& X% N5 K* p9 ^8 g. ~
  324. *         ERR_MEM if private data couldn't be allocated
    4 c* W* C! n; i% m
  325. *         any other err_t on error
    ( o4 C6 d; X: w
  326. */  j! z3 _2 ]! X6 h
  327. err_t
    8 E" l$ Y: e; a$ n* O
  328. ethernetif_init(struct netif *netif)  H8 n3 C  d  z1 i5 x# C
  329. {
    " i' Y: n: f) n5 `
  330.   struct ethernetif *ethernetif;
    ( D0 A* ]5 M# c" i6 L! Y: W2 z

  331. 8 J2 L6 b* E- U2 Z+ {) v* M
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));
    ; }' i2 Z+ i% a3 Q
  333. & C* o6 y) l. ?, \% p
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));7 H- W7 C# o/ F3 w& K# r$ Y
  335.   if (ethernetif == NULL) {7 m: ?4 _' V( k; `0 G/ W' V& f
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    1 T. J+ s, q$ _
  337.     return ERR_MEM;! c# ?* f* ?+ m/ _2 X) E
  338.   }
    7 P* [$ I  W" M  X
  339. : a) l- x$ t. q  z1 N1 U
  340. #if LWIP_NETIF_HOSTNAME0 {: l0 ?% Y3 H2 a
  341.   /* Initialize interface hostname */
    ) `3 z# o+ s+ j
  342.   netif->hostname = "lwip";  |& r) o# f+ c: Z" q0 c) ]- @
  343. #endif /* LWIP_NETIF_HOSTNAME */& V$ ?0 f( k" x8 K7 t+ L
  344.   O+ C+ G: x0 g( S
  345.   /*
    5 {3 Z0 L: n/ S5 {
  346.    * Initialize the snmp variables and counters inside the struct netif.4 ~" E" Y& g' a8 O: p# o! T
  347.    * The last argument should be replaced with your link speed, in units6 {; i' F1 Z" e( D  c: V& s& M
  348.    * of bits per second.
    3 }% n2 d7 g! D9 Y' X) [1 H3 u
  349.    */
    3 J: ^/ J5 m$ y
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);9 p9 T7 t% e' D( H8 U
  351. 3 l. \! O  P; O8 r7 [( U
  352.   netif->state = ethernetif;
    4 T* p' E% ?$ M
  353.   netif->name[0] = IFNAME0;
    2 p$ `( F* t( j$ x$ n- R' g. k
  354.   netif->name[1] = IFNAME1;9 D4 w0 j$ e  @+ b! D; G- ~  H
  355.   /* We directly use etharp_output() here to save a function call.
    & K% @7 A/ N4 V8 S* h) e
  356.    * You can instead declare your own function an call etharp_output(); R- ]3 S% c8 Y2 ~. q
  357.    * from it if you have to do some checks before sending (e.g. if link2 L. A+ p0 E* |% s
  358.    * is available...) */
      F# J0 K: Y3 M/ i) J. V) N  H
  359.   netif->output = etharp_output;
    6 ?, C- B6 n+ J/ I
  360. #if LWIP_IPV6. A4 J; F; x" c5 \+ ]; S% M* ?
  361.   netif->output_ip6 = ethip6_output;
    4 I1 D0 S# T( M% P
  362. #endif /* LWIP_IPV6 */3 H5 z+ m5 G2 Q3 L# [5 l: l" q
  363.   netif->linkoutput = low_level_output;) X; u9 V6 h  [) F) i9 ]" I* ]

  364. - I+ W6 ~7 d" q6 U: k1 J
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
    9 D8 `# I7 D- O. \# Y! i
  366. 9 t, \2 B9 P( f/ W4 |& D
  367.   /* initialize the hardware */0 o. x1 G, B' M2 \! ~  S
  368.   low_level_init(netif);1 J- E! R+ a- @; e. F

  369. . Z' s( p2 ~  e! S: P& h0 r
  370.   return ERR_OK;
    # C: \. o( Q; }9 P; V  G, n5 T
  371. }
    + T1 o! Q4 d( C- g

  372.   I+ m. z' O0 v  d, I- P7 C; J& x( s
  373. #endif /* 0 */
    % W+ z4 G1 U! G! Y+ M
复制代码

0 Q% x- J. Z% Q/ a1 y" _4 ^在项目属性中,设置Include Paths为:.;.\lwip\include1 _* u! v* N1 _4 i% x* x- p
其中点表示工程根目录。% @' @5 X5 d, x9 \% v

: R( a6 A" L. A+ g% ?& N" ~5 ^& Z9 l另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
* q1 o8 I0 j' E, q, {8 h- k
8 N; H0 n# V! p0 M, m! q3 \( r编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
! L9 h% u+ V6 m电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。
! M3 h; z0 t6 ]! G配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。
9 ?. u; f4 l. x# Z4 X. s

评分

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

查看全部评分

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

举报

5个回答
lijain 回答时间:2017-9-11 09:32:08
楼主你好,我最近也在做esp8266数据传输。做了一个stm32控制的tcp server可以传递数据,但是传递时间有点慢。可以和你讨论一下吗?我的qq是1632401541
MrJiu 回答时间:2017-7-21 11:10:56
个人给个建议,大量代码最好用文件的形式...然后将一些注意的地方,和自己整个开发过程的经验!!!!
zero99 回答时间:2017-7-24 15:03:19
版主说的是,不过还是谢谢楼主分享
wofei1314 回答时间:2017-9-11 11:09:22
Mark..... z  S9 h) E# K' m% Z
6 O1 b) Y6 K3 S( d
多谢分享
zlk1214 回答时间:2025-4-8 13:55:18
while (WiFi_GetPacketLength() == 0xfedc);
写错了,应该是
while (WiFi_GetPacketLength() != 0xfedc);
才对。
L
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版