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