Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: AT91SAM9260 RTC
PostPosted: Wed Jun 04, 2008 6:12 pm 
Offline

Joined: Fri May 04, 2007 11:02 am
Posts: 23
I use Linux4SAM demo for AT91SAM9260. I have problem with hwclock command:
Code:
root@at91sam9263ek:~$ hwclock
hwclock: Could not read time from RTC: Invalid or incomplete multibyte or wide character


in /dev/ I have rtc device.

Thanks and regards,
David


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 05, 2008 9:06 am 
Offline

Joined: Thu Jun 05, 2008 8:56 am
Posts: 5
You must first set a valid timer char (for example 2006.xx.xx), in the rtc kernel modul. After this you can call:

date -s "20080605 091400"
hwclock --systohc



example rtc-at91.sam9.c (drivers/rtc direrctory) :

/*
* Initialize and install RTC driver
*/
static int __init at91_rtc_probe(struct platform_device *pdev)
{
struct resource *r;
struct sam9_rtc *rtc;
int ret;
u32 mr;

r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r)
return -ENODEV;

rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
if (!rtc)
return -ENOMEM;

platform_set_drvdata(pdev, rtc);
rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
rtc->rtt += r->start;

mr = rtt_readl(rtc, MR);

/* unless RTT is counting at 1 Hz, re-initialize it */
if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) {
mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES);
gpbr_writel(rtc, 0);
}

/* disable all interrupts (same as on shutdown path) */
mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
rtt_writel(rtc, MR, mr);

rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev,
&at91_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtcdev)) {
ret = PTR_ERR(rtc->rtcdev);
goto fail;
}

/* register irq handler after we know what name we'll use */
ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
IRQF_DISABLED | IRQF_SHARED,
rtc->rtcdev->dev.bus_id, rtc);
if (ret) {
dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
rtc_device_unregister(rtc->rtcdev);
goto fail;
}

/* NOTE: sam9260 rev A silicon has a ROM bug which resets the
* RTT on at least some reboots. If you have that chip, you must
* initialize the time from some external source like a GPS, wall
* clock, discrete RTC, etc
*/

if (gpbr_readl(rtc) == 0) {
dev_warn(&pdev->dev, "%s: SET TIME ! sam9260 Rev A?\n",rtc->rtcdev->dev.bus_id);


unsigned int mr_2;
mr_2 = at91_sys_read(AT91_WDT_MR);
printk(KERN_ERR "crt: Watchdog register . %u\n",mr_2);


struct rtc_time tm2;
tm2.tm_year=118;
tm2.tm_mon=1;
tm2.tm_mday=1;

struct rtc_time *tm=&tm2;


int err;
u32 offset, alarm, mr;
unsigned long secs;
dev_dbg(&pdev->dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);

err = rtc_tm_to_time(tm, &secs);
if (err != 0)
return err;

mr = rtt_readl(rtc, MR);

/* disable interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));

/* read current time offset */
offset = gpbr_readl(rtc);

/* store the new base time in a battery backup register */
secs += 1;
gpbr_writel(rtc, secs);

/* adjust the alarm time for the new base */
alarm = rtt_readl(rtc, AR);
if (alarm != ALARM_DISABLED) {
if (offset > secs) {
/* time jumped backwards, increase time until alarm */
alarm += (offset - secs);
} else if ((alarm + offset) > secs) {
/* time jumped forwards, decrease time until alarm */
alarm -= (secs - offset);
} else {
/* time jumped past the alarm, disable alarm */
alarm = ALARM_DISABLED;
mr &= ~AT91_RTT_ALMIEN;
}
rtt_writel(rtc, AR, alarm);
}

/* reset the timer, and re-enable interrupts */
rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST);

return 0;

}
return 0;

fail:
platform_set_drvdata(pdev, NULL);
kfree(rtc);
return ret;
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 05, 2008 9:07 am 
Offline

Joined: Thu Jun 05, 2008 8:56 am
Posts: 5
for example the "valid date" in the source:

struct rtc_time tm2;
tm2.tm_year=118;
tm2.tm_mon=1;
tm2.tm_mday=1;


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 05, 2008 4:06 pm 
Offline

Joined: Fri May 04, 2007 11:02 am
Posts: 23
Thank you very much!
It works now.

David


Top
 Profile  
 
 Post subject: RTC
PostPosted: Fri Aug 08, 2008 11:15 am 
Offline

Joined: Fri Aug 08, 2008 11:02 am
Posts: 1
Hi I have the same problem as above -=> Board is a AT91-SAM9-L9260 from Olimex and running kernel 2.6.26.2. This has been a marked improvement from the packaged 2.6.23 as the board is now able to keep time correctly (which wasn't happening before I think because of CPU speed not being set correctly in the kernel)

Compiled kernel to include RTC support so that should be OK-> have /dev/rtc and /dev/rtc0.

I am not sure exactly what the above workaround means- do I need to change the /driver/RTC/rtc-at91.sam9.c file to be what is written there?

I have tried this and kernel compilation fails? My file is slightly different to this file - mine does not include

----------------------------------------------------------
unsigned int mr_2;
mr_2 = at91_sys_read(AT91_WDT_MR);
printk(KERN_ERR "crt: Watchdog register . %u\n",mr_2);


struct rtc_time tm2;
tm2.tm_year=118;
tm2.tm_mon=1;
tm2.tm_mday=1;

struct rtc_time *tm=&tm2;


int err;
u32 offset, alarm, mr;
unsigned long secs;
dev_dbg(&pdev->dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);

err = rtc_tm_to_time(tm, &secs);
if (err != 0)
return err;

mr = rtt_readl(rtc, MR);

/* disable interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));

/* read current time offset */
offset = gpbr_readl(rtc);

/* store the new base time in a battery backup register */
secs += 1;
gpbr_writel(rtc, secs);

/* adjust the alarm time for the new base */
alarm = rtt_readl(rtc, AR);
if (alarm != ALARM_DISABLED) {
if (offset > secs) {
/* time jumped backwards, increase time until alarm */
alarm += (offset - secs);
} else if ((alarm + offset) > secs) {
/* time jumped forwards, decrease time until alarm */
alarm -= (secs - offset);
} else {
/* time jumped past the alarm, disable alarm */
alarm = ALARM_DISABLED;
mr &= ~AT91_RTT_ALMIEN;
}
rtt_writel(rtc, AR, alarm);
}

/* reset the timer, and re-enable interrupts */
rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST);

return 0;

}
-------------------------------------------------------


let me know if I am just being silly- I would really like to get the RTC running

Thanks in advance


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: