Spark Logic

RTC Libs.

ahull Mon May 18, 2015 7:16 pm

One of the things that I would like to get working is the RTC on the STM32F103XXX – We briefly touched on this before.

Most boards have a 32,767 Hz oscillator or crystal on them and therefore only need a battery/battery holder (possibly with an in-line schottky diode, put probably not) to allow us to get the RTC operational.

What I have discovered so far.

1) There is some sort of attempt to get this working in ./hardware/Arduino_STM32/STM32F1/libraries/Untested/RTClock/
This is incomplete and incompatible with the current versions of rcc.c and rcc.h

There is a “new” version of the rcc libraries in ./hardware/Arduino_STM32/STM32F1/libraries/Untested/RTClock/new RCC/
This is not compatible with the current rcc libraries either.

2) I am unclear which rcc.[h,c] I need to try to merge or adapt the changes form “new RCC” to as there seem to be a number of candidates.

./hardware/Arduino_STM32/STM32F3/cores/maple/libmaple/stm32f3/include/series/rcc.h
./hardware/Arduino_STM32/STM32F3/cores/maple/libmaple/stm32f3/f3_rcc.c

./hardware/Arduino_STM32/STM32F3/cores/maple/libmaple/include/libmaple/rcc.h
./hardware/Arduino_STM32/STM32F3/cores/maple/libmaple/rcc.c

./hardware/Arduino_STM32/STM32F1/libraries/Untested/RTClock/new RCC/rcc.h.new
./hardware/Arduino_STM32/STM32F1/libraries/Untested/RTClock/new RCC/rcc.c.new
./hardware/Arduino_STM32/STM32F1/libraries/RTClock/new RCC/rcc.h.new
./hardware/Arduino_STM32/STM32F1/libraries/RTClock/new RCC/rcc.c.new

./hardware/Arduino_STM32/STM32F1/cores/maple/libmaple/rcc.c
./hardware/Arduino_STM32/STM32F1/system/libmaple/stm32f2/include/series/rcc.h
./hardware/Arduino_STM32/STM32F1/system/libmaple/include/libmaple/rcc.h
./hardware/Arduino_STM32/STM32F1/system/libmaple/stm32f1/include/series/rcc.h

./hardware/Arduino_STM32/STM32F4/cores/maple/libmaple/rcc.c
./hardware/Arduino_STM32/STM32F4/cores/maple/libmaple/rcc.h

Replies

victor_pv Sat May 23, 2015 12:10 am

I tested the RTC with the example called Test_RTClock, and I get a serial output with a counter that goes up every second.

The example seems very rough, had toggle led on it which has been removed from the latest repo, did not have a Serial.begin(), and referred to SerialUSB which did not work in my case, not sure if because the board selection or what.

After I changed a couple of things in the example, its working and giving me a second counter.

ahull Sat May 23, 2015 12:16 am

Sounds good, I hope to get a chance to test with a battery on the RTC VBatt pin to see if I can set the RTC and it survives killing the main CPU power.
I’ve got some button cells and holders somewhere so all I need to do is find the time to solder a few wires. Hopefully tomorrow.

mrburnette Sat May 23, 2015 12:22 am

ahull wrote:I think once we get this working, it should become one of the “standard” libs included with Roger’s git repo. and in light of that, it will have to be “/” rather than “\” throughout.

RogerClark Sat May 23, 2015 1:24 am

Hi Guys

The RTClock lib is now in the libraries folder.

I’ve converted it to the new style library, with a src subfolder and added keywords but I’ve just realised that the keywords dont all work.

I’ll fix this later, as its only a minor issue

Anyway, I’ve updated the Test_RTClock example so that it compiles on generic boards (removed toggleLed etc)

And I have tested both examples numerous times

Note. I’ve only tested on one board a generic F103C8, so it needs more testing on V and Z series etc just to be sure its ok

But I think its stable enough to move from the untested folder ;-)

Cheers

Roger

victor_pv Sat May 23, 2015 4:17 am

My test was in a VET board btw.

RogerClark Sat May 23, 2015 6:17 am

Victor

I fixed up the simple example, as it wouldn’t compile for me either ;-)

mrburnette Sat May 23, 2015 1:46 pm

RogerClark wrote:Victor

I fixed up the simple example, as it wouldn’t compile for me either ;-)

ahull Sat May 23, 2015 3:21 pm

I added a battery and battery holder to by “blue pill” board and it looks like that is all you need to keep the RTC running when everything else is powered off. I’ll post some pics later.

mrburnette Sat May 23, 2015 7:47 pm

ahull wrote:I added a battery and battery holder to by “blue pill” board and it looks like that is all you need to keep the RTC running when everything else is powered off. I’ll post some pics later.

ahull Sat May 23, 2015 9:32 pm

Pics as promised.

Image
Battery holder, wires and battery.

Image
Battery fitted. In this case + VBat (aka 3VB) is the Purple wire, Ground is green.

Image
Number of seconds since the clock was reset is in the top right corner. This has been ticking away nicely, with the scope disconnected from power for the last couple of hours. Tick count is currently 23533 seconds since the battery was fitted and the clock reset.

I now need to refine this slightly to get HH:MM:SS DD/MM/YYYY and figure out how to trigger the alarms and get the STM32F103 to sleep. But the hard bit is done.

Image
Slightly fuzzy shot of the battery holder wrapped in clear tape and popped in the project box. Wired to the GND and 3VB pins. 3VB note, not 3v3 !
WARNING Don’t wire the battery across the 3 Volt line or something will sizzle and pop, probably the battery, possibly the voltage regulator, maybe both, :shock: ensure you identify the correct pin for the RTC battery. The STM datasheet calls this pin VBat.

One interesting feature of the STM32F103 that is worth exploring are the battery backed up “registers”

The RTC and the backup registers are supplied through a switch that takes power either on VDD supply when present or through the VBAT pin. The backup registers are ten 16-bit registers used to store 20 bytes of user application data when VDD power is not present

EDIT: This link might provide some useful insights into using the RTC for human readable clock functions.

RogerClark Sat May 23, 2015 10:57 pm

Andy

I looked in that doc, but couldn’t see anything , however it is documented in the main manual RM0090 on page 820.

I didn’t realise those registers existed. Using one of them for the bootloader could be very useful, so if we do make them available int the code, I’d like to reserve the last one for the bootloader for devices using the generic bootloader, as it allows us to reliably do uploads to ram without getting false positives

ahull Sat May 23, 2015 11:55 pm

RogerClark wrote:
…
I didn’t realise those registers existed. Using one of them for the bootloader could be very useful, so if we do make them available int the code, I’d like to reserve the last one for the bootloader for devices using the generic bootloader, as it allows us to reliably do uploads to ram without getting false positives

RogerClark Sun May 24, 2015 1:55 am

I’ll read the spec and see if I can write some functions to read and write the registers

Edit. The page number and doc I quoted before were for the F4, its on page 83 in the F103 doc (ref CD00171190.pdf)

It looks like they start at address 0x40006C00 + 0x04 and the spec says

20-byte data registers (in medium-density and low-density devices) or 84-byte data
registers (in high-density, XL-density and connectivity line devices)
• Status/control register for managing tamper detection with interrupt capability
• Calibration register for storing the RTC calibration value
• Possibility to output the RTC Calibration Clock, RTC Alarm pulse or Second pulse on
TAMPER pin PC13 (when this pin is not used for tamper detection)

I will initially see if I can get them working as an adjunct to the RTC but really they are not part of the RTC they are a core function of the processor and really need to be in cores and also have the number (size of memory) switched on an ifdef depending on device density.

ahull Sun May 24, 2015 10:13 am

I’ll let you decide how best to handle the registers. Treating them as an area of ram may be simplest.

I was thinking of placing a rolling unix timestamp in some of the registers to indicate the current time, starting with the time the clock is first set, and updated periodically by software using a per second ISR. Other bytes could be used for one or more alarm times. I hadn’t fleshed out the details. One idea would be to add some sort of sub second (millisecond perhaps) precision. Another enhancement would be to store a timezone value and keep the timestamp in UTC.

A little light reading for you all..
https://en.wikipedia.org/wiki/Unix_time
https://en.wikipedia.org/wiki/C_date_an … ons#time_t
http://playground.arduino.cc/code/time
http://www.pjrc.com/teensy/td_libs_Time.html
http://www.pjrc.com/teensy/td_libs_TimeAlarms.html

STMs own licensed device driver uses a slightly different approach, which seems more wasteful of the registers but I didn’t want to simply clone their idea as It may be possible to make this slicker. Perhaps self calibrating. I would prefer to stick to some sort of 32 bit time_t C typing standard so we have the option to use existing standard c time libraries with minimal re-working.

RogerClark Sun May 24, 2015 11:14 am

Hi Andy,

I was thinking more along the lines of some general easily accessible storage, rather than necessarily just using them for RTC

As far as I can tell from the manual, although some of the BKP registers are associated with the RTC, I got the impression that they are intended to store other data as well.

Did you see the note about tamper detection, i.e you can store sensitive data in these registers,and I presume they uP will erase them if it gets a tampered trigger.

Also. I was looking at a project a while ago that needed to store some calibration data, which may fit in these registers.

I know the EEPROM can be used as well, for that sort of storage, but its much harder to update, because you need to erase and re-write a page every time you want to change a byte. Where as these BKP registers although limited in size don’t seem to have that overhead

mrburnette Sun May 24, 2015 12:21 pm

As far as I can tell from the manual, although some of the BKP registers are associated with the RTC, I got the impression that they are intended to store other data as well.

Yes, that is the intent that I ferret after a long read last night. The RTC domain already has registers associated with time, but not UNIX timestamp, but that would only take 2 16-bit registers. These registers, if one reads the entire manual, were intended to store critical memory variables when the uC was powered off or rebooted since this power domain is not reset if there is a backup battery attached.

Other than the last register that is intended to be reserved for the bootloader, I would suggest that R0 – R8 be wrapped so that a standard core library call could be used to get-set the registers. As the RTC, once set to the real time-date, has all of the necessary data to calculate the UNIX timestamp, I am not sure what benefit (other than code overhead on read, storing would be the same overhead), so maybe library or core lib to resolve and save the 9 16-bit registers for the application backup needs.

As the core code already has microsecond and millisecond counters, I really cannot see a need in having the UNIX timestamp anything but in unit seconds.

Just thinking out loud…

Ray

ahull Sun May 24, 2015 1:03 pm

Ray, you are probably correct, since we have no way to keep track of sub second time when the power is disconnected and the only timekeeping is from the RTC, it makes no sense to try to store millisecond precision. We can only be certain of the time to within the accuracy of the 32kHz crystal, but that is good enough for anything I am ever likely to want to do with the RTC. As I understand it, the RTC keeps a 32bit value (2×16 bit registers), so once set to the current Unix timestamp, and assuming we can set this value as well as read it, this would always allow us to know unix time from which we can calculate anything else (Hour,Min,Sec,Day,Month,Year etc) so the remaining battery backed registers can be used for whatever we choose.

If however the RTC time register always counts from zero when reset , we would need a battery backed up 32 bit register to store an offset to the current time.

ahull Sun May 24, 2015 3:04 pm

Well it works… no need for any extra effort. I added a serial command to the Pigscope (scope is still sans pig… I will need to perform the pig graft soon).
I can now set the time by sending

timestamp <unix time stamp>

It responds with

# Time command – 1432479737 15:2:17 24/5/2015(UTC)

The result is below.
Image

Edit: Of course getting a valid unix timestamp is another matter. In Linux its pretty easy.

date –date “+1hour” +”%s”

Gives me UTC + 1hour – Which is what I need, since I am in British Summer Time (UTC + 1 Hour).

ahull Sun May 24, 2015 3:53 pm

To get the time formatted correctly I used the Arduino Time library – https://github.com/PaulStoffregen/Time

Since the STM32 RTC is a 32 bit int, I can set it read it display it and so forth using the following code snippets

Some where before setup() include the following…
...
// SeralCommand -> https://github.com/kroimon/Arduino-SerialCommand.git
#include "RTClock.h"
RTClock rt (RTCSEL_LSE); // initialise
uint32 tt;

// Time library - https://github.com/PaulStoffregen/Time
#include "Time.h"
#define TZ "UTC+1"

// SeralCommand -> https://github.com/kroimon/Arduino-SerialCommand.git
#include <SerialCommand.h>
...

ahull Sun May 24, 2015 5:03 pm

For the record, here are my button cell and holder sources…

Button cell <Select the CR1220 option

Button cell holder

Sign in to reply