Skip to content

Write an embedded-hal backend for AVR #93

@dylanmckay

Description

@dylanmckay
Member

It would be worthwhile writing an AVR HAL implementation for embedded-hal.

embedded-hal:

Activity

jhwgh1968

jhwgh1968 commented on Apr 28, 2018

@jhwgh1968

I've been thinking about doing this for a while, and after @shepmaster gave me a nudge elsewhere, decided to create a repo for playing around with it. It doesn't quite compile yet, but hopefully the ideas should be clear pretty soon.

jhwgh1968

jhwgh1968 commented on May 28, 2018

@jhwgh1968

Progress has been made! In short:

  • I have an early version of an application-facing peripheral called GpioPort, which handles GPIO access and configuration.
  • I have a skeleton for the concept of platforms. It is designed to look similar to the Cortex stuff done by @japaric.
  • I have implemented the lowest-level API with a trait called HwRegister. All peripherals are implemented by manipulating these, and they are invisible to the application.
  • The actual register definitions are done with macros. They are a really long and ugly, but should only end up being snippets of inline assembly.

Because I still don't have a working AVR Rust compiler (sigh), I am making sure it will cargo check on a recent nightly, and doing verification with avr-gcc where I can. I also need to use feature(asm) and a little bit of feature(const_fn), which hopefully the master branch of this repo (from November 2017) is new enough to support.

I would encourage heading over to my repo and opening issues there, rather than cluttering up this thread. I am eager for comments and design suggestions -- and someone with a working compiler to tell me it actually works. 🤞

TimNN

TimNN commented on Oct 28, 2018

@TimNN

Note that there is also https://github.com/Rahix/atmega32u4-hal by @Rahix, specifically for the atmega32u4.

Rahix

Rahix commented on Oct 29, 2018

@Rahix

@TimNN: Hey, thanks for mentioning this :) I haven't yet posted it here, because I wanted to get it more feature complete first ... (Currently, only the Pins+PWM and Delay is supported)

I have also started working on similar crates for the ATtiny85, but while doing so, I hit some strange compiler bugs ... I hope they magically solve themselves, once I get the latest compiler version working

shepmaster

shepmaster commented on Nov 3, 2018

@shepmaster
Member

once I get the latest compiler version working

We've merged @TimNN's upgrades to LLVM 8, so now might be a good time to give it a shot!

Rahix

Rahix commented on Nov 3, 2018

@Rahix

@shepmaster, @TimNN: I have been able to build the compiler from his branch, but I can't compile libcore using it :(

Should I recompile the compiler again or is there something else I might have missed?

TimNN

TimNN commented on Nov 3, 2018

@TimNN

@Rahix: What kind of error are you getting? How are you compiling libcore? Feel free to reach out here / in this repo or on gitter.

Rahix

Rahix commented on Nov 3, 2018

@Rahix

Hey, thanks for the quick response! My bad for not describing the issue further ...

I am currently recompiling the compiler, I have a suspicion that I used a wrong llvm version. I'll get back to you once I have tested it!

dylanmckay

dylanmckay commented on Nov 4, 2018

@dylanmckay
MemberAuthor

@Rahix

I have also started working on similar crates for the ATtiny85, but while doing so, I hit some strange compiler bugs ... I hope they magically solve themselves, once I get the latest compiler version working

As you've noticed, Tiny support isn't very well supported. The likely cause of bugs is; originally, when I forked the AVR backend, there was no proper subtarget feature support in the backend, meaning that every instruction that the backend supported could be generated, regardless or not if the chip supports it. A few years ago I wrote in subtarget feature support, based on the device families used by GCC (avr1, avr2, ..).

The subtarget features and chip definitions can be found here.

I don't own any tiny devices and so I haven't really got around to testing the support for it. I'm certain the subtarget feature matrix is accurate, being based on GCC, but I suspect there may be lingering pieces of code in the backend that unconditionally insert new machine instructions (for example, in one of the various AVR passes or custom ISel lowering routines). I've fixed a few of these in the past.

In these cases, the fix in LLVM is to wrap the BuildMI call like:

if (Subtarget->has<FeatureName>()) { // Branch for devices that support the new 'X' feature
  BuildMI(original instruction)
} else { // Branch for more minimal devices which do not support the 'X' feature
  BuildMI(instruction 1); // Do the same thing as above, but potentially with extra instructions
  BuildMI(instruction2);  // because not all devices support the more modern instruction X'
}

If you encounter any bugs, raise an issue!

N.B. I have a side project that is an integration test suite for the AVR backend. It executes all programs in an AVR emulator. Currently, the only blocker for me setting it up permanently on a Jenkins instance is that currently clang does not know how to link AVR CRT and libgcc libraries, so it doesn't even attempt to. The integration tests compile the same C/C++ program under avr-gcc and avr-clang, then executing in an AVR simulator. I've patched clang locally to link these libraries, but I cannot upstream it until I generalize the logic from my system-specific avr-gcc sysroot to any sysroot on anybody's machine. I mention this because the AVR simulator supports the Tiny cores, giving us an easy way to test that a complex program can be compiled and executed on a Tiny, and any other chip. The simulator should be able to tell us any specific machine code instructions that it hits that are not supported by that device, which will immediately let us grep for the instruction name in the AVR backend to find the offending piece of code.

Rahix

Rahix commented on Nov 4, 2018

@Rahix

First of all: Thank you all so much for your work on the compiler!

After running out of both RAM and harddrive space, I was finally able to compile the latest version today. I will update my crates as soon as I can.

The attiny issue seems to be fixed as far as I can tell. 👍 I believe the bug was LLVM allocating a register twice, which lead to strange behaviors ... But as I said, I can't reproduce it with the latest compiler

3 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @shepmaster@TimNN@Rahix@dylanmckay@jhwgh1968

        Issue actions

          Write an embedded-hal backend for AVR · Issue #93 · avr-rust/rust-legacy-fork