summaryrefslogtreecommitdiff
path: root/examples/stm32h7/src/bin/eth.rs
blob: acb6ef3a6672221325b4681674e20aa06861a88b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

#[path = "../example_common.rs"]
mod example_common;
use example_common::config;

use cortex_m_rt::entry;
use defmt::{info, unwrap};
use defmt_rtt as _; // global logger
use embassy::executor::{Executor, Spawner};
use embassy::io::AsyncWriteExt;
use embassy::time::{Duration, Timer};
use embassy::util::Forever;
use embassy_macros::interrupt_take;
use embassy_net::{
    Config as NetConfig, Ipv4Address, Ipv4Cidr, StackResources, StaticConfigurator, TcpSocket,
};
use embassy_stm32::eth::lan8742a::LAN8742A;
use embassy_stm32::eth::{Ethernet, State};
use embassy_stm32::rng::Rng;
use embassy_stm32::{interrupt, peripherals};
use heapless::Vec;
use panic_probe as _;
use peripherals::RNG;

#[embassy::task]
async fn main_task(
    device: &'static mut Ethernet<'static, LAN8742A, 4, 4>,
    config: &'static mut StaticConfigurator,
    spawner: Spawner,
) {
    let net_resources = NET_RESOURCES.put(StackResources::new());

    // Init network stack
    embassy_net::init(device, config, net_resources);

    // Launch network task
    unwrap!(spawner.spawn(net_task()));

    info!("Network task initialized");

    // Then we can use it!
    let mut rx_buffer = [0; 1024];
    let mut tx_buffer = [0; 1024];
    let mut socket = TcpSocket::new(&mut rx_buffer, &mut tx_buffer);

    socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10)));

    let remote_endpoint = (Ipv4Address::new(192, 168, 0, 10), 8000);
    let r = socket.connect(remote_endpoint).await;
    if let Err(e) = r {
        info!("connect error: {:?}", e);
        return;
    }
    info!("connected!");
    loop {
        let r = socket.write_all(b"Hello\n").await;
        if let Err(e) = r {
            info!("write error: {:?}", e);
            return;
        }
        Timer::after(Duration::from_secs(1)).await;
    }
}

#[embassy::task]
async fn net_task() {
    embassy_net::run().await
}

#[no_mangle]
fn _embassy_rand(buf: &mut [u8]) {
    use rand_core::RngCore;

    critical_section::with(|_| unsafe {
        unwrap!(RNG_INST.as_mut()).fill_bytes(buf);
    });
}

static mut RNG_INST: Option<Rng<RNG>> = None;

static EXECUTOR: Forever<Executor> = Forever::new();
static STATE: Forever<State<'static, 4, 4>> = Forever::new();
static ETH: Forever<Ethernet<'static, LAN8742A, 4, 4>> = Forever::new();
static CONFIG: Forever<StaticConfigurator> = Forever::new();
static NET_RESOURCES: Forever<StackResources<1, 2, 8>> = Forever::new();

#[entry]
fn main() -> ! {
    info!("Hello World!");

    info!("Setup RCC...");

    let p = embassy_stm32::init(config());

    let rng = Rng::new(p.RNG);
    unsafe {
        RNG_INST.replace(rng);
    }

    let eth_int = interrupt_take!(ETH);
    let mac_addr = [0x10; 6];
    let state = STATE.put(State::new());
    let eth = unsafe {
        ETH.put(Ethernet::new(
            state, p.ETH, eth_int, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PB12, p.PB13,
            p.PB11, LAN8742A, mac_addr, 1,
        ))
    };

    let config = StaticConfigurator::new(NetConfig {
        address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 0, 61), 24),
        dns_servers: Vec::new(),
        gateway: Some(Ipv4Address::new(192, 168, 0, 1)),
    });

    let config = CONFIG.put(config);

    let executor = EXECUTOR.put(Executor::new());

    executor.run(move |spawner| {
        unwrap!(spawner.spawn(main_task(eth, config, spawner)));
    })
}