stefanrueger / urboot

Small AVR bootloader using urprotocol
GNU General Public License v3.0
55 stars 8 forks source link

Urboot and the CLKPR register #20

Closed MCUdude closed 1 year ago

MCUdude commented 1 year ago

I looked through the MightyCore boards.txt file and realized that I had to handle the CLKPR register "manually" in the bootloader when the microcontroller is configured to run at either 4 or 2 MHz internal oscillator.

When the user selects 4MHz or 2MHz internal oscillator when using MightyCore (1 MHz is handled by setting the CKDIV8 fuse), the CLKPR register is set (in the user application) to divide the clock speed down. However, when the chip receives a hardware reset, the CLKPR register doesn't get cleared but keeps the microcontroller running at 4 or 2 MHz. This is now a problem since the baud rate the bootloader will accept is now changed due to the CLKPR register.

Have you thought of this issue? With Optiboot flash, I always cleared the CLKPR so that the microcontroller was running at a known, 8 MHz speed.

https://github.com/MCUdude/optiboot_flash/blob/0d634cc1302ad3b1dcb137256edc5a7da5ab0725/optiboot_flash.c#L525-L529

stefanrueger commented 1 year ago

| when the chip receives a hardware reset, the CLKPR register doesn't get cleared when the chip receives a hardware reset

According to Microchip's general CLKPR documentation

The CKDIV8 Fuse determines the initial value of the CLKPS bits. If CKDIV8 is unprogrammed, the CLKPS bits will be reset to “0000”. If CKDIV8 is programmed, CLKPS bits are reset to “0011”, giving a division factor of 8 at start up.

My take from the documentation is that CLKPR will be reset to either 8 MHz or 1 MHz on external reset.

Which part was it where you observed that behaviour? Can you double-check with that part's datasheet and/or experimentation that reset really keeps the previous setting?

My reading of your code is that it "heals" a factory (or otherwise) CKDIV8 fuse setting (ie, F_CPU 1 MHz) if the wrong bootloader for that fuse setting was chosen. However, even if the user can upload a program they'd still be stuck with that 1 MHz setting, not?

My recommendation is to document that a bootloader with the correct F_CPU needs to be put on the part, and that F_CPU depends on the fuse setting for CKDIV8 (and other fuses, such as internal/external clock).

MCUdude commented 1 year ago

I'll try a few chips to determine if it was just a silicon bug or if this is a real thing on all AVRs.

MCUdude commented 1 year ago

I've tried playing with the CLKPR register on an ATmega328P, ATmega324PB, ATmega1284P, and ATmega2560, and on every chip the CLKPR register is restored to its initial state (CLKDIV1) when a hardware reset occurs.

I can't remember which part I used back when I discovered this "bug", but I'm sure it exists somewhere because I went through a lot of trouble to get the Arduino boards.txt right.