TinySafeBoot Baud Rates

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've  been playing with this for a while and it's been a bit flaky so I decided to do some testing on what bit rates work for both the 2 wire mode and 1 wire mode.  I tested on two different sets of target hardware and two completely different Serial level converters.  Processor is a tiny48.   Same results.  

 

With the internal 8MHz oscillator as a clock and the CLKDIV8 fuse set to achieve a 1MHz CPU clock, the fastest reliable bit rates I can run are:

 

1 wire:  300 bps

2 wire:  2400 bps

 

The 2 wire limit seems somewhat reasonable.  I was expecting the 1 wire mode to do a little better.  

 

Anyone have better results that this?   I really wanted to use the 1 wire mode so I can reprogram using only GND, VCC, and DATA, but 300bps is very slow even for a device with only 4K of FLASH.

 

I am wondering if any serial port settings or use of a USB to serial adapter might be affecting things.

 

Appreciate any comments.

 

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you remember a external pullup? (1-10k)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lundquist wrote:
set to achieve a 1MHz CPU clock, the fastest reliable bit rates I can run are
Why would you run the CPU at 1MHz ?...

 

The ones I've ringed in red are not achievable on a 1MHz clock. By this table you *should* have found 4800 baud to be usable too. So that one is a bit of a surprise. Compare this with something like:

 

 

So you'd have a whole lot more success if you cleared the "divide by 8" !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But OP can live with 2400 Baud but want one wire!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you remember a external pullup? (1-10k)

The internal pullup is enabled, but certainly a stronger pull-up should improve performance at higher baud rates.

 

For a bootloader with the word 'safe' in the name, it sure is unsafe:

 

Trx1:
        sbi TXDDR, TXBIT                ; if RX=TX (One-Wire), result is
        cbi RXDDR, RXBIT                ; pullup to Vcc for "1" (high-Z)
        sbi TXPORT, TXBIT               ; else portbit actively driven
        rjmp Waitbitcell
Trx0:
        sbi TXDDR, TXBIT                ; set TX driver for output
        cbi TXPORT, TXBIT               ; set portbit to active "0"

Note that 'one-wire' operation is configures simply by defining the TX pin and RX pin to the same port/bit.  This means that when transmitting a '1' bit, the bus is driven high for 1 (or 2) clock cycles.  If the bus is being driven low elsewhere, it would be BadTM.

 

A better way would be to compile conditionally.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just read the TinySafeBoot doc. that say for one wire a external pullup will help the speed. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the replies!   

 

Yes, I do have  pull up.  3.3K  That should be fine.  Signals all look very clean.  I see no indication that the levels are an issue.

 

The reason I run the CPU at 1.0MHz is that this is a device that runs off a CR2032 coin cell.  I need it to run at very low power during normal operation.  8MHz is not an option.

 

The table that clawson provided is for device with a hardware UART.  The ATtiny48 does not have a UART.  That info is not relevant.

 

I will try a different host and see it it helps.  Right now I am using a very fast PC with windows 10 and a USB to serial adapter.  

 

Regards,

Dave

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The table that clawson provided is for device with a hardware UART.  The ATtiny48 does not have a UART.  That info is not relevant.

Incorrect.  It is equally relevant.  Indeed, it is conservative.  The RX half of software UART implemented by TinyBoot takes only a single sample of each bit, rather than the three samples taken by the hardware UART, so no majority vote takes place.  Furthermore, the timing loops used to detect and generate the bit times are not especially accurate.

 

But that's not your problem.

 

The problem is that TSB's auto-baud calculation code has a minimum baud rate it can reliably detect, depending on the CPU clock speed.

 

For 1 MHz it is about 52 baud, so you might wonder why 300 baud won't work for you.

 

Note, however, that the minimum baud rate for 8 MHz is about 415 baud.

 

So the question I have for you is 'How do you know your AVR is running at 1 MHz?'

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The exact error in rate in the table provided is specific to a hardware UART implementation.  I suppose one could make a software UART that exactly emulated that timing with a divide by 16 and hit those error numbers, but that isn't what you normally do for a software UART.  Yes, I've done lots of work with SW UARTs on a variety of platforms.  The general concept may be relevant but it doesn't in any way explain the issue I am seeing.

 

The absence of majority voting on multiple samples is only important on noisy lines like analog modems.  A single center sample is perfectly ok in direct connect cases.  

 

Not sure why you are discussion a minimum baud rate.  I am asking about a maximum for the 1 wire mode.  

 

300bps does work fine for me in 1 wire or 2 wire mode.  I can't go higher than that in 1 wire mode though.

 

I know my AVR is running at 1MHz because all the timing in my run time code all behaves as if it is running at 1MHz.   

 

Sorry for all the fuss here.  I really only was trying to get some feedback if anyone had results with 1 wire mode of TinySafeBoot that differed from what I am seeing.  Again, 2 wire mode is working FINE.  As expected, no issues.  

 

I did try an old WinXP machine with a standard (non-USB) com port.  Exact same results.  

 

I may hook up my Saleae serial protocol analyzer at some point and see if it sheds some light on this.

 

Dave

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The exact error in rate in the table provided is specific to a hardware UART implementation.

Still incorrect.  It is the error rate of >>any<< UART implementation which employs majority vote sampling of the centre three samples from a sixteen (or eight for the double-speed table) sample bit.  There is absolutely no correlation to a specific implementation, whether in hardware or in software.  A software UART can employ the same majority vote method, and indeed such software can be found.  And as mentioned, for a single-sample UART (hardware or software), the errors are actually >>worse<<.  For a software UART they are often worse still due to sample jitter.

 

The general concept may be relevant but it doesn't in any way explain the issue I am seeing.

Where did I hear that before?  Oh yeah:

But that's not your problem.

 

 

 

Not sure why you are discussion a minimum baud rate.  I am asking about a maximum for the 1 wire mode.  

If look at how the TSB autobaud, you'll see it uses a 16-bit counter to accumulate 17 low bit times from the '@@@' autobaud characters.  Each tick of the counter is 5 cpu cycles.  If you do the arithmetic for a 16-bit counter, it overflows for '@@@' at speeds lower than 52 baud for 1 MHz, and at speeds lower than 415 baud at 8 MHz.

 

300bps does work fine for me in 1 wire or 2 wire mode.  I can't go higher than that in 1 wire mode though.

That's the part I missed.  I misunderstood that 300 baud wasn't working at all.  Re-reading the OP I see that overflow in the autobaud counter doesn't apply.

 

Sorry for all the fuss here.

No fuss.  Everyone likes a mystery.  Unless it's their own ;-)

 

I may hook up my Saleae serial protocol analyzer at some point and see if it sheds some light on this.

But:

Signals all look very clean.  I see no indication that the levels are an issue.

???

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow, OK...  I guess it is possible I forgot how UARTs work after doing microprocessor development with UARTs of all kinds hardware and software since 1982, but I doubt it.

 

Clearly the software UART in the TSB app works just fine in 2 wire mode so the timing should be perfectly OK in 1 wire mode too.  All I set out to explore here was the difference between the 1 wire half duplex mode and the two wire mode.  If it works at 2400 bps in 2 wire mode it should work at the same bit rate in 1 wire mode.  It doesn't.  Probably something in the Tx/Rx direction change...  

 

Even if the levels look fine, it is perfectly reasonable to look at the protocol with a Saleae analyzer.  The Saleae is not a scope, it is a protocol timing analyzer.  

 

I think I am done with this thread unless somebody posts something actually relevant to 1 wire mode of tinysafeboot.   The pull up recommendations were helpful but I had that covered.

 

Regards,

Dave

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Probably something in the Tx/Rx direction change...

TSB does nothing special for this.  It uses exactly the same code for both, nothing is conditionally compiled.  The only difference is what happens when you define TXDDR/TXPORT/TXBIT to be the same as RXDDR/RXPORT/RXBIT:

WaitRX:
        sbi TXDDR, TXBIT                ; if RX=TX (One-Wire), port is
        cbi RXDDR, RXBIT                ; driven open collector style,
        sbi RXPORT, RXBIT               ; else RX is input with pullup
        sbi TXPORT, TXBIT               ; and TX preset logical High
Trx1:
        sbi TXDDR, TXBIT                ; if RX=TX (One-Wire), result is
        cbi RXDDR, RXBIT                ; pullup to Vcc for "1" (high-Z)
        sbi TXPORT, TXBIT               ; else portbit actively driven
        rjmp Waitbitcell
Trx0:
        sbi TXDDR, TXBIT                ; set TX driver for output
        cbi TXPORT, TXBIT               ; set portbit to active "0"
;       rjmp Waitbitcell                ; continue with Waitbitcell
WaitRX:
        sbi TXDDR, TXBIT                ; if RX=TX (One-Wire), port is
        cbi RXDDR, RXBIT                ; driven open collector style,
        sbi RXPORT, RXBIT               ; else RX is input with pullup
        sbi TXPORT, TXBIT               ; and TX preset logical High

Cycle counts will be the same, and all bit times are handled in the same way.  The only deviation from a fully open-collector bus is that when a '1' TX follows a '1' TX, the line is driven high for 2 cycles before it is released to the pull-up (external, then internal too), but that should have no effect since the other end will be configured for open-collector RX while TSB is transmitting.

 

What does your CI-V circuit on the other end look like?

 

Wow, OK...  I guess it is possible I forgot how UARTs work after doing microprocessor development with UARTs of all kinds hardware and software since 1982, but I doubt it.

Wow.  I guess it's possible I'll spend more of my time trying to help you, but I doubt it.  Guess you got it covered.  Good luck with your project.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The main difference for 1 and 2 wire is that the transmitter hear it's own echo, and perhaps it cost some time to deal with.

 

So try to run 8 MHz and see how fast to then can run (if still only 300 it's a HW problem).

 

And why don't you run at 8MHz when programming? (either boot in 8MHz and your program set the clk down to 1 MHz, or program the div8 bit after the program is flashed)  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Unfortunately the fuses have to be set with the SPI programmer.  So, I am forced to use the same Fuse settings for the boot loader and the run time.  The end product is a small sealed wireless module.  The whole attraction of TSB is that it lets me reprogram with only GND, VCC and one port pin brought out.  If I bring out the full SPI, then I really have no need for a boot loader.

 

I just captured a 2 wire TSB session and a 1 wire TSB session.  All else is the same.  Captured the traffic with a Saleae serial analyzer.  The data out of the ATtiny48 is identical for the 1W and 2W cases and yet in 1W mode the host app declares an error and terminates.  This seems to indicate that the PC side may be the problem.  

 

The first thing the PC app sends is "@@@" for autobaud.  There is no delay at all between the stop bit of the third @ and the start bit of the reply from the TSB code on the micro.  The PC app may not handle this immediate turnaround very well.  

 

Will try with the fuses set so I run at 8MHz just to rule that out.

 

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Unfortunately the fuses have to be set with the SPI programmer.  So, I am forced to use the same Fuse settings for the boot loader and the run time.

CLKPR, or clock_prescale_set().  That's all the CKDIV8 fuse does anyhow.

 

Will try with the fuses set so I run at 8MHz just to rule that out.

Easily done, but I expect you're right the speed is not the issue.  I'd be more inclined to look at the CI-V at the other end.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Mar 30, 2018 - 03:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A final verdict...

 

I did try running the part at 8MHz.  Amazingly it was worse.  More evidence this has nothing to do with the software UART on the bootloader.  

 

The Saleae captures that show the bootloader behaving perfectly OK when the host declared an error were strong evidence to me that the host app was not handling the turnaround correctly.  I also saw that the bootloader response to the @@@ autobaud sequence left no gap for host turnaround.   

 

Note, I had also validated my hardware adapter up to 115.2K bps the other day to rule that out.

 

Based on the results that the 2 wire mode works perfectly and that the boot loader traffic was all OK in 1 wire mode, I decided to try and fake the host app into thinking it was talking 2 wire.  I did this by using the active TXD state from the PC to blank the data going back to the PC.   It is a simple mod to the transistor based level converter.  The PC app no longer sees it's own TX data.

 

The results now for 2 Wire mode and 1 Wire mode are identical.  With a 1MHz CPU clock I can run rock solid up to 2400 bps.  Note:  4800 seems to work but fails very rarely.  The host app doesn't even declare the interface 1 wire once you block the echo data.

 

I will check into the possibility of running the boot loader at 8MHz and run time at 1MHz.   I didn't THINK that was possible.  2400 is a little slow for download but not too bad for a 4K byte device.

 

I will post a schematic later of my modified adapter with the echo block.  It is on a piece of scrap paper right now. I want to document it for myself anyway.

 

Dave

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is the schematic of my adapter.  Not highly optimized.  I will eventually do something using one of the USB to Serial modules, but for now this works.  

 

TinySafeBoot 1 Wire Interface Schematic

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As per joeymorin's comments clearly I can leave the CLKDIV8 fuse unprogrammed so the the bootloader runs at 8MHz.  I would just have to add an update to the CLKPR register in my run time code to get back to 1MHz.    The only SLIGHT downside is that I would be drawing more power from my CR2032 coin cell each time I powered up while waiting for the boot loader to time out.  Since I essentially run from the battery continuously until it dies, this really shouldn't matter.  I would only incur this once for the life of the battery.

 

After decades working on AVRs, I've never touched the CLKPR register in run time code.  

 

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As per joeymorin's comments clearly I can leave the CLKDIV8 fuse unprogrammed so the the bootloader runs at 8MHz.  I would just have to add an update to the CLKPR register in my run time code to get back to 1MHz.    The only SLIGHT downside is that I would be drawing more power from my CR2032 coin cell each time I powered up while waiting for the boot loader to time out.  Since I essentially run from the battery continuously until it dies, this really shouldn't matter.  I would only incur this once for the life of the battery.

The CLKDIV8 fuse doesn't condemn you to 1 MHz.  You can program it and boot up at 1 MHz.  If a bootloader session is not initiated, simply pass control to the app.  If bootloading is initiated you could switch to 8 MHz via CLKPR (or 4 MHz, or whatever you determine to be the best balance of speed and coin-cell load) for the duration of the bootload, then switch back to 1 MHz before passing control to the app.

 

You can do this with only a very slight tweak to the bootloader source code.

 

Either:

  • Switch to the higher speed as soon as the falling edge of the start bit from the first '@' character arrives.  This lets the autobaud code do its thing at the correct speed.

Or:

  • Switch to the higher speed after auto-baud, and shift bclkh/bclkl left by the correct number of bits to scale the computed value to the new clock speed (3 shifts for 1MHz->8MHz).

 

The advantage of the first is slightly better baud calibration accuracy

 

The advantage of the second is slightly less current consumption for cases where the bootloader receives non-bootloader characters before the bootloader timeout expires.

 

In either case, you're looking at adding about 6 to 10 instructions to the bootloader source code.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I also saw that the bootloader response to the @@@ autobaud sequence left no gap for host turnaround.   

That could easily be added by inserting a call (or two) to Waitbitcell after the baud calibration.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]