stefanrueger / urboot

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

Urboot for ATTiny13/A #19

Closed MCUdude closed 1 year ago

MCUdude commented 1 year ago

Unlike other AVRs, the internal oscillator in the ATtiny13/A runs at 9.6 MHz and is dividable down to 4.8 MHz, 1.2MHz, and 600kHz. It would be great if these existed pre-compiled bootloaders for these clock speeds!

MCUdude commented 1 year ago

Do you have a suggestion that makes github display these files in the "right" order?

Not really, at least not something that ticks all the boxes.

Instead of flashing bootloaders that are compiled to be slightly slower or faster than the built-in oscillator, I think I'll instead slightly increase or decrease the baud rate. The effect is the same, but it makes it way easier to make it work seamlessly in Arduino IDE. The returning problem is that all menu options are static, so if all menu options would be valid, I'll have to provide "slightly off" bootloaders for all the external oscillator options as well.

MCUdude commented 1 year ago

After trying to get the new naming convention to work with Arduino IDE, I have some thoughts. The "older" style was easier to work with from an Arduino point of view. The bootloader was just more predictable, as there was no padding, but everything is possible, it's just a bit more work

attiny13a/internal_oscillator/4.8MHz/38400bps/urboot_attiny13a_4.8MHz_38400bps_swio_rxb1_txb0_led+b2.hex attiny13a/external_oscillator/18.432MHz/115200bps/urboot_attiny13a_18.432MHz_115200bps_swio_rxb1_txb0_led+b2.hex

stefanrueger commented 1 year ago

Maybe we should distinguish between directory names and file names. The directory names should have padding to allow for numeric sorting in github. There can now be 30+ different fcpu and baud rates.

A directory like this will be much easier to navigate than this order: fcpu_0.125MHz fcpu_0.2304MHz fcpu_0.25MHz fcpu_0.4608MHz fcpu_0.5MHz fcpu_0.9216MHz fcpu_10MHz fcpu_11.0592MHz fcpu_12MHz fcpu_1.3824MHz fcpu_14.7456MHz fcpu_1.5MHz fcpu_16MHz fcpu_1.8432MHz fcpu_18.432MHz fcpu_1MHz fcpu_20MHz fcpu_22.1184MHz fcpu_2.304MHz fcpu_24MHz fcpu_2.5MHz fcpu_2.7648MHz fcpu_2MHz fcpu_3.6864MHz fcpu_3MHz fcpu_4.608MHz fcpu_4MHz fcpu_5.5296MHz fcpu_5MHz fcpu_6MHz fcpu_7.3728MHz fcpu_8MHz fcpu_9.216MHz

see no need for the i (for internal) and x (for external) in the file names

In filenames this is as redundant as is the part name, fcpu and br. I want the filename to be unique, though: no two bootloaders in the mcus directory tree have the same file name. In theory you could put them all in a single directory.

'i' and 'x' bootloaders are different: 'i' ones have a quantisation error of max 0.5% and 'x' ones of max 2.1%. Allowing higher quantisation error potentially makes the code smaller (eg, UART in classic parts with high baud rates have high quant error).

The philosophy is that I want +/- 2.5%. External oscillators are at worst 0.2% off, so can afford to generate 2.1% quantisation error. Internal oscillators have a factory error of up to 2%, so want to force quant error to below 0.5%. Of course you can use either type for either oscillator. For bootloaders following a series fcpu-4%, fcpu-3%, ... fcpu+4% it only makes sense to offer 'i' types: they cover a frequency spectrum and neighbours are never farther than 2% from each other in terms of fcpu...

How about changing from

cores/minicore/atmega328p/external_oscillator/fcpu+16m0000_Hz/br++115k2_bps/urboot+atmega328p+16m0000x++115k2_uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

to

cores/MiniCore/ATmega328P/external_oscillator/fcpu+16.000000_MHz/br++115.200_kbps/urboot_m328p_16m0x115k2+uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

MCUdude commented 1 year ago

From a boards.txt point of view, it's actually better to have one notation for the target name, f_cpu, and baud rate. If not, I'll have to deal with all these variants (see below) manually.

Lowercase notation for the AVR part number is much better, as this is already defined in boards.txt.

Instead of this notation

cores/MiniCore/ATmega328P/external_oscillator/fcpu+16.000000_MHz/br++115.200_kbps/urboot_m328p_16m0x115k2+uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

boards.txt would be way easier to read and manage if it was like this instead.

cores/MiniCore/atmega328p/external_oscillator/fcpu+16.000000_MHz/br++115.200_kbps/urboot_atmega328p_16.000000_115.200_uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

But the absolute best for Arduino use would be this (same way I named optiboot flash), but it doesn't sort all that well.

cores/MiniCore/atmega328p/external_oscillator/16000000L/115200/urboot_atmega328p_16000000L_115200_uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

How to deal with the "second best option" to get the bootloader file name based on the settings in the IDE tools menu:

# build.mcu and upload.port are defined elsewhere in boards.txt as both of these are user selectable
328.menu.clock.16MHz_external=External 16 MHz
328.menu.clock.16MHz_external.urboot.type=external_oscillator
328.menu.clock.16MHz_external.upload.speed=115200
328.menu.clock.16MHz_external.urboot.speed=115.200
328.menu.clock.16MHz_external.build.f_cpu=16000000L
328.menu.clock.16MHz_external.utboot.clockspeed=16.000000

328.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/{urboot.type}/fcpu+{urboot.clockspeed}_MHz/br++{urboot.speed}_kbps/urboot_{build.mcu}_{urboot.clockspeed}_{urboot.speed}_{upload.port}_rxd0_txd1_ee_led+b5_fr_ce.hex

How to deal with the best option:

328.menu.clock.16MHz_external=External 16 MHz
328.menu.clock.16MHz_external.urboot.type=external_oscillator
328.menu.clock.16MHz_external.upload.speed=115200
328.menu.clock.16MHz_external.build.f_cpu=16000000L

328.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/{urboot.type}/{build.f_cpu}/{upload.speed}/urboot_{build.mcu}_{build.f_cpu}_{upload.speed}_{upload.port}_rxd0_txd1_ee_led+b5_fr_ce.hex

As you can see, the boards.txt file gets significantly less complicated in the second example, and I'll have to add the same fields for every clock frequency option that's possible to select in Arduino IDE (328.menu.clock.20MHz_external, 328.menu.clock.18.432MHz_external)

stefanrueger commented 1 year ago

Yes, there is always the tension between human readable and machine readable.

better to have one notation for the target name, f_cpu, and baud rate

That's what is currently the case, not? You just dislike the visuals of the +, or?

Also, I like short names. How about

cores/minicore/atmega328p/external_oscillator/fcpu+16x0/br++115k2/urboot_atmega328p_16x0_115k2_uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

i and x are important for the reasons outlined above. Think of them as tolerance bands as in resistors.

MCUdude commented 1 year ago

That's what is currently the case, not?

Sorry about that, you're absolutely right. f_cpu and baud rate are the same as your suggestion. I have no problems with the + being there, but I'll have to deal with them manually if the number of plusses varies from folder to folder and file to file.

Also, I like short names. How about

cores/minicore/atmega328p/external_oscillator/fcpu+16x0/br++115k2/urboot_atmega328p_16x0_115k2_uart0_rxd0_txd1_ee_led+b5_fr_ce.hex

This absolutely works! But will the folder that contains the 57600 baud bootloader be named br+++57k6? If yes, I'll have to deal with this like so:

 build.mcu and upload.port are defined elsewhere in boards.txt as both of these are user selectable
328.menu.clock.16MHz_external=External 16 MHz
328.menu.clock.16MHz_external.urboot.type=external_oscillator
328.menu.clock.16MHz_external.urboot.clockspeed_plusses=+
328.menu.clock.16MHz_external.urboot.baud_plusses=++
328.menu.clock.16MHz_external.upload.speed=115200
328.menu.clock.16MHz_external.urboot.speed=115k2
328.menu.clock.16MHz_external.build.f_cpu=16000000L
328.menu.clock.16MHz_external.utboot.clockspeed=16x0

328.menu.clock.8MHz_external=External 8 MHz
328.menu.clock.8MHz_external.urboot.type=external_oscillator
328.menu.clock.16MHz_external.urboot.clockspeed_plusses=++
328.menu.clock.8MHz_external.urboot.baud_plusses=+++
328.menu.clock.8MHz_external.upload.speed=57600
328.menu.clock.8MHz_external.urboot.speed=57k6
328.menu.clock.8MHz_external.build.f_cpu=8000000L
328.menu.clock.8MHz_external.utboot.clockspeed=8x0

328.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/{urboot.type}/fcpu{urboot.clockspeed_plusses}{urboot.clockspeed}/br{urboot.baud_plusses}{urboot.speed}/urboot_{build.mcu}_{urboot.clockspeed}_{urboot.speed}_{upload.port}_rxd0_txd1_ee_led+b5_fr_ce.hex

As you can see, this adds more lines to the file that "doesn't do anything" apart from dealing with padding.

stefanrueger commented 1 year ago

padding

Can the 328.menu.bootloader.uart0.bootloader.file entry contain wildcards? Then you could use .../fcpu*+{urboot.clockspeed}/br*+{urboot.speed}/..

I would generate the board entries with a program. Doing that by hand is punishing

MCUdude commented 1 year ago

Can the 328.menu.bootloader.uart0.bootloader.file entry contain wildcards?

Sadly, no.

I would generate the board entries with a program.

That would absolutely be the best, but to me, this is currently more work than implementing this manually in boards.txt.

However, if the padding plusses were used in the file name as well, I could take a shortcut:

build.mcu and upload.port are defined elsewhere in boards.txt as both of these are user selectable

328.menu.clock.16MHz_external=External 16 MHz
328.menu.clock.16MHz_external.urboot.type=external_oscillator
328.menu.clock.16MHz_external.upload.speed=115200
328.menu.clock.16MHz_external.urboot.speed=++115k2
328.menu.clock.16MHz_external.build.f_cpu=16000000L
328.menu.clock.16MHz_external.utboot.clockspeed=+16x0

328.menu.clock.8MHz_external=External 8 MHz
328.menu.clock.8MHz_external.urboot.type=external_oscillator
328.menu.clock.8MHz_external.upload.speed=57600
328.menu.clock.8MHz_external.urboot.speed=+++57k6
328.menu.clock.8MHz_external.build.f_cpu=8000000L
328.menu.clock.8MHz_external.utboot.clockspeed=++8x0

328.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/{urboot.type}/fcpu{urboot.clockspeed}/br{urboot.speed}/urboot_{build.mcu}_{urboot.clockspeed}_{urboot.speed}_{upload.port}_rxd0_txd1_ee_led+b5_fr_ce.hex
stefanrueger commented 1 year ago

Let me think about this over the weekend. I am sure I find a good solution.

stefanrueger commented 1 year ago

build.mcu and upload.port are defined elsewhere in boards.txt

This is one more difficulty unless you define upload.port as uart0_rxd0_txd1. Otherwise if the user chooses uart1 the rx/tx that is currently a constant in your upload file {upload.port}_rxd0_txd1 is wrong. I know that rx/tx is a derministic function of the uart, but that is not the case for swio_rxd0_txd1. And I find that this kind of naming redundancy helps users who otherwise might ask And where the heck am I supposed to hook up uart2?

Also to consider external_oscillator does not always use UARTs: for a certain fcpu/br combo it may well be SWIO (just because there is no way that UART has a quantisation error within 2.1%). And vice versa, internal_oscillator may well be using an UART just because that happens to be pitch perfect (and smaller and therefore preferable).

MCUdude commented 1 year ago

This is one more difficulty unless you define upload.port as uart0_rxd0_txd1

Yes, I'll have to add 328.menu.bootloader.uart0.upload.port=uart0_rxd0_txd1. instead of the current 328.menu.bootloader.uart0.upload.port=UART0. Good idea. I'm only using upload.port to identify the UART number when the bootloader file is selected.

Also to consider external_oscillator does not always use UARTs

Correct, but my plan is to only offer hardware UART bootloaders with MiniCore. MicroCore, however, will use swio.

stefanrueger commented 1 year ago

only offer hardware UART bootloaders with MiniCore

72 of the 370 fcpu/br combos don't use the UART b/c the quantisation error is too large, most famously 8 MHz/115,200 baud. If you compile the external C program bauderror.c in this repo you can obtain the quantisation error in detail.

stefanrueger commented 1 year ago

It's easy to do, though, just add 328.menu.bootloader.uart0.upload.port=swio_rxd0_txd1

Whenever the quantisation error is too big, it's swio_rx... that are generated instead of uartn_rx...

MCUdude commented 1 year ago

The new names for the files and folder in the cores folder work great with Arduino IDE! One thing though. Could you please provide -6% and -8% bootloaders for the ATtiny13 as well? I have a chip here that won't work with the default 4.8MHz internal oscillator bootloader unless I use a baudrate of 4500 instead of 4800.

stefanrueger commented 1 year ago

OK, a wider spread is needed than I imagined. How about the variation is in steps of 1.25% and has a range of 13 steps from -7.5% to 7.5%? Would that work? Coincidentally, 4500 = 4800-6.25%

MCUdude commented 1 year ago

I have never seen an internal oscillator being faster than it should, only slower. And since UART can handle a few percent errors, it should be fine with 1.5 or 2% steps I think.

How about:
104%, 102%, 100%, 98%, 96%, 94%, 92%, 90%

This should even cover the chips that "fell off the delivery truck" and sold on the black market.

MCUdude commented 1 year ago

I read on a forum that some ATtiny13 chips are as bas as 10% off sometimes. Usually, the 4.8MHz one is the worst, because the default calibration value that gets automatically is for the 9.6 MHz one.

Which means that in order get the 4.8MHz oscillator to be consistent, we'll have to read the second byte in the calibration register using Avrdude, and ideally write this to a fixed address so that the bootloader can load this value into its OSCCAL register. This isn't currently possible using Avrdude 7.1, but with the feature suggested in https://github.com/avrdudes/avrdude/issues/1322, I think it should be possible. However, it's probably difficult to make ut fit within 256 bytes.

stefanrueger commented 1 year ago

can handle a few percent errors

TLDR; 2% stepping is too big, and 1% too conservative. 1.25% to 1.5% seem right

Back of the envelope: if the onset of a transmitted bit is 25% of its width early or late comms start getting into murky waters. Errors accumulate over the 10 start, data and stop bits, so can afford 2.5% bit error rate, which is composed of (worst case) sender quantisation error, sender frequency error, receiver quantisation error and receiver frequency error. Assuming the host PC has perfect comms we should really not go above 2.5% for bootloader. The quantisation error can be finely controlled by urboot's SWIO, and it is set to 6000 ppm (0.6%) in mkurboots. It can still be that it is -0.6% on one step and +0.6% in the next step, so two neighbouring effective frequencies can be 1.2% plus step size apart. That would be 2.45% if the step size is chosen to be 1.25%. The step size could be set bigger (max 1.9%) but going there means the internal frequency has no further leeway during operation in terms of ageing or temperature change.

stefanrueger commented 1 year ago

never seen an internal oscillator being faster than it should, only slower

That's interesting! Could make boundaries asymmetric. Is that documented somewhere? Is it plausible owing to the waty factory calibration and/or the workings of the OSCCAL register.

MCUdude commented 1 year ago

never seen an internal oscillator being faster than it should, only slower

Well, when thinking about it, I once had an ATtiny13 where the internal 4.8 MHz oscillator ran at ~5.0 MHz, but this was most likely because the 9.6MHz calibration value was automatically loaded.

Again, the 9.6MHz oscillator is usually fine, it's just a few percent off. It's the 4.8MHz that's causing problems. And I haven't been able to use the bootloader with the internal 128kHz oscillator. Probably because this way too "off". The datasheet even states that its frequency varies with voltage, temperature and batch number. In other words, not very dependable.

mcuee commented 1 year ago

I read on a forum that some ATtiny13 chips are as bas as 10% off sometimes. Usually, the 4.8MHz one is the worst, because the default calibration value that gets automatically is for the 9.6 MHz one.

Which means that in order get the 4.8MHz oscillator to be consistent, we'll have to read the second byte in the calibration register using Avrdude, and ideally write this to a fixed address so that the bootloader can load this value into its OSCCAL register. This isn't currently possible using Avrdude 7.1, but with the feature suggested in avrdudes/avrdude#1322, I think it should be possible. However, it's probably difficult to make ut fit within 256 bytes.

In the end, this may be the better way to go for users who want to run the urboot bootloader for ATtiny13A at 4.8MHz, even if the bootloader side can not fit in 256 Bytes.

mcuee commented 1 year ago

Other than this ATtiny13/13A, are there any other AVR MCUs have this type of two OSSCAL value for two internal oscillator frequency?

stefanrueger commented 1 year ago

ideally write this to a fixed address so that the bootloader can load this value into its OSCCAL register

How does the calibration byte come to be in flash in the first instance? Once the calibration byte has been written to flash, then the additional step (min 8 bytes code) in the bootloader to fetch that byte from that flash location and store it in OSCCAL is equivalent to using a different bootloader with the correct frequency (typically the code size stays roughly the same for different frequencies). So, if the external calibration process that burns the calibration byte into flash were to burn the bootloader with the correct frequency into flash then that step could be saved.

Does the modified OSCCAL register survive a WDR? I suspect every type of reset will load the factory calibration value and store that into OSCCAL. A bootloader normally starts the application through a WDR, so the application has to set OSCCAL again (if wants to/needs to).

Do you have a natural flash address for the calibration byte?

Another idea is to put a 8-byte subroutine at FLASHEND-6-8+1 (just below the 6-byte table at FLASHEND)

calibrate:
    ldi r24,%[oscalvalue]
    sts %[oscalregister], r24
    ret

Together with an rcall calibration at the beginning of the bootloader this would enlarge the bootloader by 10 bytes. Shorter that the reset-vector protection (that I find overrated as it only kicks in when the user writes to flash in own routines using the bootloader, for the rest avrdude -c urclock looks after the reset vector). Any application can then cast the word address (FLASHEND-14UL+1UL)/2 to a function pointer and call the calibration routine as

   ((void (*)(void))((FLASHEND-14UL+1UL)/2))();

Not pretty, but should work. Any external re-calibration procedure would write the two-byte opcode ldi r1,0xYZ rather than a single calibration byte to the flash address FLASHEND-6-8+1.

An alternative 6-byte solution is to simply have ldi r24,value, sts osccal,r24 as first thing in the bootloader. As above external calibration could change the ldi opcode at bootloader start. An application can read the table at the end of flash to figure out the start of the bootloader, load the ldi opcode there, and mask the OSCCAL value out and store it there. Many more bytes (for the application) though than the call to the calibration routine above.

All things considered, I still prefer the bootloader not deal with OSCCAL; instead select an appropriate b/loader for that part. The user is free to do with OSCCAL what they want (EEPROM/Flash/ignore/let the user press x repeatedly at application start until the application that successively changes OSCCAL can read the x and thus knows the frequency is now right/...).

mcuee commented 1 year ago

@stefanrueger

I could be wrong but I think by second byte in the calibration register, @MCUdude means to say the 2nd byte of the Calibration Bytes.

Section 17.3, page 111 of the ATtiny13A datasheet https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/ATtiny13A-Data-Sheet-DS40002307A.pdf

The signature area of the ATtiny13A contains two bytes of calibration data for the internal oscillator. The calibration data in the high byte of address 0x00 is for use with the oscillator set to 9.6 MHz operation. During reset, this byte is automatically written into the OSCCAL register to ensure correct frequency of the oscillator.

There is a separate calibration byte for the internal oscillator in 4.8 MHz mode of operation but this data is not loaded automatically. The hardware always loads the 9.6 MHz calibration data during reset. To use separate calibration data for the oscillator in 4.8 MHz mode the OSCCAL register must be updated by firmware. The calibration data for 4.8 MHz operation is located in the high byte at address 0x01 of the signature area.

stefanrueger commented 1 year ago

@mcuee Thanks for the explanation. OK, so the calibration value can come from the second calibration byte of the signature area. The suggestion is that some external mechanism (AVRDUDE?) reads that byte and copies it to flash, so that the bootloader does not need to go to the expense of reading the actual (second) calibration byte. Alternatively, some external calibration mechanism could measure the actual internal 4.8 MHz clock (you rig up your chip-scale atomic clock (check out the purchase price here) to twiddle a pin once a second, upload a sketch that computes the perfect calibration byte and stores that in the flash location).

I was thinking aloud about the workflow and where to put that calibration value (a fixed flash location outside the bootloader, a fixed flash location within the bootloader, encoded as part of an ldi r24,... command in a bootloader subroutine etc) and what to do then. If you rig up an external clock source (a little quartz for a few pence will do as well :) to measure the frequency of the target AVR's oscillator with a sketch then you might as well select the right bootloader and burn that - rather than burning that calibration value to flash.

MCUdude commented 1 year ago

Yes, what I was trying to say was that there is currently no easy way of getting hold of the second byte in the calibration register. If it was, it would be cool if it was possible to "inject" this into the existing bootloader in flash somehow. But even this value isn't always spot on, and the user would still have to choose a bootloader to match their now "slightly off" oscillator.

BTW I'm pretty much finished implementing Urboot for MicroCore! I'll have to do a bit more testing (I can't get the bootloader to work when running at the internal 128kHz WDT oscillator), but I think I'm ready for a new MicroCore release very soon.

Thank you so much @stefanrueger for your help, knowledge and last but not least, patience! A reliable bootloader for the ATtiny13 (or any classic ATtiny for that matter) would still be a far-fetched dream if it wasn't for your excellent Urboot bootloader.

image
stefanrueger commented 1 year ago

This bootloader menu looks so cool! Note I have in the meantime pushed +/- 8.75% too.

running at the internal 128kHz WDT oscillator

The intl 128 kHz WDT oscillator too is notoriously off its nominal frequency. When I build a prototype PCB one of the things I routinely measure is the duration of the 1024 ms watchdog timeout against a GPS pps signal. My sample of 43 parts (mostly m328p) resulted in an average of 1049.6 ms +/- 39.33 ms (min of the sample was 979.8 ms and max was 1153.5 ms). Sooo, in my experience the frequency (not time) was typically between -6% and +1.4% off. My sample could be correlated by buying 10 pieces at a time (or so). The extremes were between -11.1% and +4.3% off. That asymmetry chimes with your experience of the internal RCs.

SpenceKonde commented 1 year ago

Iirc on classic, the spec for the wdt and ulp oscillators (as appropriate) often went unmentioned, but when thyme did let it slip it was like +/-30% or something godawful like that. It is shall we say nit intended for any sort or precision timing...


Spence Konde Azzy’S Electronics

New products! Check them out at tindie.com/stores/DrAzzy GitHub: github.com/SpenceKonde ATTinyCore: Arduino support for almost every ATTiny microcontroller Contact: @.***

On Mon, Apr 10, 2023, 19:29 Stefan Rueger @.***> wrote:

This bootloader menu looks so cool! Note I have in the meantime pushed +/- 8.75% too.

running at the internal 128kHz WDT oscillator

The intl 128 kHz WDT oscillator too is notoriously off its nominal frequency. When I build a prototype PCB one of the things I routinely measure is the duration of the 1024 ms watchdog timeout against a GPS pps signal. My sample of 43 parts (mostly m328p) resulted in an average of 1049.6 ms +/- 39.33 ms (min of the sample was 979.8 ms and max was 1153.5 ms). Sooo, in my experience typically between -1.3% and +6.3% off. My sample could be correlated by buying 10 pieces at a time (or so). The maximum length was actually 12.5% off (hopeless), the minimum one -4.3%.

— Reply to this email directly, view it on GitHub https://github.com/stefanrueger/urboot/issues/19#issuecomment-1502466532, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABTXEW4WCLDDJXVK5ZNF5I3XASJUHANCNFSM6AAAAAAVL5753U . You are receiving this because you were mentioned.Message ID: @.***>

stefanrueger commented 1 year ago

ulp = ultra low precision? :wink:

stefanrueger commented 1 year ago

I think the data sheets typically say sth about 10% for the factory calibrated(!) internal RCs, but I also suspect that these intervals are deliberately wider than reality. So would expect WDT to have similar behaviour in practice (same technolgy?)

SpenceKonde commented 1 year ago

Ultra low power I think is the official nam But yours is more accurate. (Kinda like the USI, the Useless Serial Interface on some tinies)

+/-10% applies ro the hd osc, most sheets don't give tolerance for the low speed on in the premodern era


Spence Konde Azzy’S Electronics

New products! Check them out at tindie.com/stores/DrAzzy GitHub: github.com/SpenceKonde ATTinyCore: Arduino support for almost every ATTiny microcontroller Contact: @.***

On Mon, Apr 10, 2023, 19:37 Stefan Rueger @.***> wrote:

ulp = ultra low precision? 😉

— Reply to this email directly, view it on GitHub https://github.com/stefanrueger/urboot/issues/19#issuecomment-1502472495, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABTXEWZFEXRI3MTHWVMFUJTXASKUJANCNFSM6AAAAAAVL5753U . You are receiving this because you were mentioned.Message ID: @.***>

stefanrueger commented 1 year ago

no easy way of getting hold of the second byte in the calibration register

So, unlike say the m328p, it's not possible to read the calibration bytes from software. Here how it's done for Atmega328P: Screenshot from 2023-04-12 11-07-46

The data sheet for the t13a only explains how to read the lock bits, the fuse low and fuse high byte from software, so presumably it's not possible to read the calibration byte from software. The longer I look at this the more I think that it is a bug in the design to allow fuses to be set to 4.8 MHz but not load the existing calibration byte for this into OSCCAL during reset.

It might be possible to create bespoke bootloaders just for the t13/a internal 4.8 MHz oscillator but then there would need to be an agreed workflow for this and an agreed position of the byte in flash (which could be encoded into an ldi r24, %[calibrationvalue] as indicated above at bootloader start, so that would extend the bootloader only by 6 bytes).

mcuee commented 1 year ago

@MCUdude

Just wondering why you say "there is currently no easy way of getting hold of the second byte in the calibration register"?

I can see that avrdude can do it.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c usbtiny -p t13a -qqt
avrdude> dump calibration
0000  60 65                                             |`e              |

avrdude> quit
mcuee commented 1 year ago

The data sheet for the t13a only explains how to read the lock bits, the fuse low and fuse high byte from software, so presumably it's not possible to read the calibration byte from software.

@stefanrueger

I am not so sure what you mean by "from software". But at least avrdude can read the two calibration bytes.

MCUdude commented 1 year ago

Yes, but the microcontroller can't read calibration byte two on its own. It has to be done using an external programmer, and the value has to either be written to Flash or EEPROM. Urboot can't utilize this second byte by itself. A programmer has to read it, and then write the value somewhere so that the bootloader can utilize it without using too much flash space.

A procedure like this would be difficult to implement in Arduino IDE's platform.txt.

mcuee commented 1 year ago

Yes, but the microcontroller can't read calibration byte two on its own. It has to be done using an external programmer, and the value has to either be written to Flash or EEPROM. Urboot can't utilize this second byte by itself. A programmer has to read it, and then write the value somewhere so that the bootloader can utilize it without using too much flash space.

A procedure like this would be difficult to implement in Arduino IDE's platform.txt.

I see.

I think @stefanrueger's idea of template bootloader will help here. The user needs to use a programmer and use avrdude to read the second calibration byte.

Then the template bootloader can be modified to utilize this value (input by the user). If it is difficult to do within MicroCore, this can be done by a utility which can be part of urboot. This utility can even integrate the first part (calling avrdude to read the second calibration byte).

stefanrueger commented 1 year ago

the microcontroller can't read calibration byte two on its own

This is exactly why it makes Microchip's documentation so bitter. They say " To use separate calibration data for the oscillator in 4.8 MHz mode the OSCCAL register must be updated by firmware. The calibration data for 4.8 MHz operation is located in the high byte at address 0x01 of the signature area." Buy they don't say "It's actually impossible for the firmware to read the calibration data" and leave every single user to pick up the pieces for their failure to copy the 4.8 MHz calibration value into the OSCCAL register during reset when the fuses run a different 4.8 MHz oscillator.

can be done by a utility which can be part of urboot

I don't think this is a reasonable effort and a reasonable avenue for the urboot project. The project will be better off concentrating on other issues. If someone really wants to use 4.8 MHz for a project they can set the fuses to internal 9.6 MHz (which gets the factory calibration byte loaded correctly at reset) and then set the system clock prescaler to 2 at the startup() of their sketch. The bootloader would run at 9.6 MHz (b/c it wouldn't have the code for dividing down the system clock). The only situation where this would be out of specs is for a voltage below 2.8 V where 9.6 MHz is at the verge of "overclocking".

mcuee commented 1 year ago

I don't think this is a reasonable effort and a reasonable avenue for the urboot project. The project will be better off concentrating on other issues.

Fair enough.

stefanrueger commented 1 year ago

Cannot think of anything more I could do for classic parts, so have released version u7.7.

It's been a quite positive experience to work with, in particular you @mcuee and @MCUdude on this project. I have implemented a few things that I probably wouldn't have had it not been suggested persistently by either of you (autobaud solved inspired by code from @nerdralph, repository of pre-compiled bootloaders, documentation, treating internal oscillators, find a way to deal with their notorious inaccuracy etc etc).

So thank you for that and staying alongside in that journey.

Closing this issue as completed.