Skip to content

Commit

Permalink
fix: Add an optional patch for buserror/simavr#453
Browse files Browse the repository at this point in the history
  • Loading branch information
Patryk27 committed Oct 29, 2024
1 parent 2ef9941 commit 8275eaa
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 21 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ bindgen = "0.69"
fs_extra = "1.0"
pkg-config = "0.3"
walkdir = "2.3"

[features]
patch-twi-inconsistencies = []
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
[crates-badge]: https://img.shields.io/crates/v/simavr-ffi.svg
[crates-link]: https://crates.io/crates/simavr-ffi

Low-level bindings to [simavr](https://github.com/buserror/simavr).
Low-level bindings to [simavr](https://github.com/buserror/simavr):

Supported platforms: Linux & Mac (pull requests for Windows welcome!).
```toml
[dependencies]
simavr-ffi = "1.0.1"
```

Supported platforms: Linux & Mac (pull requests welcome!).

## Requirements

Compile-time:

- clang,
- git,
- libelf,
- pkg-config,
- zlib.
Expand All @@ -34,6 +40,12 @@ $ sudo apt install clang libelf-dev pkg-config
$ brew install libelf pkg-config
```

## Feature flags

All feature flags are disabled by default - if you want, you can activate:

- `patch-twi-inconsistencies` - applies a fix for https://github.com/buserror/simavr/issues/453

## FAQ

### How does it compare to `simavr-sys`?
Expand Down
111 changes: 92 additions & 19 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,90 @@ use walkdir::WalkDir;
fn main() {
println!("cargo:rerun-if-changed=build.rs");

let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

build_simavr(&out_path);
generate_simavr_bindings(&out_path);
link_libelf();
link_zlib();
link_libzstd();
let out = PathBuf::from(env::var("OUT_DIR").unwrap());

check();
patch();
copy(&out);
revert_patch();
build(&out);
generate_bindings(&out);
link();
}

fn build_simavr(out: &Path) {
println!("=> Building simavr");

fn check() {
if !Path::new("vendor")
.join("simavr")
.join("README.md")
.exists()
{
panic!(
"\
`vendor/simavr` doesn't seem to contain the expected source code. \
If you're cloning simavr-ffi by hand, please use `git clone ... \
--recurse-submodules`."
"`vendor/simavr` doesn't exist - if you're cloning simavr-ffi by \
hand, please use `git clone ... --recurse-submodules`"
);
}
}

fn patch() {
println!("=> Patching simavr");

simavr_git(&["reset", "--hard", "HEAD"]);

#[cfg(feature = "patch-twi-inconsistencies")]
patch_ex("twi-inconsistencies.patch");
}

#[allow(unused)]
fn patch_ex(name: &str) {
let path = Path::new(file!())
.parent()
.unwrap()
.join("patches")
.join(name)
.canonicalize()
.unwrap();

simavr_git(&["apply", &path.display().to_string()]);
}

fn copy(out: &Path) {
println!("=> Copying simavr");

let out_simavr = out.join("simavr");

if !out_simavr.exists() {
fs::create_dir(&out_simavr)
.with_context(|| format!("Couldn't create directory: {}", out_simavr.display()))
.unwrap();

fs_extra::copy_items(&["vendor/simavr"], &out_simavr, &Default::default())
.with_context(|| {
format!(
"Couldn't copy simavr's sources to: {}",
out_simavr.display()
)
})
.unwrap();
}
}

fn revert_patch() {
// Don't leave the tree dirty during development
simavr_git(&["reset", "--hard", "HEAD"]);
}

fn build(out: &Path) {
println!("=> Building simavr");

#[cfg(target_family = "unix")]
build_simavr_unix(out);
build_unix(out);

#[cfg(not(target_family = "unix"))]
panic!("Sorry, I don't know how to build simavr on this architecture");
panic!("simavr-ffi works only on Unixes right now - pull requests are welcome!");
}

#[cfg(target_family = "unix")]
fn build_simavr_unix(out: &Path) {
fn build_unix(out: &Path) {
let out_simavr = out.join("simavr");

if !out_simavr.exists() {
Expand Down Expand Up @@ -76,7 +126,7 @@ fn build_simavr_unix(out: &Path) {
println!("cargo:rustc-link-lib=static=simavr");
}

fn generate_simavr_bindings(out: &Path) {
fn generate_bindings(out: &Path) {
println!("=> Generating simavr bindings");

let mut builder = bindgen::Builder::default();
Expand All @@ -97,7 +147,6 @@ fn generate_simavr_bindings(out: &Path) {
.map(|header| header.path().to_string_lossy().to_string());

for header in headers {
println!("-> Found header: {}", header);
builder = builder.header(header);
}

Expand All @@ -110,6 +159,12 @@ fn generate_simavr_bindings(out: &Path) {
.expect("Couldn't write simavr's bindings");
}

fn link() {
link_libelf();
link_zlib();
link_libzstd();
}

fn link_libelf() {
println!("=> Linking libelf");

Expand All @@ -133,3 +188,21 @@ fn link_libzstd() {

println!("cargo-rustc-link-lib=zstd");
}

fn simavr_git(args: &[&str]) {
let status = Command::new("git")
.current_dir("vendor/simavr")
.args(args)
.status()
.expect("Couldn't run `git`");

if !status.success() {
panic!(
"`git {}` returned a non-zero exit code",
args.iter()
.map(|arg| arg.to_string())
.collect::<Vec<_>>()
.join(" ")
);
}
}
63 changes: 63 additions & 0 deletions patches/twi-inconsistencies.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
diff --git a/simavr/sim/avr_twi.c b/simavr/sim/avr_twi.c
index 521c03c..f96dedd 100644
--- a/simavr/sim/avr_twi.c
+++ b/simavr/sim/avr_twi.c
@@ -289,11 +289,11 @@ avr_twi_write(
avr_twi_irq_msg(msgv, p->peer_addr, avr->data[p->r_twdr]));

if (do_read) { // read ?
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
msgv & TWI_COND_ACK ?
TWI_MRX_DATA_ACK : TWI_MRX_DATA_NACK);
} else {
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
p->state & TWI_COND_ACK ?
TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK);
}
@@ -319,7 +319,7 @@ avr_twi_write(

if (p->peer_addr & 1) { // read ?
p->state |= TWI_COND_READ; // always allow read to start with
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
p->state & TWI_COND_ACK ?
TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK);
} else {
@@ -328,7 +328,7 @@ avr_twi_write(
p->state & TWI_COND_ACK ?
TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK);
}else{
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
p->state & TWI_COND_ACK ?
TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK);
}
@@ -426,7 +426,7 @@ avr_twi_irq_input(
// INVERSE logic here
if (!(msg.u.twi.msg & TWI_COND_WRITE))
p->peer_addr |= 1;
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
msg.u.twi.msg & TWI_COND_WRITE ?
TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK );
}
@@ -439,7 +439,7 @@ avr_twi_irq_input(
}
}
if (msg.u.twi.msg & TWI_COND_STOP) {
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
msg.u.twi.msg & TWI_COND_WRITE ?
TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK );
}
@@ -456,7 +456,7 @@ avr_twi_irq_input(
if (p->state & TWI_COND_SLAVE) {
if (msg.u.twi.msg & TWI_COND_WRITE) {
avr->data[p->r_twdr] = msg.u.twi.data;
- _avr_twi_delay_state(p, 9, TWI_SRX_ADR_DATA_ACK );
+ _avr_twi_delay_state(p, 0, TWI_SRX_ADR_DATA_ACK );
}
} else {
// receive a data byte from a slave

0 comments on commit 8275eaa

Please sign in to comment.