/** * rtt_util.c * * Helper functions for the Real-Time Timer (RTT) on the ATSAMG55 microcontroller. * Used for generic delays / timeouts. * * Copyright (c) 2022 Bigscreen, Inc. */ #include #include #include "rtt_util.h" void rtt_enable(void) { RTT->RTT_MR = 3; // All special features disabled, prescaler = 3 (highest possible accuracy / granularity) } /* Returns the current value of the Real-time Timer. * Functions that wish to implement a timeout should read and * store this value locally. Then later calls to "rtt_timeout_check" * should pass in this value to determine if the allotted time * has expired. */ volatile uint32_t rtt_read_timer_value(void) { uint32_t rtt_val = RTT->RTT_VR; // What's up with this while loop? // Per the datasheet: // As CRTV can be updated asynchronously, it must be read twice at the same value // So we're just making sure that the Current Real-Time Value (CRTV) (and no, I don't know // why the ASF library has a different name for this register) isn't changing in the middle // of our register read. while (rtt_val != RTT->RTT_VR) { rtt_val = RTT->RTT_VR; } return rtt_val; } bool rtt_timeout_check(volatile uint32_t start_time, uint32_t timeout_val) { // Wraparound detection. If the current time is ever less than the // start time, there was a wraparound. volatile uint32_t current_time = rtt_read_timer_value(); // Note - wraparound case will be calculated correctly. If // start_time is higher than current_time (because the RTT value // wrapped around after 0xFFFF.FFFF), the elapsed_time will // still get the correct value thanks to the unsigned int math. uint32_t elapsed_time = current_time - start_time; if(elapsed_time >= timeout_val) { return true; } else { return false; } }