rtc

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2024 License: MIT Imports: 10 Imported by: 1

README

rtc

Go (Golang) module for using a hardware Real-Time Clock (RTC) device in Linux.

Installation

$ go get github.com/cleroux/rtc

Usage

rtc.NewTicker() and rtc.NewTimer() provide high-level interfaces inspired by Go's time.NewTicker() and time.NewTimer() with the obvious difference being that the rtc functions trigger directly from the RTC's hardware interrupts.

The following example creates a ticker that fires at 2 Hz.

ticker, err := rtc.NewTicker("/dev/rtc", 2)
if err != nil {
    panic(err)
}
defer ticker.Stop()

for tick := range ticker.C {
    fmt.Printf("Tick.  Frame:%d Time:%v Delta:%v Missed:%d\n", tick.Frame, tick.Time, tick.Delta, tick.Missed)
}

The following example sets an alarm for 5 seconds in the future and waits for the alarm to fire.

timer, err := rtc.NewTimer("/dev/rtc", time.Minute)
if err != nil {
    panic(err)
}
defer timer.Stop()

alarm := <-timer.C
fmt.Printf("Alarm.  Time:%v\n", alarm.Time)

If more flexible programming of the RTC is needed, rtc.NewRTC() instantiates an object that exposes all RTC functionality. The RTC device file is kept open until Close() is called.

c, err := rtc.NewRTC("/dev/rtc")
if err != nil {
  return err
}
defer c.Close()

t, err := c.Time()

Lastly, for convenience, static utility functions are also provided. These functions are ideal when just a single function or operation is necessary because they open and close the RTC device. For example, if reading the RTC's time as in the following example:

t, err := rtc.Time("/dev/rtc")
if err != nil {
  panic(err)
}
fmt.Printf("Current time: %v\n", t)

Running Tests

Since accessing the Real-Time Clock requires root privileges, tests must also run as root.

sudo make test

The go executable needs to be found in the root user's PATH. Edit /etc/sudoers with the visudo command and add the location of the go executable to secure_path.
For example:

`Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/usr/local/go/bin"

Contributing

Issues and Pull Requests welcome!

References

[1] The Linux kernel user's and administrator's guide: Real Time Clock (RTC) Drivers for Linux
[2] rtc - Linux manual page

License

See the LICENSE file for license rights and limitations (MIT).

Documentation

Overview

Package rtc facilitates working with real-time clocks (RTCs). High level functions such as NewTicker and NewTimer encapsulate the details of working with the RTC while providing interfaces that are similar to Go's time.NewTicker and time.NewTimer respectively. If more flexible programming of the RTC is needed, the NewRTC function returns an rtc object that exposes all RTC functionality. When this object is instantiated, the RTC device file is kept open until the Close function is called. For convenience, static utility functions are also provided to open and close the RTC when only one function is needed. For example, reading the clock once is possible simply by calling rtc.Time(). Note that when working with the RTC, the highest resolution for time values is one second as defined in unix.RTCTime. https://www.kernel.org/doc/html/latest/admin-guide/rtc.html https://blog.cloudflare.com/its-go-time-on-linux/ https://man7.org/linux/man-pages/man4/rtc.4.html https://code.woboq.org/linux/linux/drivers/char/rtc.c.html

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CancelWakeAlarm

func CancelWakeAlarm(dev string) (err error)

CancelWakeAlarm cancels the wake alarm for the specified real-time clock device.

func GetAlarm added in v1.0.0

func GetAlarm(dev string) (t time.Time, err error)

GetAlarm returns the alarm time for the specified real-time clock device.

Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	t, err := rtc.GetAlarm("/dev/rtc")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Current alarm time: %v\n", t)
}
Output:

func GetClocks added in v1.0.0

func GetClocks() (devices []string, err error)

GetClocks returns a list of real-time clocks in the system.

Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	clocks, err := rtc.GetClocks()
	if err != nil {
		panic(err)
	}
	for _, clock := range clocks {
		fmt.Printf("Clock found: %s\n", clock)
	}
}
Output:

func GetEpoch added in v1.0.0

func GetEpoch(dev string) (epoch uint, err error)

GetEpoch reads the epoch from the specified real-time clock device.

Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	epoch, err := rtc.GetEpoch("/dev/rtc")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Current epoch: %d\n", epoch)
}
Output:

func GetFrequency added in v1.0.0

func GetFrequency(dev string) (frequency uint, err error)

GetFrequency returns the frequency of the specified real-time clock device.

Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	frequency, err := rtc.GetFrequency("/dev/rtc")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Frequency: %d\n", frequency)
}
Output:

func GetTime added in v1.0.0

func GetTime(dev string) (t time.Time, err error)

GetTime reads the time from the specified real-time clock device.

Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	t, err := rtc.GetTime("/dev/rtc")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Current time: %v\n", t)
}
Output:

func GetWakeAlarm added in v1.0.0

func GetWakeAlarm(dev string) (enabled bool, pending bool, t time.Time, err error)

GetWakeAlarm returns the current state of the wake alarm for the specified real-time clock device.

func SetAlarm

func SetAlarm(dev string, t time.Time) (err error)

SetAlarm sets the alarm time for the specified real-time clock device.

Example
package main

import (
	"time"

	"github.com/cleroux/rtc"
)

func main() {
	if err := rtc.SetAlarm("/dev/rtc", time.Now().Add(time.Minute)); err != nil {
		panic(err)
	}
}
Output:

func SetAlarmInterrupt

func SetAlarmInterrupt(dev string, enable bool) (err error)

SetAlarmInterrupt enables or disables the alarm interrupt for the specified real-time clock device.

Example
package main

import (
	"github.com/cleroux/rtc"
)

func main() {
	if err := rtc.SetAlarmInterrupt("/dev/rtc", true); err != nil {
		panic(err)
	}
}
Output:

func SetEpoch

func SetEpoch(dev string, epoch uint) (err error)

SetEpoch sets the epoch on the specified real-time clock device.

Example
package main

import (
	"github.com/cleroux/rtc"
)

func main() {
	if err := rtc.SetEpoch("/dev/rtc", 99); err != nil {
		panic(err)
	}
}
Output:

func SetFrequency

func SetFrequency(dev string, frequency uint) (err error)

SetFrequency sets the periodic interrupt frequency of the specified real-time clock device.

Example
package main

import (
	"github.com/cleroux/rtc"
)

func main() {
	if err := rtc.SetFrequency("/dev/rtc", 64); err != nil {
		panic(err)
	}
}
Output:

func SetPeriodicInterrupt

func SetPeriodicInterrupt(dev string, enable bool) (err error)

SetPeriodicInterrupt enables or disables periodic interrupts for the specified real-time clock device.

func SetTime

func SetTime(dev string, t time.Time) (err error)

SetTime sets the time for the specified real-time clock device.

Example
package main

import (
	"time"

	"github.com/cleroux/rtc"
)

func main() {
	if err := rtc.SetTime("/dev/rtc", time.Now()); err != nil {
		panic(err)
	}
}
Output:

func SetUpdateInterrupt

func SetUpdateInterrupt(dev string, enable bool) (err error)

SetUpdateInterrupt enables or disables the update interrupt for the specified real-time clock device.

func SetWakeAlarm

func SetWakeAlarm(dev string, t time.Time) (err error)

SetWakeAlarm sets the wake alarm time for the specified real-time clock device.

Types

type Alarm

type Alarm struct {
	Time time.Time
}

type RTC added in v1.0.0

type RTC struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	clock, err := rtc.NewRTC("/dev/rtc")
	if err != nil {
		panic(err)
	}
	defer clock.Close()

	t, err := clock.GetTime()
	if err != nil {
		panic(err)
	}
	fmt.Printf("Current RTC Time: %v\n", t)
}
Output:

func NewRTC

func NewRTC(dev string) (*RTC, error)

NewRTC opens a real-time clock device.

func (*RTC) CancelWakeAlarm added in v1.0.0

func (c *RTC) CancelWakeAlarm() (err error)

CancelWakeAlarm cancels the real-time clock's wake alarm.

func (*RTC) Close added in v1.0.0

func (c *RTC) Close() (err error)

Close closes a real-time clock device.

func (*RTC) GetAlarm added in v1.0.0

func (c *RTC) GetAlarm() (t time.Time, err error)

GetAlarm returns the real-time clock's alarm time.

func (*RTC) GetEpoch added in v1.0.0

func (c *RTC) GetEpoch() (epoch uint, err error)

GetEpoch returns the real-time clock's epoch.

func (*RTC) GetFrequency added in v1.0.0

func (c *RTC) GetFrequency() (frequency uint, err error)

GetFrequency returns the periodic interrupt frequency.

func (*RTC) GetTime added in v1.0.0

func (c *RTC) GetTime() (t time.Time, err error)

GetTime returns the specified real-time clock device time.

func (*RTC) GetWakeAlarm added in v1.0.0

func (c *RTC) GetWakeAlarm() (enabled bool, pending bool, t time.Time, err error)

GetWakeAlarm returns the real-time clock's wake alarm time.

func (*RTC) SetAlarm added in v1.0.0

func (c *RTC) SetAlarm(t time.Time) (err error)

SetAlarm sets the real-time clock's alarm time.

func (*RTC) SetAlarmInterrupt added in v1.0.0

func (c *RTC) SetAlarmInterrupt(enable bool) (err error)

SetAlarmInterrupt enables or disables the real-time clock's alarm interrupt.

func (*RTC) SetEpoch added in v1.0.0

func (c *RTC) SetEpoch(epoch uint) (err error)

SetEpoch sets the real-time clock's epoch.

func (*RTC) SetFrequency added in v1.0.0

func (c *RTC) SetFrequency(frequency uint) (err error)

SetFrequency sets the frequency of the real-time clock's periodic interrupt.

func (*RTC) SetPeriodicInterrupt added in v1.0.0

func (c *RTC) SetPeriodicInterrupt(enable bool) (err error)

SetPeriodicInterrupt enables or disables the real-time clock's periodic interrupts.

func (*RTC) SetTime added in v1.0.0

func (c *RTC) SetTime(t time.Time) (err error)

SetTime sets the time for the specified real-time clock device.

func (*RTC) SetUpdateInterrupt added in v1.0.0

func (c *RTC) SetUpdateInterrupt(enable bool) (err error)

SetUpdateInterrupt enables or disables the real-time clock's update interrupt.

func (*RTC) SetWakeAlarm added in v1.0.0

func (c *RTC) SetWakeAlarm(t time.Time) (err error)

SetWakeAlarm sets the real-time clock's wake alarm time.

type Tick added in v1.0.0

type Tick struct {
	Time   time.Time
	Delta  time.Duration
	Frame  uint
	Missed uint32
}

type Ticker added in v0.1.1

type Ticker struct {
	C <-chan Tick
	// contains filtered or unexported fields
}

func NewTicker

func NewTicker(dev string, frequency uint) (*Ticker, error)
Example
package main

import (
	"fmt"

	"github.com/cleroux/rtc"
)

func main() {
	ticker, err := rtc.NewTicker("/dev/rtc", 2)
	if err != nil {
		panic(err)
	}
	defer ticker.Stop()

	for tick := range ticker.C {
		fmt.Printf("Tick.  Frame:%d Time:%v Delta:%v Missed:%d\n", tick.Frame, tick.Time, tick.Delta, tick.Missed)
	}
}
Output:

func (*Ticker) Stop added in v0.1.1

func (t *Ticker) Stop()

type Timer added in v0.1.1

type Timer struct {
	C <-chan Alarm
	// contains filtered or unexported fields
}

func NewTimer

func NewTimer(dev string, d time.Duration) (*Timer, error)

NewTimer creates a new Timer that will send an Alarm with the current time on its channel after at least duration d.

Example
package main

import (
	"fmt"
	"time"

	"github.com/cleroux/rtc"
)

func main() {
	timer, err := rtc.NewTimer("/dev/rtc", time.Minute)
	if err != nil {
		panic(err)
	}
	defer timer.Stop()

	alarm := <-timer.C
	fmt.Printf("Alarm.  Time:%v\n", alarm.Time)
}
Output:

func NewTimerAt

func NewTimerAt(dev string, t time.Time) (*Timer, error)

NewTimerAt creates a new Timer that will send an Alarm on its channel after the given time.

func (*Timer) Stop added in v0.1.1

func (t *Timer) Stop() bool

Stop prevents the Timer from firing. It returns true if the call stops the timer, false if the timer has already expired or been stopped. Stop does not close the channel, to prevent a read from the channel succeeding incorrectly.

To ensure the channel is empty after a call to Stop, check the return value and drain the channel. For example, assuming the program has not received from t.C already:

if !t.Stop() {
	<-t.C
}

This cannot be done concurrent to other receives from the Timer's channel or other calls to the Timer's Stop method.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL