Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement receive_data_tcp #71

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cross/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"dns",
"get_fw_version",
"join",
"receive_data_tcp",
"send_data_tcp"
]

Expand Down
2 changes: 1 addition & 1 deletion cross/dns/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fn main() -> ! {
}
}

wifi.leave().ok().unwrap();
wifi.leave().ok();
} else if status == ConnectionStatus::Disconnected {
defmt::info!("Disconnected from Network: {:?}", SSID);
sleep = 20000; // No need to loop as often after disconnecting
Expand Down
42 changes: 42 additions & 0 deletions cross/receive_data_tcp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[package]
authors = [
"Jim Hodapp",
"Caleb Bourg",
"Glyn Matthews",
"Dilyn Corner"
]
edition = "2021"
name = "receive_data_tcp"
version = "0.3.1"
description = "Example target application that demonstrates DNS functionality with the Rust-based Espressif ESP32-WROOM WiFi driver crate for RP2040 series microcontroller boards."

# makes `cargo check --all-targets` work
[[bin]]
name = "receive_data_tcp"
bench = false
doctest = false
test = false

[dependencies]
defmt = "0.3.0"
defmt-rtt = "0.3.0"
cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded-hal = { version = "0.2", features=["unproven"] }
esp32-wroom-rp = { path = "../../esp32-wroom-rp" }
panic-probe = { version = "0.3.0", features = ["print-rtt"] }
heapless = "0.7.16"

rp2040-hal = { version = "0.6", features=["rt", "eh1_0_alpha"] }
rp2040-boot2 = { version = "0.2" }
fugit = "0.3"

[features]
default = ['defmt-default']
# these features are required by defmt
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []
222 changes: 222 additions & 0 deletions cross/receive_data_tcp/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
//! # ESP32-WROOM-RP Pico Wireless Example
//!
//! This application demonstrates how to use the ESP32-WROOM-RP crate to
//! send data to a remote server over TCP.
//!
//! See the `Cargo.toml` file for Copyright and license details.

#![no_std]
#![no_main]

extern crate esp32_wroom_rp;

include!("../../secrets/secrets.rs");

// The macro for our start-up function
use cortex_m_rt::entry;

// Needed for debug output symbols to be linked in binary image
use defmt_rtt as _;

use panic_probe as _;

// Alias for our HAL crate
use rp2040_hal as hal;

use embedded_hal::spi::MODE_0;

use core::fmt::Write;

use fugit::RateExtU32;
use hal::gpio::{FloatingInput, PushPullOutput};
use hal::{clocks::Clock, pac};

use heapless::String;

use esp32_wroom_rp::{
gpio::EspControlPins, network::IpAddress, network::Port, network::TransportMode,
tcp_client::Connect, tcp_client::TcpClient, wifi::ConnectionStatus, wifi::Wifi,
};

const MAX_HTTP_DOC_LENGTH: usize = 4096 as usize;

/// The linker will place this boot block at the start of our program image. We
/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;

/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
/// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;

/// Entry point to our bare-metal application.
///
/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables are initialized.
#[entry]
fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();

// Set up the watchdog driver - needed by the clock setup code
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);

// Configure the clocks
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();

let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

// The single-cycle I/O block controls our GPIO pins
let sio = hal::Sio::new(pac.SIO);

// Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);

defmt::info!("ESP32-WROOM-RP example to send data over TCP socket");

// These are implicitly used by the spi driver if they are in the correct mode
let _spi_miso = pins.gpio16.into_mode::<hal::gpio::FunctionSpi>();
let _spi_sclk = pins.gpio18.into_mode::<hal::gpio::FunctionSpi>();
let _spi_mosi = pins.gpio19.into_mode::<hal::gpio::FunctionSpi>();

let spi = hal::Spi::<_, _, 8>::new(pac.SPI0);

// Exchange the uninitialized SPI driver for an initialized one
let spi = spi.init(
&mut pac.RESETS,
clocks.peripheral_clock.freq(),
8.MHz(),
&MODE_0,
);

let esp_pins = EspControlPins {
// CS on pin x (GPIO7)
cs: pins.gpio7.into_mode::<PushPullOutput>(),
// GPIO0 on pin x (GPIO2)
gpio0: pins.gpio2.into_mode::<PushPullOutput>(),
// RESETn on pin x (GPIO11)
resetn: pins.gpio11.into_mode::<PushPullOutput>(),
// ACK on pin x (GPIO10)
ack: pins.gpio10.into_mode::<FloatingInput>(),
};

let mut wifi = Wifi::init(spi, esp_pins, &mut delay).unwrap();

let result = wifi.join(SSID, PASSPHRASE);
defmt::info!("Join Result: {:?}", result);

