Skip to content

Commit

Permalink
add avail_data_tcp implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
calebbourg committed Feb 17, 2023
1 parent 34aa554 commit cc4c417
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 3 deletions.
3 changes: 2 additions & 1 deletion cross/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ members = [
"dns",
"get_fw_version",
"join",
"send_data_tcp"
"send_data_tcp",
"receive_data_tcp"
]

[profile.dev]
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.0"
description = "Example RP2040 target application that demonstrates how to receive data from a remote server over TCP."

# 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.1"
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 = []
214 changes: 214 additions & 0 deletions cross/receive_data_tcp/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
//! # 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(result) => {
defmt::info!("Data sent successfully: {:?}", result);
defmt::info!("Receiving Response");

match tcp_client.receive_data() {
Ok(response) => { defmt::info!("Response: {:?}", response); }
Err(e) => { defmt::info!("Error receiving data: {:?}", e); }
}
}
Err(e) => {
defmt::error!("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);
}
}
}
}
10 changes: 9 additions & 1 deletion esp32-wroom-rp/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub(crate) enum NinaCommand {
SetPassphrase = 0x11u8,
SetDNSConfig = 0x15u8,
GetConnStatus = 0x20u8,
AvailDataTcp = 0x2bu8,
StartClientTcp = 0x2du8,
StopClientTcp = 0x2eu8,
GetClientStateTcp = 0x2fu8,
Expand Down Expand Up @@ -392,7 +393,7 @@ pub(crate) trait ProtocolInterface {
fn get_conn_status(&mut self) -> Result<ConnectionStatus, Error>;
fn set_dns_config(&mut self, dns1: IpAddress, dns2: Option<IpAddress>) -> Result<(), Error>;
fn req_host_by_name(&mut self, hostname: &str) -> Result<u8, Error>;
fn get_host_by_name(&mut self) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error>;
fn get_host_by_name(&mut self) -> Result<NinaResponseBuffer, Error>;
fn resolve(&mut self, hostname: &str) -> Result<IpAddress, Error>;
fn get_socket(&mut self) -> Result<Socket, Error>;
fn start_client_tcp(
Expand All @@ -405,6 +406,13 @@ pub(crate) trait ProtocolInterface {
fn stop_client_tcp(&mut self, socket: Socket, _mode: &TransportMode) -> Result<(), Error>;
fn get_client_state_tcp(&mut self, socket: Socket) -> Result<ConnectionState, Error>;
fn send_data(&mut self, data: &str, socket: Socket) -> Result<[u8; 1], Error>;
fn receive_data(&mut self, socket: Socket) -> Result<NinaResponseBuffer, Error>;
fn avail_data_tcp(&mut self, socket: Socket) -> Result<usize, Error>;
fn get_data_buf_tcp(
&mut self,
socket: Socket,
available_length: usize,
) -> Result<NinaResponseBuffer, Error>;
}

#[derive(Debug)]
Expand Down
Loading

0 comments on commit cc4c417

Please sign in to comment.