Skip to content

Commit d179499

Browse files
committed
Merge branch 'master' into stm32f1
2 parents 69475d2 + 284079d commit d179499

File tree

12 files changed

+526
-145
lines changed

12 files changed

+526
-145
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
language: rust
22
matrix:
33
include:
4+
- rust: nightly
5+
env: FEATURES='stm32f107'
46
- rust: nightly
57
env: FEATURES='stm32f407'
68
- rust: nightly
@@ -39,6 +41,6 @@ matrix:
3941
env: FEATURES='stm32f778'
4042
- rust: nightly
4143
env: FEATURES='stm32f779'
42-
44+
4345
script:
4446
- "cargo build --target=`uname -m`-unknown-linux-gnu --no-default-features --features \"$FEATURES\""

Cargo.toml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,27 @@ travis-ci = { repository = "astro/stm32-eth", branch = "master" }
1515
maintenance = { status = "experimental" }
1616

1717
[package.metadata.docs.rs]
18-
features = [ "smoltcp-phy", "stm32f429" ]
18+
features = [ "smi", "smoltcp-phy", "stm32f429", "smoltcp/socket-tcp" ]
1919

2020
[dependencies]
2121
volatile-register = "0.2.1"
2222
aligned = "0.4.0"
23-
stm32f1xx-hal = { version = "0.9.0", optional = true }
24-
stm32f7xx-hal = { version = "0.6.0", optional = true }
23+
stm32f7xx-hal = { git = "https://github.com/stm32-rs/stm32f7xx-hal", rev = "7099b07", optional = true }
2524
stm32f4xx-hal = { version = "0.12.0", optional = true }
25+
stm32f1xx-hal = { version = "0.9.0", optional = true }
2626
cortex-m = "0.7.4"
2727
log = { version = "0.4.14", optional = true }
2828

2929
[dependencies.smoltcp]
3030
version = "0.8.0"
31-
# git = "https://github.com/smoltcp-rs/smoltcp"
32-
# branch = "master"
3331
default-features = false
3432
features = ["medium-ethernet", "proto-ipv4"]
3533
optional = true
3634

3735
[features]
3836
device-selected = []
3937
fence = []
38+
smi = []
4039

4140
stm32f107 = ["stm32f1xx-hal/stm32f107", "device-selected"]
4241

@@ -65,15 +64,13 @@ smoltcp-phy = ["smoltcp"]
6564
cortex-m = "0.7.4"
6665
cortex-m-rt = "0.7.1"
6766
panic-itm = "0.4.2"
68-
panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] }
69-
rtt-target = { version = "0.3.1", features = ["cortex-m"] }
7067
cortex-m-semihosting = "0.3.7"
68+
stm32f4xx-hal = { version = "0.12.0", features = ["rt"] }
7169
stm32f1xx-hal = { version = "0.9.0", features = ["rt"] }
72-
#stm32f4xx-hal = {version = "0.8.3", features = ["rt"] }
7370

7471
[[example]]
7572
name = "pktgen"
76-
required-features = ["stm32f429"]
73+
required-features = ["smi", "stm32f429"]
7774

