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

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