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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE
! v* N2 I0 g; }PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。
% e  G, ~; g  Q" _4 F; l0 U注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。8 o$ t! B- \* l; [2 W' E
该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。/ g+ p! V% g9 Q7 x
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
. T' X$ P& z$ x6 P$ J0 |" `6 P1 t8 t$ R( Z
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!
' P0 a/ R3 Y7 s2 r
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】% ?: h6 a( C. a( F" w- L8 S. Z
  1. #include <stdio.h>+ g" l. G2 i/ v4 h" e
  2. #include <stm32f10x.h>
    / z8 M! l+ v3 d0 i! Q
  3. #include <string.h>: l$ `! i! `* c+ F4 s  z/ E
  4. #include "lwip/init.h" // lwip_init函数所在的头文件  p1 e1 @1 e4 f" U  g
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件
    & O" R2 s0 |8 q, C
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件$ c) }! E1 k* ~1 N
  7. #include "WiFi.h"& D! B8 y2 K( K6 R4 s

  8. ' e( t3 Y$ J* U' t; c5 w3 P# Z
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明
    3 `) q8 Z# H' w) O8 i) B; N
  10. err_t ethernetif_init(struct netif *netif);  h1 O" ]- U7 L0 f8 v8 p! }* d( Y
  11. void ethernetif_input(struct netif *netif);
    ) i6 E* |$ w. x/ f, p, [; b
  12. $ K: G) K1 y0 q& J! G5 o
  13. // httptest.c中的函数- ^9 I) L% X, l7 s4 M
  14. void init_http(void);
    ( S/ x( _6 d8 W+ ?* y
  15. & Z* l( O1 f. ~8 ^% @0 ^
  16. // 延时n毫秒3 O' E# g  o( s' z& \
  17. void delay(uint16_t n)
    / O' W# r3 S8 h" M$ w" P" ]+ I
  18. {; v7 h; b( s# G
  19.     WiFi_PrepareTimer(n);+ K. X, N+ h- m/ M+ T; v
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕9 M/ r8 Q! I; C# ?/ S3 O
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志- g& _. y/ l1 |) c( m- C8 t3 [
  22. }$ n- p$ `6 ~; n
  23. : _; {3 Y7 I' C0 o
  24. void dump_data(uint8_t *data, uint16_t len)
    , i# [: E7 J# K( B5 V
  25. {; Z1 P" \2 v$ L1 Y( h8 X6 G
  26.     while (len--)( C# W/ z! `7 a
  27.         printf("%02X", *data++);
    ; M. F3 @7 ?  @) s
  28.     printf("\n");
    ( w) X7 }3 @7 U7 B( k- m5 h
  29. }
    & p; y) U) C* \# Q3 V

  30. ; F6 I9 [5 w: g4 \; D! v
  31. int fputc(int ch, FILE *fp)7 E- F. x( \7 |+ B* s6 A6 b
  32. {
    + u; g9 t5 l! l" M2 y: Q* K
  33.     if (fp == stdout), I! K" J2 `. n6 w
  34.     {7 @- |- b& O: V* T
  35.         if (ch == '\n')3 [3 t* s3 Z" b# ~5 m4 ^& `
  36.         {/ n7 m7 J3 k  A+ y* M0 @5 m1 ]% x7 `
  37.             while ((USART1->SR & USART_SR_TXE) == 0);
    ! t8 I6 N' r/ t: n2 F# }
  38.             USART1->DR = '\r';' w* {8 j% F0 R8 z8 a
  39.         }
    5 [; |, O, j/ z0 Z& g
  40.         while ((USART1->SR & USART_SR_TXE) == 0);; p1 l% r+ b7 I! c9 u
  41.         USART1->DR = ch;1 {- z, L9 \2 }7 {; ]
  42.     }2 Z$ u8 `% y9 O/ U4 F( A
  43.     return ch;8 I( p3 k/ v5 |4 ]. {0 x  g' n+ c, X
  44. }: T0 V1 b( \9 R4 e" A! @6 M. C

  45. 3 f0 J' M  j3 B8 E6 j
  46. // RTC时间转化为毫秒数
    % _1 B+ |0 Z7 C( y3 I% E
  47. uint32_t sys_now(void)
    % @8 q4 N8 p. o% I9 ^0 M( n3 S
  48. {/ @  o- z1 N" ?# w; x
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
      r+ O8 u) o' v# z
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒3 P5 O/ m: l9 {0 k& b  \& D; \
  51.     return tmp;  w* S  \- k: P5 c( i
  52. }
    : q+ q+ [% Z8 M# x9 V

  53. # i3 E$ H( K6 l* z" Z2 G
  54. int main(void)/ J& b; {' {/ y% p
  55. {
    & V  \3 M2 {8 a3 K
  56.     struct ip4_addr ipaddr, netmask, gw;) v& v: [! }; z) q) p
  57.     struct netif wifi_88w8686;; C7 W$ s. a+ l. \/ I' }2 j5 W* x
  58.     uint32_t last_check = 0;
    5 S5 w! \( V* E( {) q
  59.     5 R: j5 a& r+ o: e/ l
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;/ U' \+ r! U! U' I+ O' I% ]3 z. y
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;
    + l4 c( U/ B, D/ D
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;
    0 h5 X- W8 o2 c  J) j
  63.     ! m7 M! V4 `- c
  64.     GPIOA->CRH = 0x000004b0;; V5 ]  G& T+ a' ^
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块+ m$ Q$ u" J3 p
  66.     GPIOC->CRH = 0x000bbbbb;8 n1 ^0 i2 p' m, Y0 [& W9 k
  67.     GPIOD->CRL = 0x00000b00;  T. o8 T! i8 f- u2 Q( K$ _5 H
  68.     ; P2 {% f& e+ Y% ^
  69.     USART1->BRR = 0x271; // 波特率: 115200
    0 j2 X8 x3 W. `8 j& w1 w
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    3 z5 F+ z+ R' U
  71.     # R2 r, @, z( c5 D% _) Y4 n% z0 o
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器
    : l3 ?* `9 {" _( y& P
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)/ c& W6 {& H- W9 R* r
  74.     {5 H& g2 {5 {# C7 N4 F5 @3 E' O  D
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI5 A3 x0 {. G9 Z0 m
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
    2 r- j& f0 v# w% {4 T7 Z1 P# ~
  77.         //printf("LSI Ready!\n");
    - B$ T; Q$ D; j( W* S
  78.     }
    + V7 w) a/ Y& l0 r# I* p
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)/ q/ }7 r- t& x; A0 f% Y; T
  80.     {% y* |$ P2 d4 Q( k" }, p% T) [
  81.         // 若RTC还没有打开, 则初始化RTC
    * A3 |, X: ^/ w) d8 l& V# o
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时# `: s7 p* K) G( ^" Q3 I2 t# g
  83.         
    ( H- n7 P6 F% z: Q5 P- G
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式8 q5 }2 h5 L( M. E: Y2 |' {: T7 H" H1 g
  85.         RTC->PRLH = 0;7 b; e9 `% P: v3 L* b1 T7 I: @+ \
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)& A5 ^& ]/ Q3 t* u1 g* w+ q6 i
  87.         //RTC->CNTH = 0;. u3 T" i8 i& @% L6 b, N
  88.         //RTC->CNTL = 50; // 初始时间" g5 |+ n" d3 {6 g
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置  z& m: d/ s; e) f0 H0 @
  90.         ; {3 K! ?7 l* J0 O
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
    : I* [6 C" Y/ P$ w; j
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效
    / P3 O4 f/ M# I) d5 W- o9 ^6 l
  93.         // RTC从此处开始走时
    6 u2 G# D+ n- B" z4 G% r/ i
  94.     }
    8 Y" e7 s- b# @6 r
  95.    
    % j# o" s4 q0 V3 T/ X
  96.     WiFi_Init();" H& c( m" G. C( Z
  97.     WiFi_Scan();
    ! ^' T2 B' q% w& E+ O8 s% d7 N
  98.     7 o0 s3 b$ x) c0 ~- F! S" M3 S+ H
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点% e/ T3 _1 k, F7 y; f
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    & i. [: n  F2 k8 {! O8 a
  101.     " n& w( A, J, X, a# K
  102.     lwip_init();" W  @; n# g% s3 |) L( R) k( ?6 _2 n
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址5 |/ i  w: w, w8 K7 Q8 B
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码$ l, Z! R4 c+ P/ c6 n* {# u6 x
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
    " V, {4 _. {! r/ p4 h% k  x+ O
  106.    
    # d% A8 _" f+ q5 E% U. z/ V
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    ) ~2 C( Z% T! q
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡
    5 ?( w  V% j$ z6 Z
  109.     netif_set_up(&wifi_88w8686);5 v' `/ V1 Z- t4 l" j+ u7 s
  110.    
    1 O0 b; f- j3 n# S" O
  111.     init_http();
    ! m: `! @, ~& D$ e% B- G
  112.    
    5 W3 j, [7 x, _, z5 T
  113.     while (1)9 A# h, w4 K- A9 a
  114.     {
    7 U* t2 S" K1 d7 K
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())
    $ v" `4 l  {( y: z: F+ Y6 E$ ~
  116.             ethernetif_input(&wifi_88w8686);
    " {( B4 m" o# s& D4 _5 R0 i! V+ ~
  117.         
    ' V" y! d) N1 G# @
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)9 h4 \! Q2 d1 ^- N% a4 M" L9 e
  119.         if (sys_now() - last_check > 200): o+ {+ P# o1 W. V
  120.         {$ g% o# G; X' X* j: x4 _9 T4 r% g
  121.             last_check = sys_now();
    . a8 J$ A1 A7 V. ?% r
  122.             //printf("Time: %d\n", last_check);1 t9 T. U2 _$ L0 s1 [' \0 j
  123.             sys_check_timeouts();2 a0 t) ?, J4 q
  124.         }- ~' r- C6 l( @( n  {; |- Q: S
  125.     }
    1 @: k, C, h  T: A! o* N0 Q, G& Z; b
  126. }
复制代码
【httptest.c】
/ W& U7 d; H0 q/ j9 W& k) B& P
  1. #include <string.h>! b' \: M- D) I/ L6 u9 {
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件1 d; w5 M- _1 u- I8 `
  3. * j, W. ~  F$ L& S  M
  4. #define STR_AND_SIZE(str) (str), strlen(str)
    5 c, K, x: e5 A) M, g3 V* N

  5. 4 n# I: \6 I0 ]& @4 M+ n& f
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)1 f/ J5 b* F$ X/ _/ {
  7. {
    3 y, h& H( T3 ?& ?8 F+ T( W
  8.         char len[10]; // 存放HTML内容的长度
    7 @7 m, ]0 P1 j0 Q
  9.         char str[200]; // 存放HTML内容+ o; a, B5 W  C
  10.         # q; Q) q0 d& d" a7 y6 t/ u$ c
  11.         char name[100];
    3 S( _) k1 ?( R0 E( ?
  12.         char *pstr;
    2 j' y# G! U* G+ l) {& f; Q
  13.         uint8_t i = 0;& G% L5 `/ x: a  E( r, \# y
  14.         if (p != NULL)
    & O) Z& N7 X7 o' R+ \5 I5 a
  15.         {( C) J& a6 J+ z- _# p3 h
  16.                 // 提取页面名称4 Z1 |/ r8 R0 z. Y5 c
  17.                 pstr = (char *)p->payload;" M" V$ \5 w' M# z/ r2 A; _
  18.                 while (*pstr++ != ' ');
    ! O& u2 x: G- B3 ]. x
  19.                 while (*pstr != ' ')
      @: R; {- V- N
  20.                         name[i++] = *pstr++;
    9 Y' z. ]+ U4 B! m/ T
  21.                 name[i] = '\0'; // 不要忘了结束name字符串
    6 H: i" k! L% _9 o; R7 m$ n2 I; K
  22.                 tcp_recved(tpcb, p->tot_len);% H5 e& J2 c) l( ]' d- v; Q
  23.                
    8 W, Y) C& }9 {/ f* E
  24.                 // 生成HTML内容, D4 `: `8 ~( d9 b8 s
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
    + R7 d+ \' }! j4 R% r0 h. c
  26.                 ' c% X( ]2 Z6 g" M# t% }
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度/ E1 P4 S; m* h6 V8 F
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);& X* ]2 t+ n+ y) G. k0 B
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);' D- ~+ N- q$ ^9 j5 R" K
  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);4 Z0 y& F: L6 L9 h- Q8 ^3 E( {) Q/ _
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容) Y5 T; y, j# B0 L
  32.                 pbuf_free(p);) C! s5 h, Y7 J  M
  33.         }
    2 t0 k: t* A* V( |5 F
  34.         return ERR_OK;
    , x3 ]$ P4 Y$ E; v
  35. }- d: A; ^4 d7 P) p) C6 w' z; Z+ R
  36. + A2 O: M( l) S6 _5 e) u
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    3 Y7 {  u$ b+ L2 Z
  38. {, L8 D6 F  N4 Z* T/ w
  39.         tcp_recv(newpcb, http_recv);5 o& R, H3 {9 P4 T- }' _
  40.         return ERR_OK;
    , i' P/ f, ~1 r5 n
  41. }
    , ^6 J, X$ b. F

  42. 2 C8 Z6 m8 Z' b$ ?
  43. void init_http(void)
    # Z8 {- D5 F2 }
  44. {
    * {5 O* I, u( g6 J
  45.         struct tcp_pcb *tpcb = tcp_new();
      w& i& _/ Q$ L8 `! o
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);: p& S7 |  p' F3 d' p  g, Z1 Z
  47.         tpcb = tcp_listen(tpcb);
    ; x8 {+ Y8 o4 X
  48.         tcp_accept(tpcb, http_accept);$ H" I5 W# |" s4 L0 k( J- [
  49. }
复制代码
【WiFi.h】2 l  ?/ f( L* r0 [
  1. #define _BV(n) (1u << (n))  }$ C( R5 s! N: {1 K: F# @9 N7 Q
  2. - E9 |  f5 N7 Q; o0 B" c
  3. #define CMD52_WRITE _BV(31)5 T* c! W: V' u8 e  Q/ s6 S- b! S
  4. #define CMD52_READAFTERWRITE _BV(27)
    3 P! N* k# G9 H. y2 z/ u* r6 H

  5. ' @% G- I' x) b2 ^
  6. #define CMD53_WRITE _BV(31)& e5 {+ [: T, d' O
  7. #define CMD53_BLOCKMODE _BV(27)
    ) D# _* ^3 x; G3 N
  8. #define CMD53_INCREMENTING _BV(26)  P1 a' J. M7 I$ o

  9.   x2 O# l/ i! F" f) C
  10. // 16.5 SDIO Card Metaformat
    % `5 k; U8 `4 z
  11. #define CISTPL_NULL 0x00 // Null tuple
    ' C1 H4 e" C# ?7 I
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information% s# |8 o: m" z- r
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    ' \" r; V- w3 C* ?, E* m2 h4 {
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple' B  s; f$ Z$ X& [8 J
  15. #define CISTPL_FUNCE 0x22 // Function Extensions/ G+ |0 D' z$ W  }# D# d: [
  16. #define CISTPL_END 0xff // The End-of-chain Tuple
    ! J5 i! t; U4 s; q' `$ T: _

  17. % R% d- H3 l8 t+ }2 H7 @& H
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)( V3 y( ?/ S, u

  19. ' M. ~: |; Y5 `  Y+ ^
  20. #define WIFI_SQREADBASEADDR0 0x10
    + r, K1 y8 O* @
  21. #define WIFI_SQREADBASEADDR1 0x119 Z0 L$ P8 s$ E; E+ ?0 ?
  22. #define WIFI_SQREADBASEADDR2 0x12( c' K& i; M6 ~
  23. #define WIFI_SQREADBASEADDR3 0x133 X: @/ J% ~# C# f  r
  24. . T1 m- [% l/ E" g
  25. #define WIFI_CARDSTATUS 0x20 // Card Status; F) q" N' P  n( x  r& v
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator8 J2 N) }& ?" h0 K/ N! }
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    6 q8 |' z4 P# \3 b" N
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
    4 v, f, J( V0 B5 Y
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
    # }/ ^! W& M% Y8 U9 {
  30. ' g8 ~$ L' W4 T! y: E7 j+ @- a
  31. #define WIFI_CAPABILITY_BSS _BV(0)5 M1 N5 z# p$ ?. E% D
  32. #define WIFI_CAPABILITY_IBSS _BV(1)
    ) U$ C9 m- a, D- Y
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)& j' J9 E9 S0 r& }0 O4 k
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)
    6 r/ t9 [4 [! m0 Y/ y2 B  _& C
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)
    + [1 F* Z. E$ }1 y+ C+ X
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)
    3 O6 H3 O1 L# M8 B
  37. #define WIFI_CAPABILITY_PBCC _BV(6)2 I/ {( C4 S6 u- Z7 L$ Y9 a
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)' g& T) z$ u$ ]* `4 O; r. ~* p
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
    % y8 x4 A* j! ~7 u; M
  40. #define WIFI_CAPABILITY_QOS _BV(9)  ~& ]1 Q3 u- B- ?6 W
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)# k5 G  I6 k; p7 D7 k+ k, s
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)* d3 I0 G+ r- N- F5 C& e9 M! u6 y
  43. . }5 m$ [6 Y7 f2 V8 S) b0 M
  44. #define WIFI_SDIOFRAME_DATA 0x00; z  o+ \! h* v) u) u
  45. #define WIFI_SDIOFRAME_COMMAND 0x015 W7 r8 j; g- {6 Y  y% y; w
  46. #define WIFI_SDIOFRAME_EVENT 0x03
    1 K4 {% N) R7 H) z! j5 n

  47. " O' Z) E$ _+ y: d3 }9 I* ~
  48. /* Command List */
    . J3 Q& P2 e7 v0 s. p6 q
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    + X5 _4 w5 m1 R" F! N
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP. [5 }# t* X" h- T; V
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
    ; u+ W) @6 b* D3 ?7 T5 R
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
    % p3 C9 I+ {8 K+ F- m5 M1 F% p" |
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address
    + z( }  ]  B6 G' T( _+ ^$ r/ r- v
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption' {' @2 O# Q( D; x( _
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
    % K% o( B. h' [( x
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results* D' l: X7 t( r! \9 y5 {  f

  57. 4 U, ?* J! ?& z5 W5 u/ k; _
  58. /* Command Result Codes */
      D) K7 X; |3 K3 |3 I
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error
    3 j3 ^3 c, ?" ]3 M2 s. j
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed; O$ K  j9 c3 N& p- k/ J5 ?
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported
      E6 e3 C/ B7 [! F

  62. & Q6 X6 }8 `6 R7 V
  63. #define WIFI_ACT_GET 0
    8 u* ^6 w# p- u# V
  64. #define WIFI_ACT_SET 1# s+ L) p% @. s, v7 x& S
  65. 5 Y5 p3 \% T  L& Q1 j
  66. /* Authentication Type to be used to authenticate with AP */
    0 `& D8 `! Y7 O! T
  67. #define AUTH_MODE_OPEN 0x007 b+ ]* w# m3 T1 H& |* i+ E- `
  68. #define AUTH_MODE_SHARED 0x015 I. L% |$ v) T+ A2 c5 ?! C
  69. #define AUTH_MODE_NETWORK_EAP 0x80: t! u, C1 l2 p! `: Q  w
  70. 4 ?1 e8 W: ~" O# K
  71. /* WiFi_Associate return value */2 B0 E# n9 p9 j2 ^! q# e: o' a
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe( C( ^0 d  X  \4 W7 D5 ^) Z
  73. #define WIFI_ASSOCIATION_ERROR 0xffff
    $ L  u# k8 ?6 U' [3 T: M. m1 @
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功' M- N/ t% V7 A) x% B: W
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101. T, P; ?$ z1 W. T  s# Q; s
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧/ [. J, a8 F# X! x! I
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213
    8 X! U8 w( H- K* C+ @) }  t. L" q
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
    " z' |2 @) a$ e$ \6 P0 H+ F
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败
    * b% `8 p% ]# }
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时
    8 A, ?9 e3 e7 D6 W
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时
    + H( X- ], l, u$ A8 w: o
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时" b; x2 D- W. @6 O' J
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
    ) Y0 k5 s0 A! d3 p$ ?. p/ _

  84. , B2 I- k- E, a+ U# I0 S! `
  85. #define WIFI_KEYTYPE_WEP 0" G3 G- I0 a* }! v3 L; S
  86. #define WIFI_KEYTYPE_TKIP 1- E4 E( l6 d  Z5 |3 @' c
  87. #define WIFI_KEYTYPE_AES 2
    9 ~& V. T5 X) \$ K( u, m* U
  88. $ v( r$ {+ T) P9 c! z4 r4 _: V  a
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)4 T- I# V9 j" z5 [# v
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)
    6 Q: M0 Y1 d' r! y8 a9 C
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)+ |" ~" [, n* s8 g

  92. 5 J3 s' y: r  b
  93. #define WIFI_MACCTRL_RX _BV(0)8 S( ?2 e% Q6 A
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
    4 O) o/ h2 P% s
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)
    ' w2 ]: f+ t' y1 u2 k+ u" y
  96. #define WIFI_MACCTRL_WEP _BV(3)
    1 ?, k0 X, ^0 u% ~5 M: [6 b; L% S
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)8 g# E" ?% |; V* \9 S$ V" V) N2 @4 `% ]
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)* p  x% v7 c* J) `
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)
    $ n' x) ^, Q) f, ]
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection  x! ]* M# c7 A, F
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode" V! p3 k% J3 o
  102. 2 B' M2 I2 v& X, `0 N. H) L9 I$ F% v
  103. /* BSS type */
    # p  L* C. o7 O, y% ^
  104. #define BSS_INFRASTRUCTURE 0x01
    + f& v5 G1 x; p) k6 `
  105. #define BSS_INDEPENDENT 0x02/ n) d+ f# @; S: s( l: y
  106. #define BSS_ANY 0x03  \9 u* I$ W: U% R5 Q  Y

  107. * B# w" a( V: Y; f. Y* @# i
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */9 c* s, @. J  J8 c; M9 @
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */) m# i$ q( t: j4 u8 f; t7 U
  110. #define MRVLIETYPES_SSIDPARAMSET 0x0000, V* d' R& x; ]+ C. ~& {/ g8 z
  111. #define MRVLIETYPES_RATESPARAMSET 0x0001
    ! R- T: e: w! ^
  112. #define MRVLIETYPES_DSPARAMSET 0x0003
    8 a( y! h' Y0 \$ J" j) w0 g
  113. #define MRVLIETYPES_CFPARAMSET 0x0004
    # m2 [3 z8 A, D2 J/ d
  114. #define MRVLIETYPES_IBSSPARAMSET 0x00060 E5 |7 k2 G8 n9 t/ Y! f
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030! x. A- H2 z6 e9 k& w
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd4 f9 F9 |2 y. |3 i
  117. 4 S" A+ }+ R0 S( C) F: {. t
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100
    ( I, g" r: m" T
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x01014 y6 O5 H. t+ q" E2 H
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x0113' Z9 a' u2 L" b4 P) `
  121. #define MRVLIETYPES_AUTHTYPE 0x011f
    ) H; M$ S- ~1 R1 w

  122. . T3 P* h2 ]* S' z& w
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小* N( M7 B6 u5 t" x& A
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小/ q. X" E9 A" W% T  ]& J

  125. ; l2 M: G% @: ^5 @3 h
  126. typedef __packed struct7 E+ W& w) n5 o! v
  127. {
    ) L. [$ r  U% @3 R7 T& |
  128.         uint8_t type;8 O1 D/ b, J1 N' I0 k
  129.         uint8_t length;" ^, ]8 T; y6 ]' Q1 b
  130.         uint8_t data[1];
    " ?, h7 Q, q  y+ M$ r; V: y. S: Z
  131. } IEEEType;- c2 Q( T: N3 N
  132. # T1 F' ~/ y6 u- B$ ]. r
  133. typedef __packed struct: W- U9 r7 }1 I' |
  134. {/ t2 w8 @& E6 ?& a. S; P
  135.         uint16_t ie_length; // Total information element length9 f! A. H1 X' C7 G) C( i  P
  136.         uint8_t bssid[6]; // BSSID" C, ~9 y* V2 q2 ?
  137.         uint8_t rssi; // RSSI value as received from peer
    5 d8 Z( W8 w( s! R+ t9 {
  138.         % l5 _5 p+ b5 t& j4 F! y
  139.         /* Probe Response/Beacon Payload */
    . F' q" ^) ~& Q$ t6 b8 `
  140.         uint64_t pkt_time_stamp; // Timestamp( @2 P% Z) L" s. c+ D; [+ i" w
  141.         uint16_t bcn_interval; // Beacon interval8 r$ @. e# @5 R6 K: F% m
  142.         uint16_t cap_info; // Capabilities information
    ( ~# Q+ ~5 t/ J* Y9 j3 K
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据
    / T, v' X1 H" k
  144. } WiFi_BssDescSet;& I4 }5 u0 H* S, i" G- ^) \9 r# F" n
  145. 9 ?9 p) P  }$ H' d" t
  146. typedef __packed struct5 a9 h! R& }& H( u4 c
  147. {& j9 o" J4 s) \. f4 o
  148.         uint8_t oui[3];6 A, R8 E+ [  C; @' S; G7 U7 Z
  149.         uint8_t oui_type;
      P% @1 P* i, n+ I
  150.         uint8_t oui_subtype;9 s2 U/ z; P/ D" P( Y& h
  151.         uint8_t version;
    # ]9 n( L% L) N; o- r+ a; ]
  152. } WiFi_VendorHeader;# o2 Q5 }5 K3 ~8 m6 X6 y, A* z
  153. 6 K' F8 Z' q, @- }/ k
  154. typedef __packed struct
    , A9 l) M3 g0 _$ v
  155. {" V# h* V, y& P: N) q6 T
  156.         uint16_t type;3 E. ^! p5 [0 a5 d% O" k  i
  157.         uint16_t length;4 p$ G$ Z- t' r3 \$ m9 D0 O9 C
  158. } MrvlIEHeader;
    ( T/ j2 z6 `7 p7 R
  159. ) Q" u7 R0 |; x$ A" ^+ d% R) T8 k) e
  160. typedef __packed struct% |  ~6 E5 E3 c3 @/ s( y* h3 G# q
  161. {8 h6 c8 O5 ?% j
  162.         MrvlIEHeader header;
    - J' E0 M; u5 q* Q' s
  163.         uint16_t auth_type;
      c5 f3 F# N$ S  ^1 X2 P: ^
  164. } MrvlIETypes_AuthType_t;
    ' k% p! j! ~3 N4 S5 b: F

  165. % [& N$ C! B' A; y- K7 z" w
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec, |+ M, S" E0 S8 }5 r* J$ A. V/ O
  167. . C& k# [7 n) ~2 m) z9 R6 S
  168. typedef __packed struct
    4 Y8 G1 ]0 [2 i7 A# x  j" O
  169. {. E/ p/ P! k5 w  j' e( W
  170.         MrvlIEHeader header;
    & Z' X( `; j" H$ E6 Q
  171.         uint8_t count;
    / t0 Y; K$ X6 a- }2 e2 t
  172.         uint8_t period;6 h+ D) a$ y) N
  173.         uint16_t max_duration;" G+ T1 R% t6 \) N: I+ U4 U
  174.         uint16_t duration_remaining;5 r9 ^- v0 o. @$ r
  175. } MrvlIETypes_CfParamSet_t;7 n  o8 Y8 _" e7 R( C7 _) w
  176. 0 U+ v6 K* x4 ^1 J6 W/ b
  177. /*typedef __packed struct4 x! m% I0 V9 }8 `% D
  178. {
    . ?& a: {6 r% ~& q' y/ b/ V
  179.         MrvlIEHeader header;
    5 y$ l, B& j( E+ ^3 D6 u: e  T. }6 R
  180.         __packed struct
    ) M! b2 S7 l. T# A
  181.         {
    " |! x8 ]% u/ Y3 c4 c, g# N! J2 T
  182.                 uint8_t band_config_type;
    # J' |4 I0 t% T* T% N' V3 y
  183.                 uint8_t chan_number;
      U% Z8 `# x% }& N9 p$ Q
  184.         } channels[1];! @% {: D& {- U3 F. r! b. l" O
  185. } MrvlIETypes_ChanBandList_t;*/
    - v' ^( K+ f6 K3 r8 {
  186. 9 R/ _/ `9 d# J$ C
  187. typedef __packed struct
    ) A: Z1 E: _( U+ ?, f4 E6 k( Z* e
  188. {1 Z4 N+ w3 x& j% w8 _
  189.         MrvlIEHeader header;2 C9 R& @1 ~. a* }
  190.         __packed struct* v( j* A$ x# |+ K9 g, A: r
  191.         {
    3 S+ u1 J, j6 F4 t* W/ j, a
  192.                 uint8_t band_config_type;2 N0 C, e# |) ]6 f. i  u
  193.                 uint8_t chan_number;0 o/ z9 z# }- X9 \3 ?
  194.                 uint8_t scan_type;  d, ~/ K' E; u
  195.                 uint16_t min_scan_time;; c9 {. q+ Q# Y* A! S
  196.                 uint16_t max_scan_time;8 `& g2 O  E* J
  197.         } channels[1];
    / K9 W4 s; F4 N4 `' G" m
  198. } MrvlIETypes_ChanListParamSet_t;! h- R' J- H( Y9 N8 q

  199. # B: K. _# x* h1 j' f6 X+ F2 Z
  200. typedef __packed struct. `- ]2 B' k: e% {4 @
  201. {, j) d8 |" ]- j: r9 T
  202.         MrvlIEHeader header;) Q7 @9 y- x. i6 j( P( j
  203.         uint8_t channel;
    ' M: b1 U# n; u1 y
  204. } MrvlIETypes_DsParamSet_t;
      q5 p  s2 D8 `

  205. $ p( b1 D9 P  z  d% j' C& ]8 S
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
    . X" \4 L. [2 \6 P/ u
  207. . H9 o9 J* U: P, [2 |' {9 S3 y
  208. typedef __packed struct5 L$ |& Y  g  \1 Q/ N
  209. {
      A3 f7 D8 u# n, q# O
  210.         MrvlIEHeader header;
      O9 s+ \+ r/ L6 r" z/ z4 d9 }
  211.         uint16_t atim_window;% A0 h2 O4 Z# ^+ l4 t( k. p4 a
  212. } MrvlIETypes_IbssParamSet_t;
    1 U3 q* v% h* \5 [, G- K
  213. 0 q  y- c2 [6 G6 _4 q1 {
  214. typedef __packed struct0 {" R! Y: c- p0 O1 E& }+ o$ |
  215. {* _: H% I$ d# }+ r, Q8 Y! E0 K
  216.         MrvlIEHeader header;6 B6 [6 \6 M& v9 e, ~; m
  217.         uint16_t key_type_id;
    5 O8 R6 `- z' t( q! @
  218.         uint16_t key_info;
    ' k5 N+ ^% v8 G% s# d6 g. C
  219.         uint16_t key_len;# U% M( s9 m- ?2 \( c  d4 I
  220.         uint8_t key[32];7 C9 S  }8 @& \  v. s  V
  221. } MrvlIETypes_KeyParamSet_t;
    ' Z* n- c* i9 m" h; A7 V( N
  222. 3 G; I. F* v' [, l4 |
  223. typedef __packed struct
    . J$ |4 k2 n% T: \. q
  224. {
    9 j+ b( k/ Y8 T. Q: b6 U
  225.         MrvlIEHeader header;" k5 V! ~5 n* `) t- M
  226.         uint8_t rates[14];
    & ^/ p' Y' {0 ~, ?% ^9 n% a
  227. } MrvlIETypes_RatesParamSet_t;( F8 K) N8 b& @0 v8 o4 f
  228. ; V# r- [3 q* Q4 h% A5 x
  229. typedef __packed struct
    $ y' g3 y6 f  v7 F" Z  F* u7 X, z( h0 f
  230. {
      r# X# {1 J# j2 f5 h* Z
  231.         MrvlIEHeader header;$ s& |1 X9 A) m  G
  232.         uint8_t rsn[64];
    / ^/ U% A' W5 [- _
  233. } MrvlIETypes_RsnParamSet_t;: m" N# P! t' B

  234. 4 _! r$ T: S4 M( }3 P
  235. typedef __packed struct/ T% Z+ Z0 S! u3 D
  236. {
    , }: C( ~6 v# }( A
  237.         MrvlIEHeader header;. ?. X' J7 d  y0 {
  238.         uint8_t ssid[32];. O6 R/ g7 b( p
  239. } MrvlIETypes_SSIDParamSet_t;
    4 ]+ H& O' z9 f* M4 N! K+ W" Q9 Q8 O. W! S

  240. & q9 _1 ~+ {+ o& R
  241. typedef __packed struct- x2 k; j+ {& J
  242. {* k  O5 u/ S- k, [/ f4 t+ k
  243.         MrvlIEHeader header;6 h* W5 a/ H2 W- w8 }& q
  244.         uint64_t tsf_table[1];
    ! o8 `) b) W+ v$ D; l
  245. } MrvlIETypes_TsfTimestamp_t;. K/ t  y! c& y' y

  246. 5 ?+ A& y1 f8 F1 `* Y
  247. // 整个结构体的最大大小为256字节
    5 C# x; G/ i& ~# g
  248. typedef __packed struct
    9 i* ^$ C1 C( ]/ D/ \+ S* b! `
  249. {) q5 k: H5 a+ [; C8 K' p4 n* Q
  250.         MrvlIEHeader header;
    , Q6 C4 P3 u+ {& |6 O  T
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够
    . B/ g8 E2 ]  o. @% c6 v
  252. } MrvlIETypes_VendorParamSet_t;
    4 J4 v. {. p% c; z+ ]1 T9 i

  253. ' V) `4 X  B1 ~9 e/ c
  254. typedef __packed struct
    " m5 b5 D+ K$ b! @; b6 `  P
  255. {2 }3 H4 ]& ^: y. \7 P' c% W
  256.         uint16_t length;
    % t# j( B$ [" \/ s
  257.         uint16_t type;
    ' c* G" c# [! S
  258. } WiFi_SDIOFrameHeader;% }2 d! I1 x6 K* E

  259. 6 u0 J1 _: Y. c6 b
  260. typedef __packed struct0 [# B$ E% Z7 |
  261. {4 J* w- B# f0 f2 T* w& w9 Y, e
  262.         WiFi_SDIOFrameHeader frame_header;
    + Y( H4 U' A. D* ?7 Q6 W, |
  263.         uint16_t cmd_code;4 s5 g6 M+ I' H0 G1 g- _
  264.         uint16_t size;
    ' e8 Q( O0 D/ {- I) B5 p: b
  265.         uint16_t seq_num;2 m+ ^( M3 D6 Y! q. [+ b( ^% p
  266.         uint16_t result;
    $ Y' H5 [1 Z' v+ t! q- E: v/ k
  267. } WiFi_CommandHeader;7 O3 H0 ~! L* I; Z% b. l

  268. ; j; D+ ~9 n4 C7 B
  269. /* Table 2: Fields in Receive Packet Descriptor */4 A: A+ s$ q0 A# D! U
  270. typedef __packed struct7 X# X% K% A6 K& |# e; a# c% N
  271. {
    + u0 e$ ^, W9 @3 i; g: \) B
  272.         WiFi_SDIOFrameHeader header;
    6 w, j  e( m6 a; e! ^
  273.         uint16_t reserved1;0 a# P1 [: s* r# h' i
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)
    , L* B' v1 E. [
  275.         uint8_t reserved2;
    ' Y( N& O$ M+ w+ K- j
  276.         uint16_t rx_packet_length; // Number of bytes in the payload
    / k2 q- B& b" ?, v+ p
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed." r, C8 `, _$ s) G% a/ U! w5 R
  278.         uint8_t rx_rate; // Rate at which this packet is received9 |/ `, K$ y2 h' K
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet/ s4 @) \$ o* @/ ?& [; A
  280.         uint32_t reserved3;4 X2 x. q. v7 D7 l( D; B
  281.         uint8_t priority; // Specifies the user priority of received packet4 \5 ]7 f" q$ j7 |: {& y
  282.         uint8_t reserved4[3];
    6 w0 n: R. n5 _8 j: s  i- l+ A
  283.         uint8_t payload[1]; // 数据链路层上的帧
    4 F/ ]( ~' R0 s
  284. } WiFi_DataRx;/ L) {8 [  h/ B- K9 I
  285. 3 j0 H: K: Z* ~" n
  286. /* Table 3: Fields in Transmit Packet Descriptor */* T2 U. c: Y! f! \0 g. K1 J8 h
  287. typedef __packed struct
    . |( A! |. i" l- ?
  288. {
    1 E, q/ I: t  G" {
  289.         WiFi_SDIOFrameHeader header;
    * G0 B/ J; \9 q! s! I* G. b
  290.         uint32_t reserved1;, y4 i$ m3 {+ B0 j: {
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings
    + W9 t8 p+ b' y$ E* `4 Z
  292.         uint32_t tx_packet_offset; // Offset of the beginning of the payload data packet (802.3 or 802.11 frames) from the beginning of the packet (bytes)
    ; w# P  J+ Z1 O3 b. ~: j. @
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame8 N2 O3 Q6 b( \/ H4 V) B
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5
    ! T- h; g) l6 r( h3 c9 F% d
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 36 V6 z: }# e8 ^+ ?" ~% l* i
  296.         uint8_t priority; // Specifies the user priority of transmit packet
    % Q* E. Q, @6 Y/ l4 b
  297.         uint8_t flags;
    5 Q% ], ^0 I- ^, y# \) V% F
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations
    : W. }9 E. \7 O" F4 b  }# ?
  299.         uint8_t reserved2;; K+ a  g4 ~9 ?- k2 {5 X& m
  300.         uint8_t payload[1]; // 数据链路层上的帧7 f/ ~" X: J6 ]7 P3 [
  301. } WiFi_DataTx;
    ( y! u; M. ^0 O* t

  302. 3 b. p$ _$ q, n* [2 H
  303. typedef __packed struct
    ! p" u3 _) ]3 s& C" z* P$ i
  304. {
      Z1 m* S! G" }
  305.         WiFi_CommandHeader header;
    ) k1 V  S( d0 B6 @3 t% L$ ]
  306.         uint16_t action;0 r3 q3 p9 i) M$ l  N4 {
  307. } WiFi_Cmd_KeyMaterial;6 N+ K& T% i; U

  308. . e) b# M7 K; I; Z
  309. typedef __packed struct
    1 G' Q7 A# `! A! c- A& d1 V1 U" c
  310. {
    , V$ \' X# M$ `5 _: u
  311.         WiFi_CommandHeader header;
    6 A' w/ i+ g+ L9 ~! f% N
  312.         uint16_t action;
    $ t4 d# m7 d5 i
  313.         uint8_t mac_addr[6];
    7 j6 m  A4 f; o6 P: Q7 I0 O
  314. } WiFi_Cmd_MACAddr;1 p  M8 X8 l$ a4 W" Q+ h

  315. : _3 o6 ~( l& g; A) H' d: E7 N. @
  316. typedef __packed struct: a  o5 R; A2 Z, m6 Q' }8 f% t4 r
  317. {2 p0 W  X" l& \$ S0 Y; A
  318.         WiFi_CommandHeader header;
    * K6 S8 V. ~$ f
  319.         uint16_t action;8 J# Y8 c0 f, C; |6 A, w# m
  320.         uint16_t reserved;3 n' g' {  o+ W6 `: N
  321. } WiFi_Cmd_MACCtrl;
    8 ~, U! N0 i+ Y

  322. 9 ]8 g& H7 n9 m# h3 Q) n
  323. typedef __packed struct
    9 |2 v" u& }- i* O& R, S
  324. {
    4 _( ?" J" D' D* S  @0 C! W! Q! @" B
  325.         WiFi_CommandHeader header;
    0 [" Y6 }# l2 T# j7 c3 Y" ?
  326.         uint8_t ssid[32];
    6 U- B/ j& C1 J* s& @' D/ g
  327.         uint8_t bss_type;# M4 O8 K2 d1 {9 M& \4 r
  328.         uint16_t bcn_period;  p' Z* B( K5 h( }
  329.         uint8_t reserved1;
    ; X% l# F: x( r8 o6 \
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
    0 a$ }& u9 Q& S
  331.         uint32_t reserved2;5 u2 U+ Z' F+ z
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network' c7 B% [/ ^/ s/ F- e: n9 `
  333.         uint16_t reserved3[3];
    / n% n$ |) U0 }  @0 ^
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information
      i# A- c1 p2 R9 V. p1 ?) w% C
  335.         uint8_t data_rate[14];% m, l& k% H% y9 E1 z
  336. } WiFi_CmdRequest_ADHOCStart;
    6 `; i: J7 \4 v9 B3 M" v. @' W
  337. ( r2 |$ n- e2 O$ Q
  338. typedef __packed struct* ^4 N! Z2 X& G+ M) g/ F8 E
  339. {
    : E/ l9 |% W7 ]
  340.         WiFi_CommandHeader header;
    0 x' }- w' r  V) f! ?
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address3 Y8 B/ ?% U0 R1 j! b" g
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information
    6 |3 v; j3 \2 L& `* n0 R
  343.         uint16_t listen_interval; // Listen interval5 m8 R0 O" Q5 v2 p" v3 b
  344.         uint16_t bcn_period; // Beacon period
    & l- s6 m' n7 W+ G" I2 I/ t
  345.         uint8_t dtim_period; // DTIM period2 X/ L# ^2 i0 W2 K- V
  346. } WiFi_CmdRequest_Associate;3 Q4 i, t5 p  a; x* y4 l8 J! }% ~  d

  347. $ Z8 D/ s, U# l: p  y
  348. typedef __packed struct$ i; O+ s$ I$ T# s1 f' w9 K- g
  349. {" a/ G0 T: z; A: q3 S
  350.         WiFi_CommandHeader header;
    : p  P7 T# l- T3 w4 X
  351.         uint8_t bss_type;* V* b0 V+ k) W0 d+ d* F. i
  352.         uint8_t bss_id[6];
    3 d. B9 F1 P" U- E! z2 F- a
  353. } WiFi_CmdRequest_Scan;
    0 U/ p7 c: a+ @$ ^/ R$ x, h: p
  354. & o. W) o! D! Q- Q7 |
  355. typedef __packed struct
    3 s$ ^+ V. t' @) I
  356. {5 G4 T: a; Q) z: A* i  |
  357.         WiFi_CommandHeader header;/ R2 z. y6 t( L4 r* T7 q
  358.         uint16_t capability;0 Z, C+ Z: y9 R. k) j5 m$ O0 n7 T% i
  359.         uint16_t status_code;
    / B) W& q$ F; T
  360.         uint16_t association_id;
    # D4 p4 \% _8 I3 n( S' D
  361.         IEEEType ie_buffer;
    ; R4 Q% K5 A- R5 b% b3 C: j
  362. } WiFi_CmdResponse_Associate;. L1 B1 }8 U. i: k3 ]. U1 _! a! j. x
  363. 0 z0 e6 O+ H2 G, F$ t) G! {/ Q
  364. typedef __packed struct
    ( |. q- x! w0 `. `# i
  365. {
    $ U9 L9 \5 S! m% q9 \1 K' i
  366.         WiFi_CommandHeader header;7 V& O. R; }: r8 s: O$ Z- q& D
  367.         uint16_t buf_size;2 o# `5 X' e. J
  368.         uint8_t num_of_set;% d3 C( ?& |) |
  369. } WiFi_CmdResponse_Scan;+ T' [' n  l( L: I# U
  370. 8 V  t  A4 h& g3 [" [0 w
  371. typedef __packed struct8 x! p% U6 ~) T- x. o
  372. {7 a; T% ~3 P* f3 }
  373.         MrvlIETypes_SSIDParamSet_t ssid;
    : h8 |( e" g) z; e
  374.         uint8_t mac_addr[6];
    : i3 R3 c8 |) m
  375.         MrvlIETypes_CapInfo_t cap_info;! [) y* k7 v5 `7 t2 K# Y7 A
  376.         uint16_t bcn_period;! g' s* O  F: E" Z2 _4 o# b7 j
  377.         uint8_t channel;
    ; X$ u7 W* X' O2 m  W( P# D
  378.         MrvlIETypes_RatesParamSet_t rates;' U3 ^% U1 ~1 e4 s1 D. C+ p
  379.         MrvlIETypes_RsnParamSet_t rsn;
    7 \( Y* d) d/ B! a2 K* x& K0 j
  380.         MrvlIETypes_VendorParamSet_t wpa;
      @- ~1 Y; }2 i% d1 T) P& o7 U
  381.         MrvlIETypes_VendorParamSet_t wwm;2 {, b3 j/ U& s! M2 A
  382.         MrvlIETypes_VendorParamSet_t wps;
    / c; h+ O4 M7 b9 r5 `3 V
  383. } WiFi_SSIDInfo;, c1 p  {5 ~' D" U( U5 i

  384. - h' c( m+ ]$ s. |3 ^  p/ \, K
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)! K. j; B: F' o  M7 ~, G1 b
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)
    ; v5 R8 p) p; V  i, r. Q
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)4 M! f0 k) o( ^3 i$ b/ c$ l1 C  k
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)( s, G, R0 s" ^8 [8 b/ Z
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)$ b7 A9 o1 [1 J. K) `( k% l
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)
    1 V, Y) e7 p6 ]/ v
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)5 J# V) X( f" f9 y+ Q7 j+ x. ]' a

  392. 7 E9 q, k8 q1 w. ~+ _
  393. uint16_t WiFi_Associate(const char *ssid);5 N( ^* u6 X, D# U* `$ \' P
  394. void WiFi_CheckCmdTimeout(void);, ?% f' l2 r1 g, x3 Y# z
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    5 q) D4 x* m; m( ?8 ?
  396. uint8_t WiFi_DownloadFirmware(void);
    : K* e1 J! `$ k0 E" u% R
  397. uint16_t WiFi_GetPacketLength(void);
    2 E# V9 J: _) X) X) P, G, h
  398. void WiFi_Init(void);
    . ~5 ~+ x. g2 u/ `, }$ C9 l
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
    ) |, ]1 Q! o  k' l
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    & r8 d( _3 P. R4 ?, L& h6 D
  401. void WiFi_MACControl(uint16_t action);
    ' ^0 i8 [# @; i: F9 g' S, c
  402. uint16_t WiFi_PacketPending(void);
    2 M+ O( E$ e) \% k! T
  403. void WiFi_PrepareTimer(uint16_t nms);% P5 ~- K+ |" z; C1 a: d4 R0 y
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);* n+ W" t: @% k! B
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
    0 T- K- d. k3 \, |6 ?4 z1 @- J
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);* y) {: n7 n9 G' W3 _
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);0 L5 r% F( `8 e& D
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);
    7 E9 Q" y% `7 f
  409. void WiFi_Scan(void);
    / o, ]4 O' H1 y
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);- w" Z' `  `; \6 a7 D' B$ C
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);
    2 D7 t, K0 W$ I
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    ! C2 q6 F' B% W3 U9 I( I7 D
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);! y3 o; a8 Y7 p0 K+ d! t
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);
    9 ~& I' {" j& R* K: v
  415. void WiFi_SetBlockSize(uint8_t func);
    ' m. U0 v8 l1 U2 e. ^) B$ Q
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);
    - Y6 q) D5 s2 A1 d" f; j
  417. void WiFi_ShowCIS(uint8_t func);- t* V$ O- D; a0 g! U: V4 y
  418. void WiFi_ShowKeyMaterials(void);" A5 d7 Y$ x; R1 Z
  419. uint8_t WiFi_StartADHOC(const char *ssid);
    3 ]/ V: {! t  z; O7 m
  420. uint8_t WiFi_Wait(uint8_t status);" d5 ]  j0 A5 J' E) n$ G8 B
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);5 X+ K% i3 q, \: V0 r/ W
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
      z# _6 n: J5 }+ v# {
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);" O- i0 L2 L  J* x1 p, {
复制代码
【WiFi.c】
1 S7 T) W! ?9 w4 V8 V2 N. v/ `$ |/ k
  1. #include <stdio.h>
    5 k+ m  c7 D2 G6 p) N
  2. #include <stm32f10x.h>6 {) l! f7 ?8 s2 q4 n& z! H
  3. #include <string.h>& `+ W* X+ m" k# g/ n9 f
  4. #include "WiFi.h"/ O1 p0 q2 W! G' c2 e; J7 t6 I

  5. 3 e2 k. U4 V9 b/ [
  6. extern const unsigned char firmware_helper_sd[2516];6 e7 ?0 d& o" h7 o7 A& F% d
  7. extern const unsigned char firmware_sd8686[122916];
    ( G. [/ p' @9 [$ g/ I  P

  8. , i# `: K) S7 I! o: x# `  T
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址% s5 O( N* z0 \! i  q' g8 M( R8 p% Z

  10. : Q# ~- e, [5 j) K7 t
  11. static uint16_t rca;
    ( N9 C% {: y: T% Q8 e5 w% e. n3 C% Y
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;
    0 W2 U; u9 T5 l; f
  13. static uint32_t io_addr;6 \% x- i. a, d' c
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小( Y4 I) w; q: E6 s# [
  15. : L( ^" G) I- V2 H$ [! y
  16. void delay(uint16_t n);! r1 {7 p; Y, l: k: }' `$ c
  17. void dump_data(uint8_t *data, uint16_t len);5 y# K- K5 X! s  e6 F; T/ e

  18. ' }" U7 i) E6 W+ E; {% z/ M
  19. /* 关联一个热点 */
    : ]& X4 G& W& G0 E8 j$ u
  20. uint16_t WiFi_Associate(const char *ssid)2 R7 i: ~7 c  A. W& h
  21. {! L! z' m9 m2 p0 E& O3 R$ y7 G
  22.         uint8_t buffer[2048];( X" g, p) t. c/ G
  23.         WiFi_SSIDInfo info;
    4 |, h+ k' J6 o& [( [" n
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;0 ?  q/ x- W; z1 a" M
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;: b! r1 H: Q- J$ R
  26.         MrvlIETypes_DsParamSet_t *ds;' a% \7 F1 ^  F" w$ p
  27.         MrvlIETypes_CfParamSet_t *cf;
    % q1 U, t. s& I3 i
  28.         MrvlIETypes_AuthType_t *auth;
    6 ]) X1 c3 C9 u" @- R' d% |' H
  29.         MrvlIETypes_RsnParamSet_t *rsn;9 ]0 W; K9 {/ k

  30. / s0 u* x- o6 r/ d% i" O( s
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))
    ( J) n$ e# n' i- O
  32.         {0 @6 |+ ]4 v$ B  _) X  E
  33.                 printf("Cannot find AP: %s!\n", ssid);
    8 e2 F. k7 [" s) w! o6 W
  34.                 return WIFI_ASSOCIATION_NOTFOUND;( c- T% u6 G8 `/ x6 X$ i
  35.         }
    2 F$ Y) m# }" V% `3 f
  36.         
    6 G; Y( |7 V9 |/ G( q2 c5 H
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));1 q5 R% Y: V& K$ c" ^/ v5 V5 H' {
  38.         cmd->cap_info = info.cap_info;
    . R. i; R! |) K0 ]. d1 f
  39.         cmd->listen_interval = 10;
    9 n; d! c/ v6 N% X" A
  40.         cmd->bcn_period = info.bcn_period;
    8 Y6 \, p6 c5 ?1 R3 f# j
  41.         cmd->dtim_period = 0;
    3 N% x/ G/ z/ Q4 ^2 K2 q6 f$ m
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));
    1 q% Z( u+ Q. l  u, W4 R0 s" M% X- E
  43.         7 h) K( V' u! ~, ]
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));
    & H# @/ R" K2 f& h
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;6 i1 o  X5 \5 S# M
  46.         ds->header.length = 1;2 }- s# f( m. F- N+ P0 j  D4 F
  47.         ds->channel = info.channel;
    ! k" H8 v  \* Z  W
  48.         
    4 \' d) u% l) e0 g' x2 |
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);( C) K& o8 |8 r; m6 c( ^# ]+ C
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));
    ) l+ j, W1 v! _; \# K
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;
    # g7 }( b: |0 N/ v
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);7 s0 ~1 I# D$ Y5 _- ]
  53.         
    6 R/ a3 C  y' E8 D6 ~0 }
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));
    3 n8 _* Z. L6 g- n' I2 y) H4 |
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    , A, j# m- b. _6 j
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;  }5 ~& g$ q3 X  E7 J
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);+ \7 K  i- A: [' T
  58.         auth->auth_type = AUTH_MODE_OPEN;4 z% a  i, X! ]
  59.         
    - D3 o, _- E8 n" p7 f
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
    ; t9 @( b- k8 l; G6 q
  61.         if (info.rsn.header.type)
      Q1 h+ v  q  D) `9 K
  62.         {
    & [7 E! w3 ^5 e
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接
      `+ d' r: U7 W
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
      ?0 Y2 z9 E9 c* Q  w
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));. w. v( O& h4 y
  66.         }
    7 W1 a# U, @; B+ c/ `. R
  67.         else2 u$ {8 P6 Q0 y! _8 d
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数$ W2 T* P! E; X% |, n
  69.         
    ' z) \0 S* v, F2 d. J
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))! W4 q  O: {9 V) [6 i0 o9 x
  71.         {
    4 H( S) u) Z* `2 L( P/ U/ t+ a0 ]
  72.                 printf("Association with %s failed!\n", ssid);- R/ A2 Q$ M' H4 ]4 k" z
  73.                 return WIFI_ASSOCIATION_ERROR;) J" }$ }) v$ W# E
  74.         }
    ) I& x" e; V1 m" i, O; i1 P
  75.         
    , [1 W7 U2 m: D2 F- |! _
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);$ _9 |3 \8 m# ?
  77.         if (resp->association_id == 0xffff)
    7 m1 j4 j) }1 d/ E* T& s& I' ]5 @
  78.                 return ((-resp->capability) << 8) | resp->status_code;
    $ p' D1 {3 J3 z1 f
  79.         return WIFI_ASSOCIATION_SUCCESS;
    $ n# c1 V$ k( t3 J; ~% z. q
  80. }
      b3 a" s( ?4 L1 F8 m4 G
  81. 4 L* E, f1 J) m) O
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    2 e( N" C' ~3 n7 x# k
  83. void WiFi_CheckCmdTimeout(void)
    7 B8 s+ b' n8 J3 K4 }
  84. {- {8 _+ t. w6 p; c# C
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)  Y* j8 C4 Z0 _/ D& w3 [, C
  86.         {
    ' {# U9 W0 d' S: R' z6 ]! U
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志, B2 i' v$ F9 x7 z& y
  88.                 SDIO->CMD = SDIO->CMD; // 重发5 S5 b& Y- G0 C! ]% @4 m1 J
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);& a1 l/ N6 }+ g" a# D" x( {3 J
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);# Y+ j% N; z4 n4 N* E
  91.         }% x5 L' v. w" e- S. k% a# T
  92. }* b) h9 ~9 n3 Q% i  e) S
  93. ' W9 P4 m9 P+ r$ M# }, J
  94. /* 连接WiFi热点, 并输入密码 */6 h. ^% A$ I0 b/ C: Q% R6 o
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)
    . ]0 f# e& k, y  d4 }
  96. {+ X1 e& G2 n7 O2 N
  97.         uint16_t ret;
    8 g5 U6 O- l# k2 y
  98.         do
    7 c6 }) T+ p# L! ?8 d, g
  99.         {
    1 e' G8 R! W, A+ g3 h" E
  100.                 ret = WiFi_Associate(ssid);, G! D: R8 J7 z, k% t
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)( J: c$ `3 C" v/ H' F
  102.                 {
    . o( J' }( h2 ]8 s5 [! v
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);, ?  }$ ?9 P' K6 z# X: L7 U
  104.                         delay(2000); // 等待一段时间后重连
      }, {' c+ a* H  n; ]; |% |1 v
  105.                 }/ N; P7 C6 P( ~8 `. W
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连
    ) k8 P6 D9 o3 ~% g& S+ J; l
  107.         8 I) w( b3 W5 ^( w2 R0 I
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)9 T5 @% A" \; }+ O: A. g7 J
  109.                 return ret;% a( g. x% x2 h3 o
  110.         ! G( D' ~( N/ P2 V6 T
  111.         printf("Connected to %s!\n", ssid);
    ) y# S. d6 ~- P! l0 B1 I- c. Z  c. h
  112.         return ret;$ f8 U1 I8 B5 N/ j
  113. }5 d8 E& a# o3 C9 h' t. w5 [

  114. , b3 I9 e1 q) A3 Z
  115. /* 下载固件 */
    1 M! X/ }* ?) U. S& V
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc
    8 ]5 Q( c% ?* m2 r! D
  117. uint8_t WiFi_DownloadFirmware(void)
    % w" t. ~( h: [1 j/ u8 P
  118. {
    9 c$ t$ {$ w; D, _* {9 v) W8 o' B% R- v
  119.         uint8_t helper_buf[64];( T, P" c1 r' h$ h" X0 k
  120.         const uint8_t *data;
    : k6 c, @; h& J# [$ [2 m
  121.         uint16_t size;% m* W7 F5 _0 ^* x
  122.         uint32_t len;
    - o$ }$ ]+ n1 i  J! O
  123.         8 N" d" w. R* x/ y0 p, u
  124.         // 块大小设为32+ p- G1 w, r+ T# p
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;' l4 w, A9 ]  P$ |9 u8 U+ ~- j, q
  126.         WiFi_SetBlockSize(1); // 应用到Function 19 F9 k. R* S% |% N
  127.         : r% a" V; m! }5 w8 v, v  d
  128.         // 下载helper% e' f9 K% S$ Q, {+ X. K: I
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);
    9 m( C5 _( T$ u: U5 c  S; h4 e
  130.         data = firmware_helper_sd;* e. M) n& f1 p, D% M4 K
  131.         len = sizeof(firmware_helper_sd);
    : p" l" F  m5 f# R- Q7 O
  132.         while (len)4 x  V  N9 H& M, E" T  @8 g' B
  133.         {( b* e* O% D4 L2 H- k. F! x9 X
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量- k# T0 u! G/ h9 N9 O
  135.                 size = (len > 60) ? 60 : len;& y  H' ~8 Y' V
  136.                 *(uint32_t *)helper_buf = size;
    : M7 m/ |4 H) n
  137.                 memcpy(helper_buf + 4, data, size);9 o* c, B- s; }
  138.                
    4 U5 i4 a4 I7 \7 b
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    1 S3 m; w& v, E1 g
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));
    8 q0 u3 T& X; D8 ~9 Y
  141.                 len -= size;9 [  e0 {3 ^( @. e  t' v# k2 S
  142.                 data += size;$ ~  H# _2 ~2 Z! s! C- j  N
  143.         }% `5 v  I/ x- C; H" N( x
  144.         *(uint32_t *)helper_buf = 0;
    6 _4 L* B$ U5 z& P( ]+ D" k
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束
    8 }& O) i$ s2 `
  146.         8 G) f, f) L  o' h3 P1 u0 T
  147.         // 下载固件
    7 ?+ N/ r( W1 _* U
  148.         data = firmware_sd8686;
    + {! g% I: C2 }7 K0 e
  149.         len = sizeof(firmware_sd8686);7 c' s& r! l% x2 A  z# f7 O7 e
  150.         while (len)7 U. z! n, c5 s: o" L' ^/ |8 F
  151.         {
    0 N! i* ~6 y9 B7 F- ^# {+ W; }
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    6 c7 s: Z% v* |
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数
    * Y2 l- H; H/ f
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);$ z- }: v- S9 e, I4 t3 S  S! X
  155.                 8 a+ D. ]! L+ S! {
  156.                 if (size & 1)- m7 F& g- |0 N/ d9 N% q: S) j
  157.                 {
    & Z) D% g3 T+ b- I3 l0 u" O
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)/ K3 K7 t5 B$ z7 W% B# c, G/ z' F2 P
  159.                         printf("Error: an odd size is invalid!\n");
    . h  t5 D% {, r" n
  160.                         return 0;
    4 e. d/ x! o" R0 _
  161.                 }4 d7 E+ u, k2 W/ Z) U# h
  162.                 if (size > len); q% v. f8 W+ W/ [* Y
  163.                         size = len;
    6 q; ^+ B$ \$ I+ p
  164.                 2 F: L: o- t& v& k) i
  165.                 if (!WiFi_WritePort(data, size))
    ! [) r" {  [; m* i/ e" }
  166.                 {
    : j8 [( Z: G4 F% h4 u
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);, P( x/ K0 K$ K; J2 N& d
  168.                         return 0;5 S7 B# n& a  ^4 B
  169.                 }- a3 O/ h$ Z2 a# p
  170.                
    " x) ~3 H8 j9 F) X- ?4 ?- w
  171.                 len -= size;, M# `* c$ _) f+ Q% }, D
  172.                 data += size;
    : F  L& I- _- K& z
  173.         }
    8 A! Q$ W6 ?3 }) s& x
  174.         0 x/ s3 |( }; q/ d8 x3 y6 R
  175.         // 等待Firmware启动5 _$ R7 P& c7 s: @9 k: ?
  176.         while (WiFi_GetPacketLength() == 0xfedc);3 I/ L" W7 j5 _6 \3 P/ [( ]9 o
  177.         printf("Firmware is successfully downloaded!\n");
    2 T- E' _# h/ I
  178.         return 1;0 p2 G/ [* t9 r5 c/ ~: @& x
  179. }/ {0 G! B8 G, \- O* w

  180. & c. B$ z8 R) e$ G/ d$ S) r
  181. /* 获取数据帧大小 */  S, c- p3 v& @
  182. uint16_t WiFi_GetPacketLength(void)
    ' f, U. N; L& v: W1 u3 j( @
  183. {
    0 r7 h' F/ ?: L. k
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);7 r6 D2 _8 v8 e+ ~% D1 e  T
  185. }
    1 O* D* M% a/ `" r4 ]$ m

  186. 1 F4 g9 q% v% c/ @
  187. /* 初始化WiFi模块 */+ u: k4 S! M, F8 i( w: o' T5 _
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization9 `7 Q0 h! U# z7 ~$ O7 t
  189. void WiFi_Init(void)
    / X: `  H- n; u
  190. {% U2 c& a  X' U3 W$ d$ [) Y
  191.         printf("Initialization begins...\n");
    ; ~' S+ ^1 C1 A0 D3 }
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;
    2 Z- d1 d/ x, W, Z+ F$ [1 S
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz4 s$ x. N! j% h
  194.         delay(5); // 延时可防止CMD5重发
    ' v( u5 b/ C6 v/ ^5 W2 b! u
  195.         
    $ n! q, D; n0 @
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
    : w, u8 I9 T  d6 O# |
  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)- h' B- Z$ f  I
  198.         
    0 D) m' m6 b! R3 k8 x) P, _3 N
  199.         /* 发送CMD5: IO_SEND_OP_COND */
    6 N2 N6 v. @" O
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;9 ^' w. @7 b8 I
  201.         while (SDIO->STA & SDIO_STA_CMDACT);6 C4 @. U% r" W! E
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令
    4 o, T5 q2 s6 T: T" R( T4 |) y
  203.         if (SDIO->STA & SDIO_STA_CMDREND)
    # k- G: F( ^# W' G
  204.         {& l; \, T1 {; q6 V2 i( t
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    " z5 U9 ^& |7 V8 J; }2 f. S
  206.                 WiFi_ShowShortResponse();
    - s- q, D; j3 U2 s" s/ f
  207.         }2 i0 a- g2 x1 i6 e
  208.         " O, @: H' t/ M4 p, v6 [& {+ G
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */
    / A8 e" p' E3 }& P, h  {
  210.         SDIO->ARG = 0x300000;# ~# q( g6 A, ]3 C/ w: H2 M# @- u
  211.         SDIO->CMD = SDIO->CMD;
    % X& l+ Y0 Y6 X
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
    . r# q1 l; Z2 b' l$ V
  213.         if (SDIO->STA & SDIO_STA_CMDREND)
    7 z3 S  q0 w7 M& t+ _0 Q) m" H
  214.         {
    8 a" i- \& S( S; Q" y
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    7 d8 l2 t, h" ^7 X- s
  216.                 WiFi_ShowShortResponse();! ?0 Z' N- b* @) F2 r8 x" P& |
  217.                 if (SDIO->RESP1 & _BV(31))4 c  }4 t; Z" c0 L
  218.                 {6 i) c. T2 L7 i
  219.                         // Card is ready to operate after initialization
    , q# ]2 `( A# |$ g5 t+ \. |0 j, L  B
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);( U2 N  E5 K1 @# }1 J- R8 v7 \
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);3 T( T0 G0 A( K2 P; ?+ Z, n1 f
  222.                 }4 t/ E. J8 ]+ p9 E; A% \* H" i
  223.         }
    ; ?; u! D6 {6 V$ x: s9 a; o$ Y
  224.         
    + x4 [7 F! {4 \' V: m
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */4 Y- s" t9 B( k3 u
  226.         SDIO->ARG = 0;
    & U/ G0 R( y$ j1 i8 V
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;% o% K/ k) c0 Q1 x% J
  228.         while (SDIO->STA & SDIO_STA_CMDACT);
    ; U4 d1 m. o! r
  229.         if (SDIO->STA & SDIO_STA_CMDREND)
    . y7 E- K  N) r* w  w' y
  230.         {
    / r. {: M+ w' O# F; Y; h
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    , Y7 j, ]2 Q: F, Y! z* ^9 L/ X
  232.                 rca = SDIO->RESP1 >> 16;) N4 k  i: k6 u2 m  g
  233.                 printf("Relative card address: 0x%04x\n", rca);( r" Q+ A% C7 H* m: A' n# o
  234.         }7 Y) p: [* k. J
  235.         
    - }6 [" `  ~, }+ B1 z. ?( k
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */
    $ h& z( F7 {( t8 ~
  237.         SDIO->ARG = rca << 16;
    ) q: u& l& t0 @" i9 X
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;8 Q% b1 |( }4 f% Q2 @3 a7 W
  239.         while (SDIO->STA & SDIO_STA_CMDACT);' S9 p# }: u( P- s% q4 D& Q. s
  240.         if (SDIO->STA & SDIO_STA_CMDREND)
    9 U" a4 }# U+ H5 Q& A* u$ q0 w5 R
  241.         {
    0 h) A1 \8 L+ v9 k  \2 y
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    ! U3 L0 M( M9 d6 ]4 s9 g1 Y- v* n
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);
    3 K- M& c# a8 @0 B1 n
  244.         }
    5 `, N2 Q' I9 d
  245.         : |6 R" \0 B: I* E9 A( A2 }
  246.         // 提高时钟频率1 S8 E( `+ H" L1 P  v1 a- N
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
    ) N0 c1 Y" C* V' Y9 l! i$ ~
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒3 T: Y* C0 f; S7 ~7 p; |" J+ W$ J
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz% }$ Q/ ?3 ?8 r+ G: H
  250.         + g6 g. l$ [( `2 Q: {- a% Q9 t
  251.         /* 选择总线宽度 (Wide Bus Selection) */9 m2 `# Y' b4 H) Z- Z) J
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)
    8 p: p( J# I+ t- U& C7 V
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
    ! ~5 f$ D3 r# i, z! ]5 r
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus7 w0 |  F5 d5 J3 l  \# Q& A
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
    * z+ z; t! h/ V, T1 Z2 i6 _6 }2 n
  256.         
    - K* i$ Q3 O' q
  257.         // 初始化Function 1+ q+ M: G9 D1 z% K* F  p5 T
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)9 a+ a0 a0 A  g3 z. d
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)* \8 b6 i! x, S' t
  260.         % t" q* O' x# b; W+ p+ n
  261.         // 显示CIS信息5 i- `  |! @" F; |
  262.         //WiFi_ShowCIS(0);' w" n8 M* A( \% b- ]% P# ^$ E
  263.         //WiFi_ShowCIS(1);
    ( w# S) g; C0 p  P4 c
  264.         7 }1 A5 [7 k: _5 A
  265.         // 下载固件4 X9 m+ W# f( q1 G
  266.         WiFi_DownloadFirmware();# y7 }# U) N3 r6 i0 I) V
  267.         
    ! L5 f7 C: E9 _3 L
  268.         // 设置数据块大小为256字节! f2 |# k7 V9 ^' @( E8 R+ b- O1 D
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    . R) ?) g9 O% _; c
  270.         WiFi_SetBlockSize(0);0 d4 \  y9 B8 r5 ]) G) a6 }  I3 S, {
  271.         WiFi_SetBlockSize(1);: a/ a$ K4 f6 E* c4 o; }: U* c
  272.         / \2 H9 b; s; Y) l9 E
  273.         // 允许发送和接收  H4 E5 x1 |+ e4 C0 K
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间
    % ~% a, n4 y0 h/ t- F: b
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);
    2 b/ R) X+ X! S! a
  276. }
      n( Z8 K$ ?" i& Q& R/ }2 A" d4 \
  277. 2 R& W6 L+ F. M' ^' R. ]$ _7 q
  278. /* 获取或设置密钥 */
    3 C( ?; U3 y: H7 s
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)" A6 {# ]+ c. G! B6 p
  280. {
    $ _5 p1 \" J- e5 p
  281.         uint8_t buffer[256];
    7 Q0 q5 U& U: O( I4 E
  282.         uint8_t ret_size;; G2 b6 m/ K' J9 }2 l: L! G, @
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
    , V7 w6 R% X# D6 u
  284.         cmd->action = action;
    * g: M+ X1 z- _3 O7 w
  285.         if (action == WIFI_ACT_SET)
    + H( J, Z( k7 a, r: F
  286.         {
    ' ^6 t# {) q% H5 i" p2 t7 W
  287.                 memcpy(cmd + 1, keys, size);1 B) ^5 g# o0 C/ Z9 G6 H( f: w
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);3 b; [& [( h8 ^
  289.         }
    7 Q! c! L2 C4 s% @9 w; Z9 p9 g
  290.         else
      E6 t' B& S& K: z7 @
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));
    % t$ {# r- ?' W3 z" F; i
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));
    " K- p3 V8 z- b/ Z( X6 m
  293.         
    ) W2 i% |0 T0 |( I/ C
  294.         if (action == WIFI_ACT_GET)( ^. M! I; D  E8 c7 R
  295.         {) l$ U( I2 R9 [- G
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
    : v* X8 {/ Q' b: w6 i0 r0 K
  297.                 if (ret_size <= size)% H' z: [# j. k3 |  @
  298.                         memcpy(keys, cmd + 1, ret_size);2 W3 K5 A8 `1 y! d/ Z8 b8 n! u7 h
  299.                 else; \: p. b6 B  W% {$ L8 {
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);
    ; F0 S) V& N2 `: f9 P; D6 g
  301.                 return ret_size; // action=get时返回读取的数据大小
    ' q# X8 q+ i. W3 k, g/ p
  302.         }
    6 \- u) f6 o8 m7 Z$ I; y
  303.         else
    8 M7 L9 g1 u- D1 R. G, G  W& ?
  304.                 return cmd->header.result; // action=set时返回命令执行结果值7 f" l. _# F1 `+ m# Q: n) b- ]
  305. }8 V% ?3 M* i- o% K; b
  306. 0 \3 h) a$ d4 {$ A9 E
  307. /* 获取或设置MAC地址 */% Y) z; L. d4 i, |5 Q
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)
    / m* m+ c% O6 q0 y, h1 {
  309. {" t8 Z" R+ B& \. n
  310.         WiFi_Cmd_MACAddr cmd;* Z8 }/ u+ I: o  c: _8 h
  311.         cmd.action = action;
    & `- j9 W4 x4 m* z4 U7 [8 G6 X
  312.         if (action == WIFI_ACT_SET). j' F; B+ e% ?6 _
  313.                 memcpy(cmd.mac_addr, addr, 6);
    3 v$ i" D# \9 b) H7 P
  314.         * m$ _8 F6 T) s/ _% a; X% |2 k7 H
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));# E, L0 u, J. B3 L
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    # F8 j$ k4 h& m& J4 O
  317.         if (action == WIFI_ACT_GET)
    ) ]! F0 S# x6 T; ^6 `
  318.                 memcpy(addr, cmd.mac_addr, 6);
    0 J2 ]1 O* H: B7 m, |) ?% S
  319. }& N0 s- D; s8 t6 h  G; S

  320. - O- m2 V* u' u1 ?( B/ B4 U5 x4 v
  321. /* 配置MAC */
    8 G1 |& i% a5 [8 t9 D
  322. void WiFi_MACControl(uint16_t action), c% y) \) F9 X8 Y
  323. {
    ; m. n8 l/ W3 v5 d! Q, B; S
  324.         WiFi_Cmd_MACCtrl cmd;
    1 m( i& ]2 P; E/ C' L, o
  325.         cmd.action = action;
      T" @( h' ]. Z$ _
  326.         cmd.reserved = 0;
    4 F% q9 _# K7 U( g" {; k: k
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));
      z/ G8 |6 m; W: M
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    0 i- n/ d1 T8 k6 r7 V+ M
  329. }* S5 H; k, f" a: i' |$ w
  330. / [0 L) a7 e3 r( u1 a: `/ D: D( ?
  331. /* 获取滞留的数据包大小 */
    9 m: H: e9 D# a7 P
  332. uint16_t WiFi_PacketPending(void)2 Q0 V1 o% N8 {8 U
  333. {' T$ a# X2 j9 E4 X, i
  334.         return wifi_pending_size;
    # u0 S6 U4 l# g
  335. }
    . t% ?1 K9 ^3 \
  336.   C! G0 R8 o, Y
  337. /* 准备好超时计时器 */% R6 ~0 @7 p6 ~9 M
  338. void WiFi_PrepareTimer(uint16_t nms)
    6 c) t  H6 W% ~, c/ ]
  339. {7 r% j2 j: G3 @
  340.         TIM6->ARR = 10 * nms - 1;
    , ?" C& v( w, Z6 r, d
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz# P; [  ?+ A, H
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置
      l) D' m+ i6 [% H8 u( B9 G
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位% [0 W/ g9 X9 [+ b
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式& R6 p" h  C. c5 f" }, I* V
  345. }
    ) \$ u1 `: z2 T  q
  346. 2 b' Z# |1 x4 o& _) m0 S4 k. `7 K
  347. /* 读寄存器 */& Y8 B2 c! e/ R+ ~! j; G
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr); Z7 r4 u0 ]) s. r$ m  ~7 H
  349. {
    5 g2 w$ @0 a) G/ |
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);
    6 g" H( t/ F) q+ s% Z; s
  351.         if (SDIO->STA & SDIO_STA_CMDREND)- Y$ M' Q7 o3 C# M
  352.         {
    : r- ?0 S7 c$ u
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;7 C" W1 m2 N) n; g3 t+ P& c
  354.                 return SDIO->RESP1 & 0xff;4 g5 f0 g; B7 h) b9 J
  355.         }  W7 o# K, q. g2 F$ d' V+ r
  356.         else0 C9 h# G9 ^2 G0 C# M' `
  357.         {
    * t8 H8 t# X) V2 Y& L! p1 ^
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);% h# Q) \1 o0 I1 k: p6 M- F3 K( p
  359.                 return 0;7 ]0 p5 h0 a. O( {9 O
  360.         }
    ) n# f' {% X: n/ K' G
  361. }
    9 t6 t; W, s! D4 F& e' b  I

  362. 8 c3 r0 [% A  F
  363. /* 读数据 */
    ) T& t% W" }: g0 f
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    - S" W+ U0 Y! D
  365. // bufsize=0时, 只读取数据不存入缓冲区
    8 M3 ]# z* A0 S( ^# s/ ~
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)- H+ \9 k0 f: N  f3 v4 ^
  367. {
    8 S( D; h, b7 d% j  J
  368.         uint32_t len, temp;, m- W5 ~/ P& x* \  x: v
  369.         if (flags & CMD53_BLOCKMODE)
    ' m! E4 K, q! |5 t. r  F
  370.         {
    2 O2 u9 s5 t; P* b' z  P
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数
    - V( B' W5 p4 E' _
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
    , i2 I. _* G& y
  373.         }
    2 X8 w) @6 V5 c7 x
  374.         else
    # k  R. J  S6 J% ~
  375.         {, P1 @- B% J0 [9 i0 w" a% o0 @
  376.                 len = count; // count表示字节数2 A# @) u- s- w: j% y
  377.                 if (len % 4 != 0)$ Z. N9 ]+ ^9 C% e! ~* w
  378.                 {
    0 z3 m: L+ g8 C
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    , `: b3 }2 P  `5 [* ]$ Y8 q
  380.                         count = len;
      \, H+ a) H# [5 n2 [& x
  381.                 }
    / x: M" p; ?! d4 f7 ^
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式6 E% i3 L% [1 I/ G) _
  383.         }
    6 h3 B3 m; t& u7 n& {& D; B
  384.         SDIO->DLEN = len;
    0 ?: Q# ?3 H, ^; t0 F
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
    & G$ X0 A; l' ~. ^8 u
  386.         
    . h, J4 U+ n- A# T! J
  387.         WiFi_SendCMD53(func, addr, count, flags);
    , h$ `$ y! ?# I
  388.         while (len)
    . e) d! d8 H  ^; _
  389.         {
    % q- R$ T4 h& [3 y
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)
      A* e. Z# ]$ `
  391.                 {
    9 X; L2 c( U3 f
  392.                         // 若有数据到来就读取数据% _( i4 b4 c2 D; X7 \
  393.                         len -= 4;: @7 ]% Q$ w5 q2 W
  394.                         if (bufsize >= 4)
    4 N$ r0 `  t8 e% e
  395.                         {
    ' Z7 L6 _9 ~2 A3 @
  396.                                 *(uint32_t *)data = SDIO->FIFO;4 b, ]6 h# m$ V. W' O; o! x, A
  397.                                 data += 4;
    1 L+ x4 h/ O" k4 O4 M) {
  398.                         }
    + k* C# ~2 _* H; J" U2 c  q
  399.                         else
    5 D: \! s: }2 Z6 H4 g' ~
  400.                         {9 r  r$ ?0 y( \. y, [
  401.                                 temp = SDIO->FIFO;. u9 k: n4 i- h' W6 p
  402.                                 if (bufsize > 0)0 j* l3 K: ]( L! o3 s0 h
  403.                                 {8 k3 u$ `7 `/ n7 g
  404.                                         // 写入缓冲区最后1~3字节7 u; B4 H" j3 j% V4 d
  405.                                         memcpy(data, &temp, bufsize);- Q+ l: i4 M7 B! }0 S! Q" S
  406.                                         bufsize = 0;- Q, o# Q7 l) }$ Q
  407.                                 }
    ) T0 X0 `8 x6 ]
  408.                         }
    , M/ \4 z: o7 y
  409.                 }
    + G" J3 f+ a7 ~4 ]
  410.                
    . z5 B% `2 {8 s- r) P. @/ Y  M
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)
    7 S1 \4 J% \! C0 i% W: Y, M
  412.                 {
    3 T$ L/ G  D. ?9 [- P6 p# Z- U
  413.                         printf("Data Timeout!\n");; B7 d* t! p. _  f# V
  414.                         break;- M7 s: }% B: h' P) M
  415.                 }/ E( [9 P  w+ t  ]9 G
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)" d( {7 Y; I3 b
  417.                 {7 \0 U; P0 a% a2 d+ B( v. i% |5 H
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);) m* x6 D4 f% G  V( s
  419.                         break;8 Z9 w9 A8 ?$ d7 I7 x) I7 z
  420.                 }; i& P1 ]7 ]2 [6 X, _
  421.         }& h5 _6 K' c( b. S# l7 k
  422.         ( t3 Z, Y* h9 t$ m! j0 @
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));5 x# v* A5 s$ Z/ v' s, i
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;: ]- h6 F9 ~: q
  425.           n+ K& V* K: T% J+ ?
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;
    3 L3 c2 b  d! A* S* Q2 k
  427.         if (flags & CMD53_BLOCKMODE)% L" A3 L+ U3 k: H6 _+ [8 Z9 H
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
      ?5 r, @) a( H% Q! g' N. @4 a
  429.         
    9 u2 d. q, m6 Z9 f0 ^2 Y" A
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功
    6 j$ C( }  y% l" m
  431. }
    6 ]# m/ p6 k3 J6 X$ @& [7 m
  432. % ^& B5 K; _2 }) R
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)
    / s9 Q$ C; h  s2 i; k9 d/ M
  434. {
    / `) |) i' o  Q& z8 _
  435.         uint16_t block_num, block_size;
    6 _* ~3 O6 b3 m3 ~" }  }+ r
  436.         block_size = WiFi_GetBlockSize();
    $ I/ w7 c) T# W  q  |) d& a
  437.         0 M# Y5 Z, S0 b' F7 [
  438.         // 读取数据
    , j% ~9 G. c" j6 |+ o
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    / a' \8 J: }0 C2 U8 l% D. t
  440.         if (size >= 512 || size % block_size == 0)3 O8 w5 e8 d/ K9 V' R, y- l
  441.         {
    0 O( \. E' O1 N: g) [
  442.                 // 采用Block模式传输
    " Y; U7 c0 l" L5 P5 l- t
  443.                 block_num = size / block_size;6 u3 ?* c9 h  t1 ]
  444.                 if (size % block_size != 0)  W8 T- [+ D) g3 q, }
  445.                         block_num++;$ m7 z4 W+ J) }) @
  446.                
    " w  A1 }0 G3 m- A& d* }7 K" W
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
    / ~& l- j- b& A$ P4 c
  448.         }
    ( U/ `! }; R: X% h6 K- l+ O5 m
  449.         else
    + R; |$ m, _, e6 M
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);- n  ]: _1 p) D! a& f! I% y5 {
  451.         + T; S$ L/ S* y4 j# n
  452.         return SDIO->STA == 0;
    9 D6 H. |6 o) f7 H
  453. }
    * v8 w9 Y. }3 P! M5 a

  454. 0 B; _1 B2 h% V% p' ?8 S$ F
  455. /* 接收数据帧 */
    : d6 L* T, t- F3 ~. C; o
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)' b# w* z3 ]1 S  \, z# y# D
  457. {: L$ Q) M1 {( y
  458.         uint16_t size;! _  k5 O/ N0 D5 @3 U; K4 m
  459.         if (wifi_pending_size)
    ; K/ c: j" R$ h+ E) j
  460.         {
    8 e* Y% b2 H9 d! ^; J
  461.                 size = wifi_pending_size; // 先读取滞留的数据包9 h0 r- ?2 h! t1 b4 U
  462.                 wifi_pending_size = 0;; F- g0 R( p" l5 S
  463.         }' a* I0 B  v6 t. r+ U6 v
  464.         else6 [  C9 p0 w5 e8 L; O5 p  u- A/ Z
  465.                 size = WiFi_GetPacketLength();! g6 ]" E$ q: G+ c" O
  466.         return WiFi_ReadPort(buf, size, bufsize);  r4 U/ w- p! c- n5 P; g4 j
  467. }
    / Q3 p# B! [: n0 ^
  468. ! L, l  J" p- v! b4 r
  469. /* 接收WiFi命令的回应 */
    8 e+ S6 D0 X' h; L' d
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)' S  ^( A* N% k0 ]1 m: m1 F9 {
  471. {
    - |, e9 \/ h7 p3 f1 w; E, d
  472.         uint8_t retry_cnt = 0; // 重试次数( g9 d0 A* y# x1 A
  473.         uint8_t wait_status, resend;
    / j+ R1 e+ E: Z' }' T' h
  474.         uint16_t size;6 @- r; T2 m) a2 [6 L1 B+ s/ T1 H
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;  C1 |: u  }6 P: W  h5 ?
  476.         WiFi_SDIOFrameHeader temp;6 `/ f; B2 D4 x- }- `
  477.         7 F! z, L; y: f& s4 h) O' O
  478.         // 等待数据准备好9 n7 b* }" \9 R9 E5 k) t
  479.         do
    * w- B# f- Q( o0 m
  480.         {% G  R+ N) [! v) e. I' v  G) m
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);$ E/ Q% c# k. }  q9 @5 v( ?& a6 W
  482.                
      V0 t0 \/ }: `; ^8 Z' \
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息
    . a3 u. X) z6 M* D' B5 J
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
    + q: T5 x; w* M1 S$ V, F5 s' x
  485.                 {
    5 B; I% u9 _9 [/ x* ~
  486.                         // 若读到的是一个数据帧, 不是命令回应
    ! d% J) B) n# ~5 @
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功
      n1 A& m; X* t# G$ @& r
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);
    1 G; P) @2 z5 M0 @" Q. e
  489.                         wifi_pending_size = temp.length;$ _6 G0 C# o) F
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算9 G  F* p5 P! S6 v; \
  491.                         resend = 1;
    " c* I& B9 S5 X7 Y: a
  492.                 }& S) _2 \6 L0 p' t9 G( X# S/ j
  493.                 else if (wait_status == 0)/ ~! z% I( J* Y, d, Q  _3 j6 R
  494.                 {
    $ g+ a. L  A  \, z' o: k5 U
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)! f' q8 b( R* u% B' o) W3 B8 N4 {
  496.                         resend = 1;
    6 K" Q- i% [2 D' |
  497.                         retry_cnt++;8 I" q1 e0 V' V& P* W: d+ D
  498.                         if (retry_cnt >= 5)
    6 V/ n: g0 T7 S
  499.                         {+ F+ k) v& p. ^# Q; Z6 @- F( ~$ _
  500.                                 printf("No response!\n");
    ' B- F$ O" X, R- O. l
  501.                                 return 0;$ F. u' a  j8 ?7 D9 d+ ^2 w
  502.                         }
      g# ~+ K7 R4 u6 I% E. N9 \3 p
  503.                 }. j  Q2 N& v6 Q& l- r2 Q
  504.                 else4 T% K& c" n; h. V& [
  505.                         resend = 0;
    8 q$ S5 W1 h$ h6 V
  506.                
    9 c3 o, X$ @) g5 y
  507.                 if (resend); {1 V) k5 M! G0 P, c0 ^& u
  508.                 {, v  s( _* y9 l8 o
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND), c5 p8 w$ n/ X' x
  510.                         {* j; Q  R8 K$ [9 X3 \
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait  h; t$ X" D7 |* s* \
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);
    3 |* X) o, s% \
  513.                                 WiFi_ResendCommand(buf);" E, d' c' Y) d* T3 U% w8 J+ i' Y
  514.                         }3 ?& ]) A! Z: r# S) O' ?
  515.                         else& t- T3 e* I$ S% N4 a: L! [7 I/ N0 E
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出
    $ h! Q& D, a2 w: i+ Y6 a
  517.                 }
    9 l( H5 J/ t+ s9 b. L/ n# g
  518.         } while (resend);
    5 X8 Z: T. r0 u
  519.         4 L6 L' y  j4 s9 e$ x
  520.         size = WiFi_GetPacketLength();$ {% r2 J4 l* W, v. @
  521.         if (size > bufsize)
    0 B: ]; M8 w; ]3 Z# W3 j; ?
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
    5 W3 w: Z# X( [7 ?+ y6 V+ Z
  523.         return WiFi_ReadPort(buf, size, bufsize);) l( J7 ?  S6 [" P) \  _
  524. }
    0 K4 R2 Z1 @7 Q4 K( o2 u% B$ X

  525. . n5 C* k# o" g# A! m
  526. /* 扫描全部热点 (仅显示) */
    # B5 V8 ~+ O2 Z" b1 o0 X
  527. void WiFi_Scan(void)
    " g! @: n, W5 k. P: g
  528. {
    & R7 A( ?) R( e8 t0 c& j- w$ Q
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组
    0 a' |+ H3 G, e# [# x/ y4 n
  530.         // Stack_Size=0x00000c00
    ' O, C+ x3 p) m+ i
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
    : D  @6 G3 R; ]$ x1 U3 J( l- _
  532.         uint8_t i, j, n;
    8 _9 ?% H6 m' Q, o1 S/ }, O7 w6 X% l
  533.         uint8_t ssid[33], channel, wpa;3 `% X" }4 t( p$ t/ Y& g
  534.         uint16_t ie_size;
    " @) p, u  v  j) B+ ]2 c
  535.         
    6 N# w; j6 A' Z5 N" y
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令" C8 T9 j& ^3 W) y$ Q( b# ^% R% f
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));
    5 P- ?/ F3 u' ~
  538.         
    2 [7 d1 |/ \3 X9 f; a. U" G$ B# R
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;" Z! J1 x# E8 x' k
  540.         WiFi_BssDescSet *bss_desc_set;
    : T! Z' |, O4 `0 M( @% d- H; g+ b
  541.         WiFi_VendorHeader *vendor;
    7 p. G2 S; Z7 b% i
  542.         IEEEType *ie_params;
    # q- I. K1 V: j4 W
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;
    1 Y) n' b+ d% ]
  544.         0 g2 z0 K) i) }2 u8 s
  545.         // 分4次扫描14个通道+ ?; `1 Z' n% n6 X
  546.         for (i = 0; i < 4; i++)4 o: [, T2 ?$ `5 @: f
  547.         {
    % F  T9 r+ q8 }4 l8 t+ J! e7 X
  548.                 cmd->bss_type = BSS_ANY;) z+ x9 }+ ]# C( T- q; }
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));8 u9 M/ q& D& @2 x: s
  550.                 + b+ X- g3 Y9 E1 D; h: v) M8 e
  551.                 // 通道的基本参数4 J  L9 j! u# e4 s2 f1 Y
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数, I3 x/ `* {( u! `6 S
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    8 X) d/ T1 w; W. v0 M. V/ \
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);
    ) I- W& c) @, @/ ~8 [
  555.                 for (j = 0; j < n; j++)
    - G" r+ s" c3 i, f( b2 @+ [
  556.                 {, e  d# J! j2 w; A0 |: Y+ V3 h0 Z. a
  557.                         chanlist->channels[j].band_config_type = 0;
    + D  n& R. W* [7 @. N
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号" w5 \$ i( w/ {: x
  559.                         chanlist->channels[j].scan_type = 0;
    - @" w, j, J% y' F" E. j8 F8 r9 i" f
  560.                         chanlist->channels[j].min_scan_time = 0;  p: M1 ]: m5 w, K1 R
  561.                         chanlist->channels[j].max_scan_time = 100;
    / `+ T6 d( `- |
  562.                 }
    8 E% C1 H1 G1 a3 m
  563.                
    4 _1 E# k5 x* M# A. c
  564.                 // 发送命令并接收数据
    + R0 G6 A7 F. b4 a+ s9 @" D+ T3 g! w
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
    3 G0 i& h1 ^* b4 |  d( Y
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉
    % a7 o/ Z5 i% V1 b
  567.                
    ' x$ E3 t! s/ R, L( l3 q$ v7 @
  568.                 // 显示热点信息, num_of_set为热点数
    0 Y2 G& t) C3 B# y  c  h4 A1 H' W
  569.                 if (resp->num_of_set > 0)
    9 ^/ G) M+ F7 ~' D9 m. T
  570.                 {
    4 L" k3 G) z# G
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));& b. K( h& d0 k: Y5 c/ C9 v  \
  572.                         for (j = 0; j < resp->num_of_set; j++)
    , Q# S: v4 Y: P. d3 E, ^1 n6 d
  573.                         {: @& G$ l" S1 V; s6 b; q; {
  574.                                 wpa = 0;- H6 n$ u, q2 ?
  575.                                 ie_params = &bss_desc_set->ie_parameters;
    : u  T* V) E2 Z& Z' ?, c6 {
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));" t" Y% f8 A  \+ {9 `- Z
  577.                                 while (ie_size > 0)
    9 p2 Y$ ?3 P) D" w4 @; Q, O" s3 W
  578.                                 {+ k4 ?3 d! y! @, f# h
  579.                                         switch (ie_params->type)8 X1 R7 p; Y, T, r8 i
  580.                                         {! M" C; P1 n, X3 s8 }$ ?7 _
  581.                                         case MRVLIETYPES_SSIDPARAMSET:2 S+ r/ e, c/ ~- J- d
  582.                                                 // SSID名称& L* {3 j. z) L3 o
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);1 R' a# R+ u: t( v1 ]. E9 ^! t
  584.                                                 ssid[ie_params->length] = '\0';
    ' O. Z7 d( Y" D0 L- E
  585.                                                 break;
    - _3 n3 l- f+ Z. t
  586.                                         case MRVLIETYPES_DSPARAMSET:
    + Z  R  a! s- k! b- l0 U$ H! [
  587.                                                 // 通道号( s4 L) b1 |2 l4 f8 B
  588.                                                 channel = ie_params->data[0];# s( J- Y3 i" }; h* e
  589.                                                 break;
    . f& a$ q/ l9 k5 L
  590.                                         case MRVLIETYPES_RSNPARAMSET:
    1 ?" Z/ ^. {) O$ U9 l
  591.                                                 wpa = 2;; b! J6 y5 c4 r+ E) z' ]2 h
  592.                                                 break;" X, C5 S) z" N8 Z! y1 ~
  593.                                         case MRVLIETYPES_VENDORPARAMSET:! F5 N9 t4 r0 l$ ~
  594.                                                 if (wpa == 0)4 O6 P8 Q3 v! U
  595.                                                 {
    1 \! y* t7 ^3 Z6 o% k: j
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;
    # U" }4 Y9 f, d+ h* }: j/ z* w
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    " S' r7 F4 h2 R9 h& _( F
  598.                                                                 wpa = 1;
    0 F7 e( c+ w+ ^' j5 G( H7 Q
  599.                                                 }
    % V8 {( O% b  ~
  600.                                                 break;: j$ _& j- Z( [- Z1 [( x) W
  601.                                         }$ F: R7 K0 l- @3 P" q' D
  602.                                         ie_size -= ie_params->length + 2;3 r1 P  M# D$ o* D; }# ?$ C; `
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);! h+ P5 h8 I/ F0 T% E& Z
  604.                                 }
    % j8 @% [0 B8 }
  605.                                 if (ie_size != 0)
    $ t) @- \4 p" g. i' Y$ f, n
  606.                                         printf("ie_parameters error!\n");0 ?. M  o# i* K' A/ O
  607.                                 ' g! |/ H7 |! F8 c, p3 ^2 y
  608.                                 printf("SSID '%s', ", ssid); // 热点名称
    3 V! X5 g, u) m. B3 ?
  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地址
    % R! v: X! S$ e( U6 k
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
    ) c* o5 X7 [" W2 p0 w" ~
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);
    - k0 V. \1 m- S1 ^3 U! d
  612.                                 
    - ]. E$ C0 B- g9 r7 H$ x9 R
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);6 o: A. W) W4 B& k
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY); j  b( x  x1 ]" F" n: c
  615.                                 {
    ; n( G% N: _) r6 @' E5 ^
  616.                                         if (wpa == 1)
    3 U( t; b9 i$ C7 P- k# H
  617.                                                 printf("(WPA: ON, ");
    + j( Z8 z# @6 J1 j! q% m
  618.                                         else if (wpa == 2)
    1 ^4 I- }# _- n: X; w
  619.                                                 printf("(WPA2: ON, ");! `5 l7 b3 b) c8 k% r
  620.                                         else
    # X* m; _& Y3 Z) s2 X+ a5 O( t  w
  621.                                                 printf("(WEP: ON, ");, G# @- ~. C" Q6 f# h  F
  622.                                 }: u4 c2 T! v3 ?/ f! i
  623.                                 else
    ; }: X3 }1 L( p* F
  624.                                         printf("(WEP: OFF, ");- q4 e2 G- n, s  `' f# x
  625.                                 2 [- j: x. z: Z
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)2 q+ ~) [, I/ V! K. [
  627.                                         printf("mode: Ad-Hoc)\n");! E$ @: g8 t/ W8 B5 k
  628.                                 else
    ( D- X% U5 I& S8 M) A. b
  629.                                         printf("mode: Infrastructure)\n");
    9 a+ l8 [0 X3 [9 o) C& A, W
  630.                                 
    ( }" B  V! ]% g
  631.                                 // 转向下一个热点信息
    - s# m+ U, R( @4 d  W" S3 g" z
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);* N9 I* [2 i8 e9 F/ k
  633.                         }
    4 ?8 x. h  Y8 C8 U
  634.                         ' m6 g+ A$ [5 v* U8 ?/ ?6 `2 i2 Y
  635.                         // resp->buf_size就是bss_desc_set的总大小
    6 w1 y. C0 S) i' q# c' e5 l
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size8 ?. J2 f, X, @& m
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
    ' l) e( t0 I' t$ v& o: z2 c- R
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))" \$ V- C+ B' b' n1 k7 i4 y, s: u* I
  639.                         {
    7 U9 p1 ?7 T* |# }
  640.                                 printf("Timestamps: ");
    # L( Y2 D' i7 o3 t3 S% `
  641.                                 for (j = 0; j < resp->num_of_set; j++)
    ; @. J! T  E. A2 I0 K8 b4 Q
  642.                                         printf("%lld ", tft_table->tsf_table[j]);
    9 c9 m. a1 D) c' j9 B0 o
  643.                                 printf("\n");, B4 v# L8 @! S0 J! E
  644.                         }*/' k+ `$ o# A  g' R# S+ O- f% P
  645.                         
    " ]" ^) n, g, ~, g9 a8 I; Q! m
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table
    $ _$ ^( D) |" D3 Q4 |
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)( M' g. l8 W; r& h! u
  648.                         //        printf("data end!\n");0 M- e+ _5 A/ i4 i/ l6 }
  649.                 }
    - J0 p  B9 d- K
  650.         }
    / Z  G, l( B/ e- C7 m( [; q: D  p
  651. }
    ) D6 s# |$ w' a5 P' B3 `% p

  652. # T6 ]+ [" k  p, k" A
  653. /* 扫描指定名称的热点 */
    ) d4 L# K( X, p
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大
    5 J* m( w9 ]# m  g
  655. // info用来存放从buffer中提取出来的一些常用信息6 p- \7 ^5 W4 x" o- [% ?
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)
    ; T- h: R7 H) o. c+ M
  657. {
    ! ^  L0 Z/ k" _8 y6 }% R
  658.         uint8_t i;$ c$ A* L4 B6 @( K& K
  659.         uint16_t ie_size;# p* Z2 R, E, \& K* ?3 K7 S
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;/ t$ R! w+ Z6 L6 z8 c. n4 s
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;
    / V1 R) q. v6 I1 B
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);
    + E4 M2 n. r/ R4 O% u+ e
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;) s: r' D( l$ x
  664.         IEEEType *ie_params;9 k' |# ~- n: {: I& Z" P/ A
  665.         WiFi_VendorHeader *vendor;2 O7 U5 @9 N7 O6 a4 C6 Z
  666.         ; v& W$ j8 u% X; v- m
  667.         cmd->bss_type = BSS_ANY;
    0 d0 ?* B' j" r! v+ X, ~6 @
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    . a4 R3 a2 J  y! s8 G. @! S
  669.         6 r8 F7 r0 ]! y% s
  670.         // 添加ssid参数& N0 _) O, B3 m8 q# J
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;
    1 F" D3 k' Y8 ?& H: n) S
  672.         info->ssid.header.length = strlen(ssid);
    - M) |" o; N, r
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);1 D! Z- ^$ w  Q3 j7 j. i  Y
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    3 l$ J9 `7 A" Q  f$ v& h
  675.         
    $ Y# t: C, o% f# s
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));/ O: z! T# ]- w/ P7 B; Q; W
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    - I$ A5 {( ^/ m0 V
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    . N! \! V3 n0 G# N+ i9 w
  679.         for (i = 0; i < 14; i++)9 d7 O, z/ G. c& i2 K7 i
  680.         {" b: x0 c5 I4 \+ _
  681.                 chan_list->channels[i].band_config_type = 0;3 m: O* Z7 g" a: |  Y. M
  682.                 chan_list->channels[i].chan_number = i + 1;) A  r6 b* _+ @- P
  683.                 chan_list->channels[i].scan_type = 0;1 U1 s. r! H* t3 o* C8 [
  684.                 chan_list->channels[i].min_scan_time = 0;
    9 W  k( Z0 k& v
  685.                 chan_list->channels[i].max_scan_time = 100;& d+ B( [( l' \" V2 k; W+ U5 x
  686.         }& ?  w  b7 ~$ _9 Y+ \1 z
  687.         
    ' \5 y% ]( f) ^1 \' i# n
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));
    & l. N; \5 l' |# ]6 U2 i" r
  689.         wifi_timeout = 3000; // 延长超时时间# n( ?4 C! G: f( Y
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    & S8 K6 c! G0 |6 S
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;* y4 v% P, v! D6 t  M+ s
  692.         $ u. Q8 `( J! [+ B, V
  693.         if (resp->num_of_set == 0)6 z& c+ @4 z7 }6 c3 d3 X$ b- t
  694.                 return 0; // 失败/ _" I( ?3 c% U
  695.         
    ! A" a+ t) t! R, J3 V* F- n7 |
  696.         // bss_desc_set以扫描到的第一个信息项为准
      @3 p5 i# w- h1 v0 ?# O
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));
    6 H# d  A( i& |- o8 o" o2 m# F8 p
  698.         info->cap_info = bss_desc_set->cap_info;( D  c# S; F9 ]! ~% Z
  699.         info->bcn_period = bss_desc_set->bcn_interval;
    4 }" W& ?2 x$ j- f2 F
  700.         & P/ |7 r: z: M4 H2 G) c4 l' `
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)
    : s- H0 a5 P% B4 ^( u
  702.         info->rates.header.type = 0;
    + o4 M- r, D3 Y, P) P2 r
  703.         info->rsn.header.type = 0;# p, J' H+ F4 b3 t* z, v
  704.         info->wpa.header.type = 0;) l6 ?8 s" @3 o5 Y/ L6 x. U
  705.         info->wwm.header.type = 0;' B5 O# q+ X# M& U1 @  h- r
  706.         info->wps.header.type = 0;; V- G! i" c  W8 m% ~
  707.         
    # i' F% @! o7 y, A: |  a% X. F- m$ j
  708.         ie_params = &bss_desc_set->ie_parameters;7 n* C, @7 Z8 E7 a2 x. B! N
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    ; P  h8 d: P4 G
  710.         while (ie_size > 0)5 ?$ U! M3 i9 s. F" n
  711.         {5 a! w4 A2 ?# w
  712.                 switch (ie_params->type)
    , T$ U" E/ Q* y: }8 a% B
  713.                 {
    6 ^5 t8 ?* ^" R2 c
  714.                 case MRVLIETYPES_RATESPARAMSET:6 ?5 ?( n  D# {
  715.                         // 速率1 {3 `4 o9 ?$ A. l$ s% p+ _, n
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;
    * U3 Q. m+ T$ P9 Z
  717.                         info->rates.header.length = ie_params->length;7 O4 B3 B& c, B; p0 r, ]
  718.                         if (info->rates.header.length > sizeof(info->rates.rates)); O; F4 m$ h  n" R  [9 i1 \
  719.                                 info->rates.header.length = sizeof(info->rates.rates);0 m% B0 q) B+ [) h! X7 S
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);
    . H2 `. M2 m7 U& \
  721.                         break;
    * g: b5 w( I5 j+ c- B3 X
  722.                 case MRVLIETYPES_DSPARAMSET:
    6 j7 _( P' s9 k& Y
  723.                         // 通道号# E, e7 S. e$ x% {
  724.                         info->channel = ie_params->data[0];1 L7 F9 @$ F; p6 r' j& q3 `- i
  725.                         break;
    ( L/ c8 O1 g- `4 @: D! ?7 P
  726.                 case MRVLIETYPES_RSNPARAMSET:
    7 u6 r8 C; H$ n$ b
  727.                         // 通常只有一个RSN信息 (与WPA2相关)& g1 m; q% D2 ?+ K
  728.                         // printf("RSN len=%d\n", ie_params->length);' ^4 {7 `4 k% g. {
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
    " w, U+ L# b' s; L' q
  730.                         info->rsn.header.length = ie_params->length;
    . r' @$ G8 L. y+ g
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))9 T0 X3 w9 w! l0 R, i% o
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);
    # m, M/ L- u$ d6 O4 w  O
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);1 k% ^9 h/ |. z
  734.                         break;
    # Q. f7 e/ |6 ^) L: k
  735.                 case MRVLIETYPES_VENDORPARAMSET:
    6 M& ?% Y+ U5 m9 L
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)9 j0 g( }; m# l% r1 Z. q: u
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;
    * T5 ~- z( l- J8 b0 Q0 {
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)7 q/ w5 ^4 K& f- h4 |9 K
  739.                         {
    ' _2 I6 K/ f# y. D( G
  740.                                 switch (vendor->oui_type)3 \9 v: K1 G8 S7 I/ l; D1 D( s
  741.                                 {8 E8 n! f  N9 Q: t! l( J& u; V7 p
  742.                                 case 0x01:& ^( C2 A1 h5 O$ v  B$ E; h7 h" f5 q
  743.                                         // wpa_oui
    : e2 [# d" a2 x* z6 i
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;: Z) R/ j% [  G: v2 c! z6 M' T
  745.                                         info->wpa.header.length = ie_params->length;
    + {; B6 b5 \6 r" M+ k+ P$ _
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))
      Z5 [5 |* D7 O/ g5 K* d* |# X
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);
    ) `7 o" u6 Z+ @% d
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);; I$ [4 ]) {4 i. t6 |
  749.                                         break;
    , c( x: j8 g$ \% `- P' O
  750.                                 case 0x02:2 _/ R( f  q# w9 n$ ^: {
  751.                                         // wmm_oui
    - F8 l3 ]1 ~) ]0 D
  752.                                         if (ie_params->length == 24) // 合法大小
    ! I4 B/ h2 G* \: ^: ?+ V- e3 e% P7 T
  753.                                         {% i+ Y$ `! B9 a
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;' ~& e! T. }" s  T5 o- j* P! k
  755.                                                 info->wwm.header.length = ie_params->length;0 X1 g* y. a& A
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);* c. H) Y4 |3 ?9 P* J
  757.                                         }" o& _3 d& }! m- y2 D; l* r
  758.                                         break;: `& m, r# P8 S4 r% ^+ X& m
  759.                                 case 0x04:1 V0 M/ g7 ]3 J
  760.                                         // wps_oui
    3 L+ k/ \; e# k" K$ \
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;
    # V6 C( {3 h% u" a4 N( a
  762.                                         info->wps.header.length = ie_params->length;. P9 k7 i+ S& ]+ }- w. {4 n
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))- Q# z2 I7 J& F
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    & |2 v9 y  ?. _- y) @2 Y3 j5 W
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);! a8 Z5 X; F7 o+ q6 d
  766.                                         break;/ D4 ?: G8 D5 @( j
  767.                                 }
    ' C, L6 ^" m- T# }8 a
  768.                         }  t' U, ?- P2 E: X7 D! G0 c
  769.                         break;
    3 d9 Y% s, \1 e. n7 v
  770.                 }6 {! q6 E4 v& H9 X+ n7 P3 \
  771.                 ie_size -= ie_params->length + 2;1 q) D- e8 j" q* j& G
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);- g8 B3 R% f% S. w
  773.         }
    " z! z; i# O# J# V
  774.         
    9 Y& r9 {+ c9 N! ?. ~. w
  775.         return 1; // 成功
    8 r- h& `& i3 q6 N0 D( P
  776. }( D( |8 M! B: N0 D7 Q

  777. : ~/ G/ J0 c* U+ A- w& g/ s
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)0 P- _3 {4 g6 \  ]
  779. {
    * `) b7 T+ ]' x0 i" K
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
    + N) T2 M5 X/ N/ i' ~/ C
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;# l) I" B3 f: g
  782.         while (SDIO->STA & SDIO_STA_CMDACT);+ {/ z& t9 \$ X2 S5 a! z
  783. }# r" l# L; q  F3 m
  784. ) A! |" Y$ U) D% v
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)
    2 H& W* R9 _$ {; i% ?: |8 p
  786. {. z( M- L: q2 A! V0 w7 u3 X" V5 D
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求
    0 H3 l( g( C2 y/ f) D5 ]% B
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;0 x; d$ k6 b3 B$ E2 q
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;$ O( ^/ g! y/ }* A% T. v3 C
  790. }
    ! w# o4 c$ j& t6 W& T

  791. / H: O% a1 }9 d9 K
  792. /* 发送WiFi命令 */
    + Z+ x7 r/ t, _5 m* e1 \6 Y
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)
    7 x) J7 o7 q" C8 [9 @+ t7 n$ v
  794. {0 J9 B  n0 K# [7 a7 N0 V
  795.         static uint16_t seq_num = 0;
    $ \$ x: |, i* ^( \" ]( F, M
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;
    ( ^& V% T' h+ e, t5 Q6 W
  797.         
    ; j0 M& q% k; z( m9 ?6 A! K* o4 b
  798.         if (size != 0)
    : P+ u: b  r7 Y* H3 V
  799.         {8 T9 B' {" Q7 k, W5 Q# L
  800.                 cmdhdr->frame_header.length = size;" B9 D! X: i& D) n, z+ i& {/ c
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;. S2 T5 H5 n, c: Z
  802.                 cmdhdr->cmd_code = com_code;
    % H9 q- u# N& i1 _( w* A
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部* ~; E' z; l. O, W
  804.                 cmdhdr->seq_num = seq_num++;
    & _1 \) S7 x' o: a# q2 j
  805.                 cmdhdr->result = 0;9 |8 ~$ G3 R7 d) I2 x
  806.         }
    + T- K6 {! Y1 U6 |5 q' ]) i
  807.         else5 X+ t$ l) D% a* a, r1 A" ~
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
    ) M" u+ j" s8 p/ j6 R# h7 N
  809.         7 n5 Y2 u! Z5 N5 H+ W7 ]6 v
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃* \) P! f4 a! h; P
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())% U  A$ t# o' b7 c. c6 }% V
  812.         {
      N9 K9 V! y6 Y: k+ ]. T
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");
    + l  k; j8 X# }" `% B5 s
  814.                 WiFi_DropPacket();
    ( J  }! u9 I/ C4 @, r
  815.         }
    ( h1 |2 x, J  J
  816.         
    . I- g9 J2 C! E" X4 A+ [
  817.         WiFi_WritePort(data, size);
    4 m) P' u# M4 [' T& j
  818. }
    ; r1 N! d3 b2 [% N* G
  819. # o8 D: Q8 G% ^. v* P( N: r
  820. /* 发送数据帧 */' s" I/ r0 e. s+ }+ [
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)0 W9 G( @2 b' K, O7 G! x
  822. {
    3 X5 p. ^2 |! B" q2 l/ A' @. K
  823.         uint8_t ret;. s' L6 V% x; \5 T
  824.         
    ) d, q, E, g: j/ J* m7 i
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
    9 d' V7 X6 I7 m/ L
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
    4 M$ d" f! O( F" E, I" I* A
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;
    % W  f# S" d3 j4 m4 m5 _$ c3 |
  828.         
    2 B' q8 J" n/ z3 K5 {8 h
  829.         packet->reserved1 = 0;
    1 U2 d4 p. D( V6 k) X9 V
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings
    3 ?' z6 m+ M6 J8 Z
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader
    & I; ~3 l% _$ s
  832.         packet->tx_packet_length = packet_len;4 i- B" a& K9 m3 Q1 F) G
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);: w( T" f* S- Z3 k* _3 G& S- m
  834.         packet->priority = 0;( m0 X' Q( Z% v
  835.         packet->flags = 0;
    $ H) c! d6 J' N. V9 R
  836.         packet->pkt_delay_2ms = 0;
    * I+ V" g( b: J- Z1 n- L3 K4 s
  837.         packet->reserved2 = 0;
    1 E, e6 v' U* J% x- _9 j: ^
  838.         ' M- g' U8 ]2 o9 q( ]: l
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小( g: O. f8 p4 G7 O/ |6 h4 x
  840.         // 未读取之前不会收到新的数据帧
    - I. R  t8 a0 B  v& p6 w
  841.         if (WiFi_PacketArrived())
    4 U2 w6 y5 P0 D! u
  842.                 wifi_pending_size = WiFi_GetPacketLength();. o+ H# `1 ?0 E( U% ^% T$ q" x
  843.         
    # z8 |- S! U0 M: H5 h% t% w
  844.         ret = WiFi_WritePort(packet, packet->header.length);
    # i* W: `; V, c4 ]) p6 J4 x- u9 X
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
    " t0 ?" O/ }: ^5 H
  846.         return ret;
    $ u6 S- ~# P& [: O7 e- F
  847. }
    ! Y+ X$ T4 B7 Z, Y, _" D

  848. - D5 J+ B- g1 I+ C# o: T
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */2 T5 E) O4 |" @/ N' {$ W
  850. void WiFi_SetBlockSize(uint8_t func)
    , Y7 f/ Z, L2 R( q
  851. {3 R2 j3 d7 }. K9 {5 m! _# `6 Z2 z
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)
    / x: T# w  u/ p2 z) ~% V
  853.         uint16_t size = WiFi_GetBlockSize();
    & r! h+ D# O3 l  x( q, D, L: c
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);) Y( m- g# H/ L: {5 j  x
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);5 J$ j. m9 v# p# Z' k
  856. }( \5 m; b) q; |8 ^

  857. & L6 v' L9 m2 I$ I
  858. /* 设置密钥 */% F- ]2 M, ~( }7 i$ E1 X* z+ h
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
    . t, R: S; U) h/ b# x4 }
  860. {
    1 O1 k. e: r& R. W0 l
  861.         MrvlIETypes_KeyParamSet_t key_param;
    9 k) C" [* y! E# s
  862.         if (len > sizeof(key_param.key))
    " S' m! U: @/ k( X( g
  863.                 return CMD_STATUS_ERROR;3 |' x- b2 c& e4 k3 L) h
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;/ \  v3 m! H3 s7 z
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
    / Q7 C/ t1 A# p& f8 A0 I7 @
  866.         key_param.key_type_id = type;
    * ?7 u$ v& c/ r  U, B3 W. ^+ _+ V
  867.         key_param.key_info = info;% f6 u4 j- w" q$ o% O* z! C7 K! i
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info. u0 o7 r" k# E
  869.         if (len)
    ( o- N* d$ ?7 L4 H, `
  870.                 memcpy(key_param.key, key, len);
    5 a5 X; E5 ]7 c1 |! Z: x  o( G5 c5 [
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    9 w. F! J0 A* Q8 H9 r
  872. }" o: b( c2 w! H! d' ^
  873. 1 ^: C" S; I9 h, ^6 U$ u. e& n# }
  874. /* 显示WiFi模块信息 */" d/ Y+ u7 S( F/ I
  875. void WiFi_ShowCIS(uint8_t func)
    0 e5 A. d* m0 z! v5 n/ x# d8 y6 x
  876. {+ ~! p+ K  g) t1 r/ T) J; i
  877.         uint8_t data[255];5 g5 f* P5 E: n! ~
  878.         uint8_t i, len;
    ' b" x' Y. g- U( _
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure
    + C& `) K/ Z( J" t" a1 ?; p
  880.         uint32_t cis_ptr;
      h# O# Z7 I9 O( h, X% S. j* I; z
  881.         
    ; S: m1 q1 p# m
  882.         // 获取CIS的地址: Z; y8 f' W2 X+ Y' G$ o
  883.         cis_ptr = (func << 8) | 0x9;2 I4 G; r9 s3 S  Q  w6 k6 g
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    1 A* J. V: p+ W! q' q* ^
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);9 i+ w& ]! p+ b4 p7 T0 b; t% l6 j
  886.         
    0 W' @+ t/ L* e$ h1 x3 H2 F# A; e
  887.         // 遍历CIS, 直到尾节点
    + E5 S; B8 Z; q3 ?
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)
    ) r. ~' Q$ j! M, ^, Z5 p
  889.         {$ f! p+ y  m. E2 [0 Y/ U; B
  890.                 if (tpl_code == CISTPL_NULL). F( b: Y. R) u& H, w. h! b
  891.                         continue;2 U1 o4 Q5 l& C" e& \1 V
  892.                 ( I! n# c& ?0 D" }! ^
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小
    * K  h4 R+ q8 [- I+ {6 v* \5 O
  894.                 for (i = 0; i < tpl_link; i++)
    4 t4 o) c, R* k
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    $ C3 [* B( g5 a5 U) A
  896.                 6 R, ^5 {( ?6 a. ~  \& E
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);
    ( Q9 I& _: Q7 O5 m/ ~1 |8 b
  898.                 dump_data(data, tpl_link);
    ; t, E; {. Z. j
  899.                 switch (tpl_code)' a8 O+ o+ g/ n. h) ~
  900.                 {6 x+ p3 D; |- e; k; _3 V
  901.                 case CISTPL_VERS_1:
    * N( n# X! ~; g" P+ T
  902.                         i = 2;# w* x$ \4 O1 }/ P6 n2 X" L
  903.                         while (data[i] != 0xff)
    - H- C) c6 U* f1 G/ `( m2 C
  904.                         {
    1 D3 v# q. W% P; l
  905.                                 len = strlen((char *)&data[i]);) A# Y7 h4 b, |' G2 V. n$ b2 W
  906.                                 if (len != 0)
      ]- z4 `# j1 M" m
  907.                                         printf("%s\n", data + i);
    * }" |/ _; `  h8 |9 W8 K- B# \
  908.                                 i += len + 1;
    7 _0 n, k. ?; G, W+ x  v
  909.                         }0 [; @; ^5 o) L0 H) P
  910.                         break;0 p  l( e$ ^$ d1 ?* f
  911.                 case CISTPL_MANFID:
    : c; `9 s1 P% g6 d
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple
    - @5 k- k" n  p7 O3 k0 ~9 e; s
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
    4 k2 K* l  @6 Q+ `
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD$ Q6 W! ~# L, a8 E% r
  915.                         break;
    6 m, G- G4 P) W' f; z1 m  A
  916.                 case CISTPL_FUNCID:
    2 }5 [- J( J- G- i2 ]
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple% M* L% D5 m! S% L, `
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
    ; m# C" N# |+ Y& P' N
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT
    ' W  O2 Y! f' i8 n
  920.                         break;2 {/ Z; ?( `2 \3 i8 Y
  921.                 case CISTPL_FUNCE:
    ; @2 H: l8 ]2 H( C7 P
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple
      V" r5 ?4 k4 ?4 v8 ^9 }
  923.                         if (data[0] == 0)
    / m- P& G1 Y. S1 K
  924.                         {
    . s% l7 n5 S3 `+ c3 O
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)
    ) r6 s9 t% z5 e6 f! e
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));( }& J( l* ~5 f7 D5 ^: v: @5 w4 v/ w' l
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);
    3 @8 x) a& D6 b' `' p, ]) @
  928.                         }9 p1 u. x; w# S
  929.                         else8 h* @" w; F4 `# i0 }5 s' K* V
  930.                         {! v! N: n, a( K$ X+ ?5 m9 Q
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
    # i; m9 }& q6 k" T
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
    + m& y4 g2 F% _) Q, ]6 ~" Y6 a
  933.                         }; I+ o1 @) m* @3 r/ ?) |) w6 w
  934.                 }
    : X2 K! b  P- p6 t
  935.                 + E5 x5 ]: M' I' _0 t
  936.                 cis_ptr += tpl_link;
    7 c, C) ]& Q; _) o( z  p
  937.                 if (tpl_link == 0xff)
    6 |0 e4 t; {0 l! b
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点
    # G; n; O! s( w/ e! V4 n& x+ n% m" m
  939.         }
    * @0 x+ |- b1 J" l% K6 p
  940. }
    , |: ~/ N" i' A( }9 o
  941. ) a; `4 N* G. T% ~" A) M3 k% Y" u
  942. /* 显示所有密钥 */
    1 d" L3 U1 b9 N1 w( B+ V* `. O0 i+ E
  943. void WiFi_ShowKeyMaterials(void)
    , {! ]1 l1 t6 s/ q
  944. {0 g7 I- z. @" Q1 k2 y! g& i/ g
  945.         uint8_t buffer[256];
    4 K& \! `* N( c% z
  946.         uint16_t size;9 o+ r; `# ]% c& a9 u% N5 l5 M
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;4 F. P3 O! Y1 }( ^6 Q( u
  948.         
    - K# [6 b+ d6 p
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);
    4 k4 [3 I5 W: ?8 i2 p# u4 K: h9 @
  950.         while (size)
    ) K9 B5 i6 v) X- J& l$ T
  951.         {& s8 l9 W% E5 p* S* G. R
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
    $ c+ R) Y) @+ Y2 o) W
  953.                 dump_data(key->key, key->key_len);
    ) W" r) }& J) ?7 E0 F4 k+ b, c
  954.                 size -= MRVLIE_STRUCTLEN(*key);
    1 H+ j& @) @* Y% x/ H. v' @
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));+ ]. U- `4 P: Y1 Q
  956.         }# r" b$ R2 {2 A
  957.         if (size == 0)# Q* w- E. S" @1 H$ C9 e
  958.                 printf("data end!\n");
    ( @8 O1 \# T6 {4 i
  959. }$ B/ g: {; |; ~4 A& S
  960. ) R/ ?. m7 a) ?/ \3 l0 j
  961. /* 创建一个Ad-Hoc型的WiFi热点 */
    * @7 v/ Z! |6 E- {, J
  962. uint8_t WiFi_StartADHOC(const char *ssid)2 p( G  t0 f. j8 m) G
  963. {
    : n5 i: F. ~; O2 i
  964.         WiFi_CmdRequest_ADHOCStart cmd;
    0 k% O  H% X( e/ m% {" m
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
    % ?' w3 ]/ p; e9 D
  966.         & z2 _- v) |, L, G. C- M
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
    : y: W/ ]6 I) k; O5 x
  968.         cmd.bss_type = BSS_INDEPENDENT;& S: v1 T$ |# P
  969.         cmd.bcn_period = 100;2 T- ]4 E, o" C3 `4 \; m1 \' w" g
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;1 Y6 d2 y" B' B
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);
    0 g! s2 S% i: V, w4 M% i' `
  972.         cmd.ibss_param_set.atim_window = 0;
    4 I( x/ C: d0 f- \" B
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;6 h/ ]6 j: o7 i7 A8 B
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);/ _% g# q0 s+ G; q: y' P4 M
  975.         cmd.ds_param_set.channel = 1;
    5 s; Y( m7 V, g5 B6 U
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;; d, E7 f+ i2 A
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;$ b& l+ S, W6 u3 P% H  z
  978.         
    % Y9 f2 q( w6 x  L# w# |9 {. n' }# p
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
    , B1 a& n4 m) r. c0 X
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));0 ?7 j  C' z8 u  Q/ F
  981.         return cmd.header.result;" P# U' H* r# h2 A
  982. }
    2 P. L2 p7 Q' ^/ @2 i; k) |! \  z
  983. ) S; B( H4 D6 Y0 e1 s
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */; _$ ~- I' x9 r2 U. i; I
  985. uint8_t WiFi_Wait(uint8_t status)
    8 \: u% ]' r& R6 D- D7 |- u5 G
  986. {* Q4 j2 z0 ^: M! K4 t% X7 B0 A8 u
  987.         status |= WIFI_CARDSTATUS_IOREADY;) p, w* z! U" I2 }8 t* w5 U7 `
  988.         WiFi_PrepareTimer(wifi_timeout);
    : S* T7 u. y$ s* F0 ^4 t
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)
    ; H( w: ^, D. n1 P6 v. [# ^
  990.         {! |! V. Q8 e& }3 o
  991.                 if (TIM6->SR & TIM_SR_UIF); v7 l0 `/ z1 a! r. M' ~1 @
  992.                 {
    - l5 M' o- O' s
  993.                         // 若超时时间已到
    3 y# s  q$ H# Y% r% I- m
  994.                         TIM6->SR &= ~TIM_SR_UIF;
    " }0 s8 I; a' R/ B+ g
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);2 O3 x( x" p8 C7 a0 d4 ~
  996.                         return 0;
    1 _0 b# o! h; T+ u! E1 t
  997.                 }
      h0 O- S9 E; y7 f* m4 M
  998.         }
    . S, z5 V& l3 J( Q$ r
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器
    5 V! o7 b" U: F0 s) L% e. q2 \
  1000.         return 1;) H" _2 ?  ?/ v
  1001. }$ H- b! x+ ?8 G. ~% `

  1002. & X1 k# h2 A! [4 o
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */+ W3 J5 A4 b5 l" x! v) _
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)
    $ y, ]5 N9 v+ V' q" b  `
  1005. {
    0 }' S% V6 [0 n' _+ [( Y
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);& T, h7 R$ T. n& W  K, o  |: D
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)
    0 }# D; v) Z* f! z$ H* r) s- m
  1008.         {9 w  u) o7 S% a+ c/ C7 q
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;" W$ F  V2 t* Z' o" P* M. G
  1010.                 return SDIO->RESP1 & 0xff;
      i' x( o5 Q/ }  J
  1011.         }
    6 P2 Q3 z7 f) K. r/ v# x
  1012.         else6 E, Y5 v% U9 P# N( |$ w
  1013.         {# f$ |# A9 _9 D* s
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);$ |# h; [  U1 b7 \- Y7 L9 x
  1015.                 return 0;6 G8 Q1 w# c5 y6 @0 s$ R( Y
  1016.         }1 G5 o9 r5 M, _7 U* C# p
  1017. }
    4 R# s9 }: `' z8 p- u

  1018. 1 s/ d# B7 \% a  _0 M
  1019. /* 写数据 */
    3 J6 J8 P8 Y* Z1 @
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
      d. |: u1 v* \7 E, M/ F  c
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    ; h* V" t0 y" m
  1022. {
    ' L. t0 ]3 `3 w5 c
  1023.         uint32_t len, temp;
    " d4 f5 ]) |% S$ F8 Z1 a0 e
  1024.         if (flags & CMD53_BLOCKMODE)6 ?0 F" O/ R4 n/ Q  R
  1025.         {/ R! v6 ~* A' z( r3 l
  1026.                 len = count * WiFi_GetBlockSize();. {6 t6 ]  {; m! J2 `
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;
    $ i! Y4 I7 O' w! g$ s+ L2 }% K1 \* A
  1028.         }6 _. b# k' F0 I9 k6 P4 H
  1029.         else
    0 P5 N5 t6 m# i' K( T3 O! C- k* r7 k7 @
  1030.         {" q1 V5 }- b7 V# j
  1031.                 len = count;
    ( E4 E% X  ^; P% n9 h# v7 H
  1032.                 if (len % 4 != 0)
    ! r# m4 M3 ~7 y  |6 q4 O0 o( @9 `
  1033.                 {5 e( B; L: }* Z4 I) V
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍: W9 Y% @; L. t0 D" ]
  1035.                         count = len;/ h, X/ ^& j; K) g
  1036.                 }$ A3 x0 l/ M9 p  s5 S* q% R  _
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    $ W! j) f% S/ P, D2 w" N* _' k8 U9 Q
  1038.         }; I+ z" z" ?0 Q- u' B) n1 n( K
  1039.         SDIO->DLEN = len;
    4 i! J& h7 o$ n% ^
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块# Y& D8 F9 i4 N, K
  1041.         
    2 M- {0 ?& ]0 n. _# M
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);; q. \: D( z; @  G
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);
    ' h: R/ o% b" W! T- j+ x2 K5 S
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0)* B! h- h. Q5 u- z! H1 `! M
  1045.         {
      G- w, V! m! ?
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");3 v* @! g1 ^! P4 y7 m' Z) W
  1047.                 return;
    & b- x& [0 A, m6 n% L3 i6 E+ x
  1048.         }$ h5 @+ o5 H. H9 ?
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;
    * B" P) R+ U* b2 H1 O$ j
  1050.         
    & z1 D% ~- d; `/ `0 P* x
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据5 |0 l5 n: L0 \$ ^
  1052.         while (len)
    - H1 E& o% ~0 b- H( J
  1053.         {7 c/ z" p/ W2 l( @) E
  1054.                 len -= 4;
    ) O/ o0 u9 g: j+ u. F6 ?7 Z$ h
  1055.                 if (bufsize >= 4)
    . e  _- b  p. }6 K
  1056.                 {
    * ~) J: ?3 r- Y# e
  1057.                         SDIO->FIFO = *(uint32_t *)data;4 Z# T3 h* c& Q- h. C& w
  1058.                         data += 4;
    . k( H) {' Q1 l! E7 d4 ^, G
  1059.                         bufsize -= 4;
    - M8 c  g* P8 S! v$ {' J+ R8 d. J
  1060.                 }4 N  ~6 t/ N# @& u
  1061.                 else if (bufsize > 0)
    ; p* q) j; p# R# P5 N1 G5 J
  1062.                 {
    ( @$ w, R# r( i
  1063.                         // 发送缓冲区最后1~3字节7 d+ O7 U! C! u/ V5 |+ J5 j
  1064.                         temp = 0; // 不足的位用0填充+ K0 j7 P) o$ f. X  Q
  1065.                         memcpy(&temp, data, bufsize);
    - ~  ]0 p( `+ @2 w7 ]4 @8 s
  1066.                         SDIO->FIFO = temp;8 ?$ V9 W+ Y6 z: v
  1067.                         bufsize = 0;
    5 e; ^6 ^' x4 u& a: H2 m, o
  1068.                 }
    * j! Q/ u& f5 m9 Q7 C2 @/ V
  1069.                 else
    . W4 L$ A- O/ }" M
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0+ a9 Z# a* L, I' E/ C2 Y. W
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待3 t. q# |2 ~5 u4 [- B4 b: Z; Q, U9 ?
  1072.         }, w8 Y1 I* L+ }' y& }
  1073.         3 U: q, j* n/ _. B; q9 {3 v
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕
    ' f) Z% [& I6 e9 `
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
    ; S, x3 ]8 B+ j9 U
  1076.         * T( M% H& a# N4 E( d; ]
  1077.         // 清除相关标志位. F5 l1 ^/ V8 [, S( I, f
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;
    9 z/ c. M6 o2 ]' k# E- s3 Z& B
  1079.         if (flags & CMD53_BLOCKMODE)
    , `3 S' F+ Q9 k3 i! |6 w& u  o
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;, V5 Z" }; K5 k+ [3 e: b9 K
  1081. }( F  h5 w& v& f4 W

  1082. ' p: o! A# t" |3 Z. P: s3 b& H# x* F
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)7 m4 A. s% h. q9 J7 s5 h( L
  1084. {
    8 u3 d9 y. j; N, s9 N' t
  1085.         uint16_t block_num, block_size;  ^, @! R! J9 s! n5 @
  1086.         block_size = WiFi_GetBlockSize();, o' D3 E6 R6 }4 M0 e: o8 ]% M; K
  1087.           E8 K. o( O7 w, T3 P; ^* d: l2 C
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    " N6 z7 @% m4 g6 {8 F+ l" \( S
  1089.         if (size >= 512 || size % block_size == 0)
    ' ?) X+ [6 d/ Y. i2 [
  1090.         {, v0 P( }* F3 i8 x- y
  1091.                 // 采用Block模式传输
    - T$ z& C" X3 I' k" t8 ~( l
  1092.                 block_num = size / block_size;3 B+ b9 I, ~9 Y* W9 e
  1093.                 if (size % block_size != 0)' B, Z& R# ^8 S5 @
  1094.                         block_num++;
    " ?9 |4 F1 A+ ^
  1095.                 ) z# Q( z0 V, C" N
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);
    / `4 O* n, {* A: c, D- a
  1097.         }0 C$ K% A* q2 p8 |5 C
  1098.         else2 ?) i* j: S! l+ l2 E
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);
    , i/ N- m: L( A, R2 F" P
  1100.         return SDIO->STA == 0;
    / L- D; r+ y+ b
  1101. }# `3 V3 _1 \* J' K8 z