7875
[[example]]
7976
name = "ip"
@@ -85,6 +82,13 @@ required-features = [
8582
[[example]]
8683
name = "ip-f107"
8784
required-features = ["stm32f107", "smoltcp-phy", "log", "smoltcp/socket-tcp"]
85+
[[example]]
86+
name = "arp"
87+
required-features = ["stm32f407", "smi"]
88+
89+
[[example]]
90+
name = "arp-smoltcp"
91+
required-features = ["stm32f407", "smi", "smoltcp-phy", "smoltcp/socket-icmp"]
8892

8993
[profile.release]
9094
debug = 2

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ cargo build --example="ip-f107" --features="stm32f107 smoltcp-phy log smoltcp/so
2222
Add to the `[dependencies]` section in your `Cargo.toml`:
2323

2424
```rust
25-
stm32f4xx-hal = { version = "0.8.3", features = ["stm32f429"] }
25+
stm32f4xx-hal = { version = "0.10.1", features = ["stm32f429"] }
2626
stm32-eth = { version = "0.2.0", features = ["stm32f429"] }
2727
```
2828

2929
or
3030

3131
```rust
32-
stm32f7xx-hal = { version = "0.2.0", features = ["stm32f767"] }
32+
stm32f7xx-hal = { version = "0.6.0", features = ["stm32f767"] }
3333
stm32-eth = { version = "0.2.0", features = ["stm32f767"]}
3434
```
3535

@@ -76,7 +76,6 @@ fn main() {
7676
p.ETHERNET_DMA,
7777
&mut rx_ring[..],
7878
&mut tx_ring[..],
79-
PhyAddress::_0,
8079
clocks,
8180
eth_pins,
8281
)

examples/arp-smoltcp.rs

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// cargo build --example arp-smoltcp --features=stm32f407,smi,smoltcp-phy,smoltcp/socket-tcp,smoltcp/socket-icmp
2+
// This example uses the STM32F407 and the KSZ8051R as PHY. If necessary the pins,
3+
// the PHY register addresses and masks have to be adapted, as well as the IPs.
4+
// With Wireshark, you can see the ARP packets, which should look like this:
5+
// No. Time Source Destination Protocol Length Info
6+
// 1 0.000000000 Cetia_ad:be:ef Broadcast ARP 60 Who has 10.0.0.2? Tell 10.0.0.10
7+
8+
#![no_std]
9+
#![no_main]
10+
11+
extern crate panic_itm;
12+
13+
use core::cell::RefCell;
14+
use core::default::Default;
15+
use cortex_m_rt::{entry, exception};
16+
17+
use cortex_m::asm;
18+
use cortex_m::interrupt::Mutex;
19+
use stm32_eth::{
20+
hal::gpio::{GpioExt, Speed},
21+
hal::rcc::RccExt,
22+
hal::time::U32Ext,
23+
smi,
24+
stm32::{interrupt, CorePeripherals, Peripherals, SYST},
25+
};
26+
27+
use cortex_m_semihosting::hprintln;
28+
29+
use smoltcp::wire::{
30+
ArpOperation, ArpPacket, ArpRepr, EthernetAddress, EthernetFrame, EthernetProtocol,
31+
EthernetRepr, Ipv4Address,
32+
};
33+
use stm32_eth::{Eth, EthPins, RingEntry, TxError};
34+
35+
const PHY_REG_BSR: u8 = 0x01;
36+
const PHY_REG_BSR_UP: u16 = 1 << 2;
37+
38+
const PHY_ADDR: u8 = 0;
39+
40+
static TIME: Mutex<RefCell<usize>> = Mutex::new(RefCell::new(0));
41+
static ETH_PENDING: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false));
42+
43+
#[entry]
44+
fn main() -> ! {
45+
let p = Peripherals::take().unwrap();
46+
let mut cp = CorePeripherals::take().unwrap();
47+
48+
let rcc = p.RCC.constrain();
49+
// HCLK must be at least 25MHz to use the ethernet peripheral
50+
let clocks = rcc.cfgr.sysclk(32.mhz()).hclk(32.mhz()).freeze();
51+
52+
setup_systick(&mut cp.SYST);
53+
54+
hprintln!("Enabling ethernet...").unwrap();
55+
let gpioa = p.GPIOA.split();
56+
let gpiob = p.GPIOB.split();
57+
let gpioc = p.GPIOC.split();
58+
let gpiog = p.GPIOG.split();
59+
60+
let eth_pins = EthPins {
61+
ref_clk: gpioa.pa1,
62+
crs: gpioa.pa7,
63+
tx_en: gpiob.pb11,
64+
tx_d0: gpiog.pg13,
65+
tx_d1: gpiog.pg14,
66+
rx_d0: gpioc.pc4,
67+
rx_d1: gpioc.pc5,
68+
};
69+
70+
let mut mdio = gpioa.pa2.into_alternate().set_speed(Speed::VeryHigh);
71+
let mut mdc = gpioc.pc1.into_alternate().set_speed(Speed::VeryHigh);
72+
73+
// ETH_PHY_RESET(RST#) PB2 Chip Reset (active-low)
74+
let _eth_reset = gpiob.pb2.into_push_pull_output().set_high();
75+
76+
let mut rx_ring: [RingEntry<_>; 16] = Default::default();
77+
let mut tx_ring: [RingEntry<_>; 8] = Default::default();
78+
let mut eth = Eth::new(
79+
p.ETHERNET_MAC,
80+
p.ETHERNET_DMA,
81+
&mut rx_ring[..],
82+
&mut tx_ring[..],
83+
clocks,
84+
eth_pins,
85+
)
86+
.unwrap();
87+
eth.enable_interrupt();
88+
89+
let mut last_link_up = false;
90+
91+
loop {
92+
let link_up = link_detected(eth.smi(&mut mdio, &mut mdc));
93+
94+
if link_up != last_link_up {
95+
if link_up {
96+
hprintln!("Ethernet: link detected").unwrap();
97+
} else {
98+
hprintln!("Ethernet: no link detected").unwrap();
99+
}
100+
last_link_up = link_up;
101+
}
102+
103+
if link_up {
104+
const SIZE: usize = 14 + 28; // ETH + ARP
105+
106+
let src_mac = EthernetAddress::from_bytes(&[0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]);
107+
108+
let arp_buffer = [0; 28];
109+
let mut packet =
110+
ArpPacket::new_checked(arp_buffer).expect("ArpPacket: buffer size is not correct");
111+
let arp = ArpRepr::EthernetIpv4 {
112+
operation: ArpOperation::Request,
113+
source_hardware_addr: src_mac,
114+
source_protocol_addr: Ipv4Address::new(10, 0, 0, 10),
115+
target_hardware_addr: EthernetAddress::from_bytes(&[0x00; 6]),
116+
target_protocol_addr: Ipv4Address::new(10, 0, 0, 2),
117+
};
118+
arp.emit(&mut packet);
119+
120+
let eth_buffer = [0; SIZE]; // ETH + ARP
121+
let mut frame = EthernetFrame::new_checked(eth_buffer)
122+
.expect("EthernetFrame: buffer size is not correct");
123+
let header = EthernetRepr {
124+
src_addr: src_mac,
125+
dst_addr: EthernetAddress::BROADCAST,
126+
ethertype: EthernetProtocol::Arp,
127+
};
128+
header.emit(&mut frame);
129+
frame.payload_mut().copy_from_slice(&packet.into_inner());
130+
131+
let r = eth.send(SIZE, |buf| {
132+
buf[0..SIZE].copy_from_slice(&frame.into_inner());
133+
});
134+
135+
match r {
136+
Ok(()) => {
137+
hprintln!("ARP-smoltcp sent").unwrap();
138+
}
139+
Err(TxError::WouldBlock) => hprintln!("ARP failed").unwrap(),
140+
}
141+
} else {
142+
hprintln!("Down").unwrap();
143+
}
144+
145+
cortex_m::interrupt::free(|cs| {
146+
let mut eth_pending = ETH_PENDING.borrow(cs).borrow_mut();
147+
*eth_pending = false;
148+
149+
if !*eth_pending {
150+
asm::wfi();
151+
}
152+
});
153+
}
154+
}
155+
156+
fn setup_systick(syst: &mut SYST) {
157+
syst.set_reload(100 * SYST::get_ticks_per_10ms());
158+
syst.enable_counter();
159+
syst.enable_interrupt();
160+
}
161+
162+
#[exception]
163+
fn SysTick() {
164+
cortex_m::interrupt::free(|cs| {
165+
let mut time = TIME.borrow(cs).borrow_mut();
166+
*time += 1;
167+
})
168+
}
169+
170+
#[interrupt]
171+
fn ETH() {
172+
cortex_m::interrupt::free(|cs| {
173+
let mut eth_pending = ETH_PENDING.borrow(cs).borrow_mut();
174+
*eth_pending = true;
175+
});
176+
177+
// Clear interrupt flags
178+
let p = unsafe { Peripherals::steal() };
179+
stm32_eth::eth_interrupt_handler(&p.ETHERNET_DMA);
180+
}
181+
182+
fn link_detected<Mdio, Mdc>(smi: smi::Smi<Mdio, Mdc>) -> bool
183+
where
184+
Mdio: smi::MdioPin,
185+
Mdc: smi::MdcPin,
186+
{
187+
let status = smi.read(PHY_ADDR, PHY_REG_BSR);
188+
(status & PHY_REG_BSR_UP) == PHY_REG_BSR_UP
189+
}

0 commit comments

Comments
 (0)