Просмотр исходного кода

add files recovered from previous attempt.

banshee 1 год назад
Родитель
Сommit
50550525da
7 измененных файлов с 728 добавлено и 0 удалено
  1. 28 0
      .cargo/config.toml
  2. 108 0
      Cargo.toml
  3. 39 0
      Embed.toml
  4. 31 0
      build.rs
  5. 15 0
      memory.x
  6. 42 0
      src/fmt.rs
  7. 465 0
      src/main.rs

+ 28 - 0
.cargo/config.toml

@@ -0,0 +1,28 @@
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
+# Choose a default "cargo run" tool:
+# - probe-run provides flashing and defmt via a hardware debugger, and stack unwind on panic
+# - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode
+# - "probe-rs-cli run" is similar to probe-run but it uses the latest probe-rs lib crate
+# runner = "probe-run --chip RP2040"
+runner = "elf2uf2-rs -d"
+# runner = "probe-rs-cli run --chip RP2040 --protocol swd"
+
+rustflags = [
+  "-C", "linker=flip-link",
+  "-C", "link-arg=--nmagic",
+  "-C", "link-arg=-Tlink.x",
+  "-C", "link-arg=-Tdefmt.x",
+
+  # Code-size optimizations.
+  #   trap unreachable can save a lot of space, but requires nightly compiler.
+  #   uncomment the next line if you wish to enable it
+  # "-Z", "trap-unreachable=no",
+  "-C", "inline-threshold=5",
+  "-C", "no-vectorize-loops",
+]
+
+[build]
+target = "thumbv6m-none-eabi"
+
+[env]
+DEFMT_LOG = "debug"

+ 108 - 0
Cargo.toml

@@ -0,0 +1,108 @@
+[package]
+authors = ["Several and Joao carvalho"]
+edition = "2018"
+readme = "README.md"
+name = "rp2040-project-template"
+version = "0.1.0"
+resolver = "2"
+
+[dependencies]
+cortex-m = "0.7.3"
+cortex-m-rt = "0.7.0"
+embedded-hal = { version = "0.2.5", features=["unproven"] }
+embedded-time = "0.12.0"
+
+# jnc
+usb-device = "0.2.8"
+usbd-serial = "0.1.1"
+usbd-hid = "0.5.1"
+futures = { version = "0.3", default-features = false, optional = true }
+
+# jnc commnet pico-probe
+defmt = "0.3.0"
+defmt-rtt = "0.3.1"
+panic-probe = { version = "0.3.0", features = ["print-defmt"] }
+
+# We're using a Pico by default on this template
+rp-pico = "0.2.0"
+
+# but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead
+# sparkfun-pro-micro-rp2040 = "0.1.0"
+
+# If you're not going to use a Board Support Package you'll need these:
+rp2040-hal = { version="0.3.0", features=["rt"] }
+# rp2040-hal = { path = "../rp-hal-main/rp2040-hal", version = "0.4.0" }
+
+rp2040-boot2 = {version="0.2.0", optional = true }
+
+
+# [dev-dependencies]
+panic-halt= "0.2.0"
+# embedded-hal ="0.2.5"
+# cortex-m-rtic = "0.6.0-rc.4"
+# nb = "1.0"
+# heapless = "0.7.9"
+
+# jnc commented for test pico-probe 
+# defmt = "0.3.0"
+# defmt-rtt = "0.3.0"
+
+
+# cortex-m-rtic = "0.6.0-rc.4"
+cortex-m-rtic = "1.0.0"
+
+# static-box = "0.2.0"
+
+
+
+# cargo build/run
+[profile.dev]
+codegen-units = 1
+debug = 2
+debug-assertions = true
+incremental = false
+opt-level = 3
+overflow-checks = true
+
+# cargo build/run --release
+[profile.release]
+codegen-units = 1
+debug = 2
+debug-assertions = false
+incremental = false
+lto = 'fat'
+opt-level = 3
+overflow-checks = false
+
+# do not optimize proc-macro crates = faster builds from scratch
+[profile.dev.build-override]
+codegen-units = 8
+debug = false
+debug-assertions = false
+opt-level = 0
+overflow-checks = false
+
+[profile.release.build-override]
+codegen-units = 8
+debug = false
+debug-assertions = false
+opt-level = 0
+overflow-checks = false
+
+# cargo test
+[profile.test]
+codegen-units = 1
+debug = 2
+debug-assertions = true
+incremental = false
+opt-level = 3
+overflow-checks = true
+
+# cargo test --release
+[profile.bench]
+codegen-units = 1
+debug = 2
+debug-assertions = false
+incremental = false
+lto = 'fat'
+opt-level = 3

+ 39 - 0
Embed.toml

@@ -0,0 +1,39 @@
+[default.probe]
+protocol = "Swd"
+speed = 20000
+# If you only have one probe cargo embed will pick automatically
+# Otherwise: add your probe's VID/PID/serial to filter
+
+## rust-dap
+# usb_vid = "6666"
+# usb_pid = "4444"
+# serial = "test"
+
+
+[default.flashing]
+enabled = true
+
+[default.reset]
+enabled = true
+halt_afterwards = false
+
+[default.general]
+chip = "RP2040"
+log_level = "WARN"
+# RP2040 does not support connect_under_reset
+connect_under_reset = false
+
+[default.rtt]
+enabled = true
+up_mode = "NoBlockSkip"
+channels = [
+    { up = 0, down = 0, name = "name", up_mode = "NoBlockSkip", format = "Defmt" },
+]
+timeout = 3000
+show_timestamps = true
+log_enabled = false
+log_path = "./logs"
+
+[default.gdb]
+enabled = false
+gdb_connection_string = "127.0.0.1:2345"

+ 31 - 0
build.rs

@@ -0,0 +1,31 @@
+//! This build script copies the `memory.x` file from the crate root into
+//! a directory where the linker can always find it at build time.
+//! For many projects this is optional, as the linker always searches the
+//! project root directory -- wherever `Cargo.toml` is. However, if you
+//! are using a workspace or have a more complicated build setup, this
+//! build script becomes required. Additionally, by requesting that
+//! Cargo re-run the build script whenever `memory.x` is changed,
+//! updating `memory.x` ensures a rebuild of the application with the
+//! new memory settings.
+
+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");
+}

+ 15 - 0
memory.x

@@ -0,0 +1,15 @@
+MEMORY {
+    BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
+    FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
+    RAM   : ORIGIN = 0x20000000, LENGTH = 256K
+}
+
+EXTERN(BOOT2_FIRMWARE)
+
+SECTIONS {
+    /* ### Boot loader */
+    .boot2 ORIGIN(BOOT2) :
+    {
+        KEEP(*(.boot2));
+    } > BOOT2
+} INSERT BEFORE .text;

+ 42 - 0
src/fmt.rs

@@ -0,0 +1,42 @@
+// NOTE: This file came from:
+//       https://github.com/Nashenas88/dactyl-manuform-kb2040-rs/blob/main/src/fmt.rs
+
+//! Formatting module for helping with logging over a serial connection. This
+//! is useful on the kb2040 since there are no debugging pins exposed on the
+//! board.
+
+use core::fmt;
+
+pub(crate) struct Wrapper<'a> {
+    buf: &'a mut [u8],
+    offset: usize,
+}
+
+impl<'a> Wrapper<'a> {
+    pub(crate) fn new(buf: &'a mut [u8]) -> Self {
+        Wrapper { buf, offset: 0 }
+    }
+}
+
+impl<'a> fmt::Write for Wrapper<'a> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        let bytes = s.as_bytes();
+
+        // Skip over already-copied data.
+        let remainder = &mut self.buf[self.offset..];
+        // Check if there is space remaining (return error instead of panicking).
+        if remainder.len() < bytes.len() {
+            return Err(core::fmt::Error);
+        }
+
+        // Make the two slices the same length.
+        let remainder = &mut remainder[..bytes.len()];
+        // Copy.
+        remainder.copy_from_slice(bytes);
+
+        // Update offset to avoid overwriting.
+        self.offset += bytes.len();
+
+        Ok(())
+    }
+}

+ 465 - 0
src/main.rs

@@ -0,0 +1,465 @@
+#![no_std]
+#![no_main]
+
+use defmt_rtt as _;
+use panic_halt as _;
+
+mod fmt;
+
+#[rtic::app(device = rp_pico::hal::pac, peripherals = true)]
+mod app {
+
+    use crate::fmt::Wrapper;
+    use core::fmt::Write;
+    use embedded_hal::digital::v2::OutputPin;
+    use embedded_time::duration::Extensions;
+
+    use rp_pico::hal;
+    use rp_pico::pac;
+    use rp_pico::XOSC_CRYSTAL_FREQ;
+
+    // USB Device support
+    use usb_device::{class_prelude::*, prelude::*};
+    // USB Communications Class Device support
+    use usbd_serial::SerialPort;
+
+    // Blink time 5 seconds
+    const SCAN_TIME_US: u32 = 500000; //  200000; // 5000000;  // 1000000; // 200000;
+
+    pub struct Counter {
+        counter: u32,
+        enable: bool,
+    }
+
+    impl Counter {
+        fn new() -> Self {
+            Counter {
+                counter: 0_u32,
+                enable: true,
+            }
+        }
+
+        fn get(&self) -> u32 {
+            self.counter
+        }
+
+        fn reset(&mut self) {
+            self.counter = 0_u32;
+        }
+
+        fn increment(&mut self) {
+            self.counter += 1_u32;
+        }
+
+        fn enable(&mut self, state: bool) {
+            self.enable = state;
+        }
+    }
+
+    #[shared]
+    struct Shared {
+        timer: hal::Timer,
+        alarm: hal::timer::Alarm0,
+        led: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
+        led_blink_enable: bool,
+
+        serial: SerialPort<'static, hal::usb::UsbBus>,
+        usb_dev: usb_device::device::UsbDevice<'static, hal::usb::UsbBus>,
+
+        counter: Counter,
+    }
+
+    #[local]
+    struct Local {}
+
+    #[init(local = [usb_bus: Option<usb_device::bus::UsbBusAllocator<hal::usb::UsbBus>> = None])]
+    fn init(c: init::Context) -> (Shared, Local, init::Monotonics) {
+        //*******
+        // Initialization of the system clock.
+
+        let mut resets = c.device.RESETS;
+        let mut watchdog = hal::watchdog::Watchdog::new(c.device.WATCHDOG);
+
+        // Configure the clocks - The default is to generate a 125 MHz system clock
+        let clocks = hal::clocks::init_clocks_and_plls(
+            XOSC_CRYSTAL_FREQ,
+            c.device.XOSC,
+            c.device.CLOCKS,
+            c.device.PLL_SYS,
+            c.device.PLL_USB,
+            &mut resets,
+            &mut watchdog,
+        )
+        .ok()
+        .unwrap();
+
+        //*******
+        // Initialization of the USB and Serial and USB Device ID.
+
+        // USB
+        //
+        // Set up the USB driver
+        // The bus that is used to manage the device and class below.
+        let usb_bus: &'static _ =
+            c.local
+                .usb_bus
+                .insert(UsbBusAllocator::new(hal::usb::UsbBus::new(
+                    c.device.USBCTRL_REGS,
+                    c.device.USBCTRL_DPRAM,
+                    clocks.usb_clock,
+                    true,
+                    &mut resets,
+                )));
+
+        // Set up the USB Communications Class Device driver.
+        let serial = SerialPort::new(usb_bus);
+
+        // Create a USB device with a fake VID and PID
+        let 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();
+
+        //*******
+        // Initialization of the LED GPIO and the timer.
+
+        let sio = hal::Sio::new(c.device.SIO);
+        let pins = rp_pico::Pins::new(
+            c.device.IO_BANK0,
+            c.device.PADS_BANK0,
+            sio.gpio_bank0,
+            &mut resets,
+        );
+        let mut led = pins.led.into_push_pull_output();
+        led.set_low().unwrap();
+
+        let mut timer = hal::Timer::new(c.device.TIMER, &mut resets);
+        let mut alarm = timer.alarm_0().unwrap();
+        let _ = alarm.schedule(SCAN_TIME_US.microseconds());
+        alarm.enable_interrupt(&mut timer);
+
+        // Enable led_blink.
+        let led_blink_enable = true;
+
+        // Reset the counter
+        let counter = Counter::new();
+
+        //********
+        // Return the Shared variables struct, the Local variables struct and the XPTO Monitonics
+        //    (Note: Read again the RTIC book in the section of Monotonics timers)
+        (
+            Shared {
+                timer,
+                alarm,
+                led,
+                led_blink_enable,
+
+                serial,
+                usb_dev,
+
+                counter,
+            },
+            Local {},
+            init::Monotonics(),
+        )
+    }
+
+    /// Task that blinks the rp-pico onboard LED and that send a message "LED ON!" and "LED OFF!" do USB-Serial.
+    #[task(
+        binds = TIMER_IRQ_0,
+        priority = 1,
+        shared = [timer, alarm, led, led_blink_enable,  serial, counter],
+        local = [tog: bool = true],
+    )]
+    fn timer_irq(mut cx: timer_irq::Context) {
+        let mut buf = [0u8; 64];
+
+        let led = cx.shared.led;
+        let led_blink_enable = cx.shared.led_blink_enable;
+        let counter = cx.shared.counter;
+
+        let tog = cx.local.tog;
+
+        // Blinks the LED ON / OFF.
+        (led, led_blink_enable, counter).lock(|led_a, led_blink_enable_a, counter_a| {
+            let led_state_str: &str;
+            if *led_blink_enable_a {
+                if *tog {
+                    led_a.set_high().unwrap();
+                    led_state_str = "ON ";
+                } else {
+                    led_a.set_low().unwrap();
+                    led_state_str = "OFF";
+                }
+                let _ = writeln!(
+                    Wrapper::new(&mut buf),
+                    "LED {}!   counter = {}",
+                    led_state_str,
+                    counter_a.get()
+                );
+            }
+            if counter_a.enable {
+                counter_a.increment();
+            }
+
+            if *led_blink_enable_a {
+                *tog = !*tog;
+            }
+        });
+
+        // Clears the timer interrupt and Set's the new delta_time in the future.
+        let mut timer = cx.shared.timer;
+        let mut alarm = cx.shared.alarm;
+        (alarm).lock(|a| {
+            (timer).lock(|timer_a| {
+                a.clear_interrupt(timer_a);
+                let _ = a.schedule(SCAN_TIME_US.microseconds());
+            });
+        });
+
+        // Write the message "blabla! 2" do USB-Serial.
+        cx.shared.serial.lock(|s| {
+            write_serial(s, unsafe { core::str::from_utf8_unchecked(&buf) }, false);
+        });
+
+        /*
+        // Write the message "blabla! 2" do USB-Serial.
+        c.shared.serial.lock(|s| {
+            let mut buf = [0u8; 64];
+            let _ = writeln!(Wrapper::new(&mut buf), "blabla! {}", 2); /*"{:?}"*/
+            write_serial(s, unsafe { core::str::from_utf8_unchecked(&buf) }, false);
+        });
+        */
+    }
+
+    /// Usb interrupt handler. Runs every time the host requests new data.
+    #[task(binds = USBCTRL_IRQ, priority = 3, shared = [led, led_blink_enable, serial, usb_dev, counter])]
+    fn usb_rx(cx: usb_rx::Context) {
+        let led = cx.shared.led;
+        let led_blink_enable = cx.shared.led_blink_enable;
+
+        let usb_dev = cx.shared.usb_dev;
+        let serial = cx.shared.serial;
+        let counter = cx.shared.counter;
+
+        (led, led_blink_enable, usb_dev, serial, counter).lock(
+            |led_a, led_blink_enable_a, usb_dev_a, serial_a, counter_a| {
+                // Check for new data
+                if usb_dev_a.poll(&mut [serial_a]) {
+                    let mut buf = [0u8; 64];
+                    match serial_a.read(&mut buf) {
+                        Err(_e) => {
+                            // Do nothing
+                            // let _ = serial_a.write(b"Error.");
+                            // let _ = serial_a.flush();
+                        }
+                        Ok(0) => {
+                            // Do nothing
+                            let _ = serial_a.write(b"Didn't received data.");
+                            let _ = serial_a.flush();
+                        }
+                        Ok(_count) => {
+                            match_usb_serial_buf(
+                                &buf,
+                                led_a,
+                                led_blink_enable_a,
+                                serial_a,
+                                counter_a,
+                            );
+                        }
+                    }
+                }
+            },
+        );
+    }
+
+    // Task with least priority that only runs when nothing else is running.
+    #[idle(local = [x: u32 = 0])]
+    fn idle(_cx: idle::Context) -> ! {
+        // Locals in idle have lifetime 'static
+        // let _x: &'static mut u32 = cx.local.x;
+
+        //hprintln!("idle").unwrap();
+
+        loop {
+            cortex_m::asm::nop();
+        }
+    }
+
+    /* New Tasks */
+
+    /// This function come from the github with USB-Serial example (see link above).
+    ///
+    /// Helper function to ensure all data is written across the serial interface.
+    fn write_serial(serial: &mut SerialPort<'static, hal::usb::UsbBus>, buf: &str, block: bool) {
+        let write_ptr = buf.as_bytes();
+
+        // Because the buffer is of constant size and initialized to zero (0) we here
+        // add a test to determine the size that's really occupied by the str that we
+        // wan't to send. From index zero to first byte that is as the zero byte value.
+        let mut index = 0;
+        while index < write_ptr.len() && write_ptr[index] != 0 {
+            index += 1;
+        }
+        let mut write_ptr = &write_ptr[0..index];
+
+        while !write_ptr.is_empty() {
+            match serial.write(write_ptr) {
+                Ok(len) => write_ptr = &write_ptr[len..],
+                // Meaning the USB write buffer is full
+                Err(UsbError::WouldBlock) => {
+                    if !block {
+                        break;
+                    }
+                }
+                // On error, just drop unwritten data.
+                Err(_) => break,
+            }
+        }
+        // let _ = serial.write("\n".as_bytes());
+        let _ = serial.flush();
+    }
+
+    fn match_usb_serial_buf(
+        buf: &[u8; 64],
+        led: &mut hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
+        led_blink_enable: &mut bool,
+        serial: &mut SerialPort<'static, hal::usb::UsbBus>,
+        counter: &mut Counter,
+    ) {
+        let _buf_len = buf.len();
+        match buf[0] {
+            // Print Menu
+            b'M' | b'm' => {
+                write_serial(serial, "M - Print Menu\n", false);
+                print_menu(serial);
+            }
+            // 0 - Reset counter
+            b'0' => {
+                write_serial(serial, "M - Print Menu\n", false);
+                counter.reset();
+            }
+            // 1 - Increment counter
+            b'1' => {
+                write_serial(serial, "1 - Increment counter\n", false);
+                counter.increment();
+            }
+            // 2 - Start continues counter
+            b'2' => {
+                write_serial(serial, "2 - Start continues counter\n", false);
+                counter.enable(true);
+            }
+            // 3 - Stop continues counter
+            b'3' => {
+                write_serial(serial, "3 - Stop continues counter\n", false);
+                counter.enable(false);
+            }
+            // 4 - Get switch and LED state
+            b'4' => {
+                write_serial(serial, "4 - Get switch and LED state\n", false);
+
+                // GPIO 25 onboard LED, we are going to read the bit 8 of the gpio_status register.
+                //  OUTFROMPERI - output signal from selected peripheral, before register
+                //                override is applied.
+                // See pag 272 of the Pico Datasets:
+                // https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#_gpio_functions
+
+                let led_status_reg =
+                    unsafe { (*pac::IO_BANK0::ptr()).gpio[25].gpio_status.read().bits() };
+
+                // Reserved bit.
+                // let sio_pin_value = unsafe { (*pac::SIO::ptr()).gpio_out.read().bits() };
+
+                let (led_bool, led_status) = if ((led_status_reg & 1 << 8) >> 8) == 1_u32 {
+                    (true, "ON")
+                } else {
+                    (false, "OFF")
+                };
+
+                let mut buf = [0u8; 64];
+                let _ = writeln!(
+                    Wrapper::new(&mut buf),
+                    "LED Status {:b}, {}   LED {}",
+                    led_status_reg,
+                    led_bool,
+                    led_status
+                );
+                write_serial(
+                    serial,
+                    unsafe { core::str::from_utf8_unchecked(&buf) },
+                    false,
+                );
+
+                // unsafe { (*pac::TIMER::ptr()).timerawh.read().bits() };
+            }
+            // 5 - Set LED on
+            b'5' => {
+                write_serial(serial, "5 - Set LED on\n", false);
+                *led_blink_enable = false;
+                let _ = led.set_high();
+            }
+            // 6 - Set LED off
+            b'6' => {
+                write_serial(serial, "6 - Set LED off\n", false);
+                *led_blink_enable = false;
+                let _ = led.set_low();
+            }
+            // 7 - Set LED blink enable
+            b'7' => {
+                write_serial(serial, "7 - Set LED blink enable\n", false);
+                *led_blink_enable = true;
+            }
+            b'8' => {
+                write_serial(serial, "8 - Display data rate\n", false);
+
+                let data_rate = serial.line_coding().data_rate();
+                let mut buf = [0u8; 64];
+                let _ = writeln!(Wrapper::new(&mut buf), "Data rate: {} bit/s", data_rate);
+                write_serial(
+                    serial,
+                    unsafe { core::str::from_utf8_unchecked(&buf) },
+                    false,
+                );
+            }
+            _ => {
+                write_serial(
+                    serial,
+                    unsafe { core::str::from_utf8_unchecked(buf) },
+                    false,
+                );
+                write_serial(serial, "Invalid option!\n", false);
+            }
+        }
+    }
+
+    fn print_menu(serial: &mut SerialPort<'static, hal::usb::UsbBus>) {
+        let mut _buf = [0u8; 273];
+
+        // Create the Menu.
+        let menu_str = "*****************
+*  Menu:
+*
+*  M / m - Print menu
+*    0   - Reset counter
+*    1   - Increment counter
+*    2   - Start continues counter
+*    3   - Stop continues counter
+*    4   - Get switch and LED state
+*    5   - Set LED on
+*    6   - Set LED off
+*    7   - Set LED blink enable
+*    8   - Display data rate
+*****************
+Enter option: ";
+
+        write_serial(serial, menu_str, true);
+
+        // Send out the data to USB-Serial.
+        // let _ = serial.write(menu_str);
+
+        // let _ = writeln!(Wrapper::new(&mut buf), &menu_str);
+        // write_serial(serial, unsafe { core::str::from_utf8_unchecked(menu_str) });
+    }
+}