Chrono Integration

Relevant source files

This document covers the optional chrono feature integration that provides high-level DateTime operations for the ARM PL031 RTC driver. This feature extends the core Unix timestamp API with convenient date and time handling using the chrono crate.

For information about the core driver functionality and Unix timestamp operations, see Core Driver Implementation. For details about enabling and configuring the chrono feature, see Feature Configuration.

Purpose and Scope

The chrono integration provides a type-safe, ergonomic API layer over the core RTC driver by converting between Unix timestamps and DateTime<Utc> objects. This feature is enabled by default but can be disabled for minimal deployments that only need raw timestamp operations.

The integration handles timezone considerations by standardizing on UTC, performs bounds checking for timestamp conversions, and maintains the same interrupt and match functionality as the core API while operating on DateTime objects.

API Overview

The chrono integration extends the Rtc struct with three additional methods that mirror the core timestamp operations but operate on DateTime<Utc> types.

DateTime Operations

MethodCore EquivalentPurpose
get_time()get_unix_timestamp()Read current time as DateTime
set_time()set_unix_timestamp()Set current time from DateTime
set_match()set_match_timestamp()Set match time for interrupts

Method Implementation Details

Time Reading

The get_time() method provides a safe conversion from the hardware's 32-bit Unix timestamp to a proper DateTime object:

flowchart TD
RTC["Rtc::get_time()"]
CORE["get_unix_timestamp()"]
CONVERT["Utc.timestamp_opt()"]
UNWRAP["unwrap()"]
DATETIME["DateTime"]

CONVERT --> UNWRAP
CORE --> CONVERT
RTC --> CORE
UNWRAP --> DATETIME

Chrono DateTime Conversion Flow

The conversion uses chrono::Utc::timestamp_opt() with nanoseconds set to 0, since the PL031 hardware only provides second-level precision. The unwrap() is safe because valid PL031 timestamps always fall within chrono's supported range.

Sources: src/chrono.rs(L6 - L10) 

Time Setting

The set_time() method handles the reverse conversion with proper error handling for out-of-bounds timestamps:

flowchart TD
INPUT["DateTime"]
TIMESTAMP["time.timestamp()"]
CONVERT["try_into()?"]
SUCCESS["set_unix_timestamp()"]
ERROR["TryFromIntError"]

CONVERT --> ERROR
CONVERT --> SUCCESS
INPUT --> TIMESTAMP
TIMESTAMP --> CONVERT

DateTime to Timestamp Conversion with Error Handling

The method returns Result<(), TryFromIntError> to handle cases where the DateTime represents a time outside the PL031's supported range (Unix timestamps that don't fit in 32 bits).

Sources: src/chrono.rs(L12 - L18) 

Match Register Integration

The set_match() method extends the interrupt functionality to work with DateTime objects:

flowchart TD
subgraph subGraph2["Hardware Layer"]
    PL031_MR["PL031 Match Register"]
    INTERRUPT_GEN["Interrupt Generation"]
end
subgraph subGraph1["Core Driver Layer"]
    SET_MATCH_TS["set_match_timestamp(u32)"]
    MATCH_REG["write_volatile(MR)"]
end
subgraph subGraph0["Chrono API Layer"]
    SET_MATCH["set_match(DateTime)"]
    CONVERT_MATCH["match_time.timestamp().try_into()?"]
end

CONVERT_MATCH --> SET_MATCH_TS
MATCH_REG --> PL031_MR
PL031_MR --> INTERRUPT_GEN
SET_MATCH --> CONVERT_MATCH
SET_MATCH_TS --> MATCH_REG

Match Register DateTime Integration

This allows applications to schedule interrupts using natural DateTime objects rather than calculating Unix timestamps manually.

Sources: src/chrono.rs(L20 - L26) 

Error Handling and Type Safety

Conversion Error Types

The chrono integration uses TryFromIntError to handle timestamp conversion failures. This occurs when attempting to convert a DateTime that represents a time outside the range of a 32-bit Unix timestamp (before 1970 or after 2106).

flowchart TD
DATETIME["DateTime"]
TIMESTAMP["i64 timestamp"]
CHECK["fits in u32?"]
SUCCESS["u32 timestamp"]
ERROR["TryFromIntError"]
CORE_API["Core RTC API"]

CHECK --> ERROR
CHECK --> SUCCESS
DATETIME --> TIMESTAMP
SUCCESS --> CORE_API
TIMESTAMP --> CHECK

Timestamp Range Validation

Applications should handle these errors appropriately, either by validating DateTime inputs or providing fallback behavior for out-of-range times.

UTC Timezone Handling

The integration standardizes on UTC timezone to avoid complex timezone conversion logic in embedded systems. This ensures consistent behavior across different deployment environments and simplifies the API surface.

Sources: src/chrono.rs(L1 - L3) 

Integration with Core Functionality

The chrono methods are thin wrappers around the core driver functionality, maintaining the same safety properties and hardware access patterns while providing a more convenient interface.

flowchart TD
subgraph Hardware["Hardware"]
    PL031["ARM PL031 RTC"]
end
subgraph subGraph2["Core Driver (lib.rs)"]
    GET_UNIX["get_unix_timestamp()"]
    SET_UNIX["set_unix_timestamp()"]
    SET_MATCH_UNIX["set_match_timestamp()"]
    REGISTERS["Register Operations"]
end
subgraph subGraph1["Chrono Feature (chrono.rs)"]
    GET_TIME["get_time()"]
    SET_TIME["set_time()"]
    SET_MATCH_CHRONO["set_match()"]
end
subgraph subGraph0["Application Code"]
    APP_CHRONO["DateTime Operations"]
    APP_CORE["Unix Timestamp Operations"]
end

APP_CHRONO --> GET_TIME
APP_CHRONO --> SET_MATCH_CHRONO
APP_CHRONO --> SET_TIME
APP_CORE --> GET_UNIX
APP_CORE --> SET_MATCH_UNIX
APP_CORE --> SET_UNIX
GET_TIME --> GET_UNIX
GET_UNIX --> REGISTERS
REGISTERS --> PL031
SET_MATCH_CHRONO --> SET_MATCH_UNIX
SET_MATCH_UNIX --> REGISTERS
SET_TIME --> SET_UNIX
SET_UNIX --> REGISTERS

Chrono Integration Architecture

This design allows applications to choose the appropriate abstraction level: high-level DateTime operations for convenience, or low-level timestamp operations for performance-critical code.

Sources: src/chrono.rs(L1 - L27)