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