一直以来都想搞个寄存器配置版本的ETH,最近时间充裕,花了近2周,昨天终于实现了以太网的连接,上图 # Y; q9 D" C8 e/ l# \) d2 X& Q1 t
" P, r. ~; o- }- n; f' ]9 S/ F1 h7 T* t8 j
8 n6 Y8 {. }1 E6 h& @6 d
% J5 A8 \. P- m* W; T' L! I 这是打印结果" p: }- D; {* b1 U0 X; `9 |) Z
下面详细说明一下
1 b( ~* _: D3 x. F) m 首先实现lan8742的驱动2 ~! Z' T) d8 x
- /* Ethernet pins configuration ************************************************/
% r i$ N; S$ F ~* @+ a9 q% Y: F - /*
) W/ `3 h- |+ H) v1 J - RMII_REF_CLK ----------------------> PA1
* z& s" G% l p* u( I6 c' v% C - RMII_MDIO -------------------------> PA23 Q& ]1 q/ K8 \& `' N; K
- RMII_MDC --------------------------> PC1
8 n( B2 k( h( A& l% a3 ~9 U- y - RMII_MII_CRS_DV -------------------> PA7) W% V# X& _7 ?# I6 E1 E* _: F! W
- RMII_MII_RXD0 ---------------------> PC4% g6 {% W$ M6 f8 l+ c- e! Q
- RMII_MII_RXD1 ---------------------> PC5% X9 f3 T! W+ u h- Z
- RMII_MII_RXER ---------------------> PG2/PD5, o) P0 N9 l7 G2 y
- RMII_MII_TX_EN --------------------> PG11) `4 @' P2 S2 u6 i0 M6 H
- RMII_MII_TXD0 ---------------------> PG138 I! H, u. ~3 t1 @! o5 Z7 q
- RMII_MII_TXD1 ---------------------> PG14
$ i& Z: t. M; k3 H - */* }+ b$ d2 i5 G+ A1 y
- *(uint32_t *)0x40023830 |= 0x45; //使能PORTA\C\G时钟 0x4d,ACDG
9 b2 d' [) Z7 G& d8 N - *(uint32_t *)0x40023830 |= 0xf000000; //使能ETH,TX,RX,MAC时钟 9 c% h1 \' M" t* @
- GPIO_Set(GPIOA,PIN1|PIN2|PIN7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE); //PB3,PB4设置
; D% f; `- D, x. W- I: {: ^! X - GPIO_AF_Set(GPIOA,1,11); //PA1,AF112 x& g, S* @* Q* o' C, E2 ]
- GPIO_AF_Set(GPIOA,2,11); //PA2,AF11! b8 }3 [ [! I6 _- q: A" m4 E
- GPIO_AF_Set(GPIOA,7,11); //PA7,AF11
# E- s5 n5 _1 C5 _% W) r* n - GPIO_Set(GPIOC,PIN1|PIN4|PIN5,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE); //PB3,PB4设置5 T5 A! Z+ K4 n0 M* @
- GPIO_AF_Set(GPIOC,1,11); //PC1,AF119 n% e8 e5 Q$ ]- R/ C6 ?# y
- GPIO_AF_Set(GPIOC,4,11); //PC4,AF119 s$ D% O, O# |! M3 J
- GPIO_AF_Set(GPIOC,5,11); //PC5,AF11. w, D! L$ k: `& t/ u \. N) P4 F
- GPIO_Set(GPIOD,PIN5,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE); //PB3,PB4设置
- I- T9 | I) K& O. Q5 ~ - GPIO_AF_Set(GPIOD,5,11); //PD5,AF11
2 `9 g' B& K/ L& U- Y9 C1 O - GPIO_Set(GPIOG,PIN2|PIN11|PIN13|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE); //PB3,PB4设置
, O7 q* t! a) t$ @2 w - GPIO_AF_Set(GPIOG,2,11); //PG2,AF11
- t+ N% | U1 U/ b - GPIO_AF_Set(GPIOG,11,11); //PG11,AF110 [# f R- K1 ?5 z* o g- g. ?
- GPIO_AF_Set(GPIOG,13,11); //PG13,AF11, _4 f4 |. W0 e* N j: S( d3 B3 o' N
- GPIO_AF_Set(GPIOG,14,11); //PG14,AF11; z: B( T) w. t( X( L
9 \8 {" z! ~( T' a: d; T8 c7 D- MY_NVIC_Init(0,0,ETH_IRQn,2); //配置ETH中的分组
复制代码 然后实现LAN8742寄存器的配置4 m& ?+ F1 q' ?* Z! F+ r
- *(uint32_t *)0x40023830 |= 0x400000;6 \# z/ O; N1 F3 D. b U
- RCC->AHB1RSTR |= 0x02000000;* n) ?3 {% z: V& y7 [- D$ d9 R! ]0 o
- /* Enable SYSCFG Clock */
9 {' R9 W! d" C { - *(uint32_t *)0x40023844 |= 0x4000;/ S3 {) n' O3 v$ K$ l! V
- SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL);
! N! N+ ~( ]; M) e% r - SYSCFG->PMC |= 0x800000;//RMII1 {" r6 Z8 p5 T1 N! Z% S: s) Q/ C
- RCC->AHB1RSTR &= ~ 0x02000000;
3 B- F3 i: O" ^- M% n" d: B - ETH->DMABMR |= 0x1; //software reset
+ M8 D, K- q, l& g* h - while (ETH->DMABMR & ETH_DMABMR_SR); 6 N; p" R* }. V
, f+ a/ h# E8 E- /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */* ^! q+ [$ _1 c( l: i" J
- ETH->MACMIIAR = (uint32_t)(1<<4);
; ~& q. W- i; x( I; ^( w6 \ - write_PHY(PHY_BCR, PHY_RESET);( F: q3 x! d3 Q }( p% d
- /* 等待复位完成 */& g" h5 c$ r/ j: t9 w
- for (tout = 0; tout < 0x10000; tout++)1 Z- U% t) v4 J2 w
- {$ D/ K, V: ~' X1 C( C
- read_PHY (PHY_BSR,®v);
8 N6 f- c @0 S. y - if (!(regv & PHY_LINKED_STATUS))4 t1 W1 F- E4 E" R
- {8 M! f {" N7 d, x3 T" ]
- /* 复位完成 */
4 }% D" x; g9 ]+ n2 ?; v - printf("2. Reset Complete\r\n");5 I5 O- a: L3 `/ n! F
- break;
) Y# N% {, A2 W5 c - }
^3 z) j4 T F' f - }, W% c! D( C3 Z6 D4 O, L. u, O
- write_PHY(PHY_BCR, PHY_AUTONEGOTIATION);/ ?0 W0 i7 q. \" j% P+ `4 ~
- for (tout = 0; tout < 0x10000; tout++) N2 Q0 O- t/ {
- {
7 [& [; i; q( N& l3 |" d7 F5 i - read_PHY (PHY_BSR,®v);8 g. R7 ^! w8 T$ |
- if (!(regv & PHY_AUTONEGO_COMPLETE))
/ V- `; y2 |6 d - {& f6 O8 H7 `! A1 ~$ n5 k0 r6 K
- /* 复位完成 */
; Z) u, D% v7 x - printf("3. Auto-Negotiation Complete\r\n");2 R3 ]9 B( u+ h6 a6 M
- break;
. l( o$ r ^/ e. A# ] - }
1 O2 r* m: T9 ~* s& M - }* A. n- [% G5 o
- for (tout = 0; tout < 0x1000; tout++);
. V! W$ d9 ?( s3 q" |6 o7 }, G - read_PHY (PHY_SR,®v);# [8 A: R5 E+ ?
- printf("%x\r\n",regv);
3 j- Q4 H Q' o* a - /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
; F( W: L \* d0 c+ a - if((regv & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
) [& C) n1 d2 V e/ z& f5 @ - {
5 t4 E- N4 H: s: j ]/ E H - /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
! M+ r, B c# k: D/ h2 }- b - printf("4. Full-duplex connection\r\n");
9 A; Z/ b, R1 q8 |9 e- l9 M - phyreg |= ETH_MODE_FULLDUPLEX;6 T6 n. m6 l/ W" F6 a- N4 e: e9 ^
- }
2 ^! G0 e" D) g% P" m; z( k' O; m0 u. V - else
% z; ]6 ?, A. X k# u7 _+ n5 C - {4 x: z% O( @& q. S1 n3 M
- /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */8 I/ B- B8 p8 D1 O9 x
- printf("4. half-duplex connection\r\n"); 8 B; ~3 J" W8 D: P* @- R* k X
- phyreg |= ETH_MODE_HALFDUPLEX; 9 g I$ p; L. X" I9 }% |
- }
* }1 n( C! @: \7 X& s/ l8 @ - if((regv & PHY_SPEED_STATUS) != (uint32_t)RESET)
& l- K) O6 a4 b0 \8 ^ - {
3 V; N2 ^1 v O - /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
# g% C" Y4 A* q5 g - printf("5. 10Mbps Mode\r\n");
& z" l4 ?1 p0 t" G# G( M0 N( M% P - phyreg |= ETH_SPEED_10M;1 m P! w1 l/ [9 H) _' e" \
- }
) e4 w; K' P! Y" c - else
4 [+ O5 Y2 z+ _0 @/ \ - {; z3 D3 j+ i) R
- /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */2 G& B: c9 l3 r" s
- printf("5. 100Mbps Mode\r\n"); : P( m+ J# `$ C& c. L
- phyreg |= ETH_SPEED_100M; G& ], K& F6 ^1 A0 [' ]
- }( U- Z9 k! D, J$ V* N0 Z
- - U7 G1 F7 ?) ?' j6 b3 K' G' l
- /* Config MAC and DMA */% {% b/ D* _# T9 e) s0 h0 N3 ^+ d
- ETH_MACDMAConfig(heth, phyreg);
复制代码 下面是实现读写的函数. D' I3 |7 A. q. K
- void write_PHY (uint32_t PhyReg, uint16_t RegValue)
0 m5 ]) G' g v% [ - {9 H j# f* `) O1 K
- uint32_t tout;6 d* O) s I5 y5 P
- uint32_t tmpreg = 0;8 C3 m1 X: U, U9 N" Y
; Y7 H7 N+ z. _! `' Z% n- ETH->MACMIIDR = (uint16_t)RegValue;
- S4 A6 l8 F0 C7 u' N: j x" a4 z
) H1 w; a$ h1 ^) Q' z0 U E
& P2 a" [* w- m5 H$ C- /* Get the ETHERNET MACMIIAR value */; c# S9 t" @& f/ Q+ ]
- tmpreg = ETH->MACMIIAR;
# A4 d* S; n& _ - ' X1 A6 S$ B( B( \0 }" i
- /* Keep only the CSR Clock Range CR[2:0] bits value */
: L. x) v% J3 o% c - tmpreg &= ~ETH_MACMIIAR_CR_MASK;; W& }- C( W# U, p' f6 `/ Q' E
- 9 z& D& e( f3 {4 O a
- /* Prepare the MII register address value */: P5 E% [7 {' k' O, ?
- tmpreg |=(((uint32_t)(LAN8742A_PHY_ADDRESS << 11)) & ETH_MACMIIAR_PA); /* Set the PHY device address */
! k" h" A. T% b& ?4 q - tmpreg |=(((uint32_t)PhyReg<<6) & ETH_MACMIIAR_MR); /* Set the PHY register address */
/ ^1 C [% q; a) j( f0 N0 t# O# R- S - tmpreg |= ETH_MACMIIAR_MW; /* Set the write mode */
" G% a9 u. s; X) y7 ^& i, e - tmpreg |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */' F% n+ U: B! E: t8 ?
- 9 j9 @( r. ^- h5 b- I& h
- /* Write the result value into the MII Address register */4 k* D5 L( E. ~
- ETH->MACMIIAR = tmpreg;0 x% @3 r1 o4 \0 ^
- /* 等待操作完成,即等待MMAR_MB位被清零 */: X; w! [0 _& I4 s
- tout = 0;
5 x: i7 g3 S- @* P; `0 G - for (tout = 0; tout < MII_WR_TOUT; tout++) - V6 {! e4 k3 ^+ e# `6 x1 s
- {
/ b. m& B- z/ \- Q/ g - if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0)
% f+ ]- w) V, S h" ]" F4 c- O - {, s* M8 ^. ? @9 q4 K
- break;1 Y0 V# j8 B8 g( Y. q
- }6 o. p# G( Y* z3 y5 [" h0 x8 W- J
- }# U7 H- \1 G/ @) k; B; A$ R0 u0 V
- }
* k' T6 X" _# Q) Y `0 g - 5 o0 F& j! X- [6 S1 _
- void read_PHY (uint32_t PhyReg,uint32_t *RegValue)
$ [0 q d5 P W' s- h, U7 I! {+ K3 d - {) r; z& Q9 E5 ^
- uint32_t tout;
% M# N% n& @$ b4 `% y - uint32_t tmpreg = 0; ; l1 g* a/ o- q
) g- d d: a" ?# A- tmpreg = ETH->MACMIIAR;: G! F* Y& ]' l' f3 I" T5 t
- 2 F0 G9 L v8 c, W1 e' w
- /* Keep only the CSR Clock Range CR[2:0] bits value */
3 u8 Y5 n( t* s' W, D4 f/ m$ f) s/ I - tmpreg &= ~ETH_MACMIIAR_CR_MASK;
# b* ` e/ I; @9 a5 k - 4 C( F) q7 p; z
- /* Prepare the MII address register value */0 B7 s; Y+ M7 K; |) r
- tmpreg |=(((uint32_t)(LAN8742A_PHY_ADDRESS << 11)) & ETH_MACMIIAR_PA); /* Set the PHY device address *// Y. s7 Z3 _6 b! F9 K2 V0 ]! w
- tmpreg |=(((uint32_t)PhyReg<<6) & ETH_MACMIIAR_MR); /* Set the PHY register address */
; e: n( `2 `6 |4 }; h1 |1 @ - tmpreg &= ~ETH_MACMIIAR_MW; /* Set the read mode */7 _% }% j5 F" C/ W
- tmpreg |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
; M( V1 K" Q( R: H2 { -
+ @; {5 n3 ~) C4 A% m! n% i" b - /* Write the result value into the MII Address register */5 C$ v2 R7 d( i* l/ W7 Y2 a
- ETH->MACMIIAR = tmpreg;
% D( i+ ]$ F H& X$ o
1 D$ C" ]; T5 Y, S- /* 等待操作完成,即等待MMAR_MB位被清零 */+ C# A" W7 B0 a# d
- tout = 0;
6 \# R+ j3 l7 R0 I k5 U) D - for (tout = 0; tout < MII_RD_TOUT; tout++)
0 ]) i0 z+ ~8 S - { j ?' K% C6 t( j6 O
- if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0)
8 I* H4 c9 H; g7 N$ K! g7 } - {5 B8 R5 A+ |& q+ \! x' M# M
- break;8 A% ~$ E7 u* d4 r3 {
- }9 d* L1 ~$ [% r2 E/ l
- }
$ H' C1 \! _2 w8 B+ E8 z9 ` - /* Get MACMIIDR value */# K6 h. s, A' y. F
- *RegValue = (uint16_t)(ETH->MACMIIDR);
1 X: R" G7 e$ r2 L* ]% V - /* 从 PHY 中读取16bit的数据值 */6 I$ a( F/ n# d: B0 Y/ z- P+ k
- }
复制代码 保存可以正常运行,并且连上lan8742芯片
( g$ i) G) c4 t- D" t
: i3 C- N( E+ R4 V# b* v' T# A9 Y
' w( B. r0 {2 F3 P- Z下面开始移植lwp141,步骤就不说了,网上有 ( v" G: J) H8 Q8 |* a
! Y: p( }* D0 x O. h- x5 \
r/ |* v8 }/ N
- ` J- @! m( [. _6 f) j' d7 A9 } V& N5 X
直接给出代码; X2 U- \" T* }9 i
- static void low_level_init(struct netif *netif)3 Q9 W8 h) w! D* Q% P% L5 U" ]
- {6 R* E- s% E* p, Q2 v/ U
- uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };% ?- }7 {# `& \
-
! f- V2 B, d1 B/ X7 P8 q5 A - EthHandle.Instance = ETH;
U! B+ H5 y$ z% }9 F5 j! a3 J+ N - EthHandle.Init.MACAddr = macaddress;
2 D# S( g( F# z& w" x! L7 K. J! X ] - EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
M& H9 s! m) j' c - EthHandle.Init.Speed = ETH_SPEED_100M;
5 P0 |8 O+ b4 b - EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;, ]4 `. W$ {1 R4 g( }+ R
- EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;2 T( R0 t5 d. @( [1 S+ Y$ r& s
- EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;+ T1 L9 j ]1 u1 `% w
- EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;* G) c! z2 V+ O+ X0 C4 K8 [% K
- EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS;) q1 r8 z; N8 a+ L' U
- /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
) p) b9 N3 P5 }, J+ T- k+ k: P1 L - lan8742_init(&EthHandle);" X, Q/ V" o+ _ F" D6 \2 X
- /* Initialize Tx Descriptors list: Chain Mode */+ f7 n- Z. F) U# E' t( g Y" s
- HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
8 x# b/ G; @, U4 V7 H -
! H% a0 j6 @+ n" L. F - /* Initialize Rx Descriptors list: Chain Mode */# b1 q6 S# c& [* u5 [+ o
- HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
; H6 `. } ~/ `0 p0 E) t3 U& w - ( u: L' A1 {# F+ Z) K
- /* Set netif link flag */2 z4 }. q. T/ R5 l; z! m- ^2 {- x
- netif->flags |= NETIF_FLAG_LINK_UP;, ]4 z& _# X+ R
- /* set netif MAC hardware address length */
4 ?/ d1 `1 h' L- o- I7 C - netif->hwaddr_len = ETHARP_HWADDR_LEN;5 D8 n! O' V! h+ {
. Q) R& F# o! k' ]* D A- /* set netif MAC hardware address */! h0 U M: _- h) S Z; _
- netif->hwaddr[0] = MAC_ADDR0;
2 `: o5 B, _) j" R( P - netif->hwaddr[1] = MAC_ADDR1;
6 B! U+ X9 w, m$ `( T - netif->hwaddr[2] = MAC_ADDR2;3 j2 G l8 L. i2 n2 o
- netif->hwaddr[3] = MAC_ADDR3;( i" m' l4 G, W; {' i- z+ I( G' f
- netif->hwaddr[4] = MAC_ADDR4;6 E% M f+ y6 X* y# N4 _
- netif->hwaddr[5] = MAC_ADDR5;& R2 z/ i0 C8 l+ x+ Z. [+ o
- # D! j8 { g/ W2 I) v/ h
- /* set netif maximum transfer unit */
, \3 l. h* F& ^ - netif->mtu = 1500;" l+ k& j; P; u
- ' u1 S1 L" E0 o) x" _
- /* Accept broadcast address and ARP traffic */" C& x4 S0 N# D, i
- netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
) t9 t3 F1 z# w8 H$ a - 9 d8 S/ ] C# }' V/ O2 N/ I3 p( t
- }0 b# D% _- d) B6 M n
- err_t low_level_output(struct netif *netif, struct pbuf *p). j) { Z, h9 u0 j# ^9 C% Q5 \
- {$ k- A4 G" x+ Y( b
- err_t errval;
* H# N" V: w: U) V' I1 z - struct pbuf *q;2 b2 r# z8 i0 R5 U
- uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
# D) d6 B3 h3 `6 G' w - __IO ETH_DMADescTypeDef *DmaTxDesc;
$ b/ x3 F- I- W+ O' Y3 n - uint32_t framelength = 0;; b; c& q2 ^$ P# S+ @+ v# Y
- uint32_t bufferoffset = 0;& U5 b* l% d8 e# o
- uint32_t byteslefttocopy = 0;5 ]$ ]. Y' p: i9 g- B( Y
- uint32_t payloadoffset = 0;
$ o+ m9 W* C/ r$ j
3 g Z$ b( t: X$ W9 K- DmaTxDesc = EthHandle.TxDesc;5 Q8 r; l* o' y) y) b- T3 D1 c
- bufferoffset = 0;
: y; S _5 M+ R* c& i - & R! Q2 x, e, V% f1 I
- /* copy frame from pbufs to driver buffers */
" d/ A& q' K/ t- Y" u6 ~$ G - for(q = p; q != NULL; q = q->next)9 _* j3 t$ P3 P2 ~$ @, s
- {
3 S/ e! E9 {6 u, A4 ]- B4 ^, W6 } - /* Is this buffer available? If not, goto error */
+ [# K5 g- g; N$ m0 c! T - if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)3 `+ b% g& X$ q9 K
- {# h8 e; k; |8 z- L5 E' S
- errval = ERR_USE;9 y [; Q9 G9 f" j
- goto error;+ F7 R: `% P8 E
- }
7 L" p3 i" O$ l+ B5 n x5 S9 @6 ] -
# v) J/ a9 f. r6 i - /* Get bytes in current lwIP buffer */3 i( S3 n* ?" N" J; d1 k
- byteslefttocopy = q->len;
% B3 O- o0 p3 g9 [, p - payloadoffset = 0;
! y; v3 t& f- [3 M; q3 G3 K4 g3 _ -
: v' L1 _/ [; u3 J8 E5 `3 X$ L; F - /* Check if the length of data to copy is bigger than Tx buffer size*/( D. Y, Q: P' n5 Q( R0 T9 i
- while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ), t" z" ~; f- `1 u+ }3 T' |5 }
- {
7 B+ S# w4 E+ U& b* Y - /* Copy data to Tx buffer*/6 e7 c: w- r3 Y3 Y" u
- memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );" ?' X+ |% C4 v
-
2 `1 \/ n5 ~3 Q- q5 q; o - /* Point to next descriptor */3 G C4 z$ Q! `7 d/ G5 U, D0 b# x, F' c. G
- DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);/ E. G7 m! h+ ~' g. N9 T
- : N, B2 C( }/ k9 w, p# e2 d
- /* Check if the buffer is available */
3 U2 Z" q- |4 D+ e. C. } - if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)3 I m8 A5 N. Y U# \
- {
! Y& p' E* u u$ H - errval = ERR_USE;
0 l8 l5 r# `: T% a: Y - goto error;
% U& t* H2 [6 _) @" H) \ - }* n8 q$ j9 m1 y+ `1 m" \7 f& A
-
& x: Z1 X- Q' W6 p - buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
4 S; b5 o$ ?& K9 z -
. \5 R. I3 w* ~+ v - byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
' e9 @5 U. Z# h8 ~9 ~* | - payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
! m* D" F8 {) `3 n% ~/ W - framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);9 u, D6 W, {2 [8 V4 h+ q2 O. ~1 Q
- bufferoffset = 0;
4 M' p( R' K" G3 ^$ m - }
( l p% I5 w! m/ g3 ` -
( h, ?# ~# E3 v3 @8 S4 M5 p - /* Copy the remaining bytes */- H# }8 E7 ]8 j. J( r+ S. J
- memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy );$ @8 f8 i' O' J2 u9 Y6 o
- bufferoffset = bufferoffset + byteslefttocopy;
. M) q6 X( M9 L. j# t - framelength = framelength + byteslefttocopy;3 l/ q4 E- g4 z. T5 R
- }
; p( S1 S. Y& v- V1 W2 } - ; W6 u7 a( t( t( s$ d
- /* Clean and Invalidate data cache */
, l" t/ ~6 _; v' ~ - SCB_CleanInvalidateDCache (); + ?, b, \. }2 L+ [, S
- /* Prepare transmit descriptors to give to DMA */ 2 b+ U# G* k( B) G
- HAL_ETH_TransmitFrame(&EthHandle, framelength);# B' H/ _; A. y: }3 _6 d
-
& O+ l+ m% L! }0 e4 {0 e- t - errval = ERR_OK;5 _ T6 h& ?: b/ s/ {* \$ @
-
& g8 x! n. x/ u# I# R9 b( S1 S - error:9 Z9 \4 L3 w( H5 W- |8 o
-
) \$ }3 @. l4 K' P$ N! j - /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */5 ^. v, R* P( c L9 ~
- if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
4 }: H( w9 h0 f3 H% R - {
, c, n' G' t+ O% D$ d6 D* u - /* Clear TUS ETHERNET DMA flag */
7 j/ j/ l7 V O4 I9 X6 a0 w/ b1 m - EthHandle.Instance->DMASR = ETH_DMASR_TUS;+ u- f7 D9 j) C
- + i0 E6 W7 j- y1 F/ s Q. @+ ^; ~
- /* Resume DMA transmission*/* b1 Q% s, j) @ D* F* ]/ T
- EthHandle.Instance->DMATPDR = 0;2 ~5 r( L: a3 P1 g$ B0 `! N6 J
- }! \8 I7 R( N R7 {2 G6 Y( g" F
- return errval;
+ {" L6 W. R. q' l+ o- ?) J - }
, c0 \ k8 e" F" B - * z7 l/ Y/ f. m; Z! b& h
- /**; A. L, U" k: {* u" G1 N/ L' g
- * [url=home.php?mod=space&uid=159083]@brief[/url] Should allocate a pbuf and transfer the bytes of the incoming" {& T; r; Q5 _) |
- * packet from the interface into the pbuf.
. t( ?+ o% y- m. F - *
# u6 v" \5 J9 Y5 o& X q - * @param netif the lwip network interface structure for this ethernetif
; h- c0 a. J H - * [url=home.php?mod=space&uid=784970]@return[/url] a pbuf filled with the received packet (including MAC header)- l* A' l0 Q# A* T9 h
- * NULL on memory error q) B4 V- v* ?% `% {, I6 U( Y
- */6 Y4 I+ V7 X- f9 W3 @, j: e' m' X1 C
- struct pbuf * low_level_input(struct netif *netif)
( T6 O, G8 @$ X3 s% O1 f% H K8 ~$ ` - {- T, ]9 h3 T) T
- struct pbuf *p = NULL, *q = NULL; m& O& M$ B. {: @/ \2 M3 W
- uint16_t len = 0;9 [5 E' K+ P% D* d0 B- e
- uint8_t *buffer;/ i+ D: x/ I# M' Z# V
- __IO ETH_DMADescTypeDef *dmarxdesc;! \4 z8 c5 ?# e- m s
- uint32_t bufferoffset = 0;" Z2 v# [& K2 H
- uint32_t payloadoffset = 0;/ {5 H; u) m' Z6 R; C& j+ I
- uint32_t byteslefttocopy = 0;; [' ?. U0 B+ ~" w6 F
- uint32_t i=0;/ L; e0 Y+ v1 k
-
6 _/ l* |4 b, e0 ]& s0 R - /* get received frame */
# V7 y$ H. x' Q0 c& f - if(ETH_GetReceivedFrame(&EthHandle) != 0)0 Z7 X1 Z% R5 B. `
- return NULL;
3 ^' R2 D' y$ X -
) w) D3 \5 w( @' W7 l - /* Obtain the size of the packet and put it into the "len" variable. */
$ X9 X/ O& L3 A" N, V+ M! H - len = EthHandle.RxFrameInfos.length;
3 e- J2 ^# J' P$ c - buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
! U: [2 k, a) ^2 x8 E9 U -
1 N$ G+ Z/ Q) R( h - if (len > 0)# N H4 K7 s: J% F/ \* ]
- {
- h4 u* T9 L7 n9 s+ M - /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
/ ^0 K' M) [/ v6 M - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);! V# C' h: Q% F: R7 S
- printf("recv is ok\r\n");6 C2 j: y5 e, [: p4 v2 I& H
- }" B H: \6 N' O: H, Q/ u; Z
-
, v5 g D7 u; N7 X - /* Clean and Invalidate data cache */
! A, W; E, h P5 a) y! Z. f5 N* }6 ^ - SCB_CleanInvalidateDCache ();2 X% o8 n. R( e7 X. V H
-
1 v7 g" t) ^2 s - if (p != NULL)3 p% n' s3 g! U# a0 c7 _
- {
, ?2 }3 E& \; J: O4 F2 q' K; f% J - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
5 J" L2 t. ^0 C' o4 D0 `; h! z - bufferoffset = 0;4 m* L/ P% h# ^! s2 `5 t# n
-
( z9 S6 ?: T" _" _! D - for(q = p; q != NULL; q = q->next)
- Y* k7 Z! T. i: z- i8 A3 p/ U; H - {: [3 i6 H% v3 J7 W; X
- byteslefttocopy = q->len;' W7 Y1 l( R2 f/ H. L" r" I
- payloadoffset = 0;
3 ^. h) U1 ]2 ]4 R# E - 5 U- P5 I# ~: n; R7 C2 S, S) Y
- /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */
; f) j5 C/ {' V* E% ]# d - while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
1 p/ ^5 F% `; a4 p; M - {
3 J0 g" R- g# K4 x F |: `/ C6 R) D - /* Copy data to pbuf */! ?8 E Z2 S8 h: S( A
- memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));0 ~- L1 p# G# n
-
0 A3 f7 P/ ^3 J0 i1 G7 T- M5 |, P8 Z - /* Point to next descriptor */0 r3 I6 N! ?, p# T
- dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
4 B7 ~9 ?: {$ ~+ o! L- T - buffer = (uint8_t *)(dmarxdesc->Buffer1Addr);- ~, B4 i9 [; s I( E
-
+ @/ `$ Y$ F: Q4 L1 S - byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
8 c K d( T) w. s3 X - payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
( n: A% K8 q# Q7 [4 K - bufferoffset = 0;
* T% ^7 `" V$ V$ u6 @ - }& o3 a$ @8 r3 N9 N: y2 z) `
- " _0 b$ \$ b$ K* P1 |
- /* Copy remaining data in pbuf */% p5 q# g% x& P9 X4 i7 u
- memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy);
+ A- b# @+ w7 Z( L( z1 n5 l, Q# f, w - bufferoffset = bufferoffset + byteslefttocopy;
& ~2 g7 D/ ^$ b - }2 n3 O8 m* v2 {/ S/ O$ b( R4 P
- }
) h6 N6 D( n# b- O* o - # t$ O( N9 Y2 i" O4 l. t4 n
- /* Release descriptors to DMA */2 h3 D8 o. U% Y: d. S2 ^1 c
- /* Point to first descriptor */
5 ?2 d1 X- L- @6 t& j - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
, F' k6 d/ C1 I1 E9 X/ c - /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
3 E: v& V' Z" b - for (i=0; i< EthHandle.RxFrameInfos.SegCount; i++)
& h' }4 F# ~& K, |# S. C8 F* R [ - {
/ { | x" Q ~! r7 F* o - dmarxdesc->Status |= ETH_DMARXDESC_OWN;
; m" e( j' e6 |5 s4 c' O - dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
$ a9 R# L. S% |; o/ e9 g - }
" T3 l, F& E* o, R+ Z. I2 E+ ? -
/ i( t" ^. W: Y# T - /* Clear Segment_Count */7 \( l$ V) d5 Z0 z5 T/ ?0 c2 F
- EthHandle.RxFrameInfos.SegCount =0;, a( m. n" S; C# f) Q' ^5 D$ O
- 7 C6 q* g8 ]7 W! z8 ^$ [
- /* When Rx Buffer unavailable flag is set: clear it and resume reception */
) ]/ }( @( M4 a# z - if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)
6 z$ Z' G4 U( N+ `9 M! H, @ - {
, L( n- [' @' v0 M - /* Clear RBUS ETHERNET DMA flag */
6 D4 g* ?! i4 C - EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
* U+ |! L2 i1 {9 Q4 g8 z) H - /* Resume DMA reception */1 h, e7 }! q% Y
- EthHandle.Instance->DMARPDR = 0;+ {" |& T$ D8 K
- }! u; E4 s- W3 c" ^9 z+ S: {
- return p;, }5 {: H; k9 U+ C1 b; f. D9 H3 ?
- }
2 Q% \" |0 V( @ - void ethernetif_input( void const * argument )5 z3 ]3 a% e( K8 f" @$ ^. [" V5 ~* x
- {/ Z" D; Z- Y6 N _
- struct pbuf *p;% ^0 `; P. ^* G5 @+ U( g
- struct netif *netif = (struct netif *) argument;
4 p6 Z3 [& Q9 j. W# ~$ A3 H0 j0 Z8 R3 Q4 ] -
1 e8 g- S& n+ o; q9 J/ S0 |/ Y -
/ |* y+ a q7 G+ }8 z% B# k0 A" Q. R -
& p& h: @- `2 e3 } -
. M- M7 p, e) \& D/ e8 z - p = low_level_input( netif );4 u1 {( L: S; \* l' s0 ?8 m( `
- if (p != NULL)
- ~% e/ f6 D0 q% \1 D7 e3 v - {/ i: r; j$ B$ [) W% g5 y4 @
- if (netif->input( p, netif) != ERR_OK )
! W, L/ }5 n( F6 }, C - {
! k+ s5 P1 {: V. @ - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));( C) B; F. m9 m' c4 `
- pbuf_free(p);, P, K: j ~( U. b& t* b7 F
- }6 k4 Q" M. ], O9 U. s7 Q+ ]* ?
- }# J1 l. {. s5 n
- # ~, L2 p5 J0 G& z! m
- $ L2 {, ^) I" Z$ x8 o" i
- }1 S5 E, M$ K2 T- t: t/ W' R' b
- err_t ethernetif_init(struct netif *netif)
# N& Y; I$ e% b( a. h - {' S' D; i3 d% v7 F' q
- LWIP_ASSERT("netif != NULL", (netif != NULL));6 L& R! H+ I3 L' A
N" r1 O; I7 M" U& H- #if LWIP_NETIF_HOSTNAME$ L+ P0 h6 h' `5 Z( r
- /* Initialize interface hostname */' A# @ x& p u) W+ ?! N6 A
- netif->hostname = "lwip";
6 X7 L. u8 `1 A% M3 } - #endif /* LWIP_NETIF_HOSTNAME */9 A- Q& O r) W4 ?1 E- o
- ) ~# N1 g) D8 }
- netif->name[0] = IFNAME0;
& H, |' I3 `0 o7 B) [& O9 A - netif->name[1] = IFNAME1;
: ?. ^+ y+ ?- x E- {$ R) _- A- k7 k - 0 |4 J. `$ O" K
- /* We directly use etharp_output() here to save a function call.
& I" D8 |& q: c. E) F - * You can instead declare your own function an call etharp_output()
' ~1 I" |7 Q w+ }* L: } - * from it if you have to do some checks before sending (e.g. if link$ m4 H$ Y6 s; A" |+ p# h
- * is available...) */
H% r& Y5 ~8 d - netif->output = etharp_output;
5 A3 Y# V- N7 e9 r' o8 v - netif->linkoutput = low_level_output;& v- A% e6 _: I) o& M% Y. L
- 5 a# q' K% c- t$ r0 l# H7 R( W: a t
- /* initialize the hardware */( t, H2 c" w1 `* e
- low_level_init(netif);
, ]$ }' J+ y- k, w
- K D% r3 ^9 _! x* g1 }- return ERR_OK;" }$ ]: z9 i6 H4 \. Q8 p
- }
0 [) Y6 ~; O6 B( p0 a# ~
复制代码 编译正常,然后开始网络的配置" ]( N6 N) y* R) ^; b6 i, V8 }6 l
- static void Netif_Config(void)
% A7 g& V3 j7 `2 s, v - {
3 |& V! U T5 E1 z0 B& `- d! s7 C - ip_addr_t ipaddr;! X4 u4 R$ X- o0 d: M! k/ a$ @8 u' E
- ip_addr_t netmask;
9 v! o1 N3 e- N) H7 V. ^ - ip_addr_t gw;
3 \; h2 R/ {$ d j+ p - uint8_t iptab[4] = {0};
% s; q1 r# B& i+ q- f - uint8_t iptxt[20];
F0 {7 L" ?) {0 c2 K# ?0 w - uint8_t netmasktab[4]={0};$ ~ N" O: `5 N2 G, W. A
- uint8_t netmasktxt[30];
3 A" K1 U, }: |2 L -
1 Z9 e9 F1 U1 y4 l - uint8_t gwtab[4]={0};
0 k' L- } K0 F+ x - uint8_t gwtxt[30];. H; m. {/ @6 u" [
- . m5 n/ a; L. K4 ]
-
, l2 z3 y* u9 Q! b - mem_init(); //3?ê??ˉ?ˉì??ú′???
5 R8 q; [3 {* F - . j' f3 Q/ ]" E9 i3 o
- memp_init(); //3?ê??ˉ?ú′?3?" d8 e. `1 q# F3 Q7 N) w1 T8 ~
- & S! ^6 }( T9 J3 }4 X0 h, q) S) z- h
- #ifdef USE_DHCP
3 ?* `2 C- Y4 I6 x. z( B - ipaddr.addr = 0;
" h: i2 u; b: P7 S. I6 ~ - netmask.addr = 0;0 H: a% G2 ?$ r3 w" x. Z- K
- gw.addr = 0;6 ~: m# K/ L0 g' L8 m1 ^! L
- #else
" t( W9 {" y* I1 E, h* c6 A8 c - IP4_ADDR(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);. m" H4 Q% `8 ?' B& L2 i
- IP4_ADDR(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);" o, p) D- K% _$ E4 R
- IP4_ADDR(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);6 @# [% W: L, k: B
- #endif /* USE_DHCP */7 E& y9 P1 [( D. [
-
) H! i' H7 O* ~: ~6 H4 B# Q5 r - netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, eernetif_init, eernet_input);& }6 e& ~# i2 U, W( z
-
J' `. j# f( x, f! Q" | - /* Registers the default network interface. */
& i* x& ?" f) {/ q1 y/ u - netif_set_default(&gnetif);
, A; ^( s6 c9 W4 z6 e7 q - 4 |( x8 w0 k M+ P. {2 D' t
- if (netif_is_link_up(&gnetif))
+ O/ r" t' {7 x, t! N5 M - {, c% D) Y9 S$ c: N2 a1 P
- /* When the netif is fully configured this function must be called.*/( V. @! u5 R) V- N
- netif_set_up(&gnetif);
& N! |4 ], ~7 G - iptab[0] = IP_ADDR3;3 \7 ~' L' N! U& U! ]# m
- iptab[1] = IP_ADDR2;
% X! H9 O1 n8 Z- v$ p6 e& l - iptab[2] = IP_ADDR1;
8 V) h- W2 g3 Q. d7 B - iptab[3] = IP_ADDR0;
% D4 v$ t5 u* e. p8 X/ ?( E -
- o' z) P# n3 J) p, ~+ x. y - netmasktab[0]=NETMASK_ADDR3;" N6 \$ U& m2 H6 c+ |
- netmasktab[1]=NETMASK_ADDR2;
: V- O3 v |- }! s' h$ ~; {" W - netmasktab[2]=NETMASK_ADDR1;7 f/ e1 ?0 K2 L3 c$ Y& @ Q1 ?9 i
- netmasktab[3]=NETMASK_ADDR0;8 G+ l( N c x6 M2 P2 C% p
- ; M& x; [# x! P6 H
- gwtab[0]=GW_ADDR3;
6 L* N/ I( o9 h/ o - gwtab[1]=GW_ADDR2;. d- t' R. a* c" r5 F$ M
- gwtab[2]=GW_ADDR1;4 P" i4 W6 T3 w( \# P
- gwtab[3]=GW_ADDR0;$ f* {! _7 X6 ~+ B. p+ ]
( R' ]$ q" q$ _' d- ~- //6 j& N$ H+ B' b2 o$ [. z$ H% c
- sprintf((char*)iptxt, " %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]);
5 O* ? e C3 C: [( k1 w; C% m1 e - $ |- N: T; ^/ n5 X4 P
- sprintf((char*)netmasktxt, "%d.%d.%d.%d",netmasktab[3],netmasktab[2],netmasktab[1],netmasktab[0]);* \. _! J( J, |4 F3 T' z S4 J1 T
- 3 c% H$ H# D% G) c7 p" ?6 L+ O. U
- sprintf((char*)gwtxt,"%d.%d.%d.%d",gwtab[3],gwtab[2],gwtab[1],gwtab[0]);' z7 Q8 D% t5 I0 r8 E
-
' F: U q3 q. V8 {6 X+ | - /// }% j- M) d+ j) X y `
- printf("\r\n");* j" d6 I, U4 B. h
- printf("\r\n");/ Q, T/ E8 S& d! ^& _
- printf(" Network Cable is connected \r\n");* S, w/ l' S! L* J& @" F8 I C
- printf(" This is lwip1.4.1-ping demo test \r\n"); R Q$ b" \8 P/ p8 K0 D
- printf(" The stm32f769 ip address is: %s\r\n",iptxt);% Q$ K1 A/ w1 q$ y& M
- printf("The stm32f769 netmask address is: %s\r\n",netmasktxt);
1 ^8 N$ `5 z" D; u - printf(" The stm32f769 gw address is: %s\r\n",gwtxt);
+ B& s$ u7 t3 I8 p- H - printf("\r\n");/ P1 s. @ a/ F7 v
- printf("\r\n");
0 h7 [$ @$ ~% b, A( ]1 i' W9 w - printf("\r\n");9 W5 d' `2 \* ^! \* z
- }
; {- Y' k+ ?& T; i6 N$ Q4 q - else
( @0 c" `+ v/ D2 h# v* O8 X8 T - {" B, v2 u$ g7 F: A6 z# ]% Y0 y
- /* When the netif link is down this function must be called */% \+ |! z8 L- {& N4 X, V
- netif_set_down(&gnetif);
: }/ o& P" S5 [+ n0 Y - printf(" Network Cable is not connected \r\n");) m' g1 r# I; Q6 D
- }
! n0 m& f+ F( I7 ~ - }
复制代码 完成后,实现网络数据的处理% {. A( o, L- H
- void LwIP_Pkt_Handle(void)
7 W4 v3 }" P$ q g! K. t6 | - {6 R/ ~( n1 t( e# z5 r; \
- /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
# w3 x+ ]9 w g! | - ethernetif_input(&gnetif);! g- {6 w1 Z/ q$ Z* J
- }
* [$ r3 @4 U9 W# _6 h& W - void LwIP_Periodic_Handle(__IO uint32_t localtime)( F1 S |: d+ }4 \0 N
- {* W! z7 }4 a8 m- k) s& `( U' k
- #if LWIP_TCP) L5 V& ^3 m" U: W% i) }
- /* TCP periodic process every 250 ms */! @- j) W5 S7 ^8 `$ O2 i
- if (localtime - TCPTimer >= TCP_TMR_INTERVAL)4 G G1 W0 Q6 d
- {- [! ?6 j& c" x8 E; c o
- TCPTimer = localtime;
9 x% Z9 l6 P% { - tcp_tmr();
8 D( @: n- C' d: S' k - }5 u; f2 G4 z2 w+ M8 F
- #endif2 Q, k4 N" n6 _/ y. q
, a4 u* L0 d) X# @; P
! _. [: [3 q. _, y% P5 S- ~- etharp_tmr();
+ Y/ L1 Q, e0 a$ J3 y
3 d2 e" }- {& K0 u" N! N; N+ F- }
复制代码 在main函数添加网路初始化,及数据处理
$ X5 a' {) Q# _4 O- Netif_Config();( l K! j" q4 `( O& A" W& C
- " D K* s- v! A% v) ]* [/ |# f
- while(1)6 z0 r* D; T8 H" u5 q9 s; Q
- {1 O3 d3 b0 O/ [+ U/ s
- if (ETH_GetReceivedFrame(&EthHandle)) //?ì2éê?·??óê?μ?êy?Y°ü6 C% S, ?1 ^5 Y- b: z5 o
- { 3 z3 P$ a* x4 V9 V1 p8 O$ o8 \
- LwIP_Pkt_Handle(); //
9 V6 ?! p$ E& ~3 ~1 K, x. r4 o4 X% ^' p - }
3 `2 `5 k# r1 [$ j( { - /* handle periodic timers for LwIP */" x) ^5 ~, k; B
- LwIP_Periodic_Handle(LocalTime);1 v# }7 k8 K# H" a4 W: }9 G3 B
- led_toggle();# d* o4 w. P; i5 x
- delay_ms(5000);4 O! e4 |3 Y( W9 G, z! u4 U7 n d7 k
- }
复制代码
2 u$ j8 n' V% y ^5 T! _; X+ \& |+ w8 o) K k3 i
其他功能目前还在研究+ w. g2 F$ p7 x3 l
$ N. X4 O3 `) e4 Z% w4 ?. i |
https://www.stmcu.org.cn/module/forum/thread-615497-1-1.html