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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE2 q, M  ^5 C+ S2 f7 A/ x. ?
PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。
6 @+ G$ Z, v+ q9 _1 ?9 y注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
! k' m) z- s" g6 @! D  ?该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。: _) Y1 A# P6 N, `% t- h% Z& k
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
- ]$ J% h6 S* h
( ^% F; m, g. n% I- T$ J3 m- X( ~注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!0 V: p7 a8 i; |' c1 J
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】
- g% H( I% t( L, z+ d' }4 B
  1. #include <stdio.h>' C( F9 p) `+ s# C2 j
  2. #include <stm32f10x.h>
    5 {( E9 H: W4 b9 z9 B! R. {4 c
  3. #include <string.h>
    / [& h  z/ v5 E$ n! f
  4. #include "lwip/init.h" // lwip_init函数所在的头文件& `7 u/ B  t0 Q9 T
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件6 m+ p; v: C: n1 s) m& j. k+ R& r
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件' ]! E% E8 r7 T; t. ~$ ]
  7. #include "WiFi.h"
    # \/ O0 ^, D" N5 l5 L7 M9 x

  8. $ X/ L' a. c7 g) S& X
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明7 J0 E3 p5 D' |, [& y4 w
  10. err_t ethernetif_init(struct netif *netif);" _2 r) e. o5 t4 l5 L; C4 k( j
  11. void ethernetif_input(struct netif *netif);' z9 }& H% x/ F- Y  v

  12. , a. I( v% t5 G+ q  e+ _% u, c. j
  13. // httptest.c中的函数2 Z- T1 n7 u4 ~! x: Q8 x% @/ P
  14. void init_http(void);
    ! ^1 V9 X6 S6 h, l$ O! ^/ h

  15. * t2 q# A& R# o  r0 l. E& Q
  16. // 延时n毫秒2 {* S7 Z; q5 C- \0 ~6 U( m
  17. void delay(uint16_t n)
    8 O. e$ `! n! T
  18. {. A, V8 I1 j$ c! Q9 @7 \
  19.     WiFi_PrepareTimer(n);) {: B- _  Z8 f$ O/ A8 x0 M
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕
    ( Y7 i. l# C8 m( D8 f7 L
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
    # K5 T- _. c7 N# B+ {( {" s
  22. }3 ?: j2 R, O1 q4 h8 V( S
  23. : a( {, E: W9 R/ T
  24. void dump_data(uint8_t *data, uint16_t len)2 d' `4 j5 E+ _# n
  25. {) ]( E9 P$ O, T7 c/ _" H) o
  26.     while (len--)$ |- q5 k: k- o) o& Q  i
  27.         printf("%02X", *data++);
    + q, j6 f- T* U) q0 H  L
  28.     printf("\n");' \# P% T4 h6 {( {# F$ Q, D
  29. }! Z8 s( f( s1 x. }
  30. 1 [2 X* {% j5 f" R. |
  31. int fputc(int ch, FILE *fp)
    " m7 W8 S9 c0 `$ i( D+ o9 g
  32. {
    & `  c3 d0 X& {" `
  33.     if (fp == stdout)0 Q) l# e% K  M# t
  34.     {+ i1 x* C$ n0 F! h: d
  35.         if (ch == '\n')
    4 Y# H; b. b* s" F6 J: `
  36.         {- e/ W; C( j+ A7 Q; x. a' G0 w
  37.             while ((USART1->SR & USART_SR_TXE) == 0);4 r) p+ u$ s3 v0 W8 P, a) c
  38.             USART1->DR = '\r';# ]4 h! ~/ D' y+ l; j' l+ }
  39.         }; q0 [  [( v. K6 ^( H5 f" N
  40.         while ((USART1->SR & USART_SR_TXE) == 0);' O# X: S$ D, x0 _( a. G9 |
  41.         USART1->DR = ch;  a' f8 s2 H$ @2 g8 x7 U
  42.     }
    2 K  r0 E0 g! ~: m7 J
  43.     return ch;
    0 I9 v2 r  T! u3 J
  44. }
    , U3 g5 S9 L9 ], h- b5 U9 _0 E

  45. % X+ P2 b8 A' R# k) {3 ]" M
  46. // RTC时间转化为毫秒数$ x1 a) @- |3 i! p
  47. uint32_t sys_now(void)
    ' `3 z( n* o( ~% F* E- T# k
  48. {
    6 I* K: P; ~8 H8 [! ?4 b9 C7 q
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
    1 [$ L  z( F8 j; E; B; |
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒
    0 d" u8 W. F! I9 d
  51.     return tmp;. y/ t- h0 F. n9 e
  52. }! b$ d9 S. C( A* q

  53. ( e9 _/ r+ E4 \3 S
  54. int main(void)* M& {$ l7 |3 }0 a5 I# n
  55. {
    ( n3 |" E* I* ?- b& I
  56.     struct ip4_addr ipaddr, netmask, gw;
    9 P$ B( k7 S; f% I
  57.     struct netif wifi_88w8686;
    0 `6 y% i" y: N( ~4 M
  58.     uint32_t last_check = 0;& G) a+ |; w+ j8 s: T4 x" h
  59.     $ D$ e: R: H! l4 F9 X3 y! c6 w
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;
    : ?( r8 B2 F/ {2 T0 j! j
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;
    * }- K7 `- u0 F" W& K# V
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;2 T% b0 Q  @6 a3 v
  63.     1 }. F+ j2 H2 A$ Y* }
  64.     GPIOA->CRH = 0x000004b0;
    " D) e% ^0 ^' B8 |
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块$ o  q3 Z+ V/ U0 s4 e. W' ^! n
  66.     GPIOC->CRH = 0x000bbbbb;! y& d) J7 u6 n% u+ G2 r
  67.     GPIOD->CRL = 0x00000b00;4 I- d+ R$ z) F* e0 ]# v5 C
  68.    
    9 n) }) `! p4 z. e9 ~. i. v
  69.     USART1->BRR = 0x271; // 波特率: 115200
    ' S  m( K  P! X  Z
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;8 i# X6 U  z4 ]- [8 H7 h9 A8 J/ o; o
  71.     ; \! \& V$ Q/ s9 v
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器) t+ d. A' i6 t3 X- b  c; j* I, o
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)2 g/ R4 P# ]9 |6 @
  74.     {" Y% l! u3 ?6 G" \3 l: D  `' `/ l
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI) m( T2 j6 c: L
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
    : P8 p+ q+ z* e* g9 G8 j+ A  [. t
  77.         //printf("LSI Ready!\n");1 d; N$ E# y' D2 h. h" P2 h4 ~
  78.     }
    " y2 m5 R% w9 u$ B( ^
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)
    2 W+ N' A1 u2 }8 M5 F" A
  80.     {. s7 h- Q6 t+ V
  81.         // 若RTC还没有打开, 则初始化RTC% S4 c% w0 E& C" X+ V3 G: N; T+ ~" u
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时4 a9 N0 c; [. g% @6 }3 w# L
  83.         
    6 o! k/ W( X% ^, N
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式
    2 r7 X! Y" B3 n4 p5 T" l
  85.         RTC->PRLH = 0;
    5 W3 v% N  q9 d2 e
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
    % k$ j9 @4 Z# N. ?
  87.         //RTC->CNTH = 0;
    ' e+ h' n4 A* ^; l$ M
  88.         //RTC->CNTL = 50; // 初始时间
    ) c0 J6 g7 a4 ?' \, O
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置
    ! E; N- |/ [9 }8 C; q8 J  A9 ~  O
  90.         
    $ _4 j+ X& S3 O3 K; r$ b
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
    4 T, H5 z3 j( R
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效
    " @7 M9 P* u" r2 F+ l$ }4 }
  93.         // RTC从此处开始走时
    4 t# O# q! E0 ~( E. q
  94.     }
    * A7 P2 _. L9 ]  ~  S0 p
  95.     & h1 ?9 ~, ?# T' x$ D; g! u/ H% d
  96.     WiFi_Init();4 p5 @2 |4 w4 u3 }1 [
  97.     WiFi_Scan();! s& N# @9 _+ U; }
  98.    
    $ \* H% h1 Y* ~: ?
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点0 x3 S7 u1 C; [* V8 Q
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
    . D% `+ e1 q4 J7 c  _% {* z
  101.    
    % h7 D+ ~0 k4 D  O" I
  102.     lwip_init();& J) V0 V5 a. z; w4 z9 e
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址
    . B. R% X4 k: e% \
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
    ( k) I3 q; N1 c0 p
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
    ; u5 `. k+ t4 k! j0 [
  106.    
    / k# `1 C9 O6 b3 [1 l! A. q
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    6 Y4 v, n% U8 o& b
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡( r  u0 O4 U( P4 N6 F# Z- ]
  109.     netif_set_up(&wifi_88w8686);
    5 Q% J8 ~, o/ B& ^1 v' w
  110.     6 S9 L6 n0 p" A8 `8 a6 {
  111.     init_http();
    7 D6 ~- D2 C! T9 U$ d
  112.    
    9 {; f6 w  ]. e; z( @' s& b! d/ ~! i
  113.     while (1)
    ( c, x& T: U: s- G4 E1 K
  114.     {1 G; S8 d* x0 M; _: R
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())
    ! I% k/ ?) A* D9 _  l% i- J5 y
  116.             ethernetif_input(&wifi_88w8686);% q) r. [: A- i, r* b& {- o3 k
  117.         ) X9 g6 z) o6 M- T
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)* X* {. q. j0 g: R" O
  119.         if (sys_now() - last_check > 200)% Y# |; g5 L' L  P0 \
  120.         {
    , A8 B6 A5 _$ H5 \
  121.             last_check = sys_now();0 K" E' h. {5 N
  122.             //printf("Time: %d\n", last_check);, S  }* l- \( ?5 b% I; J  i( [
  123.             sys_check_timeouts();
    $ t' X9 ~6 K8 U  ?$ z; [
  124.         }) G- R$ F- o' O
  125.     }) D* v' j, ^/ {0 b
  126. }
复制代码
【httptest.c】' Y% ^0 G/ f. \7 |1 Z
  1. #include <string.h>
    0 L- J: b0 C+ @  q# a/ @1 s
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件
    / ^; ]+ p0 `# }) t, L

  3. ( J# v" f$ M# O! S# [4 W
  4. #define STR_AND_SIZE(str) (str), strlen(str)' }5 F- s) o) a1 q
  5. % x1 z. A% }3 U, i
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)8 b. b( O' X' g8 s3 ]0 M7 V
  7. {
    " w: T0 I' b& W) e/ z
  8.         char len[10]; // 存放HTML内容的长度
    2 T& e8 d9 c( k/ n5 P1 c8 O
  9.         char str[200]; // 存放HTML内容# J4 _- W. S% N4 q8 f4 D" |# }
  10.         
    9 y% V# ?% |! E' R) D; k
  11.         char name[100];
    0 c* k: u% W& E. k  @
  12.         char *pstr;+ }$ {$ ~: I) D- ?# p
  13.         uint8_t i = 0;
    ! g+ o' w8 v9 _# V5 ?
  14.         if (p != NULL)$ }# Z( D( _. B; g) e
  15.         {( C6 o! s- H8 x( e2 s
  16.                 // 提取页面名称% C$ Z2 a  o3 L
  17.                 pstr = (char *)p->payload;
    * J" ?  b1 [! b! ~, P
  18.                 while (*pstr++ != ' ');4 w& c  g$ D1 k, S( O/ R) ]+ Y" C0 Y" ]
  19.                 while (*pstr != ' ')0 y9 I: E. a( D8 k% [" x$ r" g
  20.                         name[i++] = *pstr++;
    " ]' ^+ F  O/ H1 t: E) r
  21.                 name[i] = '\0'; // 不要忘了结束name字符串
    - o& M/ L: D* s$ o1 o& }
  22.                 tcp_recved(tpcb, p->tot_len);
    $ v9 S7 }0 i6 D1 X
  23.                 " @) A, l' |4 Z2 D9 E9 p
  24.                 // 生成HTML内容/ i- E8 e/ {  z4 F" e. ~
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
    $ Q1 c3 I/ n) T& N7 I& `
  26.                
    ( Y; h* y5 j, \* T( T4 L
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度% R& Z3 p7 A+ P) t0 Q, U) s
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
    - O/ P/ k4 {- Y9 Z% J
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
    1 c# N& I- K) B$ @& o
  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);
    5 k, f7 m) x" D; Y
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容* t  y6 c# O0 }+ X+ M+ K* }
  32.                 pbuf_free(p);
    - s+ s4 [! _- a" k. K$ t
  33.         }
    % \( O/ N: R/ C$ h+ s  e
  34.         return ERR_OK;  e' `7 j) u* q  e9 E
  35. }
    - ?  u4 j/ a6 H& t

  36. ( v" @" _6 i* s0 V
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
    3 u8 ~9 ~4 k. w  R" w
  38. {
    : O% `* X$ t* x
  39.         tcp_recv(newpcb, http_recv);/ p7 n; S+ R$ R7 @% N9 C
  40.         return ERR_OK;
    + ?, N( n( `! P" E* o  I' A, H7 O& t
  41. }
    % I0 m6 D& }( |5 F' @

  42. 2 k" S2 E% `" o' d  S2 [, K
  43. void init_http(void)
    + k8 F" V) ]' l) a: h% h
  44. {0 h3 K* q2 T) w* n1 E& w
  45.         struct tcp_pcb *tpcb = tcp_new();
    ; p8 t" r3 d* h9 T& E
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);
    % ]% i4 [7 c1 I& L6 ^
  47.         tpcb = tcp_listen(tpcb);9 `1 h- W. ?5 E0 P  N
  48.         tcp_accept(tpcb, http_accept);7 ]" O7 k' W2 {5 |+ x% d' n" M
  49. }
复制代码
【WiFi.h】
: A' ~( x' e! y  K& ]* `$ M% ]
  1. #define _BV(n) (1u << (n))
    % h. X3 m1 z3 Z& G! G

  2. . G6 o9 e: B& W+ A+ V8 |$ c
  3. #define CMD52_WRITE _BV(31)' U; d; d/ H( V3 h/ L+ O
  4. #define CMD52_READAFTERWRITE _BV(27)$ A3 p& m5 G. `
  5. # }6 Y; u# c9 C- f
  6. #define CMD53_WRITE _BV(31)
      M2 Q* z5 r; h3 G3 J
  7. #define CMD53_BLOCKMODE _BV(27)
    8 U" U5 h$ G- F: ~
  8. #define CMD53_INCREMENTING _BV(26)
    $ ~# u# s1 d; T% `
  9. 6 D  n: y3 N( b/ G: {' V
  10. // 16.5 SDIO Card Metaformat
      r2 Y2 b7 b0 }
  11. #define CISTPL_NULL 0x00 // Null tuple; k9 C4 B9 w# z  D8 V/ Q2 X
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information" N/ C$ e/ ]; H& i2 I. L" h! {
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    3 P1 r$ s1 o3 k1 |, A! g' \
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple
    ' Z2 c/ u, p& @/ J
  15. #define CISTPL_FUNCE 0x22 // Function Extensions& k" [6 Y. R( ^$ A. ^
  16. #define CISTPL_END 0xff // The End-of-chain Tuple
    ) S# L% h2 u8 w8 j! n
  17. - z0 n" e! T" H0 m8 ^& H' E
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)
    ( r- M3 k, T/ B6 k

  19. # ]/ d& Y- `$ R8 b# u& I
  20. #define WIFI_SQREADBASEADDR0 0x10* C$ M# c0 s) V
  21. #define WIFI_SQREADBASEADDR1 0x11$ D: S* o: E$ r% T
  22. #define WIFI_SQREADBASEADDR2 0x12% |, T, h2 k' t! {
  23. #define WIFI_SQREADBASEADDR3 0x13: v8 b  A9 f: F  F: j% c

  24. ) Y* q0 h1 d  J/ B2 q& |3 s, j
  25. #define WIFI_CARDSTATUS 0x20 // Card Status
    1 G; U9 i2 p' T. J6 E9 ?( S
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator
    ' [3 E. v; ~8 c+ ~; W
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    ) s) I  p5 Q2 @' b4 u# Z; R
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
    0 G" o1 S% z) S7 z' J
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
    ! M* c9 S# `0 U

  30. ( v7 `( L9 h, E. E" W! T+ |" X
  31. #define WIFI_CAPABILITY_BSS _BV(0)
    2 |9 k* i& W! h1 _
  32. #define WIFI_CAPABILITY_IBSS _BV(1). d' _1 H3 O/ m8 H; `$ ]6 t  u
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2), [& ^( @* [9 \4 @! v6 `% S2 \" M$ Z8 W
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)$ @$ d& E" M& e* t$ F0 x0 ~
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)
    , p3 E5 ]+ g4 g! D: X) k
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)+ y+ J% U9 m3 _) V0 r
  37. #define WIFI_CAPABILITY_PBCC _BV(6)
    7 K3 A/ E; H" f+ _. H+ ?8 @
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)/ a# A3 j5 P/ E8 H; \
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
    1 V9 \/ p$ ]3 t4 K* T! p' Y! H# D
  40. #define WIFI_CAPABILITY_QOS _BV(9)
    6 Z" m: j1 Y' t" s. c5 S/ K, `
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)
    7 E' _- X7 A& ~6 O: A
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)
    6 i$ M% F% X+ S# C

  43. % M" A: a2 S7 x% D$ u* B
  44. #define WIFI_SDIOFRAME_DATA 0x00
    # n; A$ s  Y$ i+ j. |
  45. #define WIFI_SDIOFRAME_COMMAND 0x011 J6 m! v" z# l4 e# ^3 h+ `+ j
  46. #define WIFI_SDIOFRAME_EVENT 0x03
    . |5 ]6 D' ~; Y
  47. % P- o# P$ h& v
  48. /* Command List */: A; p6 \% x4 ^& C$ F/ l
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    8 s6 Q, T/ K$ a; D- o$ j
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP
    + p$ C. X4 t2 [+ {1 V3 b3 H
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
    + L/ D" u- C) X0 t0 F6 }& O
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
    # ~3 h7 @2 T. P5 h! ], B$ e
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address
    ; u  U  \% u; B* |: {' l
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption8 x# f  f+ h* Q
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
    2 ^% i# |; J1 P3 k0 `- J
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results4 n0 ]) d% X  @( y3 t# k; V  ~

  57. 9 E8 G% c* g4 i9 Q7 G* |
  58. /* Command Result Codes */- z. t( m' P% B# u/ T
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error9 R4 X0 l: G3 Z
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed* b( i$ z$ b) ~- J( {" p5 G9 U+ V
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported! t7 r; \, `5 _
  62. ' U7 R3 K: U0 r
  63. #define WIFI_ACT_GET 0! @9 L; R! w8 q. e: m( Y; T
  64. #define WIFI_ACT_SET 1
    $ u( }; {: ~0 }+ U4 {

  65. " o4 J, x3 f2 z9 O. D1 A6 N
  66. /* Authentication Type to be used to authenticate with AP */" g3 D/ w# w9 Y9 j' C0 m+ ?% V1 ?
  67. #define AUTH_MODE_OPEN 0x00; ~$ P/ Y! w, c4 U+ b
  68. #define AUTH_MODE_SHARED 0x01
    - I! V$ n9 Q; d
  69. #define AUTH_MODE_NETWORK_EAP 0x80
    ( e; `+ u1 V9 D; }
  70. * D5 m; \) D. o3 N! c
  71. /* WiFi_Associate return value */4 Z2 x. ^* z/ m& Z* K, ~, ~
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe3 Z; {% B. g0 g% U0 ]3 B+ G
  73. #define WIFI_ASSOCIATION_ERROR 0xffff
    , D$ q% a3 E5 O/ ^( Q
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功
    ! E1 {2 C+ q/ H! J* f8 W- B, x4 m
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101% b1 j6 W: Q6 P4 l! x; z
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧
    , n5 H1 C: `9 b" e, ?
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213+ G1 x( ?$ u% D$ u4 ]/ z
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
    # m, K, ~: A  N. o6 k
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败
    8 {$ F0 J, l* o
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时
    0 c. |: \. o; j2 t& R( n# J7 V
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时& E4 ~; H/ X0 Y, M4 Q* F
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时: a2 N: U# i0 ^% |- K: T
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时, [5 e* [: ^9 P  C$ L$ d
  84. ' f, W5 v. Y7 T0 f* G
  85. #define WIFI_KEYTYPE_WEP 0
    ' E+ }+ f7 M5 D. w( D7 p
  86. #define WIFI_KEYTYPE_TKIP 1
    & P4 Z- c& H4 s1 l) K
  87. #define WIFI_KEYTYPE_AES 2
    / u% w' G& T4 U( k1 r; @

  88. 0 [7 ]8 h1 Z+ O
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)* j, _! r$ j, L6 e- F
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)
    - [( d4 y. }8 P8 r
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)  h1 B; ?. @# R3 r6 w

  92. 6 _9 w/ W: [0 R2 e% A+ h6 M  N- P
  93. #define WIFI_MACCTRL_RX _BV(0)1 j9 V8 e6 o$ U+ e  o+ j7 \
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!' v6 N$ \6 V  W4 a+ g
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)- |5 m  J6 s- H# W+ F8 s2 c
  96. #define WIFI_MACCTRL_WEP _BV(3)
    ( \0 r& A9 y+ c1 N
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)
    ' d* o; K$ t3 [% U9 D9 K
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)
    : s# W7 _' {. U. b+ k2 w1 @/ B; D: f
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)% X7 k; ^0 P5 ]3 d2 T, K
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection4 G* ], @& w& X5 E& f1 M6 q
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode
    9 V% D; B$ ^: m9 Y( K# W
  102. & Z% J2 U+ L" E2 G! _+ u+ I
  103. /* BSS type */
    7 C& Z) }& j* C* M8 @; S
  104. #define BSS_INFRASTRUCTURE 0x01
    ; q" u) x2 R: `7 w! ^
  105. #define BSS_INDEPENDENT 0x02
      `4 ~+ P% h. @- {8 \# H
  106. #define BSS_ANY 0x03
    ! r/ O# ]9 q4 T8 a5 s
  107. # K6 O" f  v! J* O
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */
    * x1 d2 ~( S2 h1 m9 v
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */
    ; y8 ]3 t5 B, n/ q9 h$ T' L
  110. #define MRVLIETYPES_SSIDPARAMSET 0x0000
    1 p6 q& b) k; w, @# l
  111. #define MRVLIETYPES_RATESPARAMSET 0x0001* L! [7 W, W( u" t* x
  112. #define MRVLIETYPES_DSPARAMSET 0x0003
    0 z$ X' v- V2 i9 i3 u) A
  113. #define MRVLIETYPES_CFPARAMSET 0x0004
    ! `) r2 n8 ~3 f% E) F8 e. A
  114. #define MRVLIETYPES_IBSSPARAMSET 0x0006
    $ [* G# Y5 C, V. o' R2 ~: ?
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030
    % Y% `1 @$ R: K
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd
    4 f; u* N0 T5 _" s
  117. : \. p; J% r8 r- b7 G
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100
    - k3 d: v, D& r# @+ {
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101
    , ~0 f6 h; v/ p6 l8 u
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x0113( D" M7 E* S& }1 |7 D
  121. #define MRVLIETYPES_AUTHTYPE 0x011f
    7 S% P9 d8 j# L3 N
  122. 3 }0 U+ r0 J+ [
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小
      `6 k( |0 Q' p
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小/ x: {4 G5 f' y) D9 g) t, ^
  125. * P5 @! O& {  N2 T( V+ g5 f
  126. typedef __packed struct
    ! u( z! w2 p$ g
  127. {
    " s2 W/ V- [$ _3 ]/ z
  128.         uint8_t type;+ h5 n! V, r2 e. H
  129.         uint8_t length;" s4 x1 C, `7 {/ c0 z
  130.         uint8_t data[1];4 T: j: X% j$ h& p
  131. } IEEEType;) B& G# x+ k7 d; v+ F2 |- R
  132. + w5 }' c2 C& H8 w8 R
  133. typedef __packed struct6 J2 c1 M- s( c/ ~9 a4 }
  134. {( w+ Z# Q1 [; u- x7 ?% s1 b8 Z
  135.         uint16_t ie_length; // Total information element length) e! R+ w1 m$ \. T2 J
  136.         uint8_t bssid[6]; // BSSID
    ( S% G/ o* G1 @5 Y
  137.         uint8_t rssi; // RSSI value as received from peer
    * U# V# y! _  V
  138.         
    $ f% _+ Z( p: r! t
  139.         /* Probe Response/Beacon Payload */) k) I4 ~' Z1 a7 v- G
  140.         uint64_t pkt_time_stamp; // Timestamp
    . ]* @1 O3 c! E
  141.         uint16_t bcn_interval; // Beacon interval1 `, D  Y8 w& d' a1 U0 x7 S
  142.         uint16_t cap_info; // Capabilities information
    4 y) i! z# u# H1 L2 c% ]
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据
    2 }! f- X/ z* |5 _
  144. } WiFi_BssDescSet;
    % O3 E$ a3 V8 V* n, i
  145. 5 m2 L+ r+ D' X+ q+ U, I; `
  146. typedef __packed struct
    5 Q5 N% p( P; W2 j+ C
  147. {
    , ]) A+ O) t7 O
  148.         uint8_t oui[3];# D; ~2 G5 ?! p# L1 k/ Q
  149.         uint8_t oui_type;
    : V$ O7 T) y" U: A/ U3 x/ G
  150.         uint8_t oui_subtype;0 K2 w# w# a# F8 Q" g8 e. I: _8 v+ D
  151.         uint8_t version;
    , r4 X8 Q. f& g7 I# Y
  152. } WiFi_VendorHeader;
    ) C: I$ ]/ Y4 x! u+ `

  153. & r8 u$ X3 p8 q& g* d2 C
  154. typedef __packed struct
    # Q0 N5 A2 x! l0 U, p* {* n4 i* L6 d
  155. {$ H: B' d3 E9 z+ m/ `9 D& \( a
  156.         uint16_t type;8 [3 v3 @" _# [! x6 T' q
  157.         uint16_t length;
    ! q+ @+ m+ y- K. L3 b/ n" N6 i
  158. } MrvlIEHeader;" d% y7 W" E- Y6 N; n1 _2 C

  159. ) t# A% K  p- l3 y# M1 T
  160. typedef __packed struct  T3 b7 x& k- T) q8 t. T$ D; \
  161. {. }: T' A( \2 I- T/ G& {1 }2 P
  162.         MrvlIEHeader header;
    . u! [% C  g3 M8 {" K; g
  163.         uint16_t auth_type;) [- E# f0 }% H9 i% T# X  B
  164. } MrvlIETypes_AuthType_t;: ?, ~6 {+ ^, x
  165. ( @# x* E+ D/ P: G
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec9 u( ?* ~* v  X: U5 m5 d) N

  167. * G% n# e6 y4 J
  168. typedef __packed struct
    ) d/ X" q5 ]4 i" ^) T
  169. {
    4 W: p  _9 y( O, B9 w
  170.         MrvlIEHeader header;# o  P5 M6 z9 `6 J" C/ c5 g5 i$ ~  a
  171.         uint8_t count;
    + o5 D& ?0 q4 B6 o# X# z
  172.         uint8_t period;! w, ]+ S8 u% o* @. b
  173.         uint16_t max_duration;
    - E& b" U& c5 u% f* {+ h1 _+ [
  174.         uint16_t duration_remaining;
    . o6 B/ l9 ^& U' q
  175. } MrvlIETypes_CfParamSet_t;
    2 h8 h& z. V' [9 ~, Y
  176. 9 }8 ^  h) U1 M# |
  177. /*typedef __packed struct8 I7 S0 O6 h* ]2 y" q7 v
  178. {, {8 A0 c  ~# n2 o
  179.         MrvlIEHeader header;8 z8 n7 Z5 N' [/ W' @+ N  [2 a: T
  180.         __packed struct
    ' P$ N2 H+ T1 E* A$ Z, U, D
  181.         {
    3 U2 f- b& K- t& [" v
  182.                 uint8_t band_config_type;1 b" Z3 A  j# _' X0 r
  183.                 uint8_t chan_number;
    ( d6 {7 H9 W+ L; z- I
  184.         } channels[1];$ P# A- }# N# H$ Q" P
  185. } MrvlIETypes_ChanBandList_t;*/* [7 I; ^" t* |# w: b( O. i9 Q4 L
  186. 7 K( `5 n! O- |
  187. typedef __packed struct
    1 S3 Q2 r) ?; S* _3 q3 v3 u& d7 E
  188. {! t$ k% }$ s# y, w4 q* H
  189.         MrvlIEHeader header;
    4 ?& L, N1 \. ]) u" \  g/ b
  190.         __packed struct6 H+ U( Y& a* i
  191.         {9 Z/ q! r9 w8 [% R5 _
  192.                 uint8_t band_config_type;# t. o$ B$ A3 ^# Z6 c
  193.                 uint8_t chan_number;$ f9 v1 ~& S6 J4 @) r. }
  194.                 uint8_t scan_type;
    , e* n# N4 R/ ?; J
  195.                 uint16_t min_scan_time;
    8 l& D8 {: R' B) I) g" m8 V8 q! g
  196.                 uint16_t max_scan_time;5 @, ^" v% I/ ?
  197.         } channels[1];+ h7 ?! L, i# Q9 Z
  198. } MrvlIETypes_ChanListParamSet_t;
    $ ^5 u  }) [8 q2 I1 d- f
  199. : e$ x. @& C0 M. A9 L( Z/ m" S# S
  200. typedef __packed struct
    $ n. \: A! k. b+ l+ i
  201. {
    . ~6 u" L; b$ m8 q
  202.         MrvlIEHeader header;2 d; i" b  ~2 G7 _
  203.         uint8_t channel;
    3 i" N# X# X) \1 S
  204. } MrvlIETypes_DsParamSet_t;
    1 |! A3 B( m# B4 Q( E- x
  205. 8 l. q# N4 I& Y$ c0 h- C' H- w
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
      \1 a4 t- U( J, w4 p5 ~1 s
  207. * D0 Y7 ~1 _& T+ J1 Q) ^: N5 l( t
  208. typedef __packed struct
    / U( W4 `5 x! C1 b' T0 m
  209. {7 I: F& G! W& c; U; V. i/ w) w
  210.         MrvlIEHeader header;5 D" J' v& C& a3 d
  211.         uint16_t atim_window;
    % {5 _6 f5 e' Q
  212. } MrvlIETypes_IbssParamSet_t;0 E* o, H$ K2 l3 ^  ]

  213. 4 u* W/ y6 b) Z( @; U8 d
  214. typedef __packed struct* g7 \6 u6 v1 o- L3 A3 n3 O
  215. {
    ( F* c  W9 ]/ N4 P3 T7 T
  216.         MrvlIEHeader header;6 L. r2 d5 s1 e6 l- l: T9 L
  217.         uint16_t key_type_id;6 i! r. r2 z- m- N* o+ D. P+ Q. F
  218.         uint16_t key_info;4 V( |) W: z8 |. H* t
  219.         uint16_t key_len;- U0 S8 Y% J2 b) S" R. C5 `
  220.         uint8_t key[32];0 r+ m9 V) p; d' O4 s
  221. } MrvlIETypes_KeyParamSet_t;
    , M/ f0 c7 i- v( n) w6 r6 g" f9 F
  222. & S& s# l. Y' a  {7 v6 I- P1 Q0 K
  223. typedef __packed struct- |! z" q9 Q' H" a
  224. {4 f; D" h2 H" D- y& h
  225.         MrvlIEHeader header;. ~" A6 u4 c3 X  w3 }
  226.         uint8_t rates[14];6 s5 D' y- a* C: T6 N& |/ U
  227. } MrvlIETypes_RatesParamSet_t;
    . `6 T  R9 o* _: N$ a' M( u7 X, `
  228. + j& U, D) i3 k! t' D+ R# m
  229. typedef __packed struct- x; k! ?& o7 r2 O0 j) _# U6 @
  230. {% Q9 C% i( s4 d6 H
  231.         MrvlIEHeader header;
    2 Z# X* ~- N. A! A# G- B( h6 `
  232.         uint8_t rsn[64];( t, C; y7 f4 R' K) s$ b
  233. } MrvlIETypes_RsnParamSet_t;
    ; q& V- j7 _# [* O% o5 `

  234. $ e5 _- R4 n4 T' v  q
  235. typedef __packed struct
    ' |" L0 R0 {  r3 s
  236. {" g; g8 S* w1 n  A) P7 F  b
  237.         MrvlIEHeader header;
    / x8 b3 E. z% ~0 h
  238.         uint8_t ssid[32];. I  s! Y  p2 |3 ~: `
  239. } MrvlIETypes_SSIDParamSet_t;" D7 o4 h' {# |+ A# J- i

  240. ) q' @& H, x2 K1 t5 Z  B
  241. typedef __packed struct- R& r5 `7 A! z* I0 W+ u
  242. {: @7 H* {& f) K  W  z- d
  243.         MrvlIEHeader header;6 @4 e5 d+ j$ S5 Q7 k( A8 J1 D
  244.         uint64_t tsf_table[1];
    ; K  |3 }' z) p( e6 V
  245. } MrvlIETypes_TsfTimestamp_t;0 w4 j/ R% \- P' r6 A

  246. 4 Q- F: |% o* T+ }' x" ]+ X2 f
  247. // 整个结构体的最大大小为256字节3 I) S3 P1 j7 }3 L' k+ a+ p; {
  248. typedef __packed struct
    ( r9 b2 `# c( |& `
  249. {
    7 j7 @5 @) a/ m: o  e+ _( _/ h: Q
  250.         MrvlIEHeader header;
    9 y+ [. H+ o' y' h" L6 V
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够$ n- b8 g) h. e: S. ^( C
  252. } MrvlIETypes_VendorParamSet_t;8 t% L1 N" H$ h7 e# w! T2 ^# d

  253. 9 k; ~0 V! h+ T" Y$ F) I
  254. typedef __packed struct" ]3 V% o! m/ o8 L2 |
  255. {8 o+ i& t- m1 b0 f: ^
  256.         uint16_t length;
    - E3 t  ?* z0 ]2 B0 @2 a
  257.         uint16_t type;
    : U# A0 v5 K- A3 ?' S0 i
  258. } WiFi_SDIOFrameHeader;
    8 x9 H$ f7 Z% d
  259. ) z5 R7 ^1 _$ I9 [7 R$ v; P- v" k
  260. typedef __packed struct* C6 L' H6 P6 b$ P# t* p2 G
  261. {
    9 _1 ^0 Y& Z$ t' K/ E" L- b5 x
  262.         WiFi_SDIOFrameHeader frame_header; # O, W6 I) {8 j: P
  263.         uint16_t cmd_code;8 R) m4 m3 D% `' y9 J! l
  264.         uint16_t size;
    2 I! }" o/ i+ ?2 d8 _
  265.         uint16_t seq_num;/ N( N. T- w6 n) `: v% _( P
  266.         uint16_t result;# n7 U3 }4 x% U
  267. } WiFi_CommandHeader;
    ( a- R$ K) G5 D2 H' m

  268. 5 i9 m3 U6 v# h1 g8 L# l$ A
  269. /* Table 2: Fields in Receive Packet Descriptor */; Q" S6 Y$ r; H; ~/ g, n
  270. typedef __packed struct
    . P! o' D# {2 o; Z( t% E
  271. {
    6 p+ T+ ?6 r1 `6 a0 X$ {
  272.         WiFi_SDIOFrameHeader header;( n9 N  \+ }1 h, m/ S
  273.         uint16_t reserved1;
    * b7 i" \% `  p2 G$ ]. p( j/ {; x
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)
    & M: I3 i' u2 U! E, F% s/ b
  275.         uint8_t reserved2;7 O  y. F5 s& M: T' K8 R2 z# O6 Y
  276.         uint16_t rx_packet_length; // Number of bytes in the payload
    4 ?( D  L. Y" ~0 b$ V; `
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.- ]& M/ k9 z2 H; n$ u: i
  278.         uint8_t rx_rate; // Rate at which this packet is received
    / j2 `; n1 K: e% }' Y" ~: o( B
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet6 f; J& W8 h9 U, `% g4 c& u7 ^" R" B
  280.         uint32_t reserved3;( @% p% k$ r* h2 l
  281.         uint8_t priority; // Specifies the user priority of received packet
    8 N3 |/ [* s3 O6 ~7 i0 B2 F( \
  282.         uint8_t reserved4[3];
    + Q7 F, t8 a& D$ s! ~% N9 U
  283.         uint8_t payload[1]; // 数据链路层上的帧
    * b& }" g: |, t6 m; I6 y) C
  284. } WiFi_DataRx;' y+ ^5 q  C9 t) w% p; J
  285. " g6 ?/ \6 ^" h0 M4 c6 @
  286. /* Table 3: Fields in Transmit Packet Descriptor */
    - P# R+ m( a# ?0 i$ B8 }1 f. }
  287. typedef __packed struct" U7 @0 V9 z; o. K
  288. {: U- ?6 I! k; p  }5 S
  289.         WiFi_SDIOFrameHeader header;, e/ H/ {+ y$ |, |7 {% e1 @
  290.         uint32_t reserved1;) I0 J6 S( `2 T7 W+ T
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings% J$ E$ A& i- b; n
  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)
    2 b  h8 @+ z' I0 W/ o
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame
    ; u1 T. \/ k6 Q0 N$ w" U" m
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 54 t! R, s, F. M, F
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3
    9 f& x# g% M8 @. Y" E/ j
  296.         uint8_t priority; // Specifies the user priority of transmit packet
      g# R" s* q$ N
  297.         uint8_t flags;
    4 C; \' U2 ^) A  ?- T8 u: ~2 u
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations
      [/ `+ o/ s( \) Y% C4 O
  299.         uint8_t reserved2;. U8 ^& `3 H- ]& V* h, q
  300.         uint8_t payload[1]; // 数据链路层上的帧& _/ f0 @1 U; g6 d0 Z
  301. } WiFi_DataTx;  Y- p: U, W! v; j  Y2 j% ^  [

  302. 1 q6 T+ ?/ S! `4 s8 F+ p+ t9 R
  303. typedef __packed struct
    , k( w4 ~& ^8 U. F# f0 [- r! i
  304. {& t7 Z/ ?/ Z$ D$ x5 y
  305.         WiFi_CommandHeader header;5 C9 E3 k( y) g9 i
  306.         uint16_t action;. L5 j5 E% \& a1 h4 u9 m2 B
  307. } WiFi_Cmd_KeyMaterial;5 @' p" c1 A. L* j! U: r2 U
  308. 0 o( Q+ e* _, J1 G$ d! b
  309. typedef __packed struct
    ! }" ?% L( g3 [0 J
  310. {0 b1 C+ ^5 e6 W
  311.         WiFi_CommandHeader header;
    ; i1 f+ O9 U4 t' }; @9 B0 D" v
  312.         uint16_t action;' c0 u/ _3 L+ G+ j
  313.         uint8_t mac_addr[6];, N& F7 p5 J! k" d: ?/ z* R
  314. } WiFi_Cmd_MACAddr;
    4 e" W, p6 H$ _" b5 }

  315. ! M8 t* h- n& d- q1 S. W3 `
  316. typedef __packed struct
    ! k5 F1 h+ e7 ?$ F, P
  317. {
    : P# x( k- n& l  M  c" u+ X& C8 r1 d
  318.         WiFi_CommandHeader header;9 x( v; u( m* L
  319.         uint16_t action;- a0 q2 `" P/ ?  |
  320.         uint16_t reserved;
    , h& _9 m! @  K) G: p! z/ y" b  s
  321. } WiFi_Cmd_MACCtrl;* `1 z# z- e8 {3 b' ]

  322.   |4 }4 c, I+ T
  323. typedef __packed struct
    / ^2 M! _1 a, C4 c, t% @. Q8 }
  324. {5 w; T$ A' B) |: I  ~
  325.         WiFi_CommandHeader header;, R2 e: m; E+ }) f8 ]+ u% V! W
  326.         uint8_t ssid[32];2 c' `* Q& X, u4 K" @' k' r- R, z$ n
  327.         uint8_t bss_type;- w. D; ^9 {; @1 E
  328.         uint16_t bcn_period;/ F! n' S+ R9 S2 _
  329.         uint8_t reserved1;; h5 z* s4 l5 D: M
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
    ( ?  j( M: R) X0 o
  331.         uint32_t reserved2;, P, `0 p1 K0 Z+ ~
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network
    * y3 T/ _7 ]0 L& B& J
  333.         uint16_t reserved3[3];" N& D0 x! g1 B1 ^) m7 Q
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information5 a$ |" d$ m+ D5 s
  335.         uint8_t data_rate[14];
    ) x) v# S! e9 n; W& L0 Y8 Y
  336. } WiFi_CmdRequest_ADHOCStart;4 y8 V) p& ^3 e" o) H; H: ~6 K
  337. 6 T( ~, M  G3 P* b" }
  338. typedef __packed struct
    . f2 L' X3 r$ Q" I
  339. {: o! q7 J9 w) K+ J0 X5 M' n
  340.         WiFi_CommandHeader header;
    . r/ b( H4 }) ^
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address$ Q" }' D+ G  v* ]+ M- ~
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information0 h/ J  ^- H" ^$ p
  343.         uint16_t listen_interval; // Listen interval
    9 t4 s! y1 \( L9 N7 w
  344.         uint16_t bcn_period; // Beacon period
    ! f+ @- A5 ]9 Q
  345.         uint8_t dtim_period; // DTIM period7 l9 M9 \' ~2 i4 Q
  346. } WiFi_CmdRequest_Associate;, S  E# s( L" b( A& b: x6 A
  347. + ^5 |  l' S* C0 p
  348. typedef __packed struct7 d0 R8 X; I( a# q# p$ l
  349. {( b( m, h9 ^" f  ]* R" ?
  350.         WiFi_CommandHeader header;; G# h5 }9 Q: T( J7 n
  351.         uint8_t bss_type;
    ' d! t2 X4 N5 w: [. z' Y, ~
  352.         uint8_t bss_id[6];* k9 k! `# x; _* y2 P
  353. } WiFi_CmdRequest_Scan;4 U  r/ o& f) R3 }8 `
  354.   s! O" \, T3 F8 F- b' ]) m) m
  355. typedef __packed struct% \2 Z0 M7 A1 a& d9 D: M
  356. {% W3 p* W/ N* [: ^+ V7 B
  357.         WiFi_CommandHeader header;
    1 \: e4 t* o( P
  358.         uint16_t capability;- s& u) Y1 p  r
  359.         uint16_t status_code;% H) g3 q7 m) P- K4 F& j2 X  k/ q
  360.         uint16_t association_id;
    7 \( A& S: {# O$ S4 P/ U/ T
  361.         IEEEType ie_buffer;5 p7 m* N, |" c. v
  362. } WiFi_CmdResponse_Associate;
    4 E  n' h9 a0 e1 @! {3 o
  363. $ Q; e: D2 `6 J- c
  364. typedef __packed struct
    ) K: V& Y- P- d
  365. {3 n, ?/ U; H% b' j) m& n  K2 B( Z
  366.         WiFi_CommandHeader header;3 w0 j1 G8 u: G5 e
  367.         uint16_t buf_size;+ m# R* \2 q, i
  368.         uint8_t num_of_set;
    ! d- {2 b2 B- @! o) |, ~: q
  369. } WiFi_CmdResponse_Scan;
    3 W; Q) a. g* m) n: y' \

  370. . |2 d2 `, Q6 b7 v3 N, w
  371. typedef __packed struct+ @' h* C& N$ k' V3 A+ m
  372. {
    ) i( F3 E( [2 ]9 m& K8 u! w
  373.         MrvlIETypes_SSIDParamSet_t ssid;& V& p* _6 O! M  ]- k  p2 K
  374.         uint8_t mac_addr[6];
    ! o, c8 E8 {1 `
  375.         MrvlIETypes_CapInfo_t cap_info;( {+ Y, F6 l% r9 p
  376.         uint16_t bcn_period;
    , i6 w$ T2 E2 K  K
  377.         uint8_t channel;6 g, O2 M. _5 ^3 Y
  378.         MrvlIETypes_RatesParamSet_t rates;) D8 K) H' P; N" B: E+ m  w$ G! J
  379.         MrvlIETypes_RsnParamSet_t rsn;
    8 q+ _& \4 ~8 d! W/ c2 a
  380.         MrvlIETypes_VendorParamSet_t wpa;
    3 T! |, M" a. B: ?
  381.         MrvlIETypes_VendorParamSet_t wwm;, T; @& Z8 k" w; s
  382.         MrvlIETypes_VendorParamSet_t wps;
    ! G. c# z" L6 m
  383. } WiFi_SSIDInfo;
    ; H8 K1 X- O' h( I
  384. - n3 t1 e+ [' |
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0): w- R/ d, G1 g2 k4 h- ?
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4): z1 C/ d9 I" J
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)+ ]- p. o& U0 T& h
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)
    / l- l: ]$ R( b) y( b9 M- R
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0): R. ^& _% g& e. Z' {' b: \* R! T2 _
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)3 t: C/ M' D; P7 z9 h
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)
    + M9 ~/ B0 w  h% d0 W- ?, \
  392. : p+ ~2 Z  l( e. n( W1 ?
  393. uint16_t WiFi_Associate(const char *ssid);
    ) G8 u1 Q! X# `! I2 W9 Y1 V: ]
  394. void WiFi_CheckCmdTimeout(void);
    * |7 {$ S* b3 e2 x4 z. P  ~
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    ! S: d2 b8 v* `4 u2 s$ y
  396. uint8_t WiFi_DownloadFirmware(void);, j) ^* B  v& ?9 O+ ~9 C- P* a
  397. uint16_t WiFi_GetPacketLength(void);
    # \6 V% J% \5 _5 E  f
  398. void WiFi_Init(void);/ w2 ]$ v9 ~) U) J$ v( E
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
    , S  s5 ^( R5 Y6 H& C, R
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    ( p* S1 l( d$ `
  401. void WiFi_MACControl(uint16_t action);- T& o# m  ?0 \. e5 @2 B2 |' |" B
  402. uint16_t WiFi_PacketPending(void);6 {5 {3 U. }" i3 |9 h$ Y& _4 V
  403. void WiFi_PrepareTimer(uint16_t nms);
    0 @& B) ]! `4 A. C! ?2 c
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);; O$ \% n5 S( z4 x% v2 T: b( V
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);7 q$ U4 r% H4 c
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);
    ( q; c. f/ v3 W6 M  B, D
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);
    5 W7 \" u1 u1 l4 O. y) D+ K! E
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);* c  f* M& \9 {1 A
  409. void WiFi_Scan(void);0 x8 Z! ~7 N2 h8 I7 C1 I
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);
    % o& h4 F2 O; R5 k
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);, @% e( |5 l* v1 G6 Y+ Z; I
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    0 F+ K1 ?0 n* o% g  Z
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);4 ]$ V: \2 Y4 V; ]
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);1 P3 T+ _  k7 A' M1 W* K
  415. void WiFi_SetBlockSize(uint8_t func);  L) V# o& k7 O5 _
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);& |2 G# S& q) i5 |0 d3 Z, m
  417. void WiFi_ShowCIS(uint8_t func);
    8 i/ a/ v. a3 U* G
  418. void WiFi_ShowKeyMaterials(void);
    ' Z' f2 A* M3 l
  419. uint8_t WiFi_StartADHOC(const char *ssid);  z: l5 s  z! {8 o0 B3 [
  420. uint8_t WiFi_Wait(uint8_t status);
    # g, q" K# b0 C3 q
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);8 x: ~" F. K- k: i4 ?
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);3 o, h/ x- h& A. w
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);# n. l" {. O, C. L' C3 ]
复制代码
【WiFi.c】
4 H# ^6 L9 T/ k" s) D0 y/ T
  1. #include <stdio.h>
    $ L; R6 Z  a6 Z
  2. #include <stm32f10x.h>& s2 F" ^! c) i- [. H# A3 G& q
  3. #include <string.h>
    ) J7 ^. R) y5 D3 ~6 u$ t7 t
  4. #include "WiFi.h"
    + W0 W8 Y$ D2 n% D" o1 Q# p% @4 Q

  5. ( |$ Z& v/ h+ ^" l4 N2 p0 q
  6. extern const unsigned char firmware_helper_sd[2516];
    , ]& E6 j# w; v+ x- q
  7. extern const unsigned char firmware_sd8686[122916];% X$ |( e( I& Q' m4 M$ @6 g
  8. : S- ^8 E8 P6 q9 @% U- i9 d5 f
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
    0 ~" @$ O4 S! f" p- d- X
  10. ) O& J) _& R( R- `" ]5 w; T* f
  11. static uint16_t rca;5 ?" W3 A4 y2 t( h3 S  m5 d) ~
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;6 j! ?( H- L1 Y( s# G1 d. V' _
  13. static uint32_t io_addr;
      Q" e! ]# N5 n6 F# X
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小6 p; C  [  C- @8 b
  15. , Y+ F4 J) T* h8 x) g0 v1 ]8 v
  16. void delay(uint16_t n);
    # r: I0 \9 q* }5 d
  17. void dump_data(uint8_t *data, uint16_t len);; i& D' ^4 i/ ]5 l4 U6 x/ l

  18. " t9 G1 x; j! d$ N
  19. /* 关联一个热点 */
    " o" ~& `5 v: I& Q5 @, v% h
  20. uint16_t WiFi_Associate(const char *ssid)7 c9 E3 `: v" S! Y+ N0 Z, T9 }% ^( P
  21. {
    2 S# Z6 P# d5 S- z
  22.         uint8_t buffer[2048];2 Y( L8 }8 {- d* w: T. b
  23.         WiFi_SSIDInfo info;% m7 H* P6 |; ^7 o2 h' B
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;1 ?" X  ]  z, ]  G4 w# ?
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
    ( ], ?. `. e' }& [( v, j
  26.         MrvlIETypes_DsParamSet_t *ds;
    8 M) M% u4 F  d3 k" C" q+ K4 p2 }! M
  27.         MrvlIETypes_CfParamSet_t *cf;* O7 d8 {  o2 n7 V! K- D
  28.         MrvlIETypes_AuthType_t *auth;3 w! G/ e9 Y' _
  29.         MrvlIETypes_RsnParamSet_t *rsn;1 f  l4 X' h7 M5 u& [, ?8 ^! h0 k0 u
  30. ' h2 Z3 O/ l% P' k9 M2 Y
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))
    8 G7 ]2 U0 ~8 v. ]! G1 b5 x
  32.         {
    ( G( H2 \6 l% G* a* @
  33.                 printf("Cannot find AP: %s!\n", ssid);6 I4 A! o; u2 r0 y+ v, P& {0 S
  34.                 return WIFI_ASSOCIATION_NOTFOUND;
    * H2 c4 M# J- t( v. E3 a, B
  35.         }/ S1 y6 u% x6 O$ a( m5 y4 R
  36.         
    * [4 G) m; ~* f2 D4 y0 z; o; Y
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));6 O1 x9 U1 u4 {9 s' E
  38.         cmd->cap_info = info.cap_info;
    2 G6 t9 y# [" ?8 H% l% c/ L; I; u8 N
  39.         cmd->listen_interval = 10;/ m7 l9 D" H( l4 Q: {8 P* f$ \& P" ?
  40.         cmd->bcn_period = info.bcn_period;9 j& m0 a$ `& r/ c
  41.         cmd->dtim_period = 0;" Y  N% I  e1 P8 p2 j* n! W6 ]* }8 I
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));
    9 I7 Z0 \+ e1 `
  43.         ' k- C9 z" }* i) }2 ?
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));& E# Z* k# h/ A, f  R9 K' c
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;# O8 f2 @+ w" H9 D4 s6 N
  46.         ds->header.length = 1;6 c# V, r3 V$ X: z
  47.         ds->channel = info.channel;
    , @, L) g" |; h, ~; S7 a. Y) W* H
  48.         . W, C; P7 d% w5 f3 ~
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);8 ~5 e: X' O' d3 s+ f) e: W5 J& h
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));. L# J6 J) m. f" H% N
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;
    ; E2 c9 E, g: s- L$ M( o( E. m' s' o
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);; {. X- M  A; D9 r4 [% ?8 e( N
  53.         8 _* ]: d/ c3 O- V7 i' m: }
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));
    " P4 A% S9 B) c6 V  P
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));! }" h) u7 f; p7 p- ~  C
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;1 p8 Y/ b2 E$ u) q' O
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);. L  d/ w; b( ]) F; ^
  58.         auth->auth_type = AUTH_MODE_OPEN;
    ' G( _9 d2 P$ N1 T* t$ Q
  59.         
    3 Q, t! \, n+ x5 U  T
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
    9 Y: R% H) r+ R; q5 ?* ~# L
  61.         if (info.rsn.header.type)# X8 d2 p& A% ~2 J5 [
  62.         {
    ; G& a1 g9 x, |/ ?
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接
    ! k1 r( q9 b$ e& ^$ q- V4 O
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
    " p! h( G+ ^$ q- N
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));( @  H0 z6 N- C9 {( |
  66.         }
    7 W2 ~4 L; G. [5 R- S1 p
  67.         else% f, l- r: M+ X; t# e
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数
    5 q  t' a# S/ m' b/ H: O$ [
  69.         
    ' T6 B! D  Q- y+ }+ S7 t. e: m2 k
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))% s$ G) g  j  C
  71.         {! H0 `6 H. l8 X! Y, x( I
  72.                 printf("Association with %s failed!\n", ssid);
      _, O' Y4 W4 r3 X" z1 \2 L* z
  73.                 return WIFI_ASSOCIATION_ERROR;
    ; e: {* j. g# j6 k( M: P
  74.         }- \- j: C/ d1 G- s/ K
  75.         0 P; i# v& d! H! D$ Y% p
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);
    1 a; D; m4 G4 L7 H
  77.         if (resp->association_id == 0xffff)
    $ |/ X5 I& x; T0 o7 i
  78.                 return ((-resp->capability) << 8) | resp->status_code;
    % ~! ~# C8 N9 D7 e5 x+ i0 x/ n
  79.         return WIFI_ASSOCIATION_SUCCESS;
    8 @1 R- p' j  A% @* U3 u
  80. }
    ( ]3 V; x. s0 I' x4 G" k

  81. 1 r8 N( i  z& Z  k
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    ! ~" {, }) e6 m) h9 f$ @& o8 H" T% W4 \
  83. void WiFi_CheckCmdTimeout(void)
    1 Y6 s) L2 C, d; x: b
  84. {
    3 Z6 a! x. z; v, O
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)
    3 L. Z: N1 ^8 X7 \* A, M
  86.         {5 [$ H* S9 V. D: s
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志
    7 I" X) y) O1 K7 l9 ?3 F7 m+ n! l- e
  88.                 SDIO->CMD = SDIO->CMD; // 重发# A  d( W  d- S- a1 K, h& U: i
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);
    $ o! A$ w0 Z/ e# \" s- c- k
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);$ ^: o( H/ I# ?; i
  91.         }
    5 x0 r+ ^' ~' y( Q4 y
  92. }
    # D+ O& ~7 M  _- {7 K
  93. 8 i- p5 L6 \/ E7 t0 U
  94. /* 连接WiFi热点, 并输入密码 */
    3 f! k6 v2 q$ C0 u( R
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)
    5 B  V0 R; B* X  @% e& Q
  96. {
    + \' B! s1 J, x
  97.         uint16_t ret;9 j: j- ]* Q9 u9 d& X8 q
  98.         do" l" n" M6 e0 ^, k
  99.         {! q3 f  l& L2 @
  100.                 ret = WiFi_Associate(ssid);/ b+ W% H9 B/ c* X; e3 u5 k
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)
    " ]& f! b- k% ^/ }! S
  102.                 {6 I0 U0 K" r0 l1 z" v
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);- m% Z$ q1 G; s& X
  104.                         delay(2000); // 等待一段时间后重连' t' X% H! J2 M2 x, B
  105.                 }
    1 f  E4 z2 b: V, ?( A3 Q& T( u0 [
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连
    3 w# M/ V; c) M6 T, g! N2 k& `  c* \
  107.         % D, U: w, {6 l2 _) e1 Y* C0 x
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)* s! t% `3 `( r- R9 o; A
  109.                 return ret;' d+ w. Z+ X2 w% x
  110.         
    ' b2 |1 ]& e5 q' Q, O
  111.         printf("Connected to %s!\n", ssid);
    5 w4 _) y# p0 q* H  Z% h4 L
  112.         return ret;% Y- M  p9 s2 O/ `
  113. }
    4 Z% {6 v6 d" [/ u& G
  114. . ^  R* A( k! u7 |5 c
  115. /* 下载固件 */
    * L$ K- t6 C  q4 [3 |% X8 _7 \
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc
    ( Q2 L+ p/ w5 L7 {  y/ X
  117. uint8_t WiFi_DownloadFirmware(void)
      A/ Q' Z( o" a3 d  M% U) C, |
  118. {
    ) L6 G" S, ~) l5 V$ Z0 o' v7 G* A4 ]
  119.         uint8_t helper_buf[64];
    $ f5 ?4 b6 E2 L! q% D1 Q
  120.         const uint8_t *data;
    ! N; }. v+ C" |4 P
  121.         uint16_t size;4 a$ o$ g6 k+ ?5 o
  122.         uint32_t len;
    4 d. X" ?- C' Z0 J8 P
  123.         
    . k' J0 [( ^: R; N2 w. i
  124.         // 块大小设为32
    % U6 e/ Q2 h. D
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;
    - p: @6 t; x: h0 H
  126.         WiFi_SetBlockSize(1); // 应用到Function 1
    1 c# t: V3 t. l. ^
  127.         9 W7 X: |4 a$ R4 M& C
  128.         // 下载helper6 ?6 U" t, V% f. s" _* F; n
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);& S: Y5 [$ c3 K% ^1 g$ V
  130.         data = firmware_helper_sd;
      k; X+ ~% z+ B& R4 s9 o
  131.         len = sizeof(firmware_helper_sd);8 t# e3 v( C7 R4 O% W% [
  132.         while (len)
    # N! ?0 c# E9 v# k1 D. a0 N
  133.         {
    ! T' Q8 Z. a; C% Q8 T7 y3 e
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量  p% q+ h1 N. c9 U
  135.                 size = (len > 60) ? 60 : len;
    6 m! Q; [  ^" ]4 W: P
  136.                 *(uint32_t *)helper_buf = size;
    # s! e7 `2 H" ^8 E4 `$ c2 c
  137.                 memcpy(helper_buf + 4, data, size);
    ! o8 i2 z# X+ k  y
  138.                
    % P9 U2 v3 a' Z& k2 z
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    1 @0 l1 F) k. R0 X6 o
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));: n& u* }6 p; z0 a( q& z. A6 c0 ~" J
  141.                 len -= size;
    6 k' y2 N1 f/ ~6 ^. }
  142.                 data += size;- Y- k4 n/ M# `
  143.         }
    $ P0 @' o5 l7 m0 m$ z
  144.         *(uint32_t *)helper_buf = 0;
    * K" R" h9 Z! t
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束4 D8 V6 o# Q3 i$ t, v
  146.         ; ?: M$ w2 G6 C: c9 }, k! v" ^
  147.         // 下载固件0 y( l/ B$ F$ P7 k+ }5 b- D# c
  148.         data = firmware_sd8686;' j  G, _9 C- D; h0 ^' b) ^$ G
  149.         len = sizeof(firmware_sd8686);
    ; A& p) ?2 W' g
  150.         while (len)" h) a5 q' ?( U4 G9 D4 y% I5 U
  151.         {
    ( u  G6 _5 w- \4 R+ L7 v& p
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    ; f# r; r7 r& D* g2 E* C
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数' h2 V! a4 ^2 R9 b. _
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);
    . R5 O- I0 }0 j) b0 o. x$ D$ i  R
  155.                 ) A9 I( _: H4 [) r* l
  156.                 if (size & 1)0 k* K, d, b. u
  157.                 {, b( |7 L$ n& f3 S5 W6 P! S- Q
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)
    % J" N; \1 F7 \% i8 d, D
  159.                         printf("Error: an odd size is invalid!\n");$ g0 C; S( E0 f5 O: A
  160.                         return 0;& k! X: B* |' S0 B4 ?
  161.                 }: C$ L  ~5 C8 i% m) G
  162.                 if (size > len)
    8 o5 H3 G2 A0 _, `# U
  163.                         size = len;
    7 |3 _: V: N4 E! s
  164.                
    7 i5 y5 f) Y5 i) F8 s
  165.                 if (!WiFi_WritePort(data, size))
    8 J8 i2 P* t' n/ }- ?
  166.                 {
    ) }5 w# z4 U. P3 z
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);
    1 N- k6 O' v8 l+ z( q. X7 u# r
  168.                         return 0;
    4 p5 u3 m" `" u; g, V' V
  169.                 }
    ' l, G, S, J. ~- g3 Y! p, C* H3 {
  170.                
    & |! w. h6 f; |0 d2 Y
  171.                 len -= size;
    / T0 ?3 t8 Q. c& W# I* y9 D& V
  172.                 data += size;5 B" R; i3 M4 x
  173.         }" L( J8 g) c' S# Z/ K) p
  174.         
    ( V% j$ A8 |- E% d" c1 Q
  175.         // 等待Firmware启动
    - t, c; S/ R7 N- j" ]
  176.         while (WiFi_GetPacketLength() == 0xfedc);. f0 H3 E9 G- B5 l6 G# {8 h! X2 z
  177.         printf("Firmware is successfully downloaded!\n");% |/ x( E8 `) t- V: T9 I6 ^6 @
  178.         return 1;. y; J$ J! m" a* m7 u+ n, V' L- d
  179. }) n3 `+ U& y' Z+ W
  180. 1 Z, ?3 a: ~$ l- e# h" @
  181. /* 获取数据帧大小 */  y( c: \, r( N% S6 j" h
  182. uint16_t WiFi_GetPacketLength(void)% g) C  D; n8 [4 Q/ o
  183. {4 b1 P5 g4 g# E3 o8 q
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);1 I% D$ e7 y- Q/ V+ _: G
  185. }
    3 ^4 I* e2 \) o

  186. ! |& X& F5 p* E/ I
  187. /* 初始化WiFi模块 */2 a- f  x$ o2 q& O! C4 k' X! V
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization% l$ s* I$ x6 |7 x) l# ?* z
  189. void WiFi_Init(void)
    ; [  `$ d7 a6 E
  190. {2 G5 `& n! b+ g
  191.         printf("Initialization begins...\n");" c- s6 x0 H$ t: _
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;- j. z6 ?# [) P; U% H
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz+ j( u4 c% Q& O! `2 ~
  194.         delay(5); // 延时可防止CMD5重发
    : N' w% L2 _7 N- a! Z2 p1 v
  195.         
    ' S; F  z+ F3 j+ Z
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
    ; w" v% m! l4 Z* x. I2 `
  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)
    % O$ m. y3 D: @. ]7 }
  198.         # z" P$ \5 N4 Q6 o
  199.         /* 发送CMD5: IO_SEND_OP_COND */
    1 E4 @, k  ~- ]* w) Q' O, R
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;7 e; M& ^# |' r
  201.         while (SDIO->STA & SDIO_STA_CMDACT);8 C  y  I5 Q) S# Q
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令
    , l8 Y& h% M) w6 T9 a  I% A2 L1 t
  203.         if (SDIO->STA & SDIO_STA_CMDREND)$ t: o3 p, w: ?
  204.         {8 s) S6 j/ n( Y* z( |2 H6 |
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    2 M; k1 A; q' b
  206.                 WiFi_ShowShortResponse();# F5 B% }9 X  {% ?
  207.         }# G1 [, F1 N1 o9 J. d
  208.           L9 e7 |( ]  ], Q7 d
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */; ?2 M; |* t/ V  Z% p* W
  210.         SDIO->ARG = 0x300000;
    + ~! A6 a) V2 Z# a
  211.         SDIO->CMD = SDIO->CMD;
    ! N) u5 a. p* k5 f# M2 h3 n
  212.         while (SDIO->STA & SDIO_STA_CMDACT);
    4 P9 `3 l1 G+ s, f
  213.         if (SDIO->STA & SDIO_STA_CMDREND)
    1 o1 g# B/ G. V- q  ~
  214.         {  M( p" |5 T& o9 \
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;, [" d: w7 M' a! P6 s* ]% r
  216.                 WiFi_ShowShortResponse();7 \) F- O: `8 ?4 B: `1 S9 j' f8 n
  217.                 if (SDIO->RESP1 & _BV(31))
    5 q5 h# ]3 J1 D0 b. ?( M& _- d
  218.                 {
      U# w. V, f' q( `
  219.                         // Card is ready to operate after initialization
    ' c: C: Y: l0 i. D, H  E8 D- N
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);& n: k( C0 X- s5 C& s6 @4 b
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);
    7 i* a0 w( K+ A7 h/ ]  o6 W
  222.                 }
    5 N, H! x# J2 L8 z1 z7 h! o1 m) K9 x3 y
  223.         }
    ' P* w5 h8 _7 ^( R4 }) h
  224.         " q! ?: r  [$ Z7 _
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */
    % ]4 s' E4 y# H) [( M: Q, X/ q) o
  226.         SDIO->ARG = 0;
    # ?6 Q- K: {( W8 ^
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;
    . v0 C. q5 {) w' W
  228.         while (SDIO->STA & SDIO_STA_CMDACT);# X" m  a! ^, `
  229.         if (SDIO->STA & SDIO_STA_CMDREND), h4 z5 g( V% y" x. D- `6 [( J
  230.         {
    ) {2 k' a% |0 f( W2 |  u; L
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;* V' a; Z1 ^- ~8 c
  232.                 rca = SDIO->RESP1 >> 16;0 \+ T1 a" [* m% ^
  233.                 printf("Relative card address: 0x%04x\n", rca);
    9 }1 f, m& N+ ]1 b' m* e
  234.         }
    % R6 Q& l( M( k6 F
  235.         8 O# @% D' O) Q( Z
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */
    / {0 ?; T( g% H) }
  237.         SDIO->ARG = rca << 16;
    ) l0 Z3 g' [& g2 F  E
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
    - [  B" O7 {% _, D% s
  239.         while (SDIO->STA & SDIO_STA_CMDACT);
    ; z6 {/ w- |: ]: {- g, ~4 w
  240.         if (SDIO->STA & SDIO_STA_CMDREND)
    % S" B6 _0 _; t
  241.         {
    ! N6 @& n9 X4 V0 F  D
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;5 l2 k( A* x8 g& p$ K, D* V
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);
    $ a9 q' P, }* B* Y1 f: t# F1 d
  244.         }5 _& b+ z8 E* u; ]4 x7 {
  245.         : Q8 N! a( }! Q4 k# E- o% f2 y; j
  246.         // 提高时钟频率
    . m/ m( X( C1 K( {8 n2 T
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz* R6 P" _/ W2 p1 ^1 }
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒( |! e; A6 ?. B1 A+ h
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
    , D" l5 ~/ _2 c! g* |. P4 P
  250.         8 V3 m" }6 ^- x+ g+ O
  251.         /* 选择总线宽度 (Wide Bus Selection) */
    , _9 h8 g2 K1 d% @" n  F) n0 s
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)
    + d" R, ^6 W# N" [( b0 b7 O( K
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers* d; y5 e5 {/ [* {; Z+ A0 J
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus6 D8 n. Y- f" L. \
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
    7 T0 x5 \3 [+ K& Z' f: i8 S
  256.         ; S9 Q8 Z% u) j8 M  s8 `: G
  257.         // 初始化Function 1
    5 i; O, X) w  S; F6 S  a
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)3 g8 F$ j8 Y8 F1 O' F! G
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)8 r' @2 C# D% x) e
  260.         $ V- p' e* f. ~3 w( V, p2 |
  261.         // 显示CIS信息% X" G* C# v6 S* ^) T
  262.         //WiFi_ShowCIS(0);
    , Z, i, X3 s1 m% _" X
  263.         //WiFi_ShowCIS(1);7 a+ h8 R5 |/ t( H; I9 W4 e% @
  264.         
      c6 e4 h, _- e/ u/ O0 i9 R* g
  265.         // 下载固件1 @0 x  }/ h+ P: t- ^5 L; R3 c
  266.         WiFi_DownloadFirmware();$ A# x4 A* J, g9 Y% d- b
  267.         . U( d" }' V/ _7 |. |9 W: c
  268.         // 设置数据块大小为256字节' h' U+ @0 f0 |1 O% l! R* F
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
    ; @# ]$ f& s8 [5 A$ o. _5 U
  270.         WiFi_SetBlockSize(0);: R8 R2 Z9 V7 k/ @, o! t
  271.         WiFi_SetBlockSize(1);
    7 c  x: ]& D8 u
  272.         
    4 U* O( H. L; K8 I& b
  273.         // 允许发送和接收, z+ k  Z+ w$ {) R' L0 B
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间
    ) `7 ?1 u# o& @" ~, R! s- H4 h/ T
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);  n0 k; q, @3 F7 o
  276. }
    . d7 A$ G' n# v  t2 J5 S
  277. 4 E9 G$ x7 w+ ~& J9 a9 w
  278. /* 获取或设置密钥 */
    $ |; r) z/ W! d1 o+ X
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)
      N; x+ S- H) j# ?; c; ?8 t
  280. {: H& v& Q, f- K$ A6 b! ^
  281.         uint8_t buffer[256];
    - Y2 b5 P% [$ b! a* {* G& u: g
  282.         uint8_t ret_size;' r+ _0 h8 O" I0 d9 a6 h2 o7 Q
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
    5 O1 f6 Y) s6 X) V& t
  284.         cmd->action = action;
    % a: g8 Q) r3 \9 u
  285.         if (action == WIFI_ACT_SET)3 p# A4 J6 V7 c4 e
  286.         {) l. V& u: K9 Z! N8 K. t7 D
  287.                 memcpy(cmd + 1, keys, size);5 E% @4 v% p& Y( H+ J  f
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);
    4 k; k- }1 Y& u0 j& q7 k
  289.         }
      p4 }/ e5 A- F: W6 M( y" P9 P# Y
  290.         else
    + E( u1 o( y* Y
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));( i" i+ h; f% S8 L+ Q
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));- I5 B! ?6 A) O0 G7 Z0 @
  293.         
    # x& X7 u& N, M: x- q
  294.         if (action == WIFI_ACT_GET)3 X( T' e4 W$ o: }- }- A
  295.         {
    5 E" r" v0 F- Y* Q% w
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);, w# b. m* @. r3 @8 b
  297.                 if (ret_size <= size)! |. h/ @; k' f" T: z2 x
  298.                         memcpy(keys, cmd + 1, ret_size);
    % N! `" L. S! R* d
  299.                 else* }+ }' C% R. l' R5 G) p6 f" p
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);
    . G5 B# ]2 A7 `- w9 B1 q
  301.                 return ret_size; // action=get时返回读取的数据大小
    5 F6 b. B) D, ?
  302.         }
    ; \- Z- B3 o0 V
  303.         else) \0 y) M; u- K& P7 Z4 |; x
  304.                 return cmd->header.result; // action=set时返回命令执行结果值0 B: v' W1 a3 m
  305. }
    ' l; Z9 {- ]( ~( A% D. ]( e4 N* E

  306. * o( h5 K) k* g4 w0 M
  307. /* 获取或设置MAC地址 */
      }! ~0 ]8 R, [% [
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)% S5 A, M: f3 p& W+ A+ D# f  s
  309. {! i0 e1 O! e) `3 H& \
  310.         WiFi_Cmd_MACAddr cmd;
    : R' B  m" B: E
  311.         cmd.action = action;: ]$ {# ?4 ]/ u
  312.         if (action == WIFI_ACT_SET)
    8 k8 F/ r; M  g; N. ]8 i
  313.                 memcpy(cmd.mac_addr, addr, 6);
    3 q, C9 c5 [6 {0 U  y0 o8 Q4 d
  314.         ( i" P- ?4 O/ R" c
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));
    2 U, w. k2 P/ [& t: s* C
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));! w7 [( o" {, f' M' P+ p: y
  317.         if (action == WIFI_ACT_GET)+ \# }- U2 L2 s5 z  t
  318.                 memcpy(addr, cmd.mac_addr, 6);7 z# w, c, K/ w# ~5 \( N: o0 E8 r9 N1 T
  319. }& V: i0 j& ~( A  P
  320. 4 @& D! W4 W: G8 a- J- q7 g
  321. /* 配置MAC */
    ) F8 u8 ^# {% z" J6 \+ F" n+ h
  322. void WiFi_MACControl(uint16_t action)
    7 c- N& w- Y# Q5 \/ y6 s
  323. {
    + t9 _' o- y0 S5 z( I2 F
  324.         WiFi_Cmd_MACCtrl cmd;
    ; y2 B; }3 o; Z- c+ \  B* T
  325.         cmd.action = action;
    * W2 d5 m" S7 H
  326.         cmd.reserved = 0;4 a7 k; j, S1 c
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));
    $ u5 s: T2 Y# o7 M1 U8 h6 t
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));4 w6 H* f% ^/ M8 W: R
  329. }+ s" H; K. z9 H$ z; T
  330. 3 H) |0 G. s  I2 X1 n
  331. /* 获取滞留的数据包大小 */) J: A9 d6 v& N, |' ?
  332. uint16_t WiFi_PacketPending(void)  Q" I/ ?5 G& ~$ ]- H
  333. {
    3 W4 V! O8 p7 x2 d, V
  334.         return wifi_pending_size;
    9 j, {9 N$ I  \  T8 h! p
  335. }
    # s! {7 N9 N3 n# @" \3 }3 p
  336. $ y# x$ `+ f0 T8 ^9 h! ~. j
  337. /* 准备好超时计时器 */& G) X/ u# d& o* O- R: w' g
  338. void WiFi_PrepareTimer(uint16_t nms)
    3 h- f. T0 ?% g% E
  339. {) L5 r2 T- _1 n- [7 r3 g
  340.         TIM6->ARR = 10 * nms - 1;7 w* W* x; V' R6 }7 B6 `8 b/ O
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz
    7 i  X: _4 K& Z, o
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置
    + `" L$ S" U6 t8 i: T' g
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位: T4 }! y% w$ G6 i4 h
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式" {5 E; N  k. a6 H. e& I7 y. O
  345. }5 Z# Q" s1 J% \- d* Z
  346. 4 ]5 k; }! J1 Y9 ^( p
  347. /* 读寄存器 */
    : i; F- M/ X; e3 R. m
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr), k+ B8 F2 x/ F7 k) m
  349. {: n+ q' T' h+ o/ i2 X3 A- }" ?
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);
    , b9 t! m3 a$ I2 y! x* {3 P; q
  351.         if (SDIO->STA & SDIO_STA_CMDREND): Y, k" t) Y8 g% m+ Z! X6 g7 d
  352.         {
    & @0 N1 ]( j' S  [
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    7 }5 ]1 F: R3 B& ?' i7 ~
  354.                 return SDIO->RESP1 & 0xff;2 a' g. S! M( |5 m2 P/ R2 K
  355.         }9 b/ |: f; T# c- J0 N" h
  356.         else
    " N7 ]% A# y* c/ B
  357.         {
      k, s5 x3 F( f2 b: k
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);
    , ?+ i4 b6 u/ ^9 q0 A
  359.                 return 0;2 p" R- ?* f! K, m$ Q+ @# g
  360.         }2 ?; I6 X) y/ r0 M! p5 i
  361. }
      U+ M+ N  M7 H/ Z$ s

  362. * |" ]: I" g$ L
  363. /* 读数据 */& O; h; l5 }* u1 d* N! m
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小, c7 h! X3 _6 W
  365. // bufsize=0时, 只读取数据不存入缓冲区
    ' Y6 |% P# \8 T+ \
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)6 _* X$ B8 E2 E# c
  367. {5 {8 r; S" J3 O# p
  368.         uint32_t len, temp;
    % i6 Y9 B) {. y/ y0 K4 \
  369.         if (flags & CMD53_BLOCKMODE)
    7 ^# v$ N& A  Y! S/ c9 F
  370.         {
    ) e7 ]* J) J# L: ]0 w$ h: H
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数
    6 y, r8 C( B, M) n- M$ D1 a
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
    # q9 d9 E$ B0 B
  373.         }
    . C. w) s6 ^- L( }
  374.         else
    0 o9 Y# {, ?# w, Q& R/ C
  375.         {' V/ U! F4 |7 [( D+ {) O- j( b
  376.                 len = count; // count表示字节数
    ( |7 F: L& h8 l0 o& L5 \
  377.                 if (len % 4 != 0)2 q' ~  _$ Z$ J5 H
  378.                 {
    5 J+ w  ~2 c8 i/ G
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍4 e2 n6 l& _2 D2 ?
  380.                         count = len;
    5 x: V" K& G' T. [. `, c% m
  381.                 }( H* [, j2 |# N& v
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式& n% ?' Q; \: S" o9 e( Q
  383.         }
      N' C, }8 k& F
  384.         SDIO->DLEN = len;
    # L  H3 J" G1 t* E2 [6 p8 _
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
    $ F0 w# b* _( r0 }. ]0 c
  386.         ' K& M. L4 [5 O# b3 X  _
  387.         WiFi_SendCMD53(func, addr, count, flags);
    ( k& s1 s, W; F' O5 h
  388.         while (len)7 ?" C: A1 @" b1 _& s* W
  389.         {; s; s7 h0 q6 p3 \/ ~' M9 I3 J! d6 {
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)9 b8 Q+ V3 Q5 B8 _; [% u& A. W
  391.                 {3 A( ?2 n! N( h6 w9 Q9 e
  392.                         // 若有数据到来就读取数据6 O# Y# N0 D' G9 {- h  y
  393.                         len -= 4;$ y* d# i6 m+ v
  394.                         if (bufsize >= 4)3 C2 K0 M8 O  R$ K  _  u+ F: J
  395.                         {7 n* }! V6 w& D. ~+ f' A
  396.                                 *(uint32_t *)data = SDIO->FIFO;# q$ |  m: t, C
  397.                                 data += 4;
    3 ?' N2 O$ E+ r* ]3 i
  398.                         }
    + R0 W( p8 x2 Z$ s) Q3 e. f$ p
  399.                         else
    7 `- p( M! B, ^& v' K. ^' R9 `, t
  400.                         {
    " P5 H; a9 F8 X# T" I, S) r9 J! k$ R
  401.                                 temp = SDIO->FIFO;( p: s7 c! z7 ^3 z) [9 b6 K# U; t
  402.                                 if (bufsize > 0)0 O/ s2 O5 A& ?4 J0 [4 L9 s
  403.                                 {
      U. {) h3 L0 L* ]1 o; {% W1 Q
  404.                                         // 写入缓冲区最后1~3字节5 Z# {  N3 ]* @& ~
  405.                                         memcpy(data, &temp, bufsize);/ s3 k& c8 o  }4 c* x1 T* K
  406.                                         bufsize = 0;' H- B& F3 u8 F5 f
  407.                                 }6 t, t: S* |# m
  408.                         }
    : m/ j& v6 p( O6 \' ?; g0 Y
  409.                 }( L4 k- z: [8 J) G
  410.                
    # @$ R5 {1 p- l6 G' [5 r
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)  _  s/ V3 l. v# A3 x$ Y+ S
  412.                 {  T5 |/ E" ]8 F9 m  {+ X, d
  413.                         printf("Data Timeout!\n");
    7 p; g; c, u" Y4 e
  414.                         break;
    ) X3 Z8 ^' d/ B7 A
  415.                 }' _5 q* Q5 y( Z; _5 C/ ?% s. u; E
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)4 D# N6 U+ o# O# E7 p
  417.                 {& W" F6 g& u* k+ B- Q
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    , S* _0 ?: }* o% \
  419.                         break;
    1 d! u$ C; Z. N% n
  420.                 }
    ( i. l" m- \( j% F* V) c
  421.         }+ s  t6 k7 m' H
  422.         $ q4 Y) ~* h* }3 b, H+ ?
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));2 c! ?8 [# f/ P$ R2 N+ n
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;- _) z8 V. ^5 H( x1 c2 H* Y& T
  425.         # O0 ?, ?3 y% w' Q
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;
    # S  E; |- D" B) D9 ~- l2 J& m: g6 E
  427.         if (flags & CMD53_BLOCKMODE)
    5 }4 T; D) ]* F/ r
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
    5 p7 r9 E% }' ~& W! J) ~
  429.         
    4 r% e' [: Y6 `6 M
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功' v6 n0 m: i4 n1 A3 H. `. @
  431. }
    . G' b; S- O9 t( @" s
  432. 5 H$ q" @* x% C. Z
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)- a: _; _5 i3 Z6 d
  434. {
    ; d$ `0 q2 J# b, o, }
  435.         uint16_t block_num, block_size;6 N! g4 _# s& r1 K$ \- j- G8 x% Y
  436.         block_size = WiFi_GetBlockSize();
    5 x# a: ^) H6 Q5 C# J3 ]
  437.         
    ; y2 V0 s$ F8 B! T1 _
  438.         // 读取数据1 p$ A+ g  s( E4 ^* b* O5 {
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1, P* k' \" }1 X4 K
  440.         if (size >= 512 || size % block_size == 0): r7 f5 S: V- j) y: J1 L; p
  441.         {
    0 H2 ~' T0 m+ z& |
  442.                 // 采用Block模式传输$ K) `( Q4 D: Z) Q
  443.                 block_num = size / block_size;. t/ _' L; A5 K( F2 R
  444.                 if (size % block_size != 0)- n2 R+ C: _0 _9 N
  445.                         block_num++;
    4 \; H2 Z+ Q7 h+ k- N8 I+ }: v6 o
  446.                 7 O0 G; `) l# Q( }
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
    3 y! ~% C* ]6 N# o. C9 ^6 Q
  448.         }
    ' F* Y! q6 c- Q8 i# t
  449.         else# T7 X! v' g4 B+ ]2 F7 I  x2 q
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);+ f" U* S- |0 |. J. r$ X; ]% T
  451.         
    . ^8 U5 A, S& o6 X
  452.         return SDIO->STA == 0;
    ! e: A. d1 ]* ]8 }# O( s1 V
  453. }4 z" i# }6 T- l5 R. k, @# }
  454. ' E$ [' R  ]1 H. v) z6 w& x
  455. /* 接收数据帧 */
    9 U& L* j# r0 m- ^
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)4 K6 H4 M% M: }$ U* L' a
  457. {
    + `. f( B2 o) ^, C
  458.         uint16_t size;9 v# @% n2 ]! J: C6 f9 z7 E0 Z
  459.         if (wifi_pending_size)/ Z! m$ _) }+ f/ z7 ?5 @- U9 Z) m
  460.         {) H# l  M$ ?0 P# }
  461.                 size = wifi_pending_size; // 先读取滞留的数据包* m5 l! q7 w  w; S$ s3 ]8 r& Q
  462.                 wifi_pending_size = 0;- m$ Y! m; V  M1 |) u. @6 S
  463.         }) j" n2 u! E8 b: h( [. J, N( @4 H
  464.         else' a/ [6 ?/ n; d
  465.                 size = WiFi_GetPacketLength();
    : n! E: A% f2 k5 l: D) ~
  466.         return WiFi_ReadPort(buf, size, bufsize);  ~# Q& h) U9 q" q$ k' ]
  467. }
    # W3 ~4 i6 a- ]+ S

  468. - T4 D! F- Q$ p; E. M7 K; t
  469. /* 接收WiFi命令的回应 */
    6 L+ k% C* ^8 N, ?% T& y
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)9 J' A. Y2 t% f. I9 r( j9 {
  471. {
    1 X$ C: a7 U, G4 c
  472.         uint8_t retry_cnt = 0; // 重试次数  s  Z% Z( J* W& [3 ]. D. L
  473.         uint8_t wait_status, resend;
    5 l* v) Z( O3 [7 Z
  474.         uint16_t size;$ u; i; j1 ~/ Q
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;9 L* A8 U. r0 C8 O- W5 ?
  476.         WiFi_SDIOFrameHeader temp;" G3 N2 k' V6 X/ l
  477.         4 n  V3 L9 K7 l
  478.         // 等待数据准备好
    ; L* ?* T9 N- a9 R" M# t
  479.         do
    ! h3 w" G* o5 v. s
  480.         {0 O3 r, j' b) B  y8 l2 G
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);5 j4 M+ H* j0 R# z( S6 P
  482.                 % K/ d9 q, G; L1 |5 f
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息
      O- e- J- M" I( `0 _" x, e
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
      ]4 `( y" @& k. f' @0 T
  485.                 {
    $ h  O9 y& D+ I6 H8 V3 J4 W, g) m
  486.                         // 若读到的是一个数据帧, 不是命令回应; @6 M" v' o- C5 W- e1 u4 {/ j
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功
    / f  ^) i* ~3 Y
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);! r) E: ?( `. `$ V# N
  489.                         wifi_pending_size = temp.length;
    2 E6 u5 E  z6 h
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算
    : S0 }# d! k) _6 k1 v
  491.                         resend = 1;
    0 s+ ]  Z1 l" b
  492.                 }
    $ j$ b3 M: A- D4 i2 n% g
  493.                 else if (wait_status == 0)4 W% j5 B( b. M! Y
  494.                 {
    2 T$ Z  N: c7 D( A- U, r/ F
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)
    $ F5 }! Z& v, w$ v* @0 C
  496.                         resend = 1;. z- \1 ]8 d, T' I8 e4 W% x7 u
  497.                         retry_cnt++;/ ^5 h; R) E- E) Z' t$ y2 i
  498.                         if (retry_cnt >= 5)
    5 N  E! o- R- T/ q$ z# R% s
  499.                         {& D/ h$ ^0 p/ }1 b$ Y) A
  500.                                 printf("No response!\n");
    0 s( K7 c, f; v, ?0 U
  501.                                 return 0;- Q5 _; u/ A' P1 r
  502.                         }7 C7 d) x, r( ^& ]& s, `. B) C3 L  W
  503.                 }
    . [! N- h( J; f
  504.                 else
    " m4 ^% F6 y% m$ P3 X
  505.                         resend = 0;  w( l: \! t1 _  e! r0 J" n+ l! }# S5 P8 }
  506.                 , T/ L3 o! q8 g1 q' v) M& p
  507.                 if (resend)
    5 E1 p) p: e# c
  508.                 {
    8 c! U2 D2 P4 b5 o8 I
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)$ a, ~% s3 @+ b5 T5 u7 M
  510.                         {+ S& x4 r) \7 q  k5 F% I5 j
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait) F8 l3 i* P/ J1 X
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);4 ^" ~/ ]+ W* o4 o" U' y
  513.                                 WiFi_ResendCommand(buf);2 y# h" T! B/ K* Q$ y
  514.                         }
    ; w' N3 _& _2 x( n" m
  515.                         else
    9 C* h7 Q7 r' r; X% V
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出
    * y' x# ~9 ?8 A7 h- V0 E& ?/ y
  517.                 }
    9 U$ n- B# P8 ^
  518.         } while (resend);% f% y! x1 ?( w7 }1 K
  519.         
    % x9 Y; \5 h4 w
  520.         size = WiFi_GetPacketLength();1 d' k7 @3 ~* q  C  ?" K7 h
  521.         if (size > bufsize)
    ' c. o8 _5 h$ B7 a7 F
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
    4 @, f6 @9 X$ v+ S; ~
  523.         return WiFi_ReadPort(buf, size, bufsize);
    0 T9 w5 g) \. A8 ~. i8 l9 Z
  524. }
    ) c6 ]" _1 }( S4 u! B: t5 a. q' r
  525. $ ]1 \5 Y+ Q: ?1 A: }
  526. /* 扫描全部热点 (仅显示) */
    " y9 f  O1 ~) S* f
  527. void WiFi_Scan(void)& K( H1 K- R& |+ P* Z3 Z
  528. {
    ) Z( ~$ k) b% Z/ T6 V8 K5 m9 I
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组4 H& B$ J6 [- B; ?# q: t
  530.         // Stack_Size=0x00000c00
    ; s) G+ \+ f1 O! p+ n& I  f
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放8 t! ]# A& R5 ]; R7 I( A3 ]
  532.         uint8_t i, j, n;
    6 R7 {  ~7 {9 h/ P( Y! |4 V
  533.         uint8_t ssid[33], channel, wpa;- a* u0 W4 m3 B. t, V
  534.         uint16_t ie_size;
    + l& `! ^( M# J$ [
  535.         " K( \% c5 H. ?4 `" G
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
    ) N$ n) Y; L/ n- b; X/ d
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));" o4 \4 d% Z5 l' U4 S" q$ E
  538.         ! W6 _9 a1 N8 G9 p  b, d; b
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;
    - L1 W  e! u$ e" r. E7 e
  540.         WiFi_BssDescSet *bss_desc_set;" I$ P8 M1 o9 Z5 v8 A- y
  541.         WiFi_VendorHeader *vendor;; ]. I' @$ @* [( B+ n
  542.         IEEEType *ie_params;
    9 Z5 Y! S% ^0 r+ m- F
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;# Q) \3 p$ e& X+ Z# Q. Z  T
  544.         ! r5 a+ J) Z: _% _+ E. t- W8 ]
  545.         // 分4次扫描14个通道8 D# L  X( g6 }
  546.         for (i = 0; i < 4; i++)# d- |# p( R+ T0 M3 }+ [
  547.         {- P4 R& `. R. `+ T
  548.                 cmd->bss_type = BSS_ANY;
    ' t1 X5 Y: k) |1 P, L; \
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    8 U/ X% [. K; B( \! s6 L0 s- P" B
  550.                
    . c$ ?- D% o% q5 u, {5 R' F
  551.                 // 通道的基本参数: X" ]/ N: X# ?! O8 E! o
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数7 G+ q# V" `8 h' w# c/ X3 d. e
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;) P8 N  ~( r+ }9 h) Y
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);
    - G  F8 }8 a8 J! f' f
  555.                 for (j = 0; j < n; j++)
    / R" q5 Z0 ]% g! I& N) ]) Y
  556.                 {
    3 ?5 @! s/ ]3 ?( V, }. ?+ ^
  557.                         chanlist->channels[j].band_config_type = 0;
    + [) v, p; j' O2 y3 a7 ~
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号: W; r; a5 y3 Z3 ?
  559.                         chanlist->channels[j].scan_type = 0;8 b) j$ z+ F& D7 F- Q' `4 i
  560.                         chanlist->channels[j].min_scan_time = 0;9 w& Y1 W2 I: Q0 o
  561.                         chanlist->channels[j].max_scan_time = 100;
    5 v' `5 y: D4 X  e" _
  562.                 }4 @( u; w# }/ ]. G1 q- T. M
  563.                 ( A! _$ _( @% d2 f( x5 Z9 N
  564.                 // 发送命令并接收数据
    . ~6 h6 \7 T1 o& t/ l
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);+ Y/ N8 D6 r! H* d: l1 |
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉7 ^9 x2 j9 w8 j2 R" J
  567.                
    3 |! s7 p# M0 W  I% ?+ l3 Z% O
  568.                 // 显示热点信息, num_of_set为热点数, \1 N! D+ ?- o- l: o, v
  569.                 if (resp->num_of_set > 0)9 |# X7 ~3 k) L/ U6 p/ m
  570.                 {
    # ^+ n& k! `' y; f; h6 I. Q
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));
    , j' D; j& T6 `& d
  572.                         for (j = 0; j < resp->num_of_set; j++)
    + R5 ~& K3 v6 y2 ?6 [4 O
  573.                         {
    ( L( n% {+ I/ W! w$ E! ~4 d$ M
  574.                                 wpa = 0;
    ) N4 A& x$ A& D; W6 z1 z
  575.                                 ie_params = &bss_desc_set->ie_parameters;6 X# I, x- t- J; t5 A
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    0 T# r8 Y% l7 I6 `3 J* y! \2 J' a
  577.                                 while (ie_size > 0)
    / y$ x+ Y; @* H- l" S5 a
  578.                                 {, e) ]% y$ N- k& x0 ^
  579.                                         switch (ie_params->type); O0 n  ]# K, Y0 D: Q
  580.                                         {
    9 R, V. \3 B# E. P8 L
  581.                                         case MRVLIETYPES_SSIDPARAMSET:
    0 m' l, C! B; b- R0 N" i! y! Z9 u( M3 T
  582.                                                 // SSID名称1 N) l) ~# \! J( Q1 a/ j3 w7 L
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);" Y/ w, S4 J% |7 D; _
  584.                                                 ssid[ie_params->length] = '\0';" y+ L5 b8 |( w) d* `8 r: l; o
  585.                                                 break;
    % T5 o! L; c6 A1 `; U1 F9 m
  586.                                         case MRVLIETYPES_DSPARAMSET:
    , E  A9 ?% |- x  |- m
  587.                                                 // 通道号6 K0 s4 g7 z1 C; r2 w+ I4 f7 D; u
  588.                                                 channel = ie_params->data[0];
    7 r8 h2 T4 k4 x: Z& U. x
  589.                                                 break;3 g* I9 }6 V- t+ M8 j6 J% ?
  590.                                         case MRVLIETYPES_RSNPARAMSET:
    , \0 }5 {& H1 X9 b
  591.                                                 wpa = 2;
    9 }; J& q& _& u+ Z/ u4 J" z/ W
  592.                                                 break;6 R  B0 u8 Z8 s" E
  593.                                         case MRVLIETYPES_VENDORPARAMSET:6 g# r4 |7 j6 ^5 H- D& i; U+ w
  594.                                                 if (wpa == 0)( q5 ^7 U+ X+ M, O0 b; t9 D& Y
  595.                                                 {; q# {- u& G; f/ ^
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;
    ; A2 I9 h1 Y, z3 }
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    " Z! M7 z: l% c& c6 ?1 A3 X9 z
  598.                                                                 wpa = 1;
    * j; G6 V5 ^4 X$ p, g6 \
  599.                                                 }
    7 L; Y  M- K! Q3 P9 Y7 I2 G) c
  600.                                                 break;! _7 z; V5 Q9 m3 G2 e, m  T0 R
  601.                                         }
    , f" T" z6 B9 A8 c. |: ]! e% W: w
  602.                                         ie_size -= ie_params->length + 2;& ]8 T% O3 B7 J& M+ v* f# ^4 y' O
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    8 ]" n5 C9 I8 R5 h4 S2 C
  604.                                 }
    0 t7 D. N7 }9 c* [: N
  605.                                 if (ie_size != 0)
    , C7 {/ D- c$ X7 m! `' T! r% T
  606.                                         printf("ie_parameters error!\n");0 C9 _, p2 ]' n( J  Z. }
  607.                                 
    4 U5 c0 N6 H* A$ y1 g
  608.                                 printf("SSID '%s', ", ssid); // 热点名称" d9 l8 \  H, y. h$ d2 I
  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地址
    + x0 K6 {3 w) _1 b/ |
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号- I3 w& F) u0 D& Y5 E: e, V
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);5 B" V6 r: I/ f2 p; ]
  612.                                 - {9 t! G  S$ P' _- J! I- I
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);
    . _" i9 W% D; F
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)
    % H" e# `1 f8 X
  615.                                 {
    ' r4 y1 E5 ]1 Y5 A
  616.                                         if (wpa == 1)4 R' m4 d2 L5 ]- w' n# w- W5 b, ^
  617.                                                 printf("(WPA: ON, ");; a" I: _% }. |4 G) G) a
  618.                                         else if (wpa == 2)3 a) C; E0 Z9 p# h1 D; i* [6 G
  619.                                                 printf("(WPA2: ON, ");) i* p2 t9 ^! ]# X# C9 Z& x" ]
  620.                                         else
      G. i8 ^, e( k# v) I
  621.                                                 printf("(WEP: ON, ");
    ; U1 k" r! h( K( a
  622.                                 }$ U2 |5 ]# }% ?! U
  623.                                 else
    9 U$ n& p+ j5 ?7 S3 V
  624.                                         printf("(WEP: OFF, ");
    7 @- o. F  y- j  I' G6 }
  625.                                 
    ; [; H( z1 b: d3 V( W8 s
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)" A! v* O+ G8 V8 C! m
  627.                                         printf("mode: Ad-Hoc)\n");
    1 S( z; j' Z7 v" m) F" X
  628.                                 else5 N0 U% J$ e+ V* H$ G% i
  629.                                         printf("mode: Infrastructure)\n");
    ; e6 |& y; [& V. S" r
  630.                                 " v% Z( x# h7 X3 f  p
  631.                                 // 转向下一个热点信息
    : p0 J8 u/ Q& i( J% U* L
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);
    " @1 m4 k! K; y5 P
  633.                         }& l) K0 I( w3 {+ w$ _3 J
  634.                         
    7 S: }% V% k0 S) i) p
  635.                         // resp->buf_size就是bss_desc_set的总大小7 M: S& D3 v4 ]5 U
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size, E7 G! T9 X2 Q4 ~/ \/ O& f
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;- V2 K6 i$ G% e0 I0 z  l
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))
    : t& p! a& ^. {& x
  639.                         {
    2 o; y; c, F) b# R  u0 y
  640.                                 printf("Timestamps: ");
    $ X3 ?% |. a+ }: X1 z0 Q1 }
  641.                                 for (j = 0; j < resp->num_of_set; j++)
    , B* ]6 J7 T' i2 ^+ t& R( C8 Z
  642.                                         printf("%lld ", tft_table->tsf_table[j]);- S8 `7 }( m. |
  643.                                 printf("\n");/ n7 }6 S" E2 r, X9 f
  644.                         }*/
    1 _( O6 V/ X% v. `% B4 H
  645.                         5 a! y. U3 g8 u5 j
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table, n: H7 v) t; E7 u  |
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)
    ) K/ G  d2 C! F
  648.                         //        printf("data end!\n");
    4 k4 C* v- l7 \, `/ {$ z5 L
  649.                 }6 k" R6 ]* V5 y; m8 H% Q0 K
  650.         }
    & G% u* r+ y% P+ }( G
  651. }
    9 ]! z9 K; w) B2 K" k4 y2 a& V. c0 E3 ^
  652. " n5 p" A; ^0 I$ B, q: t
  653. /* 扫描指定名称的热点 *// k6 X( V3 n6 a2 c9 d; R% ?. j
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大
    % {$ \' G8 i) B9 W+ ]/ u6 W8 i: U
  655. // info用来存放从buffer中提取出来的一些常用信息" m  w& [2 R& m# p
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize): {( ~" D. y, l; ^1 r# K7 I
  657. {% _" H3 i, F, }, i+ ~) L$ s8 x
  658.         uint8_t i;
      j% H1 b! C: \) L. U6 I# x- d0 q
  659.         uint16_t ie_size;, w3 l* {/ L( O7 ?
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
    * G( ~+ K/ _- ?0 t
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;8 _7 A5 J3 g2 [0 {" T, ]
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);* q9 [. b0 j9 q) d4 W6 ]* j/ _7 v
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;1 F: q2 z, J. u/ C. N
  664.         IEEEType *ie_params;8 b3 ~4 i! V  O0 S
  665.         WiFi_VendorHeader *vendor;
    ' p) X  a& Q8 O1 B, M# l) d9 N
  666.         
    ) P! H# V& f" S+ ^1 Y: Z  g# b8 c+ @
  667.         cmd->bss_type = BSS_ANY;- \" {4 O+ C- d! R  S
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));. ]# I2 Y5 P( ^1 b5 S+ `& Y+ v
  669.         ' m3 X5 p" D$ I; P6 R
  670.         // 添加ssid参数
    4 [1 d; v8 t# p7 K) O
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;  P1 c$ }% c- a( w
  672.         info->ssid.header.length = strlen(ssid);; n+ F$ F6 R( k/ W; }) c2 D! u5 q
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);
    . G' f% z4 s0 F
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
    ! M; _8 A! `6 C  C0 r
  675.         
    3 K% Z; o2 E4 V  N3 Q3 I  b6 g
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));
    3 U) r1 X0 k- q- v
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;
    $ C3 @0 q  Z2 L6 G
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    0 s4 u4 g, C- B% v9 m7 k
  679.         for (i = 0; i < 14; i++)
    $ }' Y+ D) ^# a7 q$ T% d' \# X2 z
  680.         {$ L* a" _5 R% h' D) X3 z% O
  681.                 chan_list->channels[i].band_config_type = 0;4 r) E0 J( P9 T3 D/ ^
  682.                 chan_list->channels[i].chan_number = i + 1;
      g7 ^$ H' ^) o* B+ w
  683.                 chan_list->channels[i].scan_type = 0;
    ( l, A- R4 I$ K! b# n5 {- N3 ^) I
  684.                 chan_list->channels[i].min_scan_time = 0;9 F5 B2 p* u6 O& _+ p
  685.                 chan_list->channels[i].max_scan_time = 100;9 Q/ B% \6 J3 Z* v5 G
  686.         }9 c+ I+ I* u, E* U  J
  687.         - P$ U4 k5 c4 A: z% Q4 f
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));
    " q# I' H2 v1 _8 e
  689.         wifi_timeout = 3000; // 延长超时时间
    ! l) y1 F& u0 k# z* X
  690.         WiFi_ReceiveResponse(buffer, bufsize);% K0 T+ j* y1 R2 e! D9 E. l2 n' \$ u
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;4 }4 a! t5 Z( {6 Y8 G
  692.         , @9 r# N/ [1 d4 Z" F: W) k7 ?
  693.         if (resp->num_of_set == 0)$ x, f" Y& h$ x5 j; I; H4 C% l
  694.                 return 0; // 失败/ a7 g; W! Z( z
  695.         + Q. u8 Z5 |9 t7 g* _& H' _
  696.         // bss_desc_set以扫描到的第一个信息项为准
    ; F9 u; ?6 U' @' c& R4 I
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));6 f, T/ h" h9 q( n* m
  698.         info->cap_info = bss_desc_set->cap_info;
    9 e8 U/ ^- z  j: l  `) T
  699.         info->bcn_period = bss_desc_set->bcn_interval;
    + {0 N! I" g; {1 n
  700.         + V- T! H3 u* \0 i
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0): H/ E, B; Q5 |( }% h1 q0 c
  702.         info->rates.header.type = 0;4 z* i& Z) l& P2 n- [* |
  703.         info->rsn.header.type = 0;( ?' [, r' c& n
  704.         info->wpa.header.type = 0;% y. b  ^: g. \& V- \7 b
  705.         info->wwm.header.type = 0;
    # h$ T7 [9 D9 w, o% u
  706.         info->wps.header.type = 0;
    ' A' w/ j+ u* G5 E
  707.         6 ^+ @$ z- n( Z6 ~+ M) I. j1 T6 t
  708.         ie_params = &bss_desc_set->ie_parameters;6 T! v) ]. ^; e1 u
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
      l" i5 o: E7 Z! ]( Q. p$ [; R
  710.         while (ie_size > 0)
    % e" \( F* P  q+ p, X
  711.         {
    + h5 i  ?, Q" G% B
  712.                 switch (ie_params->type)
    & g. f4 D+ \& [  h6 l- p; W& l
  713.                 {8 i1 u& W$ q5 ]
  714.                 case MRVLIETYPES_RATESPARAMSET:# L6 ^# o- z5 o) K% c" }
  715.                         // 速率# }) h. P0 D4 B' Y6 y; r: L4 N* {
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;' O) y7 ]; y2 M2 J7 R
  717.                         info->rates.header.length = ie_params->length;
    / r) J. F: p8 j' T) L
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))' [0 x, r, c" e7 }. r" W4 Z
  719.                                 info->rates.header.length = sizeof(info->rates.rates);
    0 N* V3 M2 A/ g2 O# G  E
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);
    / I7 y9 `8 j1 ]
  721.                         break;
    0 c  X1 X9 G" x( y9 o
  722.                 case MRVLIETYPES_DSPARAMSET:+ q1 a) ^8 F. }! I( [
  723.                         // 通道号) n$ C) B3 j- z& {/ @3 K6 A, V6 F
  724.                         info->channel = ie_params->data[0];( ^* J7 ^9 a, T4 ?
  725.                         break;1 \4 y! b9 S' K) I
  726.                 case MRVLIETYPES_RSNPARAMSET:
    ) N) s$ U/ ]; v, k) [  ]( M
  727.                         // 通常只有一个RSN信息 (与WPA2相关)' W$ e  V# a: g% |# @9 @' A# \/ `& r# G
  728.                         // printf("RSN len=%d\n", ie_params->length);
    - A. A4 N  `& _2 [  O
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
    + u1 l: b0 [0 s2 E6 f2 P0 u% D
  730.                         info->rsn.header.length = ie_params->length;3 J/ L# L1 a; T( }7 Y
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))
    & ?! @- t1 i9 J5 H& ~
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);
    5 _& [' l. F  z" \
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);& p. i. v- t) l  [! ]) B9 t' x& }# E
  734.                         break;
    7 E1 \2 B* M/ \1 @$ p  V
  735.                 case MRVLIETYPES_VENDORPARAMSET:
    0 t5 W4 T  X, ?& P0 N- C; g! P9 y
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)& W; R+ z0 N9 g, T- P$ H
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;* D) D2 n, ~7 G! {
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)
    6 b! N. T5 ^/ z/ x0 t9 c1 x/ F: B
  739.                         {! T: ?' e  R8 B, L( M
  740.                                 switch (vendor->oui_type)
    0 r% `3 p( o9 s) d: t7 _
  741.                                 {/ z5 I) E" R7 M: x
  742.                                 case 0x01:
    : D: q9 D1 `0 W4 A) H7 _5 D/ O, |
  743.                                         // wpa_oui( t' x  I! B* u) ^
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;
    * E7 {( C7 p6 }' X, e# F" O
  745.                                         info->wpa.header.length = ie_params->length;; ^% O1 Z# w4 y- V
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))
    2 W, a3 ?1 R% G! t3 n+ I6 R* h
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);: p0 ^4 H5 A! _' Q4 K- h" k
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);1 ^& I1 L; G6 S- [. k! k
  749.                                         break;4 ^$ t' I3 K/ A5 D
  750.                                 case 0x02:" Q1 O; y3 |* B" N3 X; q! J. k
  751.                                         // wmm_oui
    $ d% _0 O, O9 m  L7 }  g
  752.                                         if (ie_params->length == 24) // 合法大小
    ; U: [/ p6 y7 {  ^
  753.                                         {2 l9 Y2 _, t+ @$ n- Z# |/ j
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;! z2 F( W1 e1 X! G1 C) y
  755.                                                 info->wwm.header.length = ie_params->length;
    2 t. X) x; [( V1 |; N* F' f  F
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);2 ~$ o, R, d( ]$ r  x
  757.                                         }
    # o5 f" d8 H. N, i9 x9 v$ t
  758.                                         break;6 }6 c" a/ _3 d0 }6 U1 f+ S$ r
  759.                                 case 0x04:7 ]6 v8 G0 v3 u9 ]6 a
  760.                                         // wps_oui
    . I8 B1 N9 ~4 h
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;# o* K% g8 N9 t# t6 p
  762.                                         info->wps.header.length = ie_params->length;" z" _* u1 H4 V0 L/ C( b2 {0 b! k
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))
    4 v8 K6 n' u- H( L# z
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    0 E- t. g, L" l) ~
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);* g6 N% x+ |3 u, h/ G
  766.                                         break;
    ! [; _7 [4 x6 [' z& O
  767.                                 }+ v! j0 U% p* _1 u/ G9 }
  768.                         }
    # a5 J  r3 F4 ~& {% Q: Y, V, L
  769.                         break;
    4 B% h; G- [( h/ z* d
  770.                 }
    ( U5 `% ?, P& y9 S9 x- m; X# C" x) W
  771.                 ie_size -= ie_params->length + 2;0 z6 U2 @8 w3 B- x' _
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);9 w0 O# ^8 k; d* d
  773.         }$ j! o$ x; i0 o; f: R
  774.         4 Z! L$ N/ w! `/ ?9 |- Q
  775.         return 1; // 成功
    6 ~9 V! Z4 U  l" O9 d2 Q
  776. }6 C+ q0 I* e  Y1 Y# d5 ~. O- H/ d* _
  777. 6 V  f6 J4 s- P. W) ]
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)0 M8 {( n4 B" N; V& z8 v. n  k
  779. {+ ?9 a- w0 s% g6 R* Y1 n0 H
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
    : E) d9 L9 }0 e# P: O
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;& |1 M. l( a* R6 T8 \
  782.         while (SDIO->STA & SDIO_STA_CMDACT);
    2 l# v# G% }% J% u( O' Q5 g
  783. }6 z$ t2 _7 n; |3 }
  784. : ]" x, [1 N" ~8 T! I. q
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)* @# w0 ?& O  Y6 k, x9 ^* [
  786. {1 A5 A! O. K/ I/ |* Z6 q
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求2 g! M+ U: h) F) X! `: A8 y
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;
    # ~# R# |- X3 U. _2 p; L2 C
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;4 A; {. ^* k. {4 k9 H
  790. }
      G6 m3 G& G4 ~4 M* T

  791. . B4 _  t  Z& k1 c$ S
  792. /* 发送WiFi命令 */
    7 O) J& ~" r# y* o3 e
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)& m$ u, m; a. L9 V% p) s
  794. {7 ]/ i% V. p/ N( C" b8 K
  795.         static uint16_t seq_num = 0;
    4 h. q2 Q5 a5 Y' ]0 D: l; e+ Y; x
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;: d. r) \2 W+ Q
  797.         , h  T8 L7 ~! @- h9 h; T
  798.         if (size != 0)7 C6 d* i' O7 m2 e2 }# @% u" R
  799.         {: y' A. m" |; K8 ^! d6 y" E
  800.                 cmdhdr->frame_header.length = size;
    9 _9 k! q0 x: a' b; U
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;7 ]  u) l. V9 e3 w/ H6 N( ]
  802.                 cmdhdr->cmd_code = com_code;7 B- Z: {  _' Y" k. X; W! F
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部
    0 P$ ~- p- a; a5 @4 D
  804.                 cmdhdr->seq_num = seq_num++;
    * Z1 d0 ^$ [, a$ q
  805.                 cmdhdr->result = 0;1 Y5 Z. ~2 r. A" q
  806.         }& Q" b1 T0 M. Q
  807.         else
    % P/ K& H& n" i% x) L
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
    ; q* D: ?: q8 A3 h* ~
  809.         + z7 v$ o; W( H, P! i# d7 D3 f
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃. N  S0 Y* m1 R7 v& y; o
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived()): C! X7 g" l% Z9 l* e
  812.         {
      F5 X2 K. d- C, }* i* h+ f
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");
    6 u4 J) i6 _. Z3 D3 R# g0 @5 r; z
  814.                 WiFi_DropPacket();
    7 t0 e4 o0 T" i6 R+ n' \9 H& p. P& b
  815.         }# `& L9 B2 E# t7 E) s
  816.         
    ) @4 w9 M. j$ |
  817.         WiFi_WritePort(data, size);
      a3 e! K' [3 J* z) M3 M" q
  818. }+ I/ w; H/ V( t4 ~' c

  819. . i* h& M" X+ K' E
  820. /* 发送数据帧 */
    6 w! \( x5 g6 y
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)% K0 K9 a' ]$ y- `0 H8 @
  822. {" E0 H7 P& C, J8 y) c% z
  823.         uint8_t ret;
    % j" r) r) R" C
  824.         * t3 E( n! q6 }3 X
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
    8 }2 W" T: k5 W* u; a+ q
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
    - V. H+ `/ y3 e& ]+ D" {8 D
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;
    ) \9 ?# [" N9 e! q9 |5 k# x
  828.         5 {: n7 p: a6 g7 m) e7 I! T* }7 N
  829.         packet->reserved1 = 0;0 G$ q7 k& m2 X
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings4 B7 Q+ M1 M& t3 z: K- r
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader
    & K& N3 i( [* v3 c
  832.         packet->tx_packet_length = packet_len;; m4 l3 h3 b. ~: Z- k. W
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);
    ' c. C8 _) F1 K7 S7 i$ \7 \
  834.         packet->priority = 0;' @3 \1 Y; ?6 k
  835.         packet->flags = 0;2 v5 j9 I* F& F. }1 e! J
  836.         packet->pkt_delay_2ms = 0;* Q0 F7 A# t4 m# ^$ n7 \: o4 o* n$ C
  837.         packet->reserved2 = 0;" W% B$ j5 P" L: ~7 [0 D( N2 H. k
  838.         
    / L" q5 u4 e+ d5 G9 P+ j" M* {
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小* D! `7 a+ f% q4 W( v/ |- U% w6 O
  840.         // 未读取之前不会收到新的数据帧% p$ _* G' C" n' G4 Z
  841.         if (WiFi_PacketArrived())
    , ~9 K4 B0 a1 t  r/ v7 l3 A
  842.                 wifi_pending_size = WiFi_GetPacketLength();* P- c# ^4 V& ?6 t, ]% }" r1 a
  843.         : D" S( L2 z) v/ G3 S. X
  844.         ret = WiFi_WritePort(packet, packet->header.length);( K% f8 J; p7 K% _3 A
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
    7 ^/ v/ h+ F7 L8 ]
  846.         return ret;
    $ e7 ]! u- j" b, d) n
  847. }
    . b+ P3 Z$ \  U/ E% v
  848. ( w4 w0 D# ^1 s, n7 o. x
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */
    ; V  I& ^- ^+ u- k  U: |
  850. void WiFi_SetBlockSize(uint8_t func)
    : Z# X+ V3 V% [( H
  851. {
    9 B. ^8 \; D+ C" ?; k
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)
      a( a6 {9 H2 D1 l  i+ m( h
  853.         uint16_t size = WiFi_GetBlockSize();
    / H5 R6 z& J* h* v8 Y
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);) L8 G( ~$ D. D! j
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);1 J8 @5 K6 v+ [$ q# b0 x
  856. }* J* r. \* {+ w  d

  857. 7 S% I4 m) f0 m( o  {. ?- K: }; E' [
  858. /* 设置密钥 */
    2 s% g0 y8 H  L
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)2 z9 B! S; E7 `( z  n5 ]
  860. {
    2 w( _: v' u. c9 e4 Y4 i4 ?0 J( ]3 Y
  861.         MrvlIETypes_KeyParamSet_t key_param;
    - s$ O& ~+ Q8 h. |8 ]& P. ~* u9 Y: }
  862.         if (len > sizeof(key_param.key))
    / C5 t# I! {  z% C/ G
  863.                 return CMD_STATUS_ERROR;7 Z$ X3 B. y0 r
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;
    3 O1 m+ \2 J2 K: g
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;7 S$ X5 k6 ~6 R) r8 V
  866.         key_param.key_type_id = type;$ D: e5 g: {$ n. {
  867.         key_param.key_info = info;- h2 |* e: d+ N+ O6 x8 D; i
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
    % o5 B. G- c, Q7 e8 k" C4 d
  869.         if (len)0 g3 X) ]/ S8 Q+ a5 @( `; H1 d& r6 v
  870.                 memcpy(key_param.key, key, len);3 H' d1 P: E6 Z) F% ^4 c' Y
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    , s# |3 y' Y! f; u/ z9 z
  872. }
    ; T( T" A: g' z( E5 X

  873. 8 R$ {4 `' e) l8 _, w0 Y
  874. /* 显示WiFi模块信息 */
    . a9 G* X+ U3 K, n$ g6 K' P
  875. void WiFi_ShowCIS(uint8_t func)
      C; C' _% G, Y! C
  876. {0 [9 c: V& e8 Y4 I; S4 ^
  877.         uint8_t data[255];9 f8 r. P, {6 W# a* r6 J5 g
  878.         uint8_t i, len;, e  x6 K0 @  O+ Q2 s2 l
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure
      O: @5 r" e+ _' T8 l; N
  880.         uint32_t cis_ptr;$ t) O+ c$ ~" k* S# {6 ]
  881.         
    / f0 y7 {3 e/ t+ C. Y
  882.         // 获取CIS的地址
    , M" L  V/ b1 f5 @2 E% ]
  883.         cis_ptr = (func << 8) | 0x9;
    6 ?& g; _8 k; N3 ]- m+ K
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    % `" ?7 L- X% @9 o, {! G9 X
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);
    % s: U) K2 E3 Z# u1 O
  886.         
    ; t) A! }9 W6 y; V
  887.         // 遍历CIS, 直到尾节点
    ! y/ @! B. S  v' ]
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)
    3 z# P% H! K; ~, @5 \/ r! E
  889.         {! s/ m" @( N: j
  890.                 if (tpl_code == CISTPL_NULL)
    ; Y) G' x  x# x! y  Y
  891.                         continue;
    7 m% h% O% d4 T& [4 a8 L
  892.                 2 v! }- j+ k$ M7 h7 s1 {. J
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小' ^. g- Q. ]; Z' ^, Y' D
  894.                 for (i = 0; i < tpl_link; i++)! O3 d' L' n. j7 t$ ]
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    # J- P0 E  p9 R1 _9 o* [
  896.                
    # T  `: @( ]8 O9 I! h9 \; y: p7 ?
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);# n! h8 ~9 J  k+ }, M/ ^$ W! @9 j
  898.                 dump_data(data, tpl_link);
    # ?# l& L! [0 ]8 C( V
  899.                 switch (tpl_code)
    5 T/ a9 A% X5 T( O$ v; ^; m; Q
  900.                 {
    3 r" r; L: j3 P: P9 u; @
  901.                 case CISTPL_VERS_1:
    7 Z2 x8 _# Q: b
  902.                         i = 2;1 s+ z0 m8 C3 B; {' f3 x' D( N2 _
  903.                         while (data[i] != 0xff)
    9 g: \# E- ?7 A: I$ l: N% m- G* m
  904.                         {, A, D# K" A. V. w
  905.                                 len = strlen((char *)&data[i]);" @" t* L0 L0 O6 F* F/ `1 q
  906.                                 if (len != 0)
    . D) k1 H: ^" [" g7 `8 G' P4 r4 O, b
  907.                                         printf("%s\n", data + i);
    2 m- T4 E& N& N- k) G
  908.                                 i += len + 1;
    ; U# O- h4 X; E
  909.                         }
    6 z4 q6 f7 U. |2 T) L3 d
  910.                         break;0 F" ~' g4 s6 W! \3 k
  911.                 case CISTPL_MANFID:; L6 Q% H% S% h% \" I
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple
    ! C4 f- _+ z. N7 `5 s0 Q+ J4 R
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF1 u/ K# o$ P8 g2 }
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD
    9 L# q  k- t- b& A0 u# [. W, d
  915.                         break;
    0 u% g: \/ ]! F- W( K
  916.                 case CISTPL_FUNCID:
    + q! G! m! U7 Z( ^
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
    2 d% O8 `8 k7 W; d, u+ a1 {# O
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
    2 }, j% l+ `) Q  D7 `- l
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT' b( g  E- N8 h1 s0 O+ {" x
  920.                         break;
    / w$ u, D2 M3 I1 p, `/ Q
  921.                 case CISTPL_FUNCE:8 v; I9 Z3 P! y; ~+ K9 u+ u4 P
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple. G% }) W0 H  b( [" a8 U
  923.                         if (data[0] == 0)
    ) s1 v1 g7 V$ N+ I
  924.                         {8 \+ r+ c; b7 S( X( m
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)) n: b( y0 }( X6 r1 F0 a# f5 w
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));
    + c+ [# m: i9 H6 r+ A
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);# O6 K/ }  j& Z4 L4 |
  928.                         }
    7 Q2 w8 S4 a1 n- w
  929.                         else
    3 B7 N3 b2 m# Q# R9 V& l
  930.                         {: S5 g9 t# `! L- y; E# [9 n# U
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
    ( C" q  r4 M) i7 E3 S3 Q
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE! J; q6 N' r0 J! J6 M7 p
  933.                         }% J1 F0 h" ^& _9 s( W6 x2 q$ P6 D
  934.                 }
    9 T1 f' U1 M# ]9 T, \
  935.                
    , k, R4 I* F, }+ B- x2 ^# Q* x
  936.                 cis_ptr += tpl_link;9 v* ]0 M* e. A" H# N( \
  937.                 if (tpl_link == 0xff); `5 J* }- ~, G" y4 w
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点
    7 R  u2 L- c9 e# }  N4 O9 }
  939.         }
    ( t) v/ V+ G$ w. w7 [
  940. }; e, c4 ~( W" ^. d9 D) O
  941. 7 A( ^+ I/ i; Q# u; h
  942. /* 显示所有密钥 */" f8 h* |" \" n* R' @3 N3 }* |
  943. void WiFi_ShowKeyMaterials(void)* b8 C! \  E+ J$ A" _
  944. {
    $ ?( q! J% i. I5 r" M
  945.         uint8_t buffer[256];
    : n% E% }9 p3 n) {, w# T& d$ O* J5 l
  946.         uint16_t size;
    3 f$ d7 a. T6 E$ U
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;# S! h% U4 _- ?' H
  948.         5 ~7 e, @* r, z  m0 n# c
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);
    0 I( a8 C: N9 t6 b7 d$ o1 m' `( U
  950.         while (size)
    7 Y6 S6 |+ ]# z3 h
  951.         {
    , t2 c) N. [' V2 X& P
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
    - c# C+ w" r) m" P0 }
  953.                 dump_data(key->key, key->key_len);
    8 S3 q5 F6 F  P- m5 r# o1 k2 H
  954.                 size -= MRVLIE_STRUCTLEN(*key);
    * I6 m: n; f: J# _2 f" q
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));- h) b$ [% V) o; i) {) E% i( C
  956.         }. I( c8 v! r( R. T1 n, ~. a
  957.         if (size == 0)
    1 N# M( L8 u+ |$ y! {+ v, t. U( |
  958.                 printf("data end!\n");$ e0 v; z" F7 [% q
  959. }
    * g+ F6 E: L: t. a6 T8 y

  960. # j- r7 {; C- m5 i" ^
  961. /* 创建一个Ad-Hoc型的WiFi热点 */
    2 x6 g( Q. s# b1 V: b$ J: q
  962. uint8_t WiFi_StartADHOC(const char *ssid)6 M9 s+ ?& \. G) e% _) D/ P5 F1 T
  963. {) |3 f1 U% O! o' S
  964.         WiFi_CmdRequest_ADHOCStart cmd;
    * A! V" o% H( A3 `( j1 T+ G
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零; o# q7 ?5 l* N
  966.         
    - t& P" }* q. |, Z
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
    # Z4 h% |6 g1 B2 v$ X- Y+ w; X
  968.         cmd.bss_type = BSS_INDEPENDENT;
      K2 V9 q1 o1 o& {$ _0 f( o0 l
  969.         cmd.bcn_period = 100;
    & p* N6 M; A" Q" c
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;
    1 g6 w- B# d7 n& W/ B
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);
    ( r: ]4 b' n  Q6 w5 J7 |
  972.         cmd.ibss_param_set.atim_window = 0;: f- r3 m8 L& ]& i# k  K, f# X
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;/ l7 `5 A3 }' S, S
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);1 o! ?$ |1 `$ o9 [& x  s3 r
  975.         cmd.ds_param_set.channel = 1;" t2 ?9 A" p9 A) T1 y& B8 `" n
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;6 F1 g) t, f4 e! d( H# o1 v
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;
    % R4 A0 ~: [- ]/ a% p; C  z
  978.         5 T$ y0 L  I  n6 X/ {) K
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
    & w+ _. M4 L& Q
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    ( K4 Z8 D$ g- k
  981.         return cmd.header.result;
    5 L* I% c* B) K* i
  982. }& F3 W: ]* d3 B, o4 O" h' W/ Q3 o
  983. $ Y1 D0 y/ I9 [1 m% Z% ^, D
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */
    / B7 o$ `7 O2 |
  985. uint8_t WiFi_Wait(uint8_t status): X2 T# j' k# f: c
  986. {: M8 q5 n- ~9 b. t5 u6 M
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    7 m; ?' h! {- {, V. M
  988.         WiFi_PrepareTimer(wifi_timeout);
    4 A, _9 ~$ H' D
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)* |& E8 a3 i) ~* o; d
  990.         {$ ~4 t6 W9 S  w
  991.                 if (TIM6->SR & TIM_SR_UIF)
    # \& ^2 K1 z- t
  992.                 {  r' A; A  U. ]
  993.                         // 若超时时间已到
    / k+ R7 j  ]0 s& q- E2 i7 n: r8 v+ Q
  994.                         TIM6->SR &= ~TIM_SR_UIF;4 v  X) C3 t8 R  |# \
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);
    ( P. ?5 o. R- c' `  L
  996.                         return 0;
    6 H3 |4 _, G% |% i9 ~& g
  997.                 }
    3 I1 M: k0 h/ c4 v; ^
  998.         }
    9 `0 x2 _; u  x
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器, m: y4 q/ o# X0 u
  1000.         return 1;. o# n: A1 b/ B& A2 k
  1001. }
    8 A9 u2 [  W+ M9 {& `! ^
  1002. $ \$ R" i2 e5 M+ Y, Y
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */
    & b8 @9 l, Q2 a* u& T
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)
    ; G1 W! I' `/ u7 h
  1005. {
    ' s& h5 f. i0 ^3 ?: e
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);3 @4 p7 _  S% h# ]
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)! V% K5 W5 b. ~' j+ h. ~3 A
  1008.         {
    ( S% O$ [$ e0 z( i
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    % u, O% X7 t7 ^+ Q  p: t, B
  1010.                 return SDIO->RESP1 & 0xff;, i" ^9 ]: \9 w. _& o. K% m
  1011.         }8 _( s1 S8 j1 S; E+ m
  1012.         else4 @1 V. t( o) A8 _- x% \
  1013.         {! Y9 R3 D2 D, T1 W8 c9 E* ]% p) |5 p
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);
    8 T0 ?, I% U, `6 M
  1015.                 return 0;' W: u7 D% t+ J" G/ T
  1016.         }
      _9 e9 A( [/ x7 o2 n  L- M
  1017. }% V9 g2 l" j6 {9 b  l; c" Y
  1018. . V3 D7 Z1 W4 i8 k+ k1 c
  1019. /* 写数据 */
      L: {* P' |) ?7 T% P# E/ _# D
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    3 s, G  c( ~6 r1 V1 s1 H
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    . x8 P$ T4 n, |3 J8 H
  1022. {
    * Z- g0 j& l  B( @
  1023.         uint32_t len, temp;
    ! o; F0 H+ |% [$ C) |
  1024.         if (flags & CMD53_BLOCKMODE)& ~  K: p6 |) P  y& ?! B
  1025.         {
    - P* J/ @* \) l( ~5 \
  1026.                 len = count * WiFi_GetBlockSize();2 {% {6 i9 D4 A/ i. i, W0 j
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;+ q% E' S' z  r
  1028.         }
    ( u5 H" H' t- T8 Q0 h' f
  1029.         else5 r' S; i! e5 N! |# w' p
  1030.         {0 z# b; X8 J  ?" P4 k
  1031.                 len = count;
    ' k) W% @' @2 B) ?- g
  1032.                 if (len % 4 != 0): n4 x3 c* \, S- `9 J
  1033.                 {
    & E3 y8 Z; \3 w- u) a
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍( k  M: U: r% j& r9 E4 C
  1035.                         count = len;
    & {$ Q0 _5 p7 L0 A. ?  f
  1036.                 }: s2 q0 [2 B% p; g- q3 q
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
    : P6 u; T# T3 I4 t$ o+ v
  1038.         }: y  l" i: L$ S
  1039.         SDIO->DLEN = len;
    7 o  O+ a  M( }6 O# \0 |" n; H( [
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块+ u% J1 @2 [8 c9 T' p
  1041.         4 b8 ]3 a* _# N
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);
    1 @0 {* D7 I) c' Z0 A# C* }
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);3 X: C; X/ h: w2 G% G  j/ o+ }1 |  e
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0)2 e. J, w- Z8 J/ a
  1045.         {
    4 w7 i$ u% L/ h+ p6 g
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");$ v. s. @6 `5 N9 ~( U+ r
  1047.                 return;
    6 w$ Y' h+ j4 x
  1048.         }
    , i6 S0 U# z$ |) d8 g% m/ A' g
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;7 u! _* z. n4 d2 A
  1050.         
    / k, t- K( \/ Y* u9 ?" J" R
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据" g6 w: s; d4 a% ^
  1052.         while (len)0 D$ I. q( d( C. U
  1053.         {1 I+ C8 d4 O, N  E2 \
  1054.                 len -= 4;5 r. S: ^1 ?* E5 s9 B1 l
  1055.                 if (bufsize >= 4)$ i( X$ C: ?. E, u8 e# v
  1056.                 {7 {8 P5 m, W) G" v% `8 O) U& r
  1057.                         SDIO->FIFO = *(uint32_t *)data;7 U: r- o7 u3 I7 [6 E' k$ m
  1058.                         data += 4;
    8 f+ c9 n. t+ E, f+ v1 o$ X- R/ k( i
  1059.                         bufsize -= 4;
    ! {$ x: O6 n4 ~; d! R' |- Y$ Z
  1060.                 }: u1 g) f! m! n& `6 X$ {' m
  1061.                 else if (bufsize > 0)
    8 F, E# v3 A3 m$ e  x5 y
  1062.                 {" i0 W5 E, d% _; q4 h2 i1 S
  1063.                         // 发送缓冲区最后1~3字节
    $ @" E& z0 I0 l, `
  1064.                         temp = 0; // 不足的位用0填充9 p$ ]9 H# P$ @3 g
  1065.                         memcpy(&temp, data, bufsize);! T  l# B. k9 U: X. M* q
  1066.                         SDIO->FIFO = temp;
    3 y! L$ }* B: q5 c( S% ~
  1067.                         bufsize = 0;% h1 V* E- T% y9 R4 j
  1068.                 }1 Z& @7 v& x/ |
  1069.                 else
    0 v' ]! h) S) T. e4 H
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0
    ) P# A' _$ v1 p4 I, l( x
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待- ?% f+ z5 ]4 P! b7 ~, }
  1072.         }$ ?8 K) z2 o; ~
  1073.         0 X$ d; G8 o  |5 q3 z( Q
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕) E  {, x# Q& F8 `: u
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
    ; O8 |) j" u1 ^( k, z
  1076.         # O8 y8 J" K& H8 y5 v- ?" j
  1077.         // 清除相关标志位
    ! [. m* a0 j6 R
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;/ h5 o% Z, Z, \7 c
  1079.         if (flags & CMD53_BLOCKMODE)
    4 C: K2 b8 L3 K8 G/ v
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;
    # ~, B$ k" u6 N: a8 \
  1081. }+ w) ]! x. O. f

  1082. - \3 n+ Z. V" M# P3 v  T
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)
    ' I% _4 b8 H) ?6 m  P* j5 b: I
  1084. {' h' Q2 G. W6 l. n/ Y" u+ X
  1085.         uint16_t block_num, block_size;+ x5 q# L: |1 Y6 Z3 B+ m' u
  1086.         block_size = WiFi_GetBlockSize();
    6 Y6 m( \& e% |5 n* h% C5 z
  1087.         
    2 g# s0 v% r0 j; Z4 \) Q1 y! G3 M2 {
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    4 [& [" X- V3 B  v" v
  1089.         if (size >= 512 || size % block_size == 0)
    4 A! T  B! A- A, ?" k
  1090.         {" ]- C7 @. ]3 j. d8 s$ r
  1091.                 // 采用Block模式传输
    3 @: L: K1 L: P. N
  1092.                 block_num = size / block_size;
    8 R4 f. v) q* l
  1093.                 if (size % block_size != 0)) j9 {$ P0 f* _8 c# O2 Y" x3 ~! X, n
  1094.                         block_num++;
    7 W/ P6 ~7 @/ c; I6 K; }7 B
  1095.                 9 |' v$ }6 H1 S) b$ k! N6 Y
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);
    2 |4 _$ `0 V4 z- ?  Z- Y
  1097.         }  j5 k# t( `" M& ?+ Z  c: k
  1098.         else
    3 F% H8 B# Q+ {7 u  ]% t: l5 f, w
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);
    $ p) |" a2 K2 e- r
  1100.         return SDIO->STA == 0;' K5 Q8 b1 F8 m9 T5 v3 L
  1101. }
    " \+ ^7 ?  u; V1 L2 U) v9 }
复制代码

* D6 W& h* A1 w$ ~7 n7 k: k; X1 {- Z/ r! e# u
在工程的所在文件夹创建一个lwip文件夹。
0 T0 D) Z' q, w( b9 i; X" A( Q然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
# B  W6 r( e3 l: w8 [8 }0 n
% N( D' u; n( i. R+ qcore/* \; ^" Z! a/ R
core/ipv4
. y- v* ^2 Y$ o8 i# dinclude/lwip2 B9 Q' M4 t8 e+ W- J
include/netif) w. r; t, [/ p% }% {8 l( W
netif/ethernet.c& f: l* v* S4 P1 C  r( N8 z5 R
netif/ethernetif.c
! ?4 F" X. Q& o. C' a! P2 q1 i: l2 ]1 }
  B; p3 b, u0 x4 ^) p$ s- r解压后,将里面的c文件都添加到工程的lwip分组下。& }) `+ D8 W3 v) ?% ]* i1 f
具体添加的文件请看下图:
$ }& v, B! y5 I# X2 N) O" w) c$ A1 [  e% f1 v

2 L- c5 N2 V* b接下来,创建lwip/include/arch/cc.h文件,内容如下:
! C1 c2 a, B% a4 i
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:# t- N5 F( Y$ k% K4 e4 [) T
  1.     #define NO_SYS 1 // 无操作系统  
    2 m3 b& X# ~/ j( y, R
  2.       2 i8 r5 Q) r8 Z& D
  3.     #define LWIP_NETCONN 0  
    ' A  T% y9 M( x, B. Y7 _
  4.     #define LWIP_SOCKET 0  
    6 c" @$ X4 `. X! z2 n
  5.     #define LWIP_STATS 0  & @+ i% H- c' Y* g' D& i. O
  6.       . {3 g( l8 |6 {" @% S
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  % O2 z2 V! v  c  w" H
  8.       ; t! L: O, I, t7 O( X/ ?
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:, z" y: D5 y- }
  1. /**' u7 Z6 i0 y4 M. ~4 J( d" i
  2. * @file' M0 u/ R8 a8 G3 g! u+ d
  3. * Ethernet Interface Skeleton
    9 ]( A+ t: W8 F& u6 \  |3 h( Y, }
  4. *4 g' a4 P( J4 ~: }" j7 Y; _+ [9 x
  5. */; E  x* P: ]1 {( S

  6. - ^2 N* J8 s7 n! D+ `- [7 i) ^
  7. /*
    9 q2 e5 K7 p: l- k, E  u
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science., P7 Q+ M& n$ ]0 n! d, Y
  9. * All rights reserved.$ ~9 V5 `: O) ~8 o$ y1 D: J
  10. *
    , ~+ p- X+ u) }8 D* h, U4 G
  11. * Redistribution and use in source and binary forms, with or without modification,
    $ F- Z( O9 P, j, a1 ^; i
  12. * are permitted provided that the following conditions are met:' ?+ v0 y7 t& p; a
  13. *
    8 P/ Z: s7 p+ g  Z
  14. * 1. Redistributions of source code must retain the above copyright notice,
    # ~* d5 G# B* A2 r6 {/ {
  15. *    this list of conditions and the following disclaimer.) z! `" x% u( W3 U) n' B3 `3 v, l
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,4 Z; j, j4 t! P
  17. *    this list of conditions and the following disclaimer in the documentation& Q. [; j' \' ~8 |: h( p0 t, z
  18. *    and/or other materials provided with the distribution.
    * l+ o' A$ }$ c  @( t, s$ W' P* k
  19. * 3. The name of the author may not be used to endorse or promote products
    / X& O; X3 X  a( e! Y
  20. *    derived from this software without specific prior written permission.
    # M2 p0 h, h# L7 s: }
  21. *
    , V7 B) o: O% Z
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    6 R/ m$ p5 Q) v! s6 |- N* E8 P
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+ i0 E1 N0 c2 O  P, Z1 m
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT: F+ i2 C! G" N. n9 ]
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,5 ]/ |) x' ~5 u8 k0 h$ T
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    1 |2 l5 ^$ `, I. s& H! D  R
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    ( `! X& D5 X6 V& b: r0 A) c
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN* r6 Z1 R: |8 ]2 Q
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    ) j% h; S6 r7 Z( Z3 W/ ^# B
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY) o9 m' }# N4 h: \
  31. * OF SUCH DAMAGE.
    4 i1 e6 w* _7 g( e
  32. *
    , E8 `; ~# W$ M9 d. k( H
  33. * This file is part of the lwIP TCP/IP stack.
    4 f9 O- H1 r0 n& u+ A" Y9 [
  34. *4 s4 I6 V' |  L: J+ H
  35. * Author: Adam Dunkels <adam@sics.se>
    9 C/ N) Q. @" a" r/ k( k" V+ \& ~
  36. *
    ' h7 u( ^9 T4 B; q  D6 S- D
  37. */
    6 p; S) ]" J- M8 _+ U

  38. ! y+ r. g2 e, y4 D3 ?
  39. /*+ ], L+ F% _# d$ R3 a6 m/ [! k4 p
  40. * This file is a skeleton for developing Ethernet network interface, H+ s- [5 ]* p
  41. * drivers for lwIP. Add code to the low_level functions and do a, p5 S* i8 P# e
  42. * search-and-replace for the word "ethernetif" to replace it with
    * R/ U7 Y1 h) j$ `; ^
  43. * something that better describes your network interface.
    2 G5 S# }" J' P4 I- m' ?
  44. */
    3 t3 H* ^6 E2 G
  45. 8 Q9 ^$ R# Z4 ~2 @2 x
  46. #include "lwip/opt.h"9 u4 l- X, f/ p3 x! Z
  47. 1 p+ o2 n: i: J1 v7 w* l+ L  k
  48. #if 1 // 允许编译器编译该文件
    7 N6 }0 \, _8 D% D# K
  49. ; o; J9 U1 [4 R& k" w) P$ P' R) j; m
  50. #include "lwip/def.h"
    * L* K0 [; O$ C0 f9 U5 F( z
  51. #include "lwip/mem.h"
    6 n0 t$ z' R; f6 @' k, X
  52. #include "lwip/pbuf.h"
    ' H% k- v4 N# ?" i- G: f
  53. #include "lwip/stats.h"
    - s/ c) x+ w. v8 }
  54. #include "lwip/snmp.h"
    . q/ |( d6 z* u! F, x( N9 B
  55. #include "lwip/ethip6.h": o5 k$ r2 D  J7 w! Y# F
  56. #include "lwip/etharp.h"
    $ p0 g6 X9 D: b# N
  57. #include "netif/ppp/pppoe.h"
    ; I+ F. Y9 E4 w/ e( z
  58. 0 x! R; w9 {" Q, W! B
  59. /* Define those to better describe your network interface. */
    6 \  _0 `2 ]$ M9 a& p
  60. #define IFNAME0 'e'% u9 O7 ?$ g# ], I
  61. #define IFNAME1 'n'
    3 Z! g/ D% g" |
  62. - ?9 A4 t+ B- V+ e2 m9 ~/ G4 t
  63. #include <string.h> // memcpy函数所在的头文件' T& n- R- ^- i" a7 X
  64. #include "WiFi.h" // WiFi模块驱动程序头文件
    9 }. G+ L$ P! n- W6 m
  65. $ h/ c! C! q  X
  66. void dump_data(uint8_t *data, uint16_t len);
    ( g! p* W9 o* h

  67. 6 `( S5 D( D; t$ U
  68. /**- z1 l: q. G' d0 x& d& y6 e" d
  69. * Helper struct to hold private data used to operate your ethernet interface.; A/ Z& y- Z* c. A4 P
  70. * Keeping the ethernet address of the MAC in this struct is not necessary
    8 ^3 |) j3 u$ y' {; M; z* f1 t6 \
  71. * as it is already kept in the struct netif.
    : j9 q8 ?/ b; j- W6 z
  72. * But this is only an example, anyway...
    9 T+ p' L, C7 Q1 g0 }
  73. */, h% t% t6 i; z# q  K1 l* C6 U6 s
  74. struct ethernetif {% y" }3 |7 T+ H5 [9 v
  75.   struct eth_addr *ethaddr;
    ; ^# {- Q+ M4 a& C/ T& h
  76.   /* Add whatever per-interface state that is needed here. */( y" R- ~) D  S' U, l: h
  77. };4 m& ~7 ^4 {+ ^( n) v: H: K3 A
  78. 7 T9 v+ o+ Y, E) E
  79. /* Forward declarations. */+ ]3 \* Q7 J2 D4 ]2 k
  80. // 这里必须去掉static+ x( K0 I3 R( X5 ]" X7 m
  81. /*static */void  ethernetif_input(struct netif *netif);
      W4 O" ?  m0 C* Z* L$ B5 Q" n
  82. 3 U& w% }2 Y4 h' l+ f- T0 v
  83. /**
    + e$ d; R+ h9 N! x
  84. * In this function, the hardware should be initialized.
    8 t# @, w# l3 q: H; W: z( }
  85. * Called from ethernetif_init().- O' c8 _, j; M5 `3 Z0 v! i
  86. *
    ( o- `. @! c4 m! C1 {. B
  87. * @param netif the already initialized lwip network interface structure+ W9 l: _  y# [" ~5 n6 Q* ^  P
  88. *        for this ethernetif
    ' H6 O! m% }$ j8 J, q6 z* ]9 @
  89. */
    7 `1 Q) t5 `; n- S. V
  90. static void
    6 W  X* @* x# R/ |2 C8 x" O) x
  91. low_level_init(struct netif *netif)  I4 X, }- S& t- @+ `3 h2 \
  92. {
    4 k' a# e9 ]" V* t! b* z( |7 h6 [
  93.   struct ethernetif *ethernetif = netif->state;4 |* V  ^& q- _9 F) c7 q) d

  94. - L3 k' a1 b8 ^& ~! ?
  95.   /* set MAC hardware address length */
    ' \# f& X( M, p+ B# h
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;! h1 F3 s  \7 z
  97. # u: h' `2 v+ \- A9 F" E8 a
  98.   /* set MAC hardware address */
    " Y0 w& R2 q5 O+ `7 O
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址( t) w/ w9 ], g8 l6 p: D
  100.   printf("MAC Addr: %02X:%02X:%02X:%02X:%02X:%02X\n", netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);1 P" y! ]* q# M) m, Z& V# J
  101. : b0 q7 r7 ^2 O$ d
  102.   /* maximum transfer unit */' ^9 W5 ?% k; N
  103.   netif->mtu = 1500;
    / a" @* D; \9 r" k6 t
  104. 5 ^* l) S6 I+ O' Z% N3 _8 A6 t( s
  105.   /* device capabilities */
    1 ~, {& V( J( i0 u4 n& K
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
    9 W; S/ C0 m2 F& y6 w4 B2 k$ E
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;6 v; W% B6 ^6 u7 f

  108. $ G8 n' E; `3 j+ _
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD8 V# Y. m0 Y* j
  110.   /*
    + f( @; H7 R, d) O; e4 w  l/ \- ?
  111.    * For hardware/netifs that implement MAC filtering.
    6 F  d! G" ?  q7 G
  112.    * All-nodes link-local is handled by default, so we must let the hardware know
    * k* M9 u5 w2 u; s6 L
  113.    * to allow multicast packets in.
    ) w0 [$ S4 s* O. T" S
  114.    * Should set mld_mac_filter previously. */3 J9 b2 T. u4 {* H% ]% [
  115.   if (netif->mld_mac_filter != NULL) {
    " q& d- |6 x# T% A8 F- z, m
  116.     ip6_addr_t ip6_allnodes_ll;
    , f6 M' }4 i$ V0 ]- K, j- i
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
    8 l' o) Z$ I/ |# Q. U0 A6 t0 q
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
    4 K3 K9 ~2 ~7 }/ E' h; i
  119.   }
    8 q# A) D3 g6 X, P  s6 g) H3 a3 y4 |
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */* U* f$ D/ K0 }" w

  121.   k1 t1 U' S8 K( l9 d
  122.   /* Do whatever else is needed to initialize interface. */
    / f; u- _2 _; q% Q* q6 l+ t
  123. }
      b5 ?! t0 A  J& d8 t

  124. ) X/ L4 w' K8 n" J3 P1 m
  125. /**3 e* |- b" B# a) E# s
  126. * This function should do the actual transmission of the packet. The packet is
    - d5 q' w  t4 Y
  127. * contained in the pbuf that is passed to the function. This pbuf
    5 m4 \' V4 f6 ~3 Z3 B! j9 T
  128. * might be chained.
    4 {7 k: V7 E2 W1 ~
  129. *9 u1 @. B# s3 H, Q" s1 y
  130. * @param netif the lwip network interface structure for this ethernetif; h9 U( ^2 i' i" w
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)0 b8 q* T! q6 |7 i7 o% {, ^7 u2 e/ h
  132. * @return ERR_OK if the packet could be sent
    * w$ e' Z/ ?4 `8 J" v
  133. *         an err_t value if the packet couldn't be sent% Q+ Q( u5 [: @8 x9 s: f
  134. *
    / s1 D0 @3 C% g; ~: R+ F
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to3 r! r' V2 b2 S& n
  136. *       strange results. You might consider waiting for space in the DMA queue
    " y: B' V9 @5 q. I" ^) s
  137. *       to become available since the stack doesn't retry to send a packet, `$ s3 R! Q; x' u9 W0 ~* X. n
  138. *       dropped because of memory failure (except for the TCP timers).
    $ e1 Q5 \- l# [1 f6 b/ g3 {' g- v
  139. */
    2 K* Q3 t  K% l4 N' ^
  140. $ ^' G* c: |  X+ V& P4 e4 o
  141. static err_t
    " P: O3 V! r8 M% k3 S! X: J
  142. low_level_output(struct netif *netif, struct pbuf *p)4 i% I3 b3 v" ~& P
  143. {8 C  Z5 q$ V% s# W( g2 c- Q* ~
  144.   struct ethernetif *ethernetif = netif->state;% D, g. B- D8 m; A, {. B
  145.   struct pbuf *q;
    ! W. S, Z: t+ y8 A9 s  N% [
  146.         : ?7 j% D# U& I1 ^/ S+ I$ H) p9 F
  147.   // 添加的变量
    % W0 W) I5 s8 h) i
  148.   uint8_t buffer[1792];+ k# s1 Q% ^1 z' t( i% P" r
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;1 g" O/ r! M0 A/ i6 o* z
  150.   uint8_t *bufptr = packet->payload;7 x6 M4 |) m% G- y7 ?- l  w+ v* `

  151. * q; d$ V# p) v) t
  152.   //initiate transfer();
    . [- O* `4 G/ W) W

  153.   a9 N$ Y% T2 n  B1 P- o6 X
  154. #if ETH_PAD_SIZE0 g& ^" M4 e* e4 Q) Q
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */  \/ m2 s5 L6 _% R  o: X# o
  156. #endif
    5 U: S2 B5 j; @

  157. 4 J$ C6 ~" E! f$ S6 r4 E$ H
  158.   for (q = p; q != NULL; q = q->next) {
    ; Z2 A# Y4 D5 |( n/ w+ u$ l
  159.     /* Send the data from the pbuf to the interface, one pbuf at a
    8 j$ P$ _1 x+ y. H, j# i$ r
  160.        time. The size of the data in each pbuf is kept in the ->len
    : u  I. {$ E0 d3 ?/ O. z8 R
  161.        variable. */
    1 W" s, K2 p, h) W9 |% b
  162.     //send data from(q->payload, q->len);
    8 U, I" c) X* {; N! n% s1 ?
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容
    : ?1 ?% _' c% C+ E3 n) y
  164.         bufptr += q->len; // 指针前移' {& |& C: h: w" k7 w- L1 @
  165.   }. [! D3 u/ T3 Z( M. c: \; E

  166. ( V0 W  N3 I. M) D6 i
  167.   //signal that packet should be sent();" t+ ?  C$ o9 j: `+ p& Q& `8 u% r
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包
    1 y, p6 g) M  f  Z
  169.   
    / t% j# L# _% K3 o) j9 y
  170.   // 打印数据包内容9 u  o, F9 W/ {2 z
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);
    - X4 n4 |  y, j- Q
  172.   dump_data(packet->payload, packet->tx_packet_length);
    ; I8 W3 }! D$ U3 _

  173. # ]: R5 J$ Z+ c3 P2 X; _
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
    1 R* t$ n6 c: C/ i5 M
  175.   if (((u8_t*)p->payload)[0] & 1) {
    ; K) w1 X- `+ k- Q3 h9 r: E
  176.     /* broadcast or multicast packet*/  c) y% g4 X% n: J4 L
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);: t6 g1 G4 i& X4 \" E8 Y# H
  178.   } else {' q# R( C$ T3 s  d( j
  179.     /* unicast packet */( L9 a/ F  p0 Y! H& @
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
    " I1 Z% Z; x! V  t
  181.   }4 s1 l) A4 L  b% v
  182.   /* increase ifoutdiscards or ifouterrors on error */6 e9 Y- I7 _4 r' W+ s0 ?

  183. % M( }6 ^& R0 D0 Y
  184. #if ETH_PAD_SIZE
    / _* J& @2 Z3 Q& x3 q# X
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */1 Y7 h9 j2 @5 t: ?& ?) ^
  186. #endif
    ( f! K: U7 ^6 O+ O
  187. - `$ h8 L4 @- a( Z6 d2 f7 N, v
  188.   LINK_STATS_INC(link.xmit);3 E4 Y# \7 y4 Y8 G+ ^7 O6 V3 ^* M

  189. 6 x9 ~# R6 U) A+ y
  190.   return ERR_OK;, H& x1 o$ ?0 ?  q
  191. }8 h4 {7 F$ r& ?2 S6 m9 k8 q6 J; `

  192. & V; m  ]5 b! a+ H2 }+ @! t
  193. /**
    ! ?+ M$ e% L4 y' T6 Q
  194. * Should allocate a pbuf and transfer the bytes of the incoming
    , s- {3 \1 U. f3 T# |4 \
  195. * packet from the interface into the pbuf., p3 \; X6 p  c- C3 c& k
  196. *
    : c0 `( u# K/ I
  197. * @param netif the lwip network interface structure for this ethernetif9 [+ g" L# m. F
  198. * @return a pbuf filled with the received packet (including MAC header)
    0 F6 u7 ?, t; i) d. d
  199. *         NULL on memory error# U3 |* V+ d7 ~  j$ B' \, D2 c
  200. */
    $ D& _* W- E7 Q* U) W( h, j5 ^0 ~  c
  201. static struct pbuf *
    6 O1 E4 ?& {% C2 n$ x
  202. low_level_input(struct netif *netif)/ h  V" ^) r' @9 y
  203. {4 q: A$ F- w1 l1 v5 x
  204.   struct ethernetif *ethernetif = netif->state;8 N3 q6 h6 t5 g8 @
  205.   struct pbuf *p, *q;
    0 F. a- |: }( j7 m% m
  206.   u16_t len;
    4 c: w% T2 r4 z5 ?
  207.         - S& }9 ]1 K- z9 g$ K; T+ c4 X( q
  208.   // 添加的变量* D1 [% p9 P" m( u
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完& j+ J1 o8 J9 A& Y0 Q
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;- m7 z# o( b! X$ I; p
  211.   uint8_t *bufptr = packet->payload;4 t" g& [" k6 z! Q

  212. 2 g! X# f5 j# L- H
  213.   /* Obtain the size of the packet and put it into the "len"! h( H! P$ j; ]3 ^, M4 l# H
  214.      variable. */
      y  z3 Q* e" f$ I) D
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
    & n4 y5 L% G( ~; e: w: ]
  216.   if (len == 0)4 K9 r2 E4 _9 Q' U! T' U. n
  217.   {
    ( p7 p7 I8 G1 j0 e1 v* D% @) L
  218.           // 若读取失败, 则不分配pbuf, 退出本函数
    / b2 }  N) n. p' f8 A, T; p. M
  219.           p = NULL;
    ' y. A3 v0 q; E5 x! h6 u6 s
  220.           goto after_alloc;& e+ d; |5 k! S. O. [5 U2 h1 a
  221.   }
    & M8 c6 D* B5 n. c
  222.   len = packet->rx_packet_length; // 获取数据包的大小
    * F# N+ r, P2 y* }% M
  223.         
    0 `: Y# W3 [1 j; t
  224.   // 打印数据包内容0 o+ o& }9 k, }: }3 D
  225.   printf("[Recv] size=%d\n", len);
    / N3 K  v. X0 f$ G$ Q
  226.   dump_data(packet->payload, len);
    % e; h: m5 D9 d

  227. - G/ y/ q& N3 y5 e
  228. #if ETH_PAD_SIZE- T7 g0 E% A- c! Z
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */5 P: u1 D* G* B& |8 }
  230. #endif
    6 J; `" s8 @4 w% H
  231. 9 }2 }5 L1 I, k4 Z
  232.   /* We allocate a pbuf chain of pbufs from the pool. */. U" a% k7 E5 r$ E7 D" b% D
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);  B  n. c( a7 ~% m, F, n
  234.   
    & G: Q- |: u2 c2 i
  235. after_alloc: // 添加此标记5 ]. Q1 a+ k/ [- t2 a8 V/ t! ~/ r+ s

  236. # t* x/ B, |8 ^( g  [0 U* `3 c
  237.   if (p != NULL) {
    - r6 x+ S: I6 N6 V  q

  238. 8 W; Z2 t# m" R8 x
  239. #if ETH_PAD_SIZE; F9 `! {6 }' A, i) |6 V
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */1 n* U: O6 X' l
  241. #endif- S- J: d3 z1 f3 {# s3 V1 o
  242. . t( Q3 c: z) H# k; {8 M3 B
  243.     /* We iterate over the pbuf chain until we have read the entire
    2 h  Q; ~& w+ u4 o8 W8 Y, K7 p3 _
  244.      * packet into the pbuf. */
    " V. ~2 e: m5 G
  245.     for (q = p; q != NULL; q = q->next) {
    : A5 g* `! G- {
  246.       /* Read enough bytes to fill this pbuf in the chain. The. t" {2 h/ @6 h3 n+ W
  247.        * available data in the pbuf is given by the q->len
    8 Q8 S4 E" Y# d5 C# a7 S
  248.        * variable.  b1 d7 k; [% U  C0 {3 w$ y. v
  249.        * This does not necessarily have to be a memcpy, you can also preallocate
    " I6 p. p/ L/ x+ h' P- y
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the) Z6 ~+ f: T: ?  h6 Z
  251.        * actually received size. In this case, ensure the tot_len member of the, |2 o6 Y- G4 n. J3 H6 y3 x
  252.        * pbuf is the sum of the chained pbuf len members.' L" l# W' b; u
  253.        */1 V! n+ K: q) T/ b3 }+ G; K
  254.       //read data into(q->payload, q->len);7 D# {$ H$ i2 d: \6 V. j
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容
    4 f9 x9 f' q; V! S7 t; M6 [- T4 l
  256.                 bufptr += q->len; // 指针前移+ U$ q( V: a1 x  M
  257.     }7 j: T& V1 q' M+ g( @5 k: ]# B
  258.     //acknowledge that packet has been read(); // 无需确认" }- H# |8 \( m: O' s

  259. 9 M5 g( j$ U9 u$ b/ ~/ \* t- u
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);* s: a' h" W, n% C
  261.     if (((u8_t*)p->payload)[0] & 1) {* e0 I+ T. T0 g+ u( q+ N3 D
  262.       /* broadcast or multicast packet*/3 }9 R' P# L- w7 W, b( w) ^$ j; B
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
    + r' M& ^  p' F" j3 x9 P; H1 Y' w
  264.     } else {
    ' Z/ x- G1 y4 B3 L% a# I5 d$ C( Q
  265.       /* unicast packet*/
    & V3 d( B& R8 t- a' X
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);  n- G5 G9 [( X( o
  267.     }
    7 y; t( h# F7 Q" Z! Z
  268. #if ETH_PAD_SIZE8 F( {: ?9 k% F& k
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
    # }1 e0 [3 P$ V7 o
  270. #endif
    $ s+ b5 c2 H5 u  R( m+ ^, n
  271. 8 D; k' ~. \! \3 ^7 E" v
  272.     LINK_STATS_INC(link.recv);
    - p% L" D' {2 c) s+ Q# Y- {
  273.   } else {* s% f& {2 e6 l
  274.     //drop packet(); // 注释掉此行
    % v" R0 c, X# w4 A
  275.     LINK_STATS_INC(link.memerr);
      V4 @: v0 z1 q% }- C0 M
  276.     LINK_STATS_INC(link.drop);
    # K4 O* x1 f9 v, \% Y. I8 `" L
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);
    ; |+ u- ~" X3 S' P/ X0 B
  278.   }
      \, S3 A# j/ X- R
  279. ' o, h: N  M5 X; H" m6 e, v& W
  280.   return p;9 s$ E4 ]' w; g9 }  X" d
  281. }% P. |2 ]( t" ~' O; V, _/ e2 u

  282. . O+ j2 C% f0 O- f3 I5 k+ |4 s
  283. /**
    & y+ u3 I4 F: Q7 q% v
  284. * This function should be called when a packet is ready to be read/ H* ]3 e+ A0 h& c  p  R
  285. * from the interface. It uses the function low_level_input() that
    . t" l2 V3 _# @
  286. * should handle the actual reception of bytes from the network& v" ?$ g: P: `0 i3 w
  287. * interface. Then the type of the received packet is determined and+ d7 s3 X8 j" W+ @; X/ S& E6 S
  288. * the appropriate input function is called.( I; k* u5 J, f& a% k- e$ y
  289. *
    3 \1 j2 f9 r+ n' S% c5 ]
  290. * @param netif the lwip network interface structure for this ethernetif; M3 d# l1 S' F" c) f8 B
  291. */
    6 G# |! l4 q; w' t" Y( o4 `7 Z" w. r
  292. // 必须去掉static; ?7 [0 j) s( x. U" Z9 y
  293. /*static */void
    ' C, f- a) f- L  D' v% [& x& U
  294. ethernetif_input(struct netif *netif)' K* s# q2 L5 }) a! w
  295. {
    : d1 D. T* h' k- X( J
  296.   struct ethernetif *ethernetif;: z2 b3 Z/ [, s, o
  297.   struct eth_hdr *ethhdr;, G# x- Z; f) m1 u) Q" \3 d
  298.   struct pbuf *p;9 ]: D) N$ L; e1 V) F

  299. " t0 A: `- F* a4 s$ G3 c; Z
  300.   ethernetif = netif->state;; k9 x+ [$ V2 z3 e. R5 L

  301. ( Y/ ^! I) p* J
  302.   /* move received packet into a new pbuf */" o: Y7 H0 v2 z2 t- X$ `
  303.   p = low_level_input(netif);) D' n* `/ G6 C
  304.   /* if no packet could be read, silently ignore this */
    4 H. B% L( g. \. V$ O( V& t" }3 \
  305.   if (p != NULL) {# Y! ]1 U6 Y' k4 k/ A
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */
    8 M5 ~, X. t; N
  307.     if (netif->input(p, netif) != ERR_OK) {* _7 W$ G4 x; v# P7 [
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));2 \. Y. J4 M$ J, p7 f
  309.       pbuf_free(p);8 U$ b; t# l- d% a9 B# [
  310.       p = NULL;: E- P, q4 `' @
  311.     }
    % n3 V; g  p- X- z/ s
  312.   }
    / l. b) p. B) j6 }+ t
  313. }; {7 p3 B* b' E- h1 X2 {2 K; F+ t4 j

  314. % s" U' ?8 k% E$ a
  315. /**- K7 a5 s! C9 t, p; j7 n, a* A
  316. * Should be called at the beginning of the program to set up the
    3 H# p0 ^9 ]" m6 w
  317. * network interface. It calls the function low_level_init() to do the
    $ |* _6 S$ E4 O# ?0 p
  318. * actual setup of the hardware.
    * N3 K' n" M7 M+ @$ h1 ], x
  319. *# M* e  v+ s& g( Y2 y
  320. * This function should be passed as a parameter to netif_add().! i' |) a3 O& R$ V. {
  321. *
    4 e' x3 l* z( |$ v$ N( ^
  322. * @param netif the lwip network interface structure for this ethernetif1 `) v5 E: M# B& M0 s' f8 C) B
  323. * @return ERR_OK if the loopif is initialized, i  O4 h7 Y- M$ X/ ], e
  324. *         ERR_MEM if private data couldn't be allocated
      p9 O% l; V0 q. S: T" h
  325. *         any other err_t on error/ N3 f5 J8 u% r. H" r; I
  326. */
    - p2 r! m% e: p0 K# S
  327. err_t
    % \; x: e- j* A) d1 {
  328. ethernetif_init(struct netif *netif)
    9 e1 j- c4 x: {" H, R  L; x7 T
  329. {
    2 i( M4 M  L- @$ `1 Z
  330.   struct ethernetif *ethernetif;# S, ?4 }1 C2 [0 z4 S
  331. ' B4 d# Y% J8 Q: y; C
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));  G" v5 ~( ?$ H% w& ~

  333. ( ~- |; V2 u- K3 m0 }* P' f
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));+ s6 `3 _$ _/ P7 }% X2 _& x
  335.   if (ethernetif == NULL) {
    / v% }) U0 j1 f% o9 h
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));8 Y4 v9 a: |+ Y( T* j; S- H0 l8 m
  337.     return ERR_MEM;3 {7 q  q4 T+ u8 _2 ?! G
  338.   }
    2 N* u7 o8 T* ?# T7 C1 W
  339. ; {8 e9 @) k3 c; I/ u# h. W9 Q
  340. #if LWIP_NETIF_HOSTNAME
    - V, |( T+ n' ]' }6 |' r4 x2 z
  341.   /* Initialize interface hostname */) ^: e0 _: H7 ~8 `! ~4 l
  342.   netif->hostname = "lwip";
    # l# p9 ^- c8 u6 J
  343. #endif /* LWIP_NETIF_HOSTNAME */
      b& s3 H! c+ ?' S" x# h9 O4 z' [
  344. % L& M# X; g! [+ m# j0 `; D
  345.   /** h, _5 Z0 }' n& y  J
  346.    * Initialize the snmp variables and counters inside the struct netif.
    * I5 k1 Q. p! {* Z* {' W- F
  347.    * The last argument should be replaced with your link speed, in units
    . }. c, Y2 k. T+ F( f9 e8 P  ]* z
  348.    * of bits per second.
    ! L* ^+ D0 M5 Y, e: x8 x
  349.    */
    ' g6 K0 {3 T+ \+ C! U
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);+ C; ~$ ^( l2 Q/ J* y
  351. 5 O* F* w% t; I1 J
  352.   netif->state = ethernetif;
    / c: R8 p+ G/ z2 V
  353.   netif->name[0] = IFNAME0;2 d! C; y- z$ ^+ M$ s2 V
  354.   netif->name[1] = IFNAME1;0 j3 z2 q4 ]- S6 B* ], i/ Y
  355.   /* We directly use etharp_output() here to save a function call.
    ' W- c; s* X" q. T9 e" I7 n8 c1 ?8 F
  356.    * You can instead declare your own function an call etharp_output(). S4 k& k- Y3 x1 C+ t
  357.    * from it if you have to do some checks before sending (e.g. if link& Y. A* c5 M6 [5 \$ C# U3 A
  358.    * is available...) */+ i4 w4 Q# _2 n( V5 }/ t7 Z
  359.   netif->output = etharp_output;' e  j# D* m/ U1 b3 m
  360. #if LWIP_IPV6
    0 V  {0 \  G5 \  V: D# B
  361.   netif->output_ip6 = ethip6_output;
    " T! R& e1 V1 _  v
  362. #endif /* LWIP_IPV6 */
    5 C2 n( {. M& E- z' T
  363.   netif->linkoutput = low_level_output;' D& a% G( C& e

  364. / D' V$ d2 _* t/ G' n1 v' _
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);+ ?5 @4 X$ @( ]% i
  366. 0 E+ L6 L' u' L; L  d5 e" X! p
  367.   /* initialize the hardware */; {& [, X. @8 j" b* S+ \. B
  368.   low_level_init(netif);8 G# z+ u1 {" s5 `# C* S
  369. 6 Q: _7 E6 S) c  J) e
  370.   return ERR_OK;
    1 \6 M' f% a1 x
  371. }) _0 ?# E  o; i9 l3 h
  372. 9 \& f" L: m" [6 `2 l9 M
  373. #endif /* 0 */
    4 z' i5 [0 X2 \4 O: @( o
复制代码
! I1 w3 l: y- x
在项目属性中,设置Include Paths为:.;.\lwip\include
& k% }. R9 a2 Z3 U. x5 `) q其中点表示工程根目录。
' E5 q( t% l! ~6 O5 F: ^6 e* T0 |: }
& ~1 V- c0 R, ?8 E' q另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
! ^5 t$ N; i* F7 t9 _) c# v+ |' D% ]; v, S3 D' K
编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。4 g( T4 l, V) h: H, y: L- o
电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。7 |8 [0 }  e. y" B7 U
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。# ^/ b4 _0 O: x% b' E' u" f$ n

评分

参与人数 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....6 \1 ]+ i9 L) p! o2 i( ?# C4 a

0 \0 L0 A/ M# \9 N" ~( n2 v多谢分享
zlk1214 回答时间:2025-4-8 13:55:18
while (WiFi_GetPacketLength() == 0xfedc);
写错了,应该是
while (WiFi_GetPacketLength() != 0xfedc);
才对。
L

所属标签

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