stm32-fmc 0.3.2

Hardware Abstraction Layer for STM32 Memory Controllers (FMC/FSMC)
Documentation
# [Documentation]https://docs.rs/stm32-fmc

# stm32-fmc

[![docs.rs](https://docs.rs/stm32-fmc/badge.svg)](https://docs.rs/stm32-fmc)
[![Crates.io](https://img.shields.io/crates/v/stm32-fmc.svg)](https://crates.io/crates/stm32-fmc)

Hardware Abstraction Layer for STM32 Memory Controllers (FMC/FSMC)

Currently only SDRAM functions are implemented.

**This crate is a work in progress! Contributions very welcome**

## Implementing

(If your HAL already implements FMC, you can skip this)

See the [docs](https://docs.rs/stm32-fmc)

# Usage

### SDRAM

The FMC peripheral supports up to 2 external SDRAM devices. This crate currently
only supports 1, although it may be on either bank 1 or 2.

External memories are defined by
[`SdramChip`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.SdramChip.html)
implementations. There are several examples in the [`devices`](src/devices/)
folder, or you can make your own.

To pass pins to a constructor, create a tuple with the following ordering:

```rust
let pins = (
    // A0-A12
    pa0, ...
    // BA0-BA1
    // D0-D31
    // NBL0 - NBL3
    // SDCKE
    // SDCLK
    // SDNCAS
    // SDNE
    // SDRAS
    // SDNWE
);
```

You can leave out address/data pins not used by your memory.

#### Constructing

If you are using a HAL, see the HAL documentation.

Otherwise you can implement
[`FmcPeripheral`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.FmcPeripheral.html)
yourself then use
[`Sdram::new`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.new)
/
[`Sdram::new_unchecked`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.new_unchecked)
directly.

#### Initialising

Once you have an
[`Sdram`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html)
instance, you can:

* Initialise it by calling
  [`init`]https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.init. This
  returns a raw pointer
* Convert the raw pointer to a sized slice using `from_raw_parts_mut`

```rust
let ram = unsafe {
    // Initialise controller and SDRAM
    let ram_ptr: *mut u32 = sdram.init(&mut delay);

    // 32 MByte = 256Mbit SDRAM = 8M u32 words
    slice::from_raw_parts_mut(ram_ptr, 8 * 1024 * 1024)
};
```

### NAND Flash

The FMC peripheral supports once external parallel NAND flash device.

External memories are defined by
[`NandChip`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.NandChip.html)
implementations. There are examples in the [`devices`](src/devices/) folder, or
you can make your own.

To pass pins to a constructor, create a tuple with the following ordering:

```rust
let pins = (
    // A17/ALE
    // A16/CLE
    pa0, ...
    // D0-D7
    // NCE/#CE
    // NOE/#RE
    // NWE/#WE
    // NWAIT/R/#B
);
```

#### Constructing

If you are using a HAL, see the HAL documentation.

Otherwise you can implement
[`FmcPeripheral`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.FmcPeripheral.html)
yourself then use
[`Nand::new`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.new)
/
[`Nand::new_unchecked`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.new_unchecked)
directly.

#### Initialising

Once you have an
[`Nand`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html) instance
you should initialise it by calling
[`init`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.init). This
returns a
[`NandDevice`](https://docs.rs/stm32-fmc/latest/stm32_fmc/nand_device/struct.NandDevice.html)
instance.

```rust
let mut nand_device = nand.init(&mut delay);

// Read device identifier
let id = nand_device.read_id();
```

### NOR Flash/PSRAM

TODO

### Troubleshooting
The library automatically does some trace-level logging either via `log` or via `defmt`.
To enable such logging, enable either the `log` or `defmt` feature in your `Cargo.toml`.

For debugging the SDRAM register contents, the library provides additional feature `trace-register-values`, which when enabled causes the init function to log the register contents to the trace level.
This is useful for example when you want to compare the register values between `stm32-fmc` and CubeMX code.
Note that one of the logging features (`log`/`defmt`) must be enabled for this to work.

### Implementing a new device

If you end up depending on a fork or a newer version of this crate than the
HAL crate for your device, you can override the version pulled in by the
external crate using a `[patch]` section in your `Cargo.toml`, as described
in the
[Cargo Book](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section).

## Releasing

* Update Cargo.toml
* Update CHANGELOG.md

```
git commit -am 'v0.2.0'
git push --set-upstream origin v0.2.0
```

Create a PR and check CI passes

```
git push --set-upstream origin v0.2.0:master
git tag -a 'v0.2.0' -m 'v0.2.0'
git push origin refs/tags/v0.2.0
cargo publish
```

## License

Licensed under either of

 * Apache License, Version 2.0
   ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license
   ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.