复制代码

1 V6 u" B! Z  A) R1 v6 ~$ @9 [3 d4 _) A* m0 B3 L0 O# N6 m, I  l
在工程的所在文件夹创建一个lwip文件夹。9 {0 K* b$ O8 y. _% [+ g3 q& j7 C
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
1 j  P8 Z- I- I8 V# n& C: z/ ]5 N) U& r: \, P4 l0 T, D
core/
1 p) y# a# {7 p  n4 M1 ^5 s1 G: rcore/ipv4$ F9 s9 R) q! h1 D- w) y. R9 `. ]
include/lwip
" t  R$ Y7 [& z, G+ ^include/netif
  s8 A& U4 F0 G" A* Wnetif/ethernet.c
- a- Y3 _( @1 l6 e. {7 B/ u0 F. unetif/ethernetif.c- ^1 k6 H3 C2 K( ^5 b3 f+ O) x

- B. V% _  H) t解压后,将里面的c文件都添加到工程的lwip分组下。
  a/ R8 C' @& j+ T; `具体添加的文件请看下图:9 U9 `) L7 t8 r( e3 ]; ~. D

5 C/ A8 P7 N% i. q/ T
: Q+ U3 P6 B& Z5 f4 r3 C接下来,创建lwip/include/arch/cc.h文件,内容如下:0 K3 K* F3 ~3 o0 z
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:  V0 Z& \% O( A% N( e0 n; p
  1.     #define NO_SYS 1 // 无操作系统  ) u* w0 D2 {3 S" z
  2.       ' h! g! X3 q- \9 o4 A  {$ T
  3.     #define LWIP_NETCONN 0  ' R& L, {( K1 t6 V; T
  4.     #define LWIP_SOCKET 0  . R9 v0 I# K. ~/ z2 E
  5.     #define LWIP_STATS 0  
    : I2 `$ v5 C" \* g3 m: J1 d
  6.       3 G9 v: _2 m7 P- a' _4 J; ^4 c" p
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  
    9 x4 x" ^$ c0 s6 k7 h# M4 G  H
  8.       
    0 y9 o0 E: A% Y' a. g( ~4 {
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:  m. H! E; }8 G/ @# d* v- x
  1. /**7 @+ P" D1 U! R
  2. * @file
    7 X( |/ u1 t; ?
  3. * Ethernet Interface Skeleton
    & J8 N' h$ K! F0 |% ^6 E0 j
  4. *
    6 g4 D. N) O  [2 T
  5. */
    2 Y! i9 n! A  b+ B% @4 p4 O

  6.   j) v( Q# {2 W6 W4 |% f
  7. /*1 e. n' Y2 d  G" b$ C* f
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.. }3 Q: V* H3 G
  9. * All rights reserved.
    . F+ P- z) `# Y  O
  10. *
    8 A/ e1 A8 x8 l+ l6 Y( S
  11. * Redistribution and use in source and binary forms, with or without modification,6 m4 B) P$ C0 m6 v5 W
  12. * are permitted provided that the following conditions are met:
    ( M  ?" `" p, J8 |+ ~' W! x) E
  13. *5 p6 [  {6 ^6 X. e  U$ p" Y
  14. * 1. Redistributions of source code must retain the above copyright notice,* x, C1 g5 j5 j3 \1 x) a
  15. *    this list of conditions and the following disclaimer.
    , V  ]$ A# U2 X% W0 w8 s1 V; j- t
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,
    & ^4 Z  y8 B0 ~! T# u+ O
  17. *    this list of conditions and the following disclaimer in the documentation3 y. e% u3 s8 N- v
  18. *    and/or other materials provided with the distribution.
    7 h7 w, n: L: m0 S6 d& l( m9 A+ W
  19. * 3. The name of the author may not be used to endorse or promote products
    . [* Z6 f$ t$ s5 H7 T
  20. *    derived from this software without specific prior written permission.
    + D7 e8 J( j2 y. d+ [
  21. *
    ' @* H" v- m( A! ~5 ~$ s! U4 a
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    $ }) f. O8 j* m
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF( c8 j9 s3 d$ J/ Z- U: d! L
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ d! i+ Q, T' K7 v* A
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,: ?" ~* s1 Z. t, z/ }8 r2 H
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  L2 G7 I9 L, j; J& u; t( U* G
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    ; k: j1 L" |$ a4 Q
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    ) X+ S# v/ d2 d6 Q
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    " P3 S! X# G9 ?3 u: z, `- y
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY' }: a' }# J8 W3 F
  31. * OF SUCH DAMAGE.8 k. G" m) |, K4 E; y8 |4 l/ N
  32. *; L& l8 @2 v+ ^4 h' Q5 \
  33. * This file is part of the lwIP TCP/IP stack.
    1 k7 v7 s' Y3 B; V! a3 t; v
  34. *
    ' E. l% q4 Z# S( j5 {
  35. * Author: Adam Dunkels <adam@sics.se>1 x9 V1 N! ^' A/ h  V/ A
  36. */ X+ Z* O8 Z$ O8 A& V& V
  37. */
    5 A' k- P2 v; A3 ?/ i

  38. " k5 |" C: K  M
  39. /*
    7 e! |0 ~0 N5 I3 d
  40. * This file is a skeleton for developing Ethernet network interface* z0 R+ g6 |( d2 E2 X
  41. * drivers for lwIP. Add code to the low_level functions and do a2 \0 E2 E+ x( J* p: h) W  ^8 F7 u. _
  42. * search-and-replace for the word "ethernetif" to replace it with
    # K' B% u( j# ~% d
  43. * something that better describes your network interface.
    ; l& E3 n- T3 u5 H) T* Z6 J$ A
  44. */
    . V# n) ^" J% [. V' ?/ R  b
  45. , Y% j/ B( T8 U" s
  46. #include "lwip/opt.h". p2 I% M1 t8 ?  T9 z
  47. ! {9 I+ j* y. @4 }9 t
  48. #if 1 // 允许编译器编译该文件
    ( E1 R& \/ w  y8 N8 d. S0 ^+ P# g

  49. & D# s  K* Q+ H6 y
  50. #include "lwip/def.h"' r; l+ p' z6 r6 I. @
  51. #include "lwip/mem.h"
    6 q% L( `2 `" E0 N
  52. #include "lwip/pbuf.h"
    5 I. H3 Z( ^$ E) R, F
  53. #include "lwip/stats.h"
    . [$ n8 c$ P% M7 y/ S
  54. #include "lwip/snmp.h"
    9 O6 f) ]; `. r4 a
  55. #include "lwip/ethip6.h"8 O) ~1 C, [; M8 D+ Y7 E
  56. #include "lwip/etharp.h"* M  K, [) R1 }! h+ D7 }: \
  57. #include "netif/ppp/pppoe.h"0 c) o2 ~. P# _/ U

  58. ; @, ?( m4 J7 B6 `
  59. /* Define those to better describe your network interface. */5 F$ e, ~7 j  H' P* S& b% D
  60. #define IFNAME0 'e'* c& V3 U) }' D( Z0 J
  61. #define IFNAME1 'n'" Z6 Y) y* x8 v/ J" J$ D3 P0 b

  62. 3 k! U: B2 y- {0 q8 v6 u, Z& N1 M7 S
  63. #include <string.h> // memcpy函数所在的头文件4 l3 [5 ]1 d+ j& e' `( ~
  64. #include "WiFi.h" // WiFi模块驱动程序头文件
    - @7 Q* ^' i2 m% _3 o; E& J
  65. & p" x4 r6 c; b7 I# q! B
  66. void dump_data(uint8_t *data, uint16_t len);$ z" A' B% i/ U  h

  67. : v  N3 G7 ~, w8 ?+ Y
  68. /**8 V* Y- o7 k' T! ~  g  R- i' P
  69. * Helper struct to hold private data used to operate your ethernet interface.
    ! n! K; y. X% V4 Z0 j* N& G' ]! s  \
  70. * Keeping the ethernet address of the MAC in this struct is not necessary
    " M7 [. z. e7 U. J
  71. * as it is already kept in the struct netif.! X) e  J5 `8 Q/ i
  72. * But this is only an example, anyway...$ U3 b" v0 O4 Q- t, p' R9 l
  73. */
    2 L: s$ ~4 {/ c* p
  74. struct ethernetif {
      T8 J0 H0 u( E
  75.   struct eth_addr *ethaddr;- P' |9 v& x8 p; h$ k
  76.   /* Add whatever per-interface state that is needed here. */
    , ~5 Z, G' C3 `0 c5 y* M+ p3 i3 H
  77. };. K# z; _) S& s3 X& O6 }
  78. 5 s4 w3 J" k: L
  79. /* Forward declarations. */. a: d2 v, H, e/ O- \# P* U: I
  80. // 这里必须去掉static
    , a2 Q7 m# ?( K" I5 w! ^4 H: _
  81. /*static */void  ethernetif_input(struct netif *netif);8 a5 C0 B! y5 F
  82. + A1 }  |8 @/ q7 V0 i6 l: h2 O/ M
  83. /**8 S- l3 b' o) _$ R; i! i, U
  84. * In this function, the hardware should be initialized.
    7 E+ h% q* O# ~* {5 }4 D& j
  85. * Called from ethernetif_init().
    5 |. o. m7 B" J4 ?
  86. *
    7 ?. L7 T, e- n' l! X2 M" o
  87. * @param netif the already initialized lwip network interface structure
    0 @  V1 _" }! n9 |5 V' o$ i
  88. *        for this ethernetif6 {& |3 U# W/ C- h3 a0 e/ x' A6 D
  89. */: y/ Y& s7 s% y
  90. static void
    % f% L+ R' u: L$ f
  91. low_level_init(struct netif *netif)/ Z% e% K  V0 ?1 v
  92. {
    + z! R9 u2 C+ N5 y: \' @
  93.   struct ethernetif *ethernetif = netif->state;( U+ P' G/ M! L$ C$ f
  94. % E. p4 j4 F, A7 E  J  [
  95.   /* set MAC hardware address length */
    % u4 s0 |- [( N1 B$ C# R3 o; i. t
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;: c; e! U6 S/ G1 H  G0 J; R0 L

  97. . b4 Q" o9 R, K( |) ~, R7 h
  98.   /* set MAC hardware address */+ X2 ~% G+ ?; E2 `/ `
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
    9 R1 T( q! O& M0 `4 T
  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]);& A- v& U- z1 H# W& Y/ ]! H

  101. 9 A1 P" X$ `; S
  102.   /* maximum transfer unit */
    + G% h0 v* I) t0 T; `4 Y) h! S3 p
  103.   netif->mtu = 1500;
    . \$ {8 l: s% l" y2 E; b  }) I

  104. & t9 T) z0 b( k# b' e/ [
  105.   /* device capabilities */9 Y  A, V; x3 O0 i
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */* u0 L& J) d1 g: p3 v1 T2 Q
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
      Y; A, \* w' c& @  C: h! O/ W6 c
  108. 0 h. }3 t1 }- a$ Y. R
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD
    3 c1 B% ~; h+ M- ?# l  `4 g7 D( i# |) s
  110.   /*7 I! t" M4 v4 i
  111.    * For hardware/netifs that implement MAC filtering.
    $ s* Y: ?) Y/ c% r
  112.    * All-nodes link-local is handled by default, so we must let the hardware know2 f! P. w* U) e+ A" j  Y9 U( Y
  113.    * to allow multicast packets in.$ N; o8 u- x6 [( v
  114.    * Should set mld_mac_filter previously. */
    ) i0 H9 [/ _7 M$ g9 P6 {
  115.   if (netif->mld_mac_filter != NULL) {
    8 U% M) P; U0 i$ H# R* L
  116.     ip6_addr_t ip6_allnodes_ll;3 L- {2 P8 w. c1 p1 v
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);( j' ~# T1 q# @2 ~% j
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
      q# o  B/ g  [! K
  119.   }
    2 F% R4 }* b- p# S9 k
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
    1 }) h" u/ j% W+ i0 V& b

  121. ; o  e- r% Q8 v1 d" y+ @7 u! C2 L
  122.   /* Do whatever else is needed to initialize interface. */7 j0 P! O% S; H  D6 T$ ]) i
  123. }
      W" V0 O5 C6 C
  124. - @/ Y* W  z. C0 c, @, Z
  125. /**/ G" V& o8 ?7 }; J
  126. * This function should do the actual transmission of the packet. The packet is
    & T  r. k7 j" D) p2 p& Z+ d
  127. * contained in the pbuf that is passed to the function. This pbuf
    1 j+ ~, `4 N3 U- N8 L9 O8 Y
  128. * might be chained.
    8 s( \1 V+ G. h% V
  129. *
    * |4 f7 S5 K2 L- G8 Q" I
  130. * @param netif the lwip network interface structure for this ethernetif; ~1 x7 y# @" V' J$ \# H4 k
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)6 e/ `* N8 S4 b% H6 W
  132. * @return ERR_OK if the packet could be sent
    $ }5 B4 O! m' G% B, a7 T
  133. *         an err_t value if the packet couldn't be sent
    4 a2 g9 B/ h; D, Z
  134. *  H+ V/ y; [4 }1 B8 t
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
    7 ~" x; [( n7 M! N, i
  136. *       strange results. You might consider waiting for space in the DMA queue' }: o& u/ y# |6 g
  137. *       to become available since the stack doesn't retry to send a packet; x9 t5 m% Y) {
  138. *       dropped because of memory failure (except for the TCP timers).3 z9 I$ k: w7 ?, w- \1 Q
  139. */$ V4 c0 |; t! L8 N

  140. 9 ]+ w' n$ U1 X+ l6 N' m7 \
  141. static err_t
    : S; q" a! D  A! I1 Y8 i0 }6 X
  142. low_level_output(struct netif *netif, struct pbuf *p)
    6 J, o+ E! U7 A: n$ B
  143. {+ L* |) S9 J% t7 ~, X
  144.   struct ethernetif *ethernetif = netif->state;
    ' O9 L0 D8 M/ E0 U+ p6 r( I) t; w
  145.   struct pbuf *q;
    " S/ g7 F6 Y5 L0 O7 u
  146.         6 }4 L4 }' N8 Q7 L" L0 U1 S
  147.   // 添加的变量
    & m7 @/ _) ?0 O1 Y
  148.   uint8_t buffer[1792];2 T# `. @1 z7 P5 p& e' t
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;
    4 X) g1 ]1 c+ g1 @8 ]$ `- L* e
  150.   uint8_t *bufptr = packet->payload;
    " T. w, _. `1 I/ n( C! M- C
  151. 8 Q5 d% K8 B; L
  152.   //initiate transfer();
    + R1 O# z* o6 q6 G) q7 X7 U# Y! s5 ]) }
  153. 4 X- F  d2 J* s; [  F8 z" r
  154. #if ETH_PAD_SIZE  w+ |, O) j5 {4 p
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    , Z2 l7 o* `2 l) N. _# I
  156. #endif
    " x0 ^5 T* c- J% q8 }" a
  157. ' D& }1 ?6 B  B. K# L1 o* Z( Q
  158.   for (q = p; q != NULL; q = q->next) {5 l1 C5 S4 q. s4 ?
  159.     /* Send the data from the pbuf to the interface, one pbuf at a+ w, H% e- z9 |5 [( I: E( |
  160.        time. The size of the data in each pbuf is kept in the ->len/ r# i" {' |: Q! ~$ W! m
  161.        variable. */
    4 t0 z' T$ V) \0 j. y- n
  162.     //send data from(q->payload, q->len);
    0 D+ n* j2 x, c: }: |; K  V
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容+ I8 R! i4 ?8 U6 i8 ?) k' Q
  164.         bufptr += q->len; // 指针前移3 y! s% }1 ]% K$ D2 p, x
  165.   }
    . O$ v# d% M2 b1 m9 h& }2 U

  166. 1 I9 ?' K+ I  S8 S4 [) ^
  167.   //signal that packet should be sent();. \, p, ~& h; Y, R  c
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包
    , p9 ^. |0 Z; y7 i5 ^* {* r& w
  169.   ; @/ Y* K" O4 z- j! E- {# O
  170.   // 打印数据包内容" u$ \, H- n3 R1 M3 @. {/ P4 X
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);
    & j8 m4 V6 I4 h, ]. h( `# [: M
  172.   dump_data(packet->payload, packet->tx_packet_length);
    5 R4 \" @1 n1 n0 ?9 R7 l. g
  173. # ?; ^4 o& D  O$ B: I) r+ K
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
    * ?7 n) o4 _# A) `- R+ Y. }
  175.   if (((u8_t*)p->payload)[0] & 1) {
    9 ]& y# i8 r) U1 P* m
  176.     /* broadcast or multicast packet*/1 p. d0 J" d) C2 r' r7 s
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
      O9 n( \* ?) G" }0 L! m
  178.   } else {6 x$ y9 u3 a) ]
  179.     /* unicast packet */% _% W" G. `6 @% L
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
    * m& U+ ^% H, h/ \; n2 M
  181.   }
      d& [( }2 q& N( q' L
  182.   /* increase ifoutdiscards or ifouterrors on error */6 C2 R8 P) I3 K% ~4 i, `% ~8 F

  183. , m! A0 l! h, |; l
  184. #if ETH_PAD_SIZE
    . [  W/ m4 ^0 K3 Y! v6 J: Z9 \7 D. F- R
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
    * n& U$ ^; [, g8 Z, ^
  186. #endif
    4 a% j; e! W8 d& v6 K

  187. ; z# T6 i& ~: E1 d* z+ M
  188.   LINK_STATS_INC(link.xmit);8 R1 K( I% F! |/ F
  189. ) L' e, b, k9 B
  190.   return ERR_OK;( {3 K- A0 ~' J" v! N% j
  191. }0 `" v+ H' A7 ]6 u6 m  H

  192. ; ]) D, w8 G# W
  193. /**
    ' T) S9 Z- ^7 ^& n) n
  194. * Should allocate a pbuf and transfer the bytes of the incoming+ u; l- u2 E+ ^5 [& I) s
  195. * packet from the interface into the pbuf.0 `) T7 ~! @" ^5 x4 ^, ]
  196. *! B+ j' y: x% X2 R7 S# p7 C
  197. * @param netif the lwip network interface structure for this ethernetif) Q, q. V9 c# n' g' t& T; s0 x, h
  198. * @return a pbuf filled with the received packet (including MAC header)7 s/ {: V/ j6 {; [+ A% s  h
  199. *         NULL on memory error2 G' f: }+ @  B& d5 ?9 F9 ?; Y* x6 ]
  200. */8 m7 j1 Z5 g  _; T8 G$ o
  201. static struct pbuf *
      S% W7 e7 i# m
  202. low_level_input(struct netif *netif)
    ) X$ H! D$ c! Y6 L3 f- ~
  203. {
    5 K. ?. a# K6 t4 b
  204.   struct ethernetif *ethernetif = netif->state;
    0 x, S1 c& h8 r( Z+ |
  205.   struct pbuf *p, *q;: ?" x6 @( V, P8 ?0 M
  206.   u16_t len;, J' o4 u) Q7 W$ n- O
  207.         
    . z8 e* G( o# n9 G7 @& U
  208.   // 添加的变量0 Z$ X: W4 {3 W
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完
    ' ?% X2 [. I4 ]8 w
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;% \5 Y- j/ N0 x4 k) V
  211.   uint8_t *bufptr = packet->payload;
    " S2 G( R/ s) [5 X0 c
  212. 2 ]0 i0 i( v: Y! ^- V
  213.   /* Obtain the size of the packet and put it into the "len"0 B* U- z# B2 M3 C8 O6 Q* O. w
  214.      variable. */  q& {7 H1 N, Z" g% h
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
    ' B$ T. s7 L% F( r# h$ ^4 r& _
  216.   if (len == 0)+ [$ P8 J5 ^& f0 l( S$ _; Y! e7 L
  217.   {
    - c" s1 c& u& n$ Z" f! _
  218.           // 若读取失败, 则不分配pbuf, 退出本函数
    2 m6 C/ q, B2 }2 x6 U1 ^
  219.           p = NULL;
    ; l, ^2 g& s5 v) y
  220.           goto after_alloc;
    2 z' R# i% D, h0 y' s
  221.   }0 ^# ?) {/ _2 K" L8 n
  222.   len = packet->rx_packet_length; // 获取数据包的大小
    4 _* g& R) q8 I/ I" F
  223.         
    4 x# K" o* @" F/ g) f, _, n( e
  224.   // 打印数据包内容
    " X0 o% g3 G9 [0 k( Z# A! _
  225.   printf("[Recv] size=%d\n", len);- ~! E+ }  |( D  E$ G3 U
  226.   dump_data(packet->payload, len);
    , n+ V3 {0 P( r, r% O" `) c6 r
  227. 0 U1 S" _0 Q0 J+ o. I' i  s
  228. #if ETH_PAD_SIZE( B! A3 C5 `! {2 t5 ?
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */( I  X& o% W. c6 L) M: T: W
  230. #endif
    ) V5 @" V$ G# F
  231. , B8 d$ X, n4 s; ^% q
  232.   /* We allocate a pbuf chain of pbufs from the pool. */
    . m- j9 w+ e5 s4 G1 v+ v
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
    ! L: j" O% X" n) F7 V4 Z/ _* I
  234.   & g! o$ Z5 n4 D4 d; |
  235. after_alloc: // 添加此标记  ~0 u/ W% d! X  l* S* M

  236. , z1 j' H# E2 {, S( P  t
  237.   if (p != NULL) {. z+ c8 I# J& @2 w: w$ l
  238. ( ^8 M1 |- g% o
  239. #if ETH_PAD_SIZE$ ~* c( q* W# P! W/ ?
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */. Q9 w- W5 i& {# l7 b
  241. #endif
    ) }+ f7 a7 ^$ O+ e3 @! z; b
  242. 1 a7 Q  k1 g/ [; S+ S1 O6 _" |
  243.     /* We iterate over the pbuf chain until we have read the entire
    . V. u9 Y+ X/ j+ e8 x
  244.      * packet into the pbuf. */  Q6 }: |+ v6 T3 q/ h
  245.     for (q = p; q != NULL; q = q->next) {
    ( h# z' ~5 b+ z. @
  246.       /* Read enough bytes to fill this pbuf in the chain. The
    % l# L$ x  T* O! }/ Z9 P$ x) g4 k
  247.        * available data in the pbuf is given by the q->len
    ' ?" h; U8 k" \9 [
  248.        * variable.5 [2 _5 }+ I1 h- j. @
  249.        * This does not necessarily have to be a memcpy, you can also preallocate5 B; }: N) }2 _, P4 [; ?: I
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
    6 e/ _8 F9 O, E7 l6 |
  251.        * actually received size. In this case, ensure the tot_len member of the  j8 h+ z5 ]) ?  e
  252.        * pbuf is the sum of the chained pbuf len members., n% i+ ]0 F& J4 _
  253.        */
    & a5 R2 s' M6 Y1 [  {* o. D
  254.       //read data into(q->payload, q->len);$ O+ w5 w7 V' a" @0 e
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容4 X; [) E# }3 k+ j! ?$ U. I
  256.                 bufptr += q->len; // 指针前移3 f7 R4 v$ f7 u, {- o
  257.     }
    6 @' X7 ?+ L+ s8 A* p- x
  258.     //acknowledge that packet has been read(); // 无需确认
    / ]) @: _2 a2 k. ^
  259. 4 y% U; E( S# u5 ]
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    6 m5 h  J2 w0 M! e3 L8 g
  261.     if (((u8_t*)p->payload)[0] & 1) {
    8 c( U) h. C! M1 D
  262.       /* broadcast or multicast packet*/
    ( @4 W- q4 n- x5 L: @) t/ s
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);+ Q: ]; [* X4 @/ x! Y! ]  }. H
  264.     } else {
    0 V$ z/ U0 m/ B2 a
  265.       /* unicast packet*/
      N0 P5 m4 \. d. @4 r0 o
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);+ g9 Y2 L5 E7 c8 Q, t" t" [
  267.     }5 x. W+ v' G( Z# L4 z- m9 M4 u% I
  268. #if ETH_PAD_SIZE
    8 m2 r+ {3 L$ ?, ]/ t; b6 A
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */! `, g% B' J# N% k9 S* W: Q
  270. #endif
    " ~7 M0 M; Z+ W* ^  A6 i0 e( d* E

  271. $ r' K& A) B, p
  272.     LINK_STATS_INC(link.recv);- q- _0 b/ I) k  U
  273.   } else {$ N2 {) H+ M: `, C5 i- d# ]7 v5 q
  274.     //drop packet(); // 注释掉此行
    7 C& @4 ]+ y  i8 M3 C+ ^
  275.     LINK_STATS_INC(link.memerr);( T9 z2 g4 v, @4 ~, R$ U* G
  276.     LINK_STATS_INC(link.drop);
    4 H: A+ [( S/ w+ W. C0 f4 q
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);
    9 I! @6 i. p4 S: f! d7 h: G8 E
  278.   }3 S3 J  p1 V5 V! H7 u! h4 S0 _

  279. + ?' D( v2 F2 m* i$ X
  280.   return p;
      z9 q/ h1 @5 @* r
  281. }
    ; C8 ?- t. H. A

  282. " ?5 S. b! `: {1 e; k. S/ D
  283. /**" f  N/ R7 {( G( T2 L
  284. * This function should be called when a packet is ready to be read
    ( G, }, d1 N( n# e. \
  285. * from the interface. It uses the function low_level_input() that
    * J: A) m9 l! a5 E8 q
  286. * should handle the actual reception of bytes from the network* A* k0 p+ N7 Z% p7 J
  287. * interface. Then the type of the received packet is determined and
    & c: H0 `0 N  |7 }
  288. * the appropriate input function is called.9 v! L6 f/ }2 s) a( v
  289. *0 J/ }8 L9 }0 U8 u# V. e* J& S! U
  290. * @param netif the lwip network interface structure for this ethernetif# V9 S6 g/ n: X/ {$ Q
  291. */. Z: s1 j6 h' J5 P9 t1 s. u8 M
  292. // 必须去掉static3 {, X7 \3 n+ M0 a
  293. /*static */void& m& P& {& V$ Q1 V
  294. ethernetif_input(struct netif *netif)
    ! q' r$ ^% y: h7 F0 I4 J& q) \
  295. {
    ( @- j* I( A& F% ?5 [  G
  296.   struct ethernetif *ethernetif;
    . K# a" }  F5 s0 M2 S
  297.   struct eth_hdr *ethhdr;3 p+ P- W2 T9 G! P# s2 t2 d
  298.   struct pbuf *p;; [% Q0 f9 @# n# H1 \# t# `

  299. 6 h$ j; |2 f6 F- u+ P
  300.   ethernetif = netif->state;- P1 W$ f4 @1 J& c! _

  301. / v. s, Y; _( f3 H1 z5 {- Y5 }' n
  302.   /* move received packet into a new pbuf */
    % j3 V$ @: D$ _# N+ @" P8 ]2 q4 o0 D( h$ ~
  303.   p = low_level_input(netif);
    ( J+ j2 c/ |: F) M# d, |; x
  304.   /* if no packet could be read, silently ignore this */
    ' F& q* b3 f7 \. u
  305.   if (p != NULL) {
    + h# r/ ?0 ]/ G
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */
    * S7 T4 P( \! X; z
  307.     if (netif->input(p, netif) != ERR_OK) {' W2 h. ~7 U4 d
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    & x- J5 E% f) R# Y& t# g
  309.       pbuf_free(p);) L5 E; X& T1 }- l- G! F4 g
  310.       p = NULL;+ V+ ^+ q( K& N2 K* s
  311.     }5 e# z$ d1 m& t& j4 M6 Z
  312.   }
    8 Q$ O. J% ~" z/ e* n
  313. }
    7 [4 a/ T; c% X1 n

  314. ' {0 u1 N: @8 ^7 Z
  315. /**' h( A/ K  n! P5 k2 f& C
  316. * Should be called at the beginning of the program to set up the6 u- S( s# d$ T' g* p, ?
  317. * network interface. It calls the function low_level_init() to do the% U- Z) x& q1 Q5 M' Q( J& ]5 t8 ~
  318. * actual setup of the hardware.: a7 C; r8 {# m4 ~, h% m+ n
  319. *
    ) J: C& r; i3 [. P% {$ e
  320. * This function should be passed as a parameter to netif_add().
    5 A/ C, s6 X# W2 e
  321. *2 _$ Z. Z$ O0 _: h
  322. * @param netif the lwip network interface structure for this ethernetif" G. r+ Z8 M+ e, C( G; Q& Q) t. X
  323. * @return ERR_OK if the loopif is initialized5 q1 D7 r. T( G, `
  324. *         ERR_MEM if private data couldn't be allocated  A$ o& Y% f; U9 i8 }  ]8 `+ N
  325. *         any other err_t on error
    & {6 t0 ?" A- c7 f
  326. */5 C! f' ]; l. Z5 c6 O3 s, d
  327. err_t
    - V7 O, \$ s$ d/ {  f2 C
  328. ethernetif_init(struct netif *netif)
    9 v( z: `- s- y6 D$ Z
  329. {$ Q- ^, z% H+ r6 V- q6 X/ ^  X
  330.   struct ethernetif *ethernetif;. D; P3 H( _* s. ^+ o; G: S
  331. ) ]- l5 k7 L% }9 R& R0 G1 ^: T
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));/ p( s4 u# i  x) g8 u+ ]: r9 Z
  333. 7 b# O% R- n* ~# ]3 C
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));- w- m, {2 C  B  B( j, S- T: x7 ^) [
  335.   if (ethernetif == NULL) {
    ) c( ?* m1 o' c3 @
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    8 _$ w" e% x( t7 @$ B+ L/ R6 _
  337.     return ERR_MEM;6 |9 ^( d; v2 S: q" l
  338.   }
    3 y# i8 B, [6 e

  339. 7 {' l, h. G5 O) J- G
  340. #if LWIP_NETIF_HOSTNAME6 h3 L  @; W" g# R$ m
  341.   /* Initialize interface hostname */
    9 u5 A* E  z) `! G0 K% e
  342.   netif->hostname = "lwip";
    $ V. T2 N) T; m! Q  V* Q
  343. #endif /* LWIP_NETIF_HOSTNAME */9 U% N/ [' C& e' S. D* [) G# m9 [
  344. " C8 `% y! g1 U7 c7 Q$ L4 G# }
  345.   /*6 d$ ^4 w  K& ^5 i4 G9 \2 R4 x
  346.    * Initialize the snmp variables and counters inside the struct netif.
    % e* _6 L* p' G; G
  347.    * The last argument should be replaced with your link speed, in units
    ( W5 Q7 \9 ]  N0 Q
  348.    * of bits per second.
    * u& `3 |6 p1 r+ K
  349.    */2 e% l- W9 Q  ~& i
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
      M+ k: _4 o2 `$ j

  351. 3 U8 A/ [9 R. Y' L3 h" E' n
  352.   netif->state = ethernetif;1 V- f  p& T$ j
  353.   netif->name[0] = IFNAME0;4 G/ E6 L7 n# W' W9 \. W+ J
  354.   netif->name[1] = IFNAME1;
    6 l5 t5 z2 L' z: x' h4 S3 H: {
  355.   /* We directly use etharp_output() here to save a function call.
    $ s3 f5 A; q) P! c$ O
  356.    * You can instead declare your own function an call etharp_output()
    " A& H. \$ S4 ?/ d- {1 v/ I
  357.    * from it if you have to do some checks before sending (e.g. if link. o& Y" N9 U6 @3 x
  358.    * is available...) */3 {& E8 K' R2 g: S2 V$ P0 V* N  `
  359.   netif->output = etharp_output;
    0 J- I0 k4 ~" W! ]! N/ D
  360. #if LWIP_IPV6% S& q3 q8 z/ F9 F: K
  361.   netif->output_ip6 = ethip6_output;/ {. {* S1 O" {' P# p
  362. #endif /* LWIP_IPV6 */1 p/ u4 T$ f4 f* [
  363.   netif->linkoutput = low_level_output;8 C8 \3 h$ m- O- v

  364. 9 ^4 g9 U' r* B* @) n8 G6 b4 W
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);" l+ n8 {4 s7 ?4 k+ V/ h
  366. 3 }% P0 j/ N+ B
  367.   /* initialize the hardware */, e3 k4 x3 V8 C" q* C0 e# t8 ?
  368.   low_level_init(netif);
      Q: t2 L$ z, H7 r% H# R
  369. ( f$ A, \( x/ H% o# i% G! ^
  370.   return ERR_OK;
    " K7 K5 K2 i) M7 E: X
  371. }3 Y( y1 r5 I& n! x% q  s( K

  372. - ^' d* |: B; F+ y
  373. #endif /* 0 */( o' F$ ~+ P. y9 V) G
复制代码
7 [+ t6 J- J2 w0 ^% i7 \
在项目属性中,设置Include Paths为:.;.\lwip\include
6 T+ s2 K1 L8 S: k' i其中点表示工程根目录。4 e1 E) ?! A. s0 {
1 V3 T* y! a; O4 e" x! _: m2 s4 {# ]
另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。- x+ W  J( T- z: l: M; T

( z, s6 c! v- A  J编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。! T* B: S3 h7 v6 n! c
电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。
: A+ K! y: C- M3 P配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。
4 g. ~4 g! f5 x" j) k. i. J, `

评分

参与人数 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....7 [( \' R2 h, ~# a4 S

8 R7 b$ J' l2 }; m多谢分享
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 手机版