本程序所用的单片机型号为:STM32F103RE9 u' n2 c3 z$ t0 x! `0 o
PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。
$ s/ C: i. f; v+ W注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。
+ E/ j' r' w7 h6 S* ~$ q该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。& @5 j% r/ F/ t! x; e
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
6 F$ a& \1 |; I" Y; k0 d, p + R* `! w2 |8 _9 D8 ]. s
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!. M0 r }6 G, o! |/ P, w
- Stack_Size EQU 0x00000c00
复制代码 【main.c】) R0 l4 W- T" t
- #include <stdio.h>' q; y4 m* Z( B+ {. T$ f, I ~$ |
- #include <stm32f10x.h>
, [" Z: _: P& h - #include <string.h>" S+ `5 y8 a# [8 f# r
- #include "lwip/init.h" // lwip_init函数所在的头文件
/ O9 _" `* o, |* t5 { - #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件3 [. @, W* y4 g; [1 O) _
- #include "netif/ethernet.h" // ethernet_input函数所在头文件
% ?, c$ G R' |& Q! ^+ Y - #include "WiFi.h"- H' E8 _$ ^4 o7 }2 Y9 h
7 Z6 g! v# F* d4 z. v- // 这两个函数位于ethernetif.c中, 但没有头文件声明
" i$ ~) h7 W4 ]+ G6 N - err_t ethernetif_init(struct netif *netif);7 {9 v; G, b+ N9 d. s4 V" Q6 [
- void ethernetif_input(struct netif *netif);9 \9 s [0 ?: a4 C( _1 {
, C. I( w. C a* }- // httptest.c中的函数- O/ L c( x( S9 ]
- void init_http(void);! o' K2 m' Z! N* k" }9 F/ \3 F
( i4 R/ v/ F( Q ?; |- // 延时n毫秒, c; y" d# \0 K+ T7 ^4 w; A( \6 Z7 H; B
- void delay(uint16_t n)
5 @$ O) i' s* z4 y' N - {
3 f' u( N* d) H3 A' f - WiFi_PrepareTimer(n);. i' Q# o* N" S* D
- while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕# y$ W0 r6 N7 W1 t, |. M$ y
- TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
% }! ~2 e, h* a- W - }, ~. Y( o$ n: q/ `, l
2 M% q+ s8 i3 z2 M9 L# D4 w- void dump_data(uint8_t *data, uint16_t len)5 X2 P" Q' ]+ {& {
- {
* V& u5 ?0 N3 i4 c' ~ - while (len--)& q! x% S9 V- A
- printf("%02X", *data++);
% p' K& e1 \5 Q. D - printf("\n");$ G' N) P# W" b. |" T i, f. S* x
- }
1 |5 x, @( ^, N* d# ]% g0 S; d
1 U' C+ z$ N; R' ~3 c- int fputc(int ch, FILE *fp)
3 P+ F: U& r& f k3 j - {0 ^0 r* h+ U. t3 b/ _
- if (fp == stdout)
. W+ |: }- e# \+ A2 ? - {
0 Y3 e( |( j6 [# ~ - if (ch == '\n')
; c# o# j" ]" } - {: s9 G0 A8 [5 [' N, Z1 y2 [2 H
- while ((USART1->SR & USART_SR_TXE) == 0);
8 w0 p+ P5 D' Q/ L4 {9 ] - USART1->DR = '\r';! C+ I, e8 Q7 g% G/ h
- }
, y; b. x/ R, S3 N: N( X - while ((USART1->SR & USART_SR_TXE) == 0);
' {+ I5 ~5 d- J, d - USART1->DR = ch;2 U& N/ g S0 A' J
- }
4 m& b2 U/ j @" T - return ch;" `1 l, {3 n& Y4 o- X8 d
- }
: C& n( v% P* N - A$ K4 _* E$ ~5 U- m3 i2 y
- // RTC时间转化为毫秒数
! F4 [; g0 h) h# a+ c1 Y* _ - uint32_t sys_now(void)7 x0 e+ M p8 D' i6 @3 V& L) `
- {1 R; j% f. P- u' c% c F3 X
- uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
2 V6 E3 b' m' q, C3 W' H5 S - tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒5 v6 w" j. d1 P( z8 L z
- return tmp;
( q- u; `% \ C/ e' b1 m - }
- u$ k, s9 f- h4 b/ c - r2 S$ z5 Z7 y/ L. g1 S$ @
- int main(void)
" ~. S& X, ]+ g5 {% `- R - {
% G! K! x B2 C: m - struct ip4_addr ipaddr, netmask, gw;
% Z1 G" t" K$ \. Y: ]& N - struct netif wifi_88w8686;
6 l) [" }% s, q) H1 Q; M4 \3 ` - uint32_t last_check = 0;- \% ?5 N w" D- O6 U+ c
- # k1 O6 J( ^% x9 a/ V+ ~" N
- RCC->AHBENR = RCC_AHBENR_SDIOEN;
& o9 W7 h3 K) B8 O* N9 b - RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;% n: t9 d' t" ^. o
- RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;
9 x! K; Z+ n8 K - $ J, \( q& F# S5 P+ \% K3 G
- GPIOA->CRH = 0x000004b0;- k3 O5 ?8 b- |
- GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块
1 E$ }* T% {, c3 V& a' L - GPIOC->CRH = 0x000bbbbb;( ]6 Z+ `2 |3 ~: w5 m4 N
- GPIOD->CRL = 0x00000b00;
: D) e" W& L4 ?4 \* @7 \ -
8 j+ ^0 h. C4 w8 A( q - USART1->BRR = 0x271; // 波特率: 115200. F7 [3 @: }6 G2 l) f/ x* v0 H
- USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
0 [0 z5 Q# Q+ X0 v) H1 t - 7 Z. { i; o. i3 H) x2 a% `, Z
- PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器
; D6 j" L' [8 }5 F5 a% k( @& H) H - if ((RCC->CSR & RCC_CSR_LSION) == 0)0 {7 x/ f n1 O ?% x
- {
6 u9 g9 M& Q" ]8 d$ c* y S - RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI, P2 `& V, U0 C1 V% G. C
- while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
! s# o$ B" a; L. T3 H - //printf("LSI Ready!\n");' G9 N8 E, E: `" W/ l
- }- L" u2 f1 j" z/ w2 O
- if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)
2 z( E8 J2 \& U - {
; O0 }5 Z+ {+ I% F# l+ u - // 若RTC还没有打开, 则初始化RTC
3 L& J' b3 F5 O5 X - RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时" w5 X+ l' \* V; X* e+ q, G
-
$ |& p1 l- K1 E: V; t - RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式) V) m- i2 N( c
- RTC->PRLH = 0;
! O3 h( [ ?# q - RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)
1 y& W4 v! E! W/ R - //RTC->CNTH = 0;
/ s" l* l: c9 m. E. u) r - //RTC->CNTL = 50; // 初始时间: O- K$ M% b& }) y$ L- ~1 l' l
- RTC->CRL &= ~RTC_CRL_CNF; // 保存设置! y$ `$ f# O. B0 ]
- 7 o1 Q; T) X' e5 V. F" s% V+ [1 A
- RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
) {% W+ q' @4 r. B - while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效7 Y: [7 r8 u, U7 J. u. f
- // RTC从此处开始走时
/ Q- @& j4 ~* `$ | - }
- D. S7 I. }# X$ K -
7 d4 L [$ T1 c) p4 e! j - WiFi_Init();
2 S% i: C5 R" \6 w1 S7 h - WiFi_Scan();: |4 y5 V( B2 w- q' U' A7 n5 I. M
-
* b$ b, G& [# ~% d2 ^ - //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点
; u) n M" H8 d - WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)0 ^& y+ c' X# c
- " I( _4 n/ J6 r
- lwip_init();( s3 M+ e2 F' X+ U3 E9 {
- IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址
3 J d; D* W7 b/ A" d - IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
9 y; v7 A# i) Z# ] - IP4_ADDR(&gw, 192, 168, 43, 1); // 网关/ r6 v0 V S w0 I! a7 n1 T2 o( I
-
% U5 ?6 C) W7 {$ o* A0 c$ q - netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);* k0 A x, w$ |/ h! I1 h0 A9 A
- netif_set_default(&wifi_88w8686); // 设为默认网卡, K" y0 S7 v0 F
- netif_set_up(&wifi_88w8686);
. G/ n6 g# c. c. k - % Z5 R% n' A7 H5 m' L5 w R
- init_http();) U3 S6 b9 C* O5 k; O( i) J
-
% ~3 K' }6 R! C - while (1)" ]' _' `, f* v/ G% e- Y
- {
3 `& z# G4 x( G9 o* q - if (WiFi_PacketPending() || WiFi_PacketArrived())
9 L8 k2 g' I9 N! X - ethernetif_input(&wifi_88w8686);
0 a8 W, ]( R- Q: k: P) M - - i9 \, B4 X* ]# Y4 N
- // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)
0 |. u/ t) d5 n - if (sys_now() - last_check > 200)$ m, t2 R+ W( c7 \! E% J$ @
- {
' l3 p. O: \+ i) b5 U# Q8 n+ q4 l - last_check = sys_now();
a' M9 W$ x- D2 s7 |, v% H8 i - //printf("Time: %d\n", last_check); f! ]* Y/ ]: Q. a4 q# Z
- sys_check_timeouts();: \5 A# `' f- x9 K: f7 U
- }- {4 P, W `: j% L9 b0 ~
- }
' a, ~) z: p0 H/ C# s - }
复制代码 【httptest.c】7 Q$ [, {! B4 f' \
- #include <string.h>* t! N2 O! @$ X/ D) {4 R9 `
- #include "lwip/tcp.h" // 一般情况下需要包含的头文件9 w9 W; F6 J0 g, s6 o, ?
- ! G, P, _* b9 d& Z9 @ j
- #define STR_AND_SIZE(str) (str), strlen(str)0 U- y" F( f+ E
- % j+ r% b5 j/ l
- err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
7 H! [ w$ K* O; \ - {
' B1 S$ G/ q! x8 h1 O7 F) L, | - char len[10]; // 存放HTML内容的长度
; t8 ?9 w/ l* ^6 Q; J: K2 M$ G - char str[200]; // 存放HTML内容
; ]* b# Q; h. S8 n' b" { F -
4 g: n0 ~ k7 X5 T2 P - char name[100];9 ?( Z6 H: A& b) R
- char *pstr;
8 S5 p# f3 g% B: \. ]& H - uint8_t i = 0;3 U" p6 k9 M7 u+ R8 s* I
- if (p != NULL)
8 R: N+ A: ^& L& _ - {8 c- C" q+ e! O6 a5 J0 N
- // 提取页面名称
& X6 B5 L" ^/ F, a - pstr = (char *)p->payload;
- K% U# @1 i* j7 o3 a$ P, f - while (*pstr++ != ' ');- R) o* G. x& A& X. ]
- while (*pstr != ' ')
# w" g7 d5 E; Q, q- {# _- Q7 ~ - name[i++] = *pstr++;
4 o8 D; y9 r; Z! o& T7 X - name[i] = '\0'; // 不要忘了结束name字符串
9 Z4 W" K2 T# ?4 Z3 c - tcp_recved(tpcb, p->tot_len);6 i, r, J* o+ z3 o6 G
-
7 a Q1 V; S2 ^0 U+ p$ W7 L - // 生成HTML内容
( [, N& K& h) t# m d4 Y& `' c - sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);. O! i1 @6 o, P4 [2 {
- 6 ]9 P, k+ q% H) z
- sprintf(len, "%d", strlen(str)); // HTML内容的长度
1 O: C2 r& d' H( @ - tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
% O' L# b) X7 o" P; u - tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);1 g* q( c. F# D/ R" N
- 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);( P( \6 n" h2 Y6 \$ L8 _9 b& Z" Z
- tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容9 O$ s# B, U1 i8 R5 C" p& L r
- pbuf_free(p);
1 q, H) W& t( E- k0 W - }3 J/ H) [; I& B B ]
- return ERR_OK;! }9 k) f* {. d1 e% h; n
- }
+ U0 s0 A: K, b1 k4 e5 c
, S/ j/ }, P* \! ] X# ^: {- x- err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
+ H- G1 V3 h6 u7 D7 U - {
I$ E" g E- n2 }- u - tcp_recv(newpcb, http_recv);
. b" c6 S& {7 @. m- V6 n - return ERR_OK;+ B0 [! t+ v! C0 R
- }
- W0 H9 n/ s# B9 B! W q
( l& C; W8 M; ?3 B* d1 F n2 t) H- void init_http(void), d7 ?7 E" O$ ~' N
- {
+ ^* a) W1 z7 @9 A - struct tcp_pcb *tpcb = tcp_new();
9 i4 ` _. e% n% y - tcp_bind(tpcb, IP_ADDR_ANY, 80);1 w0 d( k* l' |: t/ b% n
- tpcb = tcp_listen(tpcb);' c2 }' f, v. ]/ X$ [& T# Z- k" r1 ^
- tcp_accept(tpcb, http_accept);
0 y& ]/ c5 D3 H$ p3 |" A - }
复制代码 【WiFi.h】
p9 e# t, |- z, S- G. ^8 L7 ^( Y- #define _BV(n) (1u << (n))5 B! z# j) a- b
. D& O+ d1 R9 ~4 i6 H- #define CMD52_WRITE _BV(31)
% E2 S ]: ]' e1 X5 p; q4 L) [ - #define CMD52_READAFTERWRITE _BV(27)1 t0 m! y3 w; [; i! o# m( {* |! W
; c* b: z( d j4 R- #define CMD53_WRITE _BV(31)
8 b$ w! D. K q( ^, i; Y - #define CMD53_BLOCKMODE _BV(27)5 T8 a+ u/ h: `
- #define CMD53_INCREMENTING _BV(26)3 H+ c$ D7 O$ Z9 ~9 M- z
9 S- r$ q0 u3 J1 y3 H' y- // 16.5 SDIO Card Metaformat
7 ]: V7 d5 _8 D8 a" \1 \, e - #define CISTPL_NULL 0x00 // Null tuple
" X% C2 S7 e& X6 h - #define CISTPL_VERS_1 0x15 // Level 1 version/product-information5 s/ J3 {$ f' C. `% k
- #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
% O8 j- R0 x7 \) Z - #define CISTPL_FUNCID 0x21 // Function Identification Tuple
' z& |) D: a) I4 g2 [( _ - #define CISTPL_FUNCE 0x22 // Function Extensions5 \: L+ ?4 Z- k- f1 b: F- ~; J% e
- #define CISTPL_END 0xff // The End-of-chain Tuple
# y* o/ N) \: [6 q6 }, [5 l - * }% n$ \% ~+ X3 ^" S5 p2 [* i8 t
- #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)! {) t0 _( ]- J( }7 _
: M0 |9 A3 o& W" _4 F; u; R- #define WIFI_SQREADBASEADDR0 0x105 _9 j, c S, y6 d0 x% w7 w
- #define WIFI_SQREADBASEADDR1 0x114 v- d" }# Z4 e# R/ k0 `( P5 a
- #define WIFI_SQREADBASEADDR2 0x123 m+ q4 X$ n# }, r/ Y9 _7 \6 m7 F
- #define WIFI_SQREADBASEADDR3 0x13/ V2 [9 P3 N5 M& f" ~+ L# Q
8 j- B2 j7 }# I' g( h0 Y- #define WIFI_CARDSTATUS 0x20 // Card Status# i, q1 ?4 f1 J) d
- #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator9 A5 a( g! f8 z) ?5 N2 q
- #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
( r3 t: |3 P# C# s - #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready; g1 K# i; l7 u _* y1 \' L7 t" o
- #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready+ I S, ]% o( p; j/ @; X
- 6 E, L4 O/ F+ r- H8 S5 Q
- #define WIFI_CAPABILITY_BSS _BV(0)# ? w+ N7 M) m4 {, T J6 V
- #define WIFI_CAPABILITY_IBSS _BV(1)
/ J& N% K) L' M" k8 L - #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)0 t% |. b5 L3 U1 i+ I% `7 b/ w
- #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)! |$ x; F% g! r
- #define WIFI_CAPABILITY_PRIVACY _BV(4)* q' l: P6 U+ g( m7 e* [
- #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)
! f: W* K s% D9 O' M* X9 ? - #define WIFI_CAPABILITY_PBCC _BV(6)4 o: u3 _3 s# r. G. g) Q
- #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)" M3 {* s$ I. w
- #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
+ l! @" D/ H( B3 p) k - #define WIFI_CAPABILITY_QOS _BV(9)
0 L* V$ f- h' v, v - #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)8 S( p Z3 `, s a; y; D' @
- #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)
- u# z) N1 J$ l6 Q4 U6 i3 f$ ]/ I
0 i! d1 V, z: c, L+ i j( P X- #define WIFI_SDIOFRAME_DATA 0x00
[3 g1 s) p# w3 j+ [/ T2 O - #define WIFI_SDIOFRAME_COMMAND 0x01
, ~- f3 ~; G/ r) k5 b$ k - #define WIFI_SDIOFRAME_EVENT 0x03
0 M6 W- K- E9 l3 Z" C; ]
4 q& r- `: L" ?) K& @7 q- /* Command List */9 t8 }* }5 H2 L' u. o# T, L) J
- #define CMD_802_11_SCAN 0x0006 // Starts the scan process
4 P) Y$ d- q/ i3 S8 t - #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP) V1 B/ V3 H, V7 ~. z' u
- #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC7 `* v0 Z% D8 T8 d8 j
- #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
( n7 T" @( V0 D+ Z - #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address J% T; S- B. v+ E2 e
- #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption6 q, `* V* i: a) v; `6 h2 H6 g& L7 B2 g; J
- #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
9 N8 Y1 E! P) D% y! @0 M# ]. M1 ^ I - #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results
0 @# D5 o; z. W) l( t - o: A5 \% L0 l" J. s: C# m& g% n
- /* Command Result Codes */8 R6 a, W; C- s, L. M. _
- #define CMD_STATUS_SUCCESS 0x0000 // No error( l8 d/ a& i* Y) l' N' ~3 _
- #define CMD_STATUS_ERROR 0x0001 // Command failed. }- A y$ U7 z; A6 ~: c
- #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported2 d, N2 y! p$ j7 T6 g# r3 |
: J- D7 S3 j! }% v8 n- #define WIFI_ACT_GET 0
5 W- O) I7 u! P' O4 h% }6 u- _ - #define WIFI_ACT_SET 10 |: Z$ C! y, ^9 j5 t
- 4 |+ o+ K- h3 b& E3 Z) H5 {+ q
- /* Authentication Type to be used to authenticate with AP */
) e! v* a9 Q: ]2 m+ D0 a - #define AUTH_MODE_OPEN 0x00
% r. R( Z* K7 X. t9 O9 y - #define AUTH_MODE_SHARED 0x01
( Y* G2 C! L3 m" F5 X+ { - #define AUTH_MODE_NETWORK_EAP 0x80
. H$ ~' i. W5 n7 ~, _
# |( B7 j2 z: `, u0 A5 L- /* WiFi_Associate return value */; Z- Z2 A/ T, @" H. P
- #define WIFI_ASSOCIATION_NOTFOUND 0xfffe
# S8 u* O# W9 s. U/ \ - #define WIFI_ASSOCIATION_ERROR 0xffff
# ~* j4 N. h! K# q' G0 W' Y - #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功; }, _% t; U5 A9 M$ f8 r
- #define WIFI_ASSOCIATION_INTERNALERROR 0x0101
: L7 E4 j5 j6 m3 }, T - #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧2 ]) B. u8 x+ [2 ~; ^( f
- #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213
& A b: W/ ~4 I; X; {# s; K4 ^- U; K - #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
. D( }+ g2 J# Z. x/ D5 T - #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败
9 u, m" f, L& G6 ] - #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时# a1 w5 U$ [; _1 |. ^
- #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时# x% u( H2 ?( p% E! Y! F2 Z
- #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时- H7 O1 D/ a6 L3 f
- #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
# j5 H! `& h% @& V' g4 F$ D' l( v
4 R" U8 S$ I% A- #define WIFI_KEYTYPE_WEP 0
- e& W$ E; S$ t/ X - #define WIFI_KEYTYPE_TKIP 1& O! h( a' m: Y( _4 k- Y o2 v
- #define WIFI_KEYTYPE_AES 2' S E8 O1 o) J
- 2 Z" O, G8 A, D
- #define WIFI_KEYINFO_KEYENABLED _BV(2)& j& `( Q3 n# \7 @; ^$ s4 r& `
- #define WIFI_KEYINFO_UNICASTKEY _BV(1)
2 M1 g2 ] k* X8 z' J - #define WIFI_KEYINFO_MULTICASTKEY _BV(0)
: I4 a, u- Z/ T- x - 8 R: K! } g" z1 }
- #define WIFI_MACCTRL_RX _BV(0)1 M3 a* V1 C" p, Q H
- #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
0 g6 P: R/ ]. B% F! X - #define WIFI_MACCTRL_LOOPBACK _BV(2)- a+ ^( K# ?. \' X
- #define WIFI_MACCTRL_WEP _BV(3)
7 l" h4 W. k0 w, Q - #define WIFI_MACCTRL_ETHERNET2 _BV(4)
9 c( b( u/ v$ v- q! g9 t+ G2 b7 i1 h - #define WIFI_MACCTRL_PROMISCUOUS _BV(7)
) d/ w, k* e4 P, b0 \7 Z. x- Y - #define WIFI_MACCTRL_ALLMULTICAST _BV(8)( V( M& z! q; _ @4 @( ~: v
- #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection
7 ~+ w2 _& b+ T - #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode: C4 m( Z/ |& ^- N7 u! k
/ f/ v+ u3 ~5 `& [5 Y; P) E$ i5 o- /* BSS type */5 K" Z& n" X; b& X
- #define BSS_INFRASTRUCTURE 0x01% r5 q2 _9 G: B7 F4 ?
- #define BSS_INDEPENDENT 0x02
) N- v* G6 S9 |. | - #define BSS_ANY 0x03) X3 l0 K/ h( f' L* H' }7 c1 I
- 0 i, c( E; R5 N- D' E, @
- /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */5 _( i' B/ r2 B: i+ K4 j: l
- /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */
. x3 y' ?3 E: \0 |9 { T7 @ - #define MRVLIETYPES_SSIDPARAMSET 0x0000* m5 P5 P& x2 l3 a8 Y
- #define MRVLIETYPES_RATESPARAMSET 0x0001
1 V) V3 P$ D% _& c. d( n. t - #define MRVLIETYPES_DSPARAMSET 0x0003
' g+ M; w3 x% z# o - #define MRVLIETYPES_CFPARAMSET 0x0004
+ [7 ?8 i6 a0 N/ G; C( Y - #define MRVLIETYPES_IBSSPARAMSET 0x0006* S7 Q/ X( a( L3 z- d) x
- #define MRVLIETYPES_RSNPARAMSET 0x0030
" u* X2 @/ \5 |$ u/ ?: q0 e* J9 Y - #define MRVLIETYPES_VENDORPARAMSET 0x00dd
1 W* p* p' o7 d9 `' V8 j# y
0 h0 t5 I# O$ Y0 c% t- #define MRVLIETYPES_KEYPARAMSET 0x0100! B9 j3 _1 U1 T* q; h0 Z7 \7 {
- #define MRVLIETYPES_CHANLISTPARAMSET 0x0101
# G* z* V% V5 X$ p+ }; v3 h3 d4 U - #define MRVLIETYPES_TSFTIMESTAMP 0x0113
$ g5 ~8 d& a7 h. h+ J6 E. O+ z - #define MRVLIETYPES_AUTHTYPE 0x011f
( U p4 C1 [" Z2 W - # D% N' N& D1 b- K
- #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小
2 z0 H) p- L5 Z! U& f - #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小
5 q: m: b2 S4 D9 v# l - . B' M q& Z' D8 [
- typedef __packed struct, T- B4 [8 |# W3 S
- {9 a* L0 y6 C2 Y! W5 E- F; k. y5 o. [
- uint8_t type;' C+ h# }/ H8 C+ i4 u
- uint8_t length;
z0 m& r7 t" d8 a+ H8 ]' g - uint8_t data[1];' u2 _1 ]: u( c: M& j
- } IEEEType;
; K+ j- x. F1 U0 Z! b
; ~4 g2 R1 b2 C0 K3 [3 i" Q# n- typedef __packed struct4 d N% L" x5 D' N9 f* u
- {
5 n, p5 V1 J+ Z+ R( X1 a1 Y - uint16_t ie_length; // Total information element length
, `7 x: P. [+ J" H" R: ] - uint8_t bssid[6]; // BSSID
' N' @3 e" x1 u% {8 Q% @ - uint8_t rssi; // RSSI value as received from peer
5 X& ]2 w% ], l) [1 X - 0 _& F- x3 y8 H0 `
- /* Probe Response/Beacon Payload */
! S# ^6 _. Q; {$ V - uint64_t pkt_time_stamp; // Timestamp
# f+ q3 J* Y1 p4 |3 K9 Q& H9 ^0 g - uint16_t bcn_interval; // Beacon interval
* ]+ T. u) f. B" e - uint16_t cap_info; // Capabilities information
' F4 b% \' t9 j4 H/ I - IEEEType ie_parameters; // 存放的是一些IEEE类型的数据
* V5 J5 e. j( t$ Y' @ - } WiFi_BssDescSet;
' U# ~9 K' {: F9 J5 C# C- Q
+ ~2 M( g% G6 Y5 h# X6 v. K0 i' d- typedef __packed struct
9 {1 ^6 u! ~. A4 v( T0 D; l3 u' m - {$ J5 I0 Q% w$ I" C2 V( ^( c& S
- uint8_t oui[3];
8 {) ], _. O& g# } F7 V - uint8_t oui_type;" z4 |$ p4 z+ Q `
- uint8_t oui_subtype;
. s9 B$ N2 O N) |1 m+ o - uint8_t version;" L" J& _, X6 o$ l
- } WiFi_VendorHeader;% i. U: ? e- W r
3 X' Z4 x7 V! S( ?- typedef __packed struct
) o7 y( }1 a2 _ - {
8 O L: ]% ~" Y4 F$ @ - uint16_t type;
8 g& M& w# C K- N y - uint16_t length;
3 b' H0 |, a4 s8 I) h) V- p - } MrvlIEHeader;
! |0 c$ \4 x8 Y9 h - " ^ b" b# h' j- ?, P$ n/ f
- typedef __packed struct; F8 j) a8 B( d' R2 |. O* ~ k
- {
8 b/ i8 J- O. t1 G - MrvlIEHeader header;$ V4 t1 l- p+ H. q0 w- w0 G
- uint16_t auth_type;
3 _& f. W3 H# x - } MrvlIETypes_AuthType_t;
+ ]+ h! M: S5 J4 y; Y
7 d& d. m9 ?5 F( |" F2 |8 r- typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec- I. B( Q. D+ p" Y
- Y: z& F2 T& h% ^- typedef __packed struct; v! U& E3 F. g7 _1 K+ Q
- {
* q! h0 \" D* x2 u0 L/ \ - MrvlIEHeader header;1 p6 R9 q' b3 ]9 [! }% S7 K9 [
- uint8_t count;
0 F4 z$ ]! f2 n" l5 A; a6 P1 U - uint8_t period;
3 r/ h/ a/ G* w4 w" i1 b& V$ @ - uint16_t max_duration;& {/ x, b+ B# Y; m! d# }
- uint16_t duration_remaining;
! I3 D. }6 O9 v. A7 n6 _, h - } MrvlIETypes_CfParamSet_t;
' H$ z/ Y) D: l7 t4 n! Q - ' K- h9 q* X$ A! `: D
- /*typedef __packed struct
% I! m; v! K+ t: P3 Z, X - { s7 }* n$ ?' y: N: `
- MrvlIEHeader header;
! E& |" L- H* m' _( h0 q - __packed struct
1 J2 ^& h- n* X2 w. L- X* R6 I) D9 g - {' ]+ a4 \* i; [! A" P- n
- uint8_t band_config_type;
8 P" H" V' J5 ]) B6 U2 n* t A - uint8_t chan_number;
9 c, H% [7 X7 G( |& \$ Q: A - } channels[1];% |& f+ I. K# v* j& |0 }( M) N
- } MrvlIETypes_ChanBandList_t;*/
0 y+ ~0 n' j4 z( U - [$ }7 R4 `9 E# R8 e9 E
- typedef __packed struct
+ r! U% C2 B/ j& e - {+ I/ z" P/ j" |* ?
- MrvlIEHeader header;, H; }6 m. m7 E# X/ D
- __packed struct
: }: a5 D0 l8 k( {4 y( | - { i( R$ g. M- z h7 k; F1 p4 \
- uint8_t band_config_type;
w1 f! @; k/ J% E* k - uint8_t chan_number;
/ _+ @+ m& [, R# ~( x - uint8_t scan_type;
' ?0 n4 n5 ~- ^' w$ V0 A. h" `- n - uint16_t min_scan_time;: l" L, h( X# a0 Z9 m# e
- uint16_t max_scan_time;
3 ^% y* s9 c( S* ]" Z& l0 F - } channels[1];
0 N' X. a8 t) p3 }$ y* w - } MrvlIETypes_ChanListParamSet_t;
4 ?8 d, R1 k9 R: {8 \' d - ' H5 [# J3 y& L
- typedef __packed struct2 ]' I4 U6 M5 v% B
- {6 y4 \2 Q1 v/ Z# A J1 p
- MrvlIEHeader header;# o8 q( v, `; w
- uint8_t channel;
: z; Y* s( ~' ~- S: w - } MrvlIETypes_DsParamSet_t;
; {) A9 J/ _( [2 ]' q) m
- V2 N" T' v6 H6 h* ^* x ~- typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
* ^1 X6 _* c0 L& v2 `
/ ^9 n/ `& o: u$ g( t) q- typedef __packed struct' p# |# T4 C7 V$ f/ H$ Z* ~
- {
7 a: ~7 h! F; L" }: k, u7 g - MrvlIEHeader header;
/ f: @8 e# Z5 D" q - uint16_t atim_window;# e# [5 c9 k, h! h8 n1 s( ~! r/ R- ^
- } MrvlIETypes_IbssParamSet_t;: R( I6 P: j1 r9 G
- / N2 |! N6 k# y8 q" A0 ^, y
- typedef __packed struct
( {4 D& Z( I/ Q$ L4 y - {. G4 ?- N2 v) h( y: B: Q R. R/ e
- MrvlIEHeader header;" x/ b) `+ u2 K. r
- uint16_t key_type_id;* }, ]- p3 w" i$ |5 J: J. n, O
- uint16_t key_info;
$ W8 S* _: n8 ^% k! q$ P9 J - uint16_t key_len;" L6 z* k8 f8 M. E
- uint8_t key[32];* R+ O) t( T3 N+ f9 Z" ?% C2 {
- } MrvlIETypes_KeyParamSet_t;
* }9 y5 x% B' M8 u1 d+ Q4 O: `3 Q3 b - 4 s& X9 \- u0 A5 k' Q# E
- typedef __packed struct! M6 B5 p: q* Y8 J# ?$ @
- {
: V- I% E& A! o$ E8 m - MrvlIEHeader header;* \: @2 H, X& W( f! x
- uint8_t rates[14];
9 r: {$ i0 s2 t+ m - } MrvlIETypes_RatesParamSet_t;
" m3 r" ]/ K+ _6 g! ~2 `1 X! Q - , `8 w( {- n$ K: [' K% G
- typedef __packed struct2 B$ J5 E R1 H" V+ z$ Y g
- {+ @) X) V4 o' l9 R: p' T& K9 v
- MrvlIEHeader header;
, T" u+ E4 F8 t, ?$ f6 O. C - uint8_t rsn[64];- f4 o' w9 \8 i3 | [; Y
- } MrvlIETypes_RsnParamSet_t;- Q. g% K) L1 N: m9 R
- - h0 ]- s+ Z) B4 @
- typedef __packed struct; O; e, }% ]8 v" t! f {# z
- {) z/ m. b$ v$ T; j+ o6 a& |: u7 S
- MrvlIEHeader header;$ T3 Y5 O5 p+ q( c) Z" j
- uint8_t ssid[32];
; r9 Q1 @9 {/ G5 `1 {6 Y - } MrvlIETypes_SSIDParamSet_t;
0 C5 o: r, ^* e' q7 H8 o5 M0 A: h
& }* o: G; L9 }' B" k* X9 K9 }- typedef __packed struct4 S, p! V$ Q7 x5 i6 g w( `/ d
- {; J4 H0 M; o* X8 P4 f x
- MrvlIEHeader header;- m+ h' C1 ^9 E c' [1 h' i
- uint64_t tsf_table[1];
: g0 I2 }) E# h3 y5 Z, N# R - } MrvlIETypes_TsfTimestamp_t;
1 v* m" y' u' H& s: p
; b& } p, v7 i7 p" l H' L3 j. k- // 整个结构体的最大大小为256字节! [: H& j5 O: @( n$ S' l
- typedef __packed struct
3 s" ^9 b5 \1 |* B - {# @3 P/ E3 ~; B! T6 K6 T; P& }8 ]
- MrvlIEHeader header;" U3 @( e$ u+ }/ c6 d
- uint8_t vendor[64]; // 通常情况下64字节已足够
+ a1 X6 e5 X% l - } MrvlIETypes_VendorParamSet_t;& j. i/ z- F5 X, E
l t' L/ J" t- R1 L) J, F- typedef __packed struct
0 `) T: Q* S7 N$ k - {
& ~9 V% N, E# ]( m7 @7 Q% o+ P - uint16_t length;+ n+ Z+ m9 }( m: ?4 i
- uint16_t type;' B, H4 V+ D/ v; `# ~/ S
- } WiFi_SDIOFrameHeader;
8 c# k# B+ l3 j& H; l - . n2 R/ k2 B# A
- typedef __packed struct
$ g% V, |( A1 r$ y; S - {
" Z8 T6 Q9 Y( ~ - WiFi_SDIOFrameHeader frame_header; ) D7 {: M/ b1 {) X6 v/ V3 h
- uint16_t cmd_code;# A/ G& ?$ s5 H; X( D
- uint16_t size;( e7 N9 q- \: d7 k" V, d. R
- uint16_t seq_num; S0 x; P. g- _- b" H+ U% j
- uint16_t result;
/ W5 W( g2 r$ B, H3 J. c Z* \ - } WiFi_CommandHeader;6 W" \9 M$ ^# x% r0 M/ O
- & m* W- y0 c1 f" }9 F) P$ ?
- /* Table 2: Fields in Receive Packet Descriptor */
; s! v& C5 \# Y8 K& @- a1 J# X1 L - typedef __packed struct
# v" { Y U. z, B- D2 Z: j5 m - {, L9 p H8 a1 T
- WiFi_SDIOFrameHeader header;; h: x' F7 G) x* `+ D7 z
- uint16_t reserved1;5 B* ` ^ v3 E4 W5 N
- uint8_t snr; // Signal to noise ratio for this packet (dB)
4 R7 z3 Q$ ~ P5 p - uint8_t reserved2;
6 j, B+ E/ x/ j# a I: W8 d - uint16_t rx_packet_length; // Number of bytes in the payload
# ?9 r* X1 N: |( `- J. e1 D" q - uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed.
2 K4 Q! u& x. o+ ~, Y - uint8_t rx_rate; // Rate at which this packet is received1 H* t& E7 U2 e
- uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet7 n2 R" H9 d# u @ g1 d; M8 q+ H& L
- uint32_t reserved3; s& y, L& m1 c! p
- uint8_t priority; // Specifies the user priority of received packet
) C" D0 y: a- Y" t* e - uint8_t reserved4[3];0 V+ i9 R9 \1 N3 [) @* j
- uint8_t payload[1]; // 数据链路层上的帧# O2 m& [* J5 U! L$ O1 ]
- } WiFi_DataRx;0 x1 Q" y7 ]4 z4 F: K/ M. g
- ( _7 T( m3 f+ x. ~0 I" [0 J
- /* Table 3: Fields in Transmit Packet Descriptor */: `* D0 }6 ]( o) j( J& L
- typedef __packed struct
- u, ]) p% S8 I* F5 X* r - {
- J, p; V& U2 C+ E9 ^ - WiFi_SDIOFrameHeader header;
6 |1 V5 c Q% {( p+ s. Q - uint32_t reserved1;4 _- r( v' W; O- {$ _- U
- uint32_t tx_control; // See 3.2.1 Per-Packet Settings
" _1 K0 {5 o9 l4 I. |# X T/ M0 } - 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)+ F6 ^9 E2 ^ E/ c, U/ v; e
- uint16_t tx_packet_length; // Number of bytes in the payload data frame( e; Y& E% I: j( D* b. P1 z2 p, T$ }3 L
- uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5
( z. D% I: ]8 B& V1 k/ F( ^# ^+ I - uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 3/ K( @: ~* `5 U
- uint8_t priority; // Specifies the user priority of transmit packet
5 \9 Y8 t ?5 y9 z! a+ p' ]/ W+ k5 o - uint8_t flags; m$ m: e4 k+ {
- uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations# H% \' q) m/ ^, @ Z; `
- uint8_t reserved2;
1 [3 ?; W6 k1 U+ n7 W& u - uint8_t payload[1]; // 数据链路层上的帧
4 T1 M# ]! _0 ]0 i - } WiFi_DataTx;
6 ~3 k9 d6 q! f& t: [9 H4 g
$ C/ j' j. B7 N; d7 u- typedef __packed struct
+ f# E1 i% s/ H; a; F - {
. W! k! F7 Z% A! H - WiFi_CommandHeader header;2 F, K( n+ @/ e, B" j( p
- uint16_t action;
4 k! y, l! W$ e/ ?& N c& a* h - } WiFi_Cmd_KeyMaterial;
, ?6 X9 K% I I* P9 Q, R1 l% Q% l. R: O
/ E' f7 j0 d5 P5 t- @7 I- typedef __packed struct* {8 Z$ m/ s6 f
- {+ p# B% T$ Q" c% Q, {1 _; n' P
- WiFi_CommandHeader header;
4 h6 W {+ E# H" K @' ` - uint16_t action;, L" u/ L, F" M7 ] F# M0 E
- uint8_t mac_addr[6];
8 o$ A; g2 _' L( X! z/ P2 ? - } WiFi_Cmd_MACAddr;
+ U8 [) q% a1 Q4 N3 \- j" e) }
0 c. h- X4 v, u. N# k: K3 J/ J. F- typedef __packed struct5 B9 F$ L- ~. c7 @- x( [
- {
+ z, H! c' y: |$ {3 c; E9 h* I - WiFi_CommandHeader header;
8 K; {% a% U e* \ - uint16_t action;
3 c" H, z+ t0 _ - uint16_t reserved;
3 y; ^& H* u( d) h - } WiFi_Cmd_MACCtrl;5 g) L; k) H. k+ Q! ^. s: m! s
: U) o" t3 k& X- typedef __packed struct
4 a0 a% \% l) a- ^$ O, Q - {) n7 i. w b- H& \- Y' x
- WiFi_CommandHeader header;& L) G# J) Z' V' h. r( ?( f* v
- uint8_t ssid[32];
3 D( p6 d; l9 r - uint8_t bss_type;. u3 U, V0 f2 r% y. A- E9 R
- uint16_t bcn_period;
4 L5 J% e! a+ B& L) W - uint8_t reserved1;: }+ d( Q# ]0 b& c2 W6 ]" T
- MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU/ K6 \9 J8 o6 y3 b) o5 L* d
- uint32_t reserved2;
7 K' N" i% @3 m- o - MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network; _( z3 l& Y2 B( z
- uint16_t reserved3[3];- G. b7 E6 o1 E
- MrvlIETypes_CapInfo_t cap_info; // Capability information+ j# e; _6 r2 \& c! m+ B
- uint8_t data_rate[14];: o5 B& T! f% d* H5 W& v7 ?# Q! h
- } WiFi_CmdRequest_ADHOCStart;/ I3 \/ d1 i0 c0 x* ?7 s
- : I' ]# F ]: b' V9 Z
- typedef __packed struct8 _* p& t, a: o% Z
- {/ {# d5 P7 A' D' }8 L$ h& N# t' I7 F- U
- WiFi_CommandHeader header;
1 g$ h7 D( y+ D9 t z - uint8_t peer_sta_addr[6]; // Peer MAC address
6 P( q# Y9 b' U! F6 `6 q3 S! v - MrvlIETypes_CapInfo_t cap_info; // Capability information
4 q3 _# \6 D4 V - uint16_t listen_interval; // Listen interval3 d2 P% B; l) K; a5 z
- uint16_t bcn_period; // Beacon period( j& H, w1 X+ k# e! `" G1 D
- uint8_t dtim_period; // DTIM period3 q& y8 o# a6 y0 C4 T& ?
- } WiFi_CmdRequest_Associate;
+ l0 q3 d' {. X6 ^3 \& a- n
6 e6 p8 R1 a( b7 q- typedef __packed struct/ M+ ?, t2 i, D0 U
- {! J1 i: s8 n% T B W
- WiFi_CommandHeader header;
8 D' }* E5 B1 Y& `6 R - uint8_t bss_type;2 q4 i3 l+ L- D# F+ ~
- uint8_t bss_id[6];
# i" O4 s1 K0 t1 x0 _( U8 g - } WiFi_CmdRequest_Scan;
# z9 \- Y( D- q5 U* M
; U) ^! D- z6 }/ }& ]9 s2 @- typedef __packed struct& ], O3 P. F, K+ K, | g+ W
- {7 `* I& _% V/ q) e, Z& P
- WiFi_CommandHeader header;4 ]8 K3 L* g- M" O; X
- uint16_t capability;
9 u; S9 k/ D6 w% h2 k - uint16_t status_code;2 b5 j, \; q- U. i* N. N
- uint16_t association_id;, l) {* y7 c5 I. T9 v
- IEEEType ie_buffer;
) u% i* V" G" q% @. ^1 c - } WiFi_CmdResponse_Associate;5 N. Y5 u# d0 g) G4 U4 n
$ }8 n/ `- h7 t) n% v/ e- typedef __packed struct
; z5 F6 y9 P7 u0 Z# _3 h - {
Y" n# ~% l6 j4 ^5 ~ - WiFi_CommandHeader header;
2 `; `! m$ l9 g6 ~0 {0 ^ - uint16_t buf_size;* }, V7 D/ K" s5 I
- uint8_t num_of_set;
" n; T+ m/ V- p7 C - } WiFi_CmdResponse_Scan;
* B5 U$ k& U, y# \5 ] - G, z) Y' a9 u' r
- typedef __packed struct$ h0 H( s) n! M# ^4 {7 u
- {$ z- c7 {6 `1 a0 q0 R. S
- MrvlIETypes_SSIDParamSet_t ssid;
( X" H! ~2 `+ X s - uint8_t mac_addr[6];
; O1 U/ }! V4 {3 _- c- r! | - MrvlIETypes_CapInfo_t cap_info;
: w0 u6 M5 B R7 Z - uint16_t bcn_period;3 b2 C; Q9 @& U6 w- I T( U
- uint8_t channel;
2 X K' Y2 L7 c- k+ n - MrvlIETypes_RatesParamSet_t rates;
& |7 ]# ^. G8 ~) p - MrvlIETypes_RsnParamSet_t rsn;; _. v/ B6 _7 Y5 t9 S% v) q
- MrvlIETypes_VendorParamSet_t wpa;/ W8 O2 G' t1 Z9 r _& F
- MrvlIETypes_VendorParamSet_t wwm;
% n0 ]9 |' `+ |" H2 i) b$ O+ V; v - MrvlIETypes_VendorParamSet_t wps;; n( ^5 {7 F# L7 n% b8 |
- } WiFi_SSIDInfo;
* q9 A( A+ ? R1 b% ^) y
! h, M, P( S- ?4 T: j! O& y0 @1 m" b- #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0), G" T v. v. z. S& ` G
- #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)% i* g: t4 i1 I0 ]
- #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)& M, w% g3 `2 U" X! I
- #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)! l2 l: R7 S& H( w
- #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)4 A& v8 j7 [8 ^0 h
- #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)$ E$ F: G# I! ]$ n
- #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)
% K% h1 ]& ?' J5 w2 ^# [ - . c2 q, k0 m }; ^/ A1 h5 A
- uint16_t WiFi_Associate(const char *ssid);8 R/ W" S! {# l' a% P
- void WiFi_CheckCmdTimeout(void);
7 ] _1 S( R/ E9 r( Q - uint16_t WiFi_Connect(const char *ssid, const char *password);
. X; v* j: x6 }% B8 f% N - uint8_t WiFi_DownloadFirmware(void);
F6 a0 q: C4 \& e - uint16_t WiFi_GetPacketLength(void);; g# e9 L3 B- e( a
- void WiFi_Init(void);
1 v2 X) K8 M: |+ }1 M* N3 ~6 f - uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);, \; c2 f+ z. e
- void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
# g5 O M/ \. r0 ^# _- W% y - void WiFi_MACControl(uint16_t action);. J6 h( C' u4 n. B1 ~: x# R
- uint16_t WiFi_PacketPending(void);4 A5 h0 X# h4 X! I- L" v3 ?# q( ~& o
- void WiFi_PrepareTimer(uint16_t nms);, n. ^% |, e# t2 P6 |
- uint8_t WiFi_Read(uint8_t func, uint32_t addr);4 W& R: g+ K. \( I2 Z; G
- void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
# B3 _1 I5 @, y+ w0 q( P6 r - uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);
# a I, B- K) m `! L - uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);
) O4 F( w3 D8 s - uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);
6 w+ P' @% x9 Y! b, A9 t, J" l6 W - void WiFi_Scan(void);3 `" i0 q2 I+ `6 j( y
- uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);& p* Y& c5 y5 u, P" O0 ~1 ]
- void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);
( A' o. G9 q. r. H( S7 L! i4 h - void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
5 K6 A. ?) `9 G b/ ~$ y" V9 b# i - void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);
& C7 G4 m' E( J& O4 ?+ g, _+ r - uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);
; l( t' @) q# o! a8 L- Q# _ x, ? - void WiFi_SetBlockSize(uint8_t func);- Z) C3 _. b& l! c
- uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);; O9 o: N+ i( T4 y8 K
- void WiFi_ShowCIS(uint8_t func);
$ V. Z' ]; R) I5 j6 o o; k6 E - void WiFi_ShowKeyMaterials(void);+ X& g: E' C* E4 K ^# v7 l
- uint8_t WiFi_StartADHOC(const char *ssid);' O( ~9 T8 N6 ^& d8 @
- uint8_t WiFi_Wait(uint8_t status);3 C. U" T' S) |" k# O3 R
- uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);
; v/ R" j5 b+ @5 Z" ] - void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
, d* X ]1 a4 E" s, f- q- M - uint8_t WiFi_WritePort(const void *data, uint16_t size);! i) @! h; C" V9 K! Y: d- z7 @
复制代码 【WiFi.c】1 ? _7 U/ _! b# |- r0 e' U% p
- #include <stdio.h>( _. B1 v7 w. u, m7 M; \
- #include <stm32f10x.h>* z1 W5 }# V: z8 e
- #include <string.h>
) L% R+ |% `" [ - #include "WiFi.h". U7 `4 {/ z. F- X5 r2 B2 z# N, a
- & }% r4 l8 o7 A) Q
- extern const unsigned char firmware_helper_sd[2516];" S5 @6 o* o, P! n0 K, h! M, E' }
- extern const unsigned char firmware_sd8686[122916];# ~0 v6 J ^7 d" J. r7 |5 K
- 3 i. o2 Y, X6 r$ h; z) F
- //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址
0 H0 H8 `9 ^& g7 I - ( j4 m) A" c; c4 d8 `' T
- static uint16_t rca;* J7 {' C4 N. D# w
- static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;# p0 U2 Y: b# A; C
- static uint32_t io_addr;8 p2 I! [9 ]1 u) l: P
- static uint16_t wifi_pending_size = 0; // 未读的数据包大小* n* }3 E2 f" e' v8 l8 {4 @, h
- # j& ]4 a4 x( u- F
- void delay(uint16_t n);
0 p7 S3 ^' L7 p5 g - void dump_data(uint8_t *data, uint16_t len);
2 ]% S2 q- L' v - . P. T2 c$ h& X5 q4 t6 t
- /* 关联一个热点 */
0 t0 j! S5 k7 R6 ^ i, f* _6 O - uint16_t WiFi_Associate(const char *ssid)$ D, t' W. } C. {! m$ g4 m/ m9 ]
- {
; `6 U8 ~* R7 U E, ?5 k - uint8_t buffer[2048];
$ p# J- Y% S4 G - WiFi_SSIDInfo info;
7 z, }8 v+ m2 v6 I5 N - WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;/ T9 O5 M+ }3 m5 \5 i
- WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;
5 M8 @' n C3 e+ D7 g - MrvlIETypes_DsParamSet_t *ds;
' d+ g2 l4 G0 ^6 ` B Z& r - MrvlIETypes_CfParamSet_t *cf;6 }+ f d& @8 R& Q- N) A) Q& d
- MrvlIETypes_AuthType_t *auth;
( y: ^# G! ?# \ - MrvlIETypes_RsnParamSet_t *rsn;0 p# K1 ]+ R8 w- S. B; V
- / f* p& E0 ?: k/ i, \# L
- if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))( t1 Y6 ?5 v. t6 m. M: P4 i
- {
, ~1 D1 U; a R - printf("Cannot find AP: %s!\n", ssid);
9 W; |1 W) t1 }, G/ Z0 z$ w( | - return WIFI_ASSOCIATION_NOTFOUND;
4 v) ?% `1 W7 u$ I0 x; p8 r - }
( _* F3 }* X/ G0 z5 E -
4 U9 @0 o( j2 U$ Q* c" r/ u7 A4 s - memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));1 E3 \# o2 L. x/ r
- cmd->cap_info = info.cap_info;
! m4 g4 M0 X" N& F6 h& t% v - cmd->listen_interval = 10;9 K3 x7 o5 J" X7 [" K! e
- cmd->bcn_period = info.bcn_period;+ g, S9 {* n) n a6 R" b; }' p
- cmd->dtim_period = 0;
" R3 J" w% _( I9 N) n4 V - memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));1 C( M# e2 x! e6 X. _1 q
- ( d- Y$ a. y5 g. [/ a. R* v
- ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));7 C- ~0 E6 ~9 N& e
- ds->header.type = MRVLIETYPES_DSPARAMSET;" Z/ N/ r. D& G
- ds->header.length = 1; a" s$ M5 i' P+ M
- ds->channel = info.channel;
! P' |6 a' p% W" s5 L* G W - * z- T5 [9 h' e: [+ x; W, ?1 ]8 [: R
- cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);
3 a; k: D% `7 T" r# E - memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));
6 _- |3 A; ]$ k* p( r - cf->header.type = MRVLIETYPES_CFPARAMSET;
3 z; h" T. A+ {" W. n9 v" ? f0 g* V - cf->header.length = MRVLIE_PAYLOADLEN(*cf);; w% ~4 n3 M {5 H' A1 V
-
: O. N0 i& {3 S+ ]/ {0 h& Z - memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));: O+ ^ C1 {* C
- auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
% ~0 Q; I1 T/ G - auth->header.type = MRVLIETYPES_AUTHTYPE;8 C3 S2 g# L Z2 ?" A
- auth->header.length = MRVLIE_PAYLOADLEN(*auth);/ K0 J5 U3 O8 @9 O( X; m% q
- auth->auth_type = AUTH_MODE_OPEN;% W# B- n9 _0 N
- 0 m. n/ ?3 w+ Z, E3 e* r/ e3 n
- rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);8 q+ P; Y" i8 G8 _6 g6 s2 O4 M
- if (info.rsn.header.type)
: u! K/ O) ]: \ `. Q( w4 [) W - {0 u( l& l" r% ]
- // WPA2网络必须在命令中加入RSN参数才能成功连接) g: u# J" X& R9 Y( i- J
- memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
, I, ^- e9 p* A7 t# J - WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));3 Z1 e/ N6 {9 G! w2 C0 k
- }1 T( i0 _$ @3 k" U1 a. f$ F4 ^/ N
- else
/ a# }3 K# ?; u5 D8 W' z j - WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数
0 G" I6 h" K# l/ Y/ \ - , I0 \! [; `; ?
- if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))( c9 x! P9 X$ C8 Z+ ~
- {
3 b7 [' m4 b3 t Z0 t - printf("Association with %s failed!\n", ssid);
" Y" m$ V0 d6 S" d* q6 o# Y - return WIFI_ASSOCIATION_ERROR;- s% F0 W+ e: P$ x7 B' D
- }
1 P3 q0 Q3 E! D' t; u - 5 z( a' Q: V/ c1 U- J( z
- //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);. d" ]* ~& i& y9 T
- if (resp->association_id == 0xffff)9 n" T" }/ c A
- return ((-resp->capability) << 8) | resp->status_code;0 Y# g( Z. q- u8 H5 v
- return WIFI_ASSOCIATION_SUCCESS;
+ n3 j5 M7 a; f2 X1 D7 ` - }/ _$ H4 b- O# d, J* f
* [* i% L B, ]/ H, O& B- /* 检查命令是否收到了回应, 若没收到则重发命令 */
& P2 Y3 o$ g0 Z) ~ - void WiFi_CheckCmdTimeout(void)( i3 o. v; u3 U
- {
7 H8 Z, |% w6 G; w- D+ r! X$ O) I - while (SDIO->STA & SDIO_STA_CTIMEOUT)0 g# C/ [ H( J5 q- M+ v5 b
- {
8 \; B& x( ~8 K0 N, Z - SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志
& ?* L x3 c+ D9 q5 [, n - SDIO->CMD = SDIO->CMD; // 重发6 ]. `( K/ S8 ?; ?" d
- printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);, G+ ]: _) X) A' D1 i% ^6 q* W7 T, N
- while (SDIO->STA & SDIO_STA_CMDACT);8 D2 T& {/ c: D; }1 G: X; [
- }
$ r6 b3 d: Y9 }* w - }
' @' S! q7 w( M a* O: {5 G - 8 M# K& x' J" `
- /* 连接WiFi热点, 并输入密码 */
: @1 j2 I( h ?: k- I0 B - uint16_t WiFi_Connect(const char *ssid, const char *password)
6 V* g9 l+ }) u. T( B" w - {' S1 V" Z& I& [5 B- f6 S( @9 }
- uint16_t ret;
/ K) r: i; N8 G8 |5 q - do
/ t( _/ u& v+ L - {- h) @5 e* K3 t8 C" d
- ret = WiFi_Associate(ssid);
: M' Y% g% D" m9 _ - if (ret != WIFI_ASSOCIATION_SUCCESS)' c7 ]! q i- }4 x& M$ ~
- {& R& J+ S/ e( `! z8 k7 q/ F
- printf("WiFi_Associate returned 0x%04x\n", ret);6 x* E- J. p3 k* ^# ]
- delay(2000); // 等待一段时间后重连( d# K- X2 a$ N, R$ S$ S1 R# g
- }# h. r9 k, A5 s2 K8 V* d; ]) H
- } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连. U U0 f" _6 ?
- + Y% p8 _* H, {5 h
- if (ret != WIFI_ASSOCIATION_SUCCESS)
$ n+ l: \6 p. u* a! s - return ret;
! I* g8 S8 o3 x5 t1 S1 |' o, e - ; O2 z. J9 q$ _! C3 _9 h0 K* }
- printf("Connected to %s!\n", ssid);5 U& |5 J) v) p8 A) w
- return ret;
4 d R" ], y. C - }: x0 k( @8 k* @( A3 ~8 G% D
- 4 K% K/ d# c' U2 H
- /* 下载固件 */
7 H4 X# w( F( C8 } - // 参考文档: marvell-88w8686-固件下载程序说明.doc: K4 B7 {8 e; R& w
- uint8_t WiFi_DownloadFirmware(void)* Q( ?( `8 \. C
- {
! _& m* T4 q1 U3 s7 a - uint8_t helper_buf[64];
8 o' ~% x1 v/ `/ s- Z - const uint8_t *data;
3 i* @( e% c; r# | R& u/ Y - uint16_t size;- `5 I: V7 Q. X$ v/ K4 p. W+ D
- uint32_t len;
( ~1 O2 n. }6 {+ {- T - 6 {& z0 D i* o4 e) R. F% g9 c# |3 X
- // 块大小设为32
% G" C/ Q7 G/ ?; v$ A# E0 C, z - SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;. y( {" f- Z) u4 [
- WiFi_SetBlockSize(1); // 应用到Function 15 [' A0 z: o- q4 y4 G0 @6 p
-
! {* `4 L" c( Q1 @( T6 F' r - // 下载helper
. a! k8 `- Q/ L: r8 K5 J - io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);$ T- D! R; V4 q4 Y8 [
- data = firmware_helper_sd;6 `0 }+ A$ G" _4 a% P8 E
- len = sizeof(firmware_helper_sd);
* k. b- p1 O: v' K* d& r: ~+ ~ - while (len)
4 ~; ]( h2 J; P5 Z; e! M( O' D3 P - {$ h P- x$ _" H! k1 P; ], N. M
- // 每次下载64字节, 其中前4字节为本次下载的数据量
; g3 p" A0 P8 \2 Z$ L! `% V - size = (len > 60) ? 60 : len;
1 z: o) @! ^# _/ z - *(uint32_t *)helper_buf = size;
+ }; }9 l9 N( b/ O6 F' ?& m; J - memcpy(helper_buf + 4, data, size);
% u- Y" d% @+ O, K# L# y( N4 O8 j/ @ -
- r3 B5 V! j6 T: J# w# j - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);( `+ f. |2 M% u/ a
- WiFi_WritePort(helper_buf, sizeof(helper_buf));
4 J4 x/ Z. T- i* ?/ f5 `* P - len -= size;1 L1 W( ]; k& g1 h. G! \, Z
- data += size;
% ^! O* Z6 P9 F - }
/ ?: x# { b; a1 O5 ?$ X - *(uint32_t *)helper_buf = 0;+ ?/ T9 h! l. }* ~# Y
- WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束
& P9 G! G6 a8 F% A7 e8 Z - 9 p7 x3 G8 a" A
- // 下载固件 r) }8 U: J5 b3 B) A# s2 X
- data = firmware_sd8686;! j, X8 @* p9 F3 {
- len = sizeof(firmware_sd8686);8 ^& b$ d/ d! R' ~" K {
- while (len)" i+ Q# c# q: {+ W' q6 E
- {
+ r- H3 i8 C; L& o - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
$ P1 O. a! q: i' r; a. ^+ B; X/ ?# Q - while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数
) p' b4 Q- |2 @" ]$ B# [5 a5 K0 X - //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);' ?! x6 D2 |7 o( J
-
' |. x. ^; w: c3 D7 A# ` - if (size & 1)" x8 z; Q& J l- o( {+ P' y3 {
- {
. z5 z7 o8 J, H+ {, m0 \% r d - // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)7 t' {& b3 Q/ d% @0 G3 A
- printf("Error: an odd size is invalid!\n");2 H' }- f4 B( N" J# u: z3 E3 } v; i
- return 0;7 X( ]9 a' a ?4 h% G$ }* x% z
- }3 x1 K2 g9 f9 q
- if (size > len)
' _+ i# B! E$ `* O8 L7 Q9 z% _4 ^: F - size = len;' F/ ~0 x! X4 e0 L! X3 }5 S
-
- @; |# W+ Z! S$ v; E - if (!WiFi_WritePort(data, size)) B: a0 a7 m A2 g+ t! ?, G8 v
- {1 G- d9 H# ]; O7 b! c: A: b4 s: _
- printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);2 @: K7 M* W# w( p$ w: p& A
- return 0;
! A4 @1 q l' t: p9 H8 Z! m* E - }
' C# s: n% ~; ~ -
! e8 V3 f# X; C9 Y0 C+ D2 r - len -= size;) Z& Q" }& t) \+ y
- data += size;" _8 E8 P. f& |/ ]2 @% S
- }
1 D1 ?6 i0 C- a8 F# x- F9 r4 a' O - 9 y( ~8 w! K8 r3 p6 ]$ s
- // 等待Firmware启动
4 t( M# G- _& z& K - while (WiFi_GetPacketLength() == 0xfedc);
7 p x0 v# ^0 [9 W - printf("Firmware is successfully downloaded!\n");
' O- c$ e" `; x( T - return 1;6 E) j$ z$ C& ? J, |1 o5 i
- }6 Y) S! ]4 N/ k+ n
- 8 f9 V( S( u# Z; i6 u( S0 s
- /* 获取数据帧大小 */
8 Q# m- D4 \; ~- Y w0 Y - uint16_t WiFi_GetPacketLength(void)
* Q8 `) w# G+ j - {+ _9 ^- ~6 c; u0 n1 L) q
- return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);
; h H- Y8 `5 O$ n - }5 g- L& M* S/ b) O2 b8 K
- / h, l, @4 `5 b5 {
- /* 初始化WiFi模块 */$ k) t ?9 u3 q: W
- // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization7 [7 p& I3 ^* |, ~
- void WiFi_Init(void)& d) H2 F/ ^) j% p7 S, m O' D: F
- {! _8 V L; i. @$ o6 {2 C+ N
- printf("Initialization begins...\n");
/ O8 a" t q# k6 p3 D& @ - SDIO->POWER = SDIO_POWER_PWRCTRL;
7 A' e) u7 o8 o: F - SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz
" N8 S- Y# d: A% d# C6 g: f( H2 a - delay(5); // 延时可防止CMD5重发
4 h$ p" F' Q5 _7 S u/ s - u4 D) ]; G. Y5 K( s! t
- // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
0 W0 P- Q% J3 N* T& C1 s n# K - // 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)! M2 K8 {0 y* G3 `
-
* T3 V( n9 x6 @! b3 g( k9 H - /* 发送CMD5: IO_SEND_OP_COND */6 s% _2 ]9 S8 c. p
- SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;" b% y& A, G5 R0 b0 u& m2 T
- while (SDIO->STA & SDIO_STA_CMDACT);
) G1 i9 M& M. R2 X* E1 y0 F$ G; X - WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令
+ c8 h2 y8 H, ^( m - if (SDIO->STA & SDIO_STA_CMDREND)( U8 d) G, n3 J9 e& y! a& C
- {
% h( L! X# f5 |4 G1 b* e - SDIO->ICR = SDIO_ICR_CMDRENDC;' ^' W8 k0 E# G2 @4 O% `
- WiFi_ShowShortResponse();
0 ~, G+ T' @2 j( U1 X- p1 _3 c - }4 g. F6 U! p0 m
-
( P& o3 z: L0 g, J - /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */7 l6 E5 E( \' X3 K( T, f
- SDIO->ARG = 0x300000;
7 @9 n5 R% o Y& n - SDIO->CMD = SDIO->CMD;
8 N& }1 }4 `/ w9 H* Z) p5 d - while (SDIO->STA & SDIO_STA_CMDACT);: H' e+ i* Y# }. m
- if (SDIO->STA & SDIO_STA_CMDREND)' K m- _3 n- T' U
- {$ M+ |! q) ~ x4 c% C$ r
- SDIO->ICR = SDIO_ICR_CMDRENDC;* d% [. B1 m2 b
- WiFi_ShowShortResponse();
* J/ ~! n q! k) x' \& T9 z2 E7 I7 ` - if (SDIO->RESP1 & _BV(31)) ^5 d. ]; c1 m
- {
8 B) j7 J: X1 S' N - // Card is ready to operate after initialization& S5 Q3 D1 U3 a/ \0 U& ~
- printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);
* n, ?; y/ [$ L# I1 ?; x - printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);! U [/ L1 R ^; Y- ~
- }/ ~) c1 A D& p- B
- }
" V a g8 w( l8 {+ v$ U% Y( P$ G) S! ? -
: z1 P7 h$ p/ z+ G1 B' @ - /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */4 @% {- Q& Y0 J6 Q
- SDIO->ARG = 0;
5 U$ U) A7 J" M; |4 T - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;
! O& g2 B6 m! x - while (SDIO->STA & SDIO_STA_CMDACT);
$ k5 p3 T5 `$ y) w - if (SDIO->STA & SDIO_STA_CMDREND)3 O) \2 k7 ~. v$ z! {* ~
- {
6 b2 I% l5 c% X$ Q - SDIO->ICR = SDIO_ICR_CMDRENDC;% l$ Q7 |: V R" Q. y& k
- rca = SDIO->RESP1 >> 16;1 f1 l" g' e* E1 @1 r9 c: K2 W! l
- printf("Relative card address: 0x%04x\n", rca);
4 S$ N0 ]' V" B3 k% g - }8 D1 s- z; _- T/ A/ y
-
, l( Y3 X$ r" E d - /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */1 X+ I: g- u7 ^
- SDIO->ARG = rca << 16;& V9 F4 J+ c+ O
- SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;
+ {4 q$ p* `: O. a& ?# y1 M) `! U6 O - while (SDIO->STA & SDIO_STA_CMDACT);( Z. M0 @& _, @& @
- if (SDIO->STA & SDIO_STA_CMDREND)
% }3 r; w2 z: S: r# n/ _ - {, X: }! E7 i8 A! u8 W( I d
- SDIO->ICR = SDIO_ICR_CMDRENDC;/ O" C) A8 T9 e* G, f& W: u
- printf("Card selected! status=0x%08x\n", SDIO->RESP1);
" A; y9 g3 j/ S$ |; p% x9 v- |! Z - }" L# ^5 V" M' H, T# ~4 X+ x
- . j* t( _$ D. e" U; A
- // 提高时钟频率
$ I+ w0 v& b! M: E - SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
- E J: v: A/ M0 o+ l4 F! X9 o8 w - SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒
" `; e/ {0 l9 F' u7 u - //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz
5 O) k7 j+ R: j/ Q% ^ -
" F4 G9 h- Q9 x5 B - /* 选择总线宽度 (Wide Bus Selection) */8 }/ ^6 {" T2 i; S9 n: ~6 Q9 V
- // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)! q' F$ l5 A M6 @
- // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
, l2 R* P4 W* V0 M - WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus5 h/ e& `7 i9 N; o6 n
- SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
4 q! S1 |) \# ]1 O W( e& p - # r2 `; H& M- e# I* G6 q
- // 初始化Function 1
! U* e9 ?% v1 o! C" j - WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)
0 @) }2 s/ g# M! n+ i- Q- I - while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)
5 j) e) p9 O1 J( w' F -
; C8 s) M2 P- t4 m - // 显示CIS信息" X7 ~) O! w; H7 N: @
- //WiFi_ShowCIS(0);
9 T' Q6 d* E4 K+ j8 I& U - //WiFi_ShowCIS(1);( p* _! W+ ~. P( q
- ' w6 f1 g. l: p! K( h
- // 下载固件
3 `" f7 T- l! d7 D4 F - WiFi_DownloadFirmware();( D( l$ Z; Y% V" }" l" E( b
- 2 q6 V0 W- v2 x' j
- // 设置数据块大小为256字节
9 b+ j* I; V) ?' K9 ?- Y/ d* b$ N - SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
9 w4 v, E# V1 U6 x: |3 K - WiFi_SetBlockSize(0);- I6 g; d" R- V8 ~- s5 M
- WiFi_SetBlockSize(1);( m" ^) m$ t! [
-
1 l2 x4 J' A, }( H( `* o8 z( H+ C: r) u - // 允许发送和接收
+ p. w/ q$ e; h8 X7 L - // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间2 J7 d. m8 c3 D" V4 z
- WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);$ a8 |: `+ r- N5 g% D2 ?
- }" b0 C' ]; p9 {, s) e' d8 D5 m) o
- 9 F2 q& R& D( M k
- /* 获取或设置密钥 */7 e" f6 ]7 a, O6 l- L; O9 c
- uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)
7 p. c$ l. d3 F7 ?1 }; \* Z - {
# [ F s* [0 l6 x) X5 U* o0 a - uint8_t buffer[256];7 X' j7 O$ }; @) A, t2 D/ X* a0 Y; [
- uint8_t ret_size;
* r9 R7 x% s5 B7 ~8 R - WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
9 ]+ K$ K" v5 D2 C$ J4 @0 z, x% `3 C - cmd->action = action;
& g* v/ |& `4 l U9 k5 o& L - if (action == WIFI_ACT_SET)
3 P/ O3 q& b9 t" g - {6 T. C5 l- n2 @/ i' z; o
- memcpy(cmd + 1, keys, size);
2 w0 v: X* G ^6 o - WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);& g5 P/ [% F M/ C+ y; n
- }- v- w+ a0 H, \
- else5 g5 ?0 k* E4 A. Q" y. Y4 W! q: w0 S
- WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));# Q' B5 r. O: E5 v/ @2 m
- WiFi_ReceiveResponse(buffer, sizeof(buffer));! I- s: X1 D" ^8 u
- 3 \" M$ j" [ Q; |, t0 U1 }% k
- if (action == WIFI_ACT_GET)
2 ?8 N/ H" p, X7 r - {# B9 b, Q1 P3 E; b ` I) N9 |
- ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);" F0 W; Y- C0 I* m: m* @; W
- if (ret_size <= size)
4 r3 D, m, c9 o% w - memcpy(keys, cmd + 1, ret_size);' r* Y+ E) L7 r: x" z
- else
+ V6 m' c. T! d0 [1 v9 ~ - printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);
5 S3 y1 M9 q/ W- U - return ret_size; // action=get时返回读取的数据大小
( H0 p, B3 L6 q - }/ |. Z. z c" d9 f+ F( \
- else
/ G! }, [; F) w* y+ v - return cmd->header.result; // action=set时返回命令执行结果值( O' ^( _% t0 ?7 b4 M
- }- J4 @6 d. z+ S% f1 j
- # b3 ?2 P8 S" L$ Q7 A
- /* 获取或设置MAC地址 */
. W( D$ y: b. \+ v$ O7 J - void WiFi_MACAddr(uint8_t addr[6], uint8_t action)
1 e5 Q, c% P- ?* e - {6 F1 v) t0 T: ~. P) @; @
- WiFi_Cmd_MACAddr cmd;
- N2 B" a% W8 s* k1 P - cmd.action = action;5 S4 F7 a, l4 N% S; @
- if (action == WIFI_ACT_SET)
! Z" K5 c) _: | v4 H - memcpy(cmd.mac_addr, addr, 6);
& \+ ~) i- l! r7 X -
0 m- [& v, f: i( J/ e0 x - WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));
, @. x: {# G8 S" W a4 S: [ - WiFi_ReceiveResponse(&cmd, sizeof(cmd));6 \+ i3 w+ y7 m- @' i6 w
- if (action == WIFI_ACT_GET)* U+ a) A0 T$ {$ m S- X
- memcpy(addr, cmd.mac_addr, 6);, x( \) p6 u0 Q7 b% O
- }
4 c( m" \& [ X5 ?, x8 ?' o
- B* V+ H" ~3 R! o- ]0 c7 r- /* 配置MAC */
# v9 s/ e8 E8 p) S - void WiFi_MACControl(uint16_t action)$ T- Y$ I1 h: e5 G, w8 F7 R: t
- {, c* @4 w/ Y/ _/ y
- WiFi_Cmd_MACCtrl cmd;
- N+ [2 l, V" s. U - cmd.action = action;, [4 n( _5 L$ y( ]$ w( Q1 u
- cmd.reserved = 0;; ]4 P$ Z$ T' J( O
- WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));, n4 M3 A# J8 |
- WiFi_ReceiveResponse(&cmd, sizeof(cmd));- V6 L5 Q( J( \3 g
- }8 O0 p1 m; U `1 g
- 4 s+ o0 W5 @3 c; X
- /* 获取滞留的数据包大小 */
7 n. P5 v/ I, H+ o, z: P - uint16_t WiFi_PacketPending(void)4 r/ p; h# I w, @, [: u
- {1 u8 l# D9 O0 e! c5 ?4 A$ \
- return wifi_pending_size;
& w6 s# H/ Q( x) \ - }
4 J1 W$ w& B1 s& T x0 K' B2 k5 A& d/ I; ?
$ r6 K9 Y7 Z1 K+ ~- /* 准备好超时计时器 */: U7 w. d, N+ }. k, v/ J' i
- void WiFi_PrepareTimer(uint16_t nms)7 i! g* P9 A% ^) G! u$ x: k
- {( l/ O0 b3 w# K
- TIM6->ARR = 10 * nms - 1;1 R; S4 {: `) i" K6 j
- TIM6->PSC = 7199; // 72MHz/7200=10kHz
% M( T' ?0 |% g# B) |) B! @5 o - TIM6->EGR = TIM_EGR_UG; // 保存设置
1 j6 T) H! ?0 p$ A8 S' ? - TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位! A( J0 q) ]! [) s/ F- x: T* K0 |
- TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式) ~' S2 `0 i0 }: Q( ?
- }
3 C5 b0 @; x$ J( o1 A0 U3 Y
5 y* h" J3 [" O6 o5 {- /* 读寄存器 */8 F2 ^, T5 [- O& J. }! p! O" [
- uint8_t WiFi_Read(uint8_t func, uint32_t addr)
9 Q" Q6 {3 a/ v2 `, z, [ - {. @; l7 \9 ^* P0 p: [! J- L
- WiFi_SendCMD52(func, addr, NULL, NULL);
% s4 h" c6 ]/ E3 z W5 [ - if (SDIO->STA & SDIO_STA_CMDREND) m! p, K$ o7 C) d$ W
- {% e% j! P) P' a, K
- SDIO->ICR = SDIO_ICR_CMDRENDC;- B7 t, D0 g9 U5 q
- return SDIO->RESP1 & 0xff;, l* G! h Q# x# b. n
- }
$ d6 E) A; h' G/ E/ ~ - else% B: E9 O3 H# e; {, d' J. e( {
- {8 M$ L' P) o2 U
- printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);9 M: k- `7 Q+ k1 X/ U0 Z
- return 0;8 K6 Q: L$ u- {5 T( h1 L1 |, ~! y
- }8 Z3 \0 T% }2 g7 O8 m" p/ [' P
- }1 F! h- Q+ I" l/ B6 I: @
0 ^% Q7 I: [* e8 ?- /* 读数据 */: G% p; q' A: u' a7 @+ i" m$ c1 N' }
- // count为要发送的字节数或块数, bufsize为data缓冲区的大小
1 \4 X- A7 G3 w9 [- M - // bufsize=0时, 只读取数据不存入缓冲区, K+ ^" D& S/ s9 t$ ?% q! V$ @6 c
- void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
! R. O! ~2 _4 X+ z& M U' E% ` - {5 _6 r. ^5 ~! T) f
- uint32_t len, temp; D* z# w1 @# [* f
- if (flags & CMD53_BLOCKMODE) {0 q5 |9 G) U8 N* R9 ]- H$ w
- {0 _! x) c& I; h2 {- R2 K
- len = count * WiFi_GetBlockSize(); // count表示数据块数$ W; K( U8 k; Q# U2 x
- SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
$ E+ [6 ~, R( m) W - }, [, P/ v/ Q2 _8 J ]2 T
- else
6 y9 o" z; L( ~/ q1 B - {3 `. Q9 f; O. o& X ?& C9 c
- len = count; // count表示字节数
, G5 Z/ C4 l. A3 P' | - if (len % 4 != 0)
* E$ ?3 z5 t" ? - {9 D& A) w' g4 E! Y P1 S# U
- len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍' S; o& P1 o6 `/ h
- count = len;' T9 J/ ^" n6 e2 C6 h1 N! w: B
- }
' `" K; h) Q% X: B5 i' g! k - SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式! I) X4 r ]2 Q8 n- z0 j/ p
- }" ?2 ?% V5 }- `+ \
- SDIO->DLEN = len;
# k( F v' i3 w7 P7 S, Z6 S - SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机7 {$ ^, Y. N' K: J& _. ]+ l
- 8 l5 A- w. v. H
- WiFi_SendCMD53(func, addr, count, flags);: m* r" O, i0 Y! m+ C6 A; f: R1 {
- while (len)( t# s- R" \; F$ X s( c3 H* b
- {
* |0 _8 z" p( l1 r8 u+ ~1 c - if (SDIO->STA & SDIO_STA_RXDAVL)
! Y4 {- q# h+ t* k3 o; ^ - {
; p9 p; x. f" {3 y - // 若有数据到来就读取数据
' U" r! v) X7 m9 J - len -= 4;
4 X* v4 x* B) y; x - if (bufsize >= 4)
) F: P. V& p( ?2 \ - {
' M4 n3 J, j N" g3 e4 m - *(uint32_t *)data = SDIO->FIFO;! S7 d2 }' s, K) b3 j' ]$ z0 {# h
- data += 4;
, V( u6 l; z. | q - }9 d% W5 _9 F1 I1 e' ^* t
- else
, X2 M: w% ^" f/ z - {
: t* h2 R8 |" L! j - temp = SDIO->FIFO;- T2 |3 A7 r* g' F$ ^' b
- if (bufsize > 0)
' ?+ E* E. p7 {0 w+ J# v5 L' w - {
2 o( W' j5 [9 A0 B8 v: ~ - // 写入缓冲区最后1~3字节
: T, k$ d8 @9 g% A: i# T5 l: J - memcpy(data, &temp, bufsize);
1 i3 m% ]9 Q9 ]# U, u - bufsize = 0;: y& q* ~# B% V, M: i9 B0 w
- }
& c, ^1 n; o+ e, f! r - }
; p ^# {* O% B" d. G+ S - }
9 D, o) r( E! P# i* ~9 B - 4 U- B8 Y$ t- x: [3 v0 _
- if (SDIO->STA & SDIO_STA_DTIMEOUT)( u- r0 j _, T8 C
- {7 G. g5 a5 ^, A! e; [$ f' ~
- printf("Data Timeout!\n");) p- w# q7 r1 n5 O# c
- break;; S v* G+ u; s. S
- }1 C7 a5 G0 I) ?, m; d
- else if (SDIO->STA & SDIO_STA_DCRCFAIL)
1 A# X! D5 F5 Y6 o$ n9 | - {
+ f7 B5 Q0 L7 [: E8 C n' } - printf("Data CRC check failed! %d bytes are lost\n", len);
# ~7 W- t z$ e4 M1 C% F, R - break;
, `/ d- d5 D" i# K - }% O% f$ U; G1 f. Z/ e
- }: `8 Z, G: Q+ `5 e, t8 f
- " u u+ [: O8 ?/ W" H, X/ Z. E
- while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));
6 d, j$ g8 t" i* X+ e$ s - SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;
2 p8 V3 ^, t( i8 D - 5 {- W* r. Y0 q1 m9 B/ P* E
- SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;2 [3 }; R7 T. @% t
- if (flags & CMD53_BLOCKMODE)7 l0 F, c: Q; C% L# j6 f- t
- SDIO->ICR = SDIO_ICR_DBCKENDC;
/ V3 ]) T1 Z1 x4 f& r - 9 N! ]; e0 C. j: i# {
- // 通过判断SDIO->STA是否等于0可知传输是否成功+ b/ P! B5 s! c! @) r/ ~
- }
: I) n8 i! }: [0 X" M" j4 r5 {* s
. v* Z- \9 K2 A2 P( X M1 X& Q- uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)
" A4 k4 K* A7 T- z - {
2 K+ B$ o) Z$ D# S. y - uint16_t block_num, block_size;
' s* k$ |# }7 y f1 a: L - block_size = WiFi_GetBlockSize();, U% m& u! ^' L3 ], \
-
: M" b$ N) S8 F - // 读取数据
% Q; o+ b+ i9 b# m - WiFi_Wait(0); // 发送CMD53前必须IOReady=14 u8 @7 U( T1 C# k8 ?0 g6 D
- if (size >= 512 || size % block_size == 0) l3 ]3 f3 h4 L. ^/ P6 G: y+ E2 X$ D
- {- k' y! J" _! \7 g
- // 采用Block模式传输& S# ~. r* _6 r
- block_num = size / block_size;) h) g5 m3 M* `9 M8 P1 K- Z7 e
- if (size % block_size != 0)
+ h* [; v0 ]& J. ~: U6 J. k: I$ F - block_num++;
X `$ S: u4 d% M - 7 ^7 y6 J5 [/ q" |7 l/ J4 R
- WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
% J8 I- X$ `7 W - }3 b2 p& \- G/ }4 Y, r& P
- else* {' g, A* }$ ?' T& ^ ~ z( `2 ^
- WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);
% t" @2 ~6 {4 k3 E5 P: ^2 k - 0 E% c3 I2 A, D! l/ N7 u* w
- return SDIO->STA == 0;
$ X. N9 ]/ s& ~+ ], Z - }7 U4 V- s/ g. x# H8 {, b/ L
- : z& f1 w6 ]# O2 J
- /* 接收数据帧 */. R2 C5 k* X8 K# y4 V) X0 W
- uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)2 D- p) d) u8 T3 t0 s6 Q
- {
. {2 k7 J3 E! L! z( [: I; U - uint16_t size;4 {! T1 L. P4 \" K& k
- if (wifi_pending_size)
/ m7 {! @# [+ |+ u - {5 b9 ?9 P9 ~* J3 A; d$ D8 ^
- size = wifi_pending_size; // 先读取滞留的数据包
M5 ~9 {- S& c' R3 n1 _ U - wifi_pending_size = 0;
2 {, Z) s+ i4 g+ Z0 X - }6 a& m9 r% Y1 U# v3 b0 f4 M8 r$ s9 f
- else
1 Y; l0 |3 \" c; a( J% E - size = WiFi_GetPacketLength();" [' _- m3 }2 y, B
- return WiFi_ReadPort(buf, size, bufsize);
; B) x* k, W7 ]/ V. g - }
1 l+ |8 o* |2 c3 o
' q; ^2 V# {# y) T* j# O- /* 接收WiFi命令的回应 */
, G9 b. b1 e4 G2 p7 N) { - uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)
2 |9 c- W7 h( p& }' Q( A6 L8 P - { E% S: a" U* M( N
- uint8_t retry_cnt = 0; // 重试次数
- r: w( O0 X0 |6 i$ p - uint8_t wait_status, resend;
6 s+ `. X; G& x& ~& K9 p5 n$ r7 P - uint16_t size;
' b2 v, m G; D - WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf;6 u! d! U! [* _4 `
- WiFi_SDIOFrameHeader temp;8 e# E) w" X: h
- 1 }2 a, U9 v+ F5 s
- // 等待数据准备好
& p5 U, A7 E$ X - do
$ I" Z1 i9 k+ m' r( g' i, x5 r. { - {$ o( n- W; u0 j: W. h' Z0 v0 p
- wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);2 F/ D5 s2 C, [0 r J, T/ m. G3 q1 f
- 3 w9 P; [: ^* T. R
- WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息
5 M; V! R3 h# q/ |* X1 B0 R: d/ v. \ - if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
; e' i$ I \! G) `& `5 a0 u - {
2 M% c. t3 e' Q5 x% G - // 若读到的是一个数据帧, 不是命令回应- e9 x7 {. b2 m. p/ |/ j
- // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功
& }. u' W V5 N6 V7 s4 ] - printf("A packet of %d byte(s) preempted the command!\n", temp.length);$ v( F. m/ u7 j9 q3 l% o" {& j+ m. q
- wifi_pending_size = temp.length;
# `+ Y, H9 K/ ~$ v* |& s3 _+ C5 P - WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算
7 H( X1 d. a# s! i5 q: I - resend = 1;
# Q: t( c+ }4 U8 e - }5 m7 ?5 G) P! l; o+ e, w
- else if (wait_status == 0)
4 T+ u; p0 `8 s. t - {2 B1 s v# ?( M2 r5 B2 V% z4 h
- // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)
! w+ ^6 }3 P; I( B - resend = 1;
: Y- y6 o. s' E" ] - retry_cnt++;* v2 R9 @3 X2 |
- if (retry_cnt >= 5)
6 ?6 m4 P6 x# I: H - {$ b0 b* t/ g6 v. K4 s0 f
- printf("No response!\n");/ r, s6 h; @6 z3 Z. X/ {
- return 0;) B+ | R# e6 O6 f G; Y
- }
" Z+ x% u$ Q$ a: y! }, H8 y: Q - }9 X1 ^+ _: ~, S9 J( c) s
- else
1 P' X u% _% a9 q1 S - resend = 0;, _" y# m# @: i: u' N
- 3 z* @8 \0 D% d1 n% ~ H3 \4 s
- if (resend)
( N3 O! U: T! e4 c5 v - {
% Z- I) o* B% k! z - if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND)
9 B# I. W. f8 g- ? - {
5 P' P, H2 }3 @" U9 P8 z$ U - // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait6 i( b( F: ]8 v
- printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);: o# c, ~2 W8 y2 h |) @
- WiFi_ResendCommand(buf);
% l) }0 U2 }! q' n! n - }
0 k0 q* x( k9 t! ?5 ^ S - else" W6 {6 i9 J+ Y7 _( S' m/ `
- return 0; // 若buf中的内容不是命令, 则直接退出
% j* o2 S2 D' N3 ?$ t5 M2 i - }
1 T5 V9 i* z9 ~; x8 A3 o3 ` - } while (resend);
4 v. O3 }3 b7 y- c1 @5 X - + \9 Y9 z- x! Y: B2 b$ g
- size = WiFi_GetPacketLength();
! Z3 k5 E, K* W' u; q, T3 X6 a - if (size > bufsize)
# ], \2 x. ^) V( H9 x; F: B2 ~; ~: W% s - printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
$ o+ o8 z ~/ K- I3 {' s - return WiFi_ReadPort(buf, size, bufsize);5 p* A2 v" I9 G; B
- }
0 i, I. a9 ]& n0 Q1 U$ @' u; p% { - & e8 {! b: H( c4 U- w) i
- /* 扫描全部热点 (仅显示) */6 U) D2 I7 g1 h7 k- @# L
- void WiFi_Scan(void)
* H2 y" Y/ b6 X - {
8 K6 E9 h; h3 S& S3 q) i0 X - // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组
- u2 I1 O2 A5 [7 L( y" F - // Stack_Size=0x00000c00
0 q' U- l) w5 t ~( C& b2 o; ? - uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放- C6 x8 z+ v/ _1 z8 m' m
- uint8_t i, j, n;
# N( B2 @1 T: V$ ^5 }! _ - uint8_t ssid[33], channel, wpa;* m. l- ]/ }' s! x @! O
- uint16_t ie_size;9 e0 [, I7 ^- C& C" D4 d
-
+ s! |. {' ^' ^# Z$ z" @& ` - WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令
" i& K; U/ H! ` - MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));3 K' J: B7 e4 D4 T
-
A" T" f4 y5 k6 G* q4 G - WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;4 X3 q) H" J0 N' ^' V% m
- WiFi_BssDescSet *bss_desc_set;
! P) o- y0 u- }. ^! R* V4 B - WiFi_VendorHeader *vendor;4 E3 i& j* J2 B+ ^; ^ `# L4 U
- IEEEType *ie_params;( n1 X K9 h" }( ?
- //MrvlIETypes_TsfTimestamp_t *tft_table;1 r2 R' I; m" U. b8 R
- ! T d5 k" d. e- u* u
- // 分4次扫描14个通道; V7 \/ ~9 M- ?; H
- for (i = 0; i < 4; i++)
; P! Q L7 ~- k% \$ F2 O - {
* S' R5 ^% v7 ~# k7 B - cmd->bss_type = BSS_ANY;
+ Q: f8 F1 r% s j: e - memset(cmd->bss_id, 0, sizeof(cmd->bss_id));/ q, q# G" }2 Z1 y _
-
2 t9 F" d6 H U - // 通道的基本参数
+ ] n4 O( Y# Z9 y5 l+ v - n = (i == 3) ? 2 : 4; // 本次要扫描的通道数
+ B7 M# i& w' o9 A6 b# {$ K - chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;
9 U7 q i. Z& n5 I* ?7 `$ L; \ v1 m% | - chanlist->header.length = n * sizeof(chanlist->channels);
+ b) U+ ^& s H - for (j = 0; j < n; j++)
* v2 K* b5 D9 } - {
1 u5 Y& s' R6 z3 Q/ s2 w7 I' c - chanlist->channels[j].band_config_type = 0;
6 Y& q/ w# v% ^0 {7 R - chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号
' a2 V4 K% |- ~5 r6 H+ P - chanlist->channels[j].scan_type = 0;$ z9 ~1 E% W" O
- chanlist->channels[j].min_scan_time = 0;
6 N, R7 u+ A8 E; ]6 `/ H% Q2 A) _ - chanlist->channels[j].max_scan_time = 100;% E) i1 T) _; w1 C# N$ V5 O
- }% s ?9 i, S4 V2 {) k& }& h4 l
-
$ j# L6 J& b1 r2 Y, S8 V - // 发送命令并接收数据
) x0 O7 }* ] k( N: r - WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
8 {4 B0 J2 L1 V9 ^: e; \: Q - WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉: i* [+ q& W/ r
-
, q% Q0 B4 M1 D- m# u* c - // 显示热点信息, num_of_set为热点数
1 j7 a# l( T, D# a; S - if (resp->num_of_set > 0)
0 A' c% q, _5 r& V - {- `( j$ }- ]& J* l- j
- bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));# `' e0 a1 { o& L2 h/ T
- for (j = 0; j < resp->num_of_set; j++), [ r0 ~9 B, s6 ~
- {% r0 ^9 l9 K8 r" x# p7 m* l
- wpa = 0;" Z' Z# k6 i6 g+ _/ P
- ie_params = &bss_desc_set->ie_parameters;
3 ~. p+ C* e3 i" F! |* Z" w/ u6 F - ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));4 I+ G: h! ?( q- b7 \- `
- while (ie_size > 0)/ p. A, m' O# C7 `
- {
8 _% X' I9 c e3 \ - switch (ie_params->type)
- E' `3 L+ P- e5 \* Y1 ` - {
: J' L3 P7 B5 d! k( ?0 l - case MRVLIETYPES_SSIDPARAMSET:
! ^! w+ V, N% \" \* X: k" n8 E$ I - // SSID名称
* t5 l# J V4 z5 q& |8 `( @+ o - memcpy(ssid, ie_params->data, ie_params->length);9 K1 L4 F% l" p8 a( Z A
- ssid[ie_params->length] = '\0';
5 c* K! S, a, w: f. w7 J - break; z0 _* V$ k9 O+ v
- case MRVLIETYPES_DSPARAMSET:! k. @/ C" |+ P: x" g
- // 通道号, }' R+ |( M# A% _% ~+ a% X
- channel = ie_params->data[0];) n/ @5 ^& k& f6 ?' f# I
- break;3 Y% u$ U$ B& ^. j. X* i" {
- case MRVLIETYPES_RSNPARAMSET:: C2 i, J3 I. q
- wpa = 2;2 N1 D1 n& ~3 b& F, p
- break;6 Y/ ~. s9 _' T7 [/ `& k
- case MRVLIETYPES_VENDORPARAMSET:
! d' j' b& F- ~+ U, \ - if (wpa == 0)
5 K% l. r& ]1 [2 n* H - {
% z5 z1 { H) { - vendor = (WiFi_VendorHeader *)ie_params->data;2 D4 [$ ?: h' O2 G+ m9 _0 O/ p! b
- if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
& p! L. L: M+ y1 [+ i) @! `/ u - wpa = 1;
4 y& I) |0 m) k - }& l* E* p' k# e0 T
- break;
- l# h! _: o+ m+ @9 Q - }! R+ u: o2 L: y. J9 {) C
- ie_size -= ie_params->length + 2;
2 j+ d" ?+ g/ u - ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);
0 _) e- \2 d4 z+ `7 K - }
! h# _3 W+ \/ a) ?& R - if (ie_size != 0)
$ |3 a& n1 ]* b. {* h8 {! b - printf("ie_parameters error!\n");
& ^5 x8 z: Y e7 Z -
6 `. @) _! i3 L& ~* Y - printf("SSID '%s', ", ssid); // 热点名称) q6 W1 P$ }( s r* g4 h5 N
- 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地址
) [$ Q( ?7 w$ p0 L* _/ B! r - printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
# s! m5 G& Y3 I7 Y1 r b+ p3 p - //printf(" Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);% [6 K. E7 w3 P! }7 C
- : `8 G7 r" V( U- D* `! b. `4 X
- printf(" Capability: 0x%04x", bss_desc_set->cap_info);
/ ]0 ~* L, b4 l) j4 ?/ n - if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY)) I( f. ]3 _: q# t
- {
6 z" U0 }0 |& \4 Z& | - if (wpa == 1)
" x5 j, d/ k- o) s3 V# p - printf("(WPA: ON, ");+ n7 x2 I( e7 B+ C, ~" S' u2 m
- else if (wpa == 2)! U) ~3 E$ z! K; l( n9 Q" A
- printf("(WPA2: ON, ");. K6 f" D2 u j- w c9 r5 t3 q
- else
. j1 q$ Q: d( O) I+ h2 d: e, ^4 M4 r - printf("(WEP: ON, "); A. p7 l" z5 e: f0 J2 [ \$ z- |
- }
0 Z6 _- g9 T- @7 o; i v, Z - else
! b9 I$ i' V/ T$ y; w. _; m0 g& M Y - printf("(WEP: OFF, ");
- u+ J1 N" v3 Q9 s - 2 E L, V; G# b! n: V
- if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS), l" A, C, v5 ` n) b& m7 b
- printf("mode: Ad-Hoc)\n");$ Q" E. \9 h$ _8 l
- else# e5 f/ h! e7 E! [
- printf("mode: Infrastructure)\n");0 F/ W! W O, M# B$ S2 L9 f" U$ w7 b
- & j" f4 s- m: H4 K g: K7 i* b
- // 转向下一个热点信息
4 E6 l% V# {- x) D$ b0 z L - bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);/ t7 b- O4 Q# b9 U- [; |
- }0 W% }- Y. X4 i t$ j# t
-
7 D" x l' I! n% i# B+ M- E% h, V - // resp->buf_size就是bss_desc_set的总大小
; G+ F# _+ d6 O, n - // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size
) R+ F2 I% i; V - /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;: Y$ |2 W q$ R3 D* G N% p
- if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))
8 E+ Q, p; P/ v) c* @5 o4 E- H - {# W5 L, M# a' P; M
- printf("Timestamps: ");
. `) L2 a R0 J1 C2 i5 c) @ - for (j = 0; j < resp->num_of_set; j++)# w# U; _2 A3 U4 ~+ S9 Q9 y
- printf("%lld ", tft_table->tsf_table[j]);1 I* i0 T/ Y) Z
- printf("\n");. T" @/ j, c( r
- }*/
# t7 I: F- x; x \; B -
; K- ~6 y& [) k& U4 r1 T$ e' n0 W - // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table
& x/ P: Y5 Y; t$ Z1 m8 a - //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)
1 }1 N9 [, Y3 i H2 q i - // printf("data end!\n");
% E+ m- s6 I" M# {4 b - }. Q9 Q" Q8 T: g6 {
- }
; j( Y3 T0 Q P' W, R - }
& Q7 A5 B; z' m
8 R: G3 I9 f7 W4 \8 F- /* 扫描指定名称的热点 */+ M4 ^' a% Q5 l! Z/ D& q7 |
- // buffer用来存放返回的全部结果, 因此bufsize应该足够大& u/ s' a6 F7 C/ H) `) \: w1 W
- // info用来存放从buffer中提取出来的一些常用信息
+ |* k" M& L, f1 S0 A# e' b: d - uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)( K; p! U( [8 ~8 L8 r2 Z* ~( Q
- {5 @: V& S' [+ @0 L+ i1 j
- uint8_t i;
8 b1 Q' p3 |4 F, z9 N# ] - uint16_t ie_size;( ^7 ?3 L5 [3 o/ ?: j
- WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;
# n O( g9 z6 c( I8 g. p - WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;; `4 G) T0 [' y3 p- ^0 O
- WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);. o$ W$ e3 O5 d4 I& g- t
- MrvlIETypes_ChanListParamSet_t *chan_list;
& L9 \6 e/ C; U. ]# | - IEEEType *ie_params;
0 R" I& X+ F: M( ? X' k+ H* Q - WiFi_VendorHeader *vendor;
9 D4 s, r/ n8 |% M: p# G - # X! d3 O; b. n* E# ^: a
- cmd->bss_type = BSS_ANY;
& c* k! u! |# Y5 _ - memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
$ |' G! {9 T' M6 ` -
5 n- I8 ~0 o8 S' g2 u* Z& K - // 添加ssid参数# E% @; M6 _5 Y1 F
- info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;* f' x1 A4 W- @& U+ L) T6 P/ B- r
- info->ssid.header.length = strlen(ssid);
& _% [2 w) W. B9 r - memcpy(info->ssid.ssid, ssid, info->ssid.header.length);
5 S: b8 E; w! M* \* }- t- |: j. X - memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
2 O- @4 q9 _: c! `0 Q; g - 6 O( {' ]1 w5 m' _( g! ]2 R/ k
- chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));
2 _" h6 B3 n, J - chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;3 |* P$ p( l5 {- ^2 O
- chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道6 g) U! Y6 p! a6 Z @
- for (i = 0; i < 14; i++)3 O9 f c1 h) c' g( P: N) k& R
- {
( w9 g. J5 ^# h6 g [ - chan_list->channels[i].band_config_type = 0;
8 P1 ?0 c( `) Z4 S, W - chan_list->channels[i].chan_number = i + 1;
6 k' L: ~9 U8 ^1 i* V3 t1 y - chan_list->channels[i].scan_type = 0;. I9 B7 L8 F/ f# C" r" J# s0 q( z
- chan_list->channels[i].min_scan_time = 0;! `! ~' @4 ]/ y+ b; ^3 d
- chan_list->channels[i].max_scan_time = 100;: _1 r- z; [4 h& ~6 Y
- }
! \6 |" l7 {# B5 P7 ^ - & l3 f7 K2 F9 C* W) r* M
- WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));/ z& s# u; l1 u6 M8 S
- wifi_timeout = 3000; // 延长超时时间6 _: E7 _( J& r2 S N! L }8 j
- WiFi_ReceiveResponse(buffer, bufsize);
) t3 N- F" ^* [3 \( N - wifi_timeout = WIFI_DEFAULTTIMEOUT;
" z8 l3 T$ ^7 G8 g/ i - - ]% E( O7 p f' v+ b
- if (resp->num_of_set == 0)+ P+ ^& A8 ~4 h, s' W
- return 0; // 失败
5 \0 S& F1 p t. @; b& ~ -
$ ?+ u, _7 K! Y3 f- |) A- b" H8 b - // bss_desc_set以扫描到的第一个信息项为准
7 E8 g. K& h* c3 R - memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));
* a& a3 O( T5 t - info->cap_info = bss_desc_set->cap_info;
& e8 P1 F9 q# P: h) Z- X. \ - info->bcn_period = bss_desc_set->bcn_interval;( E |6 }! y5 D
-
/ i# N8 S% d! z# p+ `4 P2 e - // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)" `9 P) o5 A( \, `
- info->rates.header.type = 0;$ i( C" o! K; X- L4 Q
- info->rsn.header.type = 0;
8 I2 Y. Q8 G- N/ Y' q8 t h - info->wpa.header.type = 0;: t, E G" V: \( v
- info->wwm.header.type = 0;. q0 X: W; W1 B" u8 G- A6 {/ n! m
- info->wps.header.type = 0;
. b# G' w$ \ ^ - * B7 M% H% E- y
- ie_params = &bss_desc_set->ie_parameters;
+ m7 G2 [% D8 n+ j+ u - ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));! m! d8 q. f* b$ O0 l/ {
- while (ie_size > 0)+ Q% ]+ l7 a F* Z4 z3 y% ]
- {& `8 A; w9 H; X9 [% V, o5 ^ a) k6 p
- switch (ie_params->type)
- ?0 \, Y; C0 J8 X1 U/ n - {
& K. Q- G0 l/ \, H - case MRVLIETYPES_RATESPARAMSET:& X: V1 ^, u a: {
- // 速率( a1 G; E- w. \
- info->rates.header.type = MRVLIETYPES_RATESPARAMSET;) L6 Q$ a' {) B' L! Y1 x* }' a( q
- info->rates.header.length = ie_params->length;
9 y! ~5 q7 I1 I - if (info->rates.header.length > sizeof(info->rates.rates))
5 W1 z1 C4 _% M1 T- {5 T - info->rates.header.length = sizeof(info->rates.rates);
2 [% v) j: l/ P3 y: M3 ] } - memcpy(info->rates.rates, ie_params->data, ie_params->length);
% f: x6 p- q6 D - break;
3 H( @+ f2 M' c8 O% N) W - case MRVLIETYPES_DSPARAMSET:8 Y8 `% } _) B8 o, W* e
- // 通道号
( k1 d o# U6 }* r6 g" S - info->channel = ie_params->data[0];
( P( S7 |0 k: X V - break;2 c& U/ q7 F1 _# f2 n
- case MRVLIETYPES_RSNPARAMSET:
3 @; q" t2 r) b( }! f; t7 c0 { - // 通常只有一个RSN信息 (与WPA2相关)' S7 J+ ^" e5 I u z( @( r
- // printf("RSN len=%d\n", ie_params->length);
! i! {$ I' m6 Q4 r4 M4 S - info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;6 g8 p+ n% C% w/ Z4 V
- info->rsn.header.length = ie_params->length;( {8 H& \- F `0 T( ?& i, z9 ^
- if (info->rsn.header.length > sizeof(info->rsn.rsn))
" Z: e* ?( u; s8 X/ n) b - info->rsn.header.length = sizeof(info->rsn.rsn);
+ p# z! C1 G/ y' u8 O5 i - memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);
# f/ ], ^6 j Q$ F% I - break;
, U% Q8 n' U5 B) ^& N W k' E: _8 u - case MRVLIETYPES_VENDORPARAMSET:
* F6 |+ s+ ~ w3 T6 X$ |4 z - // 通常会有多项VENDOR信息 (与WPA相关)
# v e; I) v" p6 M6 `! X2 { - vendor = (WiFi_VendorHeader *)ie_params->data;
- m- W2 R& l+ W `- P R6 U - if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)9 |3 l% y& J9 Q% N$ h5 E! W
- {3 C% i8 n: a$ d
- switch (vendor->oui_type)
, l8 W: S @. E) Y - {+ P) @9 t. N: {. w! T3 ]
- case 0x01:
+ y4 }* J6 c: [5 Z/ s - // wpa_oui8 c# s6 k! f2 a
- info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;& k3 `/ ?/ u, P
- info->wpa.header.length = ie_params->length;
4 O- \ r5 a. k - if (info->wpa.header.length > sizeof(info->wpa.vendor))
r3 V) P; I0 ^1 S - info->wpa.header.length = sizeof(info->wpa.vendor);
; r; c* @+ ?7 m" F6 b- u7 ~ - memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);/ j+ F2 M) K4 e
- break;3 D7 n9 p8 e1 x* g! u
- case 0x02:
9 N! d" E. k3 N: l7 _3 ^ - // wmm_oui$ i4 |8 r! L: `8 P/ E
- if (ie_params->length == 24) // 合法大小
8 j% q, m( s) a- b5 G, _+ |% g I( G - {; j8 L, c9 r+ r; B# [; }) x& U
- info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;
9 Y" R' X9 q6 l - info->wwm.header.length = ie_params->length;
2 U1 X$ S" M- U& l( S - memcpy(info->wwm.vendor, ie_params->data, ie_params->length);' s% A/ ~. B' n d9 k
- }( o$ j# x' e& O% y" q' O0 m2 T, w
- break;( d! m# ]! u4 d
- case 0x04:" T. ?* t; e! z0 p2 {8 ?6 ?. z' @
- // wps_oui
1 Z) s: ]* ?5 j4 M4 j# k, w( c - info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;
/ R; |) e, z. \ - info->wps.header.length = ie_params->length;, o, ~+ |/ c' i+ |$ A
- if (info->wps.header.length > sizeof(info->wps.vendor))/ M2 p( p- t8 e! A: K& q$ ]
- info->wps.header.length = sizeof(info->wps.vendor);
) N7 Q/ S( i P, [6 U6 e' T* P - memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);# w4 z9 ^, _. U/ S1 W
- break;! ^7 q7 R6 G$ G i! c! ^
- }
( p c3 G% P K8 B K - } t3 X5 I, i( y3 w
- break;6 o4 P8 y: i7 s( A9 L
- }
9 s; E; u1 Q. H2 z/ H* W - ie_size -= ie_params->length + 2;; r8 w& D( Y) G0 M, R) T- H
- ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);) `0 H( H8 d2 f; h) l" ~
- }3 b. }. G+ H7 x w* Y* X; j# n( r
- 8 b. H( Q! \) o& C, a6 Y+ b
- return 1; // 成功+ y! s6 S2 J% }: D
- }" w7 `& m Z/ N8 E* s5 [
$ f. B" _) V; f$ ~0 z* s- void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)
2 [/ l/ @3 j8 q) H - {/ ]1 N2 s: d' {$ g* v$ \: Y: S
- SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
7 z$ |/ K; q/ \ - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;
: u! h" R$ ?/ U9 D4 F - while (SDIO->STA & SDIO_STA_CMDACT);: c$ F, l% P4 b
- }
- r) u+ z! l5 m( A/ i - : w' A& p1 J u5 i1 ]/ g/ @* L
- void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)& r( V4 I* t9 F7 v. a) Q
- {* W" A- ~7 l; \+ u0 J" N- Z& V" x j
- // 当count=512时, 和0x1ff相与后为0, 符合要求, e. A7 l! K: y' |
- SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;: i( n1 o _/ [7 m4 ^ \. B
- SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;
4 Z/ N" P) K2 H5 y - }
0 y6 w4 x5 F( [9 X, @7 R4 B - 0 Y9 k# ]7 R. O( k& ~: U4 B
- /* 发送WiFi命令 */& h7 c: a8 k% I* [ b) i
- void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)
5 l! J+ D$ f8 i. I6 C+ K - {7 j1 b m0 s0 h1 p( Y
- static uint16_t seq_num = 0;/ R/ s. N' _) L) n' I
- WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;) I# t' i7 k" O4 O, }
- $ N% ]' ^) W; G0 @
- if (size != 0)
( O* b& b" H! t+ M. B0 f - {
8 n6 _6 |; O1 e - cmdhdr->frame_header.length = size;3 z, ]8 ^: s4 {
- cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;
' w; c2 K" i0 K r - cmdhdr->cmd_code = com_code;
) v3 \" G3 \! H/ x - cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部
2 z$ D0 \" r0 V' z, v# I - cmdhdr->seq_num = seq_num++;' o: Z7 ]5 g) E& y- O4 J) P6 J
- cmdhdr->result = 0;1 `9 ?! h3 x; P ]( W) \ W* A
- }# V/ Q C* r5 I. W. p
- else
0 D: b2 p& ~* ]* c - size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
( F) c* @1 \/ ?) J8 y# B& C -
) t, b# |/ y C - // 发送命令前若恰好有数据帧到来, 则直接丢弃% Q, J! W: k1 B3 ?/ M" ?9 S5 Y
- if (WiFi_PacketPending() || WiFi_PacketArrived())
( ^; \3 U; K7 g, @, Y p0 p, k - {
1 Q! N# R+ b0 M8 D- E; J* \% V+ H5 `- _ - printf("A new packet happends to arrive when sending command! Drop it!\n");
6 q `5 o2 X$ z! t - WiFi_DropPacket();
- V# q6 k- h, y7 o5 [) c0 }$ x - }
: M& D2 c. `/ d- ` - T3 n3 R3 }% j% p. P- @& M. r9 b0 C
- WiFi_WritePort(data, size);
$ E) A" G( m1 S$ p) h5 G - }
; _- v7 f$ U/ K2 H; `) V4 a. j - : p2 Z% z0 p' t# i' T8 L
- /* 发送数据帧 */4 c. j* H. M4 t$ d) p/ K6 c+ J6 I
- uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)8 q6 s3 M4 L) l' o I. Q4 x# P; n; z
- {. D( u h b+ }9 A2 k
- uint8_t ret;
% m% j+ ^0 [& I7 L% R7 r -
]: x' ~+ m1 |) z/ ?$ z - // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
6 \8 l) Y4 D$ [# a9 {# U& @. P3 v$ j - packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
* s5 C. h( A5 N4 T0 d6 ~ - packet->header.type = WIFI_SDIOFRAME_DATA;1 O, A, U0 @, g& j
-
/ P) X+ S$ Z# I - packet->reserved1 = 0;& d p, ~- |& t9 {0 i- \
- packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings
8 }* v0 Z9 E6 W* f - packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader
; G7 V! R: f. y' C1 r6 x8 W - packet->tx_packet_length = packet_len;
. P/ l* _7 m) C& h* K$ n - memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);
5 Y m9 J( @8 L% L% Y4 ?' D - packet->priority = 0;/ K: T/ K6 y% d/ S* P% h
- packet->flags = 0;
+ P3 x/ i& n, G* X# t' W, j+ o - packet->pkt_delay_2ms = 0;0 o3 d+ `0 Q5 x4 g3 x' [6 I
- packet->reserved2 = 0;% j! ?0 @- `3 N2 @
-
& W& b6 q8 ?- r/ }( r - // 若现在有新收到的数据帧, 则暂存数据包大小% ?8 Q7 D9 [: m0 B
- // 未读取之前不会收到新的数据帧1 a& ^5 z! y/ C5 y
- if (WiFi_PacketArrived())
$ ^ q/ M3 r" v0 t5 } - wifi_pending_size = WiFi_GetPacketLength();
8 U/ D* K4 {+ A; G+ n' m, z -
* J) q5 a6 ^% w7 C8 m - ret = WiFi_WritePort(packet, packet->header.length);
9 Q6 n3 U8 {: X$ E3 i/ V5 ^ - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
7 t, I( [! B& o" ^) E- s - return ret;
) f, @* [7 s8 Y4 m2 g. h - }8 c; V" v* v3 s6 I! ?
- - ?0 y0 W6 E* _9 R: _5 ]/ z, B
- /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */
" n) x7 Q* m5 R- M- p - void WiFi_SetBlockSize(uint8_t func)
! N& ^$ [! \3 h% ?1 i" ] - {
G/ w5 G* P9 m$ T7 f+ _9 F; R - // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)* T- }/ b+ s2 P
- uint16_t size = WiFi_GetBlockSize();
5 |" s1 X0 Z: u& H' s - WiFi_Write(0, (func << 8) | 0x10, size & 0xff);# m3 x1 f2 X# k& v& j2 p; F
- WiFi_Write(0, (func << 8) | 0x11, size >> 8);
0 M+ T6 Q" I- x& h, b. d) e - }
. [; T' n- W* m - ) l3 `2 h! A4 d
- /* 设置密钥 */
2 S9 ~3 t: b- i/ V }- @' N; N& z - uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)( u# Z( V. Q. u
- {
" Z" m2 M" N& t* `$ Y5 ~ - MrvlIETypes_KeyParamSet_t key_param;
5 s. Q( E* O% t# }7 a - if (len > sizeof(key_param.key)) G2 F' U" Q& f% r2 k! ?" Q* f
- return CMD_STATUS_ERROR;4 R- L. l/ x; d8 l4 B
- key_param.header.type = MRVLIETYPES_KEYPARAMSET;, \- W( r/ _! E$ S/ d1 {: ?
- key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;( K! Q" b: P# f2 ~1 p
- key_param.key_type_id = type;
! g% B6 E5 D/ |, b+ A& L - key_param.key_info = info;+ P6 R# L6 x; M4 `6 W
- key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info
( o# W8 d8 }5 w k6 z+ J" V' x - if (len)$ v( D e* l! A+ H. w# m1 |* ^
- memcpy(key_param.key, key, len);5 Q& `: V$ d) @, q# q: Z
- return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
% N/ `# |- G7 |5 R - }
6 F* b, L' c% i) E* T) c
( {) F3 Y% [ F- \" @. Q3 G- /* 显示WiFi模块信息 */$ I2 @/ R! ^7 f% P% _ |# R9 {; t
- void WiFi_ShowCIS(uint8_t func)
3 Q0 b. Z! @( I% M - {+ F1 S: S& K2 s7 U' N
- uint8_t data[255];
) C/ c: ?# ]) b7 j - uint8_t i, len;8 ^% I7 R9 u" [8 l, H7 L
- uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure/ N6 D: t* B0 T) t+ E
- uint32_t cis_ptr;
+ J, I, O% l. g! \9 @ - , B& h3 G. ?) g3 A+ d) C# h8 T& X
- // 获取CIS的地址
* ?" f1 b# k4 q# g - cis_ptr = (func << 8) | 0x9;
: g. w4 V( A( Y& y5 w - cis_ptr = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);0 s( V5 M1 {2 s0 E& X( p
- printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);% _) |+ C8 B9 q
- , x6 v: y' K0 o; C( y! \9 c. P
- // 遍历CIS, 直到尾节点4 E* i& E" a# q; B! ~) ~) i
- while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)
2 ^2 \6 a6 n8 t( a) a- ]0 S - {
; m! Y& C8 z3 J& i - if (tpl_code == CISTPL_NULL)
/ T, q+ W- h, ~& K( J2 V - continue;. d! ` U; v+ R5 Y9 e
- 4 X, z+ Q: E+ y0 w- [3 \2 }1 W
- tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小0 j9 v; J& y2 a5 @' c" ^7 |/ c
- for (i = 0; i < tpl_link; i++)! s; b2 _% T8 k6 `( F6 L
- data[i] = WiFi_Read(0, cis_ptr + i);
6 r. j" m& n* Y6 K1 z- z" u -
. e, V) d* h: o6 @; w- S- N - printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);1 N3 p, V. o1 N5 e, ~
- dump_data(data, tpl_link);
* M0 _6 Z! o8 A - switch (tpl_code): Y+ e0 H( N: S) X" ]. e1 t2 H
- {: B1 S7 f& Z! i, Q0 ^
- case CISTPL_VERS_1:
& ]- u7 d' n5 ^# W- C - i = 2;
3 Q1 b7 L4 C& `6 g0 r6 d( b. J: M - while (data[i] != 0xff)+ _3 l4 J- Q) [4 z
- {; f! \; \; N' r4 Y
- len = strlen((char *)&data[i]);
2 |6 X" Z; _4 ], J - if (len != 0); }+ y$ Q: N/ p
- printf("%s\n", data + i);
/ w: U! v( W* o - i += len + 1;+ E6 l( k# ?: O* f2 H; i; s8 g
- }
" @3 }6 m) @" V) `# s" ? - break;
" a" ?, P/ j- L0 ]+ x5 Q) T - case CISTPL_MANFID:
8 X! v# V; L! j5 G - // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple
( s I" P8 f; H/ {$ l. x - printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
1 g6 Q: A8 R- ^' [- a7 C! b - printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD$ k' ^& h* ?3 O! g5 }2 Y! V/ I9 }
- break;
; n, F; z3 F3 i) y6 J! [ - case CISTPL_FUNCID:
9 b4 {) K! b& z7 f* m+ H, n% T - // 16.7.1 CISTPL_FUNCID: Function Identification Tuple
, }$ w2 F. P4 D) e; ^) e p - printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
4 m0 ?4 R0 z5 P! ` - printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT* c$ l! K% {6 m9 u" K
- break;/ M+ [: E3 M, Q B3 t9 _& \, z: D& O2 g
- case CISTPL_FUNCE:( Q* D1 I; L1 P- E. x6 {
- // 16.7.2 CISTPL_FUNCE: Function Extension Tuple* c/ H& q' X' A3 r' N
- if (data[0] == 0)
- g. |2 F/ p4 ~4 {: n - {
( J" x Q( e; d& k; I - // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h), J1 U4 P: S# b! [% `( R( A
- printf("maximum block size: %d\n", *(uint16_t *)(data + 1));
' H A7 v p4 |% T" T; i, Y - printf("maximum transfer rate code: 0x%02x\n", data[3]);
$ L' e# J, p# @& h, J# @9 _ - }
0 i/ w# @) J H5 C8 G" R- F - else
1 v0 Q1 T; p V# ~$ Z - {/ u' {* j1 P9 O! w' l6 b
- // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
. c# a) j' l8 p$ U* X# U - printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE9 x' l0 ?( T4 x
- }
1 v, t, e7 p4 t" }1 h* {' ~8 ? - }
, V5 ~' c9 \% H/ N5 ^0 _8 | - # g- \+ Y4 y1 t- T* u7 K
- cis_ptr += tpl_link;- ]8 w$ f, ? J b0 Q
- if (tpl_link == 0xff)2 d6 ~+ g7 P" j7 I9 }$ }
- break; // 当TPL_LINK为0xff时说明当前结点为尾节点
$ H3 k1 v/ o3 C% Y3 P9 D - }* X" y# T7 p" N2 L
- }. }0 Y! G0 b$ Z5 h; |
- . T8 M- v9 c) g s
- /* 显示所有密钥 */8 z( @; Z1 Z: k7 ?
- void WiFi_ShowKeyMaterials(void)
- V. ?: e$ e j- e4 d - {$ E2 Z6 y$ r& q; R5 q# u% x
- uint8_t buffer[256];
: P* M) l+ V; `# e: L! Z" e; K& V - uint16_t size;1 _) G1 l) d# y! `
- MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;) ~% n. E4 b$ H7 J( W4 C4 I$ D
- ( L t6 P7 p& r% y0 P
- size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);: S. B. `" X5 d# F: O3 h9 @; a5 w$ E2 }
- while (size)
. b; |9 [. T6 P% r1 J2 q - {3 D' h( d2 l1 p% N' G8 P3 l
- printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
2 n8 ?( ]6 K7 C. P - dump_data(key->key, key->key_len);
. x7 k- j! K7 h% F - size -= MRVLIE_STRUCTLEN(*key);! ]- S+ [: b' l- v
- key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));
5 D4 v' g: r8 Q& C - }$ G. l: |& i" D) N& f$ t
- if (size == 0)
4 x" w% @' r4 @" F - printf("data end!\n");2 C5 F: W0 [0 E4 N/ N
- }
; l8 ^3 v4 e1 g& j7 I K
1 d6 d; W0 z3 E$ O! {% G! ^- /* 创建一个Ad-Hoc型的WiFi热点 */2 n9 r, t# k* M' S$ b0 x8 t
- uint8_t WiFi_StartADHOC(const char *ssid): u: q! U( C9 c4 ?$ M- I
- {
% s6 n0 j2 [- \ - WiFi_CmdRequest_ADHOCStart cmd;; F M2 S6 M1 U9 q5 D
- memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
+ v S) ~1 _ C7 M2 W! J -
# o2 X4 l ?& F0 w0 }0 ~- ]5 o - strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
- K& Q% x- {4 W9 w, a - cmd.bss_type = BSS_INDEPENDENT;
8 u1 ^. v8 \! `$ q1 v; g. L - cmd.bcn_period = 100;
/ m5 K' a& g1 W$ v" \ - cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;5 [: ?3 {2 j) N- M: R* y
- cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);
0 E) s& g, }! _ ] - cmd.ibss_param_set.atim_window = 0;% x2 X/ t) q! J H6 `
- cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;
. y" z7 }2 V* L5 | - cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);
& ^1 L5 ~8 d% }+ Q+ u) e0 k - cmd.ds_param_set.channel = 1;
' l/ a9 S% i* F- R }% I L - cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;
3 x% t2 u* x" s! c+ w7 Q+ e - *(uint32_t *)cmd.data_rate = 0x968b8482;
1 R2 F4 g* {2 t2 l6 l- N) R$ H - & Y& v2 ?, E) @/ B$ y. Q3 b4 J
- WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));, x' F/ c: c5 `' I5 t) }
- WiFi_ReceiveResponse(&cmd, sizeof(cmd));
A3 [+ C- `: H Z2 P) b - return cmd.header.result;! F. f8 r. f/ Q4 E$ \8 j E
- }0 `% b3 U& Z0 E
]9 C" n0 _% E6 S- /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */4 Z% v6 \* y# T# F, p+ N
- uint8_t WiFi_Wait(uint8_t status)6 D6 n/ F' J3 C* k
- {
4 J1 f# [6 o. R4 P, B - status |= WIFI_CARDSTATUS_IOREADY;
7 g9 r* F2 A h - WiFi_PrepareTimer(wifi_timeout);" n; b# F% N- v) J
- while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)* E" ^9 t6 q# m1 w3 J8 a5 E
- {& v" j; ` o$ Y
- if (TIM6->SR & TIM_SR_UIF)
! i* A6 K! G5 P) Z - {& n$ u+ E; n' d. j1 ]6 u" \
- // 若超时时间已到
- w1 k+ e& |7 u! O - TIM6->SR &= ~TIM_SR_UIF;) m9 @- i3 ?* `) D3 R2 {
- printf("WiFi_Wait(0x%02x): timeout!\n", status);1 Z: R- t) Z5 \% E
- return 0;: s) W9 F$ ]+ e
- }
7 ^+ U1 f5 D7 T9 z4 y - }
* S4 @, @3 K8 V) o% } - TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器
* N' ]9 p! d. g+ E! N1 {) _0 | - return 1;" r6 k! p/ e' M) S
- }+ g+ [* D: B8 d* w% Y
4 [5 k x2 S+ p( F( k7 e; K- /* 写寄存器, 返回写入后寄存器的实际内容 */
/ z7 }- ?4 x1 G' D, H0 J$ K - uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)
3 ~8 ?, f7 ^' P2 X3 p2 z" p# H - {6 C+ y, O% I4 Q- g$ x. C
- WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);
; V8 x- V& G+ p; G0 @ - if (SDIO->STA & SDIO_STA_CMDREND)
( Y$ x' j; C' Q/ d" V! K - {
# z |& R( U3 O# w. k; z) L$ s3 X7 U - SDIO->ICR = SDIO_ICR_CMDRENDC;
4 _: R( n" V9 N+ g2 k; e - return SDIO->RESP1 & 0xff;& d' l. m/ s/ o- c
- }: F; [0 T+ {( ~, T
- else# m( B% k" x' m
- {( U6 G- R3 j4 A* {% d1 G! ~
- printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);
9 `$ o% v/ p* `% F - return 0;! H' v+ c: _9 s8 c7 x; D. d
- }% ^& F! O" y# e9 l, h! H5 k4 Y) P
- }8 s+ B- |9 q/ n! U' U
$ K' O3 U0 t8 l) U$ u- /* 写数据 */
* C F3 }* n( X% r1 m& K - // count为要发送的字节数或块数, bufsize为data缓冲区的大小
# n, Z( T4 A$ O u& q5 o* J% X - void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
; h5 _ `, C6 H0 M/ B( I$ D6 e - {
+ l4 O' G+ _8 J/ o0 D: _$ F - uint32_t len, temp;! s5 T$ x& f$ z1 Y
- if (flags & CMD53_BLOCKMODE)- o( o; U. g: {7 \# [! M0 c
- {
5 P5 f. Q/ v& B5 _3 T8 |+ J. r3 N3 S - len = count * WiFi_GetBlockSize();, ~5 [ P$ J0 ?5 ~
- SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;
- b1 |2 I. c% \) @: ^0 H3 K: X - } D$ W' h+ K+ i- m5 _% B, \
- else
/ P0 h8 s; p. o0 i, ?: @1 g1 E. m6 P - {
( f5 L9 D+ R( u0 q8 _ T1 u - len = count;# _$ F" X, b. W
- if (len % 4 != 0)
6 M8 w4 }* T4 n! i% c3 M7 h' J - {
' T* z, ?, i" j8 B Z: z; `0 K8 D - len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
: B0 i d! c8 V! d$ [$ J% S8 G - count = len;
6 z$ L0 ]; Y0 E* t - }
/ O! A0 I V: A - SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
% ~0 D" D# L( @+ S - }' x( x7 F2 c4 g$ U, z. u9 @. _
- SDIO->DLEN = len;
# f) y5 O) B. v1 W8 p# [ - SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块
8 X- w) b7 I- b B9 i* l - - _# g1 R( ~0 y) T% c# l* v
- WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);
5 H# V0 ?$ }' B' [/ g+ a - while (SDIO->STA & SDIO_STA_CMDACT);
1 p( n9 x3 T) D; N5 z( U! m - if ((SDIO->STA & SDIO_STA_CMDREND) == 0)
- |" @! {. z, U- K - {: }+ K5 ^$ e( j. q6 l
- printf("WiFi_WriteData: CMD53 no response!\n");! @+ k3 o( x) H/ E* f& B) ?
- return;0 y1 V/ z2 }( k. V+ _6 W8 m; a
- }1 b2 k; ]8 @2 {1 D
- SDIO->ICR = SDIO_ICR_CMDRENDC;
. M/ [) p4 ?; ` k4 N - ) Z! T3 X3 I8 P2 ]( g) p; k
- SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据+ Z7 }& A7 N3 L) Z
- while (len)
8 f& v3 Z. l, X - {( k' p. A' y. U9 O7 B
- len -= 4; n& e4 C6 L- k& B( J
- if (bufsize >= 4)
* o( [! c1 l) Y, s* b+ q6 T - {
4 n, T$ P5 t! l$ v! L7 f3 r: y/ s - SDIO->FIFO = *(uint32_t *)data;
0 R* O2 a+ F/ ~; g+ s - data += 4;
/ H* a, b0 Z" p* ^ - bufsize -= 4;
* b# J/ h8 v3 G- G - }7 F' \$ F% F8 K) z
- else if (bufsize > 0)
( G, _+ E% S4 [& c# S) j" y - {: r4 M" k0 O8 G1 q# y
- // 发送缓冲区最后1~3字节
5 E4 p) L( L9 f4 E) P$ C( u4 s1 d - temp = 0; // 不足的位用0填充& V% l! j. O9 X( s) x3 ]7 T" V
- memcpy(&temp, data, bufsize);
( _ V5 \" m$ x4 N- f$ N - SDIO->FIFO = temp;
4 d4 j3 Y4 X. j4 p - bufsize = 0;
4 V$ Z9 L* v4 w( p2 W% \! i - }
) B! Z+ m9 |% _ - else- S! `8 [/ F( k, D( Q# `4 T
- SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0$ U2 h+ ^( x! k# a
- while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待
) s! t+ c( J7 t+ o- i( Y - }; c) ~3 e2 F4 M
-
( ~: I0 @7 c) _ w7 }1 v Q - while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕+ K) f8 \1 j$ [. m( S
- SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
: ]- _; z" ]0 c" p& v D: m3 V - + M- L% O8 R, w, B/ [
- // 清除相关标志位
' e3 q4 v( I* \# o/ m% N, L - SDIO->ICR = SDIO_ICR_DATAENDC;/ G: s; a K* R: L- k7 u
- if (flags & CMD53_BLOCKMODE)
: T5 x. |( s; G1 _" J q( \# i - SDIO->ICR = SDIO_ICR_DBCKENDC;
) i, P l' b' Z1 J - }( N7 y& q2 K$ J
- f' l2 Z1 j' y9 i+ h: F1 E: d; M% w- uint8_t WiFi_WritePort(const void *data, uint16_t size)
, a1 o) q5 p( @2 ^ - {/ E' u1 i6 ]$ i, a- U" X
- uint16_t block_num, block_size;: y) h' s. x5 p9 F. [
- block_size = WiFi_GetBlockSize();' C/ T) ~( P2 h- t5 X7 ^; ]
- ' @: M- }$ v% F! M! d
- WiFi_Wait(0); // 发送CMD53前必须IOReady=1
. k4 O" P5 a3 [- R: j; I/ }9 I; c - if (size >= 512 || size % block_size == 0). T& ]2 {/ R x( e6 C- ?0 ^
- {' ^3 e! v$ Q# n0 g, B- D* @
- // 采用Block模式传输
' a" Q" n. j: } - block_num = size / block_size;# [2 ~& K' ~+ c: x
- if (size % block_size != 0)
) O3 y! S0 y/ z: U$ l6 s: a% Z - block_num++;
' @1 @# L1 b% N( m6 b3 E - 3 P1 _) v5 h( I2 z/ B
- WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);( G& b# y4 H5 I; j
- } C# |% a F. ^
- else
8 A: f, \- |3 s! R9 R5 g - WiFi_WriteData(1, io_addr, data, size, size, 0);
# _+ C* h0 f$ d4 G8 S, D - return SDIO->STA == 0;; a7 Y* {6 B6 ?; P# [: d& f
- }
5 u. Y/ V$ i8 B# w( I6 w0 a
复制代码 $ V$ W0 O+ E+ m: U' y! L9 ?
, \3 r Y* f. E: x a# T! E在工程的所在文件夹创建一个lwip文件夹。! j( P+ R) L+ @# t/ a8 ^+ q
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。# I1 i E% ]8 ?3 A5 f3 V5 R0 }
! Y; ~# S* |. E7 k+ A
core/* l0 u" p* C8 j! D
core/ipv4& Y3 A5 p3 }/ p. a+ u" M: {8 d
include/lwip8 T' f0 x8 v+ T! P. ?
include/netif7 x2 b6 {" t! T; S' o4 X
netif/ethernet.c
- U) B8 L* x8 d* V0 _netif/ethernetif.c7 f/ x# o' b5 {/ G
- f7 o$ G: ^& [5 {解压后,将里面的c文件都添加到工程的lwip分组下。
4 u' G- n o% s' x具体添加的文件请看下图:
; u& O) D" f3 P2 Y* _ 3 U( [) ^6 [6 h# X! G8 b# `6 w
) E7 R* q# _1 A5 _- j- ~6 x7 i" m/ ^接下来,创建lwip/include/arch/cc.h文件,内容如下: J! j3 Y* I) M/ ~- Y2 Y! ^
- #define PACK_STRUCT_BEGIN __packed // struct前的__packed
复制代码 创建lwip/include/lwipopts.h文件,内容如下:( a5 U! D) I* S. E
- #define NO_SYS 1 // 无操作系统 8 ?1 E9 i ]/ g3 t) n
-
2 N! w! Y1 d6 V5 l U - #define LWIP_NETCONN 0 3 i$ T; U# w2 @8 \8 A9 v; z
- #define LWIP_SOCKET 0 6 B/ P1 q9 A4 W4 N: s; C& A6 r$ x. R
- #define LWIP_STATS 0 1 g. Q8 {/ ~. e8 q
- ; d; T, s: ~- ]$ }* r! w# c+ I
- #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的
. @( v( k, G: W/ y( ^+ c -
3 A7 _# y8 D2 v+ m* Q7 s - #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)
复制代码 打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码:( L+ U1 {; V% u+ P" T
- /**
4 z; f v1 b: t/ ^6 d - * @file0 g9 P6 u9 P& V3 `: _+ h1 a M
- * Ethernet Interface Skeleton7 H! Y, J4 P# s2 a, q0 T) M7 J# q
- *# h# E) u( X( c# K
- */
6 V7 ~1 l c- N9 v( s
$ v7 u T B0 x- /*
- ]7 ^ a, p T0 e7 k - * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
1 a i+ S: I* X. e$ j - * All rights reserved.3 O% Y" D/ e1 g) U( C) A1 p
- *9 H' `: q. [& R' H
- * Redistribution and use in source and binary forms, with or without modification,5 H1 G. b/ s* |, Z. b
- * are permitted provided that the following conditions are met:$ X, L* Q+ n E: H! }
- *
7 k b# i9 B. C4 M. ?7 A - * 1. Redistributions of source code must retain the above copyright notice,
/ B7 m' k# y) f, _' o7 A7 \ - * this list of conditions and the following disclaimer.
4 Y0 a" Q: P- s' Y3 h! [2 e$ z - * 2. Redistributions in binary form must reproduce the above copyright notice,; U6 _) C$ w+ H1 h" Q% V0 ^
- * this list of conditions and the following disclaimer in the documentation( I- T( V' T. M* l- d2 H
- * and/or other materials provided with the distribution.
* ]& E4 I$ M5 _4 w4 @& F - * 3. The name of the author may not be used to endorse or promote products. e/ Q. f1 e. w3 d, W6 Q. k0 m
- * derived from this software without specific prior written permission.* @5 j# d9 J$ b+ J+ y; \# I
- *
' N9 E ~9 y! g: n8 ^# _ - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED7 @, q' \& Y9 I5 r
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# b4 ~" Y2 S" T3 C! i - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
w. ~1 ^) a B( ~! w; e. [( K - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,: g) s" `1 G0 z. i( O
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
2 u" ^; v8 L0 {/ i/ R9 t, Z - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS w% K* R/ f9 {# q) O
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% H8 [% ?2 w! T+ X ?: K# J - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
9 c, J0 g! e4 T& B& Z2 \6 J: y - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY, o- b: ^ X |; g3 A
- * OF SUCH DAMAGE.. v( Q- p3 C5 e! u2 x7 \2 j
- *
' c! H5 U/ L9 C0 }/ c - * This file is part of the lwIP TCP/IP stack.
. h W4 ^. _" k- e: c! q3 U2 I - *
" \4 m. s. [6 Q7 m- x - * Author: Adam Dunkels <adam@sics.se>& }- Z1 I; [2 K" s; \- _( @7 y
- *
v& y* `. c& ~9 ] - */4 M D" l/ S) r( k- B4 J& U
; q7 O! K* s) ~8 t- /*3 X- G& w+ w, H* d8 x
- * This file is a skeleton for developing Ethernet network interface
4 t* h9 T) l* W) E2 I5 ^ - * drivers for lwIP. Add code to the low_level functions and do a
1 N* j) H! x1 m: z0 B4 P" [( L! ] - * search-and-replace for the word "ethernetif" to replace it with
0 V. A9 c+ I' I - * something that better describes your network interface.4 W0 x+ ^" M: o7 u/ R
- */% ^# Y1 @& W+ W) @, {
- 8 t( J9 y. \7 T) u
- #include "lwip/opt.h"
* E% E" C! z; O n9 r0 ^ - # M- G5 J/ u+ V) e# \
- #if 1 // 允许编译器编译该文件* q) F3 z: R. d, | s
* t. y7 u' R; E( [- #include "lwip/def.h"/ n, r; F% A9 c: V8 x- G
- #include "lwip/mem.h"
' j* E; ~! n/ k6 I! ?+ L# M - #include "lwip/pbuf.h"
# Y( e: |: k# K! {+ `9 u - #include "lwip/stats.h"9 f/ L+ A& I: j) H# H
- #include "lwip/snmp.h"
) U0 @3 a0 N+ \( b6 [5 ? - #include "lwip/ethip6.h"
) K" E/ `( c# H8 J - #include "lwip/etharp.h"& x$ r) V) p. p* n( R8 f; Y/ {7 V
- #include "netif/ppp/pppoe.h"
7 K( d4 x) J) c4 J
5 l. x8 ^- X+ [: t4 l- /* Define those to better describe your network interface. */
1 e& H( d1 u, J$ e; u' S - #define IFNAME0 'e'! a' H* d% C4 f+ M' B4 p, O9 Z
- #define IFNAME1 'n'
) A7 C4 F* F" I0 F/ A) [$ ^. v
2 D: u2 C3 Y* B& O0 I: k- #include <string.h> // memcpy函数所在的头文件' n: q' l& }1 Z9 B7 U6 P7 q
- #include "WiFi.h" // WiFi模块驱动程序头文件& f8 {8 b# B4 z$ L* u
- 0 P9 T! Y5 M% \3 Y% P7 {: A
- void dump_data(uint8_t *data, uint16_t len);8 W* ^) h: }( ]9 E5 @ [
- ) Q& B7 n" S) X
- /**
' k7 O: W* h3 D3 l0 z; ~0 E - * Helper struct to hold private data used to operate your ethernet interface.
4 F, o- @0 m7 M) \+ C/ d2 X3 K - * Keeping the ethernet address of the MAC in this struct is not necessary
5 [0 U( t6 C" r8 R, ^( b5 z - * as it is already kept in the struct netif.* b5 H n9 m4 q' t2 z
- * But this is only an example, anyway...' S, @# U. L% O* ^7 x& A
- */
% y) C. F0 M7 m - struct ethernetif {0 j! k' K% g) Z4 X
- struct eth_addr *ethaddr;
7 W* D g8 F, {( w - /* Add whatever per-interface state that is needed here. */
$ W( l! s/ M( _4 B) n- K+ P - };: f8 ~# D( ?. K4 X
- % |8 y0 U, ^" K0 n
- /* Forward declarations. */
' ^6 ~+ G- S8 [" H. W! R - // 这里必须去掉static R$ R! C+ s* L: a
- /*static */void ethernetif_input(struct netif *netif);: x5 O3 a6 f! o4 F' E" `) d" e
- 8 m4 D! x$ R, D6 G
- /**
) C& V: _8 E7 Y s - * In this function, the hardware should be initialized.
8 u8 l/ f; w# N' F - * Called from ethernetif_init().
5 y" k8 o1 B: S. y - *+ J5 g2 V2 o" Q1 w: x& R& q' w
- * @param netif the already initialized lwip network interface structure
- @' a* p7 ^' c4 e - * for this ethernetif) g8 K1 k* y& E8 X. X
- */, ~) S6 \! m, [
- static void3 |( }' P' O9 `& j4 C% v) I* m
- low_level_init(struct netif *netif)$ N2 z* Y% O& J- y! ?. b/ h
- {
1 _* n# n, r2 p% V. P5 R4 _ - struct ethernetif *ethernetif = netif->state;
) k# Q7 B: k( G' W9 |/ n" ~
& E6 o- a4 A7 @1 f- /* set MAC hardware address length */" t2 p4 a* d" U5 K( X; X' ^; n
- netif->hwaddr_len = ETHARP_HWADDR_LEN;+ r. B2 }/ h5 K; r z! A* R
' x- f, R; J# x- /* set MAC hardware address */
6 B" I% R/ }" F$ r0 c/ R% f0 s - WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址& c5 a6 {3 N: B
- 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]);
* g% J7 j7 t# b, D" }3 b - # f1 h- c# L6 ^) w- S) M
- /* maximum transfer unit */
, x; ?+ O; e. w! W5 @ - netif->mtu = 1500;
$ w, s/ b N0 M6 L) { Z - 6 [3 k' C3 y" Z; k5 U
- /* device capabilities */
8 s6 E; z9 N4 Q+ n9 @ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */; g* N% p9 i. P, O4 O: n* i1 C
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;3 D- l- D Y0 G" w* I$ i+ x
9 b* A8 K- Y, R& ]0 M+ ^- #if LWIP_IPV6 && LWIP_IPV6_MLD+ q: `* Z0 M& L2 h" B& {
- /*# K9 j* c4 ]' C7 |) N5 O: x
- * For hardware/netifs that implement MAC filtering.0 p1 K; |& N9 E$ N: E" M
- * All-nodes link-local is handled by default, so we must let the hardware know
6 A: ^! ?) C- W' w - * to allow multicast packets in.# L" [" R5 h: F6 J
- * Should set mld_mac_filter previously. */
' ?+ U3 e, P9 A7 O. W; U: H - if (netif->mld_mac_filter != NULL) {
2 w# S7 o6 d1 o% @9 Y1 \: _ - ip6_addr_t ip6_allnodes_ll;
/ z4 @$ U+ u& l( r0 Y - ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
8 P" C" w. H$ D# P2 `9 c - netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);! R# k4 _: F. i* d! e0 @! W0 v
- }9 q# X/ b3 Y6 j/ D
- #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */" f1 ~. G3 l& i" x) @
- ) n1 e5 `: |5 o; V
- /* Do whatever else is needed to initialize interface. */
% o/ m. s+ w# I; s' Z0 x, C - }/ L1 ]) `8 b0 b9 `3 T$ q+ a: [
- ) c: z W2 g5 i6 ]: G- z: j' z
- /**
5 e. ~" U+ s: N" p h' a6 z - * This function should do the actual transmission of the packet. The packet is
8 @& [# H6 L7 Q - * contained in the pbuf that is passed to the function. This pbuf2 S4 v; ?. b4 A+ g; \: S
- * might be chained.5 j* g/ }" d9 X5 ?, G l
- *; S9 U0 ~, k5 Y! \( i
- * @param netif the lwip network interface structure for this ethernetif
6 `+ S# u3 e9 z- c# P6 q1 G - * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)8 P; i7 X6 Q' M* d. ]' e$ c
- * @return ERR_OK if the packet could be sent
+ v" s* k% ^1 x( d H6 l( C - * an err_t value if the packet couldn't be sent
& X4 R9 i& l* G9 U - *
0 I5 b( k* t6 U3 n6 e' \ - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
7 T: J4 K H9 M! }4 |8 ? - * strange results. You might consider waiting for space in the DMA queue& c) a4 x6 {" b x( c
- * to become available since the stack doesn't retry to send a packet
/ I" O/ a5 a. |1 B; y8 r - * dropped because of memory failure (except for the TCP timers).
0 Z+ W7 q4 |0 h0 ^ - */
5 X* o; v) O/ `, L# }" I
7 W0 ?8 q/ w5 i: Y- static err_t
3 O4 n& z2 \- Q' S' b - low_level_output(struct netif *netif, struct pbuf *p)' T. w; L+ ~+ B3 S1 C
- {
2 t2 F ^& f. W* N6 z, A, t - struct ethernetif *ethernetif = netif->state;
0 G! Q' {. s+ u5 `7 k7 j - struct pbuf *q;
5 d6 d! W# H6 Y# |( Z" n - 6 c. E2 [) z* Z- d9 R
- // 添加的变量
6 j. N+ O2 C6 m( x7 V, ^% i( r - uint8_t buffer[1792];
r* F" p+ t s: g z6 m6 N - WiFi_DataTx *packet = (WiFi_DataTx *)buffer;; A& h% E! v1 \; O1 v$ z+ g
- uint8_t *bufptr = packet->payload;0 T; p1 K6 _( e
- 9 t1 Z1 C. @' i1 Y# J
- //initiate transfer();, W) q# {9 a1 D1 u
' J- ], @' h9 L- A1 S$ `- o- R- #if ETH_PAD_SIZE
1 T- z" `6 }6 w e! X3 S" K - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
. H% k r* f( g3 S- x - #endif! N9 h* g) @; h1 d i+ M. D
- " A- H3 \2 w. o, D
- for (q = p; q != NULL; q = q->next) {; b y% t- m; t T6 x5 v' h
- /* Send the data from the pbuf to the interface, one pbuf at a
+ W, \' g# G* J - time. The size of the data in each pbuf is kept in the ->len
4 H4 N" z% I. Y4 Q7 i; F9 W. F - variable. */
! v( d+ M6 y* C4 ] - //send data from(q->payload, q->len);0 e( d3 C& I. R
- memcpy(bufptr, q->payload, q->len); // 复制数据包内容
! ]1 w t1 U3 r, `, _# Z4 ~7 D2 Q - bufptr += q->len; // 指针前移
- o1 T( o8 }% W" b - }
6 o) x# ?' U1 o. M3 V - , i% B8 w6 O2 U6 m+ l2 v! w! ]4 H
- //signal that packet should be sent(); V8 F9 ^9 d0 v# [6 h3 a
- WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包2 X7 m. Z+ ~, T) {3 G. s9 r) ?
-
6 u8 x# R! F% Q/ i: ?" ~: x1 y" _ - // 打印数据包内容
+ D& L- D: p% L" e$ c1 v- G% @/ y - printf("[Send] size=%d\n", packet->tx_packet_length); o* v& n' B% S/ N! O0 |. }* C
- dump_data(packet->payload, packet->tx_packet_length);0 o m& x6 }# _
4 {2 m0 p2 F. O4 q# J: t- MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
/ \# p; _1 M6 ~1 b% s - if (((u8_t*)p->payload)[0] & 1) {
6 U; j6 B% ]3 C8 ]2 p - /* broadcast or multicast packet*/- U4 B3 M3 f: ` f0 r* t2 @9 r
- MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
% o: \$ c' Y, y" f5 O1 `! { - } else {
/ h6 c8 F- Y" `- Q - /* unicast packet */
5 O: Q q3 a) |! X% P - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);- f/ U9 h0 a2 q& ?5 e$ Q4 s
- }$ m) `2 B: o: j) e A
- /* increase ifoutdiscards or ifouterrors on error */) K; ?; z2 H: Y, H- P) `" c: [
- & {! z S; V: p7 w) P$ {$ u% o
- #if ETH_PAD_SIZE% |. ~' `& e e7 F
- pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */% Y0 x X/ v) v& y N9 J1 _
- #endif
2 }6 |; g" n5 b6 p9 p+ [ - 4 A6 D3 Z: Y, _+ Y& k
- LINK_STATS_INC(link.xmit);
3 _! D9 O6 E1 A' h4 i$ q% V! s - 1 ]* d# V( J y! h4 t1 H& K$ n
- return ERR_OK;$ U* _: M _' E6 ]
- }, Z/ [4 N* L$ a7 U
* u! I( ]2 b5 ~5 `1 y" V- /**9 |- f6 j' ?2 v( b4 G) J
- * Should allocate a pbuf and transfer the bytes of the incoming. \2 j3 g! x$ b3 W/ ~9 v
- * packet from the interface into the pbuf.! s' U, f* I* i; F3 l9 S3 @
- *( X6 a8 h& U+ ^" W
- * @param netif the lwip network interface structure for this ethernetif4 Z% O4 O* m. v! X
- * @return a pbuf filled with the received packet (including MAC header)
4 Q5 R+ g' g9 ~ - * NULL on memory error
! t/ f( _. j6 z - */
! u5 ]$ p a- r1 w& A9 V - static struct pbuf *' R6 L* h4 H9 a7 p" A% w T( W
- low_level_input(struct netif *netif)
- n% O7 G+ I" v* b n) v. W4 C - { O$ {# m9 T- P, s
- struct ethernetif *ethernetif = netif->state;
" I3 c) v$ g$ H! w6 N; y- v' } - struct pbuf *p, *q;1 b+ u) N% l6 }: T* m* N
- u16_t len;* I; x) r4 A. f& l7 h
- 3 `9 O2 E3 y+ f9 Q3 x+ w
- // 添加的变量1 m; ]7 V8 ?4 L& ]) t7 G) l! R( X
- uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完% A" p# B+ N9 ^7 {9 c+ Q9 @3 u
- WiFi_DataRx *packet = (WiFi_DataRx *)buffer;3 v% j- U: f& U. F7 Z0 C! i
- uint8_t *bufptr = packet->payload;
, @4 W; m6 c; W# c% p. W. N9 R/ s
2 l, p" Y% T) T X0 \- /* Obtain the size of the packet and put it into the "len"
4 d3 I! t% L9 g; @( V' G0 n4 z - variable. */
: y" u: A! z8 U9 q - len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
) y! A$ z! S# x1 Z8 v6 Z - if (len == 0)+ Y- `+ z/ I, y+ u& B, S. n
- {6 c! m( c1 t: I1 e$ c
- // 若读取失败, 则不分配pbuf, 退出本函数8 ^5 C- E% s/ b' d3 r
- p = NULL;3 A0 b- V; G' M' S" l0 q. U+ h
- goto after_alloc;
" e2 \4 `! D* u$ [ - }9 m$ D9 r) v' ~0 ~3 o0 s1 _8 b
- len = packet->rx_packet_length; // 获取数据包的大小! `7 m" _7 N- @
-
& @& `+ b% @! W8 S - // 打印数据包内容
; A" O( ^ a% i: Q1 J" U- v! E) M - printf("[Recv] size=%d\n", len);, Q$ `" o ~. L3 w0 l5 t
- dump_data(packet->payload, len);
) `+ a& |% O/ I' _* l$ ?
4 {1 b( U, r0 h: q: s ?- #if ETH_PAD_SIZE0 G; l0 N+ P; Y! [
- len += ETH_PAD_SIZE; /* allow room for Ethernet padding */+ U/ z6 }% T# x4 }1 `9 |
- #endif7 f% \2 ?# ?7 j5 n8 R" k; m) A# w
- 2 n' M# F" F$ T
- /* We allocate a pbuf chain of pbufs from the pool. */+ o: `# G0 d& p8 {1 c
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
) F1 B" N' v' t0 C4 ] - 2 f( y9 ^2 H- J
- after_alloc: // 添加此标记6 M: G0 e2 T0 N3 [* G
8 K0 c1 B3 v0 ]% k2 H, }4 G: [ t- if (p != NULL) {, P+ z: J1 _* i8 e
- ! _& k9 O" E! e8 ~# z3 ^
- #if ETH_PAD_SIZE) K4 E% d% W4 x7 E; W( U
- pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */9 u$ C9 f$ A8 R3 ?& h+ W
- #endif
8 S r" J& u7 c+ p& X4 s3 q
. i. V! C' D6 }" b- /* We iterate over the pbuf chain until we have read the entire/ z& d; R0 {! o$ c/ x5 K
- * packet into the pbuf. */3 m3 l2 Y8 O* U# @# ]. N) z4 a
- for (q = p; q != NULL; q = q->next) {
* w; n6 O. k! L - /* Read enough bytes to fill this pbuf in the chain. The& Q) g2 K: b& U1 [: X
- * available data in the pbuf is given by the q->len
$ D( T/ F- c {4 J( m9 ?/ \ - * variable.
l5 Y+ w$ d( s5 d# b - * This does not necessarily have to be a memcpy, you can also preallocate, W5 _8 w. b* `- Z+ D/ J6 m
- * pbufs for a DMA-enabled MAC and after receiving truncate it to the
8 I4 f$ \9 `, W - * actually received size. In this case, ensure the tot_len member of the% U) H2 ?% M% S/ m
- * pbuf is the sum of the chained pbuf len members.5 r |% G( J+ ~; y3 D, i$ ^
- */
( y! Q/ T ^* H3 V6 x0 ~ - //read data into(q->payload, q->len);$ }- C: q7 F) x( }! p+ x
- memcpy(q->payload, bufptr, q->len); // 复制数据包内容4 V4 l2 u! n6 a- S7 o4 q& ^- ~
- bufptr += q->len; // 指针前移6 \- l3 W h7 L% f5 ]* }# \
- } W* U' u9 f6 _' H* r
- //acknowledge that packet has been read(); // 无需确认
" E2 v( e1 \# g - 6 I$ ~, j0 a1 G0 o
- MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);1 v: W, P% Q- L! C& Z1 P9 p3 \
- if (((u8_t*)p->payload)[0] & 1) {" S$ ^ Z; N/ P0 l
- /* broadcast or multicast packet*/* [% O# ]" Q" Q1 b. n {
- MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);( Z8 |0 h% s) t. t
- } else {
3 y0 o2 d: e" [/ s! u( S - /* unicast packet*/; L- A" S3 G5 I. e8 J$ e- R/ a
- MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
0 X4 s0 d6 u) T - }8 ]1 z( s( }/ q* p8 |
- #if ETH_PAD_SIZE
9 w% J$ |/ }6 g: D: a8 b* J% e" g - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */6 |2 G! J8 J( [; c8 |
- #endif/ v: y0 M y$ k) x1 g0 r% q
/ z& k) e5 R x* |# a% S! r- LINK_STATS_INC(link.recv);% ~! n9 C- c8 |* ~5 o- q
- } else {1 B% V1 h: z$ Z! ^* s) g4 A Y% b
- //drop packet(); // 注释掉此行0 {3 Q6 o# B7 J9 g
- LINK_STATS_INC(link.memerr);9 |4 t1 B: u( Q0 s
- LINK_STATS_INC(link.drop);
; ?9 B8 y. j" Q% [( `4 D$ {& l* m - MIB2_STATS_NETIF_INC(netif, ifindiscards);
- h! H3 m$ k# x( c- Y% w: f - }
* Y/ ]6 C Z) q$ \ - , N- e/ T4 ^9 \+ E5 s& a
- return p;$ z0 ]: O0 I$ g* p" M, `
- }1 W% p2 d4 w- s! \/ P; h1 m
/ l$ C' ~6 d. g) N1 g* Z! [& M! V* e; V- /**) I) v: J& M) g% m
- * This function should be called when a packet is ready to be read! p w1 t# M9 t+ W5 |! {( T: I, l
- * from the interface. It uses the function low_level_input() that
! H$ t, E; A. @& K5 e2 r- u$ K - * should handle the actual reception of bytes from the network: j" l5 D/ d& t* S1 j: X
- * interface. Then the type of the received packet is determined and
* B* H, r5 T$ q4 r' L* L+ ]" A - * the appropriate input function is called.
* z- O4 O- f* G: e6 i# F$ x - *8 X, ?" J' T. D6 H6 C% i
- * @param netif the lwip network interface structure for this ethernetif; S5 ? ^/ i6 A$ k" {+ Q
- */
4 P% w# Q+ K. [' g: v2 N - // 必须去掉static9 l: c9 }9 V. K6 R F& R
- /*static */void1 Q: o" o6 F6 T0 y; X
- ethernetif_input(struct netif *netif)- L3 c+ n8 k2 u
- {( k4 a3 i' n: M
- struct ethernetif *ethernetif;
|0 J, A6 e" T% |# X( Y - struct eth_hdr *ethhdr;6 o. p3 e/ p4 M; W" D
- struct pbuf *p;/ J3 W* |8 |% ]& z% U0 e
6 o ]6 ]4 B5 v0 b/ ^4 }" _- ethernetif = netif->state;
, z. Y. S4 G+ }/ a6 { - ' t. U$ D/ T! E: K1 p l b! t. e. E2 N
- /* move received packet into a new pbuf */6 a) J# i' H0 x& N
- p = low_level_input(netif);
8 [ n: L" W3 x2 X3 e - /* if no packet could be read, silently ignore this */" q( a9 D' f3 l& g: F# T1 m
- if (p != NULL) {% O# o N* Y$ r0 ~
- /* pass all packets to ethernet_input, which decides what packets it supports */
6 b+ A9 ^ r# J8 u/ E# K - if (netif->input(p, netif) != ERR_OK) {' T7 o6 F. ^2 O# K# f, _
- LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));: \8 R2 Y# v2 m6 C2 v* |( e
- pbuf_free(p);
4 P+ }. I5 m9 I$ P5 n# y8 ^ - p = NULL;
3 k! g+ \0 B! E# j - }
9 q# ?: d- T1 B8 A! } - }
8 P8 x: G7 q- R2 Q/ Y1 E3 H - }
, s1 ]7 F. K' A9 M% g# t
' N$ x+ [* S0 y; c" h% r0 L; [, i- /**
- r3 j1 [: L ?9 H9 | - * Should be called at the beginning of the program to set up the/ V( W# t2 a1 Y* \& M: l
- * network interface. It calls the function low_level_init() to do the
- j. [- n, i" L' w* F) ? - * actual setup of the hardware.
5 [$ V; t1 B" b7 O* o - *
7 n" ?2 S2 e0 f/ H. f - * This function should be passed as a parameter to netif_add().6 S( p! ^6 R8 D" W I7 ^3 x5 S
- *
& Y0 {% j+ `5 |, n, h - * @param netif the lwip network interface structure for this ethernetif
: N5 g* [% ?. g% u( Z4 q - * @return ERR_OK if the loopif is initialized
: q2 _8 z0 ?: H - * ERR_MEM if private data couldn't be allocated
4 h% c) y6 |! @3 r( Y - * any other err_t on error/ d3 l: K' R: W9 n: e% U8 N
- */$ V* s, G$ k2 ?) t4 k1 [, U
- err_t
. w1 P1 ]5 ~+ J2 @3 e6 ^ - ethernetif_init(struct netif *netif)
3 e4 F* I8 M- c - {
5 Q# f$ S! l9 |" L3 o; ^ - struct ethernetif *ethernetif;; S( d" U0 z- ^; T
% w" {6 Q3 Z2 E0 I" Y- LWIP_ASSERT("netif != NULL", (netif != NULL));
( U' N/ E" c' I- R, B% V' s6 c5 `- p! } - 7 ]/ g+ n8 s( A% x6 w3 B, @
- ethernetif = mem_malloc(sizeof(struct ethernetif));/ j5 K! }3 k8 \
- if (ethernetif == NULL) {
0 E. Q" O2 W' V7 v - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));. I9 R8 E6 T/ I( q
- return ERR_MEM;
# h7 }' p! `' g- P- A7 U" F& z - }
/ ^& W& U$ w+ r7 G0 z- g7 H - + g. |/ n, B% k
- #if LWIP_NETIF_HOSTNAME9 d) C S# _6 \6 F+ U6 F4 \! h
- /* Initialize interface hostname */
+ ~- \/ m/ T6 V. ~. Q3 D/ T - netif->hostname = "lwip";; z# a9 s8 G& N6 e5 f/ t
- #endif /* LWIP_NETIF_HOSTNAME */2 P- x/ T9 X; L5 o1 V# ^& y
- . x, m7 _' R* M" [. b0 H
- /*
) |- G1 W1 o' ~$ ~) c7 N2 { - * Initialize the snmp variables and counters inside the struct netif.5 p8 h% Z0 s% x* o6 Q
- * The last argument should be replaced with your link speed, in units
* r# @/ |, f- S2 O& ` - * of bits per second.
8 m! m: ~% X0 P' v$ v& d/ Q - */4 f) @/ e( q& p% G2 U7 e# L t1 @# Q
- MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);% p2 X. p7 ?0 [
1 m. j* V5 P: o; j( e- netif->state = ethernetif;! {9 u6 F4 z4 _7 M
- netif->name[0] = IFNAME0;7 j! X' n C# P# ^0 K# m, X3 |
- netif->name[1] = IFNAME1;+ q% Z4 m" w8 T+ s$ y
- /* We directly use etharp_output() here to save a function call.3 k1 [0 ~/ E7 i1 |+ J( Y% g
- * You can instead declare your own function an call etharp_output()
/ C/ u( H/ k/ A G: A8 [ - * from it if you have to do some checks before sending (e.g. if link9 g4 x4 w3 N$ ]* {+ V _
- * is available...) */
* u0 `* i' }+ Z- S - netif->output = etharp_output;
# Z5 f" G/ g1 U9 O% r - #if LWIP_IPV68 ?5 Q2 a4 x: X6 n. f. d" D
- netif->output_ip6 = ethip6_output;8 ?0 L( D- u3 o: i. l" B5 |% ]/ ^. W5 H
- #endif /* LWIP_IPV6 */
8 [2 q' N3 ^& R1 {$ \ - netif->linkoutput = low_level_output;: }0 U% G0 G/ U' j
- D9 S- }5 r8 {/ V/ U. N& }8 Q
- ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);$ c/ ]: H, H7 H1 w9 }
- 6 r! Q: A5 |# X9 y5 H# Q
- /* initialize the hardware *// ^8 z, d! @ X/ F% W9 C
- low_level_init(netif);
/ o6 H2 I3 u# x Q5 O7 n7 m: k* A - - }" t2 p0 z1 z, z
- return ERR_OK;
7 o5 t2 n: Z( s5 ]3 d - }
d6 M1 P8 }, M5 [; y( N" Z5 f4 ]
K, F% Q$ f( S9 ]. p- Z# @8 Q8 E- #endif /* 0 */( B5 W; ?9 T" j+ d' U
复制代码 3 d5 K8 s A7 `* A: {; `' x2 X( a
在项目属性中,设置Include Paths为:.;.\lwip\include! S0 x% A& h1 u: g+ Z8 l9 a& B0 ~
其中点表示工程根目录。* J" q7 L5 N) h4 k }

% K7 g [ x# M& E另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。3 S2 |. ]+ \' X3 u0 u4 c
3 C: f) d3 G$ \6 A3 S c F
编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
! C2 t) k7 g; Q0 n ?6 Q电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。" X$ [4 _ `( V8 E4 O' S J
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。4 h# `* q% q" @: g7 @ N5 H$ O
 |
多谢分享