Fastest way to read RTC
I have an app where I timestamp all the data I get from a bunch of external devices. I'm trying to come up with the fastest way to read the RTC and have 2 approaches, one using snprintf and some LL driver code that's pretty easy to read. It's not many lines long but slow: 207 microseconds according to the chronometer in VisualGDB. The second works directly with registers. It takes a lot more lines of code but is much faster: 10 microseconds. The timestamp and the data from every device gets logged to a file on a uSD card and should be readable in a text editor without additional formatting so my timestamp winds up being an array of ASCII values. And I'm using a STM32H7A3. BTW, I know I need to do a little more arithmetic to get the actual decimal subseconds, I just haven't gotten there yet.
Is there a better way that I haven't thought of?
uint8_t regTimestamp[18] = { 0, 0, '-', 0, 0, '-', 0, 0, 'T', 0, 0, ':', 0, 0, ':', 0, 0, 0 };
const uint8_t offset = 48;
uint32_t tr;
uint32_t ssr; //TODO need to check for all 3 registers rolling over
uint32_t dr;
uint8_t yearTens;
uint8_t yearOnes;
uint8_t monthTens;
uint8_t monthOnes;
uint8_t dayTens;
uint8_t dayOnes;
uint8_t hoursTens;
uint8_t hoursOnes;
uint8_t minuteTens;
uint8_t minuteOnes;
uint8_t secondTens;
uint8_t secondOnes;
RTClock::CPFTimestamp RTClock::getDateTimeStamp()
{
RTClock::CPFTimestamp timestamp = { 0 }; // In RTClock.hpp CPFTimestamp is typedef std::array<char, 32> CPFTimestamp;
//Here's the short, slow way
//NOTE: STM RTC requires reading the time register before the data register in order to synch date and time read
snprintf((char*)timestamp.data(),
32, "%02d-%02d-%02dT%02d:%02d:%02d.%03d",
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetSecond(RTC)),
__LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetSubSecond(RTC))),
std::cout << timestamp.data() << std::endl;
//Here's the long, fast way
tr = RTC->TR;
ssr = RTC->SSR; //TODO need to check for all 3 registers rolling over
dr = RTC->DR;
yearTens = (dr & 0x00F00000) >> 20;
yearOnes = (dr & 0x000F0000) >> 16;
regTimestamp[0] = yearTens + offset;
regTimestamp[1] = yearOnes + offset;
monthTens = (dr & 0x00001000) >> 12;
monthOnes = (dr & 0x00000F00) >> 8;
regTimestamp[3] = monthTens + offset;
regTimestamp[4] = monthOnes + offset;
dayTens = (dr & 0x00000030) >> 4;
dayOnes = (dr & 0x0000000F);
regTimestamp[6] = dayTens + offset;
regTimestamp[7] = dayOnes + offset;
hoursTens = (tr & 0x00300000) >> 20;
hoursOnes = (tr & 0x000F0000) >> 16;
regTimestamp[9] = hoursTens + offset;
regTimestamp[10] = hoursOnes + offset;
minuteTens = (tr & 0x00007000) >> 12;
minuteOnes = (tr & 0x00000F00) >> 8;
regTimestamp[12] = minuteTens + offset;
regTimestamp[13] = minuteOnes + offset;
secondTens = (tr & 0x00000030) >> 4;
secondOnes = (tr & 0x0000000F);
regTimestamp[15] = secondTens + offset;
regTimestamp[16] = secondOnes + offset;
std::cout << regTimestamp << std::endl;
return timestamp;
}
