API Evolution and Changelog
Relevant source files
This document tracks the evolution of the arm_pl031
crate's public API across versions, documenting breaking changes, feature additions, and migration guidance. It serves as a reference for understanding how the crate has evolved and helps developers plan upgrades and maintain backward compatibility.
For information about building and testing the current version, see Building and Testing. For development environment setup, see Development Environment.
Version History Overview
The arm_pl031
crate has evolved through three major releases, each introducing significant improvements to the API design and functionality. The evolution demonstrates a progression from a basic RTC interface to a more robust, safe, and feature-rich driver.
API Evolution Timeline
Sources: CHANGELOG.md(L1 - L26)
Breaking Changes Analysis
Version 0.2.0 Breaking Changes
Version 0.2.0 introduced several breaking changes that improved the API's safety and correctness:
flowchart TD subgraph subGraph1["v0.2.0 API"] NEW_NEW["unsafe Rtc::new()"] NEW_GET["get_unix_timestamp() -> u32"] NEW_SET["set_unix_timestamp(&mut self, u32)"] SEND_SYNC["impl Send + Sync for Rtc"] end subgraph subGraph0["v0.1.0 API"] OLD_NEW["Rtc::new()"] OLD_GET["get_unix_timestamp() -> u64"] OLD_SET["set_unix_timestamp(&self, u64)"] end NEW_NEW --> SEND_SYNC OLD_GET --> NEW_GET OLD_NEW --> NEW_NEW OLD_SET --> NEW_SET
Sources: CHANGELOG.md(L10 - L22)
Timestamp Type Change (u64 → u32)
The most significant breaking change was the modification of timestamp handling functions:
Function | v0.1.0 Signature | v0.2.0 Signature | Rationale |
---|---|---|---|
get_unix_timestamp | fn() -> u64 | fn() -> u32 | Match PL031 register width |
set_unix_timestamp | fn(&self, u64) | fn(&mut self, u32) | Type consistency + mutability |
This change aligned the API with the underlying hardware's 32-bit registers, preventing potential data truncation issues and improving type safety.
Safety Boundary Introduction
The Rtc::new()
constructor was marked as unsafe
to properly reflect that it requires a valid memory-mapped I/O pointer:
#![allow(unused)] fn main() { // v0.1.0 impl Rtc { pub fn new(base: *mut u8) -> Self // v0.2.0 impl Rtc { pub unsafe fn new(base: *mut u8) -> Self }
Mutability Requirements
The set_unix_timestamp
function was changed to require a mutable reference, correctly reflecting that it modifies device state:
#![allow(unused)] fn main() { // v0.1.0 fn set_unix_timestamp(&self, timestamp: u64) // v0.2.0 fn set_unix_timestamp(&mut self, timestamp: u32) }
Sources: CHANGELOG.md(L14 - L17)
Feature Evolution
Version 0.2.1 Feature Additions
Version 0.2.1 introduced new capabilities without breaking existing APIs:
flowchart TD subgraph subGraph1["Match & Interrupt API (v0.2.1)"] MATCH["Match Register Methods"] INT_ENABLE["enable_interrupt()"] INT_PENDING["interrupt_pending()"] INT_CLEAR["clear_interrupt()"] SET_MATCH["set_match_timestamp()"] end subgraph subGraph0["Core API (v0.2.0)"] BASIC["Basic RTC Operations"] TIMESTAMP["Unix Timestamp Methods"] end subgraph subGraph2["Chrono Integration (v0.2.1)"] CHRONO_DEP["Optional chrono dependency"] DATETIME["DateTime support"] GET_TIME["get_time()"] SET_TIME["set_time()"] end BASIC --> MATCH CHRONO_DEP --> DATETIME DATETIME --> GET_TIME DATETIME --> SET_TIME TIMESTAMP --> SET_MATCH
Sources: CHANGELOG.md(L3 - L9)
Interrupt Management
The addition of interrupt-related methods provided comprehensive control over PL031 interrupt functionality:
enable_interrupt()
- Enable/disable alarm interruptsinterrupt_pending()
- Check interrupt statusclear_interrupt()
- Clear pending interruptsset_match_timestamp()
- Configure alarm time
Chrono Integration
The optional chrono
feature added high-level time handling:
- Conversion between Unix timestamps and
DateTime<Utc>
- Timezone-aware time operations
- Integration with the broader Rust ecosystem
Migration Guidance
Migrating from v0.1.0 to v0.2.0
Type Changes
// v0.1.0 code
let timestamp: u64 = rtc.get_unix_timestamp();
rtc.set_unix_timestamp(timestamp);
// v0.2.0 migration
let timestamp: u32 = rtc.get_unix_timestamp();
rtc.set_unix_timestamp(timestamp); // Also requires &mut rtc
Safety Annotations
// v0.1.0 code
let rtc = Rtc::new(base_addr);
// v0.2.0 migration
let rtc = unsafe { Rtc::new(base_addr) };
Mutability Requirements
#![allow(unused)] fn main() { // v0.1.0 code fn update_time(rtc: &Rtc, new_time: u64) { rtc.set_unix_timestamp(new_time); } // v0.2.0 migration fn update_time(rtc: &mut Rtc, new_time: u32) { rtc.set_unix_timestamp(new_time); } }
Migrating from v0.2.0 to v0.2.1
Version 0.2.1 is fully backward compatible. New features can be adopted incrementally:
// Existing v0.2.0 code continues to work
let timestamp = rtc.get_unix_timestamp();
// New v0.2.1 features (optional)
rtc.set_match_timestamp(timestamp + 3600); // Alarm in 1 hour
rtc.enable_interrupt(true);
// With chrono feature enabled
#[cfg(feature = "chrono")]
{
let datetime = rtc.get_time().unwrap();
println!("Current time: {}", datetime);
}
Sources: CHANGELOG.md(L7 - L8)
Thread Safety Evolution
Send + Sync Implementation
Version 0.2.0 introduced thread safety guarantees:
flowchart TD subgraph subGraph0["Thread Safety Model"] RTC["Rtc struct"] SEND["impl Send"] SYNC["impl Sync"] VOLATILE["Volatile MMIO operations"] ATOMIC["Atomic hardware access"] end RTC --> SEND RTC --> SYNC SEND --> VOLATILE SYNC --> ATOMIC
The Send
and Sync
implementations enable safe use in multi-threaded environments, with the underlying volatile memory operations providing the necessary synchronization primitives.
Sources: CHANGELOG.md(L21)
Compatibility Matrix
Version | Breaking Changes | New Features | Rust Edition | no_std Support |
---|---|---|---|---|
0.1.0 | N/A | Basic RTC operations | 2021 | Yes |
0.2.0 | Timestamp types, Safety | Send/Sync traits | 2021 | Yes |
0.2.1 | None | Interrupts, chrono | 2021 | Yes |
Future Compatibility Considerations
The API design demonstrates several patterns that suggest future stability:
- Hardware Alignment: The v0.2.0 type changes align with hardware constraints, reducing likelihood of future type changes
- Safety First: The unsafe boundary is clearly defined and unlikely to change
- Feature Flags: Optional features like
chrono
allow expansion without breaking core functionality - Thread Safety: The Send/Sync implementation provides a stable foundation for concurrent use
The crate follows semantic versioning, ensuring that future minor versions (0.2.x) will maintain backward compatibility while major versions (0.x.0) may introduce breaking changes.
Sources: CHANGELOG.md(L1 - L26)