defmt::info!("Entering main loop");

let mut sleep: u32 = 1500;
loop {
match wifi.get_connection_status() {
Ok(status) => {
defmt::info!("Connection status: {:?}", status);
delay.delay_ms(sleep);

if status == ConnectionStatus::Connected {
defmt::info!("Connected to network: {:?}", SSID);

// The IPAddresses of two DNS servers to resolve hostnames with.
// Note that failover from ip1 to ip2 is fully functional.
let ip1: IpAddress = [9, 9, 9, 9];
let ip2: IpAddress = [8, 8, 8, 8];
let dns_result = wifi.set_dns(ip1, Some(ip2));

defmt::info!("set_dns result: {:?}", dns_result);

let hostname = "github.com";
// let ip_address: IpAddress = [140, 82, 114, 3]; // github.com

let port: Port = 80;
let mode: TransportMode = TransportMode::Tcp;

let mut http_document: String<MAX_HTTP_DOC_LENGTH> = String::from("");
// write!(http_document, "GET / HTTP/1.1\r\nHost: {}.{}.{}.{}:{}\r\nAccept: */*\r\n\r\n",
// ip_address[0],
// ip_address[1],
// ip_address[2],
// ip_address[3],
// port
// ).ok().unwrap();

write!(
http_document,
"GET / HTTP/1.1\r\nHost: {}:{}\r\nAccept: */*\r\n\r\n",
hostname, port
)
.ok()
.unwrap();

if let Err(e) = TcpClient::build(&mut wifi).connect(
hostname,
port,
mode,
&mut delay,
&mut |tcp_client| {
defmt::info!(
"TCP connection to {:?}:{:?} successful",
hostname,
port
);
defmt::info!("Hostname: {:?}", tcp_client.server_hostname());
defmt::info!("Sending HTTP Document: {:?}", http_document.as_str());
match tcp_client.send_data(&http_document) {
Ok(response) => {
defmt::info!("Send Data Response: {:?}", response);
match tcp_client.receive_data() {
Ok(response) => {
defmt::info!("Receive Data Response: {:?}", response)
}

Err(e) => {
defmt::error!("Receive Data Response error: {:?}", e)
}
}

}
Err(e) => {
defmt::error!("Send Data Response error: {:?}", e)
}
}
},
) {
defmt::error!(
"TCP connection to {:?}:{:?} failed: {:?}",
hostname,
port,
e
);
}

delay.delay_ms(100);

defmt::info!("Leaving network: {:?}", SSID);
wifi.leave().ok();
} else if status == ConnectionStatus::Disconnected {
sleep = 20000; // No need to loop as often after disconnecting
}
}
Err(e) => {
defmt::error!("Failed to get connection result: {:?}", e);
}
}
}
}
2 changes: 1 addition & 1 deletion cross/secrets/secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
// all example applications
//

const SSID: &str = "";
const SSID: &str = "Calebphone";
const PASSPHRASE: &str = "";
17 changes: 6 additions & 11 deletions esp32-wroom-rp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ use network::NetworkError;

use protocol::ProtocolError;

const ARRAY_LENGTH_PLACEHOLDER: usize = 8;

/// Highest level error types for this crate.
#[derive(Debug, Eq, PartialEq)]
pub enum Error {
Expand Down Expand Up @@ -212,17 +210,15 @@ pub struct FirmwareVersion {
}

impl FirmwareVersion {
fn new(version: [u8; ARRAY_LENGTH_PLACEHOLDER]) -> FirmwareVersion {
fn new(version: &[u8]) -> FirmwareVersion {
Self::parse(version)
}

// Takes in 8 bytes (e.g. 1.7.4) and returns a FirmwareVersion instance
fn parse(version: [u8; ARRAY_LENGTH_PLACEHOLDER]) -> FirmwareVersion {
let major_version: u8;
let minor_version: u8;
let patch_version: u8;

[major_version, _, minor_version, _, patch_version, _, _, _] = version;
fn parse(version: &[u8]) -> FirmwareVersion {
let major_version: u8 = version[0];
let minor_version: u8 = version[2];
let patch_version: u8 = version[4];

FirmwareVersion {
major: major_version,
Expand All @@ -248,8 +244,7 @@ mod tests {

#[test]
fn firmware_new_returns_a_populated_firmware_struct() {
let firmware_version: FirmwareVersion =
FirmwareVersion::new([0x1, 0x2e, 0x7, 0x2e, 0x4, 0x0, 0x0, 0x0]);
let firmware_version: FirmwareVersion = FirmwareVersion::new(&[0x1, 0x2e, 0x7, 0x2e, 0x4]);

assert_eq!(
firmware_version,
Expand Down
Loading