forked from renet/ENC424J600
Use RTIC framework on the examples
* tcp_stm32f407 no longer obtains IP address from environment variables.
This commit is contained in:
parent
25e682763c
commit
362cf3c411
|
@ -26,6 +26,12 @@ dependencies = [
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bare-metal"
|
name = "bare-metal"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
@ -106,6 +112,32 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cortex-m-rtic"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b30efcb6b7920d9016182c485687f0012487032a14c415d2fce6e9862ef8260e"
|
||||||
|
dependencies = [
|
||||||
|
"cortex-m 0.6.2",
|
||||||
|
"cortex-m-rt",
|
||||||
|
"cortex-m-rtic-macros",
|
||||||
|
"heapless",
|
||||||
|
"rtic-core",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cortex-m-rtic-macros"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a1a6a4c9550373038c0e21a78d44d529bd697c25bbf6b8004bddc6e63b119c7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rtic-syntax",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
@ -123,6 +155,7 @@ dependencies = [
|
||||||
"aligned 0.3.2",
|
"aligned 0.3.2",
|
||||||
"cortex-m 0.5.10",
|
"cortex-m 0.5.10",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
|
"cortex-m-rtic",
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
"log",
|
"log",
|
||||||
"panic-itm",
|
"panic-itm",
|
||||||
|
@ -149,6 +182,43 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1"
|
||||||
|
dependencies = [
|
||||||
|
"as-slice",
|
||||||
|
"generic-array 0.13.2",
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
|
@ -209,6 +279,23 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtic-core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bd58a6949de8ff797a346a28d9f13f7b8f54fa61bb5e3cb0985a4efb497a5ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtic-syntax"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8152fcaa845720d61e6cc570548b89144c2c307f18a480bbd97e55e9f6eeff04"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -308,6 +395,12 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
|
@ -15,6 +15,7 @@ embedded-hal = "0.2"
|
||||||
stm32f4xx-hal = { version = "0.8" , optional = true }
|
stm32f4xx-hal = { version = "0.8" , optional = true }
|
||||||
smoltcp = { version = "0.6.0", default-features = false, features = ["proto-ipv4", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", "log", "verbose", "ethernet"], optional = true }
|
smoltcp = { version = "0.6.0", default-features = false, features = ["proto-ipv4", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", "log", "verbose", "ethernet"], optional = true }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
cortex-m-rtic = "0.5.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
smoltcp-phy = ["smoltcp"]
|
smoltcp-phy = ["smoltcp"]
|
||||||
|
|
|
@ -82,9 +82,9 @@ This program demonstrates the TCP connectivity using **smoltcp** on an STM32F407
|
||||||
[nix-shell]$ run-tmux-env
|
[nix-shell]$ run-tmux-env
|
||||||
```
|
```
|
||||||
|
|
||||||
3. When the `tmux` session is ready, on the top-right pane, compile and run the example program. Choose your own IPv4 address and prefix length:
|
3. When the `tmux` session is ready, on the top-right pane, compile and run the example program. The default IP address is 192.168.1.77, which can be edited in the source file `examples/tcp_stm32f407.rs`.
|
||||||
```sh
|
```sh
|
||||||
[nix-shell]$ tcp_stm32f407 <ip> <prefix>
|
[nix-shell]$ tcp_stm32f407
|
||||||
```
|
```
|
||||||
|
|
||||||
4. To test the TCP ports, switch to the bottom-right pane (with <kbd>Ctrl</kbd>+<kbd>B</kbd>, followed by an arrow key) and use utilities like NetCat (`nc`):
|
4. To test the TCP ports, switch to the bottom-right pane (with <kbd>Ctrl</kbd>+<kbd>B</kbd>, followed by an arrow key) and use utilities like NetCat (`nc`):
|
||||||
|
@ -97,7 +97,7 @@ This program demonstrates the TCP connectivity using **smoltcp** on an STM32F407
|
||||||
|
|
||||||
#### Expected Output
|
#### Expected Output
|
||||||
|
|
||||||
(Note: the IP address, MAC address and timestamps shown below are examples only.)
|
(Note: the MAC address and timestamps shown below are examples only.)
|
||||||
|
|
||||||
ITM output at the initial state:
|
ITM output at the initial state:
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,125 +1,99 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::env;
|
|
||||||
|
|
||||||
extern crate panic_itm;
|
extern crate panic_itm;
|
||||||
use cortex_m::{iprintln, iprint};
|
use cortex_m::{iprintln, iprint};
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use embedded_hal::{
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
digital::v2::OutputPin,
|
||||||
use embedded_hal::blocking::delay::DelayMs;
|
blocking::delay::DelayMs
|
||||||
|
};
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
rcc::RccExt,
|
rcc::RccExt,
|
||||||
gpio::GpioExt,
|
gpio::GpioExt,
|
||||||
time::U32Ext,
|
time::U32Ext,
|
||||||
stm32::{CorePeripherals, Peripherals},
|
stm32::ITM,
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
spi::Spi,
|
spi::Spi,
|
||||||
time::Hertz
|
time::Hertz
|
||||||
};
|
};
|
||||||
use enc424j600;
|
use enc424j600;
|
||||||
use enc424j600::EthController;
|
use enc424j600::{smoltcp_phy, EthController};
|
||||||
use enc424j600::smoltcp_phy;
|
|
||||||
|
|
||||||
use smoltcp::wire::{
|
use smoltcp::wire::{
|
||||||
EthernetAddress, IpAddress, IpCidr
|
EthernetAddress, IpAddress, IpCidr, Ipv6Cidr
|
||||||
};
|
};
|
||||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, EthernetInterface};
|
||||||
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||||
use smoltcp::time::{Instant, Duration};
|
|
||||||
use core::str;
|
use core::str;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
use core::cell::RefCell;
|
use rtic::cyccnt::Instant;
|
||||||
use cortex_m::interrupt::Mutex;
|
|
||||||
use cortex_m_rt::exception;
|
///
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
rcc::Clocks,
|
stm32::SPI1,
|
||||||
time::MilliSeconds,
|
gpio::{
|
||||||
timer::{Timer, Event as TimerEvent},
|
gpioa::{PA5, PA6, PA7, PA4},
|
||||||
stm32::SYST
|
Alternate, AF5, Output, PushPull
|
||||||
|
}
|
||||||
};
|
};
|
||||||
/// Rate in Hz
|
type BoosterSpiEth = enc424j600::SpiEth<
|
||||||
const TIMER_RATE: u32 = 20;
|
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
|
||||||
/// Interval duration in milliseconds
|
PA4<Output<PushPull>>>;
|
||||||
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
|
||||||
/// Elapsed time in milliseconds
|
|
||||||
static TIMER_MS: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
|
||||||
|
|
||||||
/// Setup SysTick exception
|
pub struct NetStorage {
|
||||||
fn timer_setup(syst: SYST, clocks: Clocks) {
|
ip_addrs: [IpCidr; 1],
|
||||||
let mut timer = Timer::syst(syst, TIMER_RATE.hz(), clocks);
|
neighbor_cache: [Option<(IpAddress, smoltcp::iface::Neighbor)>; 8],
|
||||||
timer.listen(TimerEvent::TimeOut);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SysTick exception (Timer)
|
static mut NET_STORE: NetStorage = NetStorage {
|
||||||
#[exception]
|
// Placeholder for the real IP address, which is initialized at runtime.
|
||||||
fn SysTick() {
|
ip_addrs: [IpCidr::Ipv6(
|
||||||
cortex_m::interrupt::free(|cs| {
|
Ipv6Cidr::SOLICITED_NODE_PREFIX,
|
||||||
*TIMER_MS.borrow(cs)
|
)],
|
||||||
.borrow_mut() += TIMER_DELTA;
|
neighbor_cache: [None; 8],
|
||||||
});
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtain current time in milliseconds
|
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
pub fn timer_now() -> MilliSeconds {
|
const APP: () = {
|
||||||
let ms = cortex_m::interrupt::free(|cs| {
|
struct Resources {
|
||||||
*TIMER_MS.borrow(cs)
|
eth_iface: EthernetInterface<
|
||||||
.borrow()
|
'static,
|
||||||
});
|
'static,
|
||||||
ms.ms()
|
'static,
|
||||||
}
|
smoltcp_phy::SmoltcpDevice<BoosterSpiEth>>,
|
||||||
|
itm: ITM
|
||||||
|
}
|
||||||
|
|
||||||
#[entry]
|
#[init()]
|
||||||
fn main() -> ! {
|
fn init(mut c: init::Context) -> init::LateResources {
|
||||||
let mut cp = CorePeripherals::take().unwrap();
|
c.core.SCB.enable_icache();
|
||||||
cp.SCB.enable_icache();
|
c.core.SCB.enable_dcache(&mut c.core.CPUID);
|
||||||
cp.SCB.enable_dcache(&mut cp.CPUID);
|
|
||||||
|
|
||||||
let dp = Peripherals::take().unwrap();
|
// Enable monotonic timer CYCCNT
|
||||||
let clocks = dp.RCC.constrain()
|
c.core.DWT.enable_cycle_counter();
|
||||||
|
c.core.DCB.enable_trace();
|
||||||
|
|
||||||
|
let clocks = c.device.RCC.constrain()
|
||||||
.cfgr
|
.cfgr
|
||||||
.sysclk(168.mhz())
|
.sysclk(168.mhz())
|
||||||
.hclk(168.mhz())
|
.hclk(168.mhz())
|
||||||
.pclk1(32.mhz())
|
.pclk1(42.mhz())
|
||||||
.pclk2(64.mhz())
|
.require_pll48clk()
|
||||||
.freeze();
|
.freeze();
|
||||||
|
let mut delay = Delay::new(c.core.SYST, clocks);
|
||||||
|
|
||||||
// Init ITM & use Stimulus Port 0
|
// Init ITM
|
||||||
let mut itm = cp.ITM;
|
let mut itm = c.core.ITM;
|
||||||
let stim0 = &mut itm.stim[0];
|
let stim0 = &mut itm.stim[0];
|
||||||
|
|
||||||
iprintln!(stim0,
|
iprintln!(stim0,
|
||||||
"Eth TCP Server on STM32-F407 via NIC100/ENC424J600");
|
"Eth TCP Server on STM32-F407 via NIC100/ENC424J600");
|
||||||
|
|
||||||
// Get IP address from args
|
|
||||||
let arg_ip_raw = env!("ENC424J600_TCP_IP");
|
|
||||||
let mut arg_ip_str = arg_ip_raw.split('.');
|
|
||||||
let mut arg_ip: [u8; 4] = [0; 4];
|
|
||||||
for i in 0..4 {
|
|
||||||
match arg_ip_str.next() {
|
|
||||||
Some(x) => {
|
|
||||||
match x.parse() {
|
|
||||||
Ok(x_) => { arg_ip[i] = x_ },
|
|
||||||
Err(_) => { panic!("IPv4 address invalid!") }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => { panic!("IPv4 address invalid!") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get IP prefix length from args
|
|
||||||
let arg_ip_pref_raw = env!("ENC424J600_TCP_PREF");
|
|
||||||
let mut arg_ip_pref: u8 = 0;
|
|
||||||
match arg_ip_pref_raw.parse() {
|
|
||||||
Ok(x) => { arg_ip_pref = x },
|
|
||||||
Err(_) => { panic!("IP prefix length invalid!") }
|
|
||||||
}
|
|
||||||
|
|
||||||
// NIC100 / ENC424J600 Set-up
|
// NIC100 / ENC424J600 Set-up
|
||||||
let spi1 = dp.SPI1;
|
let spi1 = c.device.SPI1;
|
||||||
let gpioa = dp.GPIOA.split();
|
let gpioa = c.device.GPIOA.split();
|
||||||
let mut delay = Delay::new(cp.SYST, clocks);
|
|
||||||
// Mapping: see Table 9, STM32F407ZG Manual
|
// Mapping: see Table 9, STM32F407ZG Manual
|
||||||
let spi1_sck = gpioa.pa5.into_alternate_af5();
|
let spi1_sck = gpioa.pa5.into_alternate_af5();
|
||||||
let spi1_miso = gpioa.pa6.into_alternate_af5();
|
let spi1_miso = gpioa.pa6.into_alternate_af5();
|
||||||
|
@ -130,28 +104,28 @@ fn main() -> ! {
|
||||||
spisel.set_high().unwrap();
|
spisel.set_high().unwrap();
|
||||||
delay.delay_ms(1_u32);
|
delay.delay_ms(1_u32);
|
||||||
spisel.set_low().unwrap();
|
spisel.set_low().unwrap();
|
||||||
|
|
||||||
// Create SPI1 for HAL
|
// Create SPI1 for HAL
|
||||||
|
let eth_iface = {
|
||||||
|
let mut spi_eth = {
|
||||||
let spi_eth_port = Spi::spi1(
|
let spi_eth_port = Spi::spi1(
|
||||||
spi1, (spi1_sck, spi1_miso, spi1_mosi),
|
spi1, (spi1_sck, spi1_miso, spi1_mosi),
|
||||||
enc424j600::spi::interfaces::SPI_MODE,
|
enc424j600::spi::interfaces::SPI_MODE,
|
||||||
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
|
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
|
||||||
clocks);
|
clocks);
|
||||||
let mut spi_eth = enc424j600::SpiEth::new(spi_eth_port, spi1_nss);
|
enc424j600::SpiEth::new(spi_eth_port, spi1_nss)
|
||||||
// Init
|
};
|
||||||
|
|
||||||
|
// Init controller
|
||||||
match spi_eth.init_dev(&mut delay) {
|
match spi_eth.init_dev(&mut delay) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
iprintln!(stim0, "Ethernet initialized")
|
iprintln!(stim0, "Initializing Ethernet...")
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
panic!("Ethernet initialization failed!")
|
panic!("Ethernet initialization failed!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup SysTick
|
|
||||||
// Reference to stm32-eth:examples/ip.rs
|
|
||||||
timer_setup(delay.free(), clocks);
|
|
||||||
iprintln!(stim0, "Timer initialized");
|
|
||||||
|
|
||||||
// Read MAC
|
// Read MAC
|
||||||
let mut eth_mac_addr: [u8; 6] = [0; 6];
|
let mut eth_mac_addr: [u8; 6] = [0; 6];
|
||||||
spi_eth.read_from_mac(&mut eth_mac_addr);
|
spi_eth.read_from_mac(&mut eth_mac_addr);
|
||||||
|
@ -168,20 +142,37 @@ fn main() -> ! {
|
||||||
// Init Rx/Tx buffers
|
// Init Rx/Tx buffers
|
||||||
spi_eth.init_rxbuf();
|
spi_eth.init_rxbuf();
|
||||||
spi_eth.init_txbuf();
|
spi_eth.init_txbuf();
|
||||||
|
iprintln!(stim0, "Ethernet controller initialized");
|
||||||
|
|
||||||
// Copied / modified from smoltcp:
|
// Init smoltcp interface
|
||||||
// examples/loopback.rs, examples/multicast.rs
|
let eth_iface = {
|
||||||
let device = smoltcp_phy::SmoltcpDevice::new(spi_eth);
|
let device = smoltcp_phy::SmoltcpDevice::new(spi_eth);
|
||||||
let mut neighbor_cache_entries = [None; 16];
|
|
||||||
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]);
|
let store = unsafe { &mut NET_STORE };
|
||||||
let ip_addr = IpCidr::new(IpAddress::v4(
|
store.ip_addrs[0] = IpCidr::new(IpAddress::v4(192, 168, 1, 77), 24);
|
||||||
arg_ip[0], arg_ip[1], arg_ip[2], arg_ip[3]), arg_ip_pref);
|
let neighbor_cache = NeighborCache::new(&mut store.neighbor_cache[..]);
|
||||||
let mut ip_addrs = [ip_addr];
|
|
||||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
EthernetInterfaceBuilder::new(device)
|
||||||
.ethernet_addr(EthernetAddress(eth_mac_addr))
|
.ethernet_addr(EthernetAddress(eth_mac_addr))
|
||||||
.neighbor_cache(neighbor_cache)
|
.neighbor_cache(neighbor_cache)
|
||||||
.ip_addrs(&mut ip_addrs[..])
|
.ip_addrs(&mut store.ip_addrs[..])
|
||||||
.finalize();
|
.finalize()
|
||||||
|
};
|
||||||
|
iprintln!(stim0, "Ethernet interface initialized");
|
||||||
|
|
||||||
|
eth_iface
|
||||||
|
};
|
||||||
|
|
||||||
|
init::LateResources {
|
||||||
|
eth_iface,
|
||||||
|
itm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle(resources=[eth_iface, itm])]
|
||||||
|
fn idle(c: idle::Context) -> ! {
|
||||||
|
let stim0 = &mut c.resources.itm.stim[0];
|
||||||
|
let iface = c.resources.eth_iface;
|
||||||
|
|
||||||
// Copied / modified from smoltcp:
|
// Copied / modified from smoltcp:
|
||||||
// examples/loopback.rs
|
// examples/loopback.rs
|
||||||
|
@ -203,15 +194,28 @@ fn main() -> ! {
|
||||||
let mut socket_set = SocketSet::new(&mut socket_set_entries[..]);
|
let mut socket_set = SocketSet::new(&mut socket_set_entries[..]);
|
||||||
let echo_handle = socket_set.add(echo_socket);
|
let echo_handle = socket_set.add(echo_socket);
|
||||||
let greet_handle = socket_set.add(greet_socket);
|
let greet_handle = socket_set.add(greet_socket);
|
||||||
iprintln!(stim0, "TCP sockets will listen at {}", ip_addr);
|
{
|
||||||
|
let store = unsafe { &mut NET_STORE };
|
||||||
|
iprintln!(stim0,
|
||||||
|
"TCP sockets will listen at {}", store.ip_addrs[0].address());
|
||||||
|
}
|
||||||
|
|
||||||
// Copied / modified from:
|
// Copied / modified from:
|
||||||
// smoltcp:examples/loopback.rs, examples/server.rs;
|
// smoltcp:examples/loopback.rs, examples/server.rs;
|
||||||
// stm32-eth:examples/ip.rs,
|
// stm32-eth:examples/ip.rs,
|
||||||
// git.m-labs.hk/M-Labs/tnetplug
|
// git.m-labs.hk/M-Labs/tnetplug
|
||||||
|
let mut time = 0u32;
|
||||||
|
let mut next_ms = Instant::now();
|
||||||
|
use rtic::cyccnt::U32Ext;
|
||||||
|
next_ms += 168_000_u32.cycles();
|
||||||
loop {
|
loop {
|
||||||
let now = timer_now().0;
|
// Poll
|
||||||
let instant = Instant::from_millis(now as i64);
|
let tick = Instant::now() > next_ms;
|
||||||
|
if tick {
|
||||||
|
next_ms += 168_000_u32.cycles();
|
||||||
|
time += 1;
|
||||||
|
}
|
||||||
|
let instant = smoltcp::time::Instant::from_millis(time as i64);
|
||||||
match iface.poll(&mut socket_set, instant) {
|
match iface.poll(&mut socket_set, instant) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
},
|
},
|
||||||
|
@ -226,7 +230,7 @@ fn main() -> ! {
|
||||||
iprintln!(stim0,
|
iprintln!(stim0,
|
||||||
"[{}] Listening to port 1234 for echoing, time-out in 10s", instant);
|
"[{}] Listening to port 1234 for echoing, time-out in 10s", instant);
|
||||||
socket.listen(1234).unwrap();
|
socket.listen(1234).unwrap();
|
||||||
socket.set_timeout(Some(Duration::from_millis(10000)));
|
socket.set_timeout(Some(smoltcp::time::Duration::from_millis(10000)));
|
||||||
}
|
}
|
||||||
if socket.can_recv() {
|
if socket.can_recv() {
|
||||||
iprintln!(stim0,
|
iprintln!(stim0,
|
||||||
|
@ -254,4 +258,9 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn EXTI0();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
extern crate panic_itm;
|
extern crate panic_itm;
|
||||||
use cortex_m::{iprintln, iprint};
|
use cortex_m::{iprintln, iprint};
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use embedded_hal::{
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
digital::v2::OutputPin,
|
||||||
use embedded_hal::blocking::delay::DelayMs;
|
blocking::delay::DelayMs
|
||||||
|
};
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
rcc::RccExt,
|
rcc::RccExt,
|
||||||
gpio::GpioExt,
|
gpio::GpioExt,
|
||||||
time::U32Ext,
|
time::U32Ext,
|
||||||
stm32::{CorePeripherals, Peripherals},
|
stm32::ITM,
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
spi::Spi,
|
spi::Spi,
|
||||||
time::Hertz
|
time::Hertz
|
||||||
|
@ -19,32 +20,51 @@ use stm32f4xx_hal::{
|
||||||
use enc424j600;
|
use enc424j600;
|
||||||
use enc424j600::EthController;
|
use enc424j600::EthController;
|
||||||
|
|
||||||
#[entry]
|
///
|
||||||
fn main() -> ! {
|
use stm32f4xx_hal::{
|
||||||
let mut cp = CorePeripherals::take().unwrap();
|
stm32::SPI1,
|
||||||
cp.SCB.enable_icache();
|
gpio::{
|
||||||
cp.SCB.enable_dcache(&mut cp.CPUID);
|
gpioa::{PA5, PA6, PA7, PA4},
|
||||||
|
Alternate, AF5, Output, PushPull
|
||||||
|
},
|
||||||
|
};
|
||||||
|
type BoosterSpiEth = enc424j600::SpiEth<
|
||||||
|
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
|
||||||
|
PA4<Output<PushPull>>>;
|
||||||
|
|
||||||
let dp = Peripherals::take().unwrap();
|
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
let clocks = dp.RCC.constrain()
|
const APP: () = {
|
||||||
|
struct Resources {
|
||||||
|
spi_eth: BoosterSpiEth,
|
||||||
|
delay: Delay,
|
||||||
|
itm: ITM,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[init()]
|
||||||
|
fn init(mut c: init::Context) -> init::LateResources {
|
||||||
|
c.core.SCB.enable_icache();
|
||||||
|
c.core.SCB.enable_dcache(&mut c.core.CPUID);
|
||||||
|
|
||||||
|
let clocks = c.device.RCC.constrain()
|
||||||
.cfgr
|
.cfgr
|
||||||
.sysclk(168.mhz())
|
.sysclk(168.mhz())
|
||||||
.hclk(168.mhz())
|
.hclk(168.mhz())
|
||||||
.pclk1(32.mhz())
|
//.pclk1(32.mhz())
|
||||||
.pclk2(64.mhz())
|
.pclk1(42.mhz())
|
||||||
|
//.pclk2(64.mhz())
|
||||||
|
.require_pll48clk()
|
||||||
.freeze();
|
.freeze();
|
||||||
let mut delay = Delay::new(cp.SYST, clocks);
|
let mut delay = Delay::new(c.core.SYST, clocks);
|
||||||
|
|
||||||
// Init ITM & use Stimulus Port 0
|
// Init ITM
|
||||||
let mut itm = cp.ITM;
|
let mut itm = c.core.ITM;
|
||||||
let stim0 = &mut itm.stim[0];
|
let stim0 = &mut itm.stim[0];
|
||||||
|
|
||||||
iprintln!(stim0,
|
iprintln!(stim0,
|
||||||
"Eth TX Pinging on STM32-F407 via NIC100/ENC424J600");
|
"Eth TX Pinging on STM32-F407 via NIC100/ENC424J600");
|
||||||
|
|
||||||
// NIC100 / ENC424J600 Set-up
|
// NIC100 / ENC424J600 Set-up
|
||||||
let spi1 = dp.SPI1;
|
let spi1 = c.device.SPI1;
|
||||||
let gpioa = dp.GPIOA.split();
|
let gpioa = c.device.GPIOA.split();
|
||||||
// Mapping: see Table 9, STM32F407ZG Manual
|
// Mapping: see Table 9, STM32F407ZG Manual
|
||||||
let spi1_sck = gpioa.pa5.into_alternate_af5();
|
let spi1_sck = gpioa.pa5.into_alternate_af5();
|
||||||
let spi1_miso = gpioa.pa6.into_alternate_af5();
|
let spi1_miso = gpioa.pa6.into_alternate_af5();
|
||||||
|
@ -56,16 +76,19 @@ fn main() -> ! {
|
||||||
delay.delay_ms(1_u32);
|
delay.delay_ms(1_u32);
|
||||||
spisel.set_low().unwrap();
|
spisel.set_low().unwrap();
|
||||||
// Create SPI1 for HAL
|
// Create SPI1 for HAL
|
||||||
|
let mut spi_eth = {
|
||||||
let spi_eth_port = Spi::spi1(
|
let spi_eth_port = Spi::spi1(
|
||||||
spi1, (spi1_sck, spi1_miso, spi1_mosi),
|
spi1, (spi1_sck, spi1_miso, spi1_mosi),
|
||||||
enc424j600::spi::interfaces::SPI_MODE,
|
enc424j600::spi::interfaces::SPI_MODE,
|
||||||
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
|
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
|
||||||
clocks);
|
clocks);
|
||||||
let mut spi_eth = enc424j600::SpiEth::new(spi_eth_port, spi1_nss);
|
enc424j600::SpiEth::new(spi_eth_port, spi1_nss)
|
||||||
|
};
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
match spi_eth.init_dev(&mut delay) {
|
match spi_eth.init_dev(&mut delay) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
iprintln!(stim0, "Ethernet initialized")
|
iprintln!(stim0, "Initializing Ethernet...")
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
panic!("Ethernet initialization failed!")
|
panic!("Ethernet initialization failed!")
|
||||||
|
@ -88,6 +111,18 @@ fn main() -> ! {
|
||||||
// Init Rx/Tx buffers
|
// Init Rx/Tx buffers
|
||||||
spi_eth.init_rxbuf();
|
spi_eth.init_rxbuf();
|
||||||
spi_eth.init_txbuf();
|
spi_eth.init_txbuf();
|
||||||
|
iprintln!(stim0, "Ethernet controller initialized");
|
||||||
|
|
||||||
|
init::LateResources {
|
||||||
|
spi_eth,
|
||||||
|
delay,
|
||||||
|
itm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle(resources=[spi_eth, delay, itm])]
|
||||||
|
fn idle(c: idle::Context) -> ! {
|
||||||
|
let stim0 = &mut c.resources.itm.stim[0];
|
||||||
// Testing Eth TX
|
// Testing Eth TX
|
||||||
let eth_tx_dat: [u8; 64] = [
|
let eth_tx_dat: [u8; 64] = [
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x60,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x60,
|
||||||
|
@ -117,8 +152,9 @@ fn main() -> ! {
|
||||||
_ => ()
|
_ => ()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
spi_eth.send_raw_packet(ð_tx_packet);
|
c.resources.spi_eth.send_raw_packet(ð_tx_packet);
|
||||||
iprintln!(stim0, "Packet sent");
|
iprintln!(stim0, "Packet sent");
|
||||||
delay.delay_ms(100_u32);
|
c.resources.delay.delay_ms(100_u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
13
shell.nix
13
shell.nix
|
@ -22,9 +22,8 @@ let
|
||||||
echo "[Examples]"
|
echo "[Examples]"
|
||||||
echo " tx_stm32f407"
|
echo " tx_stm32f407"
|
||||||
echo " - Run tx_stm32f407 example."
|
echo " - Run tx_stm32f407 example."
|
||||||
echo " tcp_stm32f407 <ip> <pref>"
|
echo " tcp_stm32f407"
|
||||||
echo " - Run tcp_stm32f407 example with the IPv4"
|
echo " - Run tcp_stm32f407 example."
|
||||||
echo " address <ip> (dot-separated) and prefix length <pref>."
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "[Workspace]"
|
echo "[Workspace]"
|
||||||
echo " run-tmux-env"
|
echo " run-tmux-env"
|
||||||
|
@ -98,14 +97,6 @@ let
|
||||||
cargo run --release --example=tx_stm32f407 --features=stm32f407
|
cargo run --release --example=tx_stm32f407 --features=stm32f407
|
||||||
'';
|
'';
|
||||||
exTcpStm32f407 = writeShellScriptBin "tcp_stm32f407" ''
|
exTcpStm32f407 = writeShellScriptBin "tcp_stm32f407" ''
|
||||||
if [[ $1 = "" ]] || [[ $2 = "" ]]
|
|
||||||
then
|
|
||||||
echo "Arguments <ip> or <pref> are missing."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
touch ./examples/tcp_stm32f407.rs
|
|
||||||
export ENC424J600_TCP_IP=$1
|
|
||||||
export ENC424J600_TCP_PREF=$2
|
|
||||||
cargo run --release --example=tcp_stm32f407 --features=stm32f407,smoltcp-phy-all
|
cargo run --release --example=tcp_stm32f407 --features=stm32f407,smoltcp-phy-all
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
|
|
Loading…
Reference in New Issue