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