So first off, never assume that your reference is correct. Turns out the clock on the computer I was using is fast, so no matter what I did, my MCU always seemed slow.
With that out of the way, I used a serial terminal program on a different computer that allows for time stamps and logging, and started to graph my time offsets. Turns out there is a bit of ISR latency as suggested in this post:
Just a guess but I wonder if latency in the ISR could effect this? Like I wonder if the timer reload is somehow dependent on the ISR completing? Or the timer reload time is somehow a factor?
So if you change the timer so instead of going off every 1ms it goes off every 5ms does this change the error? 20 hours - 7.2 x 10^6 triggers - only need a small time error per timeout to get 20s error.
Tom
It changes it very slightly, which is why I couldn't see it before (as well as the computer clock being fast), but the terminal I am using logs ms as well, so when I graph it, I can see it. If I change it to a 20s period, it is fast, change it to 1 or 2 s, and it is slow. I'm guessing it is like you say, and the process to reload the timer takes more than 1 clock cycle, which is why a longer period seems better. Which is weird because the way that it is described in the datasheet, it made it seem like it should not add latency. I could adjust the period to overcome this, as I want a 1s interval.
Another thing I tried was to use the dedicated PWM module on the chip (still part of the MCU, just not directly tied to the CPU) instead of the timer. Unfortunately the prescaler is not as configurable as the timer, so I have to make it count in ms intervals, then my ISR adds 1s to my clock time variable every 1000ms. I also noticed the same latency on the PWM on anything under 5ms, but I'm guessing this could be partially because of my ISR taking too long to send the information over SCI, as well as any overhead latency it has.
260 C may still be too hot if you are using a hot air gun without a controlled thermal profile. I'd try using lead based solder at a lower temperature like 220 C, preferably with a preheater. Above 250C should only be needed for lead-free solder.
I have no idea how controlled the temperature on my hot air is, it's a cheap china made one. I use leaded solder, so I will try 220º next time, as long as I don't have to wait 10 minutes for my solder to flow :p. I do not have a preheater though...
For the new layout, the bottom grounds don't have a direct path to the chip's ground. They meander around too much. I would add a few ground vias around the crystal. Look at the example layouts of evaluation boards for inspiration.
I see what you mean with meandering, didn't notice that when I posted it. I did do some research on layout, but they don't all follow the same rules, which is why I seeked out advice on my problem.
Also, don't be afraid to rotate the crystal 30 or 45 degrees, it may make the tracks more direct, though it's probably unnecessary.
I will give this a try and see if it's more direct. I didn't see the spot for Kicad to rotate manually, but I see it now.
Maybe just live with the frequency inaccuracy, and scale your time constants accordingly?
I think this is what I'm going to do, and have the dedicated chip as an added option on my board.
When you say "dedicated clock chip", just be aware that that's a vague term that could mean one of at least two different things:
- A real-time clock chip (e.g. this) -- a device that counts time itself, and you can ask it for the time over SPI
- A crystal oscillator (e.g. FOX924), a quartz crystal, load capacitors and oscillator all in a single package, which outputs (say) 20 MHz which you can then input into your microcontroller. Eliminates concerns about stray capacitance, etc, because that's all internal to the package.
Not sure what you had in mind, but be sure to consider both.
Sorry, I meant dedicated RTC chip, with everything including the clock counter packaged in one.
Also, it's unfortunate that we can't even elucidate whether your crystal is oscillating at the wrong frequency, or whether your code is not dividing as you expected. It'd be really good to figure this out -- even if you don't have a frequency counter, you should be able to statically clock your CPU and at least check that a timer output is toggling after precisely N clocks as you expected.
I'm still not sure my crystal is oscillating at the right frequency, but do think the MCU has some overhead that is altering my clock readings. I could do what you suggest there, I still might, but for now I think I'm going to settle with that, and do some software trimming.