LPC1768 RTC frequency check with WDT. Compare RTC against MCU's microsecond Timer.
Check LPC1768 RTC crystal frequency using WDT. Measure with MCU's microsecond Timer. The MCU's crystal may be off a bit as well. I measured the RTC frequency error at 22 ppm. The spec for the RTC crystal is 20 ppm. Using NTP and a GPS, I had measured the MCU's crystal frequency error at -2 ppm.
Frequency measurements for other MCU/RTC cyrstals at
https://github.com/manitou48/crystals/blob/master/crystals.txt
main.cpp@0:11cc29f22037, 2015-11-16 (annotated)
- Committer:
- manitou
- Date:
- Mon Nov 16 16:56:32 2015 +0000
- Revision:
- 0:11cc29f22037
LPC1768 RTC freq check with WDT
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
manitou | 0:11cc29f22037 | 1 | // use WDT to measure drift of RTC and IRC |
manitou | 0:11cc29f22037 | 2 | // seems WDT ISR will only fire once |
manitou | 0:11cc29f22037 | 3 | #include "mbed.h" |
manitou | 0:11cc29f22037 | 4 | |
manitou | 0:11cc29f22037 | 5 | DigitalOut led1(LED1); |
manitou | 0:11cc29f22037 | 6 | uint32_t ticks; |
manitou | 0:11cc29f22037 | 7 | |
manitou | 0:11cc29f22037 | 8 | void kick() { |
manitou | 0:11cc29f22037 | 9 | __disable_irq(); |
manitou | 0:11cc29f22037 | 10 | LPC_WDT->WDFEED = 0xAA; |
manitou | 0:11cc29f22037 | 11 | LPC_WDT->WDFEED = 0x55; |
manitou | 0:11cc29f22037 | 12 | __enable_irq(); |
manitou | 0:11cc29f22037 | 13 | } |
manitou | 0:11cc29f22037 | 14 | |
manitou | 0:11cc29f22037 | 15 | void isr_wdt(void) { |
manitou | 0:11cc29f22037 | 16 | ticks++; |
manitou | 0:11cc29f22037 | 17 | led1 = 1; |
manitou | 0:11cc29f22037 | 18 | LPC_WDT->WDMOD |= (1<<3); |
manitou | 0:11cc29f22037 | 19 | // LPC_WDT->WDMOD &= ~(1<<2); |
manitou | 0:11cc29f22037 | 20 | // kick(); |
manitou | 0:11cc29f22037 | 21 | } |
manitou | 0:11cc29f22037 | 22 | |
manitou | 0:11cc29f22037 | 23 | void wdt_init() { |
manitou | 0:11cc29f22037 | 24 | LPC_WDT->WDCLKSEL = 0x2; // Set CLK src 0 IRC 1 PCLK 2 RTC |
manitou | 0:11cc29f22037 | 25 | // uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 |
manitou | 0:11cc29f22037 | 26 | LPC_WDT->WDTC = 0xfffffff; // max countdown |
manitou | 0:11cc29f22037 | 27 | LPC_WDT->WDMOD = 0x01; // enable but no reset |
manitou | 0:11cc29f22037 | 28 | NVIC_SetVector(WDT_IRQn, (uint32_t)&isr_wdt); |
manitou | 0:11cc29f22037 | 29 | NVIC_ClearPendingIRQ(WDT_IRQn); |
manitou | 0:11cc29f22037 | 30 | NVIC_EnableIRQ(WDT_IRQn); |
manitou | 0:11cc29f22037 | 31 | kick(); |
manitou | 0:11cc29f22037 | 32 | } |
manitou | 0:11cc29f22037 | 33 | |
manitou | 0:11cc29f22037 | 34 | int main() { |
manitou | 0:11cc29f22037 | 35 | uint32_t t,t0=0,us,us0,prev; |
manitou | 0:11cc29f22037 | 36 | int ppm; |
manitou | 0:11cc29f22037 | 37 | Timer tmr; |
manitou | 0:11cc29f22037 | 38 | tmr.start(); |
manitou | 0:11cc29f22037 | 39 | printf("hello %x\n",LPC_WDT->WDMOD); |
manitou | 0:11cc29f22037 | 40 | wait(1.0); |
manitou | 0:11cc29f22037 | 41 | wdt_init(); |
manitou | 0:11cc29f22037 | 42 | prev=LPC_WDT->WDTV; |
manitou | 0:11cc29f22037 | 43 | while(1) { |
manitou | 0:11cc29f22037 | 44 | t=LPC_WDT->WDTV; |
manitou | 0:11cc29f22037 | 45 | us = tmr.read_us(); |
manitou | 0:11cc29f22037 | 46 | if (t0==0 || t0 == 255) { |
manitou | 0:11cc29f22037 | 47 | t0 = t; |
manitou | 0:11cc29f22037 | 48 | us0 = us; |
manitou | 0:11cc29f22037 | 49 | } |
manitou | 0:11cc29f22037 | 50 | double tf = (t0-t)/8192.; // /8192 for rtc 1000000 for IRC |
manitou | 0:11cc29f22037 | 51 | double secs = 1.e-6*(us-us0); |
manitou | 0:11cc29f22037 | 52 | ppm = 1.e6*(tf-secs)/secs; |
manitou | 0:11cc29f22037 | 53 | printf("ticks %d %d %u %d us %x %d ppm \n",ticks,prev-t,t0-t,us-us0,t,ppm); |
manitou | 0:11cc29f22037 | 54 | prev=t; |
manitou | 0:11cc29f22037 | 55 | wait(2.0); |
manitou | 0:11cc29f22037 | 56 | } |
manitou | 0:11cc29f22037 | 57 | } |