help with writing a 64-byte serial bootloader

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

I'm writing a universal (attiny & atmega) bootloader for AVRs with up to 8K of flash that fits in 32 instructions (64 bytes) + a 2-byte virtual reset vector. The current version of the code fits in 31 instructions:
http://162.248.164.251/picobootS...

With the 1 leftover instruction I could modify RxByte to work with any pin instead of just pin0. That's if there's nothing else that I've left out that a minimal bootloader must do. I'd like to hear what more experienced AVR programmers have to say.
Another option for the leftover instruction is to do two writes to UART_Tx (0 then 1) instead of toggling with the PINx register. That would allow for support of the Atmega8 which does not toggling a pin with writes to PINx registers.

With the bootloader code mostly done, I've started working on adding picoboot support to avrdude. I plan to use the break signal from the bootloader for flow control, so there will be no need for programming timeouts or knowledge of RWW sections.

The initialization sequence from avrdude will be:
1. send break to trigger reset
http://nerdralph.blogspot.ca/201...
2. send xor of 2nd and 3rd signature bytes (from avrdude.conf)
3. send 3 zeros (clear Z command)
4. wait for break

If the target device is not running the bootloader or the signature doesn't match, then avrdude will timeout waiting for the break.
Avrdude will replace address 0 (reset vector) of the downloaded code with an rjmp to the start of the bootloader, and put an rjmp to the application start as the last word in the page before the bootloader.

Comments/suggestions welcome.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

if you can code a bootloader in 31 instructions then I am pretty impressed.

but..... do you need a bootloader in 31 instructions? there are lots of big and cheap AVRs.

regards
Greg

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

I'm an obsessive optimizer, and never thought much of programmers who consider code size/performance to be a hardware problem.
Optiboot seems quite popular, even though it's used on a lot of ATmega328's. It doesn't support ATtiny parts, and even if it did, it wouldn't be much use on something like an ATtiny25.

As for going to a bigger AVR, that's often not a cheap solution. For example one of the parts I'll be testing my bootloader on are ATtiny88's. The -AU parts are 50c ea in qty100. The cheapest AVR with 16KB (the ATtiny1634-SU) is double the price, and has fewer I/O pins.

For anything produced in volume, even saving 1c can be a big deal. I was reading some hardware design discussions where prototypes that used 0805 surface-mount resistors were changed to 0603 for production for the sake of saving 0.2c per resistor.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
I'm an obsessive optimizer, and never thought much of programmers who consider code size/performance to be a hardware problem.

Nifty.
You might want to include false start bit rejection, otherwise noise can trigger a whole-byte receive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define UART_Rx 0
#define UART_Tx 0

???

BTW, impressive!! It's unlikely I would have any use for a bootloader with no error detection and which can't read back flash, but it's impressive anyway!

"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 hate it, if a bootloader was made for easy self destruction instead reliability.

So my bootlader checks CRC and reject overwriting itself.
Also it erase the application pages backwards and restore the bootloader jump automatically.
So there exist no critical section, where interrupting or wrong data may cause, that the bootloader was lost.
The size was 256 words on the ATtiny13.

I see no gain on making it less reliable.

There are already tons of gadgets aroud the world, which are dead by a mistake during update.

Peter

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

ralphd wrote:
I'm an obsessive optimizer, and never thought much of programmers who consider code size/performance to be a hardware problem.

Nifty.
You might want to include false start bit rejection, otherwise noise can trigger a whole-byte receive.

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

Quote:
For anything produced in volume, even saving 1c can be a big deal. I was reading some hardware design discussions where prototypes that used 0805 surface-mount resistors were changed to 0603 for production for the sake of saving 0.2c per resistor.
Yep - I have been in that business. we would either have the parts programmed in bulk by a 3rd party and supplied ready for the smt machine or else programme in the in-circuit test fixture.

We found that there was a tipping point where a programmable device needed to be considered more as a custom logic device (ie no re-programme) rather than a field programmable device.

regards
Greg

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

joeymorin wrote:

#define UART_Rx 0
#define UART_Tx 0

???

In an earlier version I was trying to support my shared tx/rx half-duplex serial circuit.
http://nerdralph.blogspot.ca/201...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Thanks for all the feedback. It helped me realize that error checking is much more important than signature checking. So I'm going to remove signature checking (3 instructions) and do error checking instead, while not exceeding 32 instructions.
It might be easier if there was a compare, skip if not equal in addition to the cpse instruction. Then I could do:

rcall RxByte
cpsne crc, data

instead of:

rcall RxByte
cp crc, data
brne Error

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

OK, new version does error checking with a 1-byte crc after every 3 bytes received. And still in 31 instructions!
http://162.248.164.251/picobootS...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
OK, new version does error checking with a 1-byte crc after every 3 bytes received.
CRC is more than just exclusive or. What you have is best described as an FCS (frame check sequence). CRC can be used as an FCS, but that's not what you have. An EOR-only FCS is still better than nothing, especially since the message size is 3 bytes.

    in  crc, MCUSR
    sbrs crc, EXTRF

Your bootloader doesn't clear EXTRF. Since it appears your bootloader doesn't jump to the app code after a successful bootload (or an unsuccessful one), subsequent resets will always trigger the bootloader, in an eternal loop. Only a power-cycle can restore normal application operation.

Does this not mean that an external reset is now useful only for triggering the bootloader? And an eternal loop of bootloading can only be broken by a power cycle?

Am I missing something? Is there some way to exit the bootloader and run the app without a power cycle?

Even with a successful bootload a power cycle seems necessary, no? One of the benefits of a bootloader is easy application loading, preferably without the need for the physical access to the device required by ISP/TPI.

At the very least I would add:

    cbi MCUSR, EXTRF

... to stop the eternal bootloading.

    ; on CRC error, fall into RxByte
...
    ret

An FCS failure will lead to a ret without a preceeding rcall. The PC will be loaded with *(uint8_t*)(RAMEND+1), a non-existent SRAM location outside of the device's memory map.

A simple test on a 328P:

  uint8_t *ptr = (uint8_t*)(RAMEND+1);
  printf_P(PSTR("0x%04X == 0x%02X%02X\r\n"), (uint16_t)ptr, *(ptr+1), *ptr);
0x0900 == 0x0000

... shows that this results in a jump to the reset vector, but this is by no means guaranteed. Future versions of the device based on a different process may return 0xFFFF for an undefined memory fetch, or perhaps a random value.

In any event even a jump to the reset vector will result in a jump to the bootloader again. This would eventually result in app code being run if you clear EXTRF as mentioned above, but if the bootload failed then you'll probably wind up running amok, possibly running parts of the bootloader, and therefore possibly overwriting the bootloader.

Quote:
And still in 31 instructions!
Why is this so important? Surely a better approach is to start with a list of features, and then write the smallest program possible which implements those features. So what if it's 33 words, or 64 words?

"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

joeymorin wrote:
ralphd wrote:
OK, new version does error checking with a 1-byte crc after every 3 bytes received.
CRC is more than just exclusive or. What you have is best described as an FCS (frame check sequence). CRC can be used as an FCS, but that's not what you have. An EOR-only FCS is still better than nothing, especially since the message size is 3 bytes.

I considered putting CRC in quotes, since I know eor isn't a 'real' crc. I agree FCS is the correct term.

Quote:

At the very least I would add:
    cbi MCUSR, EXTRF

... to stop the eternal bootloading.


Good point. MCUSR is above 0x1f, so cbi can't be used. I could do it in 2 instructions, but then I'm over 32 bytes...

Quote:
And still in 31 instructions!
Why is this so important? Surely a better approach is to start with a list of features, and then write the smallest program possible which implements those features. So what if it's 33 words, or 64 words?

Because 32 words is the page size on 4K and 8K AVRs, making 32 words the smallest possible bootloader for those devices. It's like the holy grail for small bootloaders. If the booloader takes two pages instead of one, that's a real difference in the code available for the application. If it takes 31 or 32 words, it's still one page, making the difference just academic.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
I could do it in 2 instructions, but then I'm over 32 bytes...

Delay3Cycle:
    dec delayArg
    brne Delay3Cycle
    out MCUSR, delayArg
    ret

This will clear all bits in MCUSR, but other more capable bootloaders already do this (Optiboot).

Quote:
Because 32 words is the page size on 4K and 8K AVRs, making 32 words the smallest possible bootloader for those devices. It's like the holy grail for small bootloaders. If the booloader takes two pages instead of one, that's a real difference in the code available for the application. If it takes 31 or 32 words, it's still one page, making the difference just academic.
Not necessarily.

You can read/update/erase/write one of the bootloader pages. If the desired feature set takes 33 words, you can add a bit of code (perhaps 6-10 words if you're clever) that handles page updates. This might increase the bootloader from 33 to 39 words, but that's better than giving up the rest of the page.

---------

As mentioned you have no false start-bit detection. You also don't check the stop bit, so won't know of any frame errors. The FCS should catch that though.

"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

joeymorin wrote:
ralphd wrote:
I could do it in 2 instructions, but then I'm over 32 bytes...

Delay3Cycle:
    dec delayArg
    brne Delay3Cycle
    out MCUSR, delayArg
    ret

This will clear all bits in MCUSR, but other more capable bootloaders already do this (Optiboot).


That's one of the things I don't like about optiboot. Because it zeros MCUSR before jumping to the application, you can't use watchdog reset for timeouts. Instead of:

  MCUSR = 0;

I think it would be better to do:

  MCUSR = &= ~(1<<EXTRF);

joeymorin wrote:

You can read/update/erase/write one of the bootloader pages. If the desired feature set takes 33 words, you can add a bit of code (perhaps 6-10 words if you're clever) that handles page updates. This might increase the bootloader from 33 to 39 words, but that's better than giving up the rest of the page.

True. I'm getting a headache thinking about it, but true. I could have CommandLoop start on the last page, which would give me 8 more bytes to work with. The programmer would just have to write the 4 BootStart instructions in addition to VirtualReset.

I don't think I'll have to do that though, since I've added code to start the application after entering the bootloader command loop.

    cp  FCS, data
    breq CommandLoop                ; next command
    ; on FCS error, start application
    ; programmer will loose sync and report error
    ; programmer intentionally sending bad FCS doubles as
    ; a command to start application after programming
    rjmp VirtualReset               ; jump to application code

My thinking is external reset would only be used to start the bootloader. For boards with no auto reset circuit and just a reset button, there would be no issues with failing to press the upload button (or hit enter on a commandline to execute avrdude) before the bootloader timeouts.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

What am I missing on this size matters (small is better)? The AVRs have a boot area in flash whose size is minimum of x bytes (chip dependent), and fuse settings choose the size. The size increases in fairly large hunks of flash.

On popular small AVRs, 512 bytes was the minimum.

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

stevech wrote:
What am I missing on this size matters (small is better)? The AVRs have a boot area in flash whose size is minimum of x bytes (chip dependent), and fuse settings choose the size. The size increases in fairly large hunks of flash.

On popular small AVRs, 512 bytes was the minimum.


Only ATmega parts have hardware bootloader support. My bootloader will work on ATtiny parts.

And FYI, on the ATmega88 and 168 the minimum boot size is 128 words (256 bytes).

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
I think it would be better to do:
  MCUSR = &= ~(1<<EXTRF);

Of course it would, but you wanted to stay under 32 words ;)

BTW I assume you meant:

  MCUSR &= ~(1<<EXTRF);

Better still would is:

GPIOR0 = MCUSR;
MCUSR = 0;

... or some such. Lots of ways to skin a cat. What's more important to you? A 32-word bootloader, or a feature-full bootloader? As is you'll never get a flash verify squeezed in next to flash write. That is the most serious shortcoming IMO.

Quote:
I'm getting a headache thinking about it, but true. I could have CommandLoop start on the last page, which would give me 8 more bytes to work with. The programmer would just have to write the 4 BootStart instructions in addition to VirtualReset.
Well, you seem to like a challenge...

    cp  FCS, data
    breq CommandLoop                ; next command
    ; on FCS error, start application
    ; programmer will loose sync and report error
    ; programmer intentionally sending bad FCS doubles as
    ; a command to start application after programming
    rjmp VirtualReset               ; jump to application code

But:

VirtualReset:
    rjmp BootStart                  ; will be overwritten by programmer

So in the event of an FCS error, you'll be restarting the bootloader. Unless you program the last app page first, but then you'd be jumping to an incompletely written app because of the FCS error!

Quote:
before the bootloader timeouts.
I see to timeout mechanism in your bootloader. The only way out is a power cycle, or a successful bootload followed by a deliberate FCS error.

"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

stevech wrote:
What am I missing on this size matters (small is better)?
I asked this earlier as well.

as an intellectual exercise it is interesting.

As an industrial exercise reliability is king and and load errors resulting in rework or scrap will quickly erode savings from a cheaper part even in very high volumes as the errors will typically be a % of total volume.

regards
Greg

Last Edited: Wed. Feb 12, 2014 - 11:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

VirtualReset:
    rjmp BootStart                  ; will be overwritten by programmer

So in the event of an FCS error, you'll be restarting the bootloader. Unless you program the last app page first, but then you'd be jumping to an incompletely written app because of the FCS error!

That's only if no app has been loaded, in which case there's nothing else to jump to.
If an app was previously loaded, and the FCS error occurs before the first page is written, then the old app is run.
On AVRs with 64-byte pages, 33 FCS bytes will be checked before erasing the first page, so the chances of failing after a successful first page write is pretty low.

And if there is an error, the programmer loose sync and signal an error. Then target can be reset to retry programming.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

From your web link:

Quote:
Edit: Jeorg Wunsch seems to be a patch nazi, so it probably won't get added to the official avrdude while he's in control.
You've just insulted one of the most productive and helpful folks in all of AVR land. Maybe since this guys little finger knows more about AVRs that most of us ever will, maybe just maybe, he has a reason for not including your contribution. And to make the insult doubly bad, Mr. Wunsch is from Germany where they are particularly sensitive to their N-word.

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

gregd99 wrote:
stevech wrote:
What am I missing on
As an industrial exercise reliability is king and and load errors resulting in rework or scrap will quickly erode even in very high volumes as the errors will typically be a % of total volume.

So what's your point?

With any other bootloader communication errors are going to cause problems too. Based on everyone's feedback on the importance of error checking, I added the 1-byte FCS for every 3 bytes received.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Quote:
So what's your point?
Just linking back to my earlier question of what's the need for a teensy bootloader?

You explained that cost was critical. I get that but don't see how the 64 byte boot loader makes a big difference. I would assume that volume parts in a factory would not be loaded via a serial download but would be pre-programmed or programmed in the test fixture. this would mean that even the 64 bytes could be saved.

For field ops of a large volume it is likely that upgrades would be done as a board swap to minmise time on-site and minimise the probability of failures.

On the other hand if you are low-volume you probably won't have customised in-ciruit test and truck rolls for field upgrade..... but then you are also less cost sensitive.

anyway.... still impressed that you can write a boot-loader in 64 bytes.

regards
Greg

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

Quote:
I don't like about optiboot [...] zeros MCUSR before jumping to the application...

The latest version of optiboot passes the original contents of MCUSR to the user sketch in one of the registers. IIRC, there's some subtlety to MCUSR that prevents just leaving bits set...

BTW, since you're using a virtual reset vector instead of the hardware-supported "bootloader section", and are concentrated on the devices with very small memory, a 33 word bootloader is only one word worse than a 32 word bootloader, rather than "it might as well be 64 words", right?

Feel free to post suggestions (and patches!) for optiboot to the http://code.google.com/p/optiboo... page. Not everything gets done (and it's even slower to filter into actual Arduinos), but it's good to have the ideas in one central place.

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

westfw wrote:
Quote:
I don't like about optiboot [...] zeros MCUSR before jumping to the application...

The latest version of optiboot passes the original contents of MCUSR to the user sketch in one of the registers. IIRC, there's some subtlety to MCUSR that prevents just leaving bits set...

Ideally, the presence of the bootloader should be invisible(as possible) to the application code. For that reason, instead of clearing MCUSR I'm considering just clearing the EXTRF bit and writing it back to MCUSR. Have you considered doing that in optiboot? I understand that given optiboot uses the watchdog reset for the bootloader timeout that it may complicate things...

westfw wrote:

BTW, since you're using a virtual reset vector instead of the hardware-supported "bootloader section", and are concentrated on the devices with very small memory, a 33 word bootloader is only one word worse than a 32 word bootloader, rather than "it might as well be 64 words", right?

Yes, as Joey helped me figure out I can use part of the 2nd last page not just for the virtual reset vector but for part of the bootloader code as well. *If* I were able to get the code size down to 32 words, then any further size reduction would be academic.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
stevech wrote:
What am I missing on this size matters (small is better)? The AVRs have a boot area in flash whose size is minimum of x bytes (chip dependent), and fuse settings choose the size. The size increases in fairly large hunks of flash.

On popular small AVRs, 512 bytes was the minimum.


Only ATmega parts have hardware bootloader support. My bootloader will work on ATtiny parts.

And FYI, on the ATmega88 and 168 the minimum boot size is 128 words (256 bytes).

what's the flash block erase size on the ATtiny's? Obviously it can't be much larger than the size of the little bootloader.

Reminds me way-back of the clever bootloader for the PDP11 I worked on. Not in ROM. Entered with PDP-11's binary keys. We all memorized it.

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

ralphd wrote:
With any other bootloader communication errors are going to cause problems too.
With any other bootloader, they're able to do something about it. Yours just aborts, almost certainly leaving the app in an unusable state. Since there is no bootloader section per se, the risk is that the incompletely uploaded app will run amok and very possibly overwrite the bootloader.

ralphd wrote:
That's only if no app has been loaded, in which case there's nothing else to jump to.
Come again?

Either:

    1) You write the app's 'VirtualReset' vector last, in which case an FCS error before the last page write results in running the bootloader again 2) You write the app's 'VirtualReset' vector first, in which case an FCS error before the last page write results in running incomplete code
Note that 1) will only ever happen on a virgin chip with your bootloader. After which:
    3) An FCS error before the last page write results in running a Frankenstein's monster of the remnants of the last app's code and the aborted new app's code.
While 1) can happen only once on a virgin chip, 2) and 3) could brick the device.

Quote:
If an app was previously loaded, and the FCS error occurs before the first page is written, then the old app is run.
So there is one page (the first) where an FCS will have no deleterious effect. There are 126 other app pages where an FCS error could brick the AVR. Those aren't good odds.

Quote:
On AVRs with 64-byte pages, 33 FCS bytes will be checked before erasing the first page, so the chances of failing after a successful first page write is pretty low.
So you program the first page without any FCS errors. How precisely are you going to arrange for no further FCS errors? Surely an FCS error during the second (or fiftieth) page will result in franken-code running amok.

You really should account for an FCS by halting the cpu. Further, you need to command the bootloader to jump to the app after a successful bootload, and only then.

There is an alternative. You could run a bootload session thusly:

    - First, restore the 'VirtualReset' vector to point to the bootloader with the first page write. That way any FCS errors that occur after the first page write will not result in franken-code - Next, write all of the rest of the new app's pages, except the page that contains the 'VirtualReset' vector
    - Finally, write the page containing the 'VirtualReset' vector and any app code that may reside in the same page
    - At this point the app has been successfully uploaded (contingent upon no FCS collisions in any of the 4K+ eor-only FCS bytes received, something which cannot be verified since your bootloader cannot read flash)
    - Force a deliberate FCS which will result in a jump to the app via the newly written 'VirtualReset'

Quote:
That's one of the things I don't like about optiboot. Because it zeros MCUSR before jumping to the application, you can't use watchdog reset for timeouts.
I think you've misunderstood.

Look at my suggestion again:

BootStart:
    in  FCS, MCUSR                  ; use MCUSR to initialize FCS
    sbrs FCS, EXTRF                 ; run bootloader on EXTRF 
    rjmp VirtualReset               ; jump to application code
...
Delay3Cycle:
    dec delayArg
    brne Delay3Cycle
    out MCUSR, delayArg
    ret

The bootloader will only clear MCUSR if a bootload session is initiated with an EXTRF. If reset was caused by any other source, MCUSR is left untouched and control is transferred to the app via the 'VirtualReset' vector.

smileymicros wrote:
You've just insulted one of the most productive and helpful folks in all of AVR land.
Yeah, that was dumb, ralphd. D.U.M.B.

You have got a long way to go, baby, before your clever and admittedly impressive 32-word bootloader is ready to be included into proven software like avrdude.

If I were maintaining avrdude, I would decline to include support for your bootloader at this stage, and I think I can say with confidence that most folks who contribute to these forums would do the same. It is impressive, and it is interesting, but it is not ready for prime time... yet.

Personally, I would be very reluctant to include support for a bootloader which doesn't support flash read. That's a serious shortcomming. An FCS is better than nothing, but there is still no guarantee that the bootload was successful. Only a verify of flash can do that.

If you like, you can always write your own AVR programmer driver...

ralphd wrote:
Yes, as Joey helped me figure out I can use part of the 2nd last page not just for the virtual reset vector but for part of the bootloader code as well.
The trick will be to arrange your code such that everything needed to perform a page erase and a page write is located in the one bootloader-only page. It would be nice if, like EEPROM, flash erase and write could be done atomically, but alas they cannot.

Also, an undetected FCS collision while loading the data for this shared page could result in corrupted data being written, and the bootloader might be lost and device bricked.

westfw wrote:
The latest version of optiboot passes the original contents of MCUSR to the user sketch in one of the registers. IIRC, there's some subtlety to MCUSR that prevents just leaving bits set...
The 'subtlety' is that WDRF must be clear to be able to disable the watchdog. If the bootloader is skipped because there was no external reset, there's no need for optiboot to disable the watchdog nor clear WDRF. That should be the app's responsibility anyway.

Change this:

  // Adaboot no-wait mod
  ch = MCUSR;
  MCUSR = 0;
  if (!(ch & _BV(EXTRF))) appStart(ch);

... to this:

  // Adaboot no-wait mod
  ch = MCUSR;
  if (!(ch & _BV(EXTRF))) appStart();
  MCUSR = 0;

... and you don't have to pass MCUSR to the app via r2.

JJ

"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

Quote:

Yeah, that was dumb, ralphd. D.U.M.B.

As I said in this thread:

https://www.avrfreaks.net/index.p...

we probably should cut Ralph a bit of slack because of his condition - on the other hand calling anyone a "nazi" is not the greatest way to win friends and influence people ;-) (and especially not Joerg who has contributed so much to the AVR world).

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

clawson wrote:
we probably should cut Ralph a bit of slack because of his condition
A bit ;)

Ralph if I've offended you with my bluntness, please understand that it was directed only at your inappropriate comment, not your intelligence. You are not dumb. But you don't need me to tell you that ;)

"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

joeymorin wrote:
clawson wrote:
we probably should cut Ralph a bit of slack because of his condition
A bit ;)

Ralph if I've offended you with my bluntness, please understand that it was directed only at your inappropriate comment, not your intelligence. You are not dumb. But you don't need me to tell you that ;)

As I said in the other thread, from my perspective the issue is NTs misjudging Aspie's not the other way around. I am extremely logical, so it is very hard to offend me. Although I intuitively take things literally, I have learned other people tend to be more indirect in their communication. I've learned to analyze the hidden meaning behind what some people say (the ex-wife being one of those I'll never figure out), and so I'm able to translate your "dumb" to, "I wouldn't have done that."

But I'm not you, and don't really care whether you or anyone else thinks I should try to consider other people's feelings.

What I am interested is your (and other's) logical analysis of the code I write or the circuits I design. And I think that's what these forums are supposed to be about, rather than telling me or anyone else they should show more respect for certain people.

"Unthinking respect for authority is the greatest enemy of truth." - Einstein

p.s. Take a break and watch "Big Bang Theory". Wife 2.0 says(with endearment) that I'm her Sheldon, and I'm proud of that.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:
ralphd wrote:
With any other bootloader communication errors are going to cause problems too.
With any other bootloader, they're able to do something about it. Yours just aborts, almost certainly leaving the app in an unusable state. Since there is no bootloader section per se, the risk is that the incompletely uploaded app will run amok and very possibly overwrite the bootloader.

I think you are exaggerating with "very possibly overwrite the bootloader". As for what other bootloaders do, Optiboot, for instance does no error checking on the data received. Some data bytes could be getting corrupted in the transmission, and avrdude won't report any problems until the verify stage. By that time the corrupted application has already been written to flash. Optiboot will timout with a watchdog reset, and start the corrupted application.
With my bootloader has ~30 chances to detect an FCS error before a page could get written.
joeymorin wrote:

ralphd wrote:
That's only if no app has been loaded, in which case there's nothing else to jump to.
Come again?

Either:

    1) You write the app's 'VirtualReset' vector last, in which case an FCS error before the last page write results in running the bootloader again 2) You write the app's 'VirtualReset' vector first, in which case an FCS error before the last page write results in running incomplete code
Note that 1) will only ever happen on a virgin chip with your bootloader. After which:
    3) An FCS error before the last page write results in running a Frankenstein's monster of the remnants of the last app's code and the aborted new app's code.
While 1) can happen only once on a virgin chip, 2) and 3) could brick the device.

For the reasons above, my bootloader is still better than Optiboot.

joeymorin wrote:

You really should account for an FCS by halting the cpu. Further, you need to command the bootloader to jump to the app after a successful bootload, and only then.

That's a reasonable suggestion.

joeymorin wrote:

Quote:
That's one of the things I don't like about optiboot. Because it zeros MCUSR before jumping to the application, you can't use watchdog reset for timeouts.
I think you've misunderstood.

No, I understood perfectly. I was saying I like your suggestion BECAUSE it doesn't always zero MCUSR like Optiboot.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Initializing FCS from MCUSR was a bad idea since the state of WDRF, BORF, and even PORF is unknown. In fact I don't like playing with MCUSR at all since I want the bootloader to be as transparent as possible. So I initialize FCS by clearing it now.

Given that it is a serial bootloader, if there is no serial connection present, then there's no point running the bootloader. So now the bootloader will start the app if UART_Rx is low. Removing the dependency on EXTRF will also make it feasible to use the bootloader on AVRs with the RSTDISBL fuse set, which I've seen done on the ATtiny85 to get 6 usable IO pins vs 5 + RST.

The last change I've made is to halt the bootloader on FCS error.

With the changes, the code is now coincidentally exactly 64 bytes (+ 2 for the virtual reset vector).

https://code.google.com/p/picobo...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
I think you are exaggerating with "very possibly overwrite the bootloader".
Is it likely? No. Is it possible? Yes. Therefore 'possibly'. I don't see room for exaggeration.

The first and most important job of a bootloader is to be bulletproof. Always.

For hobby or other non-commercial use, there is perhaps less cause for concern. The user can always re-flash the bootloader over ISP. However, you've said "For anything produced in volume, even saving 1c can be a big deal".

Indeed it can. But for anything produced in volume, 'possibly' becomes 'almost certainly'. If you deploy 10,000 units with your bootloader and 1 percent of them go AWOL in the first year, that's 100 unhappy customers. In many businesses, 100 unhappy customers are heavier than 9,900 happy (or ambivalent) ones.

Saving 1c on 10,000 units is $100. That's a half-hour of a typical engineer's billable time.
A hundred unhappy customers can cost the contract. The sensible business choice is to use the larger part.

Quote:
As for what other bootloaders do, Optiboot, for instance does no error checking on the data received. Some data bytes could be getting corrupted in the transmission, and avrdude won't report any problems until the verify stage. By that time the corrupted application has already been written to flash. Optiboot will timout with a watchdog reset, and start the corrupted application.
Optiboot was written for parts with a proper boot section. BLS lock bits make it impossible for an app to overwrite the bootloader.

While optiboot can be (and probably has been) adapted for parts with no protected boot section, you are correct that it would be at risk in the same way. That doesn't mean it's OK to leave it to chance in your bootloader.

Quote:
For the reasons above, my bootloader is still better than Optiboot.
I admit I haven't looked at (or sought out) your programmer driver code. Are you saying you were already implementing my suggested sequence, or something similar?

In any case, your bootloader still can't verify flash. While verifying flash won't preclude a failed bootload, nor the execution of a corrupted application, it will identify when a successful bootload has occured. Your bootloader cannot do that. You can never know if the bootload was error free, unless you include verification code into the app, in which case why go to the trouble of squeezing the verify code out of the bootloader in the first place?

IMO this makes your bootloader not only inferior to Optiboot, but actually unusable in all but the most benign of applications. So far. Keep working! I struggle to imagine a future where you (with help or otherwise) manage to squeeze flash read alongside the existing code and keep it under 32 words. I am, of course, quite prepared to eat my hat ;). Wouldn't be the first time!

ralphd wrote:
No, I understood perfectly. I was saying I like your suggestion BECAUSE it doesn't always zero MCUSR like Optiboot.
I'm the one who misunderstood!

Although I think the small change I suggested for Optiboot would give it the same ability. I may post it to the issues list as @westfw has encouraged...

BootStart:
    in  FCS, MCUSR                  ; use MCUSR to initialize FCS
    sbrs FCS, EXTRF                 ; run bootloader on EXTRF 

I'm not certain why you're loading MCUSR into your FCS register. I assume it's because you want to 'seed' the FCS. However you're only testing EXTRF in MCUSR in order to determine whether or not to proceed with bootloading. There is no guarantee that the other bits (PORF, BORF, and WDRF) will be in any given state.

The programmer driver (avrdude) can't know the state of MCUSR prior to programming, so it can't know what seed the bootloader is working from. If the driver's seed differs, the check of the first packet's FCS will fail.

As written, this isn't a show stopper because your bootloader will simply restart before making any changes to flash. Since you clear MCUSR as part of the first delay loop, and provided the 'seed' used by the driver's FCS code is (1<<EXTRF), the second attempt will proceed normally.

However I'd suggest you seed the FCS register some other way in order to avoid the possibility of this 'false start'. I know that currently you're at 32 words exactly, so it may require more cleverness ;) ...

It is only an annoyance, really, and shouldn't in and of itself prevent a successful bootload, provided the driver is written to handle an FCS error on the first 'packet' of the first attempt as normal.

-----------------

One possible scenario that needs to be accounted for is an improperly handled application-triggered wdt reset. Imagine that the app uses the WDT to trigger a reset, but fails to properly disable the WDT (in an .initN section or early in main) by first clearing WDRF and then disabling via the required timed sequence. An external reset would trigger your bootloader, but WDRF would still be set, so your first FCS would fail on the first attempt. So long as the driver sends it's first byte within 15 ms MCUSR will be cleared, but you never disable the WDT so the device will reset anyway.

You might manage to receive, erase, and write the first page (which should be the page containing the bootloader-pointing 'VirtualReset' vector) before 15 ms goes by, if the baud rate is fast enough. After which a power-cycle will restore normal operation. The need for a power-cycle would be a problem where physical access to the device is difficult/impossible.

So an error on the part of the (human) application programmer can lock you out of the bootloader.

Can you beat 15 ms? Let's do some math.

Different devices will vary, but working from the ATtiny25/45/85 datasheet we see that page erase takes a maximum of 4.5 ms. Page write takes the same amount of time, but so long as the write starts before the WDT reset pulls the rug out, it will be completed:

In the datasheet, Atmel wrote:
If a reset occurs while a write operation is in progress, the write operation will be completed provided that the power supply voltage is sufficient.
Since your bootloader does nothing to inform the driver that it is ready for more data after a page erase or page write, the driver must busy loop for this period of time. It seems reasonable to set a minimum of 5 ms after commanding a page erase or a page write, before sending the next packet.

So:

    - receive bytes - erase page (5 ms)
    - receive bytes
    - initiate write
With the page erase taking 5 ms, that leaves 10 ms for the rest.

From what I can gather by looking at your code it takes 8 received bytes to place one word into the flash temporary buffer. Two packets of 4 bytes each consisting of 3 bytes plus an FCS. First packet sets address in Z, second packet receives word and places it in the buffer. It would only take 4 bytes received to erase a page, since Z would already be correctly set. Similarly, 4 bytes to initiate the page write.

So a total of 15 bytes (you currently don't wait for the FCS before spm, although you should) must be received in 10 ms, or about 67 us per bit. That's around 15 bps. At 8 MHz with your 8-bit Delay3Cycle routine you can theoretically get as low as about 10.4 kbps, but you should impose a lower limit of 19.2 kbps.

So, it's possible. Maybe.

However we haven't considered any latency between the end of reset when the WDT starts counting towards a the next reset 15 ms away, and the beginning of the bootloading process itself. Even if you were able to receive at 115.2 kbps, it would still take 5.1 ms for the receive/erase/receive, leaving you a narrow margin of no more than 9.9 ms to start the bootload process after reset.

This can get complicated when you consider different SUT/CKSEL configurations, and different serial driver latencies on different hosts. 9.9 ms isn't a lot of time. I suppose you could have an adaptive timing algorithm in the programmer driver, but that's starting to get fairly complicated, and won't guarantee success with all hosts in all cases.

In cases where the target can't be power-cycled (remote update), you might manage to program a 'rescue' app, consisting of a single page, which properly clears MCUSR and disables the WDT, then halts. The resuce app could be something as simple as:

; beginnin of 2nd-last page
.org (FLASHEND - (2 * SPM_PAGESIZE) + 1)
Rescue:
    eor r1, r1
    ldi r16, (1<<WDCE) | (1<<WDE);
    out MCUSR, r1
    sts WDTCSR, r16
    sts WDTCSR, r1
    rjmp BootStart
    
.org (FLASHEND - SPM_PAGESIZE - 1)
VirtualReset:
    rjmp Rescue
BootStart:

Note the use of WDTCSR and sts, as required by some devices like the ATmega88. This is two words longer than WDTCR/in for the ATtiny85.

This could restore bootloader control without the need for a power-cycle, but it is longer than than the simple 'VirtualReset' vector replacement detailed above. Nine words in all. This adds 64 received bytes to the bootloading session, for a total of 79 bytes. This increases the minimum baud rate to 79 kbps, excluding any latency between the end of reset and the first received byte. At 115.2 kbps, the margin for latency drops to 3 ms.

    ; execute program memory command - 0 = nop
    out SPMCSR, data
    spm
    sbi UART_Port-2, UART_Tx        ; toggle Tx break
    rcall RxByte                    ; read FCS
    cp  FCS, data
    breq CommandLoop                ; next command
    ; on FCS error, start application
    ; programmer will loose sync and report error
    ; programmer intentionally sending bad FCS doubles as
    ; a command to start application after programming
    rjmp VirtualReset               ; jump to application code

This sequence allows for a page erase or write operation before checking the FCS of the packet which initiated it.

Quote:
With my bootloader has ~30 chances to detect an FCS error before a page could get written.
That's not how FCS works. Yes, your FCS is cumulative over the entire bootload session, but that is in no way insurance against a hash collision. And since you spm before receiving or checking the FCS, all that needs to occur is for the flash address in an page erase command or page write command to be corrupted and the bootload has failed. If you're unlucky, the page you're erasing or writing will be the bootloader's page. FCS must be checked before spm.

Isn't this backwards?:

    movw r0, ZL                     ; command 0 = set Z

Shouldn't it be:

    movw ZL, r0

Isn't this also backwards?:

    cpse delayArg, data             ; delayArg == 0 after RxByte
    movw r0, ZL                     ; command 0 = set Z

As is, the movw into Z is skipped if the command is 0.

----------------------
Perhaps instead of clearing MCUSR you could reset the WDT with wdr. This will have two beneficial effects: Your bootloader will be (more) resistant to an improperly handled application-triggered WDT reset, and MCUSR will be unchanged even after a bootload session.

I think the best place for a wdr would be in the loop which waits for a start bit.

RxByte:
    wdr
    sbic UART_Port, UART_Rx         ; wait for start edge
    rjmp RxByte

This would nullify the problem of recovering from an improperly handled application-triggered WDT reset.

BTW:

.org (FLASHEND - SPM_PAGESIZE -3)

... why -3? If you wan't to place a 2-byte rjmp instruction at the very end of the second-last page of flash, shouldn't it be:

.org (FLASHEND - SPM_PAGESIZE - 1)

Otherwise Bootstart: will be placed at the last word of the second last page instead of the first word of the last page as intended.

EDIT: Ah, I see you've made some changes, some of the above may not apply. I'll review your new code, but probably not tonight ;)

"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

joeymorin wrote:
ralphd wrote:
I think you are exaggerating with "very possibly overwrite the bootloader".
Is it likely? No. Is it possible? Yes. Therefore 'possibly'. I don't see room for exaggeration.

I don't see any room for superfluous words like "very" except for exaggeration.

I appreciate the coding comments, but some of the comments seem to be "I don't feel it's reliable enough." I don't work on feelings, I work on facts.

After I explain how my bootloader is less likely than Optiboot to create your "frankenstien's monster" application, you change your argument to say what matters is protecting the bootloader section. If your argument doesn't really matter than I'm just wasting my time refuting it.

Take a look at Micronucleus and tell me what you think:
https://github.com/micronucleus/...

It does no verification, and since it's on an ATtiny85, it has no hardware bootloader protection. Yet something that according to your argument is not reliable enough for production (the Digispark with the micronucleus bootloader) raised >$300,000 on Kickstarter.
https://www.kickstarter.com/proj...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

BootStart:
    in  FCS, MCUSR                  ; use MCUSR to initialize FCS
    sbrs FCS, EXTRF                 ; run bootloader on EXTRF 

I'm not certain why you're loading MCUSR into your FCS register.


You're looking at an old copy of the code. (As you noticed at the end of your post)

joeymorin wrote:

Isn't this backwards?:
    movw r0, ZL                     ; command 0 = set Z

Shouldn't it be:

    movw ZL, r0

Isn't this also backwards?:

    cpse delayArg, data             ; delayArg == 0 after RxByte
    movw r0, ZL                     ; command 0 = set Z

As is, the movw into Z is skipped if the command is 0.

Awesome. This kind of code review is very helpful. Probably would have taken me a half hour of debugging before I would have realized I had the movw arguments reversed.

I think the cpse mistake was when I was looking at the instruction set to see if I could find something like cpsne (compare, skip not equal). Must've got distracted, and never remembered to fix it. Guess a compare and branch is what I'll have to do.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Quote:
It's unlikely I would have any use for a bootloader with no error detection and which can't read back flash

One well known bootloader with these particular "features" is the HalfKay USB bootloader used on the Teensy products It has no error error detection and can't read back flash.
If your cables are kept short the risk of garbled comms is probably pretty low. I use avrdude and a serial avr910 protocol bootloader and I don't think I've ever seen avrdude report a data error when reading back the data.

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

I don't know if data corruption during the transmission is really a concern (unless the data passes over a "noisy" link like RF) but what should always be a major concern in any bootloader is what happens if someone pulls the power lead or the comms wire half way through the process. When power is reapplied can the system always either continue from where it got to or at least start the whole process over. If there is any "hole" in the design where the system can get to a state that it cannot be recovered from it is Goodnight Vienna!

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

Quote:
Take a look at Micronucleus .... and since it's on an ATtiny85, it has no hardware bootloader protection.

Micronucleus has no hardware bootloader protection but it does have code to prevent the bootloader being overwritten. This makes the bootloader bigger, of course.

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

flenser wrote:
Quote:
Take a look at Micronucleus .... and since it's on an ATtiny85, it has no hardware bootloader protection.

Micronucleus has no hardware bootloader protection but it does have code to prevent the bootloader being overwritten. This makes the bootloader bigger, of course.

For picoboot I'll do that in the programmer. So it will have code to prevent the bootloader from being overwritten, but will keep the bootloader small since it is on the programmer side.

It looks like someone new is taking over micronucleus from Jenna and is working on some good changes in the system (bootloader and programmer) to reduce the size. I've gone through the code for Micronucleus and USBAspLoader and figure a 1KB USB bootloader is achievable. Even 512 bytes is within reach with a re-write of v-usb. V-usb is a pretty incredible (and complex) piece of code. One idea I have is to gut v-usb with a smaller and simpler core that works even at 8Mhz.
http://code.google.com/p/picoboo...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Your integrated blink test app is a nice touch, but it's missing something:

    sbi DDRB, 5

And if you want to make it more generic, you may wish to use a different bit. Bit 5 isn't available on the ATtiny25/45/85 unless RSTDISBL is programmed.

-------------------

.org (FLASHEND - 65)

Looks like you beat me to the '-3' v.s. '-1' I mentioned earlier, but I would discourage hard-coded constants. There's nothing wrong with:

.org (FLASHEND - SPM_PAGESIZE - 1)

True your bootloader is tailor-made for a 32-word page, but what if I want to use it on a device with a 64-word page?

-------------------

This tests PORTB:

BootStart:
    sbis UART_Port, UART_Rx         ; Rx high = start bootloader

You should be testing PINB, yes?:

    sbis UART_Port-2, UART_Rx

Come to think of it:

RxByte:
    sbic UART_Port, UART_Rx         ; wait for start edge
    rjmp RxByte

... has the same problem.

-------------------

Wait, I see that you've moved the break toggle to after the spm. Is that new? Or did I just misread your code earler... In any case this obviates the need for the driver to busy loop for 5 ms as I noted earlier. I was going to make that suggestion, but either you beat me to it or I'm going crosseyed ;)

-------------------

    clr FCS

Beat me to it again ;)

-------------------

    ; when upload is finished, programmer resets chip & starts app
    ; by transmitting a null byte during BootStart

So the bootloader only starts if UART_Rx is high. What if the app's circuit pulls UART_Rx high? Eternal bootloader. What if the app's circuit has UART_Rx as a floating input? Intermittently eternal bootloader.

Yes the argument could be made that since UART_Rx is being used for bootloading that it should have no other use and therefore could be weakly pulled externally low. Since you're targetting low-flash and/or low-pin-count devices this seems limiting. I think if you return to your use of EXTRF and add WDR as suggested earlier it would be more flexible.

Mind you, now that I think of it relying on EXTRF without clearing MCUSR puts you in a position similar to an improperly handled application-triggered WDT reset. Without clearing EXTRF you'd end up in an eternal bootloader loop.

Maybe test EXTRF and clear MCUSR in Delay3Cycle as discussed earlier. Yes MCUSR will be lost to the app on the first run after a bootload, but that's really not important. In fact the app can infer that a bootload just took place because MCUSR is clear, since there are no other circumstance under which this would be so.

Perhaps there's another option. I'll have to sleep on it again...

-------------------

ralphd wrote:
I don't see any room for superfluous words like "very" except for exaggeration.
A flaccid argument:
ralphd wrote:
I am extremely logical, so it is very hard to offend me
ralphd wrote:
Not very readable, but I'm a function over fashion kind of guy...
Suck it up ;)

-------------------

Quote:
After I explain how my bootloader is less likely than Optiboot to create your "frankenstien's monster" application,
I agreed with you:
joeymorin wrote:
While optiboot can be (and probably has been) adapted for parts with no protected boot section, you are correct that it would be at risk
I also suggested a change to Optiboot that would bring it in line with yours.

Quote:
you change your argument to say what matters is protecting the bootloader section.
Rubbish. I added a new thought to an existing argument by which I stand.

I also observed:

Quote:
Optiboot was written for parts with a proper boot section. BLS lock bits make it impossible for an app to overwrite the bootloader.
Stated plainly, no BLS means you simply can't guarantee the integrity of the bootloader. A failed bootload may result in broken app code that clobbers the bootloader. A successful bootload may deliver a poorly or maliciously written app which clobbers the bootloader. A bug or shortcoming in the bootloader may result in the bootloader clobbering itself. Of these three failure modes the first and third are fully under the control of the author of the bootloader, but the second can never be.

There is no need to exaggerate, because there is no grey area here, no room for interpretation. A non-BLS bootloader can fail irretrievably. The likelihood is non-zero. For most commercial applications this is intolerable, and non-BLS devices would be removed from consideration at the earliest stages of design. This was surely the motivation for designing the first self-programmable devices with a BLS.

However there is room for and value to a non-BLS bootloader, as witnessed by the sea of available options. There is also room to make a better one. At the moment your bootloader is small and impressive, but it can't yet deliver immunity from any failure mode. I think it can be made to. It may even be possible to do in 32 words. Clearly this is so, or I wouldn't have invested the time to respond. You asked for help. The word is right there in the thread title. This is me giving it to you. But this is your project, and the choices are yours to make.

-------------------

Quote:
I appreciate the coding comments, but some of the comments seem to be "I don't feel it's reliable enough." I don't work on feelings, I work on facts.
No-one but you has typed the word 'feeling' into this thread, and it is a mistake to consider my comments an expression of feeling. They are the product of analysis. You may disagree with that analysis. The analysis may even be flawed. That's fine. However if your rebuttals are going to be limited to the form of "that NT is just emotionally irrational and my bootloader is beyond reproach" then I'll be more than happy to stop commenting. That's about as disrespectful as the perceived discrimination you spoke of in your very first thread.

Perhaps we can dispense with any further "I said" / "you said" nonsense and just focus on the code from now on? Just take it as a given that I'm not a complete moron wandering through the world at the mercy of my amygdalae, and I'll take it as a given that you're not a disembodied brain on a stick bent on world domination. Yes?

-------------------

Quote:
Take a look at Micronucleus and tell me what you think:
Later, but I will. However I will say for now that a successful fund-raising campaign is hardly an accurate measure of a product's reliability. Microsoft 'raised' billions of dollars by selling supremely unreliable software for years before they started to get it right.

-------------------

#define F_CPU 8000000UL
#define BAUD  115200UL

#define DELAY_CALL_RET_COST 7
#define DELAY_LOOP_COST 3
#define DELAY_LOOP_CREDIT 1
#define RX_BIT_LOOP_COST 6

#define RX_OVERHEAD (DELAY_CALL_RET_COST-DELAY_LOOP_CREDIT+RX_BIT_LOOP_COST)

#define RXDELAY_CYCLES ((((2*F_CPU)/BAUD)+1)/2)
#define RXDELAY ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

#define RXSTART_CYCLES ((((3*F_CPU)/BAUD)+1)/2)
#define RXSTART ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

May need some tweaking to handle edge cases where the two banker's roundings compound instead of mitigate the error, but as-is it delivers the expected 19 and 31.

The other option is to do it in floating point in C and export it as a variable, as suggested by @clawson in another thread.

-------------------

Quote:
Guess a compare and branch is what I'll have to do.
Won't that cost you another word?

-------------------

There are some remaining issues, like doing the spm before receiving and checking the FCS.

This might do it:

    movw ZL, r0                     ; command 0 = set Z
    mov tmp, data                   ; preserve command
    rcall RxByte                    ; read FCS
    cp  FCS, data
Halt:
    brne Halt                       ; Halt on FCS error
    ; execute program memory command - 0 = nop
    out SPMCSR, tmp
    spm
    sbi UART_Port-2, UART_Tx        ; toggle Tx break signal
    rjmp CommandLoop                ; next command

... but at the cost of a word. Add that to the word cost to fix the cpse and you're over by two words.

///////////////////////////////////////////////////////////////////////////////

"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 added the protocol specification to the code comments:

* The protocol is a sequence of 4-byte frames:
* data lo, data hi, command, FCS (continuous EOR)
* data is copied to r0, r1, command is written to SPMCSR, followed
* by the spm instruction. If bit 6 of the command is set, r0 & r1
* are copied to Z
*
* bootloader acks to programmer with a break signal before FCS
* which starts on even frames and ends on odd frames

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:
Your integrated blink test app is a nice touch, but it's missing something:
    sbi DDRB, 5

And if you want to make it more generic, you may wish to use a different bit. Bit 5 isn't available on the ATtiny25/45/85 unless RSTDISBL is programmed.


Yes, defining LEDPIN and then not using it was a mistake. Fixed.

joeymorin wrote:

.org (FLASHEND - 65)

Looks like you beat me to the '-3' v.s. '-1' I mentioned earlier, but I would discourage hard-coded constants. There's nothing wrong with:

.org (FLASHEND - SPM_PAGESIZE - 1)

True your bootloader is tailor-made for a 32-word page, but what if I want to use it on a device with a 64-word page?


This is so it will work with a 16-word page (like the ATtiny25). I have no plans to support devices with 64-word pages. Those are the 16KB and up devices, which use a 2-word jmp instruction for the reset vector.

joeymorin wrote:

This tests PORTB:
BootStart:
    sbis UART_Port, UART_Rx         ; Rx high = start bootloader

You should be testing PINB, yes?:

    sbis UART_Port-2, UART_Rx

Come to think of it:

RxByte:
    sbic UART_Port, UART_Rx         ; wait for start edge
    rjmp RxByte

... has the same problem.


Good eye there. One problem with keeping a few different versions of my soft UART code is mistakenly coping form one of the untested versions!
Fixed now.

joeymorin wrote:

    ; when upload is finished, programmer resets chip & starts app
    ; by transmitting a null byte during BootStart

So the bootloader only starts if UART_Rx is high. What if the app's circuit pulls UART_Rx high? Eternal bootloader. What if the app's circuit has UART_Rx as a floating input? Intermittently eternal bootloader.

Yes the argument could be made that since UART_Rx is being used for bootloading that it should have no other use and therefore could be weakly pulled externally low. Since you're targetting low-flash and/or low-pin-count devices this seems limiting. I think if you return to your use of EXTRF and add WDR as suggested earlier it would be more flexible.
[...]
Perhaps there's another option. I'll have to sleep on it again...


I've given it a lot of thought, and am going to test it the way it is. On pin-limited devices the Rx line could be used for output by the application. I.e. PB1 on the digispark which is used as the LED pin, which is pulled down to ground through the LED and a ~1K resistor.
Once I've tested and used it for a bit that way I'll re-evaluate.

joeymorin wrote:

Perhaps we can dispense with any further "I said" / "you said" nonsense and just focus on the code from now on? Just take it as a given that I'm not a complete moron wandering through the world at the mercy of my amygdalae, and I'll take it as a given that you're not a disembodied brain on a stick bent on world domination. Yes?

OK, sounds good. I'll put my world domination plan on hold for a while. :-)

joeymorin wrote:

#define F_CPU 8000000UL
#define BAUD  115200UL

#define DELAY_CALL_RET_COST 7
#define DELAY_LOOP_COST 3
#define DELAY_LOOP_CREDIT 1
#define RX_BIT_LOOP_COST 6

#define RX_OVERHEAD (DELAY_CALL_RET_COST-DELAY_LOOP_CREDIT+RX_BIT_LOOP_COST)

#define RXDELAY_CYCLES ((((2*F_CPU)/BAUD)+1)/2)
#define RXDELAY ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

#define RXSTART_CYCLES ((((3*F_CPU)/BAUD)+1)/2)
#define RXSTART ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

May need some tweaking to handle edge cases where the two banker's roundings compound instead of mitigate the error, but as-is it delivers the expected 19 and 31.


Wow, nice work. I was thinking of leaving it hard-coded so a single binary would work @8Mhz/115.2kbps and 16Mhz/230.4kbps. But seeing your macros, they're definitely in. I'm particularly impressed with considering the call/ret overhead. It's 7 on all AVRs, but on the LGT8F88A (AVR clone) it's less than that.

joeymorin wrote:

There are some remaining issues, like doing the spm before receiving and checking the FCS.

The plan is to cover that in the programmer. I'll send a set Z command, then the spm erase page will be in the next frame. If the FCS for the set Z frame is bad, the bootloader halts and won't read the spm erase frame.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

.org (FLASHEND - 65)

Looks like you beat me to the '-3' v.s. '-1' I mentioned earlier, but I would discourage hard-coded constants. There's nothing wrong with:

.org (FLASHEND - SPM_PAGESIZE - 1)

True your bootloader is tailor-made for a 32-word page, but what if I want to use it on a device with a 64-word page?

I forgot to mention that SPM_PAGESIZE is wrong for some parts. I submitted bug #41519 for avr-libc and offered to commit a patch, but Jeorg's ego seems more important than improving avr-libc.
I don't kiss up to anyone, and hardcodnig the bootloader size is an easy workaround anyway.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:

joeymorin wrote:

.org (FLASHEND - 65)

Looks like you beat me to the '-3' v.s. '-1' I mentioned earlier, but I would discourage hard-coded constants. There's nothing wrong with:

.org (FLASHEND - SPM_PAGESIZE - 1)

True your bootloader is tailor-made for a 32-word page, but what if I want to use it on a device with a 64-word page?


This is so it will work with a 16-word page (like the ATtiny25). I have no plans to support devices with 64-word pages. Those are the 16KB and up devices, which use a 2-word jmp instruction for the reset vector.

And using (the sometimes broken) SPM_PAGESIZE still wouldn't help with odd parts like the ATtiny1634. It has a 16-word page size, but requires pages to be erased/written 4 at a time with a 64-word page buffer (if I ever did decide to support >8K flash parts).

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
Yes, defining LEDPIN and then not using it was a mistake. Fixed.
Not that it matters much, but why still pin 5? Are you recommending RSTDISBL for ATtiny24/45/85 bearing picoboot? That's one way to make sure users keep using it ;)

-----------------------

Quote:
I have no plans to support devices with 64-word pages. Those are the 16KB and up devices, which use a 2-word jmp instruction for the reset vector.
A jmp is not mandatory. An rjmp may be used if the destination is in range. AFACT a 'VirtualReset' vector at the end of the second-last page is reachable by rjmp with a negative offset, regardless of the actual flash size (up to 128KB).

In any event, not all devices with 64-word pages have more than 8KB of flash:

    ATtiny87 ATmega8U2 *
    AT90USB82 **
    ATmega8HVA ***
    ATA5272 ****
    ATA6616C ****
* The datasheet lists the 8U2 with a 32-word page, but the header file has #define SPM_PAGESIZE (128). I have no 8U2 with which to test. ** Supports BLS
*** Unlikely target (esoteric)
**** SOC w/ATTiny87 (unlikely target)

There are also a couple of 4KB devices with 64-word pages, and a surprising number of 4KB and 8KB devices with 128-word page sizes! Granted many of these are esoteric and unlikely targets for picoboot, but support for them is easy to accomodate:

#define PICOBOOT_MIN_PAGE_ALIGN 64

#if (SPM_PAGESIZE > PICOBOOT_MIN_PAGE_ALIGN)
#define VIRTUAL_RESET_ORG (FLASHEND - SPM_PAGESIZE) - 1)
#else
#define VIRTUAL_RESET_ORG (FLASHEND - PICOBOOT_MIN_PAGE_ALIGN - 1)
#endif

.org VIRTUAL_RESET_ORG

Note that the ATtiny441/841 have 8-word flash page sizes (although page erase is done in 4-page blocks).

-----------------------

Quote:
I'm particularly impressed with considering the call/ret overhead.
Really? I imagined you'd be more impressed by DELAY_LOOP_CREDIT ;)

-----------------------

Quote:
The plan is to cover that in the programmer. I'll send a set Z command, then the spm erase page will be in the next frame. If the FCS for the set Z frame is bad, the bootloader halts and won't read the spm erase frame.
That's better, but there's still the possibility that the command packet itself is corrupted. The corrupted command could load a word into flash, or it could issue PGERS, or RSIG, or CTPB, or RFLB... or any combination of those bits and/or PGWRT. The datasheets aren't clear whether there is a hierarchy of priority among the bits, or if behaviour is undefined.

The better solution is to verify the entire packet before the spm. I Don't know how to do it. Yet. I was on to something earlier today, but it turned out I was mistaken :(

-----------------------

Quote:
but Jeorg's ego seems more important than improving avr-libc
Device header files for AVR Libc are taken from Atmel's XML device files, so the error is likely upstream. If I was the maintainer, I wouldn't take a bug report on faith any more than you would. You would want to verify the bug with the upstream source, the manufacturer, and preferably with a real device. This is necessary to rule out a datasheet erratum.

You only submitted your bug report 5 days ago. And as bugs go this is a pretty minor one. AVR Libc is open source and maintained largely by volunteers. People have lives. It will happen. Patience, Ralph-san.

Quote:
hardcodnig the bootloader size is an easy workaround anyway.
If you yourself have verified the true page size on a real device:
; Workaround for unresolved AVR Libc issue #41519
#if (defined __AVR_ATtiny48__) || (defined __AVR_ATtiny88__)
#undef SPM_PAGESIZE
#define SPM_PAGESIZE 64
#endif

You could also wrap this local test in a test against __AVR_LIBC_VERSION__ and skip it once an upstream fix is released. This is how it's done.

Quote:
And using ... SPM_PAGESIZE still wouldn't help with odd parts like the ATtiny1634. It has a 16-word page size, but requires pages to be erased/written 4 at a time with a 64-word page buffer
That's of no consequence to the bootloader itself. The 4-page block applies only to a page erase, not a page write. Page loads and page writes are done one page (16-words) at a time. The programmer would need to be aware of course and not command a page erase between page writes within a 4-page block.

When building the bootloader you'd need to account for it and place the 'VirtualReset' vector in the last word of the 5th last page, followed by the bootloader:

#define PICOBOOT_MIN_PAGE_ALIGN 64

#if (defined __AVR_ATtiny1634__) || (defined __AVR_ATtiny441__) || (defined __AVR_ATtiny841__)
#define SPM_PAGEBLOCKSIZE (4 * SPM_PAGESIZE)
#else
#define SPM_PAGEBLOCKSIZE SPM_PAGESIZE

#if (SPM_PAGEBLOCKSIZE > PICOBOOT_MIN_PAGE_ALIGN)
#define VIRTUAL_RESET_ORG (FLASHEND - SPM_PAGEBLOCKSIZE) - 1)
#else
#define VIRTUAL_RESET_ORG (FLASHEND - PICOBOOT_MIN_PAGE_ALIGN - 1)
#endif

The effort to support these devices is so minimal, I can't conjure a reason not to.

True on such devices the consequence of course is the 3 wasted pages, but those pages could be utilised by your soon-to-be-announced picobootplus ;)

BTW, I've begun work on a yet-to-be-named 16-word bootloader ;)

"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

joeymorin wrote:
ralphd wrote:
Yes, defining LEDPIN and then not using it was a mistake. Fixed.
Not that it matters much, but why still pin 5? Are you recommending RSTDISBL for ATtiny24/45/85 bearing picoboot? That's one way to make sure users keep using it ;)

PB5 seems to be the de-facto on-board LED pin for AVR boards.

joeymorin wrote:

Quote:
I have no plans to support devices with 64-word pages. Those are the 16KB and up devices, which use a 2-word jmp instruction for the reset vector.
A jmp is not mandatory. An rjmp may be used if the destination is in range. AFACT a 'VirtualReset' vector at the end of the second-last page is reachable by rjmp with a negative offset, regardless of the actual flash size (up to 128KB).

Good point. Something worth considering.

joeymorin wrote:

There are also a couple of 4KB devices with 64-word pages, and a surprising number of 4KB and 8KB devices with 128-word page sizes! Granted many of these are esoteric and unlikely targets for picoboot, but support for them is easy to accomodate:
#define PICOBOOT_MIN_PAGE_ALIGN 64

#if (SPM_PAGESIZE > PICOBOOT_MIN_PAGE_ALIGN)
#define VIRTUAL_RESET_ORG (FLASHEND - SPM_PAGESIZE) - 1)
#else
#define VIRTUAL_RESET_ORG (FLASHEND - PICOBOOT_MIN_PAGE_ALIGN - 1)
#endif

.org VIRTUAL_RESET_ORG

Note that the ATtiny441/841 have 8-word flash page sizes (although page erase is done in 4-page blocks).


I'm going to leave it hardcoded for now. I have some Tiny85's to test with, and yesterday UPS dropped a box off from Newark with a bunch of ATtiny88's and a couple ATtiny84's. I may even try it on a 328p, since you pointed out the negative offset rjmp should work on >8K parts.

Keeping the bootloader simple is good, but if it adds a lot more complexity to the programmer, then I'll leave it out until someone who has some of the less popular chips can write the code or at least test it for me if I write it. And there's still the issue of SPM_PAGESIZE being buggy in avr-libc.

joeymorin wrote:

Quote:
I'm particularly impressed with considering the call/ret overhead.
Really? I imagined you'd be more impressed by DELAY_LOOP_CREDIT ;)

:-) The impressive part isn't that you can add 3 + 4, but that you considered that it might not always be 3 + 4.

joeymorin wrote:

Quote:
The plan is to cover that in the programmer. I'll send a set Z command, then the spm erase page will be in the next frame. If the FCS for the set Z frame is bad, the bootloader halts and won't read the spm erase frame.
That's better, but there's still the possibility that the command packet itself is corrupted. The corrupted command could load a word into flash, or it could issue PGERS, or RSIG, or CTPB, or RFLB... or any combination of those bits and/or PGWRT. The datasheets aren't clear whether there is a hierarchy of priority among the bits, or if behaviour is undefined.

The better solution is to verify the entire packet before the spm. I Don't know how to do it. Yet. I was on to something earlier today, but it turned out I was mistaken :(


If you come up with something, I'll put it in. Since it doesn't impact reliability, I'm more focused on figuring out the internals of avrdude so I can get a working programmer for testing the bootloader. I already have a working skeleton:
$ ./avrdude -p t85 -c picoboot -P com17

avrdude.exe: programmer operation not supported
avrdude.exe: programmer operation not supported
avrdude.exe: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.

avrdude.exe: programmer operation not supported

avrdude.exe done. Thank you.

joeymorin wrote:

Quote:
And using ... SPM_PAGESIZE still wouldn't help with odd parts like the ATtiny1634. It has a 16-word page size, but requires pages to be erased/written 4 at a time with a 64-word page buffer
That's of no consequence to the bootloader itself. The 4-page block applies only to a page erase, not a page write. Page loads and page writes are done one page (16-words) at a time. The programmer would need to be aware of course and not command a page erase between page writes within a 4-page block.
[...]
BTW, I've begun work on a yet-to-be-named 16-word bootloader ;)

I re-read the data sheet, and it looks like you're right about only the erase requiring 4 pages. Again, something I may go back and add after I get it working on the parts that I have, if I find someone willing to test it on the other parts.

In a few weeks I'll probably get a couple 2313a's to test with. I think those along with the tiny85s and tiny84s I'll be testing with should cover the most popular parts that would benefit from picoboot.
And when more people check out the ATtiny88, I think most will like them just as much as me.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

Quote:
but Jeorg's ego seems more important than improving avr-libc
Device header files for AVR Libc are taken from Atmel's XML device files, so the error is likely upstream. If I was the maintainer,

I volunteered to help maintain avr-libc.

I sent an email to a couple of the other libc members with the subject, "I can help with avr-libc".

Hi guys,

I'm willing to maintain and contribute to avr-libc. I am an expert in
low-level electronics, assembler, C, and early C++ (I only recently
started reading up on C++11).
Here's a couple of examples of my AVR work:
http://nerdralph.blogspot.ca/201...
http://nerdralph.blogspot.ca/201...
http://code.google.com/p/picoboot/

My experience with Jeorg is that he is dismissive of contributions to
avrdude, but that's no reason for me to assume the rest of you in the
avr-libc team share his attitude.

So are you interested in having me contribute to avr-libc?
The first thing I'd do is commit a fix for bug #41519.

It's been 5 days with no reply, so I expect none will be forthcoming.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

BTW, I've begun work on a yet-to-be-named 16-word bootloader ;)

That's actually feasible. Using USI instead of my soft UART, I'm pretty sure I could do it. Maybe even while still doing error checking.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
joeymorin wrote:

BTW, I've begun work on a yet-to-be-named 16-word bootloader ;)

That's actually feasible. Using USI instead of my soft UART, I'm pretty sure I could do it. Maybe even while still doing error checking.

I could do flash read in that amount of space, so lack of error checking wouldn't be as much of an issue.

The main code size savings would be in RxByte:
SPIxfer:
sbis USISR, USIOIF
rjmp SPIxfer
sbi USISR, USIOIF ; clear USIOIF
in data, USIDR
ret

CommandLoop would be almost the same, except without toggling UART_Tx, and with 3 byte frames instead of 4 (no FCS).

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Quote:
Jeorg's ego seems more important than improving avr-libc

Quote:
My experience with Jeorg is that he is dismissive of contributions to
avrdude
Ralph, these are not helpful comments. Please don't make them. We are all here to exchange ideas and help each other.

regards
Greg

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

joeymorin wrote:

#define F_CPU 8000000UL
#define BAUD  115200UL

#define DELAY_CALL_RET_COST 7
#define DELAY_LOOP_COST 3
#define DELAY_LOOP_CREDIT 1
#define RX_BIT_LOOP_COST 6

#define RX_OVERHEAD (DELAY_CALL_RET_COST-DELAY_LOOP_CREDIT+RX_BIT_LOOP_COST)

#define RXDELAY_CYCLES ((((2*F_CPU)/BAUD)+1)/2)
#define RXDELAY ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

#define RXSTART_CYCLES ((((3*F_CPU)/BAUD)+1)/2)
#define RXSTART ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

May need some tweaking to handle edge cases where the two banker's roundings compound instead of mitigate the error, but as-is it delivers the expected 19 and 31.

How did you test it? I added it to picoboot and got errors:

picobootSerial.S: Assembler messages:
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Error: missing ')'
picobootSerial.S:123: Warning: constant out of 8-bit range: 32000000
picobootSerial.S:123: Error: garbage at end of line

I double-checked the parenthesis matching, and that was fine.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
It's been 5 days with no reply, so I expect none will be forthcoming.
You blew it.

-----------------

ralphd wrote:
That's actually feasible. Using USI instead of my soft UART, I'm pretty sure I could do it. Maybe even while still doing error checking.
I wasn't kidding. But I'm glad you're considering taking up the mantle.

-----------------

Quote:
I could do flash read in that amount of space
...
CommandLoop would be almost the same, except without toggling UART_Tx, and with 3 byte frames instead of 4 (no FCS).
While flash read is important for reasons already discussed, it does not obviate the need to validate the integrity of the data, addresses, and commands from the programmer before acting on them. FCS is still advisable.

With USI as you've already explored you stand a chance at getting your 32-word cake and reading it too. A 16-word write-only version may also be possible for those 'really tight corners'.

Exciting!

-----------------

Quote:
How did you test it?
I didn't. Should have appended the word 'Untested'. My assertion that it spit out 19 and 31 was based on a manual check done on a calculator. Shame on me.

Looks like the assembler doesn't understand the 'UL' suffix used by C to declare 32-bit unsigned integer constants. Fortunately it doesn't seem to need them:

#define F_CPU 8000000
#define BAUD  115200

I also let a copy/paste error slip by:

#define RXSTART ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

Should be:

#define RXSTART ((((2*(RXSTART_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

Tested:

#include 

#define F_CPU 8000000
#define BAUD  115200

#define DELAY_CALL_RET_COST 7
#define DELAY_LOOP_COST 3
#define DELAY_LOOP_CREDIT 1
#define RX_BIT_LOOP_COST 6

#define RX_OVERHEAD (DELAY_CALL_RET_COST-DELAY_LOOP_CREDIT+RX_BIT_LOOP_COST)

#define RXDELAY_CYCLES ((((2*F_CPU)/BAUD)+1)/2)
#define RXDELAY ((((2*(RXDELAY_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

#define RXSTART_CYCLES ((((3*F_CPU)/BAUD)+1)/2)
#define RXSTART ((((2*(RXSTART_CYCLES-RX_OVERHEAD))/DELAY_LOOP_COST)+1)/2)

        .section .text
        .global main
main:   ldi     r16, RXDELAY
        ldi     r17, RXSTART       
        .end

Confirmed:

00000000 <__ctors_end>:
   0:   03 e1           ldi     r16, 0x13       ; 19
   2:   1f e1           ldi     r17, 0x1F       ; 31

"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

joeymorin wrote:
ralphd wrote:
It's been 5 days with no reply, so I expect none will be forthcoming.
You blew it.

You seem to be under the false impression I wanted to help with avr-libc. I'm WILLING to help (a conscious choice), but I have no DESIRE (an emotion) to help.

joeymorin wrote:

Quote:
I could do flash read in that amount of space
...
CommandLoop would be almost the same, except without toggling UART_Tx, and with 3 byte frames instead of 4 (no FCS).

With USI as you've already explored you stand a chance at getting your 32-word cake and reading it too.

*groan*
Good one, but a long way from being Monty Python material... :-)

joeymorin wrote:

Confirmed:
00000000 <__ctors_end>:
   0:   03 e1           ldi     r16, 0x13       ; 19
   2:   1f e1           ldi     r17, 0x1F       ; 31


Thanks. I'll probably put it back in later today.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

I've been working on the programmer side, and it looks like I'd have to add a special function to avrdude's serial.h for receiving break signals (and separate Win32 and posix implementations of it). Since reading bytes is just a call to serial_recv, and given the feasibility of full two-way data transfer using USART or USI, I've changed the protocol to ACK every byte by transmitting 0x80. This will leave open a way to support flash read (if 1st ACK is 0x00, 2nd ACK can be Tx data from bootloader)

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

I also figured out how to do the check the frame validity before spm, and no increase in code size. I changed the frame sequence to data1, data2, FCS, command.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
You seem to be under the false impression I wanted to help with avr-libc.
I'm a quick learner, Ralph. I have not been under that impression since I read your very first post here 4 days ago. I'll refrain from making assumptions about your impressions. Refrain from making them about mine. You're not good at it.

We have departed from the agreed format i.e. discussion of code. I'm no less guilty. Comments concerning your assessment of other members' egos are not relevant to this discussion. You have received feedback on this fact from several members so far in this thread alone, at least one of which did so in a palatably dispassionate fashion. Additional comments of this nature will not further your aims.

May I propose that any discussions outside the scope suggested by the title of your thread be conducted outside of these fora? I have neither a desire for nor an aversion to such a discussion, but I do find the balance of this thread interesting and wish (as I imagine do you) not to see it derailed. Pursuant to this I invite to you PM me regarding subject matter the inappropriateness of which has been clearly communicated to you, but which may nevertheless be of interest to you, and to keep it off of these pages.

I would like to add, with a full understanding of the limits with which it may be received, my appreciation:

* Thanks for suggestions from avrfreaks members and code
* submissions by Joey Morin.

... and a "My pleasure".

-------------------

Quote:
*groan*
Good one, but a long way from being Monty Python material... :-)
Just the usual Turing test. SOP. Jury is still out ;)

-------------------

I was a bit confused about the new RxBit loop:

RxBit:
    ; 6 cycles + delay
    rcall Delay3Cycle
    sbi UART_Port-1, UART_Tx        ; start Tx ACK
    ldi delayArg, RXDELAY           ; delay and clear carry
    sbic UART_Port, UART_Rx
    sec
    ror data
    brcc RxBit
    eor FCS, data
    cbi UART_Port-1, UART_Tx        ; stop Tx ACK
    ; fall into delay for stop bit duration

I had a detailed analysis ready to post, then I double-checked trunk and saw that you caught the error.

I see you also caught the need to set DDRxn, pushing you over 32-words. How's your headache? ;)

RxBit:
    ; 6 cycles + delay
    rcall Delay3Cycle
    cbi UART_Port, UART_Tx          ; start Tx ACK
    ldi delayArg, RXDELAY           ; delay and clear carry
    sbic UART_Port, UART_Rx
    sec
    ror data
    brcc RxBit
    eor FCS, data
    sbi UART_Port, UART_Tx          ; stop Tx ACK
    ; fall into delay for stop bit duration

I wondered why you included the cbi in the loop. Then it hit me:

Quote:
I've changed the protocol to ACK every byte by transmitting 0x80.
Nice trick.

Of course now the loop is no longer 6 cycles, but 7:

    ; 6 cycles + delay

... which will need to be reflected in the RXSTART/RXDELAY macros (yours or mine).

-------------------

On the subject of USI/USART, there are some spm-capable devices which don't have one. The ATtiny13 for example. With 1K of flash this would seem to be a good target for picoboot, but there are other devices as well, like ATtiny48/88.

Although flash read may still be out of reach for 32-words without USI/USART, I'd say picoboot would still be useful on such a device, especially now that FCS is sorted. Conditional assembly could provide for added functionality when USI/USART is available:

#ifdef USIDR
...
#elif (defined UDR) || (defined UDR0) || (defined UDR1)
...
#else
...
#endif

... so only one source file need be maintained.

-------------------

BTW, and you are likely already aware, use of sbi to toggle an output by writing to a PINx register means as is picoboot wouldn't work on some older devices like the ATmega8. Replacements for these older devices like the ATmega88 do support PINx toggling so it isn't a big issue, but it may be worth trapping for it with #ifdef, or at least documenting.

I see that the code doesn't do this any more, but it's something to consider as you continue to make changes. Since there are still 2 BootStart instructions left which could be moved into the second-last page, RMW toggling would be possible via in/eor/out.

-------------------

Quote:
I also figured out how to do the check the frame validity before spm, and no increase in code size. I changed the frame sequence to data1, data2, FCS, command.
I noodled around with changing the frame sequence and having the programmer pre-compute the FCS, but didn't manage any improvement. Your solution is elegant:
    rcall RxByte                    ; read FCS
    rcall RxByte                    ; read SPM command
    cpse FCS, delayArg              ; no error if FCS == 0
Halt:
    rjmp Halt                       ; Halt on FCS error

It took me a few moments to comprehend that the received FCS was not overwritten by the received command. Having the programmer pre-compute the transmitted FCS such that the bootloader's computed FCS is 0 so that you can leverage cpse is clever indeed.

Also impressive is the elimination of the need for a test for command 0 by deferring the movw r0, ZL instruction until after spm. Well done.

-------------------

There is one potential show stopper for some devices. On most modern AVR, the default state after reset of SPH/SPL is RAMEND. However on many (all?) older devices the default state is 0x0000. Notable among these is the ATmega8/L and friends. Mind you I've not used one and must trust the datasheet, and since some datasheets have got this very detail wrong in the past, it's worth considering.

Setting aside for the moment your willingness to support these older devices, let's consider a fix.

A naive fix for this would take 4 words (2 words for devices with <= 256 bytes SRAM, if there are any such broken-SP devices). A more clever fix might take fewer. For example since stack depth never exceeds 4 bytes the register file could be used:

    clr FCS
    ldi tmp, 15
    out SPH, FCS
    out SPL, tmp

Now only 3 words, and since they'd be a part of BootStart they can push back into the second-last page.

I started to examine the possibility of using the default SP == 0x0000 by conducting some tests on an ATtiny85. Although its SP is properly initialised to RAMEND after reset, I wanted to see what would happen when pushing/popping bytes across the SP's 0x0000 'underflow' boundary. The initial results were a little surprising. It seemed as though the SP's 'underflow' behaviour after a push was not matched by its 'overflow' behaviour after a pop. That is, crossing behaviour seemed not to be symmetrical about 0x0000.

I considered digging deeper and then abandoned further testing when I realised that even if it turned out to be symmetrical the approach would never work because the first level push (SP == 0x0000) would clobber r0. With the new deferred mov r0, ZL this would never work.

-------------------

One wrinkle I hadn't thought of with BootStart in the second-last page is version control. If an update to the bootloader changes any of the second-last page, the programmer would need to be able to distinguish between different versions in order to be able to craft a new page with the updated 'VirtualReset' vector. If the bootloader contained flash read capability this could be avoided.

-------------------

EDITS: typos

"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: Sun. Feb 16, 2014 - 05:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Progress. Did some testing on ATtiny84a.
Default blink app works (was slow until I disabled clkdiv8 fuse).
avrdude initialize works. Logic analyzer capture of initialization frame (all zeros) attached.
The RC oscillator is about 2% slow, which looks pretty close to figure 21-53 of the datasheet for ~20C and 3.3V. The bootloader bit timing is about 2% slow as well since I added 2 cycles to the bit loop with the cbi instruction (will correct that in the next build of the bootloader). Despite the ~4.25% timing shift, I'm getting no errors.

Attachment(s): 

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

I see you also caught the need to set DDRxn, pushing you over 32-words. How's your headache? ;)

I can get it back below 32 words if the Tx line has an external pullup resistor. Then I could transmit a 0 by just toggling output mode on the pin.

joeymorin wrote:

I wondered why you included the cbi in the loop. Then it hit me:
Quote:
I've changed the protocol to ACK every byte by transmitting 0x80.
Nice trick.

Of course now the loop is no longer 6 cycles, but 7:

    ; 6 cycles + delay

... which will need to be reflected in the RXSTART/RXDELAY macros (yours or mine).


cbi/sbi actually take 2 cycles - something I didn't notice until recently either. In the latest commit I've gone with 7 for RXDELAY, which gives bit timing within 0.8% of 230.4kbps @8Mhz (35 vs. 34.722 cycles per bit). As you can see, I still haven't put the macros in, but with the way you wrote them it'll be simple to handle the timing change.

joeymorin wrote:

On the subject of USI/USART, there are some spm-capable devices which don't have one. The ATtiny13 for example. With 1K of flash this would seem to be a good target for picoboot, but there are other devices as well, like ATtiny48/88.

I've got 25 ATtiny88-au sitting in a box still in the sealed anti-static bag that I'll be testing out. At 60c (CAD), I think they're the best bang for the buck of any AVR. Although they don't have USI or USART, they have hardware SPI, which I could use for a UART in the same way as USI. In fact it's easier since it supports LSB first while USI is MSB first only. Meaning if I support USI I'll have to change the protocol to send bit-reversed data.
joeymorin wrote:

BTW, and you are likely already aware, use of sbi to toggle an output by writing to a PINx register means as is picoboot wouldn't work on some older devices like the ATmega8.

Yeah, I almost bought some ATmega8A's since they're really cheap (~$7/10 from China). When I found out they don't support PINx, I changed my mind.

I'm not going to support any AVR's I can't test with, so picoboot is unlikely to support more than the four types I've mentioned before. I don't plan to support legacy/end-of-life parts.

joeymorin wrote:

One wrinkle I hadn't thought of with BootStart in the second-last page is version control. If an update to the bootloader changes any of the second-last page, the programmer would need to be able to distinguish between different versions in order to be able to craft a new page with the updated 'VirtualReset' vector.

I see it as an easy way to update the booloader. BootStart could be overwritten with a backwards jump to new code.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
cbi/sbi actually take 2 cycles
Oops. Knew that. Here's me, just counting instructions...:?

Quote:
they have hardware SPI, which I could use for a UART in the same way as USI.
I've never played with the t48/88. Does its hardware SPI suffer from the same '9th bit' problem as do other AVR? If so, it will be challenging (though I expect not impossible) to work around. One approach would be to bit-bang the start bit, but this will likely require disabling SPI between each byte... and this is only when using SPI as a master.

How do you envision using it as a slave for receiving? Receive is triggered by SS, and the shift register is driven by SCK. While SS could be kept low permanently, how would you arrange for asynchronous driving of SCK? I'm not saying it can't be done, but a few minutes spent thinking about it didn't present me with an obvious solution, at least not one which would consume fewer words than a software UART and not require additional hardware.

Quote:
I see it as an easy way to update the booloader. BootStart could be overwritten with a backwards jump to new code.
Do you propose updating the bootloader by first uploading a 'transitional' bootloader in application flash, then using it to upload a new bootloader? Nice.

However, the scenario I was referring to:
- picoboot-v1 places some or all of BootStart in page N-1 with VirtualReset
- picoboot-v1 installed on device
- programmer's config file includes picoboot-v1's page N-1 code
- during bootload, programmer merges new app's VirtualReset with picoboot-v1's page N-1 code and writes new page N-1

Then later:
- picoboot-v2 released, page N-1 code differs from that of picoboot-v1
- picoboot-v2 installed on device
- programmer's config file not updated with picoboot-v2's page N-1 code
- user uploads new app code, during which programmer merges new app's VirtualReset with old picoboot-v1's page N-1 code and writes new page N-1

The bootloader now has picoboot-v2 code in page N, but picoboot-v1 code in page N-1. If the BootStart code responsible for deciding to bootload or jump to app lies completely within page N-1, there would be no problem for a normal reset. BootStart would jump to the app.

However if a bootload is requested the v1 BootStart code in page N-1 will now proceed to the v2 CommandLoop in page N, possibly causing a disaster.

Worse is if BootStart spans page N-1 and page N, in which case every reset will run a mashup of v1 and v2 BootStart code, also possibly causing a disaster.

Unless the programmer can determine what version of picoboot it is talking to, it has no way of knowing which page N-1 code to merge with the new app's VirtualReset. The user would need to ensure that the programmer version matches the bootloader version.

If flash read is available, the programmer could read the whole bootloader and determine what version is installed. Alternatively the programmer could always update the bootloader before uploading new app code, but then a newer bootloader would be downgraded when used with an older programmer.

JJ

"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'm replying in multiple posts, since whenever I try to do it in one big post I get "bad request" errors.

joeymorin wrote:

Quote:
they have hardware SPI, which I could use for a UART in the same way as USI.
I've never played with the t48/88. Does its hardware SPI suffer from the same '9th bit' problem as do other AVR?

I'm hoping so, since it will mean I don't have to output a stop bit. My thought is to run it in master mode, and only send in response to an incoming byte (similar to what I do for the ACK now). Once I detect a start bit, I'll wait half a bit-time before setting the tx pin low. Then I'll wait a full bit time before writing the outgoing data to SPDR.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

Quote:
they have hardware SPI, which I could use for a UART in the same way as USI.
I've never played with the t48/88. Does its hardware SPI suffer from the same 9th bit problem as do other AVR?

I'm hoping so, since it will mean I don't have to output a stop bit. My thought is to run it in master mode, and only send in response to an incoming byte (similar to what I do for the ACK now). Once I detect a start bit, I'll wait half a bit-time before setting the tx pin low. Then I'll wait a full bit time before writing the outgoing data to SPDR.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

joeymorin wrote:

Unless the programmer can determine what version of picoboot it is talking to, it has no way of knowing which page N-1 code to merge with the new app's VirtualReset.

That's one of the reasons I added the ack on every byte. If I change cbi in RxBit to:
sbi UART_Port-2, UART_Tx ; toggle Tx
Then the ACK byte will be 0xd5 instead of 0xc0 (I forgot to count the start bit when I thought it would be 0x80). As an added bonus, after 8 toggles Tx will be back in the idle state, and I won't need the sbi instruction after the Rx loop.

If the bootloader is updated but used with an old version of the programmer, then the programmer will throw an error on initialization.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

I tried posting the picoboot_send_frame function from picoboot.c that I'm adding to avrdude, but something in it is causing the web server to barf. Probably something to do with needing escapes for the quotes or something. I'm planning to add the avrdude patches to the picoboot repository, so it will have to wait until it's posted.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

ralphd wrote:
the ACK byte will be 0xd5 instead of 0xc0
Neat. Have you charted how many unique ack bytes you can get with a similar approach without incurring additional word costs?

---------------

ralphd wrote:
I tried posting the picoboot_send_frame function from picoboot.c that I'm adding to avrdude, but something in it is causing the web server to barf. Probably something to do with needing escapes for the quotes or something. I'm planning to add the avrdude patches to the picoboot repository, so it will have to wait until it's posted.
Got any printf() in there? The forum software barfs on posts with the percent sign when it is followed by an alphanumeric character.

The fix is to replace those (or simply all) instances of % with %

I use a macro in my text editor (in which I compose my posts anyway) to do a global conversion before I copy/paste into the browser.

Johan banged together a greasemonkey script to do this automatically.

"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: Mon. Feb 17, 2014 - 05:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
The fix is to replace those (or simply all) instances of % with %
That didn't work. :wink:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

joeymorin wrote:
ralphd wrote:
the ACK byte will be 0xd5 instead of 0xc0
Neat. Have you charted how many unique ack bytes you can get with a similar approach without incurring additional word costs?

No, but off the top of my head I'd say only a few. With an extra instruction or two I could probably mirror the incoming data.

joeymorin wrote:

ralphd wrote:
I tried posting the picoboot_send_frame function from picoboot.c that I'm adding to avrdude, but something in it is causing the web server to barf. Probably something to do with needing escapes for the quotes or something. I'm planning to add the avrdude patches to the picoboot repository, so it will have to wait until it's posted.
Got any printf() in there?

Yup. I guess that was the problem. Not really worth the trouble to setup the greasemonkey script though...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

larryvc wrote:
joeymorin wrote:
The fix is to replace those (or simply all) instances of % with %
That didn't work. :wink:
Hmmm... strange.

Let me try that line again...

The fix is to replace those (or simply all) instances of % with %

Seems to work now... don't know what happened. I did the old double-escape trick &#37; and it worked in preview... seems it didn't take after the submit.

...And while noodling back and forth with preview on this post I notice that the escaped sequence gets 'dereferened' when backing up and previewing again... very strange...

... Must be the same gremlin that ate your smilie ;)

Anyway I'll fix the post.

EDIT: Hmmm, now I can't reproduce the problem. I guess I wasn't backing up and previewing (my usual habit) but nesting the second preview. Rats.

"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

Quote:

seems it didn't take after the submit.

Did you [Edit]? You have to fix the %'s again after each edit.

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

Hey RalphD... does your sw uart run at a multiple of the bit rate and take more than one sample per bittime? If yes, what is the multiple? (I'm guessing <16)

Imagecraft compiler user

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

bobgardner wrote:
Hey RalphD... does your sw uart run at a multiple of the bit rate and take more than one sample per bittime? If yes, what is the multiple? (I'm guessing <16)

No, it takes 1 sample as close as possible to the middle of the bit. Taking multiple samples would take up a lot more than the 14 instructions the sw uart (receive portion) takes. Plus, taking multiple samples doesn't buy you anything with a reasonably clean TTL signal. I can see the benefit for old RS-232 communications with +-15V swings on long cables, but for 3.3 or 5v TTL between a serial adapter and the AVR which are often less than a few inches long, the signals are quite clean.

Modern TTL serial devices also have much higher input impedances than the old RS232 devices. One shortcut I tried to do in picoboot was to drive the tx side with the AVR pullup resistor. It was no problem to drive the line hi, but leakage current on the AVR and the USB-TTL chip on the other side is so low that with the pullup turned off, the voltage stays above the 0 level.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

clawson wrote:
Did you [Edit]? You have to fix the %'s again after each edit.
I didn't think I did, but perhaps so.

What's with the new avatar? Ok, I know you've used it (or something like it) briefly in the past... but did you all have a meeting and declare 14/02 International AVR Freaks Change-your-avatar month? You, Larry, Smiley...

-----------------

ralphd wrote:
It was no problem to drive the line hi, but leakage current on the AVR and the USB-TTL chip on the other side is so low that with the pullup turned off, the voltage stays above the 0 level.
A high-value (e.g. 1M) pull-down should fix that. I wonder what value would be too high and would result in too slow a falling edge slew rate at your chosen bps...

"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

joeymorin wrote:
What's with the new avatar? Ok, I know you've used it (or something like it) briefly in the past... but did you all have a meeting and declare 14/02 International AVR Freaks Change-your-avatar month? You, Larry, Smiley...
Did you miss the Reading K&R thread?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

larryvc wrote:
Did you miss the Reading K&R thread?
Yes, until a few moments ago. Came back here to say Eureka ;)

I should have picked up on the wings theme...

"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

Quote:

What's with the new avatar? Ok, I know you've used it (or something like it) briefly in the past... but did you all have a meeting and declare 14/02 International AVR Freaks Change-your-avatar month?

Well the current one is just a bit of a "trial run" (i actually used Android tools on my tablet to crop/resize/etc), plus, after having the idea for "aviation avatar March" I was too impatient to wait ;-)

PS thanks for the PM's - I think I might hold some "items" in reserve until we reach March ;-)

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

Success!

avrdude -c picoboot -p t88 -P com16 -U flash:w:../blink_led-t88.hex
drain>

The blink app runs fine after disconnecting Rx and resetting. Reconnecting the Rx and resetting again runs the bootloader.
I still have to add the avrdude patches to the svn repository. I should have that done, along with an avrdude binary and a couple pre-built hex files done later this eve. Then I'll post for alpha-testers!

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Groovey.

"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]