-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
To support mega0 AVR and Tiny0/1/2 AVR, similar to optiboot_x #1
Comments
My understanding is that optiboot_dx doesn't work. I'd be interested in handling XMEGA parts (They have a huge bootloader section that I think could be made available for ordinary applications) and perhaps extend to the parts that optiboot_x can handle. Immediate priority though is to deal well with classic parts and release a reference implementation (current code is pre-release). |
optiboot_dx works well with avrdude on AVR DA/DB parts based on testing on the 128KB Flash parts. I believe it should also work for 64KB and less Flash parts (pending conformation_. optiboot_dx does not work yet for AVR DD parts. |
I have not seen any STK500v1 implementation for XMEGA parts yet. I believe the most popular bootloaders for XMEGA parts is using AVR109 protocol (xboot or CATERINA). urboot for xmega will be interesting. xboot: https://github.com/alexforencich/xboot (AVR109) stk500v2 or CATERINA (USB version of AVR109). Collection of bootloader for AVRs. |
Dx and non-Dx modern AVRs use fundamentally different methods to write the flash. On non-Dx, you fill a page buffer and then execute page-erase-write command. On Dx, you have to have erased the pages, and have NVMCMD set to FLWR but then just load low and high byte of word into R0 and R1, have the Z pointer pointing to where you want to write and execute SPM or SPM Z+. (You can also use the mapping and normal st instructions, but this looked like it would take more flash, is twice as slow (takes same time to write a byte as a word) and doesn't work correctly on the AVR128DA due to an erratum. Erasing pages is done by selecting an FLPER NVMCMD, setting the Z pointer to point to the page being erased, All modern AVRs also have the following differences:
Code executing from APPDATA cannot write to any NVM, not even EEPROM. Bootloaders start at 0x0000, not near the end of the flash. On Dx, a write for the purposes of protection only counts the SPM or ST that writes or erases flash. (you can stage everything, then call a 2 word routine in the boot section consisting of SPM, RET, and write the flash like that). Like all AVRs, it is essential that the reset cause flags be checked AND CLEARED, because you need to be able to detect a "dirty reset" where execution has reached the bootloader, but no reset has occurred. As the peripherals are in an unknown state, the only safe thing to do is a software reset at that point. That was always true, but optiboot never did this, foolishly expecting the user code to do so. Your chances of going up to a roulette table, betting on 00, and then winning twice in a row are probably better than the chance that a randomly selected Arduino sketch would check or clear the reset flags, or that the author of the code even knew that such flags exist. However on modern AVRs it's much more important to force reset after a dirty reset:
|
@SpenceKonde Thanks for a thorough overview espec with regards to the pitfalls. The urboot project originated in 2016, but I only recently published it (following a New-Year resolution to give back to the open-source community). I was hoping that not much needs changing in the bootloader for newer parts over and above changing the way flash/eeprom is written (or read) but may have underestimated some of the sublte differences you pointed out. Anyway, my plan was to first see whether/how urboot bootloaders are accepted along with |
IIRC (it's been a while since I looked at the details of the classic AVR bootloader write process, modern-non-dx probably isn't too hard of a port. You always start up at ~3.33 or ~2.66 MHz, (16/6 or 20/6), which is plenty fast enough for reading from the serial port - because of the fractional baud rate generator, the baud rate calculation error that plagued AVR in the past is gone - so you only have to consider two speeds, and there are no dead-zones between the divisors. You specify the time between the 8 or 16 samples in 64ths of a system clock with the caveat that it must be not less than 64. None of that garbage where 12 MHz chips receive one baud rate more reliably and 16 MHz ones like a different, lower baud rate if you're sticking to "standard" baud rates, and none of this UART crystal nonsense. 57600 and 115200 are some awful baud rates to hit on classic AVRs with a power-of-two-MHz system clock aren't they? Somewhere I wrote up how you could have 4 classic AVRs all running at 115200 baud (or what you think is 115200 baud, with every member of the quarrelsome quartet being able to talk to at least one other device, but none of them successfully able to talk to all three other devices plus a serial adapter. It was after I had to explain to someone on a github issue that no, those classic AVRs running at 8 MHz were not actually operating at 115200 baud, and are only able to talk to eachother, and that no it doesn't matter that they all have a crystal this isn't clock error it's baud error (apparently he had, for years, had a number of classic AVRs running at 8 MHz and what he thought was 115200 baud (no, it's 111111 baud), and complained that his new tiny 3216 couldn't talk to them and it had to be a problem with my core. Initially he didn't belive me, but he stopped posting when I suggested he could prove this was working by trying to listen in with a serial adapter and noticing that it didn't work (of course it didn't, they're talking at 111111 baud and it's trying to talk at 115108 baud, ie. it's actually able to do what you tell it. It's a whole new world in terms of the UART (and for basically no increased effort. The USART baud rate generator is just better way the hell better; we don't even use U2X mode unlesss it's needed to reach the target speed - even really close to the top, you do better by not using U2X and getting the wider error tolerance, vs classic AVR where you basically need it on for any relevant baud rate. IIRC flash writing isnt much different to set up, and changed less than you might think. And for non-DX/future EX. everything is accessible in the same address space (fully mapped flash). DX is definitely more of a challenge. |
So much so that @WestfW mentioned below.
|
Thanks for the heads up re USART. | 57600 and 115200 are some awful baud rates to hit on classic AVRs with a power-of-two-MHz system clock aren't they? When compiled urboot.c warns of baud quantisation errors in excess of 2.5%. The precompiled urboot bootloaders use software IO instead of the USART when the latter has unacceptable quantisation errors. SWIO has less quantisiation error for classic parts at the expense of code space. |
| Dx and non-Dx modern AVRs use fundamentally different methods to write the flash @SpenceKonde What is a good way for a C preprocessor to distinguish between Dx and non-Dx modern AVRs? Obvs, there is the tedious listing of I have come up with
Any intell on Ex parts and how they need to be differently treated from Dx parts? |
103 indicates a part with fully mapped flash, like a mega0 or a modern tiny. The practical upper limit is 48k of flash as they did on the mega0, with the progmem offset of 0x4000 leaving 3/4ths of the address space as mapped flash, and thus 16k to fit the ram and the special function registers. The EA-series looks like it was "forked" from the Dx-series before those parts got any of the big architectural enhancements. They have the same 16/20 selectable base clock instead of the nice directly selectable clock speed, the flash is written and erased by page, and available information thus far suggests that they behave essentially the same as the tinys. There is one big difference at least, though - WWR functionality, so you may have to poll a status register to know when you can start writing the next page. The details of that implementation haven't been released. But what is clear is that the self programming of the EA and EB will have more in common with the tinyavrs and megaavr 0-series. |
Blimey - that's a maze! My gcc-avr v12.2.0 does not know Dx parts (nor Ex parts). For all the others I get when filtered to
Didn't spot any 101. |
You're using old atpacks. The TPI interface ones (the AVRrc devices - they've also got only r16-r31, and the instruction timing is different, and direct addressed load/store is a 16-bit opcode with 128-bit address space because the memory on those things is fucking tiny) are not particularly old either - their specs are crap because they're sold for the price of dirt and have to fit in a tiny package. The 102, 104, arch codes were used for the xmega parts too, yeah. These parts have much in common with xmega. Metaphorically, throughout the development process, they were rummaging around in a junkyard full of old xmega and classic AVR's, looking for parts and subsystems that they could adapt - you can see that many of the peripherals are obviously derived from either xmega or classic AVR versions - though to their credit they did generally streamline what they reused; The xmegas were fiendishly complicated. As for why they used higher architecture versions for some parts than was necessary, I think was just from how Atmel was systematically less consistant. Technically they don't set the size of the flash, but rather are associated with maximums, so that's legal. For all Dx and Ex with 32k flash or less, it's 103, for all Dx and Ex with 64k it's 102, and for all Dx with 128k it's 104. A future 256k part would probably be 106. I don't think 101 ever saw the light of day. 105 and 107 I think are related to those parts supporting large external memories. |
OK, I am now using
So, looks like Dx and Ex get an BTW, this Arch-Linux installation is relatively recent and it misses all Dx or Ex specs files. Thats why I had to copy them over from atpacks. I installed avr-gcc using
|
And that leaves the business of distinguishing xmega devices from Dx/Ex in the C pre-processor. There are plenty of macros/register names etc that will differ. There are even some differences in the avr-gcc -specs=device-specs-dx/specs-avr64da48 -Os -E -dD pre.c | grep __AVR_ >/tmp/1
avr-gcc -mmcu=atxmega32c3 -Os -E -dD pre.c | grep __AVR_ | diff - /tmp/1
13c13,14
< #define __AVR_ISA_RMW__ 1
---
> #define __AVR_ERRATA_SKIP__ 1
> #define __AVR_ERRATA_SKIP_JMP_CALL__ 1
15,16c16,18
< #define __AVR_ATxmega32C3__ 1
< #define __AVR_DEVICE_NAME__ atxmega32c3
---
> #define __AVR_AVR64DA48__ 1
> #define __AVR_DEVICE_NAME__ avr64da48
> #define __AVR_DEV_LIB_NAME__ avr64da48 I wonder whether these are really trustworthy. Does the modern |
One easy way to get a working compiler is to get the one from @SpenceKonde. For Linux x86_64 Ref: |
I am not so sure how difficult it is to add the support of mega0 AVR and Tiny0/1/2 AVR, similar to optiboot_x.
Stretch goal will be to add the support of AVR DA/DB/DD part, similar to optiboot_dx.
Ref: optiboot_dx is too diffierent to be included in optiboot (optiboot_x is integrated into optiboot).
The text was updated successfully, but these errors were encountered: