GithubHelp home page GithubHelp logo

avr-progmem-rs's People

Contributors

cryptjar avatar dezajno avatar gergoerdi avatar michaelkamprath avatar rahix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

avr-progmem-rs's Issues

Consider pinning `avr-hal` revision in dev-dependencies

Hey!

You should probably pin the version of avr-hal in the dev-dependencies to a specific git revision. avr-hal is still quite early in development and newer versions might break the example code so this way anyone downloading the project and trying to compile the example in the future will build against the same version of avr-hal that you originally wrote it for:

[dev-dependencies.arduino-uno]
# It is not yet available via crates.io
git = "https://github.com/Rahix/avr-hal.git"
rev = "7337cd76cd96f2d27701b137396d94a06d3a501d"

(7337cd76cd96 is the latest commit on master, you should probably check whether that still works and use an older rev instead if it does not ...)

Question: array of arrays

I'd like to store sprite animation frames in PROGMEM, where each frame has the same size (represented as a [u8; 8]) but the number of frames can vary between animations.

So I have something like

progmem! {
  pub static progmem IDLE: [[u8; 8]; 1] = ....;
  pub static progmem WALK: [[u8; 8]; 3] = ...;

The first issue is dereferencing these. I can use e.g. WALK.load_at(2) to get a [u8; 8], but if I want to process it byte-wise, is there a way to avoid that 7-byte overhead and get just the one byte, something like e.g. WALK.load_wrapper_at(2).load_at(3)?

The second issue is storing a reference to the currently playing animation. If they were all the same length, I could store a &'static ProgMem<[[u8;8];3> in my state; however, since they are not, one of the wrappers has type ProgMem<[[u8;8];1> while the other one is ProgMem<[[u8;8];3>. I think what I'd need is something like a ProgMemArrayRef<[u8;8]> that has a dynamic length accessible at runtime.

Incomplete safety invariants for `read_byte_loop_raw`

Here, the code loops over the bytes that a type may occupy and reads each:

avr-progmem-rs/src/raw.rs

Lines 170 to 177 in 8d00b35

for i in 0..size_bytes {
let i: isize = i.into();
let value = unsafe {
// SAFETY: The caller must ensure that `p_addr` points into the
// program domain.
read_byte(p_addr_bytes.offset(i))
};

As you note, this is morally equivalent to ptr::copy, but implemented via bytewise reading. Unfortunately, the results are not well-defined for all T. A type may have uninitialized bytes or initialization invariants, such as padding or niches.

#[derive(Clone, Copy, Default)]
struct HasPadding {
    a: u16,
    b: u8,
}
assert_eq!(4, mem::size_of::<HasPadding>()); // A padding byte exists

If it is valid to read a padding byte, this will incite no complaints, but we are not so lucky:

for i in 0..mem::size_of::<HasPadding>() {
    unsafe {
        let padded = padded.cast::<u8>().add(i);
        let blender = blender.cast::<u8>().add(i);
        // error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
        blender.write(padded.read())
    };
}

I put together a few examples of ways to provoke Miri's anger on the Playground while studying this. In particular, you can observe how making sure there is no padding byte by so much as adding a field in the right place quiets Miri's complaints. Unfortunately, Miri is not fully aware of AVR's memory semantics, so has no useful commentary there.

Obviously, as this function is unsafe, no change in the code is required, merely documenting this additional invariant. However, this has implications on the function's usage and how it is used in this crate and others, so you may want a solution. It may be correct to simply copy all the bytes in a type before any individual byte enters Rust (i.e. to copy each T fully while in a single asm! block). This is in the domain of "underdefined semantics that may be subject to change", but is unlikely to, as it is a consequence of Rust only understanding assembly in a "black box" manner, seeing only its defined interface and having no vocabulary for what goes on inside asm!: "Whereof one cannot speak, thereof one must be silent".

Write examples with larger arrays

All of the array sizes in the documentation examples seem to be fairly small: the element type is always bytes, and the size is never more than about 5. I think that an example of hash function round constants would be more compelling, such as the data found here:

https://github.com/jedisct1/rust-hmac-sha256/blob/e787a2e40ce00c7e27b336207cdec730226ff6f1/src/lib.rs#L127-L138

Here, the program needs 64 u32s and loads (up to) 16 at a time.

Motivated via rust-lang/rust#109000.

add documentation about how to put a string in progmem

I have spent the afternoon experimenting with how to put a string in progmem.

Using

#[cfg_attr(target_arch = "avr", link_section = ".progmem.data")]
static MESSAGE3: &str = "apple";

only puts the pointer and count of the slice in progmem. The actual characters still end up in RAM.

It is possible to use something like

#[cfg_attr(target_arch = "avr", link_section = ".progmem.data")]
static MESSAGE6: &[u8; 9] = b"dai kenja";

But if you try

#[cfg_attr(target_arch = "avr", link_section = ".progmem.data")]
static MESSAGE5: &[u8; 13] = b"dai 大賢者 kenja";

you get an error:

error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte

convert from llvm_asm! to (I think) asm!

The latest AVR template now uses channel = "nightly-2022-05-10". Unfortunately, that breaks any code that uses llvm_asm!

error: cannot find macro `llvm_asm` in this scope
  --> /home/thoth/.cargo/registry/src/github.com-1ecc6299db9ec823/avr-progmem-0.2.0/src/raw.rs:84:4
   |
84 |             llvm_asm!(
   |             ^^^^^^^^

I think the avr-hal crates use feature flags enabled by build.rs to support the new rust :
Rahix/avr-hal@5d75769

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.