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