build: init project with avr_hal setup and target

Added avr_han project structure with arch definition and cargo config.
Remember to switch to nightly!
Added a basic initial project, with 4 leds (1 for CPU core). Each led
grows in intensity depending on CPU core load. Added a py script to
generate cpu load data on serial port.
This commit is contained in:
əlemi 2022-08-10 03:44:15 +02:00
commit e400459168
No known key found for this signature in database
GPG key ID: BBCBFE5D7244634E
9 changed files with 193 additions and 0 deletions

8
.cargo/config.toml Normal file
View file

@ -0,0 +1,8 @@
[build]
target = "avr-atmega328p.json"
[target.'cfg(target_arch = "avr")']
runner = "ravedude nano --open-console --baudrate 57600 -P /dev/ttyUSB0"
[unstable]
build-std = ["core"]

7
.editorconfig Normal file
View file

@ -0,0 +1,7 @@
# Default to Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
indent_size = 2

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
Cargo.lock
/target

1
.rustfmt.toml Normal file
View file

@ -0,0 +1 @@
hard_tabs = true

35
Cargo.toml Normal file
View file

@ -0,0 +1,35 @@
[package]
name = "pc-monitor"
version = "0.1.0"
authors = ["alemidev <me@alemi.dev>"]
edition = "2021"
[[bin]]
name = "pc-monitor"
test = false
bench = false
[dependencies]
panic-halt = "0.2.0"
ufmt = "0.1.0"
nb = "1"
embedded-hal = "0.2.3"
embedded-msgpack = "0.2"
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"
rev = "1aacefb335517f85d0de858231e11055d9768cdf"
features = ["arduino-nano"]
# Configure the build for minimal size - AVRs have very little program memory
[profile.dev]
panic = "abort"
lto = true
opt-level = "s"
[profile.release]
panic = "abort"
codegen-units = 1
debug = true
lto = true
opt-level = "s"

25
avr-atmega328p.json Normal file
View file

@ -0,0 +1,25 @@
{
"arch": "avr",
"atomic-cas": false,
"cpu": "atmega328p",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"eh-frame-header": false,
"exe-suffix": ".elf",
"executables": true,
"late-link-args": {
"gcc": [
"-lgcc"
]
},
"linker": "avr-gcc",
"llvm-target": "avr-unknown-unknown",
"max-atomic-width": 8,
"no-default-libraries": false,
"pre-link-args": {
"gcc": [
"-mmcu=atmega328p"
]
},
"target-c-int-width": "16",
"target-pointer-width": "16"
}

22
script/cpu-usage.py Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env python
from time import sleep
import struct
import serial
import psutil
def avg_usage_to_serial(dev:str):
port = serial.Serial(dev, baudrate=57600)
while True:
# Map float [0:100] to int [0:255], square it to put more values in the lower end, where led is more sensible
load = [ int(((x/100) **2) * 255) for x in psutil.cpu_percent(0.1, percpu=True) ] # mypy whines but percpu returns a list
port.write(struct.pack("BBBB", *load))
port.flush()
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("[!] No device specified")
else:
avg_usage_to_serial(sys.argv[1])

2
script/requirements.txt Normal file
View file

@ -0,0 +1,2 @@
psutil
pyserial

91
src/main.rs Normal file
View file

@ -0,0 +1,91 @@
#![no_std]
#![no_main]
use panic_halt as _;
use embedded_hal::serial::Read;
use arduino_hal::{simple_pwm::*, port::{Pin, mode::{PwmOutput, PullUp, Input}}, hal::port::{PD3, PB1, PB2, PB3, PD2}};
// TODO can I make it a generic "Pin" and use a slice?
struct FourLedDisplay {
led1: Pin<PwmOutput<Timer2Pwm>, PD3>,
led2: Pin<PwmOutput<Timer1Pwm>, PB1>,
led3: Pin<PwmOutput<Timer1Pwm>, PB2>,
led4: Pin<PwmOutput<Timer2Pwm>, PB3>,
button: Pin<Input<PullUp>, PD2>,
counter: u8,
}
impl FourLedDisplay {
fn new(
led1: Pin<PwmOutput<Timer2Pwm>, PD3>,
led2: Pin<PwmOutput<Timer1Pwm>, PB1>,
led3: Pin<PwmOutput<Timer1Pwm>, PB2>,
led4: Pin<PwmOutput<Timer2Pwm>, PB3>,
button: Pin<Input<PullUp>, PD2>,
) -> Self {
FourLedDisplay{
led1, led2, led3, led4, button,
counter: 0,
}
}
fn update(&mut self, value: u8) {
match self.counter {
0 => self.led1.set_duty(value),
1 => self.led2.set_duty(value),
2 => self.led3.set_duty(value),
3 => self.led4.set_duty(value),
_ => {},
}
self.counter = (self.counter + 1) % 4;
}
fn init(mut self) -> Self {
self.led1.enable();
self.led2.enable();
self.led3.enable();
self.led4.enable();
self
}
fn should_reset(&self) -> bool { self.button.is_low() }
fn reset(&mut self) {
self.counter = 0;
self.led1.set_duty(0);
self.led2.set_duty(0);
self.led3.set_duty(0);
self.led4.set_duty(0);
}
}
#[arduino_hal::entry]
fn main() -> ! {
// init board peripherals
let dp = arduino_hal::Peripherals::take().unwrap();
let timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale8);
let timer2 = Timer2Pwm::new(dp.TC2, Prescaler::Prescale8);
let pins = arduino_hal::pins!(dp);
let led1 = pins.d3.into_output().into_pwm(&timer2);
let led2 = pins.d9.into_output().into_pwm(&timer1);
let led3 = pins.d10.into_output().into_pwm(&timer1);
let led4 = pins.d11.into_output().into_pwm(&timer2);
let button = pins.d2.into_pull_up_input();
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);
// prepare display struct
let mut display = FourLedDisplay::new(led1, led2, led3, led4, button).init();
loop { // main loop
if display.should_reset() {
display.reset();
} else {
match serial.read() {
Ok(value) => display.update(value),
Err(_) => {},
}
}
}
}