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

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

; `; {9 B1 o7 o w$ E另外,为了在程序中使用printf函数,Target选项卡下的Use MicroLIB复选框也要勾选上。
& _, b% d l! @4 l' d% K" n- i
- G* w0 y4 J& X7 m编译并下载程序,电脑和WiFi模块要连同一个WiFi热点。3 h' J2 c, Q3 h4 f+ l
电脑的IP地址要手动配置。IP地址为192.168.43.71(最后一个数随便),子网掩码为255.255.255.0,网关为192.168.43.1。 N8 A3 z& t" x! c* f7 x. q$ ~. t
配置完成后,即可用电脑上的浏览器访问开发板上面的HTTP服务器。7 |% C. n, m+ p' Q; g
 |
$ P& W7 n G$ g3 e$ A/ k4 s
多谢分享