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