Disabling access to RTC

Dear all,

I got the latest resinOS 2.12.7+rev1.dev version running on an Raspberry Pi Zero W and attached an RTC (DS3231) via I2C to the RPi. I also set it up via the config.txt with:

#dtoverlay=i2c-rtc,ds3231
dtoverlay=i2c-rtc,ds1307

  • yes I am using it as ds1307, I found out that this works somehow better - and the ds3231 does only work sporadicly (dunno why, its just what I figured and thought I document it here, in case someone else was having the same problems).

Anyway: What I need to do is to disable any kind of timesync / read / write to the RTC by resinOS at all. The RTC itself is accessed via an container under special circumstances and setup, and this works very well. However, any access by resinOS will disturb this. Which services do I need to disable to prevent resinOS from accessing the RTC by itself?

Thank you very much and have a nice day

Nico

In that version of resinOS, time was kept in sync by systemd-timesyncd. During boot, the time from the rtc is read and set as well.

It might be possible to use DBUS to disable systemd-timesyncd as here https://docs.resin.io/learn/develop/runtime/#host-os

but I wouldn’t recommend that.

Can you elaborate what special circumstances access the RTC? If it is used to keep track of time, I’d recommend letting the host os keep track of it.

@zubairlk Thank you very much for your answer.
Actually your description matches the problem I face - booting the RPi Zero gives my setup problems ;):
I do a very stupid thing and use the RPi Zero in a Multi Master I2C Bus with other Microcontrollers. Accessing the I2C Bus at the same time with other systems stalls the bus and gets the whole system as such killed. To circumvent that, I created a custom sync solution which keeps all systems access out of each others reach - and it works very well. But you see, if resinOS does its very reasonable magic - it really gets in the way in this very special and uncommon setup. It is also not wanted that information is written to the rtc at all, as this is an isolated, offline-only solution. So in the end, disabling all time syncing of resinOS is exactly what I need, as I do my hwclock -r with my special sauce inside the customized container, which does deliver the correct time to resinOS - and keeps the whole sensor and time i2c bus safe and sound.

And resinOS is more or less used directly accessed via SSH as just an very reliable Balena Host, so even provisoning is done by building directly on the device with an balena build.

hey @nmaas87 If you are sure about the RTC, maybe you can give a try to stop the chronyd service.

What I would suggest trying taling to the hostOS systemd service over the dbus (as some examples are in https://docs.resin.io/learn/develop/runtime/#dbus-communication-with-host-os ) and stoppding the service like that. Similar thing was discussed in another thread about restarting units, in this case the stopping would be, using dbus-send:

DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
  dbus-send --system --print-reply --reply-timeout=2000 \
    --type=method_call \
    --dest=org.freedesktop.systemd1 \
    /org/freedesktop/systemd1 \
    org.freedesktop.systemd1.Manager.StopUnit \
    string:<servicename>.service \
    string:replace

or using gdbus:

DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
  gdbus call --system \
    --dest org.freedesktop.systemd1 \
    --object-path /org/freedesktop/systemd1 \
    --method org.freedesktop.systemd1.Manager.StopUnit \
    "<servicename>.service" \
    "replace"

where the <servicename> would be chronyd in your case.

Putting this into your container’s start script (that is called by CMD) would ensure that the service is stopped when your application starts up (either at app start, or device reboot), and before any of your other codes would run, I guess?

Definitely have to test it out, in case there are any side effects that might affect some other parts of the system. Don’t know any off-hand, though, @zubairlk might have some ideas…

It is indeed quite niche. And too bad that the Pi series don’t have 2 usable I2C buses at least :slight_smile:

Also there’s some more docs on the systemd-dbus interface at: https://www.freedesktop.org/wiki/Software/systemd/dbus/

Actually, resinOS versions <2.13.0 the service is called systemd-timesyncd, and on versions >=2.13.0 it’s chronyd, so likely you want to add both to your code, if you have devices on both version ranges.

Thank you very much @imrehg :slightly_smiling_face:
Due to the nature of the “problem” I could not allow the RPi to access the I2C at all - so I needed to bypass the DBUS idea and did directly disable called service with systemctl and another preset file to disable the “vendor enabled” state of the service. At the moment it looks like its working :slight_smile:

Regarding the “2” i2c buses: Yeah you’re right. The 2nd one can actually be used (I tried with an manual pullup), however, as far as I understand, it is shared with the camera and as I use that, I needed to step back from my inital (quite good working) tests as I did not have enough time to ensure that it would work nicely. However, I needed to vandalize my Pi Zero by manual removing the I2C pullups (having to go medival on such a cute device is always a bit sad… but in the end its better than creating problems due to incorrect pullups on an i2c bus)…

Also, I would be so happy if they would just throw away that cheap i2c periphal they attached to the cpu and would go for some real i2c multi-master capable hardware :frowning: … but I think that won’t happen any time soon…

Hi @nmaas87

What do you mean by " bypass the DBUS idea and did directly disable called service with systemctl and another preset file to disable the “vendor enabled” state of the service". Could you share some details of how did you do that?

The reason I’m asking is because:

  • if it was through the host OS access, then it is likely more manual, than doing things through the application / dbus. It might not be an issue, just less scalable (and we are just thinking in general for the use case that you mentioned, it case it might help others:)
  • if it was done in the host OS and stays over reboot, I wonder if there’s going to be an issue with host OS updates, which does not preserve OS changes.

I read up on the 2 i2c busses, and take that back. :slight_smile: Would not recommend using the second one, it’s more of a “reserved” thing, that also changes between Raspberry Pi revisions as much as I can tell, so not something to rely on.

@imrehg
Sure thing :slight_smile:Yes I did disable it directly in resinOS on host level, which means that it will very likely not survive an upgrade to the next version. Also it is not scalable at all. But you really should not think about this as an “usecase” in general, it does not scale at all and won’t be something someone in the right mind would do :wink: - but as this is a very, very special occasion it is completly ok to create a cat and not cattle.

So I did enable read/write on the main partition, did disable the service and also create a preset to disable the service at all cost (so no vendor enabled as well) and then did remount again as read/only.

mount -o remount,rw /
systemctl disable systemd-timesyncd.service
mkdir /etc/systemd/system-preset/
echo 'disable *' >> /etc/systemd/system-preset/00-systemd-timesyncd.preset
mount -o remount,ro /

Another nice thing was to disable serial console and bluetooth services - in addition to disabling those via the config.txt parameters.

systemctl mask serial-getty@serial0.service
systemctl disable brcm43438.service

So this thing will become a one of a kind specimen and will be validated “in the flesh” for its task, while keeping backups and a reciepe on how to get to the same point. it is complelty fine that way.

Regarding i2c: That is correct, sadly. I have not figured out how they are actually routed, but I figure it will be very wildly varying. However, the foundation seem to be fine in us actually using it, as long as it is only used for an EEPROM and with the corrector pull-up resistor. So… I leave that one as it is and only work with the main one without its original resistors :slight_smile: (lines pulled up globably at the end of the whole i2c chain - which works very fine)

Yeah, I wouldn’t recommend doing this in general. It works for now, and you are well aware of the limitations, so it’s fine, just a big warning here for the general readership :warning:

We’ll likely have to come up with another way to provide such workarounds some way.