Avr-hal on Arduino-Uno

Hello Rusty Ladies and Gentleman,

As per yesterday night I started to experiment with micro-controllers and Rust. I cannot get my Uno clone to blink (yes, I will buy proper hardware soon) with this super simple example.

This is everything I did step by step - please ignore step 1 to 7, I just want to remember all the steps when I run into similar issues again.

  1. Clone the source: avr-hal repo.

  2. Fear not, install and set nightly.

  3. The terminal complains:
    error: "/Users/ai/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/Cargo.lock"
    Solved by: rustup component add rust-src

  4. the terminal is still not satisfied: error: linker avr-gcc not found

tenor

Solved with:
brew tap osx-cross/avr
brew install avr-gcc

  1. get in the right directory avr-hal/boards/arduino-uno/examples and run:
    cargo +nightly build --example uno-blink
    This compiles now.

  2. run ../../mkhex.sh --debug uno-blink, and the terminal complains again:
    ../../mkhex.sh: line 18: realpath: command not found
    Solve by running brew install coreutils.

step 6. now compiles:
../../mkhex.sh --debug uno-blink
../../target/avr-atmega328p/debug/examples/uno-blink.elf:
1.1K Bytes used (1019 exact).

NOW TO THE PROBLEM!

  1. run ls -l ../../target/uno-blink.hex
    ... and the leds are not blinking :see_no_evil:! I mean neither my leds, neither the L led onboard.

I see that the digital pin 13 is on:

    // Digital pin 13 is also connected to an onboard LED marked "L"
    let mut led = pins.d13.into_output(&mut pins.ddr);
  1. At that point I try another LED, and another clone on which I flash the example program. The L on the board stops shining when I put the led in GPIO 13 byt still no sucess.

This is the full code if it can be of any help:

#![no_std]
#![no_main]

extern crate panic_halt;
use arduino_uno::prelude::*;

#[arduino_uno::entry]
fn main() -> ! {
    let dp = arduino_uno::Peripherals::take().unwrap();

    let mut delay = arduino_uno::Delay::new();
    let mut pins = arduino_uno::Pins::new(
        dp.PORTB,
        dp.PORTC,
        dp.PORTD,
    );

    // Digital pin 13 is also connected to an onboard LED marked "L"
    let mut led = pins.d13.into_output(&mut pins.ddr);

    led.set_high().void_unwrap();

    loop {
        led.toggle().void_unwrap();
        delay.delay_ms(200 as u16);
        led.toggle().void_unwrap();
        delay.delay_ms(200 as u16);
        led.toggle().void_unwrap();
        delay.delay_ms(200 as u16);
        led.toggle().void_unwrap();
        delay.delay_ms(200 as u16);
    }
}

I don't know where to start tlooking. With two boards not blinking but a program that compiles, where shall I start looking for debugging?

Ok, so I know what it was :relieved: :relieved: :relieved:!
I post it to the attention of amnesia-striken-future-me (oh hello :wave:t5:!) or anyone, really who is testing avr-hal :laughing:

You have to install avrdude ( :beer: brew it), and then run (in that specific case)(so uno-blink is the hex file which was generated...)

avrdude -p atmega328p -c arduino -P /dev/tty.usbserial-14440 -U flash:w:uno-blink.hex:i

To get which USB you are connected into use /dev/tty run ls /dev/tty* | grep usb

To run your own project, after following the instructions you need to:

  • cargo +nightly build

  • find your executable with find . -type f -perm +0111 -print (hint, it will probably be in target/debug)

  • lastly, when running avrdude, the binary file is not a hex file but an elf file :elf:t5: :fairy:t2:. Yes my friend, you are looking to arvdude an elf. Not an hex. This is funny only in Swedish coz a hex sounds like a witch :woman_mage:t5:. Sorry I am very tired.

Let me get this straight. One can program the good old 8 bit AVR processors in Rust?

If so, frikken wow! I'm stunned!

This last year my Rust usage has spread from cloud servers, to PC CLI applications to small embedded remote devices running Linux.

It just so happens this last week I got a requirement for a super simple, cheap, small micro-controller program. Looks like my Rust usage is moving another step down the chain...

2 Likes

My friend I confess I have no idea what you are talking about! I did not know it was oldschool!

That is very impressive indeed! It gives me hope!

Ah well. That atmega328p chip you are programming is made by Microchip. Originally by Atemel, who were bought by Microchip a few years ago.

It is one of many such chips using Atmel's AVR RISC CPU architecture. Which was first marketed in 1996.

https://en.wikipedia.org/wiki/AVR_microcontrollers#:~:text=The%20AVR%208-bit%20microcontroller,and%20featured%20ATmega8%20AVR%20microcontrollers.

The fact that Rust can be used to program 8 bit machines, with such tiny amounts of memory is amazing. I always had a soft spot for the AVRs.

So now I know more :slight_smile:. I thought it was pretty recent, specially made for arduino uno...

The Arduino is (or at least was) nothing more than an Atmel AVR chip on a simple board.

The "secret sauce" of Arduino, apart from the size, shape and external pin layout of the Arduino board is not the chip it uses but the Arduino IDE and libraries used to program it.

As far as I can tell, now that you are using the AVR target for the Rust tool chain and avrdude to program it then there is nothing "Arduino" in what you are doing.

Unless, perhaps, the whole show still relies on having an Arduino boot loader in the chip before you start.

Curious.

Yes I noticed that. I tried it after PIC32 and everything seemed super-easy.

I don't understand the question.

It used to be that if you bought a naked chip, like an ATMEL atmega... whatever, you had no way to get any program into it except by using the vendor supplied tool that could download code to the chip. Usually via some vendor supplied hardware 'dongle' that would interface your PC to you chip.

This was of course horribly complicated and expensive. So normal people never got to use micro-controllers like the AVR.

Enter the Arduino. They put a boot loader on the chip before you bought it that could download new application code via a simple serial link. They put a USB to serial adapter chip on the board so that you could connect the board to your PC via USB. They provided the Arduino IDE to download your application via that USB/serial link. And of course the IDE hid all the messy details of the C++ language you are using to do all this.

Someone correct me if my summary is wrong here.

I would like that any Rust programming system for the Arduino bypasses all that and can program the naked chip, without boot loader directly. Then we can use it to program any board of our creation that uses the AVR chips.

See here: https://www.arduino.cc/en/hacking/bootloader

For my part I am not even sure I want to keep the Arduino.
I first implemented my robot with a PIC32MX (mostly C and little Assembler) but needed to return the board.
I will probably change at some point (after this small project) and get a board that is recommended for the Discovery or the Ferrous system.

The Arduino might be a bit small. That is great if you really want small and simple though.

You got me wondering if I can fire up Rust on an ST32F4 Discovery board I have in a bottom draw somewhere. Prospects look good: https://crates.io/crates/stm32f4

Just a note from the sidelines: What you link to is a Peripheral Access Crate (PAC), which is auto-generated from a vendor-provided SVD file. It will get the job done, but it's not going to be comfortable.

I generally recommend to look into the HAL first (which is a higher-level, hand-written library), and only fall back to the PAC if necessary: https://crates.io/crates/stm32f4xx-hal

I don't have any experience with this specific HAL, but at first glance it looks reasonably complete and well-maintained.

2 Likes

Good point. Thanks. Looks like have some embedded Rust tinkering to do...

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.