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

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

[复制链接]
zlk1214 发布时间:2017-7-20 16:34
本程序所用的单片机型号为:STM32F103RE
8 L: I  p# f, m! e( a! GPB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。. @% J# h0 g1 ], _" C" {( M
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
4 N" W2 b1 [$ i该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。0 `, t( R0 E/ y0 G! s
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
; y5 x% P4 G6 a/ X$ @& j& O, I1 d. s0 r" P: F6 U) A- P$ w5 k
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!' r; X/ Y) ?* R8 Q+ k
  1. Stack_Size      EQU     0x00000c00  
复制代码
【main.c】% J7 p/ T& h6 o5 M* @5 k7 g
  1. #include <stdio.h>' W: Y' _0 P# V. m! I
  2. #include <stm32f10x.h># {, X4 g+ j5 {* x3 T
  3. #include <string.h>8 l, ]9 O: B/ n- m
  4. #include "lwip/init.h" // lwip_init函数所在的头文件
    , B) z1 M# A' ~$ Q$ p; h
  5. #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件
    & }" w  O0 Z( S& M
  6. #include "netif/ethernet.h" // ethernet_input函数所在头文件
    ) J7 C' s8 ?, I4 t( x
  7. #include "WiFi.h"
    $ j  l; t+ R# a' ^' J
  8. ! O6 u% J) J6 k' F" B
  9. // 这两个函数位于ethernetif.c中, 但没有头文件声明
    ) _# e, z% @8 K6 P# c
  10. err_t ethernetif_init(struct netif *netif);6 i5 n" Q, G$ z1 s4 Y% a5 _
  11. void ethernetif_input(struct netif *netif);1 A+ ]; n1 J1 o6 Z6 N2 b7 {
  12. / x+ x0 g) c  s% G: O
  13. // httptest.c中的函数
    ) L$ c; I7 S3 k' t* f4 u5 ?7 P5 Z4 X
  14. void init_http(void);, P# o- g4 V' H$ G0 u- x7 F

  15. # B( |! d  C3 s
  16. // 延时n毫秒
    6 q3 O7 \/ @$ u2 F; N' m
  17. void delay(uint16_t n)
      d% _; r+ y. K1 [4 Y* D7 r$ D1 h' U
  18. {% v0 f: b0 L6 T
  19.     WiFi_PrepareTimer(n);( t* K, c; D3 f4 K3 l3 @
  20.     while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕
    ' |& s7 [- B- m2 e5 R
  21.     TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
    ! X+ G4 r# M% y# R% M4 F6 B- ?
  22. }
    3 q4 q7 B& g/ J7 z$ F& J

  23. * t# G9 n/ |. |! s
  24. void dump_data(uint8_t *data, uint16_t len)
    ; w' p0 d3 @$ N2 G7 h1 }
  25. {& F4 R* v$ P: o8 u. z
  26.     while (len--)
    7 q( o& Y( M7 P) k  D. R& `  J8 I
  27.         printf("%02X", *data++);. h) d- O( ~* k
  28.     printf("\n");
    6 [  p8 o! g/ x. r8 e
  29. }4 ]4 Z$ s, i: ~  _
  30. % @$ h( W) s" E
  31. int fputc(int ch, FILE *fp). ~3 v1 x' D* V% L4 R, z' O
  32. {* v0 K; g0 p" ^- K8 k3 n6 K
  33.     if (fp == stdout)
    ; t" \+ c* N1 o, O: w! w
  34.     {) E9 [( u8 W8 z+ r# ]
  35.         if (ch == '\n')' K4 _* i4 J9 {  k- E: g" G
  36.         {$ [, H$ }& G+ P6 c1 ^4 o' f' c8 ?
  37.             while ((USART1->SR & USART_SR_TXE) == 0);
    ! e7 ]) z* f# J
  38.             USART1->DR = '\r';
    5 _/ z$ Q) ~( H
  39.         }+ k# L! {3 O0 G
  40.         while ((USART1->SR & USART_SR_TXE) == 0);3 R# t  Z& G0 q5 t3 S- K6 T( b
  41.         USART1->DR = ch;
    & c7 x# w8 r- G* q
  42.     }* K3 X& N6 o' |5 o( ]- z% g) o
  43.     return ch;; |, J) Z9 B+ i$ n  n* M
  44. }
    6 @1 z. |* P0 Y+ o$ D! p, t! M: Z

  45.   A: N+ N- A2 t- A! O
  46. // RTC时间转化为毫秒数
    & A; L& b  h  s. J/ h0 J
  47. uint32_t sys_now(void)
    % V/ H  v9 d3 j, o6 A( w
  48. {. t% ]5 e- |! b) {! \
  49.     uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
    + N# h" }! D+ \4 N" `" M
  50.     tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒
    $ ^4 F5 W) k/ p/ J
  51.     return tmp;
    6 s9 @8 s5 N+ \+ u/ j) V- w
  52. }
    0 Z& T" |6 f. c
  53. ( Y0 [4 d2 D' l4 w" K
  54. int main(void)" V  U) w! K0 @+ @" T# `
  55. {
    ! U- P: ?! T& }( j
  56.     struct ip4_addr ipaddr, netmask, gw;
    $ u0 t. V( G, a6 Z
  57.     struct netif wifi_88w8686;
    7 l3 b& o( |6 N1 _  D$ L
  58.     uint32_t last_check = 0;8 |! v# n, b% Z- e- L
  59.    
    4 ^! J; a. k1 C7 P1 q/ ]. G
  60.     RCC->AHBENR = RCC_AHBENR_SDIOEN;3 p4 w9 n8 g! |' d* z6 o" m. I
  61.     RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;$ d' J1 q% F4 F& J- t1 T# v& f3 u
  62.     RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;; W5 k1 X% Y* X% M$ u, x
  63.     ) e" x( {; F: K- X1 A
  64.     GPIOA->CRH = 0x000004b0;
    + ?% g3 f6 v# b" V& q& p! ?
  65.     GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块
    / A5 o( i$ L9 k$ O2 s* {
  66.     GPIOC->CRH = 0x000bbbbb;+ M/ U3 h/ A! H- c
  67.     GPIOD->CRL = 0x00000b00;
    - m  q& e; r( l4 ?
  68.    
    ) S% Q1 @# u# \: b7 K6 F
  69.     USART1->BRR = 0x271; // 波特率: 115200
    . ]/ h' x! l* b9 ~
  70.     USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    & X- z" ~. m/ }, o+ o  l9 }  g
  71.     4 [: y: ?5 I3 E# W; m; A
  72.     PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器
    1 H2 ?- U$ D) u; S. i; w+ n
  73.     if ((RCC->CSR & RCC_CSR_LSION) == 0)" O' X3 B0 H+ H
  74.     {
    ' d* A  B, T; J$ c0 {6 F
  75.         RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI/ y- S  h) I( A. e3 N
  76.         while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
    2 e; w; V$ O% S7 c, w+ d
  77.         //printf("LSI Ready!\n");
    8 J, U7 n. L2 Q/ J+ y
  78.     }
    $ `3 m, u4 A1 P( H
  79.     if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0), }3 C; w" X! q0 j0 V
  80.     {# i, H8 f* @! m% v) }0 D
  81.         // 若RTC还没有打开, 则初始化RTC
    ' ^; Z8 p6 u% Z; Q* x5 P3 I# V
  82.         RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时$ `. u- |7 ]3 y7 a
  83.           {, Y7 \( h- G2 V+ r: U  a
  84.         RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式/ X; E+ k: P- V
  85.         RTC->PRLH = 0;
    % G" `& U* B  a/ @1 D" R
  86.         RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
    & z8 G/ Z4 o; i; I7 k* J
  87.         //RTC->CNTH = 0;
    4 w$ c( t' W: g* F) `; i
  88.         //RTC->CNTL = 50; // 初始时间! z& W' D' k1 r* M9 [
  89.         RTC->CRL &= ~RTC_CRL_CNF; // 保存设置/ y/ |  y7 E( B% h$ i0 |
  90.         
    9 E3 w8 c0 V9 Q4 _; }7 f; x
  91.         RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时% r- h+ K7 }) T" q2 o/ ^6 l; x
  92.         while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效
    * E) X8 K# R7 M( a+ v: g" ^
  93.         // RTC从此处开始走时
    * H- q# H1 {5 }- u* Y
  94.     }
    7 _4 ?( d! ?5 ^; P- S( J: e" E
  95.     # I) h* \6 h% |6 U" S& U! M9 N
  96.     WiFi_Init();  g. I- Y9 p- h% p
  97.     WiFi_Scan();
    0 a4 Z) k0 w7 A9 v( h. x* X& |
  98.       F' R+ @7 P0 M6 e. _8 @( M) ~
  99.     //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点
    0 W- h% _3 n9 N' h
  100.     WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)* @5 Y7 _' B9 {
  101.       d2 n( S! U& B
  102.     lwip_init();
    7 G( t2 @( G/ z  u" m
  103.     IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址$ |% |4 ?* x/ n( ]
  104.     IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码* R: \; Y+ u' T4 {: C. Y
  105.     IP4_ADDR(&gw, 192, 168, 43, 1); // 网关/ t. Y8 s/ u. z4 V
  106.    
    & e+ Q; @4 D" S
  107.     netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);# J; `# o; ~- j8 U: \/ e
  108.     netif_set_default(&wifi_88w8686); // 设为默认网卡
    , {& \8 U' v. y2 k# }; }. J1 Z
  109.     netif_set_up(&wifi_88w8686);
    / A( u+ B' t) Y
  110.     0 D- U3 H8 m: v0 F/ J3 W
  111.     init_http();/ a. l  W" _0 B; S& F
  112.     8 t3 L: v; E/ R* [
  113.     while (1)
      y+ [3 I7 n; Y
  114.     {
    # [5 _% {' j' R: Z- Y# [
  115.         if (WiFi_PacketPending() || WiFi_PacketArrived())) b- U. `& `2 f
  116.             ethernetif_input(&wifi_88w8686);
    , M8 D1 ]5 B( Q8 G1 D- P  e
  117.         
      ]5 a! O( I% C/ j0 J
  118.         // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)
    1 c- c( {$ \9 K/ l5 u  J
  119.         if (sys_now() - last_check > 200)8 m; O/ S8 }' _2 B. J; `
  120.         {6 D8 z" \9 K4 ?" h6 B
  121.             last_check = sys_now();
    ! z( M1 m" O7 ^8 Q; \6 ^3 r. `) }
  122.             //printf("Time: %d\n", last_check);
    9 o( _8 [) A; J/ `7 y
  123.             sys_check_timeouts();
    4 R% H; @5 u, a. x) B1 Q' z
  124.         }
    1 J$ q7 V$ y' K, p- |# l: Q5 D- V/ c; n
  125.     }
    # o7 I& R- x  R8 s5 n- |
  126. }
复制代码
【httptest.c】% Q: v3 ^+ ]4 S( S- u& @
  1. #include <string.h>  @4 r: _+ o! m0 c- P
  2. #include "lwip/tcp.h" // 一般情况下需要包含的头文件
    / ^3 ^+ }; u) }7 B
  3. + d. m/ V4 k+ s! P$ m7 Z4 f) z  {4 X
  4. #define STR_AND_SIZE(str) (str), strlen(str)
    ' J: h& D/ A  s! y6 Y. a

  5. ; @* b- {8 D& g# A- f3 F* e: y
  6. err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)6 l  m9 E' e# D$ i
  7. {
    " W/ ~! `) I( m! K8 y  M5 M
  8.         char len[10]; // 存放HTML内容的长度$ s) D  s$ F; V, n
  9.         char str[200]; // 存放HTML内容! W2 X( ?% v4 s1 M% a  y! d3 \9 B: G
  10.         
    ; f; |4 X6 ]8 D  m' z' g
  11.         char name[100];2 @1 O9 ]1 o+ N2 o; ~7 a
  12.         char *pstr;
    2 N4 I; n  @# L" g5 G% D7 W
  13.         uint8_t i = 0;
    4 D! n; C9 c; n
  14.         if (p != NULL)
    9 a# ?( u  o2 }3 U5 @4 o- e6 J
  15.         {
    ( Y* i3 l4 l; w% z4 t, V
  16.                 // 提取页面名称
    % c6 c6 W2 a' S# {/ N
  17.                 pstr = (char *)p->payload;3 }) M! H% G/ W8 p$ f
  18.                 while (*pstr++ != ' ');
    $ O5 t; ~4 s) A. O' F2 s' f
  19.                 while (*pstr != ' ')
    : h  J$ E& e. ?) Y: C2 l
  20.                         name[i++] = *pstr++;6 \* m0 c1 r" [! e* P" @
  21.                 name[i] = '\0'; // 不要忘了结束name字符串& P) i* y! A: ?( o( O
  22.                 tcp_recved(tpcb, p->tot_len);8 d/ H* a: ]/ s) Y
  23.                
    . z. T/ w; k( i
  24.                 // 生成HTML内容
    # L4 R( a/ }8 `3 e# n+ ~( F6 j0 @
  25.                 sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
    9 p% P9 }; N6 k8 c0 F2 I
  26.                 % R/ s, n- ~# c, @+ n8 h$ V0 ~
  27.                 sprintf(len, "%d", strlen(str)); // HTML内容的长度6 }5 Q) O4 j+ Y. c0 ^  X# b2 j  [
  28.                 tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);8 j4 m3 B+ N6 C; o: {
  29.                 tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
      N/ p6 c% {6 K) A8 C0 F4 o- [* e
  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);
    / I0 D0 ?: h+ i' O7 ]7 N, T
  31.                 tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容
    9 F% }; K6 T- n) G2 N
  32.                 pbuf_free(p);
    6 d7 n( m! k  y5 j$ }1 a
  33.         }
    0 T, u9 z2 N0 H. N. f% q
  34.         return ERR_OK;
    1 p) N$ J$ }' |( Y6 j" N7 @7 [
  35. }  {0 e3 `0 t8 N

  36. 7 z5 P+ B) e: \' U
  37. err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)2 N8 x4 X9 N; S
  38. {
    ! a7 e. \( Z$ ~: K9 V) ^5 }9 I
  39.         tcp_recv(newpcb, http_recv);% t3 \: a3 V) w- t3 |" N
  40.         return ERR_OK;2 z+ E7 m$ D' Z8 g- i. N1 Z! A, _, Y
  41. }; G, p; [) x( @  ^4 r& m

  42. / N6 R5 W% K" m9 d/ a) p9 R8 o' g
  43. void init_http(void)# |- \# T4 h& W0 h( @/ [0 `
  44. {
    , I- X2 r; M5 p1 v! I
  45.         struct tcp_pcb *tpcb = tcp_new();
    9 G" ^: i) }; @* d9 z- U
  46.         tcp_bind(tpcb, IP_ADDR_ANY, 80);
    $ _7 x. u0 l1 F6 D/ S4 q
  47.         tpcb = tcp_listen(tpcb);
    ' f# l0 [+ `; g, {5 S2 @
  48.         tcp_accept(tpcb, http_accept);
    * D. W8 S9 F4 _) @; S! z5 z+ I, n9 L
  49. }
复制代码
【WiFi.h】; ?/ T0 Q- D# y7 o! H$ H! P
  1. #define _BV(n) (1u << (n))! @$ Q% W# _" E* u0 c. X
  2. 1 D8 y' Y' Z3 x
  3. #define CMD52_WRITE _BV(31)
      K5 D3 O' B4 D4 O* v0 t
  4. #define CMD52_READAFTERWRITE _BV(27)
    3 Z7 F4 u+ [9 ~. E8 J/ z

  5. ! ~* h7 E- {7 {4 [6 U
  6. #define CMD53_WRITE _BV(31)
    $ ~. T( U) t! |. m/ J
  7. #define CMD53_BLOCKMODE _BV(27)! ~3 L& d8 v0 Q5 o+ u+ w" G8 n; I0 M* @
  8. #define CMD53_INCREMENTING _BV(26)2 Y" s- C# D0 L5 t; _! E% |

  9. / g0 s" t  k5 h; M8 k6 Y) L, u
  10. // 16.5 SDIO Card Metaformat0 k: @7 B1 \, Y  U4 _
  11. #define CISTPL_NULL 0x00 // Null tuple
      d! d3 }5 }- J, O2 |
  12. #define CISTPL_VERS_1 0x15 // Level 1 version/product-information; a. I) k5 U" k3 [  v8 Z$ k7 ?
  13. #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
    9 W* d) e. h/ z1 X- \& M
  14. #define CISTPL_FUNCID 0x21 // Function Identification Tuple
      Y* s) }! s; c. l
  15. #define CISTPL_FUNCE 0x22 // Function Extensions
    - d3 r: E- I9 X$ U: }- j
  16. #define CISTPL_END 0xff // The End-of-chain Tuple
    $ l9 s0 b7 E- p+ m& P( h- X* b
  17. + K) v( M2 D8 P$ r7 b5 ^
  18. #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)2 U0 R/ N3 k- L' w
  19. ! w. s$ A( w, K( A4 i; w) ^7 B
  20. #define WIFI_SQREADBASEADDR0 0x10
    0 H! U6 z2 e+ I: w& ^
  21. #define WIFI_SQREADBASEADDR1 0x110 U1 ?4 O$ E) V5 f
  22. #define WIFI_SQREADBASEADDR2 0x12; u( a; D  e$ f- _3 L' J
  23. #define WIFI_SQREADBASEADDR3 0x139 N, U5 k$ `. K2 a  o: `7 Y$ v
  24. ( r) D& H) i) I/ ^
  25. #define WIFI_CARDSTATUS 0x20 // Card Status
    ; B5 ?4 i6 f* L$ @% E
  26. #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator
    & X  Y4 m! N9 B
  27. #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
    # H6 Z; G; d7 a; {2 C
  28. #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
    / [. r' C; f, U8 O  }- K6 C
  29. #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready9 J! B# x( u2 g+ d
  30. 3 u+ S6 |) F$ O8 ]- G
  31. #define WIFI_CAPABILITY_BSS _BV(0)
    7 k5 i9 P3 h; Z: |
  32. #define WIFI_CAPABILITY_IBSS _BV(1)
    % p3 O3 y4 e, c  q8 b
  33. #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)' B6 k$ G0 ?5 H4 e1 q
  34. #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)& G3 F. j5 L( B1 F1 l' h; Y
  35. #define WIFI_CAPABILITY_PRIVACY _BV(4)1 a# j! ~" \# w; Z( j
  36. #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)2 Y. z; |  n+ t9 {
  37. #define WIFI_CAPABILITY_PBCC _BV(6)
    " u7 [  S/ M- H2 ~
  38. #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)
    ' S, X& [$ k/ d9 b8 \
  39. #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)) L7 s2 j* s' N4 ]& @
  40. #define WIFI_CAPABILITY_QOS _BV(9)4 w; s& K  ?+ K0 Z8 _5 ^9 J
  41. #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)' o1 H6 L4 Y$ q- }- p
  42. #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)9 F' k/ r5 I  ~/ @) j- q4 K- X

  43. / V; u  y( V3 S& o+ e0 I
  44. #define WIFI_SDIOFRAME_DATA 0x00
    ) @' W1 J4 S. e4 N* P6 s9 W- L
  45. #define WIFI_SDIOFRAME_COMMAND 0x011 q' V% X2 k- l, N# b
  46. #define WIFI_SDIOFRAME_EVENT 0x03
    4 `' Z" v- q3 y$ Y( f; s0 i
  47. 1 B$ M: N0 }1 R) @" s
  48. /* Command List */
    5 [1 b# t1 V. s; K) c5 Q
  49. #define CMD_802_11_SCAN 0x0006 // Starts the scan process
    6 g& E& ]% g, ~+ s
  50. #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP0 k# x6 C* Q% U6 l, G7 r
  51. #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
    , }, S& k) T9 \' Z5 Q1 o' w
  52. #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network3 s4 i$ V. w# @% j/ D& s  {  i8 n
  53. #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address$ z# ]3 M9 g- r# Y3 h# K
  54. #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption
    1 U/ t( C) ]3 r
  55. #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration# d6 P. p, ~2 g! ]
  56. #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results
    - X+ E, P3 R, H6 \+ O6 X

  57. 9 P- a7 V& _: v) o: ?
  58. /* Command Result Codes */
    7 m9 `$ W1 X8 b8 e! l9 k* G
  59. #define CMD_STATUS_SUCCESS 0x0000 // No error
      x" m7 U& v$ u5 A7 H% h: o9 e
  60. #define CMD_STATUS_ERROR 0x0001 // Command failed4 \, ]* U7 K6 z+ q5 u7 s
  61. #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported( r( p, u% ?' x. W9 S" T, O8 g" |5 w
  62. 5 X. E2 m7 b% |7 e* F' o
  63. #define WIFI_ACT_GET 0
    9 f: h- E! o- k: K
  64. #define WIFI_ACT_SET 1
    ; E! W: V, e5 [8 V' K0 h  ]
  65. ( B- G" q5 M" i; A, A
  66. /* Authentication Type to be used to authenticate with AP */
    ( C4 l4 M( K3 J$ Q
  67. #define AUTH_MODE_OPEN 0x009 d6 [  r8 C1 H5 Y2 O* K4 p
  68. #define AUTH_MODE_SHARED 0x01
    % I3 G+ }3 f# a% V/ D
  69. #define AUTH_MODE_NETWORK_EAP 0x80
    , l6 ^7 K( g7 k+ f$ ^% V
  70. ! V8 N, f6 u2 N/ b0 G3 z: Q/ x
  71. /* WiFi_Associate return value */' e$ d* A3 z% x& N
  72. #define WIFI_ASSOCIATION_NOTFOUND 0xfffe
    / A$ i, J, A0 O$ Y
  73. #define WIFI_ASSOCIATION_ERROR 0xffff
    ) p/ O/ k$ n1 E5 F# G
  74. #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功, ^: |9 P/ z0 Y5 A! l. T) u! b
  75. #define WIFI_ASSOCIATION_INTERNALERROR 0x0101# i7 u9 E, b) @/ y' `7 N% i7 @
  76. #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧2 z8 J( Y$ f7 G% Q$ v2 V# N4 ?
  77. #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213: z: {! }  P+ G7 m1 h
  78. #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
    7 k( i: ^) ]- ?2 ^
  79. #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败; {; E$ e) n$ D+ U) E% ^9 B
  80. #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时) G/ H/ R3 ~6 I( H; j
  81. #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时
      ~  X9 O' s& j5 \1 U" q
  82. #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时1 t4 }& a+ b6 \8 J3 g7 Z# V
  83. #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
    + c, ~$ t* ]: @" n3 w" o$ z$ E- d% U+ x* G
  84. & V% ~. R& o  b" e( m8 L3 s5 i5 m
  85. #define WIFI_KEYTYPE_WEP 0* B  o# E4 R: E) V6 o
  86. #define WIFI_KEYTYPE_TKIP 1
    - v/ ]; T3 S' K3 J
  87. #define WIFI_KEYTYPE_AES 2. i+ O- ~2 g# q' k0 W5 F

  88. 0 \. {) K$ e( M0 k
  89. #define WIFI_KEYINFO_KEYENABLED _BV(2)9 N+ e+ x& R" m8 n+ m# }
  90. #define WIFI_KEYINFO_UNICASTKEY _BV(1)
    2 T4 m$ J: u" f  T& z$ J# w
  91. #define WIFI_KEYINFO_MULTICASTKEY _BV(0)
    , R* w& \2 ~, u; \
  92. 9 u* x  ?6 ~. u
  93. #define WIFI_MACCTRL_RX _BV(0)
    4 u/ p1 ]1 j2 p7 u$ |
  94. #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!4 c* q; _$ t% j  p# @- I$ C
  95. #define WIFI_MACCTRL_LOOPBACK _BV(2)
    2 _) z6 O- P% W
  96. #define WIFI_MACCTRL_WEP _BV(3)! t# J$ ]% d2 ^1 s
  97. #define WIFI_MACCTRL_ETHERNET2 _BV(4)% N: C! ^6 Q( [$ n  y: V6 E
  98. #define WIFI_MACCTRL_PROMISCUOUS _BV(7)7 G8 Y6 s# q) a
  99. #define WIFI_MACCTRL_ALLMULTICAST _BV(8)* t0 n2 E7 s/ k6 o
  100. #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection
    - o9 F( }& [; e, B/ Z+ S' I
  101. #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode
    & F! z9 s2 {2 E

  102. 3 l& C5 J, p- u' q( p' h
  103. /* BSS type */9 h8 h$ p5 e1 K/ z5 ^# z
  104. #define BSS_INFRASTRUCTURE 0x01
    5 M! l/ q) I- {& ]/ S. a2 `+ \
  105. #define BSS_INDEPENDENT 0x02
    7 D0 h# E6 i& T0 C3 ^& R7 c
  106. #define BSS_ANY 0x03" \6 c1 x+ q7 W0 d; P- n
  107. 8 c% d3 N: y5 z
  108. /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */
    2 {+ B) a: \$ `
  109. /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */
    ' {3 \3 Y: s5 R8 [; G. V
  110. #define MRVLIETYPES_SSIDPARAMSET 0x00009 G* P8 I+ L6 Z
  111. #define MRVLIETYPES_RATESPARAMSET 0x0001
    1 Q. M# v* P; a% Q
  112. #define MRVLIETYPES_DSPARAMSET 0x0003
    , c; Y* W. @  g7 l! @& m
  113. #define MRVLIETYPES_CFPARAMSET 0x0004
    $ C+ z+ P6 y2 G2 Z3 N
  114. #define MRVLIETYPES_IBSSPARAMSET 0x0006
    1 B9 f/ d" L" O! E1 X: X) v
  115. #define MRVLIETYPES_RSNPARAMSET 0x0030. @8 @2 m: D  P5 a( s
  116. #define MRVLIETYPES_VENDORPARAMSET 0x00dd
    ! v5 O: [7 y  w' H6 m) B
  117. 7 C8 l" x4 L) m  X$ ^
  118. #define MRVLIETYPES_KEYPARAMSET 0x0100" K$ [: K9 S) M# M+ X
  119. #define MRVLIETYPES_CHANLISTPARAMSET 0x0101
      W, L# C) G# m
  120. #define MRVLIETYPES_TSFTIMESTAMP 0x0113+ f/ p# J  E  P2 X( M2 j
  121. #define MRVLIETYPES_AUTHTYPE 0x011f
    5 Q' ^% v- `  `7 L1 }
  122. 0 Z- o& _6 V, j, ^: c
  123. #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小
    7 {6 c9 z0 _! P9 o# M  W0 X
  124. #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小
    + O  I; C( p$ U# c* n% Y3 M: E
  125. ; i( }' [3 {( w+ O( H
  126. typedef __packed struct
    ' K7 E, x2 d# V
  127. {
    . F& ]+ l( S* n+ a0 {
  128.         uint8_t type;
    # O- O$ C2 m( r% }6 {/ {4 o, P
  129.         uint8_t length;9 a( u! X: `' l8 B
  130.         uint8_t data[1];
    2 o/ w, S3 P3 M& n; s. s! O- A
  131. } IEEEType;, ^4 d' o. g8 N( q4 [
  132. 9 T/ w/ F4 O2 G' H/ j* T" [
  133. typedef __packed struct
    " D! s; T9 c6 ?  `: C" a  ~: _$ @
  134. {7 m8 [( u* M) [; ~0 p. |1 f
  135.         uint16_t ie_length; // Total information element length
    . J( z7 I  S2 ~9 G. E" V# O
  136.         uint8_t bssid[6]; // BSSID
    2 k2 d' y2 q+ a- A
  137.         uint8_t rssi; // RSSI value as received from peer
    8 t$ ^" [+ m4 p4 _7 I
  138.         
    1 @+ c2 e+ e) Q( }( z! r2 l
  139.         /* Probe Response/Beacon Payload */, j: Q& |3 |7 e
  140.         uint64_t pkt_time_stamp; // Timestamp$ @8 A7 X/ [. F0 c' p2 E& w$ h: C
  141.         uint16_t bcn_interval; // Beacon interval; D: ?2 v( C+ r# Q( G) g1 P. m; s% e
  142.         uint16_t cap_info; // Capabilities information  r4 T) s: a$ p7 y
  143.         IEEEType ie_parameters; // 存放的是一些IEEE类型的数据
    1 a0 m3 R3 C) Y; m) W. w. q/ _
  144. } WiFi_BssDescSet;
    5 Q; M% n9 J1 E  u. H* j  s+ S4 B6 U

  145. 6 J1 B4 S  I1 F  }3 e% M6 D. @; {) T
  146. typedef __packed struct7 h& y; P1 _7 h9 B, h1 S; g
  147. {/ E* i* l4 k* w/ F; q" h! N
  148.         uint8_t oui[3];
    ; g4 p% M- k' |1 b, o- J( z
  149.         uint8_t oui_type;/ h) F. l: Y6 |0 z% ?! k
  150.         uint8_t oui_subtype;
    : W+ T& J) v/ Z; H# @5 N& a5 M
  151.         uint8_t version;$ V- c$ t; Y% K
  152. } WiFi_VendorHeader;
    # M3 ^% V0 a: D) g& a& R3 I

  153. . \; Y( `3 p% T: h
  154. typedef __packed struct3 o: `% R% ?0 A- [% ]  i
  155. {
    & W, e1 u. |1 k' K4 _& d
  156.         uint16_t type;
    3 i& t! Y) Q$ `
  157.         uint16_t length;( [& C+ y3 V" i0 g0 |9 O1 C
  158. } MrvlIEHeader;, \6 h$ @/ s& g1 l2 k
  159. 3 \: F# N; n5 K4 e) T1 H' I
  160. typedef __packed struct
    1 v7 w# z% R  w. Y1 E# l9 q
  161. {
    : N* g! G7 r9 E# r
  162.         MrvlIEHeader header;
    ) b3 U  J7 U% Q  l5 k% |: \) G) G
  163.         uint16_t auth_type;" @7 @, b7 n. w& `: F$ u; X
  164. } MrvlIETypes_AuthType_t;. m$ q* c/ N7 a2 s  N3 Z0 S7 z
  165. 4 w" l) y* w" A9 }# V* D9 G* T( h, l
  166. typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec
    8 n/ g& W5 D' Z3 @1 V" ^
  167. 5 A4 t2 Q2 ~2 B  s. U
  168. typedef __packed struct* G8 d! v8 m$ `4 S( m( G
  169. {8 g5 Q% O; ?$ @8 t
  170.         MrvlIEHeader header;
    3 r3 M8 k8 `6 m$ ]# E" @' b
  171.         uint8_t count;
    - g( l1 X2 c& X& H; O" I
  172.         uint8_t period;
    + S# p2 s6 z9 E+ `" e# f
  173.         uint16_t max_duration;
    . v0 s5 M; k9 ^7 Z, c) H4 }2 j9 z
  174.         uint16_t duration_remaining;1 x" L7 C: [8 x6 q
  175. } MrvlIETypes_CfParamSet_t;
    # _: E; p5 j: Y$ w: H
  176. ! H; G$ `* ^: ?
  177. /*typedef __packed struct2 i; |) j+ b$ P( G: d7 W2 c, f1 D
  178. {) Y& \$ C" ?- w7 N
  179.         MrvlIEHeader header;
    6 Z, A7 K3 E: r
  180.         __packed struct  t5 M) B! {9 g+ l. r
  181.         {
    5 t0 _# z# e' W, e* }  b- D8 @
  182.                 uint8_t band_config_type;1 d' |* s1 R5 ?- o
  183.                 uint8_t chan_number;/ _3 ^: H- G- D/ V0 {) d
  184.         } channels[1];
    4 A/ x, u0 V3 g7 h2 B: S/ v+ A
  185. } MrvlIETypes_ChanBandList_t;*/5 m9 o1 k9 b. X+ d$ a
  186. 0 ?8 p0 s) P1 b
  187. typedef __packed struct
    * o2 l, V* u* k. R' u
  188. {
    0 W! T! m% N& N+ v0 r6 n, ?
  189.         MrvlIEHeader header;
    7 I- y7 n. ^7 j" f1 P5 U
  190.         __packed struct4 M! R" f2 N: y, t1 h6 L
  191.         {
    & A9 h% C5 {& f8 G/ ]
  192.                 uint8_t band_config_type;( g- G( a' i$ y2 X7 z: J* h8 @
  193.                 uint8_t chan_number;, ]$ `" T, l/ b7 M9 o; |+ j
  194.                 uint8_t scan_type;
    2 \" o! K5 R2 D8 m
  195.                 uint16_t min_scan_time;! @  w) W  y7 @. S( Y6 g
  196.                 uint16_t max_scan_time;6 |% i4 S4 N) C  t% x! G& {& l
  197.         } channels[1];
    ' N) M) G: h! y9 K  J
  198. } MrvlIETypes_ChanListParamSet_t;
    5 [' v3 a" C/ {5 M5 d6 h
  199. & O1 m" D+ E9 G& j! N! r
  200. typedef __packed struct5 z1 ]2 f8 ]/ p+ i" Y
  201. {
    ( V$ J$ ~+ W' j* M/ ?1 x
  202.         MrvlIEHeader header;( E9 K) G) V2 l7 G
  203.         uint8_t channel;
    - Q+ w3 m/ o  l" c4 `+ Q9 t
  204. } MrvlIETypes_DsParamSet_t;7 j( {. ^" M) i9 _* Q

  205. : s) u3 w, a! x3 e
  206. typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
    6 v( S3 N4 J* Y/ I, g# b
  207. % j! h  @( B" c1 U
  208. typedef __packed struct
    & R. h6 E6 i/ F2 J- H5 A. l3 ?
  209. {" T) W1 i) }* M  w( Z
  210.         MrvlIEHeader header;
    5 e) a. i: N' E" ~" ?6 y* Z/ W
  211.         uint16_t atim_window;, e% C3 `: |1 o) ^8 `
  212. } MrvlIETypes_IbssParamSet_t;. c( A, d2 x! g; H1 o

  213. 3 }7 M1 u9 o0 ]/ T; `
  214. typedef __packed struct. M" B# e; x% {; y: u( O
  215. {
    % L2 v: t: I8 [! D, ?
  216.         MrvlIEHeader header;
    8 m  y0 a. Q7 a  J/ \9 u
  217.         uint16_t key_type_id;2 ^" B4 y' c2 V
  218.         uint16_t key_info;
    $ T( a5 r  t1 i' q8 R4 G
  219.         uint16_t key_len;  N+ i  y- ^( M2 t9 Q
  220.         uint8_t key[32];
    6 `- c; t5 c; u! P$ R
  221. } MrvlIETypes_KeyParamSet_t;
    ; `& V8 w) U7 I7 Y+ f7 m! N
  222. 5 h$ C! A) G" ~9 I* D/ g0 L
  223. typedef __packed struct6 s- Y: M; n# `" D6 s, L! l- A
  224. {
    ! ~2 Z" {. _; z/ W% D7 r
  225.         MrvlIEHeader header;0 w2 }+ D" z! o7 H. i. d4 |$ S
  226.         uint8_t rates[14];
    7 k8 P, j. \4 s$ [$ s" F; a
  227. } MrvlIETypes_RatesParamSet_t;# @8 P0 A* y' r5 R7 J

  228. ) L6 b- F2 l9 D: a/ i: C5 G3 H2 m
  229. typedef __packed struct. ~6 g6 Z- R1 V  B$ `
  230. {) c! w0 t6 }2 D# A& o# I
  231.         MrvlIEHeader header;* f$ n6 I- f0 e9 F/ i- K
  232.         uint8_t rsn[64];
    7 d# T' Z, F' d6 D. z1 \1 _( \
  233. } MrvlIETypes_RsnParamSet_t;
    3 ^; C: b2 \8 J. \! ?

  234. 6 R2 @! d: [) @) d, Q/ o+ Z% z  U
  235. typedef __packed struct* s1 Q1 G; z' m
  236. {/ L9 J, ^; d% Y6 H% p" d
  237.         MrvlIEHeader header;  I, x. i0 y0 Z: Q8 d. i3 s
  238.         uint8_t ssid[32];1 l4 a! [& l+ p) c1 v1 ~
  239. } MrvlIETypes_SSIDParamSet_t;6 _& [% X" u# n
  240. , w$ ~: ?$ E* z. G1 Y' E2 R( c
  241. typedef __packed struct
    " F7 K. k; J! n9 Q1 M9 R" o
  242. {; T0 C7 I) p; q) J$ Z+ B
  243.         MrvlIEHeader header;
    # E/ W6 O% y- j+ e9 [
  244.         uint64_t tsf_table[1];( f' o3 _" q$ W' ?8 S) O
  245. } MrvlIETypes_TsfTimestamp_t;
    0 x: L2 v8 ^# k9 }
  246. 1 H& B+ }( m# P/ S& W
  247. // 整个结构体的最大大小为256字节
    # R9 }% Q2 P7 i: }, `1 T, T
  248. typedef __packed struct- c! S* t: S  m/ X4 z3 b6 @
  249. {
    4 u1 B4 o( R1 V! N6 B
  250.         MrvlIEHeader header;
    & p' y  p( U  N
  251.         uint8_t vendor[64]; // 通常情况下64字节已足够
    ( K& g8 K' I0 ~; Q" q* B6 o
  252. } MrvlIETypes_VendorParamSet_t;) _# j4 I3 F" J* J% i; i- b% |
  253. % b+ t5 K5 b2 w4 U( T& o
  254. typedef __packed struct( w& T4 I" U- t! h; w! ]5 \2 g* ]
  255. {
    3 w) j# P1 Y1 p5 @+ C
  256.         uint16_t length;
    / S9 J/ _" y$ T  y, s/ M
  257.         uint16_t type;
    % l4 ]2 p* ^* W6 d/ N
  258. } WiFi_SDIOFrameHeader;; q& p7 b# P( n! ]$ a

  259. % Y) q& J5 E" @6 m% Z' e
  260. typedef __packed struct  U& ~+ L; H0 y( ]6 g
  261. {
    " _& G7 y# K3 _4 U( y5 D
  262.         WiFi_SDIOFrameHeader frame_header; + W& P) R# p: c0 P& g: g# [
  263.         uint16_t cmd_code;
    9 S7 l$ w/ V. w9 a4 q* L' ?
  264.         uint16_t size;
    1 A' P, V% h6 n
  265.         uint16_t seq_num;
    8 L/ W- q4 w' s7 N' o% p. h) `$ H
  266.         uint16_t result;" m! i$ w, h/ b  M! p0 V8 F1 q
  267. } WiFi_CommandHeader;+ ^4 G/ y! f# n- h

  268. / k- ]) _- R' c! u2 s6 c9 N& @# V
  269. /* Table 2: Fields in Receive Packet Descriptor */
    ! P3 \. D$ M) s7 \+ o1 e" N) o
  270. typedef __packed struct
    0 h0 y3 v; z: v
  271. {; x9 {9 P' _5 w/ x! B2 x4 o* U$ L
  272.         WiFi_SDIOFrameHeader header;3 J  T5 R4 w% Y
  273.         uint16_t reserved1;9 C& a& Y) ?; Y( K) C) [2 g
  274.         uint8_t snr; // Signal to noise ratio for this packet (dB)
    4 F9 w  A3 l. l# P8 e9 p
  275.         uint8_t reserved2;
    8 l  p0 k/ t5 \) B! M4 _! A" Z
  276.         uint16_t rx_packet_length; // Number of bytes in the payload! O+ i8 r/ y- j2 V
  277.         uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.1 {0 e7 x# b& h3 e. l9 v; U" `9 s
  278.         uint8_t rx_rate; // Rate at which this packet is received
    6 s  k1 I$ W% U0 m, ^$ j
  279.         uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet) E9 s" L/ o! P/ q
  280.         uint32_t reserved3;3 E: K$ p+ ^' F% O
  281.         uint8_t priority; // Specifies the user priority of received packet
    1 Y* y$ K, T' Q, o. l
  282.         uint8_t reserved4[3];3 {  T  C- S/ z! s" v/ T
  283.         uint8_t payload[1]; // 数据链路层上的帧
    # p; a  r$ k- o
  284. } WiFi_DataRx;
    " Q' b5 k  p' S# C! ~+ f
  285. % B. p6 M) f6 r1 y- S. o
  286. /* Table 3: Fields in Transmit Packet Descriptor */5 v; y! ~! g8 O" y! z
  287. typedef __packed struct
    - n4 U4 b, @- U3 s7 j- P; D/ V, ~
  288. {
    " E0 p/ K2 }& E3 j
  289.         WiFi_SDIOFrameHeader header;
    , m; ]6 H8 I7 ^. @
  290.         uint32_t reserved1;
    5 \# D" _: z# }# B8 K; ?# }
  291.         uint32_t tx_control; // See 3.2.1 Per-Packet Settings2 r3 f4 d8 q/ u7 N# [! G. O( ~
  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)
    ( x5 u4 ~, l" U. Z$ {0 X& Q$ c
  293.         uint16_t tx_packet_length; // Number of bytes in the payload data frame
    3 D4 O4 g- {# |7 o0 k) P. u
  294.         uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5/ J6 ~* M+ J4 A7 s5 D3 p/ I% g
  295.         uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3
    - r( i* Y; W6 `7 E
  296.         uint8_t priority; // Specifies the user priority of transmit packet7 O4 o. e* J( C
  297.         uint8_t flags;( }0 W: i# L/ k# n2 f0 n
  298.         uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations( E6 J& Q6 W3 g7 u1 X$ u  ?
  299.         uint8_t reserved2;
    : P8 L1 U8 M5 s3 ^# }4 y
  300.         uint8_t payload[1]; // 数据链路层上的帧
    4 z5 m8 D* C) F
  301. } WiFi_DataTx;
    ! `2 ~, |  v/ p8 G

  302. 2 d- R# Q/ J& Q+ D, k6 N
  303. typedef __packed struct* B# ?$ K0 U5 V+ {1 `+ v) Q
  304. {
    & L8 E0 o5 F1 @
  305.         WiFi_CommandHeader header;
    ' q9 K" h& R: F9 H- ]
  306.         uint16_t action;
    ( I1 N# n4 I# b2 h
  307. } WiFi_Cmd_KeyMaterial;3 Z7 ~+ P+ O+ v8 c" [) [/ e

  308. 7 G4 u6 Y: t0 Z2 n7 F# u* n7 m. ?3 E
  309. typedef __packed struct: p+ p: R( f+ R
  310. {
      p+ T* M6 T% ], |5 M' ?
  311.         WiFi_CommandHeader header;
    0 j6 B# j8 ~) s
  312.         uint16_t action;
    9 X3 }  _3 Y  O' ]6 z) _' K
  313.         uint8_t mac_addr[6];
    % `; U" t& _8 n# I* y
  314. } WiFi_Cmd_MACAddr;
    0 g7 P" X$ l3 ]' R

  315. 6 b( n- e! h8 Z0 r
  316. typedef __packed struct1 M$ Y3 T- R. B6 p8 A. s
  317. {
    6 K* ~# ^: j) b7 P
  318.         WiFi_CommandHeader header;
    / d) ~) [& R; l+ \3 |
  319.         uint16_t action;
    & X% X/ H( \) i: n4 H. `
  320.         uint16_t reserved;
    & N- g  V" y/ l1 N
  321. } WiFi_Cmd_MACCtrl;
    7 ~' m0 ?$ p; [2 w5 {  l- k

  322. . x, J: g% J7 S( \7 k
  323. typedef __packed struct
    8 b  k& l$ B: L9 a% ?
  324. {- F8 Y" _0 `! C% {, O: v
  325.         WiFi_CommandHeader header;) n2 r' q5 V/ b* p7 Z+ w2 ^2 c
  326.         uint8_t ssid[32];' D. N7 Z1 X: q4 V0 |% e/ E
  327.         uint8_t bss_type;3 f2 @/ ^0 `5 D2 L* \- v3 C! A2 l" J
  328.         uint16_t bcn_period;/ `! {& |5 s, d" v( H8 y! x
  329.         uint8_t reserved1;
    : o" ?+ S/ P* z! x
  330.         MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
      A7 p8 v# B" C  i' j' N
  331.         uint32_t reserved2;
    & Z3 Y0 p2 d$ G. w: \  A
  332.         MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network
    . p( u+ E/ C- j3 ]1 J; d
  333.         uint16_t reserved3[3];
    9 E6 R. z& T- n' f% p
  334.         MrvlIETypes_CapInfo_t cap_info; // Capability information, n5 D1 }8 ~) x
  335.         uint8_t data_rate[14];
    4 K5 t" g) r& z# f
  336. } WiFi_CmdRequest_ADHOCStart;5 L" p+ o* y# H9 @

  337. - Q- R# D  ]; J2 e9 K+ A& ^
  338. typedef __packed struct
    ) f. I0 r% Z- I3 v6 }! U
  339. {
    5 [* W4 T* U+ P  W# m- O5 H
  340.         WiFi_CommandHeader header;- Z5 x: X- d6 e- n$ @2 e
  341.         uint8_t peer_sta_addr[6]; // Peer MAC address4 g4 B2 E! e1 b( C: |
  342.         MrvlIETypes_CapInfo_t cap_info; // Capability information5 G1 B. L+ N6 K" D
  343.         uint16_t listen_interval; // Listen interval
    % k* u& m% D( t% q( {* Y
  344.         uint16_t bcn_period; // Beacon period
    $ [; O7 r, ^$ u) Q  |$ s
  345.         uint8_t dtim_period; // DTIM period
    3 ]+ o& I# j6 R! g( H
  346. } WiFi_CmdRequest_Associate;+ h+ p* t: f+ b
  347. 7 K: z& E, y8 d; o
  348. typedef __packed struct
    ! |5 `2 s3 z+ @4 e/ x
  349. {
    & d; i% T/ {+ o9 W8 b1 n# k1 w
  350.         WiFi_CommandHeader header;
    7 o5 b7 Y- _- s* M
  351.         uint8_t bss_type;
    4 \& J2 A! Z+ d1 v
  352.         uint8_t bss_id[6];1 K( \- a, S2 W$ Z1 b
  353. } WiFi_CmdRequest_Scan;
    + E. c* i  ?4 k8 j
  354. ) x$ M+ `4 @  B# c% e; A+ R3 H
  355. typedef __packed struct
    ! K0 G! T% D; g
  356. {9 M2 M. g, N% o  r: x3 E
  357.         WiFi_CommandHeader header;
    : s/ q/ @8 w( E) ~
  358.         uint16_t capability;0 F* j* C7 [+ h3 L3 j( j$ \# F
  359.         uint16_t status_code;
    # Y2 L8 B' v6 }% \
  360.         uint16_t association_id;$ l8 a+ A: v9 f% _1 p
  361.         IEEEType ie_buffer;
    & o( z7 y1 Z. {, j1 P, X" r; a
  362. } WiFi_CmdResponse_Associate;& x4 u/ m" M0 a
  363. . }$ F* x1 [+ n+ r1 `0 r" ?+ W
  364. typedef __packed struct
    - S& w5 Y4 N; F7 O3 R8 L# u
  365. {; Q3 x0 ~( E5 k
  366.         WiFi_CommandHeader header;/ T- }" _8 P* c6 R; v1 r: R
  367.         uint16_t buf_size;7 J- U( ^$ L# w/ {+ O
  368.         uint8_t num_of_set;
    1 J; I# }) D; Z7 q/ [' m+ H1 [
  369. } WiFi_CmdResponse_Scan;
    + F" `3 M1 r4 ]5 g! m: |+ `

  370. & ^7 k$ j: q* {% G- P5 e
  371. typedef __packed struct3 F6 s8 P) \# b; E) {4 h3 \  b
  372. {5 @5 _4 n! }, Q. a* d4 k; Z1 p
  373.         MrvlIETypes_SSIDParamSet_t ssid;
    - h; }: l; {' y9 c% d. p
  374.         uint8_t mac_addr[6];
      L  T9 w) t8 g" N0 ~
  375.         MrvlIETypes_CapInfo_t cap_info;
    5 \0 Z# u$ J5 H
  376.         uint16_t bcn_period;
    * D! U$ I! y2 N+ \. F/ c. `! c7 a8 ?
  377.         uint8_t channel;# q$ G/ W$ u/ h% |
  378.         MrvlIETypes_RatesParamSet_t rates;
    3 n2 Q) |1 Z2 A* F4 h6 ^
  379.         MrvlIETypes_RsnParamSet_t rsn;' _, t( w* i4 ^! e" k$ C" \
  380.         MrvlIETypes_VendorParamSet_t wpa;
    0 {, h) ]6 A" `& [3 l& {
  381.         MrvlIETypes_VendorParamSet_t wwm;
    4 \  R/ `, u# V3 j
  382.         MrvlIETypes_VendorParamSet_t wps;
    ; W0 T$ X, J( Z# ?' l
  383. } WiFi_SSIDInfo;3 z% R/ r! ~* u% ~' |

  384. / F& u4 N" D% Q6 ~4 a% i2 q2 v2 g! P
  385. #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)
    2 f$ q4 {7 }& E7 m
  386. #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)/ ]; e% ]( p' ^* y( g
  387. #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)  f+ C1 i! Z. D0 l2 Q
  388. #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY), j  p3 `: F# d9 B
  389. #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)) G6 a5 S! q( j+ w& _3 }( w
  390. #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)
    $ X. ]0 i2 H4 b! P2 R9 i6 _
  391. #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)
    * N+ \+ S9 V: H# a5 L5 [' H( ]

  392. ; R8 [2 ]1 r, D0 l
  393. uint16_t WiFi_Associate(const char *ssid);9 n" f4 b  c  C+ x5 g
  394. void WiFi_CheckCmdTimeout(void);
    ! v( S7 B4 {& }2 x( V9 A& j( H
  395. uint16_t WiFi_Connect(const char *ssid, const char *password);
    6 J* [4 q  J% L9 s. L  f
  396. uint8_t WiFi_DownloadFirmware(void);
    0 P) G; B) J: O) h
  397. uint16_t WiFi_GetPacketLength(void);
    1 i+ J7 n3 S. R* V
  398. void WiFi_Init(void);" ~8 I# h% O% }0 D
  399. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
    : |3 {& y0 H. P' J6 s  C
  400. void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
    ) Q% ~1 F! }7 Y& b' a0 _
  401. void WiFi_MACControl(uint16_t action);* I' g3 d2 S+ G  M" b* ?) N
  402. uint16_t WiFi_PacketPending(void);* e. k3 b8 I6 [1 S" H1 A* A: a! }
  403. void WiFi_PrepareTimer(uint16_t nms);
    6 b6 q. @# S* ^! x/ ~+ L
  404. uint8_t WiFi_Read(uint8_t func, uint32_t addr);8 i6 Q: k- `& B
  405. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);- X8 o: o" f2 x2 I0 G
  406. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);
    " w0 t3 @: n& a( ?  A
  407. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);
    7 m7 I2 k  D2 E2 L  N
  408. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);" I4 ^8 C5 U% v$ q4 ?, R3 _4 h
  409. void WiFi_Scan(void);
    - s1 A" g7 ^2 m6 n& |% F: \+ h
  410. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);$ `2 |! ^! `: T* f8 j
  411. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);0 i* A$ }- o) P, b
  412. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
    % I: p3 z  X1 G+ M% k$ t
  413. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);
    & b6 \5 A* H- T2 ^# G
  414. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);. a8 }1 k4 P4 U! p( Y5 h
  415. void WiFi_SetBlockSize(uint8_t func);: n% W- M7 Y# _! R- Z
  416. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);
    0 b1 \2 j$ q6 J
  417. void WiFi_ShowCIS(uint8_t func);
    ( n4 i  I' x7 N; Q
  418. void WiFi_ShowKeyMaterials(void);
    9 N4 f! B6 r3 A: z/ \8 a
  419. uint8_t WiFi_StartADHOC(const char *ssid);' f0 W+ \# j( J
  420. uint8_t WiFi_Wait(uint8_t status);
    ( ^: H8 Z% m* s/ Y
  421. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);( `0 e( W7 B6 ~3 ^- D$ K  m" i
  422. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
    ( e/ z& `: X1 P# D1 D( s+ Z
  423. uint8_t WiFi_WritePort(const void *data, uint16_t size);% V- a- ~& U9 A# j  M* u* r6 S* W
复制代码
【WiFi.c】3 o+ f4 T! ^5 a( O0 ~& e4 a4 P
  1. #include <stdio.h>) L1 }7 E4 M* T1 U- R! B
  2. #include <stm32f10x.h>6 o7 k3 D1 [* t/ Z; B" p
  3. #include <string.h>
    8 y8 l7 x/ R: H  U3 }0 U5 L8 ^3 i
  4. #include "WiFi.h"3 Z0 ?/ E3 t6 Q$ O& y

  5. ) X! s  N2 _/ R) ~1 ~# K
  6. extern const unsigned char firmware_helper_sd[2516];/ O) n8 ^% S  y( U
  7. extern const unsigned char firmware_sd8686[122916];
    8 L0 x  r9 d, ~, q6 t
  8. 2 G  R4 C+ o: V2 z
  9. //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
    ) d2 D' e% L. f) @0 z& n# v

  10. ) G2 j4 D& ~' b& q4 I- X# ~7 M7 \4 @
  11. static uint16_t rca;
    / J, e8 r' o, F, I) j
  12. static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;
    2 \9 K+ G# u$ T; @" p" O% y8 r0 K/ z2 ?
  13. static uint32_t io_addr;
    - U5 p% N% f" o8 x
  14. static uint16_t wifi_pending_size = 0; // 未读的数据包大小
    8 g  y+ @9 l. L) C& f
  15. " A9 X' b) i( Q# D' F, a
  16. void delay(uint16_t n);
    0 G1 t6 c4 Q; [2 Q% c8 Q: S  b5 C4 \
  17. void dump_data(uint8_t *data, uint16_t len);
    : B7 ?- K0 L$ {. C7 U
  18. 1 F# r9 y, i3 \, G( s
  19. /* 关联一个热点 */
    2 C& I1 x, f  x. T3 E: [8 E
  20. uint16_t WiFi_Associate(const char *ssid)
    : `: h( m; m& C: p4 ~  d
  21. {# s9 t( T. M. a) _$ X
  22.         uint8_t buffer[2048];! M7 W6 E* A  \
  23.         WiFi_SSIDInfo info;
    & n  w9 F6 ^' _
  24.         WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;
      M0 ?1 B4 L" ~( C: \
  25.         WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;) R0 m1 u% }  z$ H
  26.         MrvlIETypes_DsParamSet_t *ds;2 r0 a3 ]2 e3 v0 L4 c
  27.         MrvlIETypes_CfParamSet_t *cf;' |! s5 N! @; P! @. s8 I0 x
  28.         MrvlIETypes_AuthType_t *auth;- s6 J9 V/ k3 o2 a* w6 k$ j
  29.         MrvlIETypes_RsnParamSet_t *rsn;
    ' r+ s) J  p7 x7 G4 P* g/ ^

  30. , h! b1 U/ ~- E
  31.         if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))5 U8 E$ @; M; n4 C9 r3 q  I
  32.         {
    ' |6 L& e6 _6 W) \
  33.                 printf("Cannot find AP: %s!\n", ssid);
    3 y3 p1 N0 t( l6 U0 e
  34.                 return WIFI_ASSOCIATION_NOTFOUND;
      ~' G3 J1 M7 M" V" d- H
  35.         }
    8 d- X! `) k0 U" f9 V3 n) ~$ y. b, J
  36.         
      J) c+ c- A3 i6 @6 W- v
  37.         memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));3 d6 D+ ]  b# W! U+ ]+ W# _$ |. k6 ^
  38.         cmd->cap_info = info.cap_info;
    4 l9 H$ a5 L% s6 E: ^5 e
  39.         cmd->listen_interval = 10;
    9 I6 l! }, u" \( K  ]
  40.         cmd->bcn_period = info.bcn_period;) z. M0 R% l  S
  41.         cmd->dtim_period = 0;2 H7 C$ c) a9 r+ s
  42.         memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));) v% W9 n  y% ^/ s+ b
  43.         1 t1 ]; [  d; h& T; S( Q7 b
  44.         ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));, w" v: o0 @+ ~+ s: O
  45.         ds->header.type = MRVLIETYPES_DSPARAMSET;
    * M6 @+ c' J" W
  46.         ds->header.length = 1;3 n  b' g: f" k7 N! k( o
  47.         ds->channel = info.channel;
    - k/ }+ c8 K& P0 D, I
  48.         , k# d3 Y  q4 U' |! L& {, @
  49.         cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);7 I9 p" u' y- Q% m% T% f3 P- W$ f- q
  50.         memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));; \8 g6 f% y" B% ?
  51.         cf->header.type = MRVLIETYPES_CFPARAMSET;
    5 E* H" M# S6 e& P: j- i
  52.         cf->header.length = MRVLIE_PAYLOADLEN(*cf);8 O/ U  h3 |6 T5 T
  53.         # |4 s5 R& J/ F; s7 j
  54.         memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));
    ; ?% x2 S( g2 C' e  k
  55.         auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
    + H! _* ^( B- X8 }3 @
  56.         auth->header.type = MRVLIETYPES_AUTHTYPE;
    9 i: E7 T: Q) l& D/ n; `, Q# ?: T
  57.         auth->header.length = MRVLIE_PAYLOADLEN(*auth);3 C5 w" J6 y9 F
  58.         auth->auth_type = AUTH_MODE_OPEN;( l7 G' [3 N# V3 a; s
  59.         
    2 \7 X) p3 L$ _3 i0 z
  60.         rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
    6 w6 F9 l$ l+ b
  61.         if (info.rsn.header.type)
    # i$ c- P8 Z# v- Q: e
  62.         {
    $ s1 J& R2 T7 d- ~
  63.                 // WPA2网络必须在命令中加入RSN参数才能成功连接: H: y1 B0 r5 _/ r( `' k
  64.                 memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
    ) \$ v  ^% O& W% ]; s
  65.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));
    & }# p5 ]+ ^" u0 L* p. W: p
  66.         }
    * c2 S& K/ s' H$ Z$ x
  67.         else$ x2 v8 ?; F/ U5 @
  68.                 WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数
    5 e. F4 A- c+ V' o7 V2 u
  69.         
    6 P: T  I4 T  o* ~
  70.         if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))2 N- t- j2 z! z' q
  71.         {0 Z2 Q7 Q4 a# A9 O5 ^- \0 \
  72.                 printf("Association with %s failed!\n", ssid);
    " }3 l# N8 @' l2 O3 {/ Z
  73.                 return WIFI_ASSOCIATION_ERROR;/ o+ B& j) a( I$ \
  74.         }
    ' F' \/ O0 O/ P! U$ F
  75.         
    & Y" i0 j0 k4 P2 l7 ~4 G1 m2 Z" S1 ?
  76.         //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);
    ' L+ O$ U3 D& e1 M
  77.         if (resp->association_id == 0xffff)2 L  x" o+ u5 _) o8 w- N7 ~
  78.                 return ((-resp->capability) << 8) | resp->status_code;
    % I/ F2 t4 ]1 X/ H% I) l" Y5 M
  79.         return WIFI_ASSOCIATION_SUCCESS;
    ) h1 x* [8 _6 |+ v! ^9 u" Z
  80. }# C* T3 s$ E  _
  81. 6 C% v5 E2 }& ?" w1 L' F% ?
  82. /* 检查命令是否收到了回应, 若没收到则重发命令 */
    1 L1 h8 F5 ?+ z; C7 T2 Z3 l- y2 w5 J7 \
  83. void WiFi_CheckCmdTimeout(void)
    " t& y, p$ J1 O$ d" n3 |7 q3 \
  84. {; d' w9 Z3 h: U# Q8 ~
  85.         while (SDIO->STA & SDIO_STA_CTIMEOUT)  F. a0 u% i; E' m) J: H8 e6 i: j! k
  86.         {
    . a. k# X0 l! B% X
  87.                 SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志1 X9 _! m; {& X: v
  88.                 SDIO->CMD = SDIO->CMD; // 重发4 J% i+ _8 o  y# R
  89.                 printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);0 G8 X% D* R7 k
  90.                 while (SDIO->STA & SDIO_STA_CMDACT);
    + }! B) n& H- i! Y0 R
  91.         }
    % x2 y  V; I; s/ b* ~
  92. }
    . O! R: o- l8 i) \. @% p
  93. 6 C4 H* b4 e7 K" b) _! b
  94. /* 连接WiFi热点, 并输入密码 */
    6 j* ~) l) `# q/ s) P, c4 Y: v
  95. uint16_t WiFi_Connect(const char *ssid, const char *password)
    5 P5 w( {  Z% ~# B4 M' V
  96. {
    2 \0 `+ c& y) j) H( W  f% R' C
  97.         uint16_t ret;/ E5 H6 q4 b, A" r- B! I! Q+ l
  98.         do; `- q" `, Y5 T7 b0 Z& I; E
  99.         {+ `$ p8 ?; p% G! g
  100.                 ret = WiFi_Associate(ssid);3 \, e; {5 S) V7 R
  101.                 if (ret != WIFI_ASSOCIATION_SUCCESS)2 t7 |0 `: w/ A
  102.                 {  B  f& F, C  H" x  G1 |# [
  103.                         printf("WiFi_Associate returned 0x%04x\n", ret);
    9 v  y; `: h; ]0 ?8 B
  104.                         delay(2000); // 等待一段时间后重连9 l4 X: Z4 _% R/ V% S9 ?% h7 V+ w2 U
  105.                 }& K+ p5 J2 K$ V7 J6 Z
  106.         } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连/ _' k% \" Y4 ~( T  K  O/ b
  107.         
    , ?$ p" _! `1 Y9 K9 v; L) j, s. X/ h
  108.         if (ret != WIFI_ASSOCIATION_SUCCESS)
    ) \$ M5 C  o" o# D2 z! e- n
  109.                 return ret;, O( \9 y! c* F3 p
  110.         
    ; c2 V' e- f7 g3 g) G
  111.         printf("Connected to %s!\n", ssid);; [" n, n" a: H% ?
  112.         return ret;; v* c& U' O% `+ ~4 {) V% ~% b  D
  113. }
    * ?3 \: E7 t2 T* c( \# P
  114. ; o# }  E; v" w4 k0 `
  115. /* 下载固件 */
    ! E: B! c7 e) ^3 K4 i3 r* m) K
  116. // 参考文档: marvell-88w8686-固件下载程序说明.doc% n6 M: U# ]9 H2 f6 j
  117. uint8_t WiFi_DownloadFirmware(void)( U0 U/ ^8 L: U' `; h2 g2 [. m
  118. {
    6 D. v- c+ n3 k- [+ X5 F% u
  119.         uint8_t helper_buf[64];
    9 I# ~, R9 M1 t  K
  120.         const uint8_t *data;4 W6 m, t; g7 l# P
  121.         uint16_t size;
    9 k5 n; H7 V/ I- U/ o4 I) g$ j, p9 j; `
  122.         uint32_t len;
    $ R4 U( r. W# V0 N; H8 m; m1 f
  123.         
    ; M9 T4 w8 m% l6 s# [
  124.         // 块大小设为32
    5 _  Z, ^* F) d8 R7 }6 C
  125.         SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;: w1 r; d5 a/ s* s6 r
  126.         WiFi_SetBlockSize(1); // 应用到Function 1
    / B$ T% c- O# n9 j7 K& ^; f
  127.         
    7 A6 V: m$ Z& q- f
  128.         // 下载helper
    / `6 _% [7 a" T+ u
  129.         io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);
    , P0 F* V& t5 i+ o7 x3 ?% v% o
  130.         data = firmware_helper_sd;" O% `. u, O1 L1 N5 I# K& v+ L
  131.         len = sizeof(firmware_helper_sd);
    + }8 J' B" z  g, ?9 J
  132.         while (len)9 ?( M- K9 |  s# q
  133.         {' S6 X, n5 [( g$ L$ B. M9 A- Z, m
  134.                 // 每次下载64字节, 其中前4字节为本次下载的数据量
    ! w$ c! W6 M! F
  135.                 size = (len > 60) ? 60 : len;; K% O; ]! E4 J) \2 t
  136.                 *(uint32_t *)helper_buf = size;
    6 b5 q9 L* e: m3 U3 k. b# m+ u
  137.                 memcpy(helper_buf + 4, data, size);1 r" d; b' q" I# ?# J' y4 k) j
  138.                 * v" z- z  H! H& u5 n9 C
  139.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    2 G8 o2 r* E6 y/ Y
  140.                 WiFi_WritePort(helper_buf, sizeof(helper_buf));
    : m5 |8 O7 ]$ U5 C8 c
  141.                 len -= size;
    0 l4 @4 R5 A# l9 H
  142.                 data += size;
    + D- B5 S4 Q  F' h6 c: n1 I3 ~3 q, o
  143.         }
    - Q" b9 y( w. T* q
  144.         *(uint32_t *)helper_buf = 0;
    / ~  v( Y  s% w% m3 f- b
  145.         WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束$ R* J; r( a$ s2 Q5 x) H
  146.         
    ! g' m. {# h: U, G8 o+ T7 z- y
  147.         // 下载固件5 [1 Q; o1 l, e% }0 d$ Y0 W
  148.         data = firmware_sd8686;
    ; l1 b/ h$ ?5 o' F7 X8 q
  149.         len = sizeof(firmware_sd8686);
    " z% j, K( }" H: Q; a0 r( |" O
  150.         while (len)! ^" B; n9 I8 O) V/ s" w0 o; b
  151.         {
    ' N* p3 y2 Z. j/ d% i5 R
  152.                 WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
    5 C/ e1 I$ ?/ A) E
  153.                 while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数. k( R. F, }# [) D5 c. S1 \
  154.                 //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);( J% r% w: x4 M+ S5 b3 Y' U
  155.                 7 E+ Z5 I, A" Q1 Y
  156.                 if (size & 1)
    ( m; f: t- t3 k
  157.                 {
    1 A, Y$ V5 W/ I& _  j1 q
  158.                         // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)9 _5 `4 F# x4 x$ Z/ `5 b' E
  159.                         printf("Error: an odd size is invalid!\n");
    $ w/ H. B( ?) l5 f
  160.                         return 0;
    . J3 y- M8 @( S( O
  161.                 }' s  h- C% p3 Q  S0 A3 @
  162.                 if (size > len)
    + c) W$ a4 _; n) \. @/ N4 ?0 d
  163.                         size = len;
    3 M9 @1 X4 G9 M$ c5 d
  164.                 - X- _7 ]% `% X
  165.                 if (!WiFi_WritePort(data, size))
    ! o( o0 @! n7 I5 Q& n2 B4 {
  166.                 {
    - F' d7 l  V0 d* e9 k+ y
  167.                         printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);
    5 v& `0 G: v6 R# {0 T& L
  168.                         return 0;
    0 u' ?0 v6 J) r& T$ ~# x- T
  169.                 }
    9 f: m% e) ]+ }6 i& K: p
  170.                
    : {7 p* x- Z5 Z8 \% K/ B
  171.                 len -= size;' Q! D% B/ E4 H4 s( m# r- e
  172.                 data += size;$ h2 c" j. m4 \8 }4 D. u
  173.         }9 c% Q8 S& F; [
  174.           D' N8 Q2 u0 ], ~; \
  175.         // 等待Firmware启动1 B  m2 `' F7 O/ L6 d% P6 }
  176.         while (WiFi_GetPacketLength() == 0xfedc);
    ! B' Y( p, x7 s. s) o8 p
  177.         printf("Firmware is successfully downloaded!\n");0 N" ?8 h/ z2 T6 I" O- v
  178.         return 1;
    8 J8 G1 `2 I' n! W
  179. }
    $ M! O: V- {/ d9 p7 u& ^/ B

  180. 8 P8 P7 O( R! U
  181. /* 获取数据帧大小 */; Y0 Z$ K) u) ]* Q6 C
  182. uint16_t WiFi_GetPacketLength(void)( `. |0 N6 @- D8 k1 R( v
  183. {
    . I# j  q) K* Z! n5 }5 V2 b' U0 b
  184.         return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);0 O: [2 W" w: L# e4 C
  185. }) b# O8 b3 o% D( E1 N" H* z

  186. - S8 X, p7 u; h9 E' j0 J" C8 i
  187. /* 初始化WiFi模块 */
    8 B: g$ K; g) G4 |* X6 @8 _6 T
  188. // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization8 @. w4 }* Q5 u4 [. g4 H- |
  189. void WiFi_Init(void)
    5 M; A0 V- g$ b# S" j5 i( w; h
  190. {2 r$ ]) L8 a  y+ s( e; H
  191.         printf("Initialization begins...\n");
    0 J5 H% A" W; u" _' J3 f
  192.         SDIO->POWER = SDIO_POWER_PWRCTRL;1 S  `$ ]/ P) ?5 W& w
  193.         SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz2 Q) X( x% N. C9 \4 i, S
  194.         delay(5); // 延时可防止CMD5重发8 Q; h( S! a, D# }- b
  195.         
    1 d7 F1 f+ ~+ m1 e5 a  o2 i
  196.         // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52$ N" G2 Y1 N. C6 U
  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)
    $ F1 c" j# x' `0 D- O
  198.           M1 n; j3 r' x8 _9 ~
  199.         /* 发送CMD5: IO_SEND_OP_COND */0 K* k4 b/ e' J
  200.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;0 g  @2 }0 E$ X. {
  201.         while (SDIO->STA & SDIO_STA_CMDACT);1 i7 a- ?8 h7 u; _3 d8 \3 K% j$ Z
  202.         WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令" k1 d" ?& ~5 G- s  K1 W- V
  203.         if (SDIO->STA & SDIO_STA_CMDREND)
    , r7 P, E1 b' i* y+ @% l2 h
  204.         {
    : j6 O4 n7 a7 `' O! A) T8 E2 g1 \$ P' Y
  205.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    0 A! `0 F9 U" o
  206.                 WiFi_ShowShortResponse();. B: o7 z+ q5 o/ v3 Z, r: K
  207.         }
    0 q, x) E( }$ H5 M0 I" Z
  208.         
    . C! E! I, T/ g9 k+ [
  209.         /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */
    ; ^$ F# A- A) L- r
  210.         SDIO->ARG = 0x300000;
    1 I4 s6 V6 T2 P# f2 t+ e: U
  211.         SDIO->CMD = SDIO->CMD;
    6 V, P( ~% l1 y2 l2 R! p* B4 n5 R# T
  212.         while (SDIO->STA & SDIO_STA_CMDACT);) v! G: v; r3 c5 u4 r) n( k7 ^: w
  213.         if (SDIO->STA & SDIO_STA_CMDREND)
    # @( d+ ?" C& \5 Z+ A5 o" m3 a
  214.         {
    6 C& C# t: R; y$ \+ d6 l
  215.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    5 G! Z% b8 f- q
  216.                 WiFi_ShowShortResponse();" @9 k% g. t$ o  \, }
  217.                 if (SDIO->RESP1 & _BV(31))
    4 T2 b0 ?5 `) K2 e( R
  218.                 {5 C* v  ?" c( V/ ?  I
  219.                         // Card is ready to operate after initialization
    % C3 H3 m5 t  @; M6 L
  220.                         printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);0 }6 T$ X# ~: N
  221.                         printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);
    5 G9 y7 [; O6 o; e7 D
  222.                 }( \: C5 z2 y- A! u
  223.         }
    9 H, i2 s+ w! f. `4 V* o7 Q
  224.           x0 `9 G( B+ [0 ?6 I* u
  225.         /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */% }# l- [7 }! s7 X6 g$ v( y
  226.         SDIO->ARG = 0;
    / F* p' F7 Z3 H- x5 h) f
  227.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;- x% i5 D8 x) O: h" ?& T' M& Z
  228.         while (SDIO->STA & SDIO_STA_CMDACT);* M/ f- r8 P' d& w
  229.         if (SDIO->STA & SDIO_STA_CMDREND)7 M7 B; r0 O+ D2 ~
  230.         {/ }- F. g- J8 v
  231.                 SDIO->ICR = SDIO_ICR_CMDRENDC;, e4 w. ]4 j/ f0 O5 a
  232.                 rca = SDIO->RESP1 >> 16;2 e( |0 i+ \7 a8 K  P* l
  233.                 printf("Relative card address: 0x%04x\n", rca);& r1 F4 a$ [9 ^8 ?
  234.         }
    " X$ Y) G. \2 K% |
  235.           i7 a9 B+ d3 u. _: v: i, p
  236.         /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */) j) O6 q- B; N4 i  j
  237.         SDIO->ARG = rca << 16;2 z3 O4 V" I0 ^: g1 p' \
  238.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
    . q( n$ i6 t% G1 a2 |8 m! ^0 `
  239.         while (SDIO->STA & SDIO_STA_CMDACT);# u& v/ U7 S  e6 j
  240.         if (SDIO->STA & SDIO_STA_CMDREND)
    8 }0 \; H  N3 h1 X! i7 n! b; S6 k9 u
  241.         {
    ' w  `5 T, s6 [1 C- ?! r; F/ v
  242.                 SDIO->ICR = SDIO_ICR_CMDRENDC;0 b* R$ ?- k2 c& z7 z* o3 {
  243.                 printf("Card selected! status=0x%08x\n", SDIO->RESP1);
    7 T0 u3 ], e6 n2 o1 @5 h+ u1 t
  244.         }: d8 s: z3 J: D+ i0 {; i/ Y
  245.         - L* M( f$ G' V9 ], l: \' T4 Y
  246.         // 提高时钟频率
    " C8 H, Q! I1 b# |( b0 A' _
  247.         SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz3 c4 Z/ c9 u- h. Y( [5 ]! c) k
  248.         SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒
    - `3 a8 j- P: j  G0 Y; h2 @  B4 {
  249.         //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
    # }2 X8 E; A4 S; e. F+ V
  250.         8 M; [7 q: H* U
  251.         /* 选择总线宽度 (Wide Bus Selection) */8 \# c& M; z& b) h2 Z/ ?  K, Q
  252.         // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)
    1 W/ {5 {. s, B3 }+ D1 Q: X  ~# c
  253.         // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
    8 N# e% h9 N8 k' E9 a& y0 o
  254.         WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus' O& A4 K, B( v4 L7 u
  255.         SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
    * q1 E% c4 ~" x
  256.         : K3 n9 e" W$ l/ n' B
  257.         // 初始化Function 1
    ( K2 c, i2 U% U
  258.         WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)
    2 A5 f! I( U: I8 b5 a$ F5 z
  259.         while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)% p# S. {2 R6 n) s
  260.         
    ( T* w6 a$ K  U$ Z# f
  261.         // 显示CIS信息$ V/ z. |; G  e8 ?7 {/ i
  262.         //WiFi_ShowCIS(0);  B/ \6 _$ s$ I) Q! a) n
  263.         //WiFi_ShowCIS(1);
    4 v+ x7 T" l# c: O5 A+ u3 B- M
  264.         6 M. q8 ~- {8 [+ e6 g
  265.         // 下载固件
    * r& u; g& U2 N" G3 [  n) x
  266.         WiFi_DownloadFirmware();/ I9 e/ G2 k, G9 [" Q% \# Y
  267.         ( z/ ]3 k/ h! S3 W0 _# }6 q
  268.         // 设置数据块大小为256字节) K. z2 w* E( a: q2 ?0 y+ Y5 c
  269.         SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;4 Y; c" j0 M9 C
  270.         WiFi_SetBlockSize(0);- V" A8 F! K2 _  h& f  L
  271.         WiFi_SetBlockSize(1);
    - ]+ e7 A( y8 Q! D) i
  272.         8 M% Z$ ]: Y$ a* [7 [
  273.         // 允许发送和接收
    ) T& p. d4 F2 t0 y1 F; D
  274.         // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间' L( o- `- I/ b, {
  275.         WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);
    / j0 G+ z/ W, Y4 X
  276. }
    8 H# J( C! P8 J) ]7 F7 l

  277. - M9 C: L3 r$ {1 i/ j
  278. /* 获取或设置密钥 */2 F# j+ J. O4 a6 k
  279. uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)
    4 y) q" E9 l6 m3 i
  280. {
    . j0 ]9 ~1 E5 ~" j
  281.         uint8_t buffer[256];
    1 u- O) I) k  p
  282.         uint8_t ret_size;
    2 [- J6 ]; L  N
  283.         WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
    ' t3 C; w8 e( y. ^8 V+ O
  284.         cmd->action = action;
    5 o) V& f3 t0 k
  285.         if (action == WIFI_ACT_SET)3 {; W3 M; U8 U7 m' J9 X
  286.         {5 |% r1 R: O& h
  287.                 memcpy(cmd + 1, keys, size);. }7 [2 K; T7 H* Q+ V2 D/ i
  288.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);
    ' m# q5 T9 A+ j+ S3 \/ P7 f0 r" @
  289.         }. Z+ M" e9 Y$ R5 I! N
  290.         else" \4 v1 h& ]3 Z% x/ j- n: H" P
  291.                 WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));) k6 a+ t* y. q( q6 N
  292.         WiFi_ReceiveResponse(buffer, sizeof(buffer));' ?+ y/ C0 h  l' z
  293.         
    0 y* `2 m7 y# D; D4 ?
  294.         if (action == WIFI_ACT_GET)
    % X. U& K7 V6 t5 _+ d
  295.         {
    9 V3 V8 a2 V2 r& ^; r. N0 L% L
  296.                 ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
    2 @7 U1 g( g  J$ h$ R9 |0 T; k
  297.                 if (ret_size <= size)
    1 u5 B/ G+ y3 S
  298.                         memcpy(keys, cmd + 1, ret_size);  v* T) G0 [+ X; H; @) w% T
  299.                 else
    7 A4 t  H; T6 W! i8 W9 B) g4 U
  300.                         printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);
    5 {3 p0 j4 ^+ U* L; ~% ~; e* B
  301.                 return ret_size; // action=get时返回读取的数据大小8 U! q" J9 m, H1 c9 o+ Q
  302.         }
    & B) ~: l; J" L$ r6 y9 @! h
  303.         else# h- J6 a# ]& A( i
  304.                 return cmd->header.result; // action=set时返回命令执行结果值- U+ n0 V2 d- ~5 Q' a5 A  N
  305. }( z8 H0 o0 B4 P  n7 W. ?

  306. * I" P5 U) ~$ W& ?
  307. /* 获取或设置MAC地址 */
    5 G* m# o' l. P! B5 Y) E
  308. void WiFi_MACAddr(uint8_t addr[6], uint8_t action)$ B. Z/ Z, L" u. l: ^) D
  309. {# q4 U- r  J* _7 o, O
  310.         WiFi_Cmd_MACAddr cmd;
    ) k" S6 G! m) h
  311.         cmd.action = action;+ h4 J& `& t' u: ]  @5 e
  312.         if (action == WIFI_ACT_SET)' n" J4 \) A) M" H7 m
  313.                 memcpy(cmd.mac_addr, addr, 6);
    9 e, a2 S1 ^9 ?& L6 R. g! \
  314.         
    $ J+ x3 t1 a# u; V4 j6 q
  315.         WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));
    4 A! o, V& S) [+ p; [% R' Q( D
  316.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));
    + e% e4 e9 f3 K! P( z8 N, c
  317.         if (action == WIFI_ACT_GET)( ~! o5 w! F' _
  318.                 memcpy(addr, cmd.mac_addr, 6);$ u( b- L' r: K  u! r
  319. }
    + `: Q9 C9 B$ L) f: `8 C  R" A

  320. * t! h0 D4 {; s2 g
  321. /* 配置MAC */; P2 D& t9 }' J( U5 J
  322. void WiFi_MACControl(uint16_t action)0 c& v# y2 T+ G( E2 ]4 X% G* v- Q3 ?2 x
  323. {
    1 x/ J; |, h) f* r# ^
  324.         WiFi_Cmd_MACCtrl cmd;
    2 |  l) h' q: x- P! ?
  325.         cmd.action = action;2 |6 k1 B; A5 j: v) s' [; e
  326.         cmd.reserved = 0;
    2 e& C& h% J# m! O7 G( Y
  327.         WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));
    9 s( W5 d. f* ~8 L: b  ~' p! e
  328.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));2 q% ?8 }' O* J/ W- r
  329. }
    3 P% u- V3 b6 B1 o

  330. 6 B, B9 X# c0 C6 J, z$ ~
  331. /* 获取滞留的数据包大小 */! F# H# X! P$ e+ G8 E& d
  332. uint16_t WiFi_PacketPending(void)
    ' u' n4 S! a! y& n
  333. {8 ]; g0 w% J& W2 c
  334.         return wifi_pending_size;: O4 g( T5 s- F4 c. ]+ ~- H
  335. }5 d; w3 t# e4 U0 W, V! |

  336. 8 [. \7 M# t- ?
  337. /* 准备好超时计时器 *// s* z* M( Y5 m" J; v. i
  338. void WiFi_PrepareTimer(uint16_t nms)
    3 \+ e/ T8 ]9 _8 ]6 {+ T
  339. {
    9 V5 i0 ?7 H; q
  340.         TIM6->ARR = 10 * nms - 1;
    # b* I6 u. ?+ _- e  _; ~8 ]
  341.         TIM6->PSC = 7199; // 72MHz/7200=10kHz& W. c1 t! d& K, w
  342.         TIM6->EGR = TIM_EGR_UG; // 保存设置* k6 M6 \' f# z
  343.         TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位3 N9 B( I+ O& i, i* R3 c( w
  344.         TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式  F7 D$ U4 R, \
  345. }
    : d' p2 ^- O- Q1 G

  346. 9 z) R: D; j* u* `
  347. /* 读寄存器 */
    $ }  h' g. U, E  {6 w/ k* F
  348. uint8_t WiFi_Read(uint8_t func, uint32_t addr)
    & B/ o$ v# B) m7 y4 ~' A' s
  349. {, E# X9 \) v& y* z* f
  350.         WiFi_SendCMD52(func, addr, NULL, NULL);, K/ C/ i0 [  K
  351.         if (SDIO->STA & SDIO_STA_CMDREND)/ g+ w- L7 p2 J4 B( H
  352.         {' Y5 o$ ?7 X0 a: h$ `. q
  353.                 SDIO->ICR = SDIO_ICR_CMDRENDC;
    4 Y+ [& e! J$ r: }# B: ^
  354.                 return SDIO->RESP1 & 0xff;; ~- Q5 E6 X7 `" v. c
  355.         }
      t% L" x( N! o! L2 z8 X2 r$ ?
  356.         else- f3 Y4 n" _0 ?* q- [7 Y, f! r
  357.         {2 ~' F( ~8 |4 X) ]' F
  358.                 printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);0 ]" I9 U5 R+ M9 W1 v$ f* ]
  359.                 return 0;" s: U1 c3 o# T
  360.         }
    " e/ W4 T- D, y9 y3 e9 m
  361. }7 K% N8 v/ O) X9 f. H( q3 L

  362. 9 J' H" B  u; e8 ]- n" ^
  363. /* 读数据 */
    ! c# \* ?6 i. Y: Y! m2 a. t0 \6 S
  364. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    ' `8 J# Y7 }: C! p& ^5 F9 c4 [
  365. // bufsize=0时, 只读取数据不存入缓冲区
    1 y% N  \* C5 x* i) M3 d( J7 G
  366. void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)- s' s1 l4 j7 w/ u4 B
  367. {
    + z( N( I! T  \6 q# b% a5 U* Y
  368.         uint32_t len, temp;$ Z3 B: x" ]# I4 L6 k% B8 u% Q
  369.         if (flags & CMD53_BLOCKMODE)
      W1 D: m* H% N( ]3 ^& G
  370.         {" W; B9 e' O4 J/ C
  371.                 len = count * WiFi_GetBlockSize(); // count表示数据块数
    " q* k% O* _# m. [8 G8 `, }
  372.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
    7 V7 I0 G, v: I# T
  373.         }
    9 k  _' o7 H* S) f: e1 `" t
  374.         else. X3 Q; u0 Q2 H" N1 d
  375.         {! B: [. ~1 e' c" Y3 h
  376.                 len = count; // count表示字节数
    " j% e, r, m7 Q+ o) R
  377.                 if (len % 4 != 0)" M" v% |8 ?7 L6 }$ l  c, K
  378.                 {8 Y" V# Q+ p8 B0 T% B! r
  379.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍$ j- J- o  b7 w) W" J
  380.                         count = len;0 w7 h' l4 C2 y) s- w
  381.                 }
    , Q3 h3 r0 f) y  R5 ^
  382.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式
    5 P0 m2 A+ U" x9 ^3 }
  383.         }) J5 D+ N5 u$ {9 I
  384.         SDIO->DLEN = len;
    7 y' l9 h1 ]' f& f% i
  385.         SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
    ' }) y0 [7 r; G- B! |% H
  386.         
    * y8 x( g- \! j  m9 E" R! x; R& f
  387.         WiFi_SendCMD53(func, addr, count, flags);
    - B& C9 a* f. O6 _" V4 P* z
  388.         while (len)
    , r( E* g6 p* ]. C4 s
  389.         {
    . f# M/ z$ G( [. ^+ L  `5 a/ C$ D
  390.                 if (SDIO->STA & SDIO_STA_RXDAVL)+ V  B% v; |  A! u! x! @7 `
  391.                 {8 @, F+ b) z! i/ \! Q1 ?5 A
  392.                         // 若有数据到来就读取数据
    + `0 e9 ^' b. W0 I9 h6 u4 D; c
  393.                         len -= 4;
    7 N% m$ L& f9 l8 R0 E, P9 f
  394.                         if (bufsize >= 4)
    - l0 Y. f8 b: l* P& f
  395.                         {  Z, N6 j3 ~5 U" M
  396.                                 *(uint32_t *)data = SDIO->FIFO;5 i- B( L' N  D% p+ a$ C9 v0 ~
  397.                                 data += 4;
    ( h  b* n  l1 R* g
  398.                         }
    % }" n( H; ?/ O7 O* i
  399.                         else6 f  L5 A& f, b  z0 z
  400.                         {
    9 M+ E. n! v( v6 n2 f/ L7 M
  401.                                 temp = SDIO->FIFO;$ D4 i. Z+ P: L$ c) j' u
  402.                                 if (bufsize > 0)5 V# k  k' b+ T! A$ l
  403.                                 {, {* C& F, a, i# J5 @* B% J7 C
  404.                                         // 写入缓冲区最后1~3字节2 |! \* T: ^" G
  405.                                         memcpy(data, &temp, bufsize);
    7 _2 t! s2 U+ O
  406.                                         bufsize = 0;
    / h7 p3 H. A  u2 D+ ^8 O2 u
  407.                                 }
    7 G, ^. S4 O& v& i" l
  408.                         }
    ; W; l& X- T9 i( t
  409.                 }$ q7 A+ C# g- @2 ]
  410.                
    & K' ^  v9 x$ U  \
  411.                 if (SDIO->STA & SDIO_STA_DTIMEOUT)( @- c: q, x9 I# B9 _
  412.                 {
    * ]! T3 l# X8 r+ v$ ^' ~2 n
  413.                         printf("Data Timeout!\n");' [7 T0 P$ y% u7 w- V. H4 `
  414.                         break;/ ^- v% A- H# s) A- Y
  415.                 }" n! e9 y9 {- a: @' u0 X4 X: O
  416.                 else if (SDIO->STA & SDIO_STA_DCRCFAIL)
      ]0 u+ M2 o3 B
  417.                 {5 q- Q2 \) F4 D2 a0 ]
  418.                         printf("Data CRC check failed! %d bytes are lost\n", len);
    & ^4 {$ e2 A( z; H6 ?
  419.                         break;5 j, S, I+ J  N9 u3 h/ z
  420.                 }* C- Z5 ~9 l/ C
  421.         }* Y0 r$ V# U/ u% d9 O
  422.         4 U6 B+ n7 m! N+ G# P7 u
  423.         while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));: x- E- I- z+ b
  424.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;% u* t4 O# u; M% k
  425.         
    5 L. O! _$ y* Q( O/ c9 O
  426.         SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;$ I/ ~- ?7 i1 t1 s) u* w- c
  427.         if (flags & CMD53_BLOCKMODE)8 Q* R' S- y/ k, R: F$ o: A: q
  428.                 SDIO->ICR = SDIO_ICR_DBCKENDC;6 Z$ O( t4 O9 Q/ G+ C5 s
  429.         5 o$ }! \  c% ~4 v# Q' `+ K
  430.         // 通过判断SDIO->STA是否等于0可知传输是否成功
    9 ~) ^- C" V" J4 e1 c
  431. }" Z+ O8 K5 ?$ o; h* S( g5 R0 D
  432. : R0 r- k  g) C! H
  433. uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)" @4 D- P7 }- V
  434. {" ~# z! [  R! S9 ~! H
  435.         uint16_t block_num, block_size;4 N# j0 _7 v( Y9 x2 v; {/ s, x
  436.         block_size = WiFi_GetBlockSize();
    0 e0 z- A+ F/ f/ f5 t
  437.         
    4 _* \: n$ x8 B
  438.         // 读取数据
    $ K3 ]5 y* I  k! U
  439.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    ; u5 {& V6 k3 q: |. \5 v
  440.         if (size >= 512 || size % block_size == 0)/ H& R$ Y0 M: P) B, x
  441.         {
    0 S. z( {. H# c( I
  442.                 // 采用Block模式传输, F- q/ d# U( f& t& ~
  443.                 block_num = size / block_size;1 g; J  y% A$ j: h* l$ Q) g: I
  444.                 if (size % block_size != 0)
    6 d7 m: g; P" l7 l" U) f
  445.                         block_num++;
    ) q) F3 r2 \( m
  446.                 + |3 i& W0 Q8 ?2 r. _$ a7 w0 |; s
  447.                 WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);3 Z; C' ~, M/ c  B# J' h9 l& n
  448.         }/ X) f+ f5 B6 [( Y1 z
  449.         else
    5 n- k5 [7 d* k1 _; q! a
  450.                 WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);
    ' y/ Y2 g- p0 L0 n7 K2 w% f
  451.         
    & N' _7 J0 a/ T
  452.         return SDIO->STA == 0;
    / s4 H; U$ p2 n- _$ L( w2 ^
  453. }1 G" e4 U' r6 T; `1 D. D$ y0 f# L
  454.   f& U7 c1 z" F* k4 i
  455. /* 接收数据帧 */4 [* r7 v! o- n# K5 y
  456. uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)
    1 V+ ~6 Z) A9 C6 _
  457. {2 p: {: C1 V; G3 u1 [; ^; t
  458.         uint16_t size;. E! T+ ?# ^4 g
  459.         if (wifi_pending_size)
    - q* y4 F  M' j6 d2 b* G) t
  460.         {  R' p. ]* j+ J1 X7 Q4 `1 h
  461.                 size = wifi_pending_size; // 先读取滞留的数据包) ~. S2 m0 C  W1 Y5 i/ \0 v
  462.                 wifi_pending_size = 0;
    , O! N3 S9 d9 O7 n6 Q
  463.         }* [6 v2 a) c+ j; ?( M2 |7 b  h; e
  464.         else
    $ w& I" {0 f- d& t) p
  465.                 size = WiFi_GetPacketLength();
    * P- U" H. D" m7 l9 x; [
  466.         return WiFi_ReadPort(buf, size, bufsize);  u( C2 \9 r) e5 q
  467. }3 k) C7 \2 M+ x3 g5 z4 `" _
  468. * ?0 z% Z' i3 }9 W2 b) a" y( ~9 v3 T
  469. /* 接收WiFi命令的回应 */  T, i2 f* r3 r
  470. uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)* K  h. m& @( h) G* A/ G
  471. {
    * q5 W3 n  {/ x( j8 r. y/ U
  472.         uint8_t retry_cnt = 0; // 重试次数
    6 k; ?/ m* D9 r2 B5 w4 g" N# b
  473.         uint8_t wait_status, resend;- `$ D: B# G5 R( W8 L2 j
  474.         uint16_t size;2 m4 z+ X5 W; Q$ Q: y& Q. V0 ?
  475.         WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;) ^7 s- \: T* E
  476.         WiFi_SDIOFrameHeader temp;
    ( V/ T( I" G$ \* Z
  477.         % J. w% @. Y+ w( w! |1 L- D
  478.         // 等待数据准备好# e$ t# k. o5 \4 L2 j, l
  479.         do% {% Y2 Y3 v& `, r) W9 h% g: B$ A* D6 C
  480.         {
      L5 I5 k2 a- O4 e+ ~
  481.                 wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);
    . A- s) @+ p6 j. k. q
  482.                 ' O- R1 q& H" i
  483.                 WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息( y0 O9 E+ [/ @- g8 r- |
  484.                 if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部& I9 U5 s, i% e* X
  485.                 {
    " ?" _  c4 b8 R! d7 u; \8 e+ B0 K
  486.                         // 若读到的是一个数据帧, 不是命令回应% R& n+ g9 z9 m$ A" }
  487.                         // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功+ ?  i6 ^; z+ L/ I  g" }! Z
  488.                         printf("A packet of %d byte(s) preempted the command!\n", temp.length);
    " H8 b( _& @4 n
  489.                         wifi_pending_size = temp.length;4 [' w5 |: N" f. a$ }3 A* o
  490.                         WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算) y3 o& v% y) c
  491.                         resend = 1;3 b7 R# X# S, G, d4 B& N5 B2 c
  492.                 }
    . }: V; s6 h  O
  493.                 else if (wait_status == 0); T7 x  x! H8 b0 I, x+ s  v
  494.                 {; p) J" L$ d0 `% k  F9 F
  495.                         // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)
    " Z5 E! s! M- B  E: Q8 X
  496.                         resend = 1;
    5 p4 ~. ]& C% r! p* r" h
  497.                         retry_cnt++;
    ) u4 I! `1 B' @( j3 e# h
  498.                         if (retry_cnt >= 5)
    7 Z) w4 Y, |2 ~( ^
  499.                         {6 }4 ]" s3 N. v! ^( M3 T
  500.                                 printf("No response!\n");* U* W8 T) Q! x" A6 d& d4 u
  501.                                 return 0;! o) E/ D% \9 u" t* `
  502.                         }4 C+ |$ a# b6 b6 D/ {+ G! }4 v
  503.                 }; I6 W8 g) \( Y8 k+ m5 e* ]' O
  504.                 else
    6 ?0 [, n/ p. R  c! g. h3 W
  505.                         resend = 0;  v: v4 r0 `9 [0 f, q# F
  506.                
    % w7 s4 d, X' k  U( F0 R
  507.                 if (resend)7 Q) d9 B2 f8 G$ F) e& \
  508.                 {
    # F/ ^9 p* }6 _( ~: U
  509.                         if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)
    6 e1 f3 ]* S6 ^" ?' d0 s" L; Q
  510.                         {
    5 D4 K7 \0 h( X
  511.                                 // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait
    * ]- C( v/ h3 y* K
  512.                                 printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);
    4 W: K- B; H3 m( `9 K/ F$ C
  513.                                 WiFi_ResendCommand(buf);0 j" P4 P6 O# t3 R: [9 h: C
  514.                         }5 ^  a6 x/ P' T- b- N$ `( N; K
  515.                         else
    9 d  v, _/ o: \4 D) m1 ~, q7 E! ]
  516.                                 return 0; // 若buf中的内容不是命令, 则直接退出
    . A. n& K, f3 t" U$ m
  517.                 }9 n; o# |1 Y+ k
  518.         } while (resend);! l% g3 a* ~' L0 `
  519.         & ?; _# i. x+ ~& j7 X5 M
  520.         size = WiFi_GetPacketLength();
    # g, _- F7 v' L0 s) f1 x; D& p
  521.         if (size > bufsize)
    ' p* x  [# g8 T; q7 R
  522.                 printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
      v) W3 n- u9 ~: F
  523.         return WiFi_ReadPort(buf, size, bufsize);
    1 x% l- e6 ~: K8 ]5 I" k$ ~1 t* T
  524. }
    / l% ?/ a3 r- B) A5 I' A6 ^' }
  525. 0 I7 u! E. g( e; `8 _6 u7 P
  526. /* 扫描全部热点 (仅显示) */
    # e1 |5 D" l- g9 K% u8 m
  527. void WiFi_Scan(void)
    $ ?  B8 E- o4 \8 v0 {
  528. {
    . t* J2 p$ ]1 ~1 }) t
  529.         // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组2 G6 w* N9 S% y; l  S8 ?# s
  530.         // Stack_Size=0x00000c009 G0 A/ a; ^2 I# r  Z
  531.         uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放7 d- a$ b) X9 ~' b) _9 W
  532.         uint8_t i, j, n;
    ' f! N1 S  B3 `: _2 Y2 A. B, x) n
  533.         uint8_t ssid[33], channel, wpa;
    0 W# {+ l- J/ F& h  w
  534.         uint16_t ie_size;
    7 h( I2 |: S5 w6 c, o3 A* V0 y
  535.         " |- q, y! k# z! C. z
  536.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令9 E5 L- [4 I- c' S. B- z
  537.         MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));$ T, n& `4 x1 J. f1 j. G
  538.         
    " g- z' B% |5 F
  539.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;6 y, ~* x8 _% w2 |
  540.         WiFi_BssDescSet *bss_desc_set;, a0 T; S9 e* H4 \' |. W
  541.         WiFi_VendorHeader *vendor;; ?+ j) \) V1 q  [2 ?. m
  542.         IEEEType *ie_params;4 d! ?2 Z$ t1 M* f
  543.         //MrvlIETypes_TsfTimestamp_t *tft_table;$ y2 |- B+ O8 n' U! r4 C. t% ~4 F
  544.         4 l+ P8 S! P/ V" B
  545.         // 分4次扫描14个通道
    * C" r  H" [, `# d
  546.         for (i = 0; i < 4; i++): U) {9 _- v# K% m  F
  547.         {
    ' l, c9 h9 B+ v( j
  548.                 cmd->bss_type = BSS_ANY;
    " S! {& S# W: U, R/ w( b
  549.                 memset(cmd->bss_id, 0, sizeof(cmd->bss_id));  B  N( I' U1 e# M- N! B" S
  550.                
    5 y" L5 I: q7 _  L1 d. R; [! n8 V
  551.                 // 通道的基本参数# L, ]# |/ a8 t# Y+ n4 V0 [: d
  552.                 n = (i == 3) ? 2 : 4; // 本次要扫描的通道数
    5 T) j/ E, w0 [( r! U0 g  {! U
  553.                 chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;/ S# ^! G- S: `8 r' f8 P+ C( B
  554.                 chanlist->header.length = n * sizeof(chanlist->channels);) P0 z" o( u" ?1 e
  555.                 for (j = 0; j < n; j++)5 q$ [+ o" W& B0 q6 @: A+ c
  556.                 {
    : F, d: r! n4 T6 @/ u
  557.                         chanlist->channels[j].band_config_type = 0;
    6 T1 \2 h+ p- r. v
  558.                         chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号
    * q) K0 t1 C- |5 k" O& A
  559.                         chanlist->channels[j].scan_type = 0;
    / G: g2 {3 o/ L7 ]
  560.                         chanlist->channels[j].min_scan_time = 0;7 S4 W5 O! l: D
  561.                         chanlist->channels[j].max_scan_time = 100;4 Z) S9 x' [2 y( n
  562.                 }
    , K+ o* H/ I, b) _6 _# o
  563.                
    & B; z9 B6 \. h% C
  564.                 // 发送命令并接收数据
    - y* s4 r8 u+ Y
  565.                 WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);' q2 d9 f" z. l7 y" S7 ~& @" u
  566.                 WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉
    # z! |4 V% [1 R9 G2 k3 G! ]
  567.                
      x$ \, N1 Q3 c; c
  568.                 // 显示热点信息, num_of_set为热点数5 R) F' d5 f' `7 i
  569.                 if (resp->num_of_set > 0)
    # t+ V2 e4 X$ `4 [4 U, Z) G
  570.                 {
    2 t  i5 D8 I( t* s
  571.                         bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));! U, {: z2 o) t2 E! _9 ^. o5 i
  572.                         for (j = 0; j < resp->num_of_set; j++)
    : z. {/ R3 A0 B. f4 X% ?" K
  573.                         {
    ) g. a; ^/ p" [, k' C
  574.                                 wpa = 0;
    ( P2 A. d& z; L  h( _" x
  575.                                 ie_params = &bss_desc_set->ie_parameters;( Y) r& A- P- F; h$ h
  576.                                 ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    , F, g* Y: k" Z+ N2 e8 `" T) m2 F
  577.                                 while (ie_size > 0)
    " j3 y7 C3 Z* B4 Q% D2 z
  578.                                 {
    3 N2 c7 n0 r( P: ^$ _
  579.                                         switch (ie_params->type)- @8 ~+ l* I3 C8 v/ A. t
  580.                                         {
    ' G5 O4 ]+ q& P; O& l0 U
  581.                                         case MRVLIETYPES_SSIDPARAMSET:
    ( F7 \5 h& ~- e& ^
  582.                                                 // SSID名称
    / H, l1 V' b  t7 t0 @7 l
  583.                                                 memcpy(ssid, ie_params->data, ie_params->length);
    6 g& q4 P5 l2 @3 i" p' g9 V3 @
  584.                                                 ssid[ie_params->length] = '\0';0 y; v2 |8 K6 p  `' ?6 N
  585.                                                 break;
    , s+ v" M' u! G: R
  586.                                         case MRVLIETYPES_DSPARAMSET:
    1 r, `" I8 F* d! B% ^6 Z
  587.                                                 // 通道号
    ! [* W, L9 o0 v6 a2 p. P5 y
  588.                                                 channel = ie_params->data[0];4 H9 d7 Q  S! r1 c- j; D
  589.                                                 break;
    . i! q4 x# v* f3 t3 t, h6 J
  590.                                         case MRVLIETYPES_RSNPARAMSET:/ V* o$ a' l  j* N( t
  591.                                                 wpa = 2;
    % ~7 P6 ~/ E5 ~, m6 D# a* \( V
  592.                                                 break;$ X0 T6 n0 c  ~7 P+ q* r  {6 `
  593.                                         case MRVLIETYPES_VENDORPARAMSET:
    " d/ A& o4 L2 r4 _% D9 b, A# C8 O
  594.                                                 if (wpa == 0)
    / E1 U- m, r; T$ Q5 ?7 R
  595.                                                 {
    % O( n0 |) N1 c* ~9 R
  596.                                                         vendor = (WiFi_VendorHeader *)ie_params->data;! U2 R* D% K' s" Q! u
  597.                                                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
    4 }" g) G5 N9 x4 ~/ G
  598.                                                                 wpa = 1;$ g' W& C& |( f& Y; b8 W
  599.                                                 }. |! R9 }; q+ d# ?" m4 y
  600.                                                 break;2 D0 q- ~( w! Y7 h/ m4 @7 R
  601.                                         }) j: _3 L- S& O$ |% D0 T4 F' d1 H) W  K
  602.                                         ie_size -= ie_params->length + 2;
    ; G2 C# l  X9 z' X
  603.                                         ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    ! ^9 [/ R2 F" T! ?2 h
  604.                                 }
    " L1 a, t( s- O
  605.                                 if (ie_size != 0)
    * ~9 k+ r) G1 b* d
  606.                                         printf("ie_parameters error!\n");& w7 I1 N' s0 [. e$ _) ~+ t' s
  607.                                 : d+ A' W1 n7 a
  608.                                 printf("SSID '%s', ", ssid); // 热点名称
    $ Y2 ?. t+ \! U
  609.                                 printf("MAC %02X:%02X:%02X:%02X:%02X:%02X, ", bss_desc_set->bssid[0], bss_desc_set->bssid[1], bss_desc_set->bssid[2], bss_desc_set->bssid[3], bss_desc_set->bssid[4], bss_desc_set->bssid[5]); // MAC地址2 q: U& @4 H  E" h2 g" _, r
  610.                                 printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
    + n8 G# i/ N7 s
  611.                                 //printf("  Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);
    9 x' o; |3 n# s1 A2 `# E
  612.                                 7 m/ C/ q6 t; ?1 m/ ^. }
  613.                                 printf("  Capability: 0x%04x", bss_desc_set->cap_info);# ?/ R' E( \' b( D4 t, e
  614.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)
    ; p) x. l# F8 o- _* c! _$ |1 ]* _
  615.                                 {
    + }; }. r0 w. u  X
  616.                                         if (wpa == 1)2 h* k! _' z1 j  [) X4 |) ~. T( D
  617.                                                 printf("(WPA: ON, ");
    ' s1 K, q" K4 X/ h# N& u
  618.                                         else if (wpa == 2)) J2 y) \8 r. a
  619.                                                 printf("(WPA2: ON, ");0 O- I7 Q8 c0 C+ u- o: Y/ g
  620.                                         else# R. E; Q/ U( a/ w* T3 X
  621.                                                 printf("(WEP: ON, ");  v0 K! W5 j9 p/ S$ }' l; ?2 l/ D
  622.                                 }; j2 I% l* g& @- @# k- w3 q& S
  623.                                 else/ e( x' Q* P" m6 F1 G6 M4 w
  624.                                         printf("(WEP: OFF, ");9 L' ?  L0 v7 s! q7 \( X5 m
  625.                                 
    7 Y6 D' {$ {1 d$ n& x0 o: O3 d6 ?: g
  626.                                 if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)
    0 w0 i3 `% W7 B# {% h
  627.                                         printf("mode: Ad-Hoc)\n");/ U' _" L, F3 E! E2 ~! j
  628.                                 else/ ~' D2 P6 y2 m# j. m0 Y
  629.                                         printf("mode: Infrastructure)\n");& F4 s: W" L) k- q
  630.                                 
    ( x5 g# L+ e2 G$ Q
  631.                                 // 转向下一个热点信息3 D% i$ a% J* Z* D3 Q# H5 \
  632.                                 bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);4 ?+ B, g1 x& M8 A7 J7 {! |
  633.                         }
      ~( o5 X' ^6 g
  634.                         
    7 p8 ]9 g( z% N0 s# p) F
  635.                         // resp->buf_size就是bss_desc_set的总大小
    + C. \' v1 a* t8 Q
  636.                         // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size
    2 G3 p& L- G! o* h+ r
  637.                         /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
    , a( `2 k3 `) X% S
  638.                         if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))
    ; }+ A+ [. g0 _/ m
  639.                         {: d0 X' c% q6 o+ P3 ]7 F; u, e3 b- z" T
  640.                                 printf("Timestamps: ");% f; d( N& I) l# N/ M2 d: F6 f
  641.                                 for (j = 0; j < resp->num_of_set; j++)
    & O2 f1 F( L& o& g& p
  642.                                         printf("%lld ", tft_table->tsf_table[j]);
    - a  X- i" N: B- H
  643.                                 printf("\n");* b8 z9 p( D) X( N6 j" I
  644.                         }*/* f1 H1 `1 E4 G
  645.                         
    # D% V. ~6 a! @
  646.                         // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table+ |) x" _* c; {
  647.                         //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)% D( n8 b$ S" i7 e9 T" d
  648.                         //        printf("data end!\n");
    / V& l$ g* W* w& v1 t
  649.                 }, y, S( q( C0 t. t; L+ u1 l1 N7 ]; O
  650.         }* T: \  Y6 M2 G' b$ a
  651. }# M% I3 a1 ?& d$ n

  652.   {! x, D- H, j. Q7 f( h" \! G: c4 r$ e
  653. /* 扫描指定名称的热点 */
    4 a. ~1 g+ l& A, d
  654. // buffer用来存放返回的全部结果, 因此bufsize应该足够大8 B% z; H# ?2 o( C* d" I! w
  655. // info用来存放从buffer中提取出来的一些常用信息
    2 ?& o$ b8 w! Q) B
  656. uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)
    / T2 v5 Q# o: m0 y8 V9 o1 e
  657. {0 d4 q/ O9 t. t
  658.         uint8_t i;
    9 s% T8 N% |/ _; k7 w2 ^6 g$ b
  659.         uint16_t ie_size;# h1 Q6 d8 b8 U3 ~$ N( a
  660.         WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
    + C6 ^0 h5 l/ _' x- T! q1 N3 P
  661.         WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;" B0 t/ D+ [0 f" a; J
  662.         WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);
    7 G4 Y4 W& e! V& a4 h; _
  663.         MrvlIETypes_ChanListParamSet_t *chan_list;
    8 A! w" P/ c3 k* t
  664.         IEEEType *ie_params;+ a, f" s/ o  ^: q. M5 w, p4 j! I
  665.         WiFi_VendorHeader *vendor;
    ! Z2 n- ?) v. o- q/ K) x$ r7 F
  666.         
    3 b  r$ e6 h. G; {3 d
  667.         cmd->bss_type = BSS_ANY;: J& F( Q- w3 r# I* y
  668.         memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
    . L) o; b1 P. q# i- \8 i; N. O: a- s3 O
  669.         . ?  m& _7 h$ D+ c, T4 J
  670.         // 添加ssid参数6 x) `9 b/ W" S* R
  671.         info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;5 i" {2 Z. H: ~6 k+ b
  672.         info->ssid.header.length = strlen(ssid);9 J$ b$ |" ?  z: M4 A* x% ^% J
  673.         memcpy(info->ssid.ssid, ssid, info->ssid.header.length);" g/ }6 J  |7 p% p
  674.         memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));' l& f" }- L( R
  675.         - t1 J- Z- ?& C( o/ _, k9 i0 C
  676.         chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));: T; X7 X. r6 K" i( V& Z% g
  677.         chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;" L7 y3 p! p; \. N9 k9 l( x% f0 D
  678.         chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
    6 ]1 @8 c. x* s! s% f: i
  679.         for (i = 0; i < 14; i++)
    & a" @" q6 K- Q, p6 ?4 W4 E4 k
  680.         {
    ! m9 E; S1 Z/ f: U# j# g$ E- ~
  681.                 chan_list->channels[i].band_config_type = 0;% B* R( T' e6 n% f- v6 j; c+ \
  682.                 chan_list->channels[i].chan_number = i + 1;
    + d" h) Z/ u: v+ s6 X) `
  683.                 chan_list->channels[i].scan_type = 0;: y) o, |6 v% E( a- |5 Y
  684.                 chan_list->channels[i].min_scan_time = 0;
    $ B% D+ _# o( ]; A% }) g
  685.                 chan_list->channels[i].max_scan_time = 100;
    9 I2 z7 E; e6 g5 X/ w8 A
  686.         }: r& t3 r$ a8 s( T4 c' Q
  687.         
    8 }7 v& T) {0 m! x" R. p; }& W6 b
  688.         WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));
    % j3 o# u& a. t  L4 g8 L' h8 A
  689.         wifi_timeout = 3000; // 延长超时时间
    6 I6 h0 f# Y) E) F
  690.         WiFi_ReceiveResponse(buffer, bufsize);
    , e2 ^7 `6 H: b  C5 b
  691.         wifi_timeout = WIFI_DEFAULTTIMEOUT;
    % \2 S5 ^2 R' t, W" I
  692.         * ?: k2 N. X* u3 [
  693.         if (resp->num_of_set == 0)
    + C  B; ^  f2 h3 G1 G* j' {- r# D
  694.                 return 0; // 失败
    8 N! P5 A, C& a( Z
  695.         " S6 _& k. X: V. O: |: ^
  696.         // bss_desc_set以扫描到的第一个信息项为准1 w# Y9 P8 }# [
  697.         memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));
    - Z. ]! }# ^# v9 X& O
  698.         info->cap_info = bss_desc_set->cap_info;
    3 v& c( z. a; G  N0 W
  699.         info->bcn_period = bss_desc_set->bcn_interval;
    6 @8 B1 g5 u) K. C! \6 A
  700.         7 y' P" `& g' r* ], `; u
  701.         // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)
    9 G. _' ~$ W) G
  702.         info->rates.header.type = 0;) Y3 G- F& l! T! O# ~" v& n
  703.         info->rsn.header.type = 0;
    0 i# j/ [* |3 w- p' Y$ S6 M
  704.         info->wpa.header.type = 0;3 w" z* r, ^& `: V8 y) h: d3 V( ^& m9 l
  705.         info->wwm.header.type = 0;
    % @+ r3 I  M/ W/ q
  706.         info->wps.header.type = 0;
    1 {8 G* h9 Q- K  G0 ~1 i% a; {
  707.         0 p5 z* i& n/ ]1 z+ f) h4 F
  708.         ie_params = &bss_desc_set->ie_parameters;
    ; I  G& O( {4 \+ l- K, B" G
  709.         ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
    9 q& O8 a, j+ v1 W7 P& @( [" N( w
  710.         while (ie_size > 0)1 K$ A' X# g  h8 o! M, G+ c
  711.         {6 R. ?' \8 k" S( e  d' d2 O
  712.                 switch (ie_params->type)1 ~2 V5 ]( }0 V- v" d
  713.                 {: [2 T, g' R8 Q3 w
  714.                 case MRVLIETYPES_RATESPARAMSET:
    3 v: g2 u, |: G  u; W0 r0 t0 l4 v
  715.                         // 速率
    + {7 m$ q* V& K" e# u3 V
  716.                         info->rates.header.type = MRVLIETYPES_RATESPARAMSET;  z1 h2 _9 U8 n: P  z
  717.                         info->rates.header.length = ie_params->length;* T% r" F8 k4 T9 S
  718.                         if (info->rates.header.length > sizeof(info->rates.rates))0 r- s2 f; k- y5 m5 L
  719.                                 info->rates.header.length = sizeof(info->rates.rates);* @* H' v$ T& X$ T
  720.                         memcpy(info->rates.rates, ie_params->data, ie_params->length);5 R1 V0 G8 I/ Y4 I  a4 R  W
  721.                         break;- W& `' v7 _, N0 I, j) u4 B4 [) ^1 Z
  722.                 case MRVLIETYPES_DSPARAMSET:5 C# H$ w& t: A" Z) @3 {0 z3 P
  723.                         // 通道号
    1 @# ~. \) s6 g* }. Q
  724.                         info->channel = ie_params->data[0];
    $ s3 w; x% p6 M& I  _+ T
  725.                         break;1 e! V/ Y( J- b( F, U4 ~) u
  726.                 case MRVLIETYPES_RSNPARAMSET:  A/ c  S/ u& j  C" r
  727.                         // 通常只有一个RSN信息 (与WPA2相关)
    3 f' @0 z( k0 n* d; g. d# p! E# z
  728.                         // printf("RSN len=%d\n", ie_params->length);
    . |/ b( i8 E" o9 w; `4 S* O
  729.                         info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;9 h3 K6 H' _5 t
  730.                         info->rsn.header.length = ie_params->length;. g7 W: r: K' d6 d/ f' _7 o
  731.                         if (info->rsn.header.length > sizeof(info->rsn.rsn))" `3 c/ N5 X# Z8 k5 x
  732.                                 info->rsn.header.length = sizeof(info->rsn.rsn);
    ( Z# }( q, G, v+ t4 U
  733.                         memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);
    ! G" a5 }7 H5 O1 J
  734.                         break;
    : W6 T0 h7 j  W" T
  735.                 case MRVLIETYPES_VENDORPARAMSET:
    . W, q  ?$ `  G3 M! {# Z
  736.                         // 通常会有多项VENDOR信息 (与WPA相关)5 i) d9 K# y  D7 |9 v; L* ~% g
  737.                         vendor = (WiFi_VendorHeader *)ie_params->data;
    ( X: ?) T% h! v( _% ]
  738.                         if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2), _3 o* f9 e6 |# }5 ]
  739.                         {. M" k" f' S( U$ W; ]/ v+ s5 T/ z
  740.                                 switch (vendor->oui_type)
    % p1 z& F  g. Q# \
  741.                                 {
    2 n8 X6 t4 L7 D6 Q& \
  742.                                 case 0x01:/ e* l$ w! _7 v$ n
  743.                                         // wpa_oui: I0 C7 D8 i" J! z: U5 Z( ~& _
  744.                                         info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;
    , ~, n/ U( t* P. n# F% k$ O
  745.                                         info->wpa.header.length = ie_params->length;6 Q- C+ h+ L8 |/ e3 `$ G- o
  746.                                         if (info->wpa.header.length > sizeof(info->wpa.vendor))7 K3 o; x4 ^  H# N
  747.                                                 info->wpa.header.length = sizeof(info->wpa.vendor);
    0 }4 h1 J) j# _- o7 j' _' L( x  b
  748.                                         memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);
    - s$ {' l/ C2 S9 d5 x/ n3 u
  749.                                         break;9 @/ x* e4 V& B, p8 m
  750.                                 case 0x02:
    $ I, g; _! W+ J8 s, L0 u: \( m* C
  751.                                         // wmm_oui: d9 s! D1 r3 E2 g
  752.                                         if (ie_params->length == 24) // 合法大小; V* w* k8 B% x' {
  753.                                         {$ L9 g8 w( u# L) O5 F
  754.                                                 info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;* {* J& F2 Y) s; n
  755.                                                 info->wwm.header.length = ie_params->length;% f; ]+ |4 @7 y1 W- T/ F
  756.                                                 memcpy(info->wwm.vendor, ie_params->data, ie_params->length);
    & x  _7 p1 b! m* `' j
  757.                                         }
    1 j- a$ `! ?# ^& {6 x: H. K
  758.                                         break;
    + |2 U$ i. W$ |4 c# T
  759.                                 case 0x04:& [" O+ X# p& s
  760.                                         // wps_oui* R, \( g. \# O
  761.                                         info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;
    1 k1 b+ d( d6 O5 S& B
  762.                                         info->wps.header.length = ie_params->length;
    : S4 V2 b$ j9 n  `
  763.                                         if (info->wps.header.length > sizeof(info->wps.vendor))
    4 {3 b# L- H3 n; ?5 w
  764.                                                 info->wps.header.length = sizeof(info->wps.vendor);
    3 _$ w. b, [# f9 C% s8 q. l/ I. o
  765.                                         memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);
    7 Y! j3 e+ A  m9 g" [4 m
  766.                                         break;
    , ^  I" A- l# r* G6 L1 T% v
  767.                                 }, j6 q& `# c2 z) X
  768.                         }' {* o% l- G+ c$ J3 s' T2 I  u
  769.                         break;
    / h; o' W- |- |7 e6 A( g
  770.                 }9 i6 M2 b0 @7 l8 Y9 ?( w
  771.                 ie_size -= ie_params->length + 2;7 i( U- t3 `& R" n4 d# M4 @7 F
  772.                 ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
    # E' h% j% U4 l8 R; n
  773.         }* H, d( y7 U8 w4 p- Q6 u
  774.         
    # L2 N4 Y) g1 e7 ?6 t" [7 k1 I
  775.         return 1; // 成功
    3 i, \/ p( p' l* K2 G! d; Z
  776. }( S' O; Y1 S7 n. u1 h1 T

  777. 8 z, O1 @2 y( v0 y; L; a
  778. void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)
    ! ]0 @" Z. l9 m# y/ r$ `. ?5 x
  779. {- L5 K7 l; i$ _. T2 E6 U9 Q, W
  780.         SDIO->ARG = (func << 28) | (addr << 9) | data | flags;8 `& Z: A, u) Y
  781.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;
    % A% v: s( A0 M; V, C$ _$ r3 [
  782.         while (SDIO->STA & SDIO_STA_CMDACT);
    ' [+ n- m& M6 P4 O8 R
  783. }
    7 P( O4 L# V' J' C# U( i5 E9 l

  784. 5 k: H+ J8 A: E8 Z
  785. void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags), g- v! E6 ^# F
  786. {( D5 V+ |" H1 g0 o3 u! X
  787.         // 当count=512时, 和0x1ff相与后为0, 符合要求
    + C7 y- C% M3 d# R  P4 v! Z1 j
  788.         SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;
    ; s9 m! ]4 J" }2 G$ m# z) d9 F) q
  789.         SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;1 {* p3 V' m4 [; U- c4 W* B" y0 G
  790. }
    ) D6 l/ h' l9 h' ?) F

  791. 8 m' i5 o/ H7 o! ]% |6 n: F* B/ _- p# j
  792. /* 发送WiFi命令 */  Q7 e1 b0 f) E/ y6 C1 {- g6 z  ]
  793. void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)  q' _; {( v' J' G8 W9 M& l9 m* T
  794. {
    ! q, U( J  R, Z. r7 U2 N( h0 C
  795.         static uint16_t seq_num = 0;  Z' \: _  U/ f1 X9 S  l) }* A
  796.         WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;3 ~4 j" l! D0 e% a- p3 |$ J
  797.         ; z& k' F0 }: v5 q
  798.         if (size != 0)7 W9 z5 |4 L2 ?3 ]0 F6 p, m
  799.         {
      e/ z; }$ G. Q$ h" ]
  800.                 cmdhdr->frame_header.length = size;2 ?2 e8 [' _( T  y9 F
  801.                 cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;
    3 |2 p0 @+ `3 r
  802.                 cmdhdr->cmd_code = com_code;% c9 i3 @5 h( y. t7 S$ U! ]
  803.                 cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部2 \! a6 @: g+ z2 _5 l& K* y( ^
  804.                 cmdhdr->seq_num = seq_num++;
    ) X% g, Q# \; f+ y- Z7 C  {6 p
  805.                 cmdhdr->result = 0;
    , w& S: w3 P) o3 {- C% ?8 F' r8 Q
  806.         }4 h: z( v7 N' E! }3 x4 n5 Z) y
  807.         else: t/ q* y. e7 e6 ?9 E8 w
  808.                 size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr4 V/ Q* w4 ^. ~% D' D. C
  809.         
    1 i. b0 n$ ?7 F  ^# d
  810.         // 发送命令前若恰好有数据帧到来, 则直接丢弃
    6 }, v/ _. a8 H% x
  811.         if (WiFi_PacketPending() || WiFi_PacketArrived())6 O: [' d6 ~' j. v; `; m+ d4 h$ M5 t2 e( x
  812.         {2 x0 L( r8 b1 o# L, T" J
  813.                 printf("A new packet happends to arrive when sending command! Drop it!\n");
    $ n2 _: Q/ Z+ O" |& s$ D
  814.                 WiFi_DropPacket();
    ; e9 d% G1 H$ v
  815.         }. G5 R7 C# g# L: J( T
  816.         
    " U, M# W0 P  c. x% p9 H* m+ d
  817.         WiFi_WritePort(data, size);
      e% t% D* x( }
  818. }! G7 s- k9 r- k2 K1 Y7 g' g! N3 z

  819. . G6 N$ r  [- C0 F" H0 D  y; r
  820. /* 发送数据帧 */" x0 {. j* D5 c' G" }# q
  821. uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)6 o6 n1 [% x) N6 @/ l5 e, \" v  z# b0 e- A
  822. {9 T' ?' }6 d0 a  s- l4 A/ a
  823.         uint8_t ret;
    : u7 @0 X! C+ n3 H
  824.         $ O% {/ R5 H. j9 ?) x3 N0 G
  825.         // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path' I( V9 F; X/ k: E# v
  826.         packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
    ; q0 b9 I( l0 }! D: N" o! D0 Q
  827.         packet->header.type = WIFI_SDIOFRAME_DATA;
    7 K0 @, @3 k! ~6 J5 ^) }% U
  828.         : M* r- [7 d. Y9 Q/ ~
  829.         packet->reserved1 = 0;
    3 u5 G9 v) C  S" d2 u4 I
  830.         packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings
    ) y. d4 y1 i( d4 ?( Q. r
  831.         packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader+ w! b5 p7 [6 R5 X
  832.         packet->tx_packet_length = packet_len;
    1 R/ O! y9 q0 w1 M6 v5 ^
  833.         memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);1 C/ U; ]2 L4 M! J! R: v' ?
  834.         packet->priority = 0;
    ; j5 |0 g4 o/ \* f* G3 S; o
  835.         packet->flags = 0;0 [8 r" V4 ~1 Y5 d& s7 Z
  836.         packet->pkt_delay_2ms = 0;. X' A0 v  C# k( ?
  837.         packet->reserved2 = 0;" c. L5 U( M$ ?( h" K7 M" P+ `7 Y
  838.         7 ]& ~3 X, m* b# s# e  C
  839.         // 若现在有新收到的数据帧, 则暂存数据包大小. L4 r6 D+ a9 L9 b% a" Q* J4 k6 k
  840.         // 未读取之前不会收到新的数据帧
    / P# V3 i, w* L' @0 I) e0 S& A7 N
  841.         if (WiFi_PacketArrived())% f) v* z' [8 ~9 o
  842.                 wifi_pending_size = WiFi_GetPacketLength();
    8 f! e& y$ X! }3 h* a% N
  843.         
    3 J+ U  k$ I7 e8 n5 f3 |1 p
  844.         ret = WiFi_WritePort(packet, packet->header.length);% l9 n& I. e1 C. |" W0 {
  845.         WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1) F0 y9 ?- x0 m; z& z6 L: a# \
  846.         return ret;
    ; x. X: \! K# s2 a! x' e( R
  847. }7 n' u4 i4 W) q% q9 S( l8 b

  848. # Y; `! h3 X! ?- A5 ]3 |/ C
  849. /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */
    ; d$ Z* a0 h) O# E8 S
  850. void WiFi_SetBlockSize(uint8_t func)
    0 i5 x8 y2 u; K& o% Y! C- O8 _$ h
  851. {
    * R2 ?6 V% g1 H5 {- D
  852.         // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)' ?5 R. s7 `9 |6 Y3 g& d" B* A, H
  853.         uint16_t size = WiFi_GetBlockSize();
    6 [' K7 V# f' V) F
  854.         WiFi_Write(0, (func << 8) | 0x10, size & 0xff);
    & a; ]) K% |' A. W9 r' y
  855.         WiFi_Write(0, (func << 8) | 0x11, size >> 8);
    % C6 l4 Z. b1 s: ]8 ]  j
  856. }, z/ L" ?4 z. g  k! t. x+ q

  857. + {* |% {) s$ E& ]
  858. /* 设置密钥 */5 v1 O+ i% M2 U( J, x8 s' J
  859. uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
    ) D$ h. g: s3 `* ]) p
  860. {
    % q! g0 S$ d. A0 ?8 _
  861.         MrvlIETypes_KeyParamSet_t key_param;
    - U8 N( t& l; {8 }
  862.         if (len > sizeof(key_param.key))
    8 }& z4 j9 c. J, ~9 k- ^5 z* q5 i
  863.                 return CMD_STATUS_ERROR;2 m, s- X8 F" s2 S2 y- I
  864.         key_param.header.type = MRVLIETYPES_KEYPARAMSET;, b  v1 m/ G4 B+ N7 x; i3 Q3 K
  865.         key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
    6 A7 L" S+ C8 `' L% @" q
  866.         key_param.key_type_id = type;
    * e7 v2 b! n3 L/ {. W5 T0 ~
  867.         key_param.key_info = info;" K. Y. ~, C" O
  868.         key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info# e. g$ j; {- F7 K1 G
  869.         if (len); @$ }! x+ y* ^0 i7 W- ^% s' ]8 W
  870.                 memcpy(key_param.key, key, len);5 q; t  z5 z8 b" V* O; _: K4 R
  871.         return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
    + b" h; X: d. r! B
  872. }
    # o2 r% a3 J6 W2 Q& k; m9 ~- p, v

  873. 7 s- A/ Z0 _/ U/ m, u! u. I. v) |: r
  874. /* 显示WiFi模块信息 */
    , r# U+ C( n" e. o, l5 \6 o
  875. void WiFi_ShowCIS(uint8_t func); z. I  m7 i  E0 N. O; H; E2 Z
  876. {
    7 U! a5 u; m) J+ g3 E2 H. P6 u7 O
  877.         uint8_t data[255];* s+ }# Z0 S7 Z* |/ R& s2 e
  878.         uint8_t i, len;' U7 [  s+ U2 v+ v3 O( d" S
  879.         uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure9 w3 {" ~/ ~; _" \$ E7 V1 p
  880.         uint32_t cis_ptr;
    5 Z2 W. I5 ~! U$ T8 U* U
  881.         8 N1 V7 g; ^9 K6 B; g
  882.         // 获取CIS的地址' \" ]9 u, K2 ]$ R1 x& G
  883.         cis_ptr = (func << 8) | 0x9;7 s% P$ J  o3 ~8 P9 m
  884.         cis_ptr        = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
    # ]1 Y+ S( W1 y% w2 E& E* l
  885.         printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);
    1 y, x2 }- B1 I: l2 S& ^
  886.         
    ) L: k! z) W$ `' m
  887.         // 遍历CIS, 直到尾节点9 F' u4 J# m! @* i& N
  888.         while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)7 e9 W; U9 @- L" Q* R: d  U" ?
  889.         {
      a7 y& M* R8 H5 d4 G
  890.                 if (tpl_code == CISTPL_NULL)! N  J& k. P2 f
  891.                         continue;2 ?4 O6 H6 \; n, S1 J3 u4 P) z! d0 u
  892.                 6 U- x! @# [" K2 w  f
  893.                 tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小# K1 `5 h3 x0 ?* o- b" z
  894.                 for (i = 0; i < tpl_link; i++); `9 u$ c! m( i3 x+ O% m# T
  895.                         data[i] = WiFi_Read(0, cis_ptr + i);
    7 w& K& k7 @9 D8 a/ G7 L
  896.                
    # K- h7 W( E/ y& p" `
  897.                 printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);+ |! O! P& A: w+ j% Z
  898.                 dump_data(data, tpl_link);
    * a9 Y6 {4 W  N7 U4 k; e3 P
  899.                 switch (tpl_code)
    0 @5 q; I+ n3 A: d) c8 Q  w
  900.                 {
    ' s' i2 H- }" C8 v
  901.                 case CISTPL_VERS_1:
    1 I+ h& ~3 s: D! ?( j4 r+ f- h7 e- v
  902.                         i = 2;( B5 j6 [8 N& |4 l3 J
  903.                         while (data[i] != 0xff); c. \* X$ j  L& Y" x
  904.                         {
    : m( x- G, b8 ~8 ^# b& g
  905.                                 len = strlen((char *)&data[i]);
    - z0 d* V+ f+ C+ I* y$ c
  906.                                 if (len != 0)4 m' Y5 B; Q* m3 o6 R
  907.                                         printf("%s\n", data + i);
    ! [* `# M- C) Q' S' }" i' `  E7 g
  908.                                 i += len + 1;8 L. q' t0 H+ ]% F# S
  909.                         }7 j! z; o5 a% n# q, \& Y1 E1 w
  910.                         break;
    ! Z4 W6 z  l; j
  911.                 case CISTPL_MANFID:
    % E/ g4 H' p6 T" F& f
  912.                         // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple! F& ?5 o( V. e/ M5 e
  913.                         printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF4 Z) J: C$ E$ o1 P. O2 n
  914.                         printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD$ Q* o( ^+ r8 Y/ z1 X- A. K
  915.                         break;
    + C# e5 I( z3 l! @: {
  916.                 case CISTPL_FUNCID:7 O/ P1 U. o1 {1 @9 e
  917.                         // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
    2 @( V! o/ f9 d5 R; f
  918.                         printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION0 S) C$ x7 h5 [1 F; C$ {  L
  919.                         printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT
    1 M7 p1 D) a: M' [1 A) Y- _$ @( E
  920.                         break;) _1 c/ @3 P# J3 e& N" S8 \
  921.                 case CISTPL_FUNCE:- f3 |) Z9 V* e( N0 [0 R- n
  922.                         // 16.7.2 CISTPL_FUNCE: Function Extension Tuple
    4 g; N) r" @2 [* U3 z: U3 r( k
  923.                         if (data[0] == 0)  D  l( N0 x" \! D6 R) |8 Z( o
  924.                         {
    5 Z: m7 Y( Q3 V/ Q# `- v/ e
  925.                                 // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)
    ! v$ `9 n& e' ^" e2 T
  926.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 1));/ K9 w  o6 T  q1 u( d7 v
  927.                                 printf("maximum transfer rate code: 0x%02x\n", data[3]);" Y) ]- L, }* h5 C: @
  928.                         }
    & E0 q" F* [: i
  929.                         else
    3 Z4 U! B% j3 E6 M
  930.                         {+ o* h2 @: G0 B, p! j
  931.                                 // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
    * i$ m4 e( M) B5 T% |
  932.                                 printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
    4 n- m# i. |& W# d
  933.                         }+ |% k* M% U8 s' ?$ U
  934.                 }/ D  }, Q% [. T0 O
  935.                
    9 e2 c& a0 N* w0 ~
  936.                 cis_ptr += tpl_link;1 `- o9 n) I) W% Y; j6 P3 ^
  937.                 if (tpl_link == 0xff)7 M& `7 z; j! Y) O  |
  938.                         break; // 当TPL_LINK为0xff时说明当前结点为尾节点
    8 B5 [, d( ]3 T' e: ?+ @! J, D; H
  939.         }
    : P' L) V2 Q5 G6 [3 a* _* I- U4 v
  940. }8 t) b! q, p+ C( o4 P

  941. 2 w" I0 Y- g( x& Q4 l8 w- q
  942. /* 显示所有密钥 */$ l) M0 ?: u; A4 `- Q+ n
  943. void WiFi_ShowKeyMaterials(void)+ e" S- _3 ]8 F: w& s4 A
  944. {
    ! Q2 Q. @  D8 n5 v( F
  945.         uint8_t buffer[256];
    4 Z2 U. \3 p0 H7 M9 P
  946.         uint16_t size;
      }( \) H( \$ I# G3 j9 B- e
  947.         MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;
    0 O6 v6 Z( z2 Z6 ^
  948.         
    ( Z# q, i7 h; y9 x* |, T8 l+ D
  949.         size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);
    . Y" Z! s6 m8 P8 Y% f5 ~
  950.         while (size)
    ; L2 ?9 p8 Z; x" b
  951.         {) Y  a, |; S% P' `  c$ z
  952.                 printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
    7 G  m, s( L: s0 v) o
  953.                 dump_data(key->key, key->key_len);! g# r9 `' B9 V! b' }
  954.                 size -= MRVLIE_STRUCTLEN(*key);
    0 t+ r6 m( c: c) K0 B2 c
  955.                 key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));
    9 \) ?  \/ S! X9 U* g. i' N
  956.         }7 ?* L, @. m' l/ n7 h( g
  957.         if (size == 0)
    5 H  }, ]5 I* w) [: r$ A! t
  958.                 printf("data end!\n");* D1 j( H  J6 e
  959. }
    ! ]2 ]# {7 I3 I4 g0 a

  960. & q6 a% m( p! P: L/ Z2 @
  961. /* 创建一个Ad-Hoc型的WiFi热点 */& n4 l+ l. }; u; S+ g
  962. uint8_t WiFi_StartADHOC(const char *ssid)- W) {: z: T4 ^) m
  963. {5 E7 @1 G" D: r, {& N4 j
  964.         WiFi_CmdRequest_ADHOCStart cmd;6 z8 B7 e8 n, o. w% l' ?" a
  965.         memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零$ z# p* v3 N. v! i  ]- Y. L6 Q( l6 n
  966.         
    0 }$ |* c! N6 l- ~6 x
  967.         strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));; O8 r: j  }; f1 T2 x& Z
  968.         cmd.bss_type = BSS_INDEPENDENT;8 R! j( K9 J' W0 \' @5 P' Y3 c7 ^2 h
  969.         cmd.bcn_period = 100;5 u) `" H$ V4 X
  970.         cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;1 k3 j) |" J% Y' J
  971.         cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);8 r  a/ E/ W8 w
  972.         cmd.ibss_param_set.atim_window = 0;& t- {" H6 x: A9 @
  973.         cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;- p: s! d, X, D
  974.         cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);
    3 m* h; _+ g7 c+ E1 s
  975.         cmd.ds_param_set.channel = 1;. k( \# y' n  Z
  976.         cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;
    8 u/ B* W/ [8 `3 V( L+ Q. H% |
  977.         *(uint32_t *)cmd.data_rate = 0x968b8482;
    " c9 ~' ]9 r( b$ U
  978.         7 f# l  |2 x( i0 Q6 d1 ?1 V: g; l
  979.         WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));; i3 y2 V: A0 W8 g: K( y, M6 G
  980.         WiFi_ReceiveResponse(&cmd, sizeof(cmd));9 L; V3 a: W3 a" x  C4 e9 t
  981.         return cmd.header.result;
    4 }0 m$ ?6 J" i
  982. }
    % d. l9 ^$ n: _: Y. }) k
  983. ( ^/ B' b/ I) V% \# F2 h% i0 J  {# A6 |
  984. /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */( J2 @) e3 O) r
  985. uint8_t WiFi_Wait(uint8_t status)( W( o( h9 V2 A! P
  986. {
    , ^4 M' s2 \5 W5 k! f* t$ i- O
  987.         status |= WIFI_CARDSTATUS_IOREADY;
    * K/ A# q, ~, o# h4 W
  988.         WiFi_PrepareTimer(wifi_timeout);& |& m' N5 J8 Z# Z
  989.         while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status): r$ t* x& c: ^; N8 L3 I+ J
  990.         {% T5 X$ W- E9 ^2 m" P5 ^% n
  991.                 if (TIM6->SR & TIM_SR_UIF); ?6 M1 s- A$ Y9 I1 v
  992.                 {- ^# l; l6 _  J) p: S5 O' u
  993.                         // 若超时时间已到( l9 A+ O  m2 K( o" n6 i2 v
  994.                         TIM6->SR &= ~TIM_SR_UIF;
    8 A2 U+ b' Z! a' a9 S$ ^# K
  995.                         printf("WiFi_Wait(0x%02x): timeout!\n", status);- Q. R, H' v2 y4 ^3 {/ A
  996.                         return 0;
    ) j! M9 _: a5 b
  997.                 }3 f% |2 K( U" ]  x
  998.         }( |; m  u7 p" R2 g0 C
  999.         TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器# b; e9 [* _7 _* }/ I
  1000.         return 1;( z6 z7 N: c) K8 X
  1001. }2 D& N# E& N/ F1 Z6 y
  1002. ' D) A4 b2 S5 a9 z
  1003. /* 写寄存器, 返回写入后寄存器的实际内容 */  D1 Y. Q; ?9 {6 b3 s& `$ `
  1004. uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)3 t$ C. m+ D- X" W1 N6 x, b
  1005. {8 q5 u& N6 ], k% X
  1006.         WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);" c1 i: a. r0 {$ l; D" T* ^
  1007.         if (SDIO->STA & SDIO_STA_CMDREND)
    * T* G3 C4 H! c7 a
  1008.         {
    3 @( u: J6 m% X- g/ [  C  D+ T
  1009.                 SDIO->ICR = SDIO_ICR_CMDRENDC;3 n: L7 N" ?; e8 |1 }2 z0 H7 z
  1010.                 return SDIO->RESP1 & 0xff;- v& S, W% z% R* {2 E' e
  1011.         }
    + z. {- ]) O( J  @( E
  1012.         else
    9 t& w) }+ n% D
  1013.         {( ?2 M* j, ]( j% M- p# }
  1014.                 printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);
    4 u& o2 t! x5 ~: V
  1015.                 return 0;
    0 F% f0 e+ J) l- h( G1 m% _
  1016.         }
    0 V3 h8 Q: }9 i( k- Q: @2 [
  1017. }
    0 T/ Y1 H7 n/ d; q- z2 I" U

  1018. 8 n# M& R& `* b9 C& t0 f, G
  1019. /* 写数据 */$ a! ]5 ?, A8 c; M2 R
  1020. // count为要发送的字节数或块数, bufsize为data缓冲区的大小
    9 |- s8 d& ^1 U& n
  1021. void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
    3 }+ b2 c6 ?9 E
  1022. {
    & _4 ?; Q, ^& u9 W
  1023.         uint32_t len, temp;& \9 p% G: C! d- s
  1024.         if (flags & CMD53_BLOCKMODE)
      I% I2 z5 s) U7 v8 ~* ?8 _: |( V
  1025.         {
    0 I! b4 R4 [8 t% @( N
  1026.                 len = count * WiFi_GetBlockSize();
    ! y1 b$ P3 u0 I: B% E2 ?" d
  1027.                 SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;* p  W; v" K% @
  1028.         }7 [+ ?) d1 L! ^( ~3 s
  1029.         else! M: A$ p$ J" \; @
  1030.         {1 G0 f$ a7 _% t
  1031.                 len = count;3 x# g: Z; ^3 S' @- [2 S/ [, K  t
  1032.                 if (len % 4 != 0)8 |* L1 A& w  H, M' y+ d0 x
  1033.                 {
    5 d3 o8 ^4 G8 u% r9 n" M8 J
  1034.                         len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
    , b- V4 }% w! Y5 l+ }
  1035.                         count = len;
    % F7 c. u: }. v; f' b9 [& ]: _
  1036.                 }
    * r' v5 S( m, i9 ^. w
  1037.                 SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
      o3 y8 H& G5 ^2 m4 D
  1038.         }% ^* Y4 |; x- T) ^4 ]) {9 K4 ^5 L
  1039.         SDIO->DLEN = len;
    ' L0 O; u. r" k- `) k" g: p4 G
  1040.         SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块
    % y: \/ C  H7 r5 W  k: ]5 m* i
  1041.         4 N0 l" p0 k7 A
  1042.         WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);- M. }( k, w' x9 U: C; @7 P
  1043.         while (SDIO->STA & SDIO_STA_CMDACT);' U- V) s/ ?2 {! @* Y$ e- T
  1044.         if ((SDIO->STA & SDIO_STA_CMDREND) == 0); f' T" j# q( j( y( S
  1045.         {  h7 X- U6 G. T. q. n3 k  E! A: l
  1046.                 printf("WiFi_WriteData: CMD53 no response!\n");$ m* L& Q/ _% K" R, U
  1047.                 return;! M8 ]& Z" h* ]9 Q5 J% }, c* o
  1048.         }( H" P" e7 T' _* F9 [
  1049.         SDIO->ICR = SDIO_ICR_CMDRENDC;5 |+ j, _8 v1 c$ Y; g
  1050.         
    7 N& t) O- h( }  |% K* v* l
  1051.         SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据
    - T1 A) q- O9 I' l& `6 h" z
  1052.         while (len)' H+ Z/ M! Z( ~; G& ], y
  1053.         {
    ; P+ Z2 K/ N! c' D: S. S4 Z# A
  1054.                 len -= 4;
    ) y; S  ]* D& m. i9 C( l4 n7 J
  1055.                 if (bufsize >= 4). N, L1 z" j8 ]3 i
  1056.                 {$ z$ T* @8 S( r5 w
  1057.                         SDIO->FIFO = *(uint32_t *)data;9 p3 H5 a3 n$ w; ^0 f# f
  1058.                         data += 4;
    6 v& m" T& C0 S' S/ Y) E8 l  p1 H
  1059.                         bufsize -= 4;
    0 t4 G" R$ ~% D3 L# G0 {6 v1 Y
  1060.                 }, K# ^7 _8 A# P5 T: j- c
  1061.                 else if (bufsize > 0)( y6 N3 S9 d( }# ?
  1062.                 {8 i+ H* r" Y$ }1 q+ `
  1063.                         // 发送缓冲区最后1~3字节
    - D9 _9 d& x* q7 m1 y/ }( F
  1064.                         temp = 0; // 不足的位用0填充# x+ ^! k( g2 K5 i. x
  1065.                         memcpy(&temp, data, bufsize);
    0 [! ?2 V3 a9 ]" e5 F' _/ b
  1066.                         SDIO->FIFO = temp;
    ; r! z0 j5 ]" ~% m+ }. C& S
  1067.                         bufsize = 0;( O# S6 r8 n1 w# P
  1068.                 }
    $ ]* [& m  S& f9 V
  1069.                 else: {2 j( R* k3 m- A+ _- }4 G
  1070.                         SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0
    4 x' D8 D: J; v- B5 a' N
  1071.                 while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待
    ( l0 x$ v2 ^' k3 k, a
  1072.         }
    * ?. E& l! Y. p9 b' c% w
  1073.         : u& h4 o0 O( v# z+ ]4 V: m0 i5 i+ ~
  1074.         while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕. X  n" P% P; Z4 Z
  1075.         SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
    5 Y0 Q* x+ @' `( d/ P
  1076.         
    ( G7 V9 W4 w% p" m+ Y
  1077.         // 清除相关标志位- e5 t1 Z0 |, }
  1078.         SDIO->ICR = SDIO_ICR_DATAENDC;
    6 @' @9 ^" g1 J7 C
  1079.         if (flags & CMD53_BLOCKMODE)/ L% x0 R3 V4 @5 c! i- ?0 V: W
  1080.                 SDIO->ICR = SDIO_ICR_DBCKENDC;" B/ X1 O5 V7 h4 `
  1081. }
    , g- t( Z/ q4 \2 F6 Q

  1082. ( ^/ j% x+ i0 D* N! ?
  1083. uint8_t WiFi_WritePort(const void *data, uint16_t size)
    # @$ I7 _" w% }& v: K
  1084. {
    ( m5 Q/ O- y0 T* ~
  1085.         uint16_t block_num, block_size;
    2 h+ e. f2 `+ R) o5 s
  1086.         block_size = WiFi_GetBlockSize();
    / k: d: _0 R8 s( F
  1087.         
    , v0 X. x+ z' U; k3 U0 s4 C3 Y
  1088.         WiFi_Wait(0); // 发送CMD53前必须IOReady=1
    4 R( V4 O. A. ~9 N& ]9 V- c
  1089.         if (size >= 512 || size % block_size == 0); j$ v3 W/ e" q/ Y
  1090.         {+ t/ u( ]' Y$ ~! I; F/ p4 B
  1091.                 // 采用Block模式传输
    2 D. R/ \9 T. p" n6 q
  1092.                 block_num = size / block_size;0 d7 ^! R$ S! r' A3 `0 p
  1093.                 if (size % block_size != 0)
    9 @* g: q4 V8 D3 k
  1094.                         block_num++;
    " Y* P. m) M. r( c* N1 o8 t; M' b
  1095.                
    / I1 l  d1 W$ N) _
  1096.                 WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);
    ' q- }) E3 N0 C+ V6 R
  1097.         }
    2 N# I; v+ J8 E  B" S
  1098.         else, T- K3 S8 g0 S/ x2 H5 D% m
  1099.                 WiFi_WriteData(1, io_addr, data, size, size, 0);' F- M0 `) b% w3 `- N( b( a
  1100.         return SDIO->STA == 0;
    4 W0 h0 C5 t& `+ [- X' V( k) g
  1101. }; B, V6 M( [6 ]7 S0 _/ s
复制代码
7 K4 [7 w7 {  E! z; g. |- O

* I1 B! m( T# n2 r5 B在工程的所在文件夹创建一个lwip文件夹。
6 ~( N) J; q8 P然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
: K9 D! F) d7 a* P! R
/ {5 L$ w9 l6 s: _  o5 g5 t/ T3 d0 hcore/
$ `; Y" l6 s% G$ g( xcore/ipv4/ o0 O7 I! r( P1 C9 k; ~, |
include/lwip. g; z  f& W1 M" ]2 F8 c
include/netif
- I% q2 e* Y% @+ vnetif/ethernet.c, o/ Y8 q1 K8 K3 \+ B
netif/ethernetif.c7 O8 T0 p/ b, Q0 c& O( w" U( p

7 W! ^& E$ s/ h& W. b, Z6 p解压后,将里面的c文件都添加到工程的lwip分组下。
1 ^" ]4 D* v% d具体添加的文件请看下图:: R/ b5 L6 o+ n2 w  n
& {# B" B$ k4 `& }* T

. F: o! w) c% M; Z9 x接下来,创建lwip/include/arch/cc.h文件,内容如下:
* |& _8 q# K+ P: Z: n
  1.     #define PACK_STRUCT_BEGIN __packed // struct前的__packed  
复制代码
创建lwip/include/lwipopts.h文件,内容如下:1 z. O- D: u0 D4 K! z$ K
  1.     #define NO_SYS 1 // 无操作系统  ! y. N  T; H7 m% l# {0 J
  2.       
    3 X" {% P* y- m1 [. N4 ~) ?
  3.     #define LWIP_NETCONN 0  
    8 N+ u; ^2 @) S8 n- |& F  w4 k8 F9 |
  4.     #define LWIP_SOCKET 0  
    9 W8 B# _+ y5 p4 |
  5.     #define LWIP_STATS 0  6 v/ D/ ?3 F& T
  6.       
    2 [# S4 A3 s9 C% k# e
  7.     #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的  , l9 D2 {9 W. l, y6 q
  8.       
    & A* Q: H) s( i+ L6 }% r
  9.     #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)  
复制代码
打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:
& k1 y- K, e. T
  1. /**- m. M0 Z- H' l* f! {' R: L6 Z7 N! \
  2. * @file4 A  O3 G  V5 _7 a; N. P: T
  3. * Ethernet Interface Skeleton, o/ m" `+ Y  y7 Y; c9 @
  4. *
    $ {" G+ w# y, E" c
  5. */# |% W, R& Q9 @* f
  6. ( I  g% h+ `6 S
  7. /*$ h% e$ w. G2 k% r
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
    ; E4 Y* V; u7 E
  9. * All rights reserved.
    ; Z! u7 i* U$ Z/ q: K
  10. *
    ! V1 ~+ N8 x0 o) n  d# D! ^
  11. * Redistribution and use in source and binary forms, with or without modification,
    ( X  B# V1 g0 x5 R; J7 a
  12. * are permitted provided that the following conditions are met:, i3 _% b5 p/ f, F$ t5 P8 }
  13. *
    ; L9 f: F; o7 L( O
  14. * 1. Redistributions of source code must retain the above copyright notice,
    9 g4 E0 C, `: H! r
  15. *    this list of conditions and the following disclaimer.
    : ]0 j! m! L+ n. d4 A) W4 r& ^
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,$ |; j6 Y6 \7 P
  17. *    this list of conditions and the following disclaimer in the documentation" p* N: V; H6 F9 j- r) g
  18. *    and/or other materials provided with the distribution.
    - l7 k* r, j3 A( ^. m
  19. * 3. The name of the author may not be used to endorse or promote products
    ( O' r- `  J6 R- u' n4 E% e
  20. *    derived from this software without specific prior written permission.
    5 x) @1 X6 E3 l4 [5 \
  21. *
    ! r% `. O) S( c; w8 e, d. w. ]0 K
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  ], ]! r, o/ B9 ^
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF7 n1 ~& |/ Q% k4 F# k' |% Q3 i
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    1 A6 x$ z9 z* R
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ w$ y  a) G, q' e5 ~
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  I: C2 Y( D, Y7 {% Z* ?2 s0 f% d
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    + B$ h' M; F+ E$ E4 E. P9 S" _
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    0 N! j8 ]/ p  H) p  i8 c3 @
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    , n0 l$ ^, b' f8 y9 e3 r( m
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
    $ A) ^: S; ^0 x- l/ g
  31. * OF SUCH DAMAGE.( G( h* c8 t! r% `0 F% w; m
  32. *1 @2 W! N% q" ^% w* Z
  33. * This file is part of the lwIP TCP/IP stack./ z6 s; b7 l0 B
  34. *
    1 H- Z# P! C6 x  s
  35. * Author: Adam Dunkels <adam@sics.se>: t  s' o& S% ?' w$ X3 ~6 a* x
  36. *! {" }; |* P8 g1 P  ^
  37. */9 J, F2 [1 R) p1 F: H8 J5 ~

  38. . Q: P1 }: \% t" r
  39. /*
    4 u3 i5 P6 B3 d- A
  40. * This file is a skeleton for developing Ethernet network interface% Z' x% s# l5 ~7 f
  41. * drivers for lwIP. Add code to the low_level functions and do a* C3 c4 b& `+ n! y. G0 ?
  42. * search-and-replace for the word "ethernetif" to replace it with
    " ^+ ^+ [) Z7 h7 @
  43. * something that better describes your network interface." q. K# b$ T7 |6 `! P1 @( u: Z
  44. */& G" u$ }; t  Z0 L
  45. + n% f/ M5 m% w$ i8 }+ Q4 T
  46. #include "lwip/opt.h"7 H' n0 w9 O  ^! W' f

  47. " J( X  L2 y, R9 C9 G" {0 Y
  48. #if 1 // 允许编译器编译该文件
    ! G- O, n0 O# r$ ^; I! w! D6 _

  49. ! R4 t( V4 B+ @
  50. #include "lwip/def.h"* m: B+ E8 L- g- g+ e' e# _$ x" V' E
  51. #include "lwip/mem.h"1 r. x/ F  K( o0 n- l4 M1 E
  52. #include "lwip/pbuf.h"
    # T5 E% p9 y  _  [- O, v% D2 \  H
  53. #include "lwip/stats.h"$ m0 ~; k# z$ q, E
  54. #include "lwip/snmp.h"
    * y* X+ ?5 f0 m( v" p4 j
  55. #include "lwip/ethip6.h". y+ d4 Y6 I% a  F: C5 Z) y$ F- J3 E
  56. #include "lwip/etharp.h"
    6 z7 e, _' a2 s" C% }% p5 `$ B
  57. #include "netif/ppp/pppoe.h". `1 ?* \9 _% T: N: Y7 n
  58. , `* X- E, V4 E1 Z: ]" l! f  g5 @
  59. /* Define those to better describe your network interface. */* E3 {& ?, W* Q! r
  60. #define IFNAME0 'e'5 w, c) _- o8 a9 l
  61. #define IFNAME1 'n'
    " B4 k9 S% F3 a1 Y' Y7 P. d
  62. $ o0 e" R  E! N
  63. #include <string.h> // memcpy函数所在的头文件  U% K9 q8 G" x  C/ d
  64. #include "WiFi.h" // WiFi模块驱动程序头文件
    % A8 i$ s  y" k# F9 X( a$ Y8 q

  65. " }/ [0 V8 x% U  s( D( {6 Y: W
  66. void dump_data(uint8_t *data, uint16_t len);$ l/ h$ {7 s! e% D' I3 Z
  67. % \# R+ n$ w& p
  68. /**
    ) l. S( P" E8 a; C  w' g6 ^
  69. * Helper struct to hold private data used to operate your ethernet interface.
    5 x, A4 q$ u7 D( K7 E
  70. * Keeping the ethernet address of the MAC in this struct is not necessary3 b% U' k/ V* Z7 i
  71. * as it is already kept in the struct netif.
    5 I+ |. m0 E2 n* a+ d6 m
  72. * But this is only an example, anyway...
    * O* ^" _! n' Y) t
  73. */2 E: P* Q2 |7 F; q, W. s: @6 u8 O2 m
  74. struct ethernetif {
      k' n) V% j# G& y
  75.   struct eth_addr *ethaddr;
    / X1 W% n  n" `3 _: Y
  76.   /* Add whatever per-interface state that is needed here. */
    + Y& b: l0 v# M1 m
  77. };
    ) x& R# n& e( O

  78. & l, U* u2 W# i3 H0 g% K
  79. /* Forward declarations. */
    + J7 ]: s9 r& ~) S8 O! H' J, y
  80. // 这里必须去掉static$ A+ r3 u/ s0 c) w9 o8 u) p# D
  81. /*static */void  ethernetif_input(struct netif *netif);
    ) D0 S+ c* `4 _8 Z9 t' q( }5 A. ?

  82. * O9 s2 r" B: y2 R* M* n/ [; ^, F
  83. /**
    ) ?2 T7 w! I0 G) ?' O0 {: \
  84. * In this function, the hardware should be initialized.. r/ R5 i) P- m& |8 `3 q
  85. * Called from ethernetif_init().1 e* N: }8 r' F, [
  86. *+ x9 h0 t% t( g, ^& @
  87. * @param netif the already initialized lwip network interface structure
    : V( x: A' \) B5 d5 g( ]# P/ B3 \
  88. *        for this ethernetif
    4 P9 k3 C" d& H3 P
  89. */
    $ J$ B- y5 L! c7 J8 a7 ~* u5 E
  90. static void7 o( y5 f0 s9 M9 ]
  91. low_level_init(struct netif *netif)
    2 l: h* [5 S' C, C/ W
  92. {( y% E* q( a. s
  93.   struct ethernetif *ethernetif = netif->state;( _, H8 e" b. S3 d/ D, n  ?
  94. 8 \- `1 M5 J+ y3 n# H
  95.   /* set MAC hardware address length */  j0 P5 C, L" G* k/ U& T, }
  96.   netif->hwaddr_len = ETHARP_HWADDR_LEN;% p3 Q# {, Y1 G# D

  97. - Y  R5 q; B% X; u
  98.   /* set MAC hardware address */
    . R- Y& a# m4 C9 }2 A# V) i+ z8 c
  99.   WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
    5 x4 [5 J, s( M2 ~3 N, s5 Y
  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]);
    ) Q  k9 Y0 k" v. X( f) ]/ q

  101. ) V1 \( ]- i% @! ~
  102.   /* maximum transfer unit */; z) m! Q0 k4 `1 ?* W+ d! K
  103.   netif->mtu = 1500;
    0 x% v+ {' n( \7 U# c/ F
  104. 6 T- X$ Q4 _) u. H' f
  105.   /* device capabilities */
    ' L$ h# ~1 C: T' W; Y! A& @
  106.   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */9 l9 v0 p# {. a6 T3 b( b1 o5 }: Z
  107.   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;' R# R( x8 ~- l+ A, Q' y9 C% B

  108.   H6 Y% c" O* k1 e, j- [5 Z9 h1 t
  109. #if LWIP_IPV6 && LWIP_IPV6_MLD
    # T( M5 d  C: S  _
  110.   /*+ g7 Q; z! U/ T5 F" M
  111.    * For hardware/netifs that implement MAC filtering.
      T4 y2 q! R) Y2 U/ ^
  112.    * All-nodes link-local is handled by default, so we must let the hardware know
    ! l' }7 H+ E( v1 @
  113.    * to allow multicast packets in.
    0 \+ B. s/ Y. Y
  114.    * Should set mld_mac_filter previously. */
    6 n. I; B' f' [( \9 p
  115.   if (netif->mld_mac_filter != NULL) {; g+ M( W7 W0 B; S4 [
  116.     ip6_addr_t ip6_allnodes_ll;- @( r$ O' L, [7 O2 }* I& f  Z& T
  117.     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);0 X$ P8 S7 Q3 u- {6 v
  118.     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
    ( e2 K  B& T; R) f0 S! A) |5 R
  119.   }
    ! h( r0 r7 V8 ]0 M
  120. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
    - |6 ]; i5 E! R9 A  V- ?/ o$ t

  121. ; v# V9 ?, q# S2 m4 N7 I& a. U8 Y
  122.   /* Do whatever else is needed to initialize interface. */
    5 Q; e) J, s+ X" s, P
  123. }+ p6 U3 e4 \( q1 h$ \% h

  124. 1 N2 B4 _) y- Y
  125. /**4 Y% _5 E2 V4 o# A; J) o8 X5 ?# C; b. V
  126. * This function should do the actual transmission of the packet. The packet is
    . m. @8 ^( h, F8 @! j0 Z
  127. * contained in the pbuf that is passed to the function. This pbuf' h8 ^$ z" H+ m* P
  128. * might be chained.3 n& a7 K" l4 B! `
  129. *8 l7 W! F! m9 s5 Y. {
  130. * @param netif the lwip network interface structure for this ethernetif% E( H7 H7 [$ ?" k
  131. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
    # m3 S( Q. I7 p% {$ D3 @
  132. * @return ERR_OK if the packet could be sent( n7 J' J  t4 p/ v5 P
  133. *         an err_t value if the packet couldn't be sent
    ; r& o, Z$ I. e6 G* l5 @* e
  134. *
    , J9 v) j3 t, k% Z- @# I
  135. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to# p4 S9 c) }: G& t% v8 s% A2 E
  136. *       strange results. You might consider waiting for space in the DMA queue9 e. M4 d* v, z+ K
  137. *       to become available since the stack doesn't retry to send a packet
    , p/ t9 L- m; y8 l0 [) L  A' V
  138. *       dropped because of memory failure (except for the TCP timers).
    ' \) F( ^- l3 a1 `" `/ `
  139. */* g$ u: F7 {8 @- M! d
  140. % o2 N! m9 a+ \9 P. g1 `9 K) m
  141. static err_t
    + e% ?6 E% t0 G' P0 m/ y7 {8 t2 L
  142. low_level_output(struct netif *netif, struct pbuf *p). |) G" D; F8 ?( m; g4 a+ Z* n0 I
  143. {
    : A3 X7 {% h2 e- |2 P7 S) r9 t/ E
  144.   struct ethernetif *ethernetif = netif->state;' c7 H* h- j' U. n3 f
  145.   struct pbuf *q;
    4 a, M6 s" O! V" H$ m
  146.         , t2 G" R4 c) p/ K( a2 _
  147.   // 添加的变量
    - K4 t0 X5 ]5 P/ p8 u9 x' z9 Y4 h
  148.   uint8_t buffer[1792];
    ( N$ `$ F- Q4 ^7 d
  149.   WiFi_DataTx *packet = (WiFi_DataTx *)buffer;. S* J5 `6 R: U2 E
  150.   uint8_t *bufptr = packet->payload;* G( s- B) ~% @6 M" \& F' `$ Z

  151. 3 ?- E9 ^. |  B
  152.   //initiate transfer();# ^4 H# B! }6 s/ Y2 @9 G. F4 ^
  153. % m, h$ g% Z6 c: I3 n
  154. #if ETH_PAD_SIZE$ V# O0 P; \; A# s4 j: B
  155.   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    9 h5 h9 H9 ]6 B  N6 A7 B& Q$ L
  156. #endif& K+ R4 x/ M- Y7 e6 H& {

  157. . l) ]: l8 D7 s% b, F; T. p
  158.   for (q = p; q != NULL; q = q->next) {0 }9 q' S" B  q# K2 G
  159.     /* Send the data from the pbuf to the interface, one pbuf at a/ B0 Z) v  }3 ^/ f" q
  160.        time. The size of the data in each pbuf is kept in the ->len
    1 Y3 J# I4 u# Q, R# X+ Y
  161.        variable. */
    + Z; p: I7 ~9 X& Y% M9 v- f
  162.     //send data from(q->payload, q->len);7 t/ {' s9 `- z# F. j$ \2 E
  163.         memcpy(bufptr, q->payload, q->len); // 复制数据包内容
    & ^4 K( \- ^/ h8 Q- r
  164.         bufptr += q->len; // 指针前移
    1 T$ H  H3 N: w) P, G4 }4 o  g
  165.   }' `* A8 c  H$ l8 `

  166. ( ^( ?$ x- }: G& z8 Y  A
  167.   //signal that packet should be sent();
    5 K' ^3 z6 Z9 z" ]
  168.   WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包' v% v9 l2 F% P% n
  169.   
    7 E8 W- [: n9 ]- A! i8 F
  170.   // 打印数据包内容* ^0 @0 M: r& \4 u* v
  171.   printf("[Send] size=%d\n", packet->tx_packet_length);
    8 T' X# W% p" L0 R, x: `7 S$ p
  172.   dump_data(packet->payload, packet->tx_packet_length);
    5 y! ]0 h& Z1 s
  173. * N$ i5 ^% `! B+ w3 [" u; J4 V' _; K: F
  174.   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);  h# n2 f# v; @! N' t. i
  175.   if (((u8_t*)p->payload)[0] & 1) {
    ' l& r' Y- {# ^% y" h0 j! b
  176.     /* broadcast or multicast packet*/0 l: i6 n9 {' Y. ~" ?/ S* z4 m
  177.     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
    # n7 d4 i0 d: L6 \* k; P
  178.   } else {
    ; Q2 e* |) }" t3 O7 l! w# R: Z0 R
  179.     /* unicast packet */
    $ a) g' i: M3 ?. h* ]
  180.     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);) c4 ^8 W* R- W9 K
  181.   }
    : a7 |3 \2 B8 a
  182.   /* increase ifoutdiscards or ifouterrors on error */$ t& u' ?! D6 d* x5 ^

  183.   A: J3 A, h  ~/ T
  184. #if ETH_PAD_SIZE8 I0 Y: k8 R1 x4 Q
  185.   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */) q; U& Y9 d0 p) [3 j9 ]6 h
  186. #endif% I4 X7 F, Q- N5 f

  187. 3 k9 s$ c& q  }4 S0 \' ]% E
  188.   LINK_STATS_INC(link.xmit);
    ; A' e% w; d0 h4 K: A; `0 N, ^
  189.   L8 a) b, K" h% D8 `
  190.   return ERR_OK;
    7 q2 F* W, `4 x7 `0 h/ R* l0 ~
  191. }% U* I9 y- b9 X: b. _8 ]' ?5 b- m  T
  192. ) S" ~" r- J4 D7 |, S% V0 c
  193. /**3 \; S3 B# b* H! L7 s! m$ c
  194. * Should allocate a pbuf and transfer the bytes of the incoming
    9 u& c0 P( B8 I7 K) X: h) L/ |
  195. * packet from the interface into the pbuf.4 \2 j& N7 I5 N, Q; m- Q
  196. *
    ( j/ X% J' G$ J# u
  197. * @param netif the lwip network interface structure for this ethernetif3 ?1 d4 m- U' S# F
  198. * @return a pbuf filled with the received packet (including MAC header)
    ( N9 P& `, Q+ g% C
  199. *         NULL on memory error
    # B# }0 w" k) E: M& ]- Z
  200. */
    5 r& a- d) B5 S" r. F7 ~5 G7 L
  201. static struct pbuf *
    * }, ?8 L7 {3 }7 }
  202. low_level_input(struct netif *netif)
    1 B9 k% y% w3 Q: X- N1 I$ H4 i
  203. {# X* W4 p  i# m% c
  204.   struct ethernetif *ethernetif = netif->state;3 |- g& j) `0 x2 A" |3 o0 P4 B
  205.   struct pbuf *p, *q;
    8 T) P4 A/ V7 P' F
  206.   u16_t len;0 B% h+ y8 M  o
  207.         
    % T/ O0 J2 Z0 H3 G% B# L
  208.   // 添加的变量. K+ _1 T2 E1 f  }- ]
  209.   uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完8 }! [3 W+ ]: i& t- j
  210.   WiFi_DataRx *packet = (WiFi_DataRx *)buffer;
    2 }) o7 j, r4 k2 w
  211.   uint8_t *bufptr = packet->payload;
    2 S& M' |( r. f& u/ y

  212. 5 V6 x5 j. E1 A1 |
  213.   /* Obtain the size of the packet and put it into the "len"# G( I* h! Z, [; w
  214.      variable. */
    . d/ R. e# d( X
  215.   len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
    $ k# S1 B% P) ]# n( f& i) I
  216.   if (len == 0)  E4 X/ P4 G; C/ U! r! F. |
  217.   {
    ) ^( e& R4 }  Y, B! ~
  218.           // 若读取失败, 则不分配pbuf, 退出本函数" ?: }& X2 e" }4 m+ i
  219.           p = NULL;7 T  n: r6 P+ g2 m' K
  220.           goto after_alloc;
    , {; N  X$ [  ]" x
  221.   }$ ~. P' C  \, A! L1 B" t2 m
  222.   len = packet->rx_packet_length; // 获取数据包的大小
    ) R* o& K0 T2 u7 ?* {7 l/ _
  223.         
    " A" s1 |/ ]6 m- ~
  224.   // 打印数据包内容
    , l4 L' `, y9 v% t' W6 J
  225.   printf("[Recv] size=%d\n", len);
    8 U- L0 Q4 M  F% ?$ o4 A* n
  226.   dump_data(packet->payload, len);5 j5 N7 s# @) A" D& A
  227. : n7 b$ C& l/ G% x
  228. #if ETH_PAD_SIZE. P  h+ r+ s7 t& Q; V- G/ y) Y+ W
  229.   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */, }* K, u$ i9 q
  230. #endif( J0 ^" R4 Z* t
  231. - z- \& ~- }  }5 f* U
  232.   /* We allocate a pbuf chain of pbufs from the pool. */
    ( D3 @' f! P) `+ i: ]4 v4 P8 }
  233.   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);7 ?2 |) H) c& @: S* N
  234.   ) y: i( P& M' J, t
  235. after_alloc: // 添加此标记
    + I! u0 [) j8 E, Y( M0 ^

  236. * B8 Y+ M9 {# E* q$ s
  237.   if (p != NULL) {
    8 X# v6 F2 i4 V: J- F9 N9 ~6 `
  238. : X7 D# L& X6 U0 G: T& m8 [" R& w& h
  239. #if ETH_PAD_SIZE$ @; L# w* P8 k+ t4 J6 g) S- [5 w
  240.     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
    & `1 g, h) b; a( S8 D/ R
  241. #endif2 P/ f) s! l; X5 {2 U

  242. ( |* S. f) B' C" @0 \1 I$ X
  243.     /* We iterate over the pbuf chain until we have read the entire9 I( }* k2 B: Q
  244.      * packet into the pbuf. */& f# q* v2 ^1 f8 {" o2 A& ]. W7 A5 _
  245.     for (q = p; q != NULL; q = q->next) {( S! g  Z& X1 I% S+ t9 w
  246.       /* Read enough bytes to fill this pbuf in the chain. The
    9 R/ ~, ~! O* Q6 o, e
  247.        * available data in the pbuf is given by the q->len4 ?- \: \( ]7 I1 w' _
  248.        * variable.( ^5 B4 W( ~4 d! A- l% @
  249.        * This does not necessarily have to be a memcpy, you can also preallocate
    5 c) X" b9 a7 J9 ~  {1 y
  250.        * pbufs for a DMA-enabled MAC and after receiving truncate it to the1 K# k2 n9 O2 c, a% v
  251.        * actually received size. In this case, ensure the tot_len member of the& ]+ g; |' H+ Z7 c+ J$ w
  252.        * pbuf is the sum of the chained pbuf len members.
    : e" U/ `3 f2 L
  253.        */
    * E$ ~/ G* ~2 ~: t
  254.       //read data into(q->payload, q->len);
    % W' e  J' G0 _- K; |" n& T
  255.                 memcpy(q->payload, bufptr, q->len); // 复制数据包内容
    2 v# A7 k9 }$ X. ?
  256.                 bufptr += q->len; // 指针前移
    / L9 D6 ?+ j/ S0 _( E5 g' g
  257.     }
    " A6 V% T: }& s
  258.     //acknowledge that packet has been read(); // 无需确认
    4 v! U- l6 j; q5 g" [% h! S

  259. 4 j9 w! c8 `3 Y2 l" C
  260.     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    , J( a" S, G' D' v7 j
  261.     if (((u8_t*)p->payload)[0] & 1) {2 r" r5 x5 N. B$ D1 J% ]6 q3 {
  262.       /* broadcast or multicast packet*/2 G: d  K- V+ Z" K: ]2 t# ^
  263.       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);. ^+ g! i0 I: [
  264.     } else {
    ) C) q; g- O$ O3 n' T7 r: L" Q( v1 r
  265.       /* unicast packet*/
    6 Y5 ~) s" S/ n
  266.       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
    4 m3 l) \5 N5 m# _2 w
  267.     }
    / E+ d3 }6 b( V1 R* ^% N$ _# b
  268. #if ETH_PAD_SIZE2 E+ W  s) O& J% C+ u( {
  269.     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */; a3 x3 A. I! j, O
  270. #endif
    2 m3 s4 ]4 t; \3 U5 y% r

  271. : b4 w* ~: k+ b  c- B: h) q  H3 K
  272.     LINK_STATS_INC(link.recv);. U3 B3 W1 ^& G6 B
  273.   } else {
    ( e5 w/ f0 P1 x2 c  I
  274.     //drop packet(); // 注释掉此行* X' a- U; \6 `, J& K& e6 K
  275.     LINK_STATS_INC(link.memerr);
    2 K9 B$ P$ D, k5 W  N2 X* _8 N2 K
  276.     LINK_STATS_INC(link.drop);1 h8 O- W! T1 l4 J) ]3 M
  277.     MIB2_STATS_NETIF_INC(netif, ifindiscards);3 T% x1 [8 l! E
  278.   }
    * Y7 d1 u  q$ H) ]5 X' }
  279. 5 C/ ^+ w' X9 }, L; o$ Z
  280.   return p;: l0 [- `2 C; v# W  z3 }
  281. }
    0 m6 r) A, m4 w2 B

  282. , d) C# X/ Z6 g7 M# P
  283. /**7 [+ ~0 I  d1 @- f9 V
  284. * This function should be called when a packet is ready to be read
    + ]' c  N3 E  s% B# D3 t
  285. * from the interface. It uses the function low_level_input() that
    ; n; ~6 Z1 @% H, K
  286. * should handle the actual reception of bytes from the network
    4 S) A1 t/ Y/ s; Y0 n
  287. * interface. Then the type of the received packet is determined and/ Y# x& P) \/ w
  288. * the appropriate input function is called.* F. \; q. v  H
  289. *
    & w0 X' D$ C- l. ^3 s  B9 W* r
  290. * @param netif the lwip network interface structure for this ethernetif
    ( D- |" N* I  {, |9 c$ N" Y0 L7 T
  291. */
    7 @/ q0 y* b1 r8 K
  292. // 必须去掉static
    3 H( l& r! x! v9 m2 ~
  293. /*static */void
    ; X% {" i  d8 m3 U7 P& p
  294. ethernetif_input(struct netif *netif)$ Y* P4 s# E8 T9 c6 I  `! j/ u
  295. {5 b: R( r+ c/ w; ^, i; l6 Z
  296.   struct ethernetif *ethernetif;
    8 s* D2 \+ Y) [3 F5 l3 J, `9 L$ ^
  297.   struct eth_hdr *ethhdr;
    : j9 X  w6 o+ |2 s* a4 {8 G" h
  298.   struct pbuf *p;
    & n0 O9 \2 N& |% r# V; Z# _/ K

  299. ( z" b2 ^2 \' y9 u; D
  300.   ethernetif = netif->state;3 h. T$ e6 D# n7 Y% Q- v; }

  301.   y& ^3 S; g' T* _
  302.   /* move received packet into a new pbuf */
    " [! \3 o9 M/ ^' n+ O
  303.   p = low_level_input(netif);# M7 T8 }" s7 m4 X
  304.   /* if no packet could be read, silently ignore this */
    - R# u* x' p+ W! W- L
  305.   if (p != NULL) {1 _3 Z: w2 R4 S; g9 _! N/ k9 B
  306.     /* pass all packets to ethernet_input, which decides what packets it supports */: ?( d0 t$ @1 G  B9 A
  307.     if (netif->input(p, netif) != ERR_OK) {6 K" @4 B: ^6 h6 H5 i
  308.       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));% }3 w) g* z3 T
  309.       pbuf_free(p);+ n- e8 o. i$ E+ T% w: l
  310.       p = NULL;. E4 H) \3 A0 }5 R5 |
  311.     }
    + r1 R2 S7 ^6 V5 N
  312.   }7 u6 g' M( C" T, A
  313. }7 |, j6 O$ J$ g! z

  314. 5 H: M) I4 X; B: m$ u! U% X! z9 Z
  315. /**/ M0 ]/ f: o+ h) a3 s5 }5 a
  316. * Should be called at the beginning of the program to set up the  p1 M, Z1 O$ e
  317. * network interface. It calls the function low_level_init() to do the  |3 p0 e% N; Q, L* ?
  318. * actual setup of the hardware.
    4 D8 a9 s% @% b. a' T* O3 p
  319. *8 m$ B" [3 Q  |
  320. * This function should be passed as a parameter to netif_add().
    7 Q4 T  c7 p3 O2 B& B
  321. *1 R  {7 \& X8 W  D7 q5 f7 l
  322. * @param netif the lwip network interface structure for this ethernetif
    ( A3 q- T) \3 g% D0 Q5 ]
  323. * @return ERR_OK if the loopif is initialized
    4 h6 J0 L; r  q
  324. *         ERR_MEM if private data couldn't be allocated( ?9 I* m4 U" }8 I4 C1 B
  325. *         any other err_t on error% S, W" Y9 b5 Z0 i9 w
  326. */% q5 T; @$ N2 A$ l" I
  327. err_t
    6 K; I1 X/ z& F! K+ L
  328. ethernetif_init(struct netif *netif)7 a2 R: p. t- o! ~/ U
  329. {. ?6 U$ G7 y1 b* t
  330.   struct ethernetif *ethernetif;0 P( W% N, j1 U/ a/ w

  331. . C9 _: d+ g3 R3 ^* X0 u4 [
  332.   LWIP_ASSERT("netif != NULL", (netif != NULL));
    # i/ K3 k% L  b) ~* m. u* O/ c. _

  333. 9 z  q) R' V- |2 A. V- J, [0 Z- B- D( Q
  334.   ethernetif = mem_malloc(sizeof(struct ethernetif));( R: C( I% Q! |( R! h+ }
  335.   if (ethernetif == NULL) {
    ( Y% F) w! L$ P+ U( X
  336.     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    2 _. J0 \% d4 w2 @5 h
  337.     return ERR_MEM;* `8 M, k; n. _6 L
  338.   }
    4 j8 n0 v7 ~( m0 _/ P

  339. 5 i8 R" W: ?# i1 u1 W
  340. #if LWIP_NETIF_HOSTNAME1 h5 D: |& C: {1 Y. q) p
  341.   /* Initialize interface hostname */
    + l" U. r9 N' p- C3 b) E( k
  342.   netif->hostname = "lwip";9 g) G/ T7 N0 G+ R/ d
  343. #endif /* LWIP_NETIF_HOSTNAME */6 [! c4 O7 W  G* D! h. p: C

  344. & n5 l3 E+ u* G" r
  345.   /*/ U+ t2 I) }) e9 |* f. }; q3 O
  346.    * Initialize the snmp variables and counters inside the struct netif.
    " w& d$ }) C% A3 W/ |! g3 @
  347.    * The last argument should be replaced with your link speed, in units% ^  u' w9 C4 K& e6 A- h9 o
  348.    * of bits per second." \. F. `' s0 |  Z% v3 n
  349.    */0 \% m! o0 [+ o
  350.   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);1 S) Z$ N$ {0 w- ^9 t  Z" p8 i: a7 |

  351. 1 J% D1 D( m- e+ r% J
  352.   netif->state = ethernetif;
    ' Z8 m, y( {5 X$ O
  353.   netif->name[0] = IFNAME0;
    " C2 `5 d. I) g& Y5 p$ L" X
  354.   netif->name[1] = IFNAME1;
    * F8 W, s8 W2 T6 G' B( m) ~
  355.   /* We directly use etharp_output() here to save a function call.
    - K" N2 x  w- E9 _
  356.    * You can instead declare your own function an call etharp_output()
    1 }7 u0 B- `0 P& Q% `% c0 T4 i
  357.    * from it if you have to do some checks before sending (e.g. if link
    5 r/ U( h0 g4 D1 f" X
  358.    * is available...) */6 J1 m; ~  d5 e- @1 w
  359.   netif->output = etharp_output;1 Y& m& M9 S$ Z- T% B6 h
  360. #if LWIP_IPV6
    6 m% [- v% O2 U2 G( K& _* u- e. i
  361.   netif->output_ip6 = ethip6_output;
    : M* C( c: q+ q8 q) n9 t" b
  362. #endif /* LWIP_IPV6 */
    3 n" W: R. Q: Q0 O, O% ^4 `- E# F
  363.   netif->linkoutput = low_level_output;: z: |2 O! {+ Q. @

  364. ! w% W3 a5 @2 Q# H! O+ H9 d
  365.   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);5 r4 D# e0 O! x
  366. 8 @& L  t; X0 E8 T2 j3 R
  367.   /* initialize the hardware */
    $ e; [6 q. M% e8 F: ~
  368.   low_level_init(netif);8 _# r- x0 U2 F: B- d" ]7 c5 h+ }
  369. 3 r( v4 `0 t: e+ j& g  ~
  370.   return ERR_OK;6 x, r9 [2 P; d1 Z4 {
  371. }
    ) N6 g/ z# s6 R, l; C

  372. ) w! q! k$ w% B' q( `: i6 h& w  m
  373. #endif /* 0 */
    / ?) a8 m" Y7 D4 A
复制代码

: s3 _% C6 N) `3 T; S" }在项目属性中,设置Include Paths为:.;.\lwip\include+ P5 J4 I, N  j7 p2 c" }
其中点表示工程根目录。1 W, {  M8 B$ F5 v

/ T3 O, u7 h& p另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
$ X1 `& h: G' Y/ |  w# j6 {8 c2 c# w' W- \
编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
1 y" c& F- ]; v! d电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。% m% \) g9 U1 n" ^3 q
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。
' g  l2 y% Q. y

评分

参与人数 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....% n; H, F; Y$ F! z
# O1 _9 @1 n& G1 e1 L3 M& Z& F" k
多谢分享
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 手机版