Closed mcuee closed 1 year ago
Features like automatically detect which serial port to use may be even more troublesome and may not be worth the efforts.
It's certainly possible to compile bootloaders for USART1, USART2, ... for fixed baud rates: When you compile an urboot bootloader you can set which USART you want the comms to be on: Just specify UARTNUM=x
when using make
or -DUARTNUM=x
when compiling... (x=0, 1, 2, ...).
However, for autobaud urboot.c
needs to know the RX line of the chosen USART to measure the baud rate before initialising the USART. The table here here needs filling in. The atdf files are not great for this. Maybe someone can help?
(As for the Optiboot Issue #285 I don't know of a valid use case, and cannot imagine one, for the bootloader "automatically" scanning where communications come from. In my world, bootloaders should utilise as few I/O lines as possible and these should be known and fixed; otherwise if the bootloader starts twiggling all sorts of I/O lines at each reset, the projects implemented on the board might do strange things while the I/O lines are scanned: just imagine one of the I/O lines opens the gate of the attached alligator compound... this does not bear thinking about :)
The table is copied here fore reference.
I actually don't even have a table for now many USARTS any one part has (beyond 0 or > 0).
Here is an example of what would be good:
Part | NUART | RXD0 | TXD0 | RXD1 | TXD1 | RXD2 | TXD2 | RXD3 | TXD3 | ||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
attiny167 | 0 | ||||||||||||
atmega328p | 1 | PD0 | PD1 | ||||||||||
atmega328pb | 2 | PD0 | PD1 | PB4 | PB3 | ||||||||
atmega2560 | 4 | PE0 | PE1 | PD2 | PD3 | PH0 | PH1 | PJ0 | PJ1 |
Here is what I have in machine-readable format (you can tell my xml-fu with atdfs is waning). And there are likely some mistakes in that table, too :(
I have now managed to collect the RX/TX lines for all UARTs of almost all 8-bit AVR. This has allowed me to create pre-compiled bootloaders for all serial ports of all classic parts. The autobaud feature needs to know on which RX line the host sends data in order to sample it and compute the correct baud rate register UBRRn. This includes the LIN/UARTs of ATtiny167/87 and a dozen or so other parts; that interface is designed for an automotive Local Interconnect Network and can be used as ordinary UART.
Here the table of RX/TX lines for all UARTs of parts in the bash script that creates pre-compiled bootloaders: https://github.com/stefanrueger/urboot/blob/74ecad651111878a53752a03896074d7230ce12f/src/mkurboots#L547-L918
Fun fact 1: Atmel's LIN/UARTs allow the setting of the sample rate 8..63 in addition to the BRR. Classic UARTs only can set the sample rate to 8 or 16. This means that LIN/UARTs can create almost all baud rates within 1% of quantisation error. Urboot bootloaders for these parts make use of that.
Fun fact 2: Classic UARTs struggle to generate 115200 baud from F_CPU = 8 MHz (a whopping 3.7% quantification error). In these cases an urboot bootloader with software I/O is generated instead.
Fun fact 3: The bash script always numbers UARTs of a part starting from UARTNUM=0, irrespective how the data sheet numbers them (some parts only have USART1, the XMEGA parts name their USARTs after the port, eg, USARTC0),
Fun fact 4: Some classic parts (ATtiny441andATtiny841) can assign different alternative pins to RX/TX for an UART. This is done with the CPP constant UARTALT=1 and noted in the file name with _alt1, see here, for example.
Fun fact 5: Some UARTs have RX/TX on a port that is outside the bit addressable I/O space. This happens for UART2 and UART3 on the ATmega2560, for example. As the autobaud sensing loop requires a fast scanning of the RX line, autobaud bootloaders cannot be generated for these UARTs.
Fun fact 6: Software I/O also relies on clock cycles of opcodes and is unable to deal with RX/TX ports outside the bit addressable I/O space (usually Port H and above). So no SWIO for UART2 or UART3 of ATmega2560 either. Bootloaders for ordinary fixed baud rates given F_CPU are possible, and generated, for UARTs with those non-bit-addressable ports though.
Fun fact 7: I have changed the naming scheme of the urboot bootloaders to always indicate the I/O mode (SWIO/UART) and the RX/TX lines that the user should interface the part with.
Fun fact 8: While reviewing the UART initialisation code I realised that almost all classic UARTs already have the UART character size bitfield set to 8N1 after reset, so could save typically 4 bytes.
Fun fact 9: I also realised that a lot of classic parts (around 50%) already initialise SP to RAMEND after reset, so could save that initialisation for a number of parts, too.
@mcuee and @MCUdude, have a look at the generated pre-compiled urboot bootloaders in the urboot.hex repository.
This should close the issue. In fact, I think once you have tested a sample of generated bootloaders, I will want to formally release v7.7 of urboot bootloaders.
Nice one. I will carry out some tests and report here soon, probably over this weekend.
Fun fact 5: Some UARTs have RX/TX on a port that is outside the bit addressable I/O space. This happens for UART2 and UART3 on the ATmega2560, for example. As the autobaud sensing loop requires a fast scanning of the RX line, autobaud bootloaders cannot be generated for these UARTs.
Does "outside the bit addressable I/O space" means above the 8-bit address space? When looking at the ATmega2560 datasheet, it appears to me that only the USART3 registers have addresses above 0xFF:
For reference, here are the USART2 registers in the ATmega2560 datasheet:
The problem is not where the USART registers are, but where the Port for the RX line is. It is this loop https://github.com/stefanrueger/urboot/blob/74ecad651111878a53752a03896074d7230ce12f/src/urboot.c#L1958-L1960 that needs bit access (using the sbis
opcode) to the PIN
of the Port of the RX line associated to USART2. And the PIN of Port H is way outside I/O space [0x20, 0x3f]. One loop iteration takes 5 cycles (mapping neatly to the 5 low bit that are measured after the start bit) and cannot afford to be substantially longer...
Maybe I should have clarified: the bit-addressable I/O space is an address region of only 32 bytes (normally from 0x20 onwards, but in some parts from 0 onwards). Only in these 32 bytes can every single bit be individually addressed by the sbis
, sbic
, sbi
, cbi
opcodes.
So, I have now refined the UART capabilities, and even cater for ATmega161's single byte that the two different msb-4 bit share between the two 12-bit BRR registers of UART0 and UART1. If anyone has an ATmega161, that's a good edge case to test (slow baud rate with high F_CPU on UART1).
@stefanrueger
Tested the ATmega2560 115200bps bootloader for UART0/1/2/3 and they all work well. https://github.com/stefanrueger/urboot.hex/tree/main/boards/mega-r3/fcpu_16mhz/115200_bps
Test results here.
I use the avrdude patch from Marius for the testing of UART1/2/3 since I do not have the capacitors with me.
Thanks for testing @mcuee!
So, I trust this issue can now be closed?
Yes this can be closed.
It would be great to provide urboot hex files for non-default serial port. I think this is one of the major missing feature from urboot.
As per the previous discussions in avrdude, it may not be so easy to do this automatically though.
Maybe @MCUdude has some ideas since he has done this in optiboot_flash.