rtc: pseudo driver for linux + server framework
The commit also includes a test program incl. run script. Fixes #1344.
This commit is contained in:
parent
a36d0ec83a
commit
febca1b827
|
@ -0,0 +1,44 @@
|
||||||
|
# RTC test
|
||||||
|
|
||||||
|
build { core init drivers/rtc drivers/timer test/rtc }
|
||||||
|
|
||||||
|
create_boot_directory
|
||||||
|
|
||||||
|
install_config {
|
||||||
|
<config prio_levels="2" verbose="yes">
|
||||||
|
<parent-provides>
|
||||||
|
<service name="ROM"/>
|
||||||
|
<service name="RAM"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
|
<service name="IO_MEM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="CAP"/>
|
||||||
|
<service name="PD"/>
|
||||||
|
<service name="RM"/>
|
||||||
|
<service name="CPU"/>
|
||||||
|
<service name="LOG"/>
|
||||||
|
<service name="SIGNAL"/>
|
||||||
|
</parent-provides>
|
||||||
|
<default-route>
|
||||||
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
|
</default-route>
|
||||||
|
<start name="timer">
|
||||||
|
<resource name="RAM" quantum="1M"/>
|
||||||
|
<provides> <service name="Timer"/> </provides>
|
||||||
|
</start>
|
||||||
|
<start name="rtc_drv" priority="-1">
|
||||||
|
<resource name="RAM" quantum="1M"/>
|
||||||
|
<provides><service name="Rtc"/></provides>
|
||||||
|
</start>
|
||||||
|
<start name="test-rtc" priority="-1">
|
||||||
|
<resource name="RAM" quantum="1M"/>
|
||||||
|
</start>
|
||||||
|
</config>}
|
||||||
|
|
||||||
|
build_boot_image { core init timer rtc_drv test-rtc }
|
||||||
|
|
||||||
|
append qemu_args " -nographic -m 128 "
|
||||||
|
|
||||||
|
run_genode_until ".*--- RTC test finished ---.*\n" 20
|
||||||
|
|
||||||
|
puts "Test succeeded"
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* \brief Linux RTC pseudo driver
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \date 2015-01-06
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linux includes */
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
|
|
||||||
|
Genode::uint64_t Rtc::get_time(void)
|
||||||
|
{
|
||||||
|
struct timeval now { };
|
||||||
|
|
||||||
|
gettimeofday(&now, nullptr);
|
||||||
|
|
||||||
|
return now.tv_sec * 1000000ULL + now.tv_usec;
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* \brief Simple real-time-clock driver
|
* \brief RTC server
|
||||||
* \author Christian Helmuth
|
* \author Christian Helmuth
|
||||||
* \author Markus Partheymueller
|
* \date 2015-01-06
|
||||||
* \date 2007-04-18
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2013 Genode Labs GmbH
|
* Copyright (C) 2015 Genode Labs GmbH
|
||||||
* Copyright (C) 2012 Intel Corporation
|
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
@ -15,229 +13,73 @@
|
||||||
|
|
||||||
/* Genode */
|
/* Genode */
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/sleep.h>
|
#include <os/server.h>
|
||||||
#include <base/rpc_server.h>
|
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
#include <cap_session/connection.h>
|
|
||||||
#include <rtc_session/rtc_session.h>
|
#include <rtc_session/rtc_session.h>
|
||||||
#include <base/printf.h>
|
|
||||||
#include <io_port_session/connection.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
#include "rtc.h"
|
||||||
|
|
||||||
static bool verbose = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time helper
|
|
||||||
*/
|
|
||||||
bool is_leap_year(int year)
|
|
||||||
{
|
|
||||||
if (((year & 3) || !((year % 100) != 0)) && (year % 400 != 0)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return UNIX time from given date and time.
|
|
||||||
*/
|
|
||||||
uint64_t mktime(int day, int mon, int year, int hour, int minutes, int seconds)
|
|
||||||
{
|
|
||||||
bool jan_mar = mon < 3;
|
|
||||||
uint64_t ret = 0;
|
|
||||||
ret += (367*(10+mon))/12;
|
|
||||||
ret += jan_mar*2;
|
|
||||||
ret -= 719866;
|
|
||||||
ret += day;
|
|
||||||
ret += jan_mar * is_leap_year(year);
|
|
||||||
ret += 365*year;
|
|
||||||
ret += year/4;
|
|
||||||
ret -= year/100;
|
|
||||||
ret += year/400;
|
|
||||||
ret *= 24;
|
|
||||||
ret += hour;
|
|
||||||
ret *= 60;
|
|
||||||
ret += minutes;
|
|
||||||
ret *= 60;
|
|
||||||
ret += seconds;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t get_rtc_time();
|
|
||||||
|
|
||||||
namespace Rtc {
|
namespace Rtc {
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
class Session_component : public Genode::Rpc_object<Session>
|
struct Session_component;
|
||||||
{
|
struct Root;
|
||||||
public:
|
struct Main;
|
||||||
uint64_t get_current_time()
|
|
||||||
{
|
|
||||||
uint64_t ret = get_rtc_time();
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
PINF("Time is: %llx\n", ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class Root_component : public Genode::Root_component<Session_component>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Session_component *_create_session(const char *args)
|
|
||||||
{
|
|
||||||
return new (md_alloc()) Session_component();
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
Root_component(Genode::Rpc_entrypoint *ep,
|
|
||||||
Genode::Allocator *allocator)
|
|
||||||
: Genode::Root_component<Session_component>(ep, allocator)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Our RTC port session
|
|
||||||
*/
|
|
||||||
Io_port_connection *rtc_ports;
|
|
||||||
|
|
||||||
|
struct Rtc::Session_component : public Genode::Rpc_object<Session>
|
||||||
enum RTC
|
|
||||||
{
|
{
|
||||||
RTC_SECONDS = 0,
|
uint64_t get_current_time() override
|
||||||
RTC_SECONDS_ALARM = 1,
|
{
|
||||||
RTC_MINUTES = 2,
|
uint64_t ret = Rtc::get_time();
|
||||||
RTC_MINUTES_ALARM = 3,
|
|
||||||
RTC_HOURS = 4,
|
|
||||||
RTC_HOURS_ALARM = 5,
|
|
||||||
RTC_DAY_OF_WEEK = 6,
|
|
||||||
RTC_DAY_OF_MONTH = 7,
|
|
||||||
RTC_MONTH = 8,
|
|
||||||
RTC_YEAR = 9,
|
|
||||||
|
|
||||||
RTC_REG_A = 10,
|
return ret;
|
||||||
RTC_REG_B = 11,
|
}
|
||||||
RTC_REG_C = 12,
|
|
||||||
RTC_REG_D = 13,
|
|
||||||
|
|
||||||
RTC_FREQ_SELECT = RTC_REG_A,
|
|
||||||
RTC_UIP = 0x80,
|
|
||||||
RTC_DIV_CTL = 0x70,
|
|
||||||
RTC_REF_CLCK_4MHZ = 0x00,
|
|
||||||
RTC_REF_CLCK_1MHZ = 0x10,
|
|
||||||
RTC_REF_CLCK_32KHZ = 0x20,
|
|
||||||
RTC_DIV_RESET1 = 0x60,
|
|
||||||
RTC_DIV_RESET2 = 0x70,
|
|
||||||
RTC_RATE_SELECT = 0x0F,
|
|
||||||
|
|
||||||
RTC_CONTROL = RTC_REG_B,
|
|
||||||
RTC_SET = 0x80,
|
|
||||||
RTC_PIE = 0x40,
|
|
||||||
RTC_AIE = 0x20,
|
|
||||||
RTC_UIE = 0x10,
|
|
||||||
RTC_SQWE = 0x08,
|
|
||||||
RTC_DM_BINARY = 0x04,
|
|
||||||
RTC_24H = 0x02,
|
|
||||||
RTC_DST_EN = 0x01,
|
|
||||||
|
|
||||||
RTC_PORT_BASE = 0x70,
|
|
||||||
RTC_PORT_ADDR = RTC_PORT_BASE,
|
|
||||||
RTC_PORT_DATA = RTC_PORT_BASE + 1,
|
|
||||||
RTC_PORT_SIZE = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline unsigned cmos_read(unsigned char addr)
|
class Rtc::Root : public Genode::Root_component<Session_component>
|
||||||
{
|
{
|
||||||
unsigned char val;
|
protected:
|
||||||
rtc_ports->outb(RTC_PORT_ADDR, addr);
|
|
||||||
// iodelay();
|
Session_component *_create_session(const char *args)
|
||||||
val = rtc_ports->inb(RTC_PORT_DATA);
|
{
|
||||||
// iodelay();
|
return new (md_alloc()) Session_component();
|
||||||
return val;
|
}
|
||||||
}
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Root(Server::Entrypoint &ep, Allocator &md_alloc)
|
||||||
|
:
|
||||||
|
Genode::Root_component<Session_component>(&ep.rpc_ep(), &md_alloc)
|
||||||
|
{
|
||||||
|
/* trigger initial RTC read */
|
||||||
|
Rtc::get_time();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline void cmos_write(unsigned char val, unsigned char addr)
|
struct Rtc::Main
|
||||||
{
|
{
|
||||||
rtc_ports->outb(RTC_PORT_ADDR, addr);
|
Server::Entrypoint &ep;
|
||||||
// iodelay();
|
|
||||||
rtc_ports->outb(RTC_PORT_DATA, val);
|
|
||||||
// iodelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Sliced_heap sliced_heap { env()->ram_session(), env()->rm_session() };
|
||||||
|
|
||||||
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
|
Root root { ep, sliced_heap };
|
||||||
#define BCD_TO_BIN(val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
|
|
||||||
#define BIN_TO_BCD(val) ((val) = (((val)/10) << 4) + (val) % 10)
|
|
||||||
|
|
||||||
|
Main(Server::Entrypoint &ep) : ep(ep)
|
||||||
/**
|
{
|
||||||
* Get current time from CMOS and initialize values.
|
env()->parent()->announce(ep.manage(root));
|
||||||
*/
|
|
||||||
static uint64_t get_rtc_time(void)
|
|
||||||
{
|
|
||||||
unsigned year, mon, day, hour, min, sec;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* The Linux interpretation of the CMOS clock register contents:
|
|
||||||
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
|
|
||||||
* RTC registers show the second which has precisely just started.
|
|
||||||
* Let's hope other operating systems interpret the RTC the same way. */
|
|
||||||
|
|
||||||
/* read RTC exactly on falling edge of update flag */
|
|
||||||
for (i = 0 ; i < 1000000 ; i++)
|
|
||||||
if (cmos_read(RTC_FREQ_SELECT) & RTC_UIP) break;
|
|
||||||
|
|
||||||
for (i = 0 ; i < 1000000 ; i++)
|
|
||||||
if (!(cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) break;
|
|
||||||
|
|
||||||
do {
|
|
||||||
sec = cmos_read(RTC_SECONDS);
|
|
||||||
min = cmos_read(RTC_MINUTES);
|
|
||||||
hour = cmos_read(RTC_HOURS);
|
|
||||||
day = cmos_read(RTC_DAY_OF_MONTH);
|
|
||||||
mon = cmos_read(RTC_MONTH);
|
|
||||||
year = cmos_read(RTC_YEAR);
|
|
||||||
} while (sec != cmos_read(RTC_SECONDS));
|
|
||||||
|
|
||||||
/* convert BCD to binary format if needed */
|
|
||||||
if (!(cmos_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
|
||||||
BCD_TO_BIN(sec);
|
|
||||||
BCD_TO_BIN(min);
|
|
||||||
BCD_TO_BIN(hour);
|
|
||||||
BCD_TO_BIN(day);
|
|
||||||
BCD_TO_BIN(mon);
|
|
||||||
BCD_TO_BIN(year);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
if ((year += 1900) < 1970) year += 100;
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
PINF("Date:%02d.%02d.%04d Time:%02d:%02d:%02d\n", day, mon, year,
|
|
||||||
hour, min, sec);
|
|
||||||
|
|
||||||
/* return microseconds */
|
|
||||||
return mktime(day, mon, year, hour, min, sec) * 1000000ULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
/**********************
|
||||||
{
|
** Server framework **
|
||||||
static Io_port_connection ports(RTC_PORT_BASE, RTC_PORT_SIZE);
|
**********************/
|
||||||
rtc_ports = &ports;
|
|
||||||
|
|
||||||
Cap_connection cap;
|
char const * Server::name() { return "rtc_ep"; }
|
||||||
static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
|
Genode::size_t Server::stack_size() { return 1024 * sizeof(long); }
|
||||||
|
void Server::construct(Server::Entrypoint &ep) { static Rtc::Main inst(ep); }
|
||||||
enum { STACK_SIZE = 1024*sizeof(size_t) };
|
|
||||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rtc_ep");
|
|
||||||
static Rtc::Root_component rtc_root(&ep, &sliced_heap);
|
|
||||||
env()->parent()->announce(ep.manage(&rtc_root));
|
|
||||||
|
|
||||||
sleep_forever();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* \brief RTC/CMOS clock driver
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \author Markus Partheymueller
|
||||||
|
* \date 2007-04-18
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007-2015 Genode Labs GmbH
|
||||||
|
* Copyright (C) 2012 Intel Corporation
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode */
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <base/sleep.h>
|
||||||
|
#include <base/rpc_server.h>
|
||||||
|
#include <root/component.h>
|
||||||
|
#include <cap_session/connection.h>
|
||||||
|
#include <rtc_session/rtc_session.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
#include <io_port_session/connection.h>
|
||||||
|
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time helper
|
||||||
|
*/
|
||||||
|
static bool is_leap_year(int year)
|
||||||
|
{
|
||||||
|
if (((year & 3) || !((year % 100) != 0)) && (year % 400 != 0)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return UNIX time from given date and time.
|
||||||
|
*/
|
||||||
|
static uint64_t mktime(int day, int mon, int year, int hour, int minutes, int seconds)
|
||||||
|
{
|
||||||
|
bool jan_mar = mon < 3;
|
||||||
|
uint64_t ret = 0;
|
||||||
|
ret += (367*(10+mon))/12;
|
||||||
|
ret += jan_mar*2;
|
||||||
|
ret -= 719866;
|
||||||
|
ret += day;
|
||||||
|
ret += jan_mar * is_leap_year(year);
|
||||||
|
ret += 365*year;
|
||||||
|
ret += year/4;
|
||||||
|
ret -= year/100;
|
||||||
|
ret += year/400;
|
||||||
|
ret *= 24;
|
||||||
|
ret += hour;
|
||||||
|
ret *= 60;
|
||||||
|
ret += minutes;
|
||||||
|
ret *= 60;
|
||||||
|
ret += seconds;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum RTC
|
||||||
|
{
|
||||||
|
RTC_SECONDS = 0,
|
||||||
|
RTC_SECONDS_ALARM = 1,
|
||||||
|
RTC_MINUTES = 2,
|
||||||
|
RTC_MINUTES_ALARM = 3,
|
||||||
|
RTC_HOURS = 4,
|
||||||
|
RTC_HOURS_ALARM = 5,
|
||||||
|
RTC_DAY_OF_WEEK = 6,
|
||||||
|
RTC_DAY_OF_MONTH = 7,
|
||||||
|
RTC_MONTH = 8,
|
||||||
|
RTC_YEAR = 9,
|
||||||
|
|
||||||
|
RTC_REG_A = 10,
|
||||||
|
RTC_REG_B = 11,
|
||||||
|
RTC_REG_C = 12,
|
||||||
|
RTC_REG_D = 13,
|
||||||
|
|
||||||
|
RTC_FREQ_SELECT = RTC_REG_A,
|
||||||
|
RTC_UIP = 0x80,
|
||||||
|
RTC_DIV_CTL = 0x70,
|
||||||
|
RTC_REF_CLCK_4MHZ = 0x00,
|
||||||
|
RTC_REF_CLCK_1MHZ = 0x10,
|
||||||
|
RTC_REF_CLCK_32KHZ = 0x20,
|
||||||
|
RTC_DIV_RESET1 = 0x60,
|
||||||
|
RTC_DIV_RESET2 = 0x70,
|
||||||
|
RTC_RATE_SELECT = 0x0F,
|
||||||
|
|
||||||
|
RTC_CONTROL = RTC_REG_B,
|
||||||
|
RTC_SET = 0x80,
|
||||||
|
RTC_PIE = 0x40,
|
||||||
|
RTC_AIE = 0x20,
|
||||||
|
RTC_UIE = 0x10,
|
||||||
|
RTC_SQWE = 0x08,
|
||||||
|
RTC_DM_BINARY = 0x04,
|
||||||
|
RTC_24H = 0x02,
|
||||||
|
RTC_DST_EN = 0x01,
|
||||||
|
|
||||||
|
RTC_PORT_BASE = 0x70,
|
||||||
|
RTC_PORT_ADDR = RTC_PORT_BASE,
|
||||||
|
RTC_PORT_DATA = RTC_PORT_BASE + 1,
|
||||||
|
RTC_PORT_SIZE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our RTC port session
|
||||||
|
*/
|
||||||
|
static Io_port_connection & rtc_ports()
|
||||||
|
{
|
||||||
|
static Io_port_connection inst(RTC_PORT_BASE, RTC_PORT_SIZE);
|
||||||
|
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline unsigned cmos_read(unsigned char addr)
|
||||||
|
{
|
||||||
|
unsigned char val;
|
||||||
|
rtc_ports().outb(RTC_PORT_ADDR, addr);
|
||||||
|
// iodelay();
|
||||||
|
val = rtc_ports().inb(RTC_PORT_DATA);
|
||||||
|
// iodelay();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
|
||||||
|
#define BCD_TO_BIN(val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
|
||||||
|
#define BIN_TO_BCD(val) ((val) = (((val)/10) << 4) + (val) % 10)
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t Rtc::get_time(void)
|
||||||
|
{
|
||||||
|
unsigned year, mon, day, hour, min, sec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* The Linux interpretation of the CMOS clock register contents:
|
||||||
|
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
|
||||||
|
* RTC registers show the second which has precisely just started.
|
||||||
|
* Let's hope other operating systems interpret the RTC the same way. */
|
||||||
|
|
||||||
|
/* read RTC exactly on falling edge of update flag */
|
||||||
|
for (i = 0 ; i < 1000000 ; i++)
|
||||||
|
if (cmos_read(RTC_FREQ_SELECT) & RTC_UIP) break;
|
||||||
|
|
||||||
|
for (i = 0 ; i < 1000000 ; i++)
|
||||||
|
if (!(cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) break;
|
||||||
|
|
||||||
|
do {
|
||||||
|
sec = cmos_read(RTC_SECONDS);
|
||||||
|
min = cmos_read(RTC_MINUTES);
|
||||||
|
hour = cmos_read(RTC_HOURS);
|
||||||
|
day = cmos_read(RTC_DAY_OF_MONTH);
|
||||||
|
mon = cmos_read(RTC_MONTH);
|
||||||
|
year = cmos_read(RTC_YEAR);
|
||||||
|
} while (sec != cmos_read(RTC_SECONDS));
|
||||||
|
|
||||||
|
/* convert BCD to binary format if needed */
|
||||||
|
if (!(cmos_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||||
|
BCD_TO_BIN(sec);
|
||||||
|
BCD_TO_BIN(min);
|
||||||
|
BCD_TO_BIN(hour);
|
||||||
|
BCD_TO_BIN(day);
|
||||||
|
BCD_TO_BIN(mon);
|
||||||
|
BCD_TO_BIN(year);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((year += 1900) < 1970) year += 100;
|
||||||
|
|
||||||
|
return mktime(day, mon, year, hour, min, sec) * 1000000ULL;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* \brief RTC driver interface
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \date 2015-01-06
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _RTC_H_
|
||||||
|
#define _RTC_H_
|
||||||
|
|
||||||
|
#include <base/stdint.h>
|
||||||
|
|
||||||
|
namespace Rtc {
|
||||||
|
|
||||||
|
/* Get real time in microseconds since 1970 */
|
||||||
|
Genode::uint64_t get_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _RTC_H_ */
|
|
@ -1,4 +1,12 @@
|
||||||
TARGET = rtc_drv
|
TARGET = rtc_drv
|
||||||
REQUIRES = x86
|
REQUIRES = x86
|
||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
LIBS = base
|
LIBS = base server
|
||||||
|
|
||||||
|
# enforce hybrid prg on Linux
|
||||||
|
ifeq ($(filter-out $(SPECS),linux),)
|
||||||
|
SRC_CC += linux.cc
|
||||||
|
LIBS += lx_hybrid
|
||||||
|
else
|
||||||
|
SRC_CC += rtc.cc
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* \brief Test for RTC driver
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \date 2015-01-06
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
#include <rtc_session/connection.h>
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Genode::printf("--- RTC test started ---\n");
|
||||||
|
|
||||||
|
/* open sessions */
|
||||||
|
static Rtc::Connection rtc;
|
||||||
|
static Timer::Connection timer;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 4; ++i) {
|
||||||
|
Genode::uint64_t now = rtc.get_current_time();
|
||||||
|
|
||||||
|
Genode::printf("RTC: %llu.%06llu seconds since 1970\n",
|
||||||
|
now / 1000000ULL,
|
||||||
|
now % 1000000ULL);
|
||||||
|
|
||||||
|
timer.msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::printf("--- RTC test finished ---\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
TARGET = test-rtc
|
||||||
|
SRC_CC = main.cc
|
||||||
|
LIBS = base
|
Loading…
Reference in New Issue