本程序所用的单片机型号为:STM32F103RE
! v* N2 I0 g; }PB12端口为外接的WiFi模块电源开关,当PB12输出低电平时接通电源。
% e G, ~; g Q" _4 F; l0 U注意:WM-G-MR-09模块的芯片组(Chip Set)就是Marvell 88W8686。8 o$ t! B- \* l; [2 W' E
该程序目前只能连接没有设密码的路由器,创建热点时也无法设置密码。/ g+ p! V% g9 Q7 x
固件内容请参考:http://blog.csdn.net/zlk1214/article/details/74612925
. T' X$ P& z$ x6 P $ J0 |" `6 P1 t8 t$ R( Z
注意必须把STM32启动文件*.s中的函数堆栈大小Stack_Size改大,否则函数中无法创建大数组!
' P0 a/ R3 Y7 s2 r- Stack_Size EQU 0x00000c00
复制代码 【main.c】% ?: h6 a( C. a( F" w- L8 S. Z
- #include <stdio.h>+ g" l. G2 i/ v4 h" e
- #include <stm32f10x.h>
/ z8 M! l+ v3 d0 i! Q - #include <string.h>: l$ `! i! `* c+ F4 s z/ E
- #include "lwip/init.h" // lwip_init函数所在的头文件 p1 e1 @1 e4 f" U g
- #include "lwip/timeouts.h" // sys_check_timeouts函数所在的头文件
& O" R2 s0 |8 q, C - #include "netif/ethernet.h" // ethernet_input函数所在头文件$ c) }! E1 k* ~1 N
- #include "WiFi.h"& D! B8 y2 K( K6 R4 s
' e( t3 Y$ J* U' t; c5 w3 P# Z- // 这两个函数位于ethernetif.c中, 但没有头文件声明
3 `) q8 Z# H' w) O8 i) B; N - err_t ethernetif_init(struct netif *netif); h1 O" ]- U7 L0 f8 v8 p! }* d( Y
- void ethernetif_input(struct netif *netif);
) i6 E* |$ w. x/ f, p, [; b - $ K: G) K1 y0 q& J! G5 o
- // httptest.c中的函数- ^9 I) L% X, l7 s4 M
- void init_http(void);
( S/ x( _6 d8 W+ ?* y - & Z* l( O1 f. ~8 ^% @0 ^
- // 延时n毫秒3 O' E# g o( s' z& \
- void delay(uint16_t n)
/ O' W# r3 S8 h" M$ w" P" ]+ I - {; v7 h; b( s# G
- WiFi_PrepareTimer(n);+ K. X, N+ h- m/ M+ T; v
- while ((TIM6->SR & TIM_SR_UIF) == 0); // 等待计时完毕9 M/ r8 Q! I; C# ?/ S3 O
- TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志- g& _. y/ l1 |) c( m- C8 t3 [
- }$ n- p$ `6 ~; n
- : _; {3 Y7 I' C0 o
- void dump_data(uint8_t *data, uint16_t len)
, i# [: E7 J# K( B5 V - {; Z1 P" \2 v$ L1 Y( h8 X6 G
- while (len--)( C# W/ z! `7 a
- printf("%02X", *data++);
; M. F3 @7 ? @) s - printf("\n");
( w) X7 }3 @7 U7 B( k- m5 h - }
& p; y) U) C* \# Q3 V
; F6 I9 [5 w: g4 \; D! v- int fputc(int ch, FILE *fp)7 E- F. x( \7 |+ B* s6 A6 b
- {
+ u; g9 t5 l! l" M2 y: Q* K - if (fp == stdout), I! K" J2 `. n6 w
- {7 @- |- b& O: V* T
- if (ch == '\n')3 [3 t* s3 Z" b# ~5 m4 ^& `
- {/ n7 m7 J3 k A+ y* M0 @5 m1 ]% x7 `
- while ((USART1->SR & USART_SR_TXE) == 0);
! t8 I6 N' r/ t: n2 F# } - USART1->DR = '\r';' w* {8 j% F0 R8 z8 a
- }
5 [; |, O, j/ z0 Z& g - while ((USART1->SR & USART_SR_TXE) == 0);; p1 l% r+ b7 I! c9 u
- USART1->DR = ch;1 {- z, L9 \2 }7 {; ]
- }2 Z$ u8 `% y9 O/ U4 F( A
- return ch;8 I( p3 k/ v5 |4 ]. {0 x g' n+ c, X
- }: T0 V1 b( \9 R4 e" A! @6 M. C
3 f0 J' M j3 B8 E6 j- // RTC时间转化为毫秒数
% _1 B+ |0 Z7 C( y3 I% E - uint32_t sys_now(void)
% @8 q4 N8 p. o% I9 ^0 M( n3 S - {/ @ o- z1 N" ?# w; x
- uint32_t tmp = (RTC->CNTH << 16) | RTC->CNTL; // 秒
r+ O8 u) o' v# z - tmp = tmp * 1000 + (32767 - RTC->DIVL) * 1000 / 32768; // 毫秒3 P5 O/ m: l9 {0 k& b \& D; \
- return tmp; w* S \- k: P5 c( i
- }
: q+ q+ [% Z8 M# x9 V
# i3 E$ H( K6 l* z" Z2 G- int main(void)/ J& b; {' {/ y% p
- {
& V \3 M2 {8 a3 K - struct ip4_addr ipaddr, netmask, gw;) v& v: [! }; z) q) p
- struct netif wifi_88w8686;; C7 W$ s. a+ l. \/ I' }2 j5 W* x
- uint32_t last_check = 0;
5 S5 w! \( V* E( {) q - 5 R: j5 a& r+ o: e/ l
- RCC->AHBENR = RCC_AHBENR_SDIOEN;/ U' \+ r! U! U' I+ O' I% ]3 z. y
- RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM6EN;
+ l4 c( U/ B, D/ D - RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN;
0 h5 X- W8 o2 c J) j - ! m7 M! V4 `- c
- GPIOA->CRH = 0x000004b0;; V5 ] G& T+ a' ^
- GPIOB->CRH = 0x00030000; // PB12为外接的WiFi模块电源开关, PB12=0时打开WiFi模块+ m$ Q$ u" J3 p
- GPIOC->CRH = 0x000bbbbb;8 n1 ^0 i2 p' m, Y0 [& W9 k
- GPIOD->CRL = 0x00000b00; T. o8 T! i8 f- u2 Q( K$ _5 H
- ; P2 {% f& e+ Y% ^
- USART1->BRR = 0x271; // 波特率: 115200
0 j2 X8 x3 W. `8 j& w1 w - USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
3 z5 F+ z+ R' U - # R2 r, @, z( c5 D% _) Y4 n% z0 o
- PWR->CR = PWR_CR_DBP; // 允许写入后备寄存器
: l3 ?* `9 {" _( y& P - if ((RCC->CSR & RCC_CSR_LSION) == 0)/ c& W6 {& H- W9 R* r
- {5 H& g2 {5 {# C7 N4 F5 @3 E' O D
- RCC->CSR |= RCC_CSR_LSION; // 开内部低速晶振LSI5 A3 x0 {. G9 Z0 m
- while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
2 r- j& f0 v# w% {4 T7 Z1 P# ~ - //printf("LSI Ready!\n");
- B$ T; Q$ D; j( W* S - }
+ V7 w) a/ Y& l0 r# I* p - if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)/ q/ }7 r- t& x; A0 f% Y; T
- {% y* |$ P2 d4 Q( k" }, p% T) [
- // 若RTC还没有打开, 则初始化RTC
* A3 |, X: ^/ w) d8 l& V# o - RCC->BDCR |= RCC_BDCR_RTCEN; // 打开RTC外设, 但暂不开始走时# `: s7 p* K) G( ^" Q3 I2 t# g
-
( H- n7 P6 F% z: Q5 P- G - RTC->CRL |= RTC_CRL_CNF; // 进入RTC配置模式8 q5 }2 h5 L( M. E: Y2 |' {: T7 H" H1 g
- RTC->PRLH = 0;7 b; e9 `% P: v3 L* b1 T7 I: @+ \
- RTC->PRLL = 39999; // 定时1s (PRLH和PRLL寄存器只能写不能读)& A5 ^& ]/ Q3 t* u1 g* w+ q6 i
- //RTC->CNTH = 0;. u3 T" i8 i& @% L6 b, N
- //RTC->CNTL = 50; // 初始时间" g5 |+ n" d3 {6 g
- RTC->CRL &= ~RTC_CRL_CNF; // 保存设置 z& m: d/ s; e) f0 H0 @
- ; {3 K! ?7 l* J0 O
- RCC->BDCR |= RCC_BDCR_RTCSEL_1; // 选LSI作为RTC时钟, 准备走时
: I* [6 C" Y/ P$ w; j - while ((RTC->CRL & RTC_CRL_RTOFF) == 0); // 等待设置生效
/ P3 O4 f/ M# I) d5 W- o9 ^6 l - // RTC从此处开始走时
6 u2 G# D+ n- B" z4 G% r/ i - }
8 Y" e7 s- b# @6 r -
% j# o" s4 q0 V3 T/ X - WiFi_Init();" H& c( m" G. C( Z
- WiFi_Scan();
! ^' T2 B' q% w& E+ O8 s% d7 N - 7 o0 s3 b$ x) c0 ~- F! S" M3 S+ H
- //WiFi_StartADHOC("Marvell_88W8686"); // 创建一个热点% e/ T3 _1 k, F7 y; f
- WiFi_Connect("vivo Y29L", NULL); // 连接一个WiFi热点 (目前还不支持设密码)
& i. [: n F2 k8 {! O8 a - " n& w( A, J, X, a# K
- lwip_init();" W @; n# g% s3 |) L( R) k( ?6 _2 n
- IP4_ADDR(&ipaddr, 192, 168, 43, 10); // IP地址5 |/ i w: w, w8 K7 Q8 B
- IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码$ l, Z! R4 c+ P/ c6 n* {# u6 x
- IP4_ADDR(&gw, 192, 168, 43, 1); // 网关
" V, {4 _. {! r/ p4 h% k x+ O -
# d% A8 _" f+ q5 E% U. z/ V - netif_add(&wifi_88w8686, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
) ~2 C( Z% T! q - netif_set_default(&wifi_88w8686); // 设为默认网卡
5 ?( w V% j$ z6 Z - netif_set_up(&wifi_88w8686);5 v' `/ V1 Z- t4 l" j+ u7 s
-
1 O0 b; f- j3 n# S" O - init_http();
! m: `! @, ~& D$ e% B- G -
5 W3 j, [7 x, _, z5 T - while (1)9 A# h, w4 K- A9 a
- {
7 U* t2 S" K1 d7 K - if (WiFi_PacketPending() || WiFi_PacketArrived())
$ v" `4 l {( y: z: F+ Y6 E$ ~ - ethernetif_input(&wifi_88w8686);
" {( B4 m" o# s& D4 _5 R0 i! V+ ~ -
' V" y! d) N1 G# @ - // sys_check_timeouts函数千万不能调用的太频繁, 否则会出错!(例如开机后要等1~2分钟DHCP才能分配到IP地址)9 h4 \! Q2 d1 ^- N% a4 M" L9 e
- if (sys_now() - last_check > 200): o+ {+ P# o1 W. V
- {$ g% o# G; X' X* j: x4 _9 T4 r% g
- last_check = sys_now();
. a8 J$ A1 A7 V. ?% r - //printf("Time: %d\n", last_check);1 t9 T. U2 _$ L0 s1 [' \0 j
- sys_check_timeouts();2 a0 t) ?, J4 q
- }- ~' r- C6 l( @( n {; |- Q: S
- }
1 @: k, C, h T: A! o* N0 Q, G& Z; b - }
复制代码 【httptest.c】
/ W& U7 d; H0 q/ j9 W& k) B& P- #include <string.h>! b' \: M- D) I/ L6 u9 {
- #include "lwip/tcp.h" // 一般情况下需要包含的头文件1 d; w5 M- _1 u- I8 `
- * j, W. ~ F$ L& S M
- #define STR_AND_SIZE(str) (str), strlen(str)
5 c, K, x: e5 A) M, g3 V* N
4 n# I: \6 I0 ]& @4 M+ n& f- err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)1 f/ J5 b* F$ X/ _/ {
- {
3 y, h& H( T3 ?& ?8 F+ T( W - char len[10]; // 存放HTML内容的长度
7 @7 m, ]0 P1 j0 Q - char str[200]; // 存放HTML内容+ o; a, B5 W C
- # q; Q) q0 d& d" a7 y6 t/ u$ c
- char name[100];
3 S( _) k1 ?( R0 E( ? - char *pstr;
2 j' y# G! U* G+ l) {& f; Q - uint8_t i = 0;& G% L5 `/ x: a E( r, \# y
- if (p != NULL)
& O) Z& N7 X7 o' R+ \5 I5 a - {( C) J& a6 J+ z- _# p3 h
- // 提取页面名称4 Z1 |/ r8 R0 z. Y5 c
- pstr = (char *)p->payload;" M" V$ \5 w' M# z/ r2 A; _
- while (*pstr++ != ' ');
! O& u2 x: G- B3 ]. x - while (*pstr != ' ')
@: R; {- V- N - name[i++] = *pstr++;
9 Y' z. ]+ U4 B! m/ T - name[i] = '\0'; // 不要忘了结束name字符串
6 H: i" k! L% _9 o; R7 m$ n2 I; K - tcp_recved(tpcb, p->tot_len);% H5 e& J2 c) l( ]' d- v; Q
-
8 W, Y) C& }9 {/ f* E - // 生成HTML内容, D4 `: `8 ~( d9 b8 s
- sprintf(str, "<meta charset="gb2312"><title>获取网页名称</title><div style="font-family:Arial"><b>请求的网页文件名称是: </b>%s</div>", name);
+ R7 d+ \' }! j4 R% r0 h. c - ' c% X( ]2 Z6 g" M# t% }
- sprintf(len, "%d", strlen(str)); // HTML内容的长度/ E1 P4 S; m* h6 V8 F
- tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);& X* ]2 t+ n+ y) G. k0 B
- tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);' D- ~+ N- q$ ^9 j5 R" K
- 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);4 Z0 y& F: L6 L9 h- Q8 ^3 E( {) Q/ _
- tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容) Y5 T; y, j# B0 L
- pbuf_free(p);) C! s5 h, Y7 J M
- }
2 t0 k: t* A* V( |5 F - return ERR_OK;
, x3 ]$ P4 Y$ E; v - }- d: A; ^4 d7 P) p) C6 w' z; Z+ R
- + A2 O: M( l) S6 _5 e) u
- err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
3 Y7 { u$ b+ L2 Z - {, L8 D6 F N4 Z* T/ w
- tcp_recv(newpcb, http_recv);5 o& R, H3 {9 P4 T- }' _
- return ERR_OK;
, i' P/ f, ~1 r5 n - }
, ^6 J, X$ b. F
2 C8 Z6 m8 Z' b$ ?- void init_http(void)
# Z8 {- D5 F2 } - {
* {5 O* I, u( g6 J - struct tcp_pcb *tpcb = tcp_new();
w& i& _/ Q$ L8 `! o - tcp_bind(tpcb, IP_ADDR_ANY, 80);: p& S7 | p' F3 d' p g, Z1 Z
- tpcb = tcp_listen(tpcb);
; x8 {+ Y8 o4 X - tcp_accept(tpcb, http_accept);$ H" I5 W# |" s4 L0 k( J- [
- }
复制代码 【WiFi.h】2 l ?/ f( L* r0 [
- #define _BV(n) (1u << (n)) }$ C( R5 s! N: {1 K: F# @9 N7 Q
- - E9 | f5 N7 Q; o0 B" c
- #define CMD52_WRITE _BV(31)5 T* c! W: V' u8 e Q/ s6 S- b! S
- #define CMD52_READAFTERWRITE _BV(27)
3 P! N* k# G9 H. y2 z/ u* r6 H
' @% G- I' x) b2 ^- #define CMD53_WRITE _BV(31)& e5 {+ [: T, d' O
- #define CMD53_BLOCKMODE _BV(27)
) D# _* ^3 x; G3 N - #define CMD53_INCREMENTING _BV(26) P1 a' J. M7 I$ o
x2 O# l/ i! F" f) C- // 16.5 SDIO Card Metaformat
% `5 k; U8 `4 z - #define CISTPL_NULL 0x00 // Null tuple
' C1 H4 e" C# ?7 I - #define CISTPL_VERS_1 0x15 // Level 1 version/product-information% s# |8 o: m" z- r
- #define CISTPL_MANFID 0x20 // Manufacturer Identification String Tuple
' \" r; V- w3 C* ?, E* m2 h4 { - #define CISTPL_FUNCID 0x21 // Function Identification Tuple' B s; f$ Z$ X& [8 J
- #define CISTPL_FUNCE 0x22 // Function Extensions/ G+ |0 D' z$ W }# D# d: [
- #define CISTPL_END 0xff // The End-of-chain Tuple
! J5 i! t; U4 s; q' `$ T: _
% R% d- H3 l8 t+ }2 H7 @& H- #define WIFI_DEFAULTTIMEOUT 1500 // WiFi命令回应的超时时间(ms)( V3 y( ?/ S, u
' M. ~: |; Y5 ` Y+ ^- #define WIFI_SQREADBASEADDR0 0x10
+ r, K1 y8 O* @ - #define WIFI_SQREADBASEADDR1 0x119 Z0 L$ P8 s$ E; E+ ?0 ?
- #define WIFI_SQREADBASEADDR2 0x12( c' K& i; M6 ~
- #define WIFI_SQREADBASEADDR3 0x133 X: @/ J% ~# C# f r
- . T1 m- [% l/ E" g
- #define WIFI_CARDSTATUS 0x20 // Card Status; F) q" N' P n( x r& v
- #define WIFI_CARDSTATUS_IOREADY _BV(3) // I/O Ready Indicator8 J2 N) }& ?" h0 K/ N! }
- #define WIFI_CARDSTATUS_CISCARDRDY _BV(2) // Card Information Structure Card Ready
6 q8 |' z4 P# \3 b" N - #define WIFI_CARDSTATUS_UPLDCARDRDY _BV(1) // Upload Card Ready
4 v, f, J( V0 B5 Y - #define WIFI_CARDSTATUS_DNLDCARDRDY _BV(0) // Download Card Ready
# }/ ^! W& M% Y8 U9 { - ' g8 ~$ L' W4 T! y: E7 j+ @- a
- #define WIFI_CAPABILITY_BSS _BV(0)5 M1 N5 z# p$ ?. E% D
- #define WIFI_CAPABILITY_IBSS _BV(1)
) U$ C9 m- a, D- Y - #define WIFI_CAPABILITY_CF_POLLABLE _BV(2)& j' J9 E9 S0 r& }0 O4 k
- #define WIFI_CAPABILITY_CF_POLL_REQUEST _BV(3)
6 r/ t9 [4 [! m0 Y/ y2 B _& C - #define WIFI_CAPABILITY_PRIVACY _BV(4)
+ [1 F* Z. E$ }1 y+ C+ X - #define WIFI_CAPABILITY_SHORT_PREAMBLE _BV(5)
3 O6 H3 O1 L# M8 B - #define WIFI_CAPABILITY_PBCC _BV(6)2 I/ {( C4 S6 u- Z7 L$ Y9 a
- #define WIFI_CAPABILITY_CHANNEL_AGILITY _BV(7)' g& T) z$ u$ ]* `4 O; r. ~* p
- #define WIFI_CAPABILITY_SPECTRUM_MGMT _BV(8)
% y8 x4 A* j! ~7 u; M - #define WIFI_CAPABILITY_QOS _BV(9) ~& ]1 Q3 u- B- ?6 W
- #define WIFI_CAPABILITY_SHORT_SLOT _BV(10)# k5 G I6 k; p7 D7 k+ k, s
- #define WIFI_CAPABILITY_DSSS_OFDM _BV(13)* d3 I0 G+ r- N- F5 C& e9 M! u6 y
- . }5 m$ [6 Y7 f2 V8 S) b0 M
- #define WIFI_SDIOFRAME_DATA 0x00; z o+ \! h* v) u) u
- #define WIFI_SDIOFRAME_COMMAND 0x015 W7 r8 j; g- {6 Y y% y; w
- #define WIFI_SDIOFRAME_EVENT 0x03
1 K4 {% N) R7 H) z! j5 n
" O' Z) E$ _+ y: d3 }9 I* ~- /* Command List */
. J3 Q& P2 e7 v0 s. p6 q - #define CMD_802_11_SCAN 0x0006 // Starts the scan process
+ X5 _4 w5 m1 R" F! N - #define CMD_802_11_ASSOCIATE 0x0012 // Initiate an association with the AP. [5 }# t* X" h- T; V
- #define CMD_MAC_CONTROL 0x0028 // Controls hardware MAC
; u+ W) @6 b* D3 ?7 T5 R - #define CMD_802_11_AD_HOC_START 0x002b // Starts an Ad-Hoc network
% p3 C9 I+ {8 K+ F- m5 M1 F% p" | - #define CMD_802_11_MAC_ADDR 0x004d // WLAN MAC address
+ z( } ] B6 G' T( _+ ^$ r/ r- v - #define CMD_802_11_KEY_MATERIAL 0x005e // Gets/sets key material used to do Tx encryption or Rx decryption' {' @2 O# Q( D; x( _
- #define CMD_802_11_BG_SCAN_CONFIG 0x006b // Gets/sets background scan configuration
% K% o( B. h' [( x - #define CMD_802_11_BG_SCAN_QUERY 0x006c // Gets background scan results* D' l: X7 t( r! \9 y5 { f
4 U, ?* J! ?& z5 W5 u/ k; _- /* Command Result Codes */
D) K7 X; |3 K3 |3 I - #define CMD_STATUS_SUCCESS 0x0000 // No error
3 j3 ^3 c, ?" ]3 M2 s. j - #define CMD_STATUS_ERROR 0x0001 // Command failed; O$ K j9 c3 N& p- k/ J5 ?
- #define CMD_STATUS_UNSUPPORTED 0x0002 // Command is not supported
E6 e3 C/ B7 [! F
& Q6 X6 }8 `6 R7 V- #define WIFI_ACT_GET 0
8 u* ^6 w# p- u# V - #define WIFI_ACT_SET 1# s+ L) p% @. s, v7 x& S
- 5 Y5 p3 \% T L& Q1 j
- /* Authentication Type to be used to authenticate with AP */
0 `& D8 `! Y7 O! T - #define AUTH_MODE_OPEN 0x007 b+ ]* w# m3 T1 H& |* i+ E- `
- #define AUTH_MODE_SHARED 0x015 I. L% |$ v) T+ A2 c5 ?! C
- #define AUTH_MODE_NETWORK_EAP 0x80: t! u, C1 l2 p! `: Q w
- 4 ?1 e8 W: ~" O# K
- /* WiFi_Associate return value */2 B0 E# n9 p9 j2 ^! q# e: o' a
- #define WIFI_ASSOCIATION_NOTFOUND 0xfffe( C( ^0 d X \4 W7 D5 ^) Z
- #define WIFI_ASSOCIATION_ERROR 0xffff
$ L u# k8 ?6 U' [3 T: M. m1 @ - #define WIFI_ASSOCIATION_SUCCESS 0x0000 // 连接成功' M- N/ t% V7 A) x% B: W
- #define WIFI_ASSOCIATION_INTERNALERROR 0x0101. T, P; ?$ z1 W. T s# Q; s
- #define WIFI_ASSOCIATION_AUTHUNHANDLED(ret) (((ret) & 0xff00) == 0x200) // 未处理的认证帧/ [. J, a8 F# X! x! I
- #define WIFI_ASSOCIATION_UNSUPPORTEDAUTHALG 0x0213
8 X! U8 w( H- K* C+ @) } t. L" q - #define WIFI_ASSOCIATION_INVALIDSEQUENCENUMBER 0x0214
" z' |2 @) a$ e$ \6 P0 H+ F - #define WIFI_ASSOCIATION_AUTHREFUSED(ret) (((ret) & 0xff00) == 0x300) // 认证失败
* b% `8 p% ]# } - #define WIFI_ASSOCIATION_TIMEOUT(ret) (((ret) & 0xff00) == 0x400) // 超时
8 A, ?9 e3 e7 D6 W - #define WIFI_ASSOCIATION_ASSOCTIMEOUT 0x0401 // 连接超时
+ H( X- ], l, u$ A8 w: o - #define WIFI_ASSOCIATION_AUTHTIMEOUT 0x402 // 认证超时" b; x2 D- W. @6 O' J
- #define WIFI_ASSOCIATION_NETWORKJOINTIMEOUT 0x403 // 加入网络时超时
) Y0 k5 s0 A! d3 p$ ?. p/ _
, B2 I- k- E, a+ U# I0 S! `- #define WIFI_KEYTYPE_WEP 0" G3 G- I0 a* }! v3 L; S
- #define WIFI_KEYTYPE_TKIP 1- E4 E( l6 d Z5 |3 @' c
- #define WIFI_KEYTYPE_AES 2
9 ~& V. T5 X) \$ K( u, m* U - $ v( r$ {+ T) P9 c! z4 r4 _: V a
- #define WIFI_KEYINFO_KEYENABLED _BV(2)4 T- I# V9 j" z5 [# v
- #define WIFI_KEYINFO_UNICASTKEY _BV(1)
6 Q: M0 Y1 d' r! y8 a9 C - #define WIFI_KEYINFO_MULTICASTKEY _BV(0)+ |" ~" [, n* s8 g
5 J3 s' y: r b- #define WIFI_MACCTRL_RX _BV(0)8 S( ?2 e% Q6 A
- #define WIFI_MACCTRL_TX _BV(1) // 此位必须要置1才能发送数据!!!
4 O) o/ h2 P% s - #define WIFI_MACCTRL_LOOPBACK _BV(2)
' w2 ]: f+ t' y1 u2 k+ u" y - #define WIFI_MACCTRL_WEP _BV(3)
1 ?, k0 X, ^0 u% ~5 M: [6 b; L% S - #define WIFI_MACCTRL_ETHERNET2 _BV(4)8 g# E" ?% |; V* \9 S$ V" V) N2 @4 `% ]
- #define WIFI_MACCTRL_PROMISCUOUS _BV(7)* p x% v7 c* J) `
- #define WIFI_MACCTRL_ALLMULTICAST _BV(8)
$ n' x) ^, Q) f, ] - #define WIFI_MACCTRL_ENFORCEPROTECTION _BV(10) // strict protection x! ]* M# c7 A, F
- #define WIFI_MACCTRL_ADHOCGPROTECTIONMODE _BV(13) // 802.11g protection mode" V! p3 k% J3 o
- 2 B' M2 I2 v& X, `0 N. H) L9 I$ F% v
- /* BSS type */
# p L* C. o7 O, y% ^ - #define BSS_INFRASTRUCTURE 0x01
+ f& v5 G1 x; p) k6 ` - #define BSS_INDEPENDENT 0x02/ n) d+ f# @; S: s( l: y
- #define BSS_ANY 0x03 \9 u* I$ W: U% R5 Q Y
* B# w" a( V: Y; f. Y* @# i- /* Table 45: IEEE 802.11 Standard IE Translated to Marvell IE */9 c* s, @. J J8 c; M9 @
- /* PDF中的表45有一些拼写错误, MRVIIE应该改为MRVLIE */) m# i$ q( t: j4 u8 f; t7 U
- #define MRVLIETYPES_SSIDPARAMSET 0x0000, V* d' R& x; ]+ C. ~& {/ g8 z
- #define MRVLIETYPES_RATESPARAMSET 0x0001
! R- T: e: w! ^ - #define MRVLIETYPES_DSPARAMSET 0x0003
8 a( y! h' Y0 \$ J" j) w0 g - #define MRVLIETYPES_CFPARAMSET 0x0004
# m2 [3 z8 A, D2 J/ d - #define MRVLIETYPES_IBSSPARAMSET 0x00060 E5 |7 k2 G8 n9 t/ Y! f
- #define MRVLIETYPES_RSNPARAMSET 0x0030! x. A- H2 z6 e9 k& w
- #define MRVLIETYPES_VENDORPARAMSET 0x00dd4 f9 F9 |2 y. |3 i
- 4 S" A+ }+ R0 S( C) F: {. t
- #define MRVLIETYPES_KEYPARAMSET 0x0100
( I, g" r: m" T - #define MRVLIETYPES_CHANLISTPARAMSET 0x01014 y6 O5 H. t+ q" E2 H
- #define MRVLIETYPES_TSFTIMESTAMP 0x0113' Z9 a' u2 L" b4 P) `
- #define MRVLIETYPES_AUTHTYPE 0x011f
) H; M$ S- ~1 R1 w
. T3 P* h2 ]* S' z& w- #define MRVLIE_PAYLOADLEN(s) (sizeof(s) - sizeof((s).header)) // 已知结构体大小sizeof(s), 求数据域的大小* N( M7 B6 u5 t" x& A
- #define MRVLIE_STRUCTLEN(s) (sizeof((s).header) + (s).header.length) // 已知数据域大小, 求整个结构体的大小/ q. X" E9 A" W% T ]& J
; l2 M: G% @: ^5 @3 h- typedef __packed struct7 E+ W& w) n5 o! v
- {
) L. [$ r U% @3 R7 T& | - uint8_t type;8 O1 D/ b, J1 N' I0 k
- uint8_t length;" ^, ]8 T; y6 ]' Q1 b
- uint8_t data[1];
" ?, h7 Q, q y+ M$ r; V: y. S: Z - } IEEEType;- c2 Q( T: N3 N
- # T1 F' ~/ y6 u- B$ ]. r
- typedef __packed struct: W- U9 r7 }1 I' |
- {/ t2 w8 @& E6 ?& a. S; P
- uint16_t ie_length; // Total information element length9 f! A. H1 X' C7 G) C( i P
- uint8_t bssid[6]; // BSSID" C, ~9 y* V2 q2 ?
- uint8_t rssi; // RSSI value as received from peer
5 d8 Z( W8 w( s! R+ t9 { - % l5 _5 p+ b5 t& j4 F! y
- /* Probe Response/Beacon Payload */
. F' q" ^) ~& Q$ t6 b8 ` - uint64_t pkt_time_stamp; // Timestamp( @2 P% Z) L" s. c+ D; [+ i" w
- uint16_t bcn_interval; // Beacon interval8 r$ @. e# @5 R6 K: F% m
- uint16_t cap_info; // Capabilities information
( ~# Q+ ~5 t/ J* Y9 j3 K - IEEEType ie_parameters; // 存放的是一些IEEE类型的数据
/ T, v' X1 H" k - } WiFi_BssDescSet;& I4 }5 u0 H* S, i" G- ^) \9 r# F" n
- 9 ?9 p) P }$ H' d" t
- typedef __packed struct5 a9 h! R& }& H( u4 c
- {& j9 o" J4 s) \. f4 o
- uint8_t oui[3];6 A, R8 E+ [ C; @' S; G7 U7 Z
- uint8_t oui_type;
P% @1 P* i, n+ I - uint8_t oui_subtype;9 s2 U/ z; P/ D" P( Y& h
- uint8_t version;
# ]9 n( L% L) N; o- r+ a; ] - } WiFi_VendorHeader;# o2 Q5 }5 K3 ~8 m6 X6 y, A* z
- 6 K' F8 Z' q, @- }/ k
- typedef __packed struct
, A9 l) M3 g0 _$ v - {" V# h* V, y& P: N) q6 T
- uint16_t type;3 E. ^! p5 [0 a5 d% O" k i
- uint16_t length;4 p$ G$ Z- t' r3 \$ m9 D0 O9 C
- } MrvlIEHeader;
( T/ j2 z6 `7 p7 R - ) Q" u7 R0 |; x$ A" ^+ d% R) T8 k) e
- typedef __packed struct% | ~6 E5 E3 c3 @/ s( y* h3 G# q
- {8 h6 c8 O5 ?% j
- MrvlIEHeader header;
- J' E0 M; u5 q* Q' s - uint16_t auth_type;
c5 f3 F# N$ S ^1 X2 P: ^ - } MrvlIETypes_AuthType_t;
' k% p! j! ~3 N4 S5 b: F
% [& N$ C! B' A; y- K7 z" w- typedef uint16_t MrvlIETypes_CapInfo_t; // Section 7.3.1.4: IEEE 802.11-1999 Spec, |+ M, S" E0 S8 }5 r* J$ A. V/ O
- . C& k# [7 n) ~2 m) z9 R6 S
- typedef __packed struct
4 Y8 G1 ]0 [2 i7 A# x j" O - {. E/ p/ P! k5 w j' e( W
- MrvlIEHeader header;
& Z' X( `; j" H$ E6 Q - uint8_t count;
/ t0 Y; K$ X6 a- }2 e2 t - uint8_t period;6 h+ D) a$ y) N
- uint16_t max_duration;" G+ T1 R% t6 \) N: I+ U4 U
- uint16_t duration_remaining;5 r9 ^- v0 o. @$ r
- } MrvlIETypes_CfParamSet_t;7 n o8 Y8 _" e7 R( C7 _) w
- 0 U+ v6 K* x4 ^1 J6 W/ b
- /*typedef __packed struct4 x! m% I0 V9 }8 `% D
- {
. ?& a: {6 r% ~& q' y/ b/ V - MrvlIEHeader header;
5 y$ l, B& j( E+ ^3 D6 u: e T. }6 R - __packed struct
) M! b2 S7 l. T# A - {
" |! x8 ]% u/ Y3 c4 c, g# N! J2 T - uint8_t band_config_type;
# J' |4 I0 t% T* T% N' V3 y - uint8_t chan_number;
U% Z8 `# x% }& N9 p$ Q - } channels[1];! @% {: D& {- U3 F. r! b. l" O
- } MrvlIETypes_ChanBandList_t;*/
- v' ^( K+ f6 K3 r8 { - 9 R/ _/ `9 d# J$ C
- typedef __packed struct
) A: Z1 E: _( U+ ?, f4 E6 k( Z* e - {1 Z4 N+ w3 x& j% w8 _
- MrvlIEHeader header;2 C9 R& @1 ~. a* }
- __packed struct* v( j* A$ x# |+ K9 g, A: r
- {
3 S+ u1 J, j6 F4 t* W/ j, a - uint8_t band_config_type;2 N0 C, e# |) ]6 f. i u
- uint8_t chan_number;0 o/ z9 z# }- X9 \3 ?
- uint8_t scan_type; d, ~/ K' E; u
- uint16_t min_scan_time;; c9 {. q+ Q# Y* A! S
- uint16_t max_scan_time;8 `& g2 O E* J
- } channels[1];
/ K9 W4 s; F4 N4 `' G" m - } MrvlIETypes_ChanListParamSet_t;! h- R' J- H( Y9 N8 q
# B: K. _# x* h1 j' f6 X+ F2 Z- typedef __packed struct. `- ]2 B' k: e% {4 @
- {, j) d8 |" ]- j: r9 T
- MrvlIEHeader header;) Q7 @9 y- x. i6 j( P( j
- uint8_t channel;
' M: b1 U# n; u1 y - } MrvlIETypes_DsParamSet_t;
q5 p s2 D8 `
$ p( b1 D9 P z d% j' C& ]8 S- typedef MrvlIETypes_DsParamSet_t MrvlIETypes_PhyParamDSSet_t;
. X" \4 L. [2 \6 P/ u - . H9 o9 J* U: P, [2 |' {9 S3 y
- typedef __packed struct5 L$ |& Y g \1 Q/ N
- {
A3 f7 D8 u# n, q# O - MrvlIEHeader header;
O9 s+ \+ r/ L6 r" z/ z4 d9 } - uint16_t atim_window;% A0 h2 O4 Z# ^+ l4 t( k. p4 a
- } MrvlIETypes_IbssParamSet_t;
1 U3 q* v% h* \5 [, G- K - 0 q y- c2 [6 G6 _4 q1 {
- typedef __packed struct0 {" R! Y: c- p0 O1 E& }+ o$ |
- {* _: H% I$ d# }+ r, Q8 Y! E0 K
- MrvlIEHeader header;6 B6 [6 \6 M& v9 e, ~; m
- uint16_t key_type_id;
5 O8 R6 `- z' t( q! @ - uint16_t key_info;
' k5 N+ ^% v8 G% s# d6 g. C - uint16_t key_len;# U% M( s9 m- ?2 \( c d4 I
- uint8_t key[32];7 C9 S }8 @& \ v. s V
- } MrvlIETypes_KeyParamSet_t;
' Z* n- c* i9 m" h; A7 V( N - 3 G; I. F* v' [, l4 |
- typedef __packed struct
. J$ |4 k2 n% T: \. q - {
9 j+ b( k/ Y8 T. Q: b6 U - MrvlIEHeader header;" k5 V! ~5 n* `) t- M
- uint8_t rates[14];
& ^/ p' Y' {0 ~, ?% ^9 n% a - } MrvlIETypes_RatesParamSet_t;( F8 K) N8 b& @0 v8 o4 f
- ; V# r- [3 q* Q4 h% A5 x
- typedef __packed struct
$ y' g3 y6 f v7 F" Z F* u7 X, z( h0 f - {
r# X# {1 J# j2 f5 h* Z - MrvlIEHeader header;$ s& |1 X9 A) m G
- uint8_t rsn[64];
/ ^/ U% A' W5 [- _ - } MrvlIETypes_RsnParamSet_t;: m" N# P! t' B
4 _! r$ T: S4 M( }3 P- typedef __packed struct/ T% Z+ Z0 S! u3 D
- {
, }: C( ~6 v# }( A - MrvlIEHeader header;. ?. X' J7 d y0 {
- uint8_t ssid[32];. O6 R/ g7 b( p
- } MrvlIETypes_SSIDParamSet_t;
4 ]+ H& O' z9 f* M4 N! K+ W" Q9 Q8 O. W! S
& q9 _1 ~+ {+ o& R- typedef __packed struct- x2 k; j+ {& J
- {* k O5 u/ S- k, [/ f4 t+ k
- MrvlIEHeader header;6 h* W5 a/ H2 W- w8 }& q
- uint64_t tsf_table[1];
! o8 `) b) W+ v$ D; l - } MrvlIETypes_TsfTimestamp_t;. K/ t y! c& y' y
5 ?+ A& y1 f8 F1 `* Y- // 整个结构体的最大大小为256字节
5 C# x; G/ i& ~# g - typedef __packed struct
9 i* ^$ C1 C( ]/ D/ \+ S* b! ` - {) q5 k: H5 a+ [; C8 K' p4 n* Q
- MrvlIEHeader header;
, Q6 C4 P3 u+ {& |6 O T - uint8_t vendor[64]; // 通常情况下64字节已足够
. B/ g8 E2 ] o. @% c6 v - } MrvlIETypes_VendorParamSet_t;
4 J4 v. {. p% c; z+ ]1 T9 i
' V) `4 X B1 ~9 e/ c- typedef __packed struct
" m5 b5 D+ K$ b! @; b6 ` P - {2 }3 H4 ]& ^: y. \7 P' c% W
- uint16_t length;
% t# j( B$ [" \/ s - uint16_t type;
' c* G" c# [! S - } WiFi_SDIOFrameHeader;% }2 d! I1 x6 K* E
6 u0 J1 _: Y. c6 b- typedef __packed struct0 [# B$ E% Z7 |
- {4 J* w- B# f0 f2 T* w& w9 Y, e
- WiFi_SDIOFrameHeader frame_header;
+ Y( H4 U' A. D* ?7 Q6 W, | - uint16_t cmd_code;4 s5 g6 M+ I' H0 G1 g- _
- uint16_t size;
' e8 Q( O0 D/ {- I) B5 p: b - uint16_t seq_num;2 m+ ^( M3 D6 Y! q. [+ b( ^% p
- uint16_t result;
$ Y' H5 [1 Z' v+ t! q- E: v/ k - } WiFi_CommandHeader;7 O3 H0 ~! L* I; Z% b. l
; j; D+ ~9 n4 C7 B- /* Table 2: Fields in Receive Packet Descriptor */4 A: A+ s$ q0 A# D! U
- typedef __packed struct7 X# X% K% A6 K& |# e; a# c% N
- {
+ u0 e$ ^, W9 @3 i; g: \) B - WiFi_SDIOFrameHeader header;
6 w, j e( m6 a; e! ^ - uint16_t reserved1;0 a# P1 [: s* r# h' i
- uint8_t snr; // Signal to noise ratio for this packet (dB)
, L* B' v1 E. [ - uint8_t reserved2;
' Y( N& O$ M+ w+ K- j - uint16_t rx_packet_length; // Number of bytes in the payload
/ k2 q- B& b" ?, v+ p - uint8_t nf; // Noise floor for this packet (dBm). Noise floor is always negative. The absolute value is passed." r, C8 `, _$ s) G% a/ U! w5 R
- uint8_t rx_rate; // Rate at which this packet is received9 |/ `, K$ y2 h' K
- uint32_t rx_packet_offset; // Offset from the start of the packet to the beginning of the payload data packet/ s4 @) \$ o* @/ ?& [; A
- uint32_t reserved3;4 X2 x. q. v7 D7 l( D; B
- uint8_t priority; // Specifies the user priority of received packet4 \5 ]7 f" q$ j7 |: {& y
- uint8_t reserved4[3];
6 w0 n: R. n5 _8 j: s i- l+ A - uint8_t payload[1]; // 数据链路层上的帧
4 F/ ]( ~' R0 s - } WiFi_DataRx;/ L) {8 [ h/ B- K9 I
- 3 j0 H: K: Z* ~" n
- /* Table 3: Fields in Transmit Packet Descriptor */* T2 U. c: Y! f! \0 g. K1 J8 h
- typedef __packed struct
. |( A! |. i" l- ? - {
1 E, q/ I: t G" { - WiFi_SDIOFrameHeader header;
* G0 B/ J; \9 q! s! I* G. b - uint32_t reserved1;, y4 i$ m3 {+ B0 j: {
- uint32_t tx_control; // See 3.2.1 Per-Packet Settings
+ W9 t8 p+ b' y$ E* `4 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# P J+ Z1 O3 b. ~: j. @ - uint16_t tx_packet_length; // Number of bytes in the payload data frame8 N2 O3 Q6 b( \/ H4 V) B
- uint16_t tx_dest_addr_high; // Destination MAC address bytes 4 to 5
! T- h; g) l6 r( h3 c9 F% d - uint32_t tx_dest_addr_low; // Destination MAC address bytes 0 to 36 V6 z: }# e8 ^+ ?" ~% l* i
- uint8_t priority; // Specifies the user priority of transmit packet
% Q* E. Q, @6 Y/ l4 b - uint8_t flags;
5 Q% ], ^0 I- ^, y# \) V% F - uint8_t pkt_delay_2ms; // Amount of time the packet has been queued in the driver layer for WMM implementations
: W. }9 E. \7 O" F4 b }# ? - uint8_t reserved2;; K+ a g4 ~9 ?- k2 {5 X& m
- uint8_t payload[1]; // 数据链路层上的帧7 f/ ~" X: J6 ]7 P3 [
- } WiFi_DataTx;
( y! u; M. ^0 O* t
3 b. p$ _$ q, n* [2 H- typedef __packed struct
! p" u3 _) ]3 s& C" z* P$ i - {
Z1 m* S! G" } - WiFi_CommandHeader header;
) k1 V S( d0 B6 @3 t% L$ ] - uint16_t action;0 r3 q3 p9 i) M$ l N4 {
- } WiFi_Cmd_KeyMaterial;6 N+ K& T% i; U
. e) b# M7 K; I; Z- typedef __packed struct
1 G' Q7 A# `! A! c- A& d1 V1 U" c - {
, V$ \' X# M$ `5 _: u - WiFi_CommandHeader header;
6 A' w/ i+ g+ L9 ~! f% N - uint16_t action;
$ t4 d# m7 d5 i - uint8_t mac_addr[6];
7 j6 m A4 f; o6 P: Q7 I0 O - } WiFi_Cmd_MACAddr;1 p M8 X8 l$ a4 W" Q+ h
: _3 o6 ~( l& g; A) H' d: E7 N. @- typedef __packed struct: a o5 R; A2 Z, m6 Q' }8 f% t4 r
- {2 p0 W X" l& \$ S0 Y; A
- WiFi_CommandHeader header;
* K6 S8 V. ~$ f - uint16_t action;8 J# Y8 c0 f, C; |6 A, w# m
- uint16_t reserved;3 n' g' { o+ W6 `: N
- } WiFi_Cmd_MACCtrl;
8 ~, U! N0 i+ Y
9 ]8 g& H7 n9 m# h3 Q) n- typedef __packed struct
9 |2 v" u& }- i* O& R, S - {
4 _( ?" J" D' D* S @0 C! W! Q! @" B - WiFi_CommandHeader header;
0 [" Y6 }# l2 T# j7 c3 Y" ? - uint8_t ssid[32];
6 U- B/ j& C1 J* s& @' D/ g - uint8_t bss_type;# M4 O8 K2 d1 {9 M& \4 r
- uint16_t bcn_period; p' Z* B( K5 h( }
- uint8_t reserved1;
; X% l# F: x( r8 o6 \ - MrvlIETypes_IbssParamSet_t ibss_param_set; // ATIM window length in TU
0 a$ }& u9 Q& S - uint32_t reserved2;5 u2 U+ Z' F+ z
- MrvlIETypes_DsParamSet_t ds_param_set; // The channel for ad-hoc network' c7 B% [/ ^/ s/ F- e: n9 `
- uint16_t reserved3[3];
/ n% n$ |) U0 } @0 ^ - MrvlIETypes_CapInfo_t cap_info; // Capability information
i# A- c1 p2 R9 V. p1 ?) w% C - uint8_t data_rate[14];% m, l& k% H% y9 E1 z
- } WiFi_CmdRequest_ADHOCStart;
6 `; i: J7 \4 v9 B3 M" v. @' W - ( r2 |$ n- e2 O$ Q
- typedef __packed struct* ^4 N! Z2 X& G+ M) g/ F8 E
- {
: E/ l9 |% W7 ] - WiFi_CommandHeader header;
0 x' }- w' r V) f! ? - uint8_t peer_sta_addr[6]; // Peer MAC address3 Y8 B/ ?% U0 R1 j! b" g
- MrvlIETypes_CapInfo_t cap_info; // Capability information
6 |3 v; j3 \2 L& `* n0 R - uint16_t listen_interval; // Listen interval5 m8 R0 O" Q5 v2 p" v3 b
- uint16_t bcn_period; // Beacon period
& l- s6 m' n7 W+ G" I2 I/ t - uint8_t dtim_period; // DTIM period2 X/ L# ^2 i0 W2 K- V
- } WiFi_CmdRequest_Associate;3 Q4 i, t5 p a; x* y4 l8 J! }% ~ d
$ Z8 D/ s, U# l: p y- typedef __packed struct$ i; O+ s$ I$ T# s1 f' w9 K- g
- {" a/ G0 T: z; A: q3 S
- WiFi_CommandHeader header;
: p P7 T# l- T3 w4 X - uint8_t bss_type;* V* b0 V+ k) W0 d+ d* F. i
- uint8_t bss_id[6];
3 d. B9 F1 P" U- E! z2 F- a - } WiFi_CmdRequest_Scan;
0 U/ p7 c: a+ @$ ^/ R$ x, h: p - & o. W) o! D! Q- Q7 |
- typedef __packed struct
3 s$ ^+ V. t' @) I - {5 G4 T: a; Q) z: A* i |
- WiFi_CommandHeader header;/ R2 z. y6 t( L4 r* T7 q
- uint16_t capability;0 Z, C+ Z: y9 R. k) j5 m$ O0 n7 T% i
- uint16_t status_code;
/ B) W& q$ F; T - uint16_t association_id;
# D4 p4 \% _8 I3 n( S' D - IEEEType ie_buffer;
; R4 Q% K5 A- R5 b% b3 C: j - } WiFi_CmdResponse_Associate;. L1 B1 }8 U. i: k3 ]. U1 _! a! j. x
- 0 z0 e6 O+ H2 G, F$ t) G! {/ Q
- typedef __packed struct
( |. q- x! w0 `. `# i - {
$ U9 L9 \5 S! m% q9 \1 K' i - WiFi_CommandHeader header;7 V& O. R; }: r8 s: O$ Z- q& D
- uint16_t buf_size;2 o# `5 X' e. J
- uint8_t num_of_set;% d3 C( ?& |) |
- } WiFi_CmdResponse_Scan;+ T' [' n l( L: I# U
- 8 V t A4 h& g3 [" [0 w
- typedef __packed struct8 x! p% U6 ~) T- x. o
- {7 a; T% ~3 P* f3 }
- MrvlIETypes_SSIDParamSet_t ssid;
: h8 |( e" g) z; e - uint8_t mac_addr[6];
: i3 R3 c8 |) m - MrvlIETypes_CapInfo_t cap_info;! [) y* k7 v5 `7 t2 K# Y7 A
- uint16_t bcn_period;! g' s* O F: E" Z2 _4 o# b7 j
- uint8_t channel;
; X$ u7 W* X' O2 m W( P# D - MrvlIETypes_RatesParamSet_t rates;' U3 ^% U1 ~1 e4 s1 D. C+ p
- MrvlIETypes_RsnParamSet_t rsn;
7 \( Y* d) d/ B! a2 K* x& K0 j - MrvlIETypes_VendorParamSet_t wpa;
@- ~1 Y; }2 i% d1 T) P& o7 U - MrvlIETypes_VendorParamSet_t wwm;2 {, b3 j/ U& s! M2 A
- MrvlIETypes_VendorParamSet_t wps;
/ c; h+ O4 M7 b9 r5 `3 V - } WiFi_SSIDInfo;, c1 p {5 ~' D" U( U5 i
- h' c( m+ ]$ s. |3 ^ p/ \, K- #define WiFi_DropPacket() WiFi_ReceivePacket(0, 0)! K. j; B: F' o M7 ~, G1 b
- #define WiFi_GetBlockSize() _BV((SDIO->DCTRL & SDIO_DCTRL_DBLOCKSIZE) >> 4)
; v5 R8 p) p; V i, r. Q - #define WiFi_GetMACAddr(addr) WiFi_MACAddr((addr), WIFI_ACT_GET)4 M! f0 k) o( ^3 i$ b/ c$ l1 C k
- #define WiFi_PacketArrived() (WiFi_Read(1, WIFI_CARDSTATUS) & WIFI_CARDSTATUS_UPLDCARDRDY)( s, G, R0 s" ^8 [8 b/ Z
- #define WiFi_ResendCommand(cmd) WiFi_SendCommand(0, (cmd), 0)$ b7 A9 o1 [1 J. K) `( k% l
- #define WiFi_SetMACAddr(addr) WiFi_MACAddr((uint8_t *)(addr), WIFI_ACT_SET)
1 V, Y) e7 p6 ]/ v - #define WiFi_ShowShortResponse() printf("Command response received: CMD%d, RESP_%08x\n", SDIO->RESPCMD, SDIO->RESP1)5 J# V) X( f" f9 y+ Q7 j+ x. ]' a
7 E9 q, k8 q1 w. ~+ _- uint16_t WiFi_Associate(const char *ssid);5 N( ^* u6 X, D# U* `$ \' P
- void WiFi_CheckCmdTimeout(void);, ?% f' l2 r1 g, x3 Y# z
- uint16_t WiFi_Connect(const char *ssid, const char *password);
5 q) D4 x* m; m( ?8 ? - uint8_t WiFi_DownloadFirmware(void);
: K* e1 J! `$ k0 E" u% R - uint16_t WiFi_GetPacketLength(void);
2 E# V9 J: _) X) X) P, G, h - void WiFi_Init(void);
. ~5 ~+ x. g2 u/ `, }$ C9 l - uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action);
) |, ]1 Q! o k' l - void WiFi_MACAddr(uint8_t addr[6], uint8_t action);
& r8 d( _3 P. R4 ?, L& h6 D - void WiFi_MACControl(uint16_t action);
' ^0 i8 [# @; i: F9 g' S, c - uint16_t WiFi_PacketPending(void);
2 M+ O( E$ e) \% k! T - void WiFi_PrepareTimer(uint16_t nms);% P5 ~- K+ |" z; C1 a: d4 R0 y
- uint8_t WiFi_Read(uint8_t func, uint32_t addr);* n+ W" t: @% k! B
- void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
0 T- K- d. k3 \, |6 ?4 z1 @- J - uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize);* y) {: n7 n9 G' W3 _
- uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize);0 L5 r% F( `8 e& D
- uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize);
7 E9 Q" y% `7 f - void WiFi_Scan(void);
/ o, ]4 O' H1 y - uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize);- w" Z' ` `; \6 a7 D' B$ C
- void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags);
2 D7 t, K0 W$ I - void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags);
! C2 q6 F' B% W3 U9 I( I7 D - void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size);! y3 o; a8 Y7 p0 K+ d! t
- uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len);
9 ~& I' {" j& R* K: v - void WiFi_SetBlockSize(uint8_t func);
' m. U0 v8 l1 U2 e. ^) B$ Q - uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len);
- Y6 q) D5 s2 A1 d" f; j - void WiFi_ShowCIS(uint8_t func);- t* V$ O- D; a0 g! U: V4 y
- void WiFi_ShowKeyMaterials(void);" A5 d7 Y$ x; R1 Z
- uint8_t WiFi_StartADHOC(const char *ssid);
3 ]/ V: {! t z; O7 m - uint8_t WiFi_Wait(uint8_t status);" d5 ] j0 A5 J' E) n$ G8 B
- uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value);5 X+ K% i3 q, \: V0 r/ W
- void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags);
z# _6 n: J5 }+ v# { - uint8_t WiFi_WritePort(const void *data, uint16_t size);" O- i0 L2 L J* x1 p, {
复制代码 【WiFi.c】
1 S7 T) W! ?9 w4 V8 V2 N. v/ `$ |/ k- #include <stdio.h>
5 k+ m c7 D2 G6 p) N - #include <stm32f10x.h>6 {) l! f7 ?8 s2 q4 n& z! H
- #include <string.h>& `+ W* X+ m" k# g/ n9 f
- #include "WiFi.h"/ O1 p0 q2 W! G' c2 e; J7 t6 I
3 e2 k. U4 V9 b/ [- extern const unsigned char firmware_helper_sd[2516];6 e7 ?0 d& o" h7 o7 A& F% d
- extern const unsigned char firmware_sd8686[122916];
( G. [/ p' @9 [$ g/ I P
, i# `: K) S7 I! o: x# ` T- //const uint8_t wifi_mac_addr[] = {0x62, 0x1d, 0x2f, 0x00, 0x4e, 0x2d}; // MAC地址的第一个字节必须为偶数! 否则为多播地址% s5 O( N* z0 \! i q' g8 M( R8 p% Z
: Q# ~- e, [5 j) K7 t- static uint16_t rca;
( N9 C% {: y: T% Q8 e5 w% e. n3 C% Y - static uint16_t wifi_timeout = WIFI_DEFAULTTIMEOUT;
0 W2 U; u9 T5 l; f - static uint32_t io_addr;6 \% x- i. a, d' c
- static uint16_t wifi_pending_size = 0; // 未读的数据包大小( Y4 I) w; q: E6 s# [
- : L( ^" G) I- V2 H$ [! y
- void delay(uint16_t n);! r1 {7 p; Y, l: k: }' `$ c
- void dump_data(uint8_t *data, uint16_t len);5 y# K- K5 X! s e6 F; T/ e
' }" U7 i) E6 W+ E; {% z/ M- /* 关联一个热点 */
: ]& X4 G& W& G0 E8 j$ u - uint16_t WiFi_Associate(const char *ssid)2 R7 i: ~7 c A. W& h
- {! L! z' m9 m2 p0 E& O3 R$ y7 G
- uint8_t buffer[2048];( X" g, p) t. c/ G
- WiFi_SSIDInfo info;
4 |, h+ k' J6 o& [( [" n - WiFi_CmdRequest_Associate *cmd = (WiFi_CmdRequest_Associate *)buffer;0 ? q/ x- W; z1 a" M
- WiFi_CmdResponse_Associate *resp = (WiFi_CmdResponse_Associate *)buffer;: b! r1 H: Q- J$ R
- MrvlIETypes_DsParamSet_t *ds;' a% \7 F1 ^ F" w$ p
- MrvlIETypes_CfParamSet_t *cf;
% q1 U, t. s& I3 i - MrvlIETypes_AuthType_t *auth;
6 ]) X1 c3 C9 u" @- R' d% |' H - MrvlIETypes_RsnParamSet_t *rsn;9 ]0 W; K9 {/ k
/ s0 u* x- o6 r/ d% i" O( s- if (!WiFi_ScanSSID(ssid, &info, buffer, sizeof(buffer)))
( J) n$ e# n' i- O - {0 @6 |+ ]4 v$ B _) X E
- printf("Cannot find AP: %s!\n", ssid);
8 e2 F. k7 [" s) w! o6 W - return WIFI_ASSOCIATION_NOTFOUND;( c- T% u6 G8 `/ x6 X$ i
- }
2 F$ Y) m# }" V% `3 f -
6 G; Y( |7 V9 |/ G( q2 c5 H - memcpy(cmd->peer_sta_addr, info.mac_addr, sizeof(info.mac_addr));1 q5 R% Y: V& K$ c" ^/ v5 V5 H' {
- cmd->cap_info = info.cap_info;
. R. i; R! |) K0 ]. d1 f - cmd->listen_interval = 10;
9 n; d! c/ v6 N% X" A - cmd->bcn_period = info.bcn_period;
8 Y6 \, p6 c5 ?1 R3 f# j - cmd->dtim_period = 0;
3 N% x/ G/ z/ Q4 ^2 K2 q6 f$ m - memcpy(cmd + 1, &info.ssid, MRVLIE_STRUCTLEN(info.ssid));
1 q% Z( u+ Q. l u, W4 R0 s" M% X- E - 7 h) K( V' u! ~, ]
- ds = (MrvlIETypes_DsParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info.ssid));
& H# @/ R" K2 f& h - ds->header.type = MRVLIETYPES_DSPARAMSET;6 i1 o X5 \5 S# M
- ds->header.length = 1;2 }- s# f( m. F- N+ P0 j D4 F
- ds->channel = info.channel;
! k" H8 v \* Z W -
4 \' d) u% l) e0 g' x2 | - cf = (MrvlIETypes_CfParamSet_t *)(ds + 1);( C) K& o8 |8 r; m6 c( ^# ]+ C
- memset(cf, 0, sizeof(MrvlIETypes_CfParamSet_t));
) l+ j, W1 v! _; \# K - cf->header.type = MRVLIETYPES_CFPARAMSET;
# g7 }( b: |0 N/ v - cf->header.length = MRVLIE_PAYLOADLEN(*cf);7 s0 ~1 I# D$ Y5 _- ]
-
6 R/ a3 C y' E8 D6 ~0 } - memcpy(cf + 1, &info.rates, MRVLIE_STRUCTLEN(info.rates));
3 n8 _* Z. L6 g- n' I2 y) H4 | - auth = (MrvlIETypes_AuthType_t *)((uint8_t *)(cf + 1) + MRVLIE_STRUCTLEN(info.rates));
, A, j# m- b. _6 j - auth->header.type = MRVLIETYPES_AUTHTYPE; }5 ~& g$ q3 X E7 J
- auth->header.length = MRVLIE_PAYLOADLEN(*auth);+ \7 K i- A: [' T
- auth->auth_type = AUTH_MODE_OPEN;4 z% a i, X! ]
-
- D3 o, _- E8 n" p7 f - rsn = (MrvlIETypes_RsnParamSet_t *)(auth + 1);
; t9 @( b- k8 l; G6 q - if (info.rsn.header.type)
Q1 h+ v q D) `9 K - {
& [7 E! w3 ^5 e - // WPA2网络必须在命令中加入RSN参数才能成功连接
`+ d' r: U7 W - memcpy(rsn, &info.rsn, MRVLIE_STRUCTLEN(info.rsn));
?0 Y2 z9 E9 c* Q w - WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer + MRVLIE_STRUCTLEN(info.rsn));. w. v( O& h4 y
- }
7 W1 a# U, @; B+ c/ `. R - else2 u$ {8 P6 Q0 y! _8 d
- WiFi_SendCommand(CMD_802_11_ASSOCIATE, buffer, (uint8_t *)rsn - buffer); // 其余网络不需要RSN参数$ W2 T* P! E; X% |, n
-
' z) \0 S* v, F2 d. J - if (!WiFi_ReceiveResponse(buffer, sizeof(buffer)))! W4 q O: {9 V) [6 i0 o9 x
- {
4 H( S) u) Z* `2 L( P/ U/ t+ a0 ] - printf("Association with %s failed!\n", ssid);- R/ A2 Q$ M' H4 ]4 k" z
- return WIFI_ASSOCIATION_ERROR;) J" }$ }) v$ W# E
- }
) I& x" e; V1 m" i, O; i1 P -
, [1 W7 U2 m: D2 F- |! _ - //printf("capability=0x%04x, status_code=0x%04x, aid=0x%04x\n", resp->capability, resp->status_code, resp->association_id);$ _9 |3 \8 m# ?
- if (resp->association_id == 0xffff)
7 m1 j4 j) }1 d/ E* T& s& I' ]5 @ - return ((-resp->capability) << 8) | resp->status_code;
$ p' D1 {3 J3 z1 f - return WIFI_ASSOCIATION_SUCCESS;
$ n# c1 V$ k( t3 J; ~% z. q - }
b3 a" s( ?4 L1 F8 m4 G - 4 L* E, f1 J) m) O
- /* 检查命令是否收到了回应, 若没收到则重发命令 */
2 e( N" C' ~3 n7 x# k - void WiFi_CheckCmdTimeout(void)
7 B8 s+ b' n8 J3 K4 } - {- {8 _+ t. w6 p; c# C
- while (SDIO->STA & SDIO_STA_CTIMEOUT) Y* j8 C4 Z0 _/ D& w3 [, C
- {
' {# U9 W0 d' S: R' z6 ]! U - SDIO->ICR = SDIO_ICR_CTIMEOUTC; // 清除标志, B2 i' v$ F9 x7 z& y
- SDIO->CMD = SDIO->CMD; // 重发5 S5 b& Y- G0 C! ]% @4 m1 J
- printf("Timeout! Resend CMD%d\n", SDIO->CMD & SDIO_CMD_CMDINDEX);& a1 l/ N6 }+ g" a# D" x( {3 J
- while (SDIO->STA & SDIO_STA_CMDACT);# Y+ j% N; z4 n4 N* E
- }% x5 L' v. w" e- S. k% a# T
- }* b) h9 ~9 n3 Q% i e) S
- ' W9 P4 m9 P+ r$ M# }, J
- /* 连接WiFi热点, 并输入密码 */6 h. ^% A$ I0 b/ C: Q% R6 o
- uint16_t WiFi_Connect(const char *ssid, const char *password)
. ]0 f# e& k, y d4 } - {+ X1 e& G2 n7 O2 N
- uint16_t ret;
8 g5 U6 O- l# k2 y - do
7 c6 }) T+ p# L! ?8 d, g - {
1 e' G8 R! W, A+ g3 h" E - ret = WiFi_Associate(ssid);, G! D: R8 J7 z, k% t
- if (ret != WIFI_ASSOCIATION_SUCCESS)( J: c$ `3 C" v/ H' F
- {
. o( J' }( h2 ]8 s5 [! v - printf("WiFi_Associate returned 0x%04x\n", ret);, ? }$ ?9 P' K6 z# X: L7 U
- delay(2000); // 等待一段时间后重连
}, {' c+ a* H n; ]; |% |1 v - }/ N; P7 C6 P( ~8 `. W
- } while (WIFI_ASSOCIATION_TIMEOUT(ret) || ret == WIFI_ASSOCIATION_NOTFOUND); // 若连接超时, 或未扫描到热点, 则重连
) k8 P6 D9 o3 ~% g& S+ J; l - 8 I) w( b3 W5 ^( w2 R0 I
- if (ret != WIFI_ASSOCIATION_SUCCESS)9 T5 @% A" \; }+ O: A. g7 J
- return ret;% a( g. x% x2 h3 o
- ! G( D' ~( N/ P2 V6 T
- printf("Connected to %s!\n", ssid);
) y# S. d6 ~- P! l0 B1 I- c. Z c. h - return ret;$ f8 U1 I8 B5 N/ j
- }5 d8 E& a# o3 C9 h' t. w5 [
, b3 I9 e1 q) A3 Z- /* 下载固件 */
1 M! X/ }* ?) U. S& V - // 参考文档: marvell-88w8686-固件下载程序说明.doc
8 ]5 Q( c% ?* m2 r! D - uint8_t WiFi_DownloadFirmware(void)
% w" t. ~( h: [1 j/ u8 P - {
9 c$ t$ {$ w; D, _* {9 v) W8 o' B% R- v - uint8_t helper_buf[64];( T, P" c1 r' h$ h" X0 k
- const uint8_t *data;
: k6 c, @; h& J# [$ [2 m - uint16_t size;% m* W7 F5 _0 ^* x
- uint32_t len;
- o$ }$ ]+ n1 i J! O - 8 N" d" w. R* x/ y0 p, u
- // 块大小设为32+ p- G1 w, r+ T# p
- SDIO->DCTRL = (SDIO->DCTRL & ~SDIO_DCTRL_DBLOCKSIZE) | SDIO_DCTRL_DBLOCKSIZE_2 | SDIO_DCTRL_DBLOCKSIZE_0;' l4 w, A9 ] P$ |9 u8 U+ ~- j, q
- WiFi_SetBlockSize(1); // 应用到Function 19 F9 k. R* S% |% N
- : r% a" V; m! }5 w8 v, v d
- // 下载helper% e' f9 K% S$ Q, {+ X. K: I
- io_addr = WiFi_Read(1, 0x00) | (WiFi_Read(1, 0x01) << 8) | (WiFi_Read(1, 0x02) << 16);
9 m( C5 _( T$ u: U5 c S; h4 e - data = firmware_helper_sd;* e. M) n& f1 p, D% M4 K
- len = sizeof(firmware_helper_sd);
: p" l" F m5 f# R- Q7 O - while (len)4 x V N9 H& M, E" T @8 g' B
- {( b* e* O% D4 L2 H- k. F! x9 X
- // 每次下载64字节, 其中前4字节为本次下载的数据量- k# T0 u! G/ h9 N9 O
- size = (len > 60) ? 60 : len;& y H' ~8 Y' V
- *(uint32_t *)helper_buf = size;
: M7 m/ |4 H) n - memcpy(helper_buf + 4, data, size);9 o* c, B- s; }
-
4 U5 i4 a4 I7 \7 b - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
1 S3 m; w& v, E1 g - WiFi_WritePort(helper_buf, sizeof(helper_buf));
8 q0 u3 T& X; D8 ~9 Y - len -= size;9 [ e0 {3 ^( @. e t' v# k2 S
- data += size;$ ~ H# _2 ~2 Z! s! C- j N
- }% `5 v I/ x- C; H" N( x
- *(uint32_t *)helper_buf = 0;
6 _4 L* B$ U5 z& P( ]+ D" k - WiFi_WritePort(helper_buf, sizeof(helper_buf)); // 以空数据包结束
8 }& O) i$ s2 ` - 8 G) f, f) L o' h3 P1 u0 T
- // 下载固件
7 ?+ N/ r( W1 _* U - data = firmware_sd8686;
+ {! g% I: C2 }7 K0 e - len = sizeof(firmware_sd8686);7 c' s& r! l% x2 A z# f7 O7 e
- while (len)7 U. z! n, c5 s: o" L' ^/ |8 F
- {
0 N! i* ~6 y9 B7 F- ^# {+ W; } - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY);
6 c7 s: Z% v* | - while ((size = WiFi_Read(1, WIFI_SQREADBASEADDR0) | (WiFi_Read(1, WIFI_SQREADBASEADDR1) << 8)) == 0); // 获取本次下载的字节数
* Y2 l- H; H/ f - //printf("Required: %d bytes, Remaining: %d bytes\n", size, len);$ z- }: v- S9 e, I4 t3 S S! X
- 8 a+ D. ]! L+ S! {
- if (size & 1)- m7 F& g- |0 N/ d9 N% q: S) j
- {
& Z) D% g3 T+ b- I3 l0 u" O - // 若size为奇数(如17), 则说明接收端有CRC校验错误, 应重新传送上一次的内容(这部分代码省略)/ K3 K7 t5 B$ z7 W% B# c, G/ z' F2 P
- printf("Error: an odd size is invalid!\n");
. h t5 D% {, r" n - return 0;
4 e. d/ x! o" R0 _ - }4 d7 E+ u, k2 W/ Z) U# h
- if (size > len); q% v. f8 W+ W/ [* Y
- size = len;
6 q; ^+ B$ \$ I+ p - 2 F: L: o- t& v& k) i
- if (!WiFi_WritePort(data, size))
! [) r" { [; m* i/ e" } - {
: j8 [( Z: G4 F% h4 u - printf("Data transfer error! SDIO->STA=0x%08x\n", SDIO->STA);, P( x/ K0 K$ K; J2 N& d
- return 0;5 S7 B# n& a ^4 B
- }- a3 O/ h$ Z2 a# p
-
" x) ~3 H8 j9 F) X- ?4 ?- w - len -= size;, M# `* c$ _) f+ Q% }, D
- data += size;
: F L& I- _- K& z - }
8 A! Q$ W6 ?3 }) s& x - 0 x/ s3 |( }; q/ d8 x3 y6 R
- // 等待Firmware启动5 _$ R7 P& c7 s: @9 k: ?
- while (WiFi_GetPacketLength() == 0xfedc);3 I/ L" W7 j5 _6 \3 P/ [( ]9 o
- printf("Firmware is successfully downloaded!\n");
2 T- E' _# h/ I - return 1;0 p2 G/ [* t9 r5 c/ ~: @& x
- }/ {0 G! B8 G, \- O* w
& c. B$ z8 R) e$ G/ d$ S) r- /* 获取数据帧大小 */ S, c- p3 v& @
- uint16_t WiFi_GetPacketLength(void)
' f, U. N; L& v: W1 u3 j( @ - {
0 r7 h' F/ ?: L. k - return WiFi_Read(1, 0x34) | (WiFi_Read(1, 0x35) << 8);7 r6 D2 _8 v8 e+ ~% D1 e T
- }
1 O* D* M% a/ `" r4 ]$ m
1 F4 g9 q% v% c/ @- /* 初始化WiFi模块 */+ u: k4 S! M, F8 i( w: o' T5 _
- // SDIO Simplified Specification Version 3.00: 3. SDIO Card Initialization9 `7 Q0 h! U# z7 ~$ O7 t
- void WiFi_Init(void)
/ X: ` H- n; u - {% U2 c& a X' U3 W$ d$ [) Y
- printf("Initialization begins...\n");
; ~' S+ ^1 C1 A0 D3 } - SDIO->POWER = SDIO_POWER_PWRCTRL;
2 Z- d1 d/ x, W, Z+ F$ [1 S - SDIO->CLKCR = SDIO_CLKCR_CLKEN | 178; // 初始化时最高允许的频率: 72MHz/(178+2)=400kHz4 s$ x. N! j% h
- delay(5); // 延时可防止CMD5重发
' v( u5 b/ C6 v/ ^5 W2 b! u -
$ n! q, D; n0 @ - // 不需要发送CMD0, 因为SD I/O card的初始化命令是CMD52
: w, u8 I9 T d6 O# | - // 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)- h' B- Z$ f I
-
0 D) m' m6 b! R3 k8 x) P, _3 N - /* 发送CMD5: IO_SEND_OP_COND */
6 N2 N6 v. @" O - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 5;9 ^' w. @7 b8 I
- while (SDIO->STA & SDIO_STA_CMDACT);6 C4 @. U% r" W! E
- WiFi_CheckCmdTimeout(); // 为了保险起见还是要检查一下是否要重发命令
4 o, T5 q2 s6 T: T" R( T4 |) y - if (SDIO->STA & SDIO_STA_CMDREND)
# k- G: F( ^# W' G - {& l; \, T1 {; q6 V2 i( t
- SDIO->ICR = SDIO_ICR_CMDRENDC;
" z5 U9 ^& |7 V8 J; }2 f. S - WiFi_ShowShortResponse();
- s- q, D; j3 U2 s" s/ f - }2 i0 a- g2 x1 i6 e
- " O, @: H' t/ M4 p, v6 [& {+ G
- /* 设置参数VDD Voltage Window: 3.2~3.4V, 并再次发送CMD5 */
/ A8 e" p' E3 }& P, h { - SDIO->ARG = 0x300000;# ~# q( g6 A, ]3 C/ w: H2 M# @- u
- SDIO->CMD = SDIO->CMD;
% X& l+ Y0 Y6 X - while (SDIO->STA & SDIO_STA_CMDACT);
. r# q1 l; Z2 b' l$ V - if (SDIO->STA & SDIO_STA_CMDREND)
7 z3 S q0 w7 M& t+ _0 Q) m" H - {
8 a" i- \& S( S; Q" y - SDIO->ICR = SDIO_ICR_CMDRENDC;
7 d8 l2 t, h" ^7 X- s - WiFi_ShowShortResponse();! ?0 Z' N- b* @) F2 r8 x" P& |
- if (SDIO->RESP1 & _BV(31))4 c }4 t; Z" c0 L
- {6 i) c. T2 L7 i
- // Card is ready to operate after initialization
, q# ]2 `( A# |$ g5 t+ \. |0 j, L B - printf("Number of I/O Functions: %d\n", (SDIO->RESP1 >> 28) & 7);( U2 N E5 K1 @# }1 J- R8 v7 \
- printf("Memory Present: %d\n", (SDIO->RESP1 & _BV(27)) != 0);3 T( T0 G0 A( K2 P; ?+ Z, n1 f
- }4 t/ E. J8 ]+ p9 E; A% \* H" i
- }
; ?; u! D6 {6 V$ x: s9 a; o$ Y -
+ x4 [7 F! {4 \' V: m - /* 获取WiFi模块地址 (CMD3: SEND_RELATIVE_ADDR, Ask the card to publish a new relative address (RCA)) */4 Y- s" t9 B( k3 u
- SDIO->ARG = 0;
& U/ G0 R( y$ j1 i8 V - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 3;% o% K/ k) c0 Q1 x% J
- while (SDIO->STA & SDIO_STA_CMDACT);
; U4 d1 m. o! r - if (SDIO->STA & SDIO_STA_CMDREND)
. y7 E- K N) r* w w' y - {
/ r. {: M+ w' O# F; Y; h - SDIO->ICR = SDIO_ICR_CMDRENDC;
, Y7 j, ]2 Q: F, Y! z* ^9 L/ X - rca = SDIO->RESP1 >> 16;) N4 k i: k6 u2 m g
- printf("Relative card address: 0x%04x\n", rca);( r" Q+ A% C7 H* m: A' n# o
- }7 Y) p: [* k. J
-
- }6 [" ` ~, }+ B1 z. ?( k - /* 选中WiFi模块 (CMD7: SELECT/DESELECT_CARD) */
$ h& z( F7 {( t8 ~ - SDIO->ARG = rca << 16;
) q: u& l& t0 @" i9 X - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 7;8 Q% b1 |( }4 f% Q2 @3 a7 W
- while (SDIO->STA & SDIO_STA_CMDACT);' S9 p# }: u( P- s% q4 D& Q. s
- if (SDIO->STA & SDIO_STA_CMDREND)
9 U" a4 }# U+ H5 Q& A* u$ q0 w5 R - {
0 h) A1 \8 L+ v9 k \2 y - SDIO->ICR = SDIO_ICR_CMDRENDC;
! U3 L0 M( M9 d6 ]4 s9 g1 Y- v* n - printf("Card selected! status=0x%08x\n", SDIO->RESP1);
3 K- M& c# a8 @0 B1 n - }
5 `, N2 Q' I9 d - : |6 R" \0 B: I* E9 A( A2 }
- // 提高时钟频率1 S8 E( `+ H" L1 P v1 a- N
- SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 70; // 72MHz/(70+2)=1MHz
) N0 c1 Y" C* V' Y9 l! i$ ~ - SDIO->DTIMER = 1000000; // 当频率为1MHz时, 超时时间为1秒3 T: Y* C0 f; S7 ~7 p; |" J+ W$ J
- //SDIO->CLKCR = (SDIO->CLKCR & ~SDIO_CLKCR_CLKDIV) | 1; // 72MHz/(1+2)=24MHz% }$ Q/ ?3 ?8 r+ G: H
- + g6 g. l$ [( `2 Q: {- a% Q9 t
- /* 选择总线宽度 (Wide Bus Selection) */9 m2 `# Y' b4 H) Z- Z) J
- // For an SDIO card a write to the CCCR using CMD52 is used to select bus width. (See 4.5 Bus Width)
8 p: p( J# I+ t- U& C7 V - // CMD52: IO_RW_DIRECT, CCCR: Card Common Control Registers
! ~5 f$ D3 r# i, z! ]5 r - WiFi_Write(0, 0x07, WiFi_Read(0, 0x07) | 0x02); // Bus Width: 4-bit bus7 w0 | F5 d5 J3 l \# Q& A
- SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
* z+ z; t! h/ V, T1 Z2 i6 _6 }2 n -
- K* i$ Q3 O' q - // 初始化Function 1+ q+ M: G9 D1 z% K* F p5 T
- WiFi_Write(0, 0x02, 0x02); // IOE1=1 (Enable Function)9 a+ a0 a0 A g3 z. d
- while ((WiFi_Read(0, 3) & 0x02) == 0); // 等到IOR1=1 (I/O Function Ready)* \8 b6 i! x, S' t
- % t" q* O' x# b; W+ p+ n
- // 显示CIS信息5 i- ` |! @" F; |
- //WiFi_ShowCIS(0);' w" n8 M* A( \% b- ]% P# ^$ E
- //WiFi_ShowCIS(1);
( w# S) g; C0 p P4 c - 7 }1 A5 [7 k: _5 A
- // 下载固件4 X9 m+ W# f( q1 G
- WiFi_DownloadFirmware();# y7 }# U) N3 r6 i0 I) V
-
! L5 f7 C: E9 _3 L - // 设置数据块大小为256字节! f2 |# k7 V9 ^' @( E8 R+ b- O1 D
- SDIO->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3;
. R) ?) g9 O% _; c - WiFi_SetBlockSize(0);0 d4 \ y9 B8 r5 ]) G) a6 } I3 S, {
- WiFi_SetBlockSize(1);: a/ a$ K4 f6 E* c4 o; }: U* c
- / \2 H9 b; s; Y) l9 E
- // 允许发送和接收 H4 E5 x1 |+ e4 C0 K
- // 不使用带有LLC子层的802.2SNAP帧格式, 这样LLC和SNAP这8个字节的内容就不会夹在数据链路层的源地址字段与数据字段之间
% ~% a, n4 y0 h/ t- F: b - WiFi_MACControl(WIFI_MACCTRL_ETHERNET2 | WIFI_MACCTRL_TX | WIFI_MACCTRL_RX);
2 b/ R) X+ X! S! a - }
n( Z8 K$ ?" i& Q& R/ }2 A" d4 \ - 2 R& W6 L+ F. M' ^' R. ]$ _7 q
- /* 获取或设置密钥 */
3 C( ?; U3 y: H7 s - uint16_t WiFi_KeyMaterial(MrvlIETypes_KeyParamSet_t *keys, uint16_t size, uint8_t action)" A6 {# ]+ c. G! B6 p
- {
$ _5 p1 \" J- e5 p - uint8_t buffer[256];
7 Q0 q5 U& U: O( I4 E - uint8_t ret_size;; G2 b6 m/ K' J9 }2 l: L! G, @
- WiFi_Cmd_KeyMaterial *cmd = (WiFi_Cmd_KeyMaterial *)buffer;
, V7 w6 R% X# D6 u - cmd->action = action;
* g: M+ X1 z- _3 O7 w - if (action == WIFI_ACT_SET)
+ H( J, Z( k7 a, r: F - {
' ^6 t# {) q% H5 i" p2 t7 W - memcpy(cmd + 1, keys, size);1 B) ^5 g# o0 C/ Z9 G6 H( f: w
- WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial) + size);3 b; [& [( h8 ^
- }
7 Q! c! L2 C4 s% @9 w; Z9 p9 g - else
E6 t' B& S& K: z7 @ - WiFi_SendCommand(CMD_802_11_KEY_MATERIAL, buffer, sizeof(WiFi_Cmd_KeyMaterial));
% t$ {# r- ?' W3 z" F; i - WiFi_ReceiveResponse(buffer, sizeof(buffer));
" K- p3 V8 z- b/ Z( X6 m -
) W2 i% |0 T0 |( I/ C - if (action == WIFI_ACT_GET)( ^. M! I; D E8 c7 R
- {) l$ U( I2 R9 [- G
- ret_size = cmd->header.size - sizeof(cmd->header) - sizeof(cmd->action);
: v* X8 {/ Q' b: w6 i0 r0 K - if (ret_size <= size)% H' z: [# j. k3 | @
- memcpy(keys, cmd + 1, ret_size);2 W3 K5 A8 `1 y! d/ Z8 b8 n! u7 h
- else; \: p. b6 B W% {$ L8 {
- printf("WiFi_KeyMaterial: Buffer size is too small! %d bytes required!\n", ret_size);
; F0 S) V& N2 `: f9 P; D6 g - return ret_size; // action=get时返回读取的数据大小
' q# X8 q+ i. W3 k, g/ p - }
6 \- u) f6 o8 m7 Z$ I; y - else
8 M7 L9 g1 u- D1 R. G, G W& ? - return cmd->header.result; // action=set时返回命令执行结果值7 f" l. _# F1 `+ m# Q: n) b- ]
- }8 V% ?3 M* i- o% K; b
- 0 \3 h) a$ d4 {$ A9 E
- /* 获取或设置MAC地址 */% Y) z; L. d4 i, |5 Q
- void WiFi_MACAddr(uint8_t addr[6], uint8_t action)
/ m* m+ c% O6 q0 y, h1 { - {" t8 Z" R+ B& \. n
- WiFi_Cmd_MACAddr cmd;* Z8 }/ u+ I: o c: _8 h
- cmd.action = action;
& `- j9 W4 x4 m* z4 U7 [8 G6 X - if (action == WIFI_ACT_SET). j' F; B+ e% ?6 _
- memcpy(cmd.mac_addr, addr, 6);
3 v$ i" D# \9 b) H7 P - * m$ _8 F6 T) s/ _% a; X% |2 k7 H
- WiFi_SendCommand(CMD_802_11_MAC_ADDR, &cmd, sizeof(cmd));# E, L0 u, J. B3 L
- WiFi_ReceiveResponse(&cmd, sizeof(cmd));
# F8 j$ k4 h& m& J4 O - if (action == WIFI_ACT_GET)
) ]! F0 S# x6 T; ^6 ` - memcpy(addr, cmd.mac_addr, 6);
0 J2 ]1 O* H: B7 m, |) ?% S - }& N0 s- D; s8 t6 h G; S
- O- m2 V* u' u1 ?( B/ B4 U5 x4 v- /* 配置MAC */
8 G1 |& i% a5 [8 t9 D - void WiFi_MACControl(uint16_t action), c% y) \) F9 X8 Y
- {
; m. n8 l/ W3 v5 d! Q, B; S - WiFi_Cmd_MACCtrl cmd;
1 m( i& ]2 P; E/ C' L, o - cmd.action = action;
T" @( h' ]. Z$ _ - cmd.reserved = 0;
4 F% q9 _# K7 U( g" {; k: k - WiFi_SendCommand(CMD_MAC_CONTROL, &cmd, sizeof(cmd));
z/ G8 |6 m; W: M - WiFi_ReceiveResponse(&cmd, sizeof(cmd));
0 i- n/ d1 T8 k6 r7 V+ M - }* S5 H; k, f" a: i' |$ w
- / [0 L) a7 e3 r( u1 a: `/ D: D( ?
- /* 获取滞留的数据包大小 */
9 m: H: e9 D# a7 P - uint16_t WiFi_PacketPending(void)2 Q0 V1 o% N8 {8 U
- {' T$ a# X2 j9 E4 X, i
- return wifi_pending_size;
# u0 S6 U4 l# g - }
. t% ?1 K9 ^3 \ - C! G0 R8 o, Y
- /* 准备好超时计时器 */% R6 ~0 @7 p6 ~9 M
- void WiFi_PrepareTimer(uint16_t nms)
6 c) t H6 W% ~, c/ ] - {7 r% j2 j: G3 @
- TIM6->ARR = 10 * nms - 1;
, ?" C& v( w, Z6 r, d - TIM6->PSC = 7199; // 72MHz/7200=10kHz# P; [ ?+ A, H
- TIM6->EGR = TIM_EGR_UG; // 保存设置
l) D' m+ i6 [% H8 u( B9 G - TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志位% [0 W/ g9 X9 [+ b
- TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // 开始计时, 模式为非循环模式& R6 p" h C. c5 f" }, I* V
- }
) \$ u1 `: z2 T q - 2 b' Z# |1 x4 o& _) m0 S4 k. `7 K
- /* 读寄存器 */& Y8 B2 c! e/ R+ ~! j; G
- uint8_t WiFi_Read(uint8_t func, uint32_t addr); Z7 r4 u0 ]) s. r$ m ~7 H
- {
5 g2 w$ @0 a) G/ | - WiFi_SendCMD52(func, addr, NULL, NULL);
6 g" H( t/ F) q+ s% Z; s - if (SDIO->STA & SDIO_STA_CMDREND)- Y$ M' Q7 o3 C# M
- {
: r- ?0 S7 c$ u - SDIO->ICR = SDIO_ICR_CMDRENDC;7 C" W1 m2 N) n; g3 t+ P& c
- return SDIO->RESP1 & 0xff;4 g5 f0 g; B7 h) b9 J
- } W7 o# K, q. g2 F$ d' V+ r
- else0 C9 h# G9 ^2 G0 C# M' `
- {
* t8 H8 t# X) V2 Y& L! p1 ^ - printf("WiFi_Read failed, SDIO->STA=0x%08x!\n", SDIO->STA);% h# Q) \1 o0 I1 k: p6 M- F3 K( p
- return 0;7 ]0 p5 h0 a. O( {9 O
- }
) n# f' {% X: n/ K' G - }
9 t6 t; W, s! D4 F& e' b I
8 c3 r0 [% A F- /* 读数据 */
) T& t% W" }: g0 f - // count为要发送的字节数或块数, bufsize为data缓冲区的大小
- S" W+ U0 Y! D - // bufsize=0时, 只读取数据不存入缓冲区
8 M3 ]# z* A0 S( ^# s/ ~ - void WiFi_ReadData(uint8_t func, uint32_t addr, uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)- H+ \9 k0 f: N f3 v4 ^
- {
8 S( D; h, b7 d% j J - uint32_t len, temp;, m- W5 ~/ P& x* \ x: v
- if (flags & CMD53_BLOCKMODE)
' m! E4 K, q! |5 t. r F - {
2 O2 u9 s5 t; P* b' z P - len = count * WiFi_GetBlockSize(); // count表示数据块数
- V( B' W5 p4 E' _ - SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE; // Block模式
, i2 I. _* G& y - }
2 X8 w) @6 V5 c7 x - else
# k R. J S6 J% ~ - {, P1 @- B% J0 [9 i0 w" a% o0 @
- len = count; // count表示字节数2 A# @) u- s- w: j% y
- if (len % 4 != 0)$ Z. N9 ]+ ^9 C% e! ~* w
- {
0 z3 m: L+ g8 C - len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍
, `: b3 }2 P `5 [* ]$ Y8 q - count = len;
\, H+ a) H# [5 n2 [& x - }
/ x: M" p; ?! d4 f7 ^ - SDIO->DCTRL |= SDIO_DCTRL_DTMODE; // Multibyte模式6 E% i3 L% [1 I/ G) _
- }
6 h3 B3 m; t& u7 n& {& D; B - SDIO->DLEN = len;
0 ?: Q# ?3 H, ^; t0 F - SDIO->DCTRL |= SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; // 设置传输方向为从模块到主机
& G$ X0 A; l' ~. ^8 u -
. h, J4 U+ n- A# T! J - WiFi_SendCMD53(func, addr, count, flags);
, h$ `$ y! ?# I - while (len)
. e) d! d8 H ^; _ - {
% q- R$ T4 h& [3 y - if (SDIO->STA & SDIO_STA_RXDAVL)
A* e. Z# ]$ ` - {
9 X; L2 c( U3 f - // 若有数据到来就读取数据% _( i4 b4 c2 D; X7 \
- len -= 4;: @7 ]% Q$ w5 q2 W
- if (bufsize >= 4)
4 N$ r0 ` t8 e% e - {
' Z7 L6 _9 ~2 A3 @ - *(uint32_t *)data = SDIO->FIFO;4 b, ]6 h# m$ V. W' O; o! x, A
- data += 4;
1 L+ x4 h/ O" k4 O4 M) { - }
+ k* C# ~2 _* H; J" U2 c q - else
5 D: \! s: }2 Z6 H4 g' ~ - {9 r r$ ?0 y( \. y, [
- temp = SDIO->FIFO;. u9 k: n4 i- h' W6 p
- if (bufsize > 0)0 j* l3 K: ]( L! o3 s0 h
- {8 k3 u$ `7 `/ n7 g
- // 写入缓冲区最后1~3字节7 u; B4 H" j3 j% V4 d
- memcpy(data, &temp, bufsize);- Q+ l: i4 M7 B! }0 S! Q" S
- bufsize = 0;- Q, o# Q7 l) }$ Q
- }
) T0 X0 `8 x6 ] - }
, M/ \4 z: o7 y - }
+ G" J3 f+ a7 ~4 ] -
. z5 B% `2 {8 s- r) P. @/ Y M - if (SDIO->STA & SDIO_STA_DTIMEOUT)
7 S1 \4 J% \! C0 i% W: Y, M - {
3 T$ L/ G D. ?9 [- P6 p# Z- U - printf("Data Timeout!\n");; B7 d* t! p. _ f# V
- break;- M7 s: }% B: h' P) M
- }/ E( [9 P w+ t ]9 G
- else if (SDIO->STA & SDIO_STA_DCRCFAIL)" d( {7 Y; I3 b
- {7 \0 U; P0 a% a2 d+ B( v. i% |5 H
- printf("Data CRC check failed! %d bytes are lost\n", len);) m* x6 D4 f% G V( s
- break;8 Z9 w9 A8 ?$ d7 I7 x) I7 z
- }; i& P1 ]7 ]2 [6 X, _
- }& h5 _6 K' c( b. S# l7 k
- ( t3 Z, Y* h9 t$ m! j0 @
- while (SDIO->STA & (SDIO_STA_CMDACT | SDIO_STA_RXACT));5 x# v* A5 s$ Z/ v' s, i
- SDIO->DCTRL &= ~SDIO_DCTRL_DTEN;: ]- h6 F9 ~: q
- n+ K& V* K: T% J+ ?
- SDIO->ICR = SDIO_STA_DATAEND | SDIO_ICR_CMDRENDC;
3 L3 c2 b d! A* S* Q2 k - if (flags & CMD53_BLOCKMODE)% L" A3 L+ U3 k: H6 _+ [8 Z9 H
- SDIO->ICR = SDIO_ICR_DBCKENDC;
?5 r, @) a( H% Q! g' N. @4 a -
9 u2 d. q, m6 Z9 f0 ^2 Y" A - // 通过判断SDIO->STA是否等于0可知传输是否成功
6 j$ C( } y% l" m - }
6 ]# m/ p6 k3 J6 X$ @& [7 m - % ^& B5 K; _2 }) R
- uint16_t WiFi_ReadPort(void *buf, uint16_t size, uint16_t bufsize)
/ s9 Q$ C; h s2 i; k9 d/ M - {
/ `) |) i' o Q& z8 _ - uint16_t block_num, block_size;
6 _* ~3 O6 b3 m3 ~" } }+ r - block_size = WiFi_GetBlockSize();
$ I/ w7 c) T# W q |) d& a - 0 M# Y5 Z, S0 b' F7 [
- // 读取数据
, j% ~9 G. c" j6 |+ o - WiFi_Wait(0); // 发送CMD53前必须IOReady=1
/ a' \8 J: }0 C2 U8 l% D. t - if (size >= 512 || size % block_size == 0)3 O8 w5 e8 d/ K9 V' R, y- l
- {
0 O( \. E' O1 N: g) [ - // 采用Block模式传输
" Y; U7 c0 l" L5 P5 l- t - block_num = size / block_size;6 u3 ?* c9 h t1 ]
- if (size % block_size != 0) W8 T- [+ D) g3 q, }
- block_num++;$ m7 z4 W+ J) }) @
-
" w A1 }0 G3 m- A& d* }7 K" W - WiFi_ReadData(1, io_addr, buf, block_num, bufsize, CMD53_BLOCKMODE);
/ ~& l- j- b& A$ P4 c - }
( U/ `! }; R: X% h6 K- l+ O5 m - else
+ R; |$ m, _, e6 M - WiFi_ReadData(1, io_addr, buf, size, bufsize, 0);- n ]: _1 p) D! a& f! I% y5 {
- + T; S$ L/ S* y4 j# n
- return SDIO->STA == 0;
9 D6 H. |6 o) f7 H - }
* v8 w9 Y. }3 P! M5 a
0 B; _1 B2 h% V% p' ?8 S$ F- /* 接收数据帧 */
: d6 L* T, t- F3 ~. C; o - uint16_t WiFi_ReceivePacket(void *buf, uint16_t bufsize)' b# w* z3 ]1 S \, z# y# D
- {: L$ Q) M1 {( y
- uint16_t size;! _ k5 O/ N0 D5 @3 U; K4 m
- if (wifi_pending_size)
; K/ c: j" R$ h+ E) j - {
8 e* Y% b2 H9 d! ^; J - size = wifi_pending_size; // 先读取滞留的数据包9 h0 r- ?2 h! t1 b4 U
- wifi_pending_size = 0;; F- g0 R( p" l5 S
- }' a* I0 B v6 t. r+ U6 v
- else6 [ C9 p0 w5 e8 L; O5 p u- A/ Z
- size = WiFi_GetPacketLength();! g6 ]" E$ q: G+ c" O
- return WiFi_ReadPort(buf, size, bufsize); r4 U/ w- p! c- n5 P; g4 j
- }
/ Q3 p# B! [: n0 ^ - ! L, l J" p- v! b4 r
- /* 接收WiFi命令的回应 */
8 e+ S6 D0 X' h; L' d - uint16_t WiFi_ReceiveResponse(void *buf, uint16_t bufsize)' S ^( A* N% k0 ]1 m: m1 F9 {
- {
- |, e9 \/ h7 p3 f1 w; E, d - uint8_t retry_cnt = 0; // 重试次数( g9 d0 A* y# x1 A
- uint8_t wait_status, resend;
/ j+ R1 e+ E: Z' }' T' h - uint16_t size;6 @- r; T2 m) a2 [6 L1 B+ s/ T1 H
- WiFi_CommandHeader *cmd = (WiFi_CommandHeader *)buf; C1 |: u }6 P: W h5 ?
- WiFi_SDIOFrameHeader temp;6 `/ f; B2 D4 x- }- `
- 7 F! z, L; y: f& s4 h) O' O
- // 等待数据准备好9 n7 b* }" \9 R9 E5 k) t
- do
* w- B# f- Q( o0 m - {% G R+ N) [! v) e. I' v G) m
- wait_status = WiFi_Wait(WIFI_CARDSTATUS_UPLDCARDRDY);$ E/ Q% c# k. } q9 @5 v( ?& a6 W
-
V0 t0 \/ }: `; ^8 Z' \ - WiFi_ReadPort(&temp, sizeof(temp), sizeof(temp)); // 试着读取头部信息
. a3 u. X) z6 M* D' B5 J - if (temp.type == WIFI_SDIOFRAME_DATA && temp.length > 0) // 若读取到一个数据帧的头部
+ q: T5 x; w* M1 S$ V, F5 s' x - {
5 B; I% u9 _9 [/ x* ~ - // 若读到的是一个数据帧, 不是命令回应
! d% J) B) n# ~5 @ - // 则直接丢掉该数据帧, 然后重发命令, 保证命令执行成功
n1 A& m; X* t# G$ @& r - printf("A packet of %d byte(s) preempted the command!\n", temp.length);
1 G; P) @2 z5 M0 @" Q. e - wifi_pending_size = temp.length;$ _6 G0 C# o) F
- WiFi_DropPacket(); // 必须读取完整个数据包, 只读完头部不算9 G F* p5 P! S6 v; \
- resend = 1;
" c* I& B9 S5 X7 Y: a - }& S) _2 \6 L0 p' t9 G( X# S/ j
- else if (wait_status == 0)/ ~! z% I( J* Y, d, Q _3 j6 R
- {
$ g+ a. L A \, z' o: k5 U - // 若WiFi_Wait返回0, 则说明超时 (状态位在规定的时间内未置位)! f' q8 b( R* u% B' o) W3 B8 N4 {
- resend = 1;
6 K" Q- i% [2 D' | - retry_cnt++;8 I" q1 e0 V' V& P* W: d+ D
- if (retry_cnt >= 5)
6 V/ n: g0 T7 S - {+ F+ k) v& p. ^# Q; Z6 @- F( ~$ _
- printf("No response!\n");
' B- F$ O" X, R- O. l - return 0;$ F. u' a j8 ?7 D9 d+ ^2 w
- }
g# ~+ K7 R4 u6 I% E. N9 \3 p - }. j Q2 N& v6 Q& l- r2 Q
- else4 T% K& c" n; h. V& [
- resend = 0;
8 q$ S5 W1 h$ h6 V -
9 c3 o, X$ @) g5 y - if (resend); {1 V) k5 M! G0 P, c0 ^& u
- {, v s( _* y9 l8 o
- if (cmd->frame_header.type == WIFI_SDIOFRAME_COMMAND), c5 p8 w$ n/ X' x
- {* j; Q R8 K$ [9 X3 \
- // 若超时后还没收到数据, 则重发命令, 然后再次执行WiFi_Wait h; t$ X" D7 |* s* \
- printf("Resend WiFi command 0x%04x! size=%d\n", cmd->cmd_code, cmd->frame_header.length);
3 |* X) o, s% \ - WiFi_ResendCommand(buf);" E, d' c' Y) d* T3 U% w8 J+ i' Y
- }3 ?& ]) A! Z: r# S) O' ?
- else& t- T3 e* I$ S% N4 a: L! [7 I/ N0 E
- return 0; // 若buf中的内容不是命令, 则直接退出
$ h! Q& D, a2 w: i+ Y6 a - }
9 l( H5 J/ t+ s9 b. L/ n# g - } while (resend);
5 X8 Z: T. r0 u - 4 L6 L' y j4 s9 e$ x
- size = WiFi_GetPacketLength();$ {% r2 J4 l* W, v. @
- if (size > bufsize)
0 B: ]; M8 w; ]3 Z# W3 j; ? - printf("WiFi_ReceiveResponse: Buffer size is too small! %d bytes required!\n", size);
5 W3 w: Z# X( [7 ?+ y6 V+ Z - return WiFi_ReadPort(buf, size, bufsize);) l( J7 ? S6 [" P) \ _
- }
0 K4 R2 Z1 @7 Q4 K( o2 u% B$ X
. n5 C* k# o" g# A! m- /* 扫描全部热点 (仅显示) */
# B5 V8 ~+ O2 Z" b1 o0 X - void WiFi_Scan(void)
" g! @: n, W5 k. P: g - {
& R7 A( ?) R( e8 t0 c& j- w$ Q - // 必须把STM32启动文件*.s中的Stack_Size改大, 否则函数中无法创建大数组
0 a' |+ H3 G, e# [# x/ y4 n - // Stack_Size=0x00000c00
' O, C+ x3 p) m+ i - uint8_t buffer[2048]; // 用于接收返回的WiFi接入点信息, 需要较大的内存空间来存放
: D @6 G3 R; ]$ x1 U3 J( l- _ - uint8_t i, j, n;
8 _9 ?% H6 m' Q, o1 S/ }, O7 w6 X% l - uint8_t ssid[33], channel, wpa;3 `% X" }4 t( p$ t/ Y& g
- uint16_t ie_size;
" @) p, u v j) B+ ]2 c -
6 N# w; j6 A' Z5 N" y - WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer; // 用buffer空间来存放要发送的命令" C8 T9 j& ^3 W) y$ Q( b# ^% R% f
- MrvlIETypes_ChanListParamSet_t *chanlist = (MrvlIETypes_ChanListParamSet_t *)(buffer + sizeof(WiFi_CmdRequest_Scan));
5 P- ?/ F3 u' ~ -
2 [7 d1 |/ \3 X9 f; a. U" G$ B# R - WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;" Z! J1 x# E8 x' k
- WiFi_BssDescSet *bss_desc_set;
: T! Z' |, O4 `0 M( @% d- H; g+ b - WiFi_VendorHeader *vendor;
7 p. G2 S; Z7 b% i - IEEEType *ie_params;
# q- I. K1 V: j4 W - //MrvlIETypes_TsfTimestamp_t *tft_table;
1 Y) n' b+ d% ] - 0 g2 z0 K) i) }2 u8 s
- // 分4次扫描14个通道+ ?; `1 Z' n% n6 X
- for (i = 0; i < 4; i++)4 o: [, T2 ?$ `5 @: f
- {
% F T9 r+ q8 }4 l8 t+ J! e7 X - cmd->bss_type = BSS_ANY;) z+ x9 }+ ]# C( T- q; }
- memset(cmd->bss_id, 0, sizeof(cmd->bss_id));8 u9 M/ q& D& @2 x: s
- + b+ X- g3 Y9 E1 D; h: v) M8 e
- // 通道的基本参数4 J L9 j! u# e4 s2 f1 Y
- n = (i == 3) ? 2 : 4; // 本次要扫描的通道数, I3 x/ `* {( u! `6 S
- chanlist->header.type = MRVLIETYPES_CHANLISTPARAMSET;
8 X) d/ T1 w; W. v0 M. V/ \ - chanlist->header.length = n * sizeof(chanlist->channels);
) I- W& c) @, @/ ~8 [ - for (j = 0; j < n; j++)
- G" r+ s" c3 i, f( b2 @+ [ - {, e d# J! j2 w; A0 |: Y+ V3 h0 Z. a
- chanlist->channels[j].band_config_type = 0;
+ D n& R. W* [7 @. N - chanlist->channels[j].chan_number = 4 * i + j + 1; // 通道号" w5 \$ i( w/ {: x
- chanlist->channels[j].scan_type = 0;
- @" w, j, J% y' F" E. j8 F8 r9 i" f - chanlist->channels[j].min_scan_time = 0; p: M1 ]: m5 w, K1 R
- chanlist->channels[j].max_scan_time = 100;
/ `+ T6 d( `- | - }
8 E% C1 H1 G1 a3 m -
4 _1 E# k5 x* M# A. c - // 发送命令并接收数据
+ R0 G6 A7 F. b4 a+ s9 @" D+ T3 g! w - WiFi_SendCommand(CMD_802_11_SCAN, buffer, sizeof(WiFi_CmdRequest_Scan) + sizeof(chanlist->header) + chanlist->header.length);
3 G0 i& h1 ^* b4 | d( Y - WiFi_ReceiveResponse(buffer, sizeof(buffer)); // 接收的数据会将cmd和chanlist中的内容覆盖掉
% a7 o/ Z5 i% V1 b -
' x$ E3 t! s/ R, L( l3 q$ v7 @ - // 显示热点信息, num_of_set为热点数
0 Y2 G& t) C3 B# y c h4 A1 H' W - if (resp->num_of_set > 0)
9 ^/ G) M+ F7 ~' D9 m. T - {
4 L" k3 G) z# G - bss_desc_set = (WiFi_BssDescSet *)(buffer + sizeof(WiFi_CmdResponse_Scan));& b. K( h& d0 k: Y5 c/ C9 v \
- for (j = 0; j < resp->num_of_set; j++)
, Q# S: v4 Y: P. d3 E, ^1 n6 d - {: @& G$ l" S1 V; s6 b; q; {
- wpa = 0;- H6 n$ u, q2 ?
- ie_params = &bss_desc_set->ie_parameters;
: u T* V) E2 Z& Z' ?, c6 { - ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));" t" Y% f8 A \+ {9 `- Z
- while (ie_size > 0)
9 p2 Y$ ?3 P) D" w4 @; Q, O" s3 W - {+ k4 ?3 d! y! @, f# h
- switch (ie_params->type)8 X1 R7 p; Y, T, r8 i
- {! M" C; P1 n, X3 s8 }$ ?7 _
- case MRVLIETYPES_SSIDPARAMSET:2 S+ r/ e, c/ ~- J- d
- // SSID名称& L* {3 j. z) L3 o
- memcpy(ssid, ie_params->data, ie_params->length);1 R' a# R+ u: t( v1 ]. E9 ^! t
- ssid[ie_params->length] = '\0';
' O. Z7 d( Y" D0 L- E - break;
- _3 n3 l- f+ Z. t - case MRVLIETYPES_DSPARAMSET:
+ Z R a! s- k! b- l0 U$ H! [ - // 通道号( s4 L) b1 |2 l4 f8 B
- channel = ie_params->data[0];# s( J- Y3 i" }; h* e
- break;
. f& a$ q/ l9 k5 L - case MRVLIETYPES_RSNPARAMSET:
1 ?" Z/ ^. {) O$ U9 l - wpa = 2;; b! J6 y5 c4 r+ E) z' ]2 h
- break;" X, C5 S) z" N8 Z! y1 ~
- case MRVLIETYPES_VENDORPARAMSET:! F5 N9 t4 r0 l$ ~
- if (wpa == 0)4 O6 P8 Q3 v! U
- {
1 \! y* t7 ^3 Z6 o% k: j - vendor = (WiFi_VendorHeader *)ie_params->data;
# U" }4 Y9 f, d+ h* }: j/ z* w - if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2 && vendor->oui_type == 0x01)
" S' r7 F4 h2 R9 h& _( F - wpa = 1;
0 F7 e( c+ w+ ^' j5 G( H7 Q - }
% V8 {( O% b ~ - break;: j$ _& j- Z( [- Z1 [( x) W
- }$ F: R7 K0 l- @3 P" q' D
- ie_size -= ie_params->length + 2;3 r1 P M# D$ o* D; }# ?$ C; `
- ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);! h+ P5 h8 I/ F0 T% E& Z
- }
% j8 @% [0 B8 } - if (ie_size != 0)
$ t) @- \4 p" g. i' Y$ f, n - printf("ie_parameters error!\n");0 ?. M o# i* K' A/ O
- ' g! |/ H7 |! F8 c, p3 ^2 y
- printf("SSID '%s', ", ssid); // 热点名称
3 V! X5 g, u) m. B3 ? - 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地址
% R! v: X! S$ e( U6 k - printf("RSSI %d, Channel %d\n", bss_desc_set->rssi, channel); // 信号强度和通道号
) c* o5 X7 [" W2 p0 w" ~ - //printf(" Timestamp %lld, Beacon interval %d\n", bss_desc_set->pkt_time_stamp, bss_desc_set->bcn_interval);
- k0 V. \1 m- S1 ^3 U! d -
- ]. E$ C0 B- g9 r7 H$ x9 R - printf(" Capability: 0x%04x", bss_desc_set->cap_info);6 o: A. W) W4 B& k
- if (bss_desc_set->cap_info & WIFI_CAPABILITY_PRIVACY); j b( x x1 ]" F" n: c
- {
; n( G% N: _) r6 @' E5 ^ - if (wpa == 1)
3 U( t; b9 i$ C7 P- k# H - printf("(WPA: ON, ");
+ j( Z8 z# @6 J1 j! q% m - else if (wpa == 2)
1 ^4 I- }# _- n: X; w - printf("(WPA2: ON, ");! `5 l7 b3 b) c8 k% r
- else
# X* m; _& Y3 Z) s2 X+ a5 O( t w - printf("(WEP: ON, ");, G# @- ~. C" Q6 f# h F
- }: u4 c2 T! v3 ?/ f! i
- else
; }: X3 }1 L( p* F - printf("(WEP: OFF, ");- q4 e2 G- n, s `' f# x
- 2 [- j: x. z: Z
- if (bss_desc_set->cap_info & WIFI_CAPABILITY_IBSS)2 q+ ~) [, I/ V! K. [
- printf("mode: Ad-Hoc)\n");! E$ @: g8 t/ W8 B5 k
- else
( D- X% U5 I& S8 M) A. b - printf("mode: Infrastructure)\n");
9 a+ l8 [0 X3 [9 o) C& A, W -
( }" B V! ]% g - // 转向下一个热点信息
- s# m+ U, R( @4 d W" S3 g" z - bss_desc_set = (WiFi_BssDescSet *)((uint8_t *)bss_desc_set + sizeof(bss_desc_set->ie_length) + bss_desc_set->ie_length);* N9 I* [2 i8 e9 F/ k
- }
4 ?8 x. h Y8 C8 U - ' m6 g+ A$ [5 v* U8 ?/ ?6 `2 i2 Y
- // resp->buf_size就是bss_desc_set的总大小
6 w1 y. C0 S) i' q# c' e5 l - // 因此tft_table == buffer + sizeof(WiFi_CmdResponse_Scan) + resp->buf_size8 ?. J2 f, X, @& m
- /*tft_table = (MrvlIETypes_TsfTimestamp_t *)bss_desc_set;
' l) e( t0 I' t$ v& o: z2 c- R - if (tft_table->header.type == MRVLIETYPES_TSFTIMESTAMP && tft_table->header.length == resp->num_of_set * sizeof(uint64_t))" \$ V- C+ B' b' n1 k7 i4 y, s: u* I
- {
7 U9 p1 ?7 T* |# } - printf("Timestamps: ");
# L( Y2 D' i7 o3 t3 S% ` - for (j = 0; j < resp->num_of_set; j++)
; @. J! T E. A2 I0 K8 b4 Q - printf("%lld ", tft_table->tsf_table[j]);
9 c9 m. a1 D) c' j9 B0 o - printf("\n");, B4 v# L8 @! S0 J! E
- }*/' k+ `$ o# A g' R# S+ O- f% P
-
" ]" ^) n, g, ~, g9 a8 I; Q! m - // TSF timestamp table是整个数据的末尾, 后面没有Channel/band table
$ _$ ^( D) |" D3 Q4 | - //if (((uint8_t *)tft_table - buffer) + sizeof(tft_table->header) + resp->num_of_set * sizeof(uint64_t) == cmd->header.frame_header.length)( M' g. l8 W; r& h! u
- // printf("data end!\n");0 M- e+ _5 A/ i4 i/ l6 }
- }
- J0 p B9 d- K - }
/ Z G, l( B/ e- C7 m( [; q: D p - }
) D6 s# |$ w' a5 P' B3 `% p
# T6 ]+ [" k p, k" A- /* 扫描指定名称的热点 */
) d4 L# K( X, p - // buffer用来存放返回的全部结果, 因此bufsize应该足够大
5 J* m( w9 ]# m g - // info用来存放从buffer中提取出来的一些常用信息6 p- \7 ^5 W4 x" o- [% ?
- uint8_t WiFi_ScanSSID(const char *ssid, WiFi_SSIDInfo *info, uint8_t *buffer, uint16_t bufsize)
; T- h: R7 H) o. c+ M - {
! ^ L0 Z/ k" _8 y6 }% R - uint8_t i;$ c$ A* L4 B6 @( K& K
- uint16_t ie_size;# p* Z2 R, E, \& K* ?3 K7 S
- WiFi_CmdRequest_Scan *cmd = (WiFi_CmdRequest_Scan *)buffer;/ t$ R! w+ Z6 L6 z8 c. n4 s
- WiFi_CmdResponse_Scan *resp = (WiFi_CmdResponse_Scan *)buffer;
/ V1 R) q. v6 I1 B - WiFi_BssDescSet *bss_desc_set = (WiFi_BssDescSet *)(resp + 1);
+ E4 M2 n. r/ R4 O% u+ e - MrvlIETypes_ChanListParamSet_t *chan_list;) s: r' D( l$ x
- IEEEType *ie_params;9 k' |# ~- n: {: I& Z" P/ A
- WiFi_VendorHeader *vendor;2 O7 U5 @9 N7 O6 a4 C6 Z
- ; v& W$ j8 u% X; v- m
- cmd->bss_type = BSS_ANY;
0 d0 ?* B' j" r! v+ X, ~6 @ - memset(cmd->bss_id, 0, sizeof(cmd->bss_id));
. a4 R3 a2 J y! s8 G. @! S - 6 r8 F7 r0 ]! y% s
- // 添加ssid参数& N0 _) O, B3 m8 q# J
- info->ssid.header.type = MRVLIETYPES_SSIDPARAMSET;
1 F" D3 k' Y8 ?& H: n) S - info->ssid.header.length = strlen(ssid);
- M) |" o; N, r - memcpy(info->ssid.ssid, ssid, info->ssid.header.length);1 D! Z- ^$ w Q3 j7 j. i Y
- memcpy(cmd + 1, &info->ssid, MRVLIE_STRUCTLEN(info->ssid));
3 l$ J9 `7 A" Q f$ v& h -
$ Y# t: C, o% f# s - chan_list = (MrvlIETypes_ChanListParamSet_t *)((uint8_t *)(cmd + 1) + MRVLIE_STRUCTLEN(info->ssid));/ O: z! T# ]- w/ P7 B; Q; W
- chan_list->header.type = MRVLIETYPES_CHANLISTPARAMSET;
- I$ A5 {( ^/ m0 V - chan_list->header.length = 14 * sizeof(chan_list->channels); // 一次性扫描14个通道
. N! \! V3 n0 G# N+ i9 w - for (i = 0; i < 14; i++)9 d7 O, z/ G. c& i2 K7 i
- {" b: x0 c5 I4 \+ _
- chan_list->channels[i].band_config_type = 0;3 m: O* Z7 g" a: | Y. M
- chan_list->channels[i].chan_number = i + 1;) A r6 b* _+ @- P
- chan_list->channels[i].scan_type = 0;1 U1 s. r! H* t3 o* C8 [
- chan_list->channels[i].min_scan_time = 0;
9 W k( Z0 k& v - chan_list->channels[i].max_scan_time = 100;& d+ B( [( l' \" V2 k; W+ U5 x
- }& ? w b7 ~$ _9 Y+ \1 z
-
' \5 y% ]( f) ^1 \' i# n - WiFi_SendCommand(CMD_802_11_SCAN, buffer, ((uint8_t *)chan_list - buffer) + MRVLIE_STRUCTLEN(*chan_list));
& l. N; \5 l' |# ]6 U2 i" r - wifi_timeout = 3000; // 延长超时时间# n( ?4 C! G: f( Y
- WiFi_ReceiveResponse(buffer, bufsize);
& S8 K6 c! G0 |6 S - wifi_timeout = WIFI_DEFAULTTIMEOUT;* y4 v% P, v! D6 t M+ s
- $ u. Q8 `( J! [+ B, V
- if (resp->num_of_set == 0)6 z& c+ @4 z7 }6 c3 d3 X$ b- t
- return 0; // 失败/ _" I( ?3 c% U
-
! A" a+ t) t! R, J3 V* F- n7 | - // bss_desc_set以扫描到的第一个信息项为准
@3 p5 i# w- h1 v0 ?# O - memcpy(info->mac_addr, bss_desc_set->bssid, sizeof(info->mac_addr));
6 H# d A( i& |- o8 o" o2 m# F8 p - info->cap_info = bss_desc_set->cap_info;( D c# S; F9 ]! ~% Z
- info->bcn_period = bss_desc_set->bcn_interval;
4 }" W& ?2 x$ j- f2 F - & P/ |7 r: z: M4 H2 G) c4 l' `
- // 若type=0, 则表明没有该项的信息 (除SSID结构体外, 因为SSID的type=MRVLIETYPES_SSIDPARAMSET=0)
: s- H0 a5 P% B4 ^( u - info->rates.header.type = 0;
+ o4 M- r, D3 Y, P) P2 r - info->rsn.header.type = 0;# p, J' H+ F4 b3 t* z, v
- info->wpa.header.type = 0;) l6 ?8 s" @3 o5 Y/ L6 x. U
- info->wwm.header.type = 0;' B5 O# q+ X# M& U1 @ h- r
- info->wps.header.type = 0;; V- G! i" c W8 m% ~
-
# i' F% @! o7 y, A: | a% X. F- m$ j - ie_params = &bss_desc_set->ie_parameters;7 n* C, @7 Z8 E7 a2 x. B! N
- ie_size = bss_desc_set->ie_length - (sizeof(WiFi_BssDescSet) - sizeof(bss_desc_set->ie_length) - sizeof(bss_desc_set->ie_parameters));
; P h8 d: P4 G - while (ie_size > 0)5 ?$ U! M3 i9 s. F" n
- {5 a! w4 A2 ?# w
- switch (ie_params->type)
, T$ U" E/ Q* y: }8 a% B - {
6 ^5 t8 ?* ^" R2 c - case MRVLIETYPES_RATESPARAMSET:6 ?5 ?( n D# {
- // 速率1 {3 `4 o9 ?$ A. l$ s% p+ _, n
- info->rates.header.type = MRVLIETYPES_RATESPARAMSET;
* U3 Q. m+ T$ P9 Z - info->rates.header.length = ie_params->length;7 O4 B3 B& c, B; p0 r, ]
- if (info->rates.header.length > sizeof(info->rates.rates)); O; F4 m$ h n" R [9 i1 \
- info->rates.header.length = sizeof(info->rates.rates);0 m% B0 q) B+ [) h! X7 S
- memcpy(info->rates.rates, ie_params->data, ie_params->length);
. H2 `. M2 m7 U& \ - break;
* g: b5 w( I5 j+ c- B3 X - case MRVLIETYPES_DSPARAMSET:
6 j7 _( P' s9 k& Y - // 通道号# E, e7 S. e$ x% {
- info->channel = ie_params->data[0];1 L7 F9 @$ F; p6 r' j& q3 `- i
- break;
( L/ c8 O1 g- `4 @: D! ?7 P - case MRVLIETYPES_RSNPARAMSET:
7 u6 r8 C; H$ n$ b - // 通常只有一个RSN信息 (与WPA2相关)& g1 m; q% D2 ?+ K
- // printf("RSN len=%d\n", ie_params->length);' ^4 {7 `4 k% g. {
- info->rsn.header.type = MRVLIETYPES_RSNPARAMSET;
" w, U+ L# b' s; L' q - info->rsn.header.length = ie_params->length;
. r' @$ G8 L. y+ g - if (info->rsn.header.length > sizeof(info->rsn.rsn))9 T0 X3 w9 w! l0 R, i% o
- info->rsn.header.length = sizeof(info->rsn.rsn);
# m, M/ L- u$ d6 O4 w O - memcpy(info->rsn.rsn, ie_params->data, info->rsn.header.length);1 k% ^9 h/ |. z
- break;
# Q. f7 e/ |6 ^) L: k - case MRVLIETYPES_VENDORPARAMSET:
6 M& ?% Y+ U5 m9 L - // 通常会有多项VENDOR信息 (与WPA相关)9 j0 g( }; m# l% r1 Z. q: u
- vendor = (WiFi_VendorHeader *)ie_params->data;
* T5 ~- z( l- J8 b0 Q0 { - if (vendor->oui[0] == 0x00 && vendor->oui[1] == 0x50 && vendor->oui[2] == 0xf2)7 q/ w5 ^4 K& f- h4 |9 K
- {
' _2 I6 K/ f# y. D( G - switch (vendor->oui_type)3 \9 v: K1 G8 S7 I/ l; D1 D( s
- {8 E8 n! f N9 Q: t! l( J& u; V7 p
- case 0x01:& ^( C2 A1 h5 O$ v B$ E; h7 h" f5 q
- // wpa_oui
: e2 [# d" a2 x* z6 i - info->wpa.header.type = MRVLIETYPES_VENDORPARAMSET;: Z) R/ j% [ G: v2 c! z6 M' T
- info->wpa.header.length = ie_params->length;
+ {; B6 b5 \6 r" M+ k+ P$ _ - if (info->wpa.header.length > sizeof(info->wpa.vendor))
Z5 [5 |* D7 O/ g5 K* d* |# X - info->wpa.header.length = sizeof(info->wpa.vendor);
) `7 o" u6 Z+ @% d - memcpy(info->wpa.vendor, ie_params->data, info->wpa.header.length);; I$ [4 ]) {4 i. t6 |
- break;
, c( x: j8 g$ \% `- P' O - case 0x02:2 _/ R( f q# w9 n$ ^: {
- // wmm_oui
- F8 l3 ]1 ~) ]0 D - if (ie_params->length == 24) // 合法大小
! I4 B/ h2 G* \: ^: ?+ V- e3 e% P7 T - {% i+ Y$ `! B9 a
- info->wwm.header.type = MRVLIETYPES_VENDORPARAMSET;' ~& e! T. }" s T5 o- j* P! k
- info->wwm.header.length = ie_params->length;0 X1 g* y. a& A
- memcpy(info->wwm.vendor, ie_params->data, ie_params->length);* c. H) Y4 |3 ?9 P* J
- }" o& _3 d& }! m- y2 D; l* r
- break;: `& m, r# P8 S4 r% ^+ X& m
- case 0x04:1 V0 M/ g7 ]3 J
- // wps_oui
3 L+ k/ \; e# k" K$ \ - info->wps.header.type = MRVLIETYPES_VENDORPARAMSET;
# V6 C( {3 h% u" a4 N( a - info->wps.header.length = ie_params->length;. P9 k7 i+ S& ]+ }- w. {4 n
- if (info->wps.header.length > sizeof(info->wps.vendor))- Q# z2 I7 J& F
- info->wps.header.length = sizeof(info->wps.vendor);
& |2 v9 y ?. _- y) @2 Y3 j5 W - memcpy(info->wps.vendor, ie_params->data, info->wps.header.length);! a8 Z5 X; F7 o+ q6 d
- break;/ D4 ?: G8 D5 @( j
- }
' C, L6 ^" m- T# }8 a - } t' U, ?- P2 E: X7 D! G0 c
- break;
3 d9 Y% s, \1 e. n7 v - }6 {! q6 E4 v& H9 X+ n7 P3 \
- ie_size -= ie_params->length + 2;1 q) D- e8 j" q* j& G
- ie_params = (IEEEType *)((uint8_t *)ie_params + ie_params->length + 2);- g8 B3 R% f% S. w
- }
" z! z; i# O# J# V -
9 Y& r9 {+ c9 N! ?. ~. w - return 1; // 成功
8 r- h& `& i3 q6 N0 D( P - }( D( |8 M! B: N0 D7 Q
: ~/ G/ J0 c* U+ A- w& g/ s- void WiFi_SendCMD52(uint8_t func, uint32_t addr, uint8_t data, uint32_t flags)0 P- _3 {4 g6 \ ]
- {
* `) b7 T+ ]' x0 i" K - SDIO->ARG = (func << 28) | (addr << 9) | data | flags;
+ N) T2 M5 X/ N/ i' ~/ C - SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 52;# l) I" B3 f: g
- while (SDIO->STA & SDIO_STA_CMDACT);+ {/ z& t9 \$ X2 S5 a! z
- }# r" l# L; q F3 m
- ) A! |" Y$ U) D% v
- void WiFi_SendCMD53(uint8_t func, uint32_t addr, uint16_t count, uint32_t flags)
2 H& W* R9 _$ {; i% ?: |8 p - {. z( M- L: q2 A! V0 w7 u3 X" V5 D
- // 当count=512时, 和0x1ff相与后为0, 符合要求
0 H3 l( g( C2 y/ f) D5 ]% B - SDIO->ARG = (func << 28) | (addr << 9) | (count & 0x1ff) | flags;0 x; d$ k6 b3 B$ E2 q
- SDIO->CMD = SDIO_CMD_CPSMEN | SDIO_CMD_WAITRESP_0 | 53;$ O( ^/ g! y/ }* A% T. v3 C
- }
! w# o4 c$ j& t6 W& T
/ H: O% a1 }9 d9 K- /* 发送WiFi命令 */
+ Z+ x7 r/ t, _5 m* e1 \6 Y - void WiFi_SendCommand(uint16_t com_code, void *data, uint16_t size)
7 x) J7 o7 q" C8 [9 @+ t7 n$ v - {0 J9 B n0 K# [7 a7 N0 V
- static uint16_t seq_num = 0;
$ \$ x: |, i* ^( \" ]( F, M - WiFi_CommandHeader *cmdhdr = (WiFi_CommandHeader *)data;
( ^& V% T' h+ e, t5 Q6 W -
; j0 M& q% k; z( m9 ?6 A! K* o4 b - if (size != 0)
: P+ u: b r7 Y* H3 V - {8 T9 B' {" Q7 k, W5 Q# L
- cmdhdr->frame_header.length = size;" B9 D! X: i& D) n, z+ i& {/ c
- cmdhdr->frame_header.type = WIFI_SDIOFRAME_COMMAND;. S2 T5 H5 n, c: Z
- cmdhdr->cmd_code = com_code;
% H9 q- u# N& i1 _( w* A - cmdhdr->size = size - sizeof(WiFi_SDIOFrameHeader); // 命令大小包括命令头部, 但不包括SDIO帧头部* ~; E' z; l. O, W
- cmdhdr->seq_num = seq_num++;
& _1 \) S7 x' o: a# q2 j - cmdhdr->result = 0;9 |8 ~$ G3 R7 d) I2 x
- }
+ T- K6 {! Y1 U6 |5 q' ]) i - else5 X+ t$ l) D% a* a, r1 A" ~
- size = cmdhdr->frame_header.length; // 重发命令时不填写cmdhdr
) M" u+ j" s8 p/ j6 R# h7 N - 7 n5 Y2 u! Z5 N5 H+ W7 ]6 v
- // 发送命令前若恰好有数据帧到来, 则直接丢弃* \) P! f4 a! h; P
- if (WiFi_PacketPending() || WiFi_PacketArrived())% U A$ t# o' b7 c. c6 }% V
- {
N9 K9 V! y6 Y: k+ ]. T - printf("A new packet happends to arrive when sending command! Drop it!\n");
+ l k; j8 X# }" `% B5 s - WiFi_DropPacket();
( J }! u9 I/ C4 @, r - }
( h1 |2 x, J J -
. I- g9 J2 C! E" X4 A+ [ - WiFi_WritePort(data, size);
4 m) P' u# M4 [' T& j - }
; r1 N! d3 b2 [% N* G - # o8 D: Q8 G% ^. v* P( N: r
- /* 发送数据帧 */' s" I/ r0 e. s+ }+ [
- uint8_t WiFi_SendPacket(WiFi_DataTx *packet, uint16_t packet_len)0 W9 G( @2 b' K, O7 G! x
- {
3 X5 p. ^2 |! B" q2 l/ A' @. K - uint8_t ret;. s' L6 V% x; \5 T
-
) d, q, E, g: j/ J* m7 i - // 有关发送数据包的细节, 请参考Firmware Specification PDF的Chapter 3: Data Path
9 d' V7 X6 I7 m/ L - packet->header.length = sizeof(WiFi_DataTx) - sizeof(packet->payload) + packet_len;
4 M$ d" f! O( F" E, I" I* A - packet->header.type = WIFI_SDIOFRAME_DATA;
% W f# S" d3 j4 m4 m5 _$ c3 | -
2 B' q8 J" n/ z3 K5 {8 h - packet->reserved1 = 0;
1 U2 d4 p. D( V6 k) X9 V - packet->tx_control = 0; // 控制信息的格式请参考3.2.1 Per-Packet Settings
3 ?' z6 m+ M6 J8 Z - packet->tx_packet_offset = sizeof(WiFi_DataTx) - sizeof(packet->payload) - sizeof(packet->header); // 不包括SDIOFrameHeader
& I; ~3 l% _$ s - packet->tx_packet_length = packet_len;4 i- B" a& K9 m3 Q1 F) G
- memcpy((void *)&packet->tx_dest_addr_high, packet->payload, 6);: w( T" f* S- Z3 k* _3 G& S- m
- packet->priority = 0;( m0 X' Q( Z% v
- packet->flags = 0;
$ H) c! d6 J' N. V9 R - packet->pkt_delay_2ms = 0;
* I+ V" g( b: J- Z1 n- L3 K4 s - packet->reserved2 = 0;
1 E, e6 v' U* J% x- _9 j: ^ - ' M- g' U8 ]2 o9 q( ]: l
- // 若现在有新收到的数据帧, 则暂存数据包大小( g: O. f8 p4 G7 O/ |6 h4 x
- // 未读取之前不会收到新的数据帧
- I. R t8 a0 B v& p6 w - if (WiFi_PacketArrived())
4 U2 w6 y5 P0 D! u - wifi_pending_size = WiFi_GetPacketLength();. o+ H# `1 ?0 E( U% ^% T$ q" x
-
# z8 |- S! U0 M: H5 h% t% w - ret = WiFi_WritePort(packet, packet->header.length);
# i* W: `; V, c4 ]) p6 J4 x- u9 X - WiFi_Wait(WIFI_CARDSTATUS_DNLDCARDRDY); // WiFi模块收到数据后, 会将该位置1
" t0 ?" O/ }: ^5 H - return ret;
$ u6 S- ~# P& [: O7 e- F - }
! Y+ X$ T4 B7 Z, Y, _" D
- D5 J+ B- g1 I+ C# o: T- /* 将SDIO->DCTRL中的块大小信息应用到WiFi模块指定的功能区上 */2 T5 E) O4 |" @/ N' {$ W
- void WiFi_SetBlockSize(uint8_t func)
, Y7 f/ Z, L2 R( q - {3 R2 j3 d7 }. K9 {5 m! _# `6 Z2 z
- // Part E1: 6.9 Card Common Control Registers (CCCR), 6.10 Function Basic Registers (FBR)
/ x: T# w u/ p2 z) ~% V - uint16_t size = WiFi_GetBlockSize();
& r! h+ D# O3 l x( q, D, L: c - WiFi_Write(0, (func << 8) | 0x10, size & 0xff);) Y( m- g# H/ L: {5 j x
- WiFi_Write(0, (func << 8) | 0x11, size >> 8);5 J$ j. m9 v# p# Z' k
- }( \5 m; b) q; |8 ^
& L6 v' L9 m2 I$ I- /* 设置密钥 */% F- ]2 M, ~( }7 i$ E1 X* z+ h
- uint8_t WiFi_SetKeyMaterial(uint16_t type, uint16_t info, const uint8_t *key, uint16_t len)
. t, R: S; U) h/ b# x4 } - {
1 O1 k. e: r& R. W0 l - MrvlIETypes_KeyParamSet_t key_param;
9 k) C" [* y! E# s - if (len > sizeof(key_param.key))
" S' m! U: @/ k( X( g - return CMD_STATUS_ERROR;3 |' x- b2 c& e4 k3 L) h
- key_param.header.type = MRVLIETYPES_KEYPARAMSET;/ \ v3 m! H3 s7 z
- key_param.header.length = (key_param.key - (uint8_t *)&key_param) - sizeof(key_param.header) + len;
/ Q7 C/ t1 A# p& f8 A0 I7 @ - key_param.key_type_id = type;
* ?7 u$ v& c/ r U, B3 W. ^+ _+ V - key_param.key_info = info;% f6 u4 j- w" q$ o% O* z! C7 K! i
- key_param.key_len = len; // 当len=0时可保留key的值, 只更新key_info. u0 o7 r" k# E
- if (len)
( o- N* d$ ?7 L4 H, ` - memcpy(key_param.key, key, len);
5 a5 X; E5 ]7 c1 |! Z: x o( G5 c5 [ - return WiFi_KeyMaterial(&key_param, MRVLIE_STRUCTLEN(key_param), WIFI_ACT_SET);
9 w. F! J0 A* Q8 H9 r - }" o: b( c2 w! H! d' ^
- 1 ^: C" S; I9 h, ^6 U$ u. e& n# }
- /* 显示WiFi模块信息 */" d/ Y+ u7 S( F/ I
- void WiFi_ShowCIS(uint8_t func)
0 e5 A. d* m0 z! v5 n/ x# d8 y6 x - {+ ~! p+ K g) t1 r/ T) J; i
- uint8_t data[255];5 g5 f* P5 E: n! ~
- uint8_t i, len;
' b" x' Y. g- U( _ - uint8_t tpl_code, tpl_link; // 16.2 Basic Tuple Format and Tuple Chain Structure
+ C& `) K/ Z( J" t" a1 ?; p - uint32_t cis_ptr;
h# O# Z7 I9 O( h, X% S. j* I; z -
; S: m1 q1 p# m - // 获取CIS的地址: Z; y8 f' W2 X+ Y' G$ o
- cis_ptr = (func << 8) | 0x9;2 I4 G; r9 s3 S Q w6 k6 g
- cis_ptr = WiFi_Read(0, cis_ptr) | (WiFi_Read(0, cis_ptr + 1) << 8) | (WiFi_Read(0, cis_ptr + 2) << 16);
1 A* J. V: p+ W! q' q* ^ - printf("Pointer to Function %d Card Information Structure (CIS): 0x%08x\n", func, cis_ptr);9 i+ w& ]! p+ b4 p7 T0 b; t% l6 j
-
0 W' @+ t/ L* e$ h1 x3 H2 F# A; e - // 遍历CIS, 直到尾节点
+ E5 S; B8 Z; q3 ? - while ((tpl_code = WiFi_Read(0, cis_ptr++)) != CISTPL_END)
) r. ~' Q$ j! M, ^, Z5 p - {$ f! p+ y m. E2 [0 Y/ U; B
- if (tpl_code == CISTPL_NULL). F( b: Y. R) u& H, w. h! b
- continue;2 U1 o4 Q5 l& C" e& \1 V
- ( I! n# c& ?0 D" }! ^
- tpl_link = WiFi_Read(0, cis_ptr++); // 本结点数据的大小
* K h4 R+ q8 [- I+ {6 v* \5 O - for (i = 0; i < tpl_link; i++)
4 t4 o) c, R* k - data[i] = WiFi_Read(0, cis_ptr + i);
$ C3 [* B( g5 a5 U) A - 6 R, ^5 {( ?6 a. ~ \& E
- printf("[CIS Tuple 0x%02x] addr=0x%08x size=%d\n", tpl_code, cis_ptr - 2, tpl_link);
( Q9 I& _: Q7 O5 m/ ~1 |8 b - dump_data(data, tpl_link);
; t, E; {. Z. j - switch (tpl_code)' a8 O+ o+ g/ n. h) ~
- {6 x+ p3 D; |- e; k; _3 V
- case CISTPL_VERS_1:
* N( n# X! ~; g" P+ T - i = 2;# w* x$ \4 O1 }/ P6 n2 X" L
- while (data[i] != 0xff)
- H- C) c6 U* f1 G/ `( m2 C - {
1 D3 v# q. W% P; l - len = strlen((char *)&data[i]);) A# Y7 h4 b, |' G2 V. n$ b2 W
- if (len != 0)
]- z4 `# j1 M" m - printf("%s\n", data + i);
* }" |/ _; ` h8 |9 W8 K- B# \ - i += len + 1;
7 _0 n, k. ?; G, W+ x v - }0 [; @; ^5 o) L0 H) P
- break;0 p l( e$ ^$ d1 ?* f
- case CISTPL_MANFID:
: c; `9 s1 P% g6 d - // 16.6 CISTPL_MANFID: Manufacturer Identification String Tuple
- @5 k- k" n p7 O3 k0 ~9 e; s - printf("SDIO Card manufacturer code: 0x%04x\n", *(uint16_t *)data); // TPLMID_MANF
4 k2 K* l @6 Q+ ` - printf("manufacturer information (Part Number and/or Revision): 0x%04x\n", *(uint16_t *)(data + 2)); // TPLMID_CARD$ Q6 W! ~# L, a8 E% r
- break;
6 m, G- G4 P) W' f; z1 m A - case CISTPL_FUNCID:
2 }5 [- J( J- G- i2 ] - // 16.7.1 CISTPL_FUNCID: Function Identification Tuple% M* L% D5 m! S% L, `
- printf("Card function code: 0x%02x\n", data[0]); // TPLFID_FUNCTION
; m# C" N# |+ Y& P' N - printf("System initialization bit mask: 0x%02x\n", data[1]); // TPLFID_SYSINIT
' W O2 Y! f' i8 n - break;2 {/ Z; ?( `2 \3 i8 Y
- case CISTPL_FUNCE:
; @2 H: l8 ]2 H( C7 P - // 16.7.2 CISTPL_FUNCE: Function Extension Tuple
V" r5 ?4 k4 ?4 v8 ^9 } - if (data[0] == 0)
/ m- P& G1 Y. S1 K - {
. s% l7 n5 S3 `+ c3 O - // 16.7.3 CISTPL_FUNCE Tuple for Function 0 (Extended Data 00h)
) r6 s9 t% z5 e6 f! e - printf("maximum block size: %d\n", *(uint16_t *)(data + 1));( }& J( l* ~5 f7 D5 ^: v: @5 w4 v/ w' l
- printf("maximum transfer rate code: 0x%02x\n", data[3]);
3 @8 x) a& D6 b' `' p, ]) @ - }9 p1 u. x; w# S
- else8 h* @" w; F4 `# i0 }5 s' K* V
- {! v! N: n, a( K$ X+ ?5 m9 Q
- // 16.7.4 CISTPL_FUNCE Tuple for Function 1-7 (Extended Data 01h)
# i; m9 }& q6 k" T - printf("maximum block size: %d\n", *(uint16_t *)(data + 0x0c)); // TPLFE_MAX_BLK_SIZE
+ m& y4 g2 F% _) Q, ]6 ~" Y6 a - }; I+ o1 @) m* @3 r/ ?) |) w6 w
- }
: X2 K! b P- p6 t - + E5 x5 ]: M' I' _0 t
- cis_ptr += tpl_link;
7 c, C) ]& Q; _) o( z p - if (tpl_link == 0xff)
6 |0 e4 t; {0 l! b - break; // 当TPL_LINK为0xff时说明当前结点为尾节点
# G; n; O! s( w/ e! V4 n& x+ n% m" m - }
* @0 x+ |- b1 J" l% K6 p - }
, |: ~/ N" i' A( }9 o - ) a; `4 N* G. T% ~" A) M3 k% Y" u
- /* 显示所有密钥 */
1 d" L3 U1 b9 N1 w( B+ V* `. O0 i+ E - void WiFi_ShowKeyMaterials(void)
, {! ]1 l1 t6 s/ q - {0 g7 I- z. @" Q1 k2 y! g& i/ g
- uint8_t buffer[256];
4 K& \! `* N( c% z - uint16_t size;9 o+ r; `# ]% c& a9 u% N5 l5 M
- MrvlIETypes_KeyParamSet_t *key = (MrvlIETypes_KeyParamSet_t *)buffer;4 F. P3 O! Y1 }( ^6 Q( u
-
- K# [6 b+ d6 p - size = WiFi_KeyMaterial(key, sizeof(buffer), WIFI_ACT_GET);
4 k4 [3 I5 W: ?8 i2 p# u4 K: h9 @ - while (size)
) K9 B5 i6 v) X- J& l$ T - {& s8 l9 W% E5 p* S* G. R
- printf("Type %d, Info 0x%04x, Len %d\n", key->key_type_id, key->key_info, key->key_len);
$ c+ R) Y) @+ Y2 o) W - dump_data(key->key, key->key_len);
) W" r) }& J) ?7 E0 F4 k+ b, c - size -= MRVLIE_STRUCTLEN(*key);
1 H+ j& @) @* Y% x/ H. v' @ - key = (MrvlIETypes_KeyParamSet_t *)((uint8_t *)key + MRVLIE_STRUCTLEN(*key));+ ]. U- `4 P: Y1 Q
- }# r" b$ R2 {2 A
- if (size == 0)# Q* w- E. S" @1 H$ C9 e
- printf("data end!\n");
( @8 O1 \# T6 {4 i - }$ B/ g: {; |; ~4 A& S
- ) R/ ?. m7 a) ?/ \3 l0 j
- /* 创建一个Ad-Hoc型的WiFi热点 */
* @7 v/ Z! |6 E- {, J - uint8_t WiFi_StartADHOC(const char *ssid)2 p( G t0 f. j8 m) G
- {
: n5 i: F. ~; O2 i - WiFi_CmdRequest_ADHOCStart cmd;
0 k% O H% X( e/ m% {" m - memset(&cmd, 0, sizeof(cmd)); // 由于命令中含有Reserved区域, 所以必须先清零
% ?' w3 ]/ p; e9 D - & z2 _- v) |, L, G. C- M
- strncpy((char *)cmd.ssid, ssid, sizeof(cmd.ssid));
: y: W/ ]6 I) k; O5 x - cmd.bss_type = BSS_INDEPENDENT;& S: v1 T$ |# P
- cmd.bcn_period = 100;2 T- ]4 E, o" C3 `4 \; m1 \' w" g
- cmd.ibss_param_set.header.type = MRVLIETYPES_IBSSPARAMSET;1 Y6 d2 y" B' B
- cmd.ibss_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ibss_param_set);
0 g! s2 S% i: V, w4 M% i' ` - cmd.ibss_param_set.atim_window = 0;
4 I( x/ C: d0 f- \" B - cmd.ds_param_set.header.type = MRVLIETYPES_DSPARAMSET;6 h/ ]6 j: o7 i7 A8 B
- cmd.ds_param_set.header.length = MRVLIE_PAYLOADLEN(cmd.ds_param_set);/ _% g# q0 s+ G; q: y' P4 M
- cmd.ds_param_set.channel = 1;
5 s; Y( m7 V, g5 B6 U - cmd.cap_info = WIFI_CAPABILITY_IBSS/* | WIFI_CAPABILITY_PRIVACY*/;; d, E7 f+ i2 A
- *(uint32_t *)cmd.data_rate = 0x968b8482;$ b& l+ S, W6 u3 P% H z
-
% Y9 f2 q( w6 x L# w# |9 {. n' }# p - WiFi_SendCommand(CMD_802_11_AD_HOC_START, &cmd, sizeof(cmd));
, B1 a& n4 m) r. c0 X - WiFi_ReceiveResponse(&cmd, sizeof(cmd));0 ?7 j C' z8 u Q/ F
- return cmd.header.result;" P# U' H* r# h2 A
- }
2 P. L2 p7 Q' ^/ @2 i; k) |! \ z - ) S; B( H4 D6 Y0 e1 s
- /* 在规定的超时时间内, 等待指定的卡状态位置位(自动包括IO Ready位), 若成功则返回1 */; _$ ~- I' x9 r2 U. i; I
- uint8_t WiFi_Wait(uint8_t status)
8 \: u% ]' r& R6 D- D7 |- u5 G - {* Q4 j2 z0 ^: M! K4 t% X7 B0 A8 u
- status |= WIFI_CARDSTATUS_IOREADY;) p, w* z! U" I2 }8 t* w5 U7 `
- WiFi_PrepareTimer(wifi_timeout);
: S* T7 u. y$ s* F0 ^4 t - while ((WiFi_Read(1, WIFI_CARDSTATUS) & status) != status)
; H( w: ^, D. n1 P6 v. [# ^ - {! |! V. Q8 e& }3 o
- if (TIM6->SR & TIM_SR_UIF); v7 l0 `/ z1 a! r. M' ~1 @
- {
- l5 M' o- O' s - // 若超时时间已到
3 y# s q$ H# Y% r% I- m - TIM6->SR &= ~TIM_SR_UIF;
" }0 s8 I; a' R/ B+ g - printf("WiFi_Wait(0x%02x): timeout!\n", status);2 O3 x( x" p8 C7 a0 d4 ~
- return 0;
1 _0 b# o! h; T+ u! E1 t - }
h0 O- S9 E; y7 f* m4 M - }
. S, z5 V& l3 J( Q$ r - TIM6->CR1 &=~ TIM_CR1_CEN; // 关闭定时器
5 V! o7 b" U: F0 s) L% e. q2 \ - return 1;) H" _2 ? ?/ v
- }$ H- b! x+ ?8 G. ~% `
& X1 k# h2 A! [4 o- /* 写寄存器, 返回写入后寄存器的实际内容 */+ W3 J5 A4 b5 l" x! v) _
- uint8_t WiFi_Write(uint8_t func, uint32_t addr, uint8_t value)
$ y, ]5 N9 v+ V' q" b ` - {
0 }' S% V6 [0 n' _+ [( Y - WiFi_SendCMD52(func, addr, value, CMD52_WRITE | CMD52_READAFTERWRITE);& T, h7 R$ T. n& W K, o |: D
- if (SDIO->STA & SDIO_STA_CMDREND)
0 }# D; v) Z* f! z$ H* r) s- m - {9 w u) o7 S% a+ c/ C7 q
- SDIO->ICR = SDIO_ICR_CMDRENDC;" W$ F V2 t* Z' o" P* M. G
- return SDIO->RESP1 & 0xff;
i' x( o5 Q/ } J - }
6 P2 Q3 z7 f) K. r/ v# x - else6 E, Y5 v% U9 P# N( |$ w
- {# f$ |# A9 _9 D* s
- printf("WiFi_Write failed, SDIO->STA=0x%08x!\n", SDIO->STA);$ |# h; [ U1 b7 \- Y7 L9 x
- return 0;6 G8 Q1 w# c5 y6 @0 s$ R( Y
- }1 G5 o9 r5 M, _7 U* C# p
- }
4 R# s9 }: `' z8 p- u
1 s/ d# B7 \% a _0 M- /* 写数据 */
3 J6 J8 P8 Y* Z1 @ - // count为要发送的字节数或块数, bufsize为data缓冲区的大小
d. |: u1 v* \7 E, M/ F c - void WiFi_WriteData(uint8_t func, uint32_t addr, const uint8_t *data, uint16_t count, uint16_t bufsize, uint32_t flags)
; h* V" t0 y" m - {
' L. t0 ]3 `3 w5 c - uint32_t len, temp;
" d4 f5 ]) |% S$ F8 Z1 a0 e - if (flags & CMD53_BLOCKMODE)6 ?0 F" O/ R4 n/ Q R
- {/ R! v6 ~* A' z( r3 l
- len = count * WiFi_GetBlockSize();. {6 t6 ] {; m! J2 `
- SDIO->DCTRL &= ~SDIO_DCTRL_DTMODE;
$ i! Y4 I7 O' w! g$ s+ L2 }% K1 \* A - }6 _. b# k' F0 I9 k6 P4 H
- else
0 P5 N5 t6 m# i' K( T3 O! C- k* r7 k7 @ - {" q1 V5 }- b7 V# j
- len = count;
( E4 E% X ^; P% n9 h# v7 H - if (len % 4 != 0)
! r# m4 M3 ~7 y |6 q4 O0 o( @9 ` - {5 e( B; L: }* Z4 I) V
- len += 4 - len % 4; // WiFi模块要求写入的字节数必须为4的整数倍: W9 Y% @; L. t0 D" ]
- count = len;/ h, X/ ^& j; K) g
- }$ A3 x0 l/ M9 p s5 S* q% R _
- SDIO->DCTRL |= SDIO_DCTRL_DTMODE;
$ W! j) f% S/ P, D2 w" N* _' k8 U9 Q - }; I+ z" z" ?0 Q- u' B) n1 n( K
- SDIO->DLEN = len;
4 i! J& h7 o$ n% ^ - SDIO->DCTRL &= ~SDIO_DCTRL_DTDIR; // 设置传输方向: 从主机到模块# Y& D8 F9 i4 N, K
-
2 M- {0 ?& ]0 n. _# M - WiFi_SendCMD53(func, addr, count, flags | CMD53_WRITE);; q. \: D( z; @ G
- while (SDIO->STA & SDIO_STA_CMDACT);
' h: R/ o% b" W! T- j+ x2 K5 S - if ((SDIO->STA & SDIO_STA_CMDREND) == 0)* B! h- h. Q5 u- z! H1 `! M
- {
G- w, V! m! ? - printf("WiFi_WriteData: CMD53 no response!\n");3 v* @! g1 ^! P4 y7 m' Z) W
- return;
& b- x& [0 A, m6 n% L3 i6 E+ x - }$ h5 @+ o5 H. H9 ?
- SDIO->ICR = SDIO_ICR_CMDRENDC;
* B" P) R+ U* b2 H1 O$ j -
& z1 D% ~- d; `/ `0 P* x - SDIO->DCTRL |= SDIO_DCTRL_DTEN; // 开始发送数据5 |0 l5 n: L0 \$ ^
- while (len)
- H1 E& o% ~0 b- H( J - {7 c/ z" p/ W2 l( @) E
- len -= 4;
) O/ o0 u9 g: j+ u. F6 ?7 Z$ h - if (bufsize >= 4)
. e _- b p. }6 K - {
* ~) J: ?3 r- Y# e - SDIO->FIFO = *(uint32_t *)data;4 Z# T3 h* c& Q- h. C& w
- data += 4;
. k( H) {' Q1 l! E7 d4 ^, G - bufsize -= 4;
- M8 c g* P8 S! v$ {' J+ R8 d. J - }4 N ~6 t/ N# @& u
- else if (bufsize > 0)
; p* q) j; p# R# P5 N1 G5 J - {
( @$ w, R# r( i - // 发送缓冲区最后1~3字节7 d+ O7 U! C! u/ V5 |+ J5 j
- temp = 0; // 不足的位用0填充+ K0 j7 P) o$ f. X Q
- memcpy(&temp, data, bufsize);
- ~ ]0 p( `+ @2 w7 ]4 @8 s - SDIO->FIFO = temp;8 ?$ V9 W+ Y6 z: v
- bufsize = 0;
5 e; ^6 ^' x4 u& a: H2 m, o - }
* j! Q/ u& f5 m9 Q7 C2 @/ V - else
. W4 L$ A- O/ }" M - SDIO->FIFO = 0; // 缓冲区已用完, 因此发送0+ a9 Z# a* L, I' E/ C2 Y. W
- while (SDIO->STA & SDIO_STA_TXFIFOF); // 如果FIFO已满则等待3 t. q# |2 ~5 u4 [- B4 b: Z; Q, U9 ?
- }, w8 Y1 I* L+ }' y& }
- 3 U: q, j* n/ _. B; q9 {3 v
- while (SDIO->STA & SDIO_STA_TXACT); // 等待发送完毕
' f) Z% [& I6 e9 ` - SDIO->DCTRL &= ~SDIO_DCTRL_DTEN; // 数据传输完毕后DTEN应及时清零, 防止后续对DCTRL寄存器操作后误启动数据传输导致超时或CRC校验错误
; S, x3 ]8 B+ j9 U - * T( M% H& a# N4 E( d; ]
- // 清除相关标志位. F5 l1 ^/ V8 [, S( I, f
- SDIO->ICR = SDIO_ICR_DATAENDC;
9 z/ c. M6 o2 ]' k# E- s3 Z& B - if (flags & CMD53_BLOCKMODE)
, `3 S' F+ Q9 k3 i! |6 w& u o - SDIO->ICR = SDIO_ICR_DBCKENDC;, V5 Z" }; K5 k+ [3 e: b9 K
- }( F h5 w& v& f4 W
' p: o! A# t" |3 Z. P: s3 b& H# x* F- uint8_t WiFi_WritePort(const void *data, uint16_t size)7 m4 A. s% h. q9 J7 s5 h( L
- {
8 u3 d9 y. j; N, s9 N' t - uint16_t block_num, block_size; ^, @! R! J9 s! n5 @
- block_size = WiFi_GetBlockSize();, o' D3 E6 R6 }4 M0 e: o8 ]% M; K
- E8 K. o( O7 w, T3 P; ^* d: l2 C
- WiFi_Wait(0); // 发送CMD53前必须IOReady=1
" N6 z7 @% m4 g6 {8 F+ l" \( S - if (size >= 512 || size % block_size == 0)
' ?) X+ [6 d/ Y. i2 [ - {, v0 P( }* F3 i8 x- y
- // 采用Block模式传输
- T$ z& C" X3 I' k" t8 ~( l - block_num = size / block_size;3 B+ b9 I, ~9 Y* W9 e
- if (size % block_size != 0)' B, Z& R# ^8 S5 @
- block_num++;
" ?9 |4 F1 A+ ^ - ) z# Q( z0 V, C" N
- WiFi_WriteData(1, io_addr, data, block_num, size, CMD53_BLOCKMODE);
/ `4 O* n, {* A: c, D- a - }0 C$ K% A* q2 p8 |5 C
- else2 ?) i* j: S! l+ l2 E
- WiFi_WriteData(1, io_addr, data, size, size, 0);
, i/ N- m: L( A, R2 F" P - return SDIO->STA == 0;
/ L- D; r+ y+ b - }# `3 V3 _1 \* J' K8 z
复制代码
1 V6 u" B! Z A) R1 v6 ~$ @9 [3 d4 _) A* m0 B3 L0 O# N6 m, I l
在工程的所在文件夹创建一个lwip文件夹。9 {0 K* b$ O8 y. _% [+ g3 q& j7 C
然后在lwip的官方网站下载lwip-2.0.2.zip,打开压缩包中的lwip-2.0.2/src文件夹,解压以下文件夹到工程的lwip目录下。
1 j P8 Z- I- I8 V# n& C: z/ ]5 N) U& r: \, P4 l0 T, D
core/
1 p) y# a# {7 p n4 M1 ^5 s1 G: rcore/ipv4$ F9 s9 R) q! h1 D- w) y. R9 `. ]
include/lwip
" t R$ Y7 [& z, G+ ^include/netif
s8 A& U4 F0 G" A* Wnetif/ethernet.c
- a- Y3 _( @1 l6 e. {7 B/ u0 F. unetif/ethernetif.c- ^1 k6 H3 C2 K( ^5 b3 f+ O) x
- B. V% _ H) t解压后,将里面的c文件都添加到工程的lwip分组下。
a/ R8 C' @& j+ T; `具体添加的文件请看下图:9 U9 `) L7 t8 r( e3 ]; ~. D

5 C/ A8 P7 N% i. q/ T
: Q+ U3 P6 B& Z5 f4 r3 C接下来,创建lwip/include/arch/cc.h文件,内容如下:0 K3 K* F3 ~3 o0 z
- #define PACK_STRUCT_BEGIN __packed // struct前的__packed
复制代码 创建lwip/include/lwipopts.h文件,内容如下: V0 Z& \% O( A% N( e0 n; p
- #define NO_SYS 1 // 无操作系统 ) u* w0 D2 {3 S" z
- ' h! g! X3 q- \9 o4 A {$ T
- #define LWIP_NETCONN 0 ' R& L, {( K1 t6 V; T
- #define LWIP_SOCKET 0 . R9 v0 I# K. ~/ z2 E
- #define LWIP_STATS 0
: I2 `$ v5 C" \* g3 m: J1 d - 3 G9 v: _2 m7 P- a' _4 J; ^4 c" p
- #define MEM_ALIGNMENT 4 // STM32单片机是32位的单片机, 因此是4字节对齐的
9 x4 x" ^$ c0 s6 k7 h# M4 G H -
0 y9 o0 E: A% Y' a. g( ~4 { - #define SYS_LIGHTWEIGHT_PROT 0 // 不进行临界区保护 (在中断中调用lwip函数时要小心)
复制代码 打开lwip/netif/ethernetif.c文件,按照下面的中文提示修改代码: m. H! E; }8 G/ @# d* v- x
- /**7 @+ P" D1 U! R
- * @file
7 X( |/ u1 t; ? - * Ethernet Interface Skeleton
& J8 N' h$ K! F0 |% ^6 E0 j - *
6 g4 D. N) O [2 T - */
2 Y! i9 n! A b+ B% @4 p4 O
j) v( Q# {2 W6 W4 |% f- /*1 e. n' Y2 d G" b$ C* f
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.. }3 Q: V* H3 G
- * All rights reserved.
. F+ P- z) `# Y O - *
8 A/ e1 A8 x8 l+ l6 Y( S - * Redistribution and use in source and binary forms, with or without modification,6 m4 B) P$ C0 m6 v5 W
- * are permitted provided that the following conditions are met:
( M ?" `" p, J8 |+ ~' W! x) E - *5 p6 [ {6 ^6 X. e U$ p" Y
- * 1. Redistributions of source code must retain the above copyright notice,* x, C1 g5 j5 j3 \1 x) a
- * this list of conditions and the following disclaimer.
, V ]$ A# U2 X% W0 w8 s1 V; j- t - * 2. Redistributions in binary form must reproduce the above copyright notice,
& ^4 Z y8 B0 ~! T# u+ O - * this list of conditions and the following disclaimer in the documentation3 y. e% u3 s8 N- v
- * and/or other materials provided with the distribution.
7 h7 w, n: L: m0 S6 d& l( m9 A+ W - * 3. The name of the author may not be used to endorse or promote products
. [* Z6 f$ t$ s5 H7 T - * derived from this software without specific prior written permission.
+ D7 e8 J( j2 y. d+ [ - *
' @* H" v- m( A! ~5 ~$ s! U4 a - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
$ }) f. O8 j* m - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF( c8 j9 s3 d$ J/ Z- U: d! L
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT+ d! i+ Q, T' K7 v* A
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,: ?" ~* s1 Z. t, z/ }8 r2 H
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT L2 G7 I9 L, j; J& u; t( U* G
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; k: j1 L" |$ a4 Q - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
) X+ S# v/ d2 d6 Q - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
" P3 S! X# G9 ?3 u: z, `- y - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY' }: a' }# J8 W3 F
- * OF SUCH DAMAGE.8 k. G" m) |, K4 E; y8 |4 l/ N
- *; L& l8 @2 v+ ^4 h' Q5 \
- * This file is part of the lwIP TCP/IP stack.
1 k7 v7 s' Y3 B; V! a3 t; v - *
' E. l% q4 Z# S( j5 { - * Author: Adam Dunkels <adam@sics.se>1 x9 V1 N! ^' A/ h V/ A
- */ X+ Z* O8 Z$ O8 A& V& V
- */
5 A' k- P2 v; A3 ?/ i
" k5 |" C: K M- /*
7 e! |0 ~0 N5 I3 d - * This file is a skeleton for developing Ethernet network interface* z0 R+ g6 |( d2 E2 X
- * drivers for lwIP. Add code to the low_level functions and do a2 \0 E2 E+ x( J* p: h) W ^8 F7 u. _
- * search-and-replace for the word "ethernetif" to replace it with
# K' B% u( j# ~% d - * something that better describes your network interface.
; l& E3 n- T3 u5 H) T* Z6 J$ A - */
. V# n) ^" J% [. V' ?/ R b - , Y% j/ B( T8 U" s
- #include "lwip/opt.h". p2 I% M1 t8 ? T9 z
- ! {9 I+ j* y. @4 }9 t
- #if 1 // 允许编译器编译该文件
( E1 R& \/ w y8 N8 d. S0 ^+ P# g
& D# s K* Q+ H6 y- #include "lwip/def.h"' r; l+ p' z6 r6 I. @
- #include "lwip/mem.h"
6 q% L( `2 `" E0 N - #include "lwip/pbuf.h"
5 I. H3 Z( ^$ E) R, F - #include "lwip/stats.h"
. [$ n8 c$ P% M7 y/ S - #include "lwip/snmp.h"
9 O6 f) ]; `. r4 a - #include "lwip/ethip6.h"8 O) ~1 C, [; M8 D+ Y7 E
- #include "lwip/etharp.h"* M K, [) R1 }! h+ D7 }: \
- #include "netif/ppp/pppoe.h"0 c) o2 ~. P# _/ U
; @, ?( m4 J7 B6 `- /* Define those to better describe your network interface. */5 F$ e, ~7 j H' P* S& b% D
- #define IFNAME0 'e'* c& V3 U) }' D( Z0 J
- #define IFNAME1 'n'" Z6 Y) y* x8 v/ J" J$ D3 P0 b
3 k! U: B2 y- {0 q8 v6 u, Z& N1 M7 S- #include <string.h> // memcpy函数所在的头文件4 l3 [5 ]1 d+ j& e' `( ~
- #include "WiFi.h" // WiFi模块驱动程序头文件
- @7 Q* ^' i2 m% _3 o; E& J - & p" x4 r6 c; b7 I# q! B
- void dump_data(uint8_t *data, uint16_t len);$ z" A' B% i/ U h
: v N3 G7 ~, w8 ?+ Y- /**8 V* Y- o7 k' T! ~ g R- i' P
- * Helper struct to hold private data used to operate your ethernet interface.
! n! K; y. X% V4 Z0 j* N& G' ]! s \ - * Keeping the ethernet address of the MAC in this struct is not necessary
" M7 [. z. e7 U. J - * as it is already kept in the struct netif.! X) e J5 `8 Q/ i
- * But this is only an example, anyway...$ U3 b" v0 O4 Q- t, p' R9 l
- */
2 L: s$ ~4 {/ c* p - struct ethernetif {
T8 J0 H0 u( E - struct eth_addr *ethaddr;- P' |9 v& x8 p; h$ k
- /* Add whatever per-interface state that is needed here. */
, ~5 Z, G' C3 `0 c5 y* M+ p3 i3 H - };. K# z; _) S& s3 X& O6 }
- 5 s4 w3 J" k: L
- /* Forward declarations. */. a: d2 v, H, e/ O- \# P* U: I
- // 这里必须去掉static
, a2 Q7 m# ?( K" I5 w! ^4 H: _ - /*static */void ethernetif_input(struct netif *netif);8 a5 C0 B! y5 F
- + A1 } |8 @/ q7 V0 i6 l: h2 O/ M
- /**8 S- l3 b' o) _$ R; i! i, U
- * In this function, the hardware should be initialized.
7 E+ h% q* O# ~* {5 }4 D& j - * Called from ethernetif_init().
5 |. o. m7 B" J4 ? - *
7 ?. L7 T, e- n' l! X2 M" o - * @param netif the already initialized lwip network interface structure
0 @ V1 _" }! n9 |5 V' o$ i - * for this ethernetif6 {& |3 U# W/ C- h3 a0 e/ x' A6 D
- */: y/ Y& s7 s% y
- static void
% f% L+ R' u: L$ f - low_level_init(struct netif *netif)/ Z% e% K V0 ?1 v
- {
+ z! R9 u2 C+ N5 y: \' @ - struct ethernetif *ethernetif = netif->state;( U+ P' G/ M! L$ C$ f
- % E. p4 j4 F, A7 E J [
- /* set MAC hardware address length */
% u4 s0 |- [( N1 B$ C# R3 o; i. t - netif->hwaddr_len = ETHARP_HWADDR_LEN;: c; e! U6 S/ G1 H G0 J; R0 L
. b4 Q" o9 R, K( |) ~, R7 h- /* set MAC hardware address */+ X2 ~% G+ ?; E2 `/ `
- WiFi_GetMACAddr(netif->hwaddr); // 获取网卡的默认MAC地址
9 R1 T( q! O& M0 `4 T - 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]);& A- v& U- z1 H# W& Y/ ]! H
9 A1 P" X$ `; S- /* maximum transfer unit */
+ G% h0 v* I) t0 T; `4 Y) h! S3 p - netif->mtu = 1500;
. \$ {8 l: s% l" y2 E; b }) I
& t9 T) z0 b( k# b' e/ [- /* device capabilities */9 Y A, V; x3 O0 i
- /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */* u0 L& J) d1 g: p3 v1 T2 Q
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
Y; A, \* w' c& @ C: h! O/ W6 c - 0 h. }3 t1 }- a$ Y. R
- #if LWIP_IPV6 && LWIP_IPV6_MLD
3 c1 B% ~; h+ M- ?# l `4 g7 D( i# |) s - /*7 I! t" M4 v4 i
- * For hardware/netifs that implement MAC filtering.
$ s* Y: ?) Y/ c% r - * All-nodes link-local is handled by default, so we must let the hardware know2 f! P. w* U) e+ A" j Y9 U( Y
- * to allow multicast packets in.$ N; o8 u- x6 [( v
- * Should set mld_mac_filter previously. */
) i0 H9 [/ _7 M$ g9 P6 { - if (netif->mld_mac_filter != NULL) {
8 U% M) P; U0 i$ H# R* L - ip6_addr_t ip6_allnodes_ll;3 L- {2 P8 w. c1 p1 v
- ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);( j' ~# T1 q# @2 ~% j
- netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
q# o B/ g [! K - }
2 F% R4 }* b- p# S9 k - #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
1 }) h" u/ j% W+ i0 V& b
; o e- r% Q8 v1 d" y+ @7 u! C2 L- /* Do whatever else is needed to initialize interface. */7 j0 P! O% S; H D6 T$ ]) i
- }
W" V0 O5 C6 C - - @/ Y* W z. C0 c, @, Z
- /**/ G" V& o8 ?7 }; J
- * This function should do the actual transmission of the packet. The packet is
& T r. k7 j" D) p2 p& Z+ d - * contained in the pbuf that is passed to the function. This pbuf
1 j+ ~, `4 N3 U- N8 L9 O8 Y - * might be chained.
8 s( \1 V+ G. h% V - *
* |4 f7 S5 K2 L- G8 Q" I - * @param netif the lwip network interface structure for this ethernetif; ~1 x7 y# @" V' J$ \# H4 k
- * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)6 e/ `* N8 S4 b% H6 W
- * @return ERR_OK if the packet could be sent
$ }5 B4 O! m' G% B, a7 T - * an err_t value if the packet couldn't be sent
4 a2 g9 B/ h; D, Z - * H+ V/ y; [4 }1 B8 t
- * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
7 ~" x; [( n7 M! N, i - * strange results. You might consider waiting for space in the DMA queue' }: o& u/ y# |6 g
- * to become available since the stack doesn't retry to send a packet; x9 t5 m% Y) {
- * dropped because of memory failure (except for the TCP timers).3 z9 I$ k: w7 ?, w- \1 Q
- */$ V4 c0 |; t! L8 N
9 ]+ w' n$ U1 X+ l6 N' m7 \- static err_t
: S; q" a! D A! I1 Y8 i0 }6 X - low_level_output(struct netif *netif, struct pbuf *p)
6 J, o+ E! U7 A: n$ B - {+ L* |) S9 J% t7 ~, X
- struct ethernetif *ethernetif = netif->state;
' O9 L0 D8 M/ E0 U+ p6 r( I) t; w - struct pbuf *q;
" S/ g7 F6 Y5 L0 O7 u - 6 }4 L4 }' N8 Q7 L" L0 U1 S
- // 添加的变量
& m7 @/ _) ?0 O1 Y - uint8_t buffer[1792];2 T# `. @1 z7 P5 p& e' t
- WiFi_DataTx *packet = (WiFi_DataTx *)buffer;
4 X) g1 ]1 c+ g1 @8 ]$ `- L* e - uint8_t *bufptr = packet->payload;
" T. w, _. `1 I/ n( C! M- C - 8 Q5 d% K8 B; L
- //initiate transfer();
+ R1 O# z* o6 q6 G) q7 X7 U# Y! s5 ]) } - 4 X- F d2 J* s; [ F8 z" r
- #if ETH_PAD_SIZE w+ |, O) j5 {4 p
- pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
, Z2 l7 o* `2 l) N. _# I - #endif
" x0 ^5 T* c- J% q8 }" a - ' D& }1 ?6 B B. K# L1 o* Z( Q
- for (q = p; q != NULL; q = q->next) {5 l1 C5 S4 q. s4 ?
- /* Send the data from the pbuf to the interface, one pbuf at a+ w, H% e- z9 |5 [( I: E( |
- time. The size of the data in each pbuf is kept in the ->len/ r# i" {' |: Q! ~$ W! m
- variable. */
4 t0 z' T$ V) \0 j. y- n - //send data from(q->payload, q->len);
0 D+ n* j2 x, c: }: |; K V - memcpy(bufptr, q->payload, q->len); // 复制数据包内容+ I8 R! i4 ?8 U6 i8 ?) k' Q
- bufptr += q->len; // 指针前移3 y! s% }1 ]% K$ D2 p, x
- }
. O$ v# d% M2 b1 m9 h& }2 U
1 I9 ?' K+ I S8 S4 [) ^- //signal that packet should be sent();. \, p, ~& h; Y, R c
- WiFi_SendPacket(packet, bufptr - packet->payload); // 发送数据包
, p9 ^. |0 Z; y7 i5 ^* {* r& w - ; @/ Y* K" O4 z- j! E- {# O
- // 打印数据包内容" u$ \, H- n3 R1 M3 @. {/ P4 X
- printf("[Send] size=%d\n", packet->tx_packet_length);
& j8 m4 V6 I4 h, ]. h( `# [: M - dump_data(packet->payload, packet->tx_packet_length);
5 R4 \" @1 n1 n0 ?9 R7 l. g - # ?; ^4 o& D O$ B: I) r+ K
- MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
* ?7 n) o4 _# A) `- R+ Y. } - if (((u8_t*)p->payload)[0] & 1) {
9 ]& y# i8 r) U1 P* m - /* broadcast or multicast packet*/1 p. d0 J" d) C2 r' r7 s
- MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
O9 n( \* ?) G" }0 L! m - } else {6 x$ y9 u3 a) ]
- /* unicast packet */% _% W" G. `6 @% L
- MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
* m& U+ ^% H, h/ \; n2 M - }
d& [( }2 q& N( q' L - /* increase ifoutdiscards or ifouterrors on error */6 C2 R8 P) I3 K% ~4 i, `% ~8 F
, m! A0 l! h, |; l- #if ETH_PAD_SIZE
. [ W/ m4 ^0 K3 Y! v6 J: Z9 \7 D. F- R - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
* n& U$ ^; [, g8 Z, ^ - #endif
4 a% j; e! W8 d& v6 K
; z# T6 i& ~: E1 d* z+ M- LINK_STATS_INC(link.xmit);8 R1 K( I% F! |/ F
- ) L' e, b, k9 B
- return ERR_OK;( {3 K- A0 ~' J" v! N% j
- }0 `" v+ H' A7 ]6 u6 m H
; ]) D, w8 G# W- /**
' T) S9 Z- ^7 ^& n) n - * Should allocate a pbuf and transfer the bytes of the incoming+ u; l- u2 E+ ^5 [& I) s
- * packet from the interface into the pbuf.0 `) T7 ~! @" ^5 x4 ^, ]
- *! B+ j' y: x% X2 R7 S# p7 C
- * @param netif the lwip network interface structure for this ethernetif) Q, q. V9 c# n' g' t& T; s0 x, h
- * @return a pbuf filled with the received packet (including MAC header)7 s/ {: V/ j6 {; [+ A% s h
- * NULL on memory error2 G' f: }+ @ B& d5 ?9 F9 ?; Y* x6 ]
- */8 m7 j1 Z5 g _; T8 G$ o
- static struct pbuf *
S% W7 e7 i# m - low_level_input(struct netif *netif)
) X$ H! D$ c! Y6 L3 f- ~ - {
5 K. ?. a# K6 t4 b - struct ethernetif *ethernetif = netif->state;
0 x, S1 c& h8 r( Z+ | - struct pbuf *p, *q;: ?" x6 @( V, P8 ?0 M
- u16_t len;, J' o4 u) Q7 W$ n- O
-
. z8 e* G( o# n9 G7 @& U - // 添加的变量0 Z$ X: W4 {3 W
- uint8_t buffer[1792]; // 由于WiFi模块本身不支持使用多个CMD53命令读取数据包, 所以必须建立一个缓冲区, 一次性读取完
' ?% X2 [. I4 ]8 w - WiFi_DataRx *packet = (WiFi_DataRx *)buffer;% \5 Y- j/ N0 x4 k) V
- uint8_t *bufptr = packet->payload;
" S2 G( R/ s) [5 X0 c - 2 ]0 i0 i( v: Y! ^- V
- /* Obtain the size of the packet and put it into the "len"0 B* U- z# B2 M3 C8 O6 Q* O. w
- variable. */ q& {7 H1 N, Z" g% h
- len = WiFi_ReceivePacket(buffer, sizeof(buffer)); // 读取整个数据包, 返回值包含头部大小
' B$ T. s7 L% F( r# h$ ^4 r& _ - if (len == 0)+ [$ P8 J5 ^& f0 l( S$ _; Y! e7 L
- {
- c" s1 c& u& n$ Z" f! _ - // 若读取失败, 则不分配pbuf, 退出本函数
2 m6 C/ q, B2 }2 x6 U1 ^ - p = NULL;
; l, ^2 g& s5 v) y - goto after_alloc;
2 z' R# i% D, h0 y' s - }0 ^# ?) {/ _2 K" L8 n
- len = packet->rx_packet_length; // 获取数据包的大小
4 _* g& R) q8 I/ I" F -
4 x# K" o* @" F/ g) f, _, n( e - // 打印数据包内容
" X0 o% g3 G9 [0 k( Z# A! _ - printf("[Recv] size=%d\n", len);- ~! E+ } |( D E$ G3 U
- dump_data(packet->payload, len);
, n+ V3 {0 P( r, r% O" `) c6 r - 0 U1 S" _0 Q0 J+ o. I' i s
- #if ETH_PAD_SIZE( B! A3 C5 `! {2 t5 ?
- len += ETH_PAD_SIZE; /* allow room for Ethernet padding */( I X& o% W. c6 L) M: T: W
- #endif
) V5 @" V$ G# F - , B8 d$ X, n4 s; ^% q
- /* We allocate a pbuf chain of pbufs from the pool. */
. m- j9 w+ e5 s4 G1 v+ v - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
! L: j" O% X" n) F7 V4 Z/ _* I - & g! o$ Z5 n4 D4 d; |
- after_alloc: // 添加此标记 ~0 u/ W% d! X l* S* M
, z1 j' H# E2 {, S( P t- if (p != NULL) {. z+ c8 I# J& @2 w: w$ l
- ( ^8 M1 |- g% o
- #if ETH_PAD_SIZE$ ~* c( q* W# P! W/ ?
- pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */. Q9 w- W5 i& {# l7 b
- #endif
) }+ f7 a7 ^$ O+ e3 @! z; b - 1 a7 Q k1 g/ [; S+ S1 O6 _" |
- /* We iterate over the pbuf chain until we have read the entire
. V. u9 Y+ X/ j+ e8 x - * packet into the pbuf. */ Q6 }: |+ v6 T3 q/ h
- for (q = p; q != NULL; q = q->next) {
( h# z' ~5 b+ z. @ - /* Read enough bytes to fill this pbuf in the chain. The
% l# L$ x T* O! }/ Z9 P$ x) g4 k - * available data in the pbuf is given by the q->len
' ?" h; U8 k" \9 [ - * variable.5 [2 _5 }+ I1 h- j. @
- * This does not necessarily have to be a memcpy, you can also preallocate5 B; }: N) }2 _, P4 [; ?: I
- * pbufs for a DMA-enabled MAC and after receiving truncate it to the
6 e/ _8 F9 O, E7 l6 | - * actually received size. In this case, ensure the tot_len member of the j8 h+ z5 ]) ? e
- * pbuf is the sum of the chained pbuf len members., n% i+ ]0 F& J4 _
- */
& a5 R2 s' M6 Y1 [ {* o. D - //read data into(q->payload, q->len);$ O+ w5 w7 V' a" @0 e
- memcpy(q->payload, bufptr, q->len); // 复制数据包内容4 X; [) E# }3 k+ j! ?$ U. I
- bufptr += q->len; // 指针前移3 f7 R4 v$ f7 u, {- o
- }
6 @' X7 ?+ L+ s8 A* p- x - //acknowledge that packet has been read(); // 无需确认
/ ]) @: _2 a2 k. ^ - 4 y% U; E( S# u5 ]
- MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
6 m5 h J2 w0 M! e3 L8 g - if (((u8_t*)p->payload)[0] & 1) {
8 c( U) h. C! M1 D - /* broadcast or multicast packet*/
( @4 W- q4 n- x5 L: @) t/ s - MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);+ Q: ]; [* X4 @/ x! Y! ] }. H
- } else {
0 V$ z/ U0 m/ B2 a - /* unicast packet*/
N0 P5 m4 \. d. @4 r0 o - MIB2_STATS_NETIF_INC(netif, ifinucastpkts);+ g9 Y2 L5 E7 c8 Q, t" t" [
- }5 x. W+ v' G( Z# L4 z- m9 M4 u% I
- #if ETH_PAD_SIZE
8 m2 r+ {3 L$ ?, ]/ t; b6 A - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */! `, g% B' J# N% k9 S* W: Q
- #endif
" ~7 M0 M; Z+ W* ^ A6 i0 e( d* E
$ r' K& A) B, p- LINK_STATS_INC(link.recv);- q- _0 b/ I) k U
- } else {$ N2 {) H+ M: `, C5 i- d# ]7 v5 q
- //drop packet(); // 注释掉此行
7 C& @4 ]+ y i8 M3 C+ ^ - LINK_STATS_INC(link.memerr);( T9 z2 g4 v, @4 ~, R$ U* G
- LINK_STATS_INC(link.drop);
4 H: A+ [( S/ w+ W. C0 f4 q - MIB2_STATS_NETIF_INC(netif, ifindiscards);
9 I! @6 i. p4 S: f! d7 h: G8 E - }3 S3 J p1 V5 V! H7 u! h4 S0 _
+ ?' D( v2 F2 m* i$ X- return p;
z9 q/ h1 @5 @* r - }
; C8 ?- t. H. A
" ?5 S. b! `: {1 e; k. S/ D- /**" f N/ R7 {( G( T2 L
- * This function should be called when a packet is ready to be read
( G, }, d1 N( n# e. \ - * from the interface. It uses the function low_level_input() that
* J: A) m9 l! a5 E8 q - * should handle the actual reception of bytes from the network* A* k0 p+ N7 Z% p7 J
- * interface. Then the type of the received packet is determined and
& c: H0 `0 N |7 } - * the appropriate input function is called.9 v! L6 f/ }2 s) a( v
- *0 J/ }8 L9 }0 U8 u# V. e* J& S! U
- * @param netif the lwip network interface structure for this ethernetif# V9 S6 g/ n: X/ {$ Q
- */. Z: s1 j6 h' J5 P9 t1 s. u8 M
- // 必须去掉static3 {, X7 \3 n+ M0 a
- /*static */void& m& P& {& V$ Q1 V
- ethernetif_input(struct netif *netif)
! q' r$ ^% y: h7 F0 I4 J& q) \ - {
( @- j* I( A& F% ?5 [ G - struct ethernetif *ethernetif;
. K# a" } F5 s0 M2 S - struct eth_hdr *ethhdr;3 p+ P- W2 T9 G! P# s2 t2 d
- struct pbuf *p;; [% Q0 f9 @# n# H1 \# t# `
6 h$ j; |2 f6 F- u+ P- ethernetif = netif->state;- P1 W$ f4 @1 J& c! _
/ v. s, Y; _( f3 H1 z5 {- Y5 }' n- /* move received packet into a new pbuf */
% j3 V$ @: D$ _# N+ @" P8 ]2 q4 o0 D( h$ ~ - p = low_level_input(netif);
( J+ j2 c/ |: F) M# d, |; x - /* if no packet could be read, silently ignore this */
' F& q* b3 f7 \. u - if (p != NULL) {
+ h# r/ ?0 ]/ G - /* pass all packets to ethernet_input, which decides what packets it supports */
* S7 T4 P( \! X; z - if (netif->input(p, netif) != ERR_OK) {' W2 h. ~7 U4 d
- LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
& x- J5 E% f) R# Y& t# g - pbuf_free(p);) L5 E; X& T1 }- l- G! F4 g
- p = NULL;+ V+ ^+ q( K& N2 K* s
- }5 e# z$ d1 m& t& j4 M6 Z
- }
8 Q$ O. J% ~" z/ e* n - }
7 [4 a/ T; c% X1 n
' {0 u1 N: @8 ^7 Z- /**' h( A/ K n! P5 k2 f& C
- * Should be called at the beginning of the program to set up the6 u- S( s# d$ T' g* p, ?
- * network interface. It calls the function low_level_init() to do the% U- Z) x& q1 Q5 M' Q( J& ]5 t8 ~
- * actual setup of the hardware.: a7 C; r8 {# m4 ~, h% m+ n
- *
) J: C& r; i3 [. P% {$ e - * This function should be passed as a parameter to netif_add().
5 A/ C, s6 X# W2 e - *2 _$ Z. Z$ O0 _: h
- * @param netif the lwip network interface structure for this ethernetif" G. r+ Z8 M+ e, C( G; Q& Q) t. X
- * @return ERR_OK if the loopif is initialized5 q1 D7 r. T( G, `
- * ERR_MEM if private data couldn't be allocated A$ o& Y% f; U9 i8 } ]8 `+ N
- * any other err_t on error
& {6 t0 ?" A- c7 f - */5 C! f' ]; l. Z5 c6 O3 s, d
- err_t
- V7 O, \$ s$ d/ { f2 C - ethernetif_init(struct netif *netif)
9 v( z: `- s- y6 D$ Z - {$ Q- ^, z% H+ r6 V- q6 X/ ^ X
- struct ethernetif *ethernetif;. D; P3 H( _* s. ^+ o; G: S
- ) ]- l5 k7 L% }9 R& R0 G1 ^: T
- LWIP_ASSERT("netif != NULL", (netif != NULL));/ p( s4 u# i x) g8 u+ ]: r9 Z
- 7 b# O% R- n* ~# ]3 C
- ethernetif = mem_malloc(sizeof(struct ethernetif));- w- m, {2 C B B( j, S- T: x7 ^) [
- if (ethernetif == NULL) {
) c( ?* m1 o' c3 @ - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
8 _$ w" e% x( t7 @$ B+ L/ R6 _ - return ERR_MEM;6 |9 ^( d; v2 S: q" l
- }
3 y# i8 B, [6 e
7 {' l, h. G5 O) J- G- #if LWIP_NETIF_HOSTNAME6 h3 L @; W" g# R$ m
- /* Initialize interface hostname */
9 u5 A* E z) `! G0 K% e - netif->hostname = "lwip";
$ V. T2 N) T; m! Q V* Q - #endif /* LWIP_NETIF_HOSTNAME */9 U% N/ [' C& e' S. D* [) G# m9 [
- " C8 `% y! g1 U7 c7 Q$ L4 G# }
- /*6 d$ ^4 w K& ^5 i4 G9 \2 R4 x
- * Initialize the snmp variables and counters inside the struct netif.
% e* _6 L* p' G; G - * The last argument should be replaced with your link speed, in units
( W5 Q7 \9 ] N0 Q - * of bits per second.
* u& `3 |6 p1 r+ K - */2 e% l- W9 Q ~& i
- MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
M+ k: _4 o2 `$ j
3 U8 A/ [9 R. Y' L3 h" E' n- netif->state = ethernetif;1 V- f p& T$ j
- netif->name[0] = IFNAME0;4 G/ E6 L7 n# W' W9 \. W+ J
- netif->name[1] = IFNAME1;
6 l5 t5 z2 L' z: x' h4 S3 H: { - /* We directly use etharp_output() here to save a function call.
$ s3 f5 A; q) P! c$ O - * You can instead declare your own function an call etharp_output()
" A& H. \$ S4 ?/ d- {1 v/ I - * from it if you have to do some checks before sending (e.g. if link. o& Y" N9 U6 @3 x
- * is available...) */3 {& E8 K' R2 g: S2 V$ P0 V* N `
- netif->output = etharp_output;
0 J- I0 k4 ~" W! ]! N/ D - #if LWIP_IPV6% S& q3 q8 z/ F9 F: K
- netif->output_ip6 = ethip6_output;/ {. {* S1 O" {' P# p
- #endif /* LWIP_IPV6 */1 p/ u4 T$ f4 f* [
- netif->linkoutput = low_level_output;8 C8 \3 h$ m- O- v
9 ^4 g9 U' r* B* @) n8 G6 b4 W- ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);" l+ n8 {4 s7 ?4 k+ V/ h
- 3 }% P0 j/ N+ B
- /* initialize the hardware */, e3 k4 x3 V8 C" q* C0 e# t8 ?
- low_level_init(netif);
Q: t2 L$ z, H7 r% H# R - ( f$ A, \( x/ H% o# i% G! ^
- return ERR_OK;
" K7 K5 K2 i) M7 E: X - }3 Y( y1 r5 I& n! x% q s( K
- ^' d* |: B; F+ y- #endif /* 0 */( o' F$ ~+ P. y9 V) G
复制代码 7 [+ t6 J- J2 w0 ^% i7 \
在项目属性中,设置Include Paths为:.;.\lwip\include
6 T+ s2 K1 L8 S: k' i其中点表示工程根目录。4 e1 E) ?! A. s0 {
1 V3 T* y! a; O4 e" x! _: m2 s4 {# ]
另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。- x+ W J( T- z: l: M; T
( z, s6 c! v- A J编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。! T* B: S3 h7 v6 n! c
电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。
: A+ K! y: C- M3 P配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。
4 g. ~4 g! f5 x" j) k. i. J, ` |
多谢分享