## esp-hal API guidelines ## Construction / Destruction of drivers - Avoid methods like `free(self) -> Self` instead, the driver should use the `PeripheralRef` API. - See: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c6/esp_hal/peripheral/index.html - Add `Drop` implementations to drivers that reset the peripheral to idle state. (with the exception of GPIO, imo, but we can discuss that) - Drivers that consume optional numbers of pins should use the builder pattern to do so (see SPI for example) - JB: I would also like to see anything with more advanced configuration use this pattern! We're already doing so for UART, for example ## Interop - Structs and enums implement the [common-traits](https://rust-lang.github.io/api-guidelines/interoperability.html#types-eagerly-implement-common-traits-c-common-traits) where applicable. - cfg'd `defmt` derives and impls are added to new structs and enums. - Don't use `log::XXX!` macros directly - use the wrappers in `fmt.rs` (e.g. just `info!` instead of `log::info!` or importing `log::*`) ## API Surface - All new public items must be documented (once we've caught up this can be automated with `deny(missing_docs)`) - Private details shouldn't be leaked into the public API, and should be make private where possible. - Implementation details that _need_ to be public should be marked with `doc(hidden)` and a comment as to why it needs to be public. - Any public traits, that **must** not be implemented downstream need to be `Sealed` - Prefer compile-time checks over runtime checks where possible, prefer a fallible API over panics - JB: Even better, evaluate whether it's possible to create an API that *cannot* fail! Sometimes we can get clever! - Follow naming conventions in order to be consistent across drivers - For example, users would expect that similar peripherals, say the UART and USB Serial/JTAG, probably work in about the same way, e.g.) `write_bytes`, `read_byte`, etc. - TODO: Codify the naming conventions as much as possible - APIs should ideally be as simple as possible, and require as few function calls as practical to use. Configuration should be secondary to ease of use right now, IMO. - Driver API decisions should be assessed individually, and _not_ just follow embedded-hal or other ecosystem trait crates - Avoid type states and extraneous generics whenever possible - These often lead to usability, and tend to just complicate things needlessly - Common cases of useless type info is storing pin information, this is usually not required and will bloat the complexity of the type massively - Structures and Enums should be CamelCase - SM: Avoiding `&mut self` when `&self` is safe to use. `&self` is generally easier to use as an API. Typical applications of this are where the methods just do writes to registers which don't have side effects. For example starting a timer is fine for &self, worst case a timer will be started twice if two parts of the program call it. A real example here: https://github.com/esp-rs/esp-hal/pull/1500#pullrequestreview-2015911974 ## Maintainability - Avoid excessive use of macros unless there is no other option; modification of the PAC crates should be considered before resorting to macros. - If you are adding `#[cfg]` attributes to stick-handle around differences in PACs, stop! Update the PACs instead! - Every line of code is a liability. Take some time to see if your implementation can be simplified before opening a PR. See if community PRs can be simplified before merging - If your are porting code from ESP-IDF, please include a link WITH the commit hash in it, and please highlight the relevant line(s) of code! - I have seen a lot of links in comments already without hashes, which now point to meaningless code - This just adds further confusion, and does nothing to help people in the future (in this case, me :D) - Follow standard coding "good practices" - Avoid magic numbers - Give variables/functions meanginful names, avoid single-character names unless it is obvious (e.g. `i` for index) - If a part of the code is complex/confusing, or additional context/information is required to fully grok it, please add a comment including all relevant information, issues/PRs, links, etc. - If you are linking to a file within a git repository, ensure that the URL contains a commit hash