本程序所用的单片机型号为:STM32F103RE
6 P1 r5 ]6 N3 O! y; X3 ~. TPB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。& m% Q' X% h! q# x
注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。. D( d# M7 h5 M4 u6 @
该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。
! U$ C. \( h- Z, _9 j; i固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925- D4 `1 `8 l0 U1 `, i& c/ N- T

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

: R( a6 A" L. A+ g% ?& N" ~5 ^& Z9 l另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
* q1 o8 I0 j' E, q, {8 h- k
8 N; H0 n# V! p0 M, m! q3 \( r编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。
! L9 h% u+ V6 m电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。
! M3 h; z0 t6 ]! G配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。
9 ?. u; f4 l. x# Z4 X. s |
6 O1 b) Y6 K3 S( d
多谢分享