Skip to content

Instantly share code, notes, and snippets.

@ithinuel
Last active March 29, 2023 21:39
Show Gist options
  • Save ithinuel/d3ec02b4dee849f4740f15fb909efc1a to your computer and use it in GitHub Desktop.
Save ithinuel/d3ec02b4dee849f4740f15fb909efc1a to your computer and use it in GitHub Desktop.
adc to usb-serial example
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "elf2uf2-rs -d"
rustflags = [
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
]
[build]
target = "thumbv6m-none-eabi"
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
}
[package]
name = "sandbox"
version = "0.1.0"
authors = ["Wilfried Chauveau <wilfried.chauveau@ithinuel.me>"]
edition = "2021"
license = "MIT or Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
codegen-units = 1 # better optimizations
#debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
panic = "abort"
opt-level = 's'
[dependencies]
cortex-m-rt = "*"
rtt-target = { version = "*", features = ["cortex-m"] }
panic-halt = "*"
rp-pico = "*"
rp2040-hal = "*"
fugit = "*"
embedded-hal = "*"
usb-device = "*"
usbd-serial = "*"
//! # ADC Example
//!
//! This application demonstrates how to read ADC samples from the temperature
//! sensor and pin and output them to a USB Serial port.
//!
//! It may need to be adapted to your particular board layout and/or pin assignment.
//!
//! See the `Cargo.toml` file for Copyright and license details.
#![no_std]
#![no_main]
// Ensure we halt the program on panic (if we don't mention this crate it won't
// be linked)
use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal;
use usbd_serial::SerialPort;
// Some traits we need
use fugit::ExtU32;
use core::fmt::Write;
use embedded_hal::{adc::OneShot, serial::Write as serial_Write};
use usb_device::{prelude::*, class_prelude::{UsbBusAllocator, UsbBus}};
// A shorter alias for the Peripheral Access Crate, which provides low-level
// register access
use hal::pac;
struct SerialWrapper<'b, B: UsbBus>(SerialPort<'b, B>);
impl<B: UsbBus> core::fmt::Write for SerialWrapper<'_, B> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
let _ = self.0.write(s.as_bytes());
Ok(())
}
}
#[rp_pico::entry]
fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::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(
rp_pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
// 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,
);
// Set up the USB driver
let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new(
pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut pac.RESETS,
));
// Set up the USB Communications Class Device driver
let mut serial = SerialPort::new(&usb_bus);
// Create a USB device with a fake VID and PID
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(2) // from: https://www.usb.org/defined-class-codes
.build();
// Write to the UART
let _ = serial.write(b"ADC example\r\n");
let mut serial = SerialWrapper(serial);
// Enable ADC
let mut adc = hal::Adc::new(pac.ADC, &mut pac.RESETS);
// Enable the temperature sense channel
let mut temperature_sensor = adc.enable_temp_sensor();
// Configure GPIO26 as an ADC input
let mut adc_pin_0 = pins.gpio26.into_floating_input();
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
let mut next_sample = timer.get_counter() + 1u32.secs();
loop {
let now = timer.get_counter();
if now >= next_sample {
// Read the raw ADC counts from the temperature sensor channel.
let temp_sens_adc_counts: u16 = adc.read(&mut temperature_sensor).unwrap();
let pin_adc_counts: u16 = adc.read(&mut adc_pin_0).unwrap();
writeln!(
serial,
"ADC readings: Temperature: {temp_sens_adc_counts:02} Pin: {pin_adc_counts:02}\r\n"
)
.unwrap();
next_sample = now + 1u32.secs();
}
// Check for new data
if usb_dev.poll(&mut [&mut serial.0]) {
let mut buf = [0u8; 64];
let _ = serial.0.read(&mut buf);
}
}
}
// End of file
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;
SECTIONS {
.panic_dump (NOLOAD):
{
_panic_dump_start = .;
. = _panic_dump_start + 1K;
_panic_dump_end = .;
} > RAM
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment