Adding Delay to Optiboot for RS-485 support

Hi everyone, I'm hoping you can help me with this little problem...

I've patched optiboot.c to control the DE line for an RS-485 driver when sending data, in hopes that I could get to programming my device over RS-485 (it's a custom board, and I'd prefer to not have to fiddle around and switch all sorts of stuff to program vs. interact with it - the RS-485 driver's output are properly hooked up to standard TX/RX, and communication works fine over RS-485, and TTL serial works fine when I disable the driver via a hardware jumper).

In a quest to perform this activity, I've added the following to optiboot.c's putch() function:

void putch(char ch) {
#ifndef SOFT_UART

  PORTD |= _BV(PORTD5);
  PORTB |= _BV(PORTB5);
  
  while (!(UCSR0A & _BV(UDRE0)));
  UDR0 = ch;
  
   PORTD &= ~_BV(PORTD5);
   PORTB &= ~_BV(PORTB5);

Digital 5 is the DE pin, and digital 13 is just there for debug purposes. I've also included the requisite DDR.. instructions up in main():

  DDRD |= _BV(PORTD5);
  DDRB |= _BV(PORTB5);

... and clocked it back to 9600 for uploading*, as speed isn't as important as simply being able to use the RS-485 interface, added a boards definition, and so forth.

    • this required adding a define to get around the SOFT_UART automatic definition, which triggered all sorts of errors compiling.

All this is fine and dandy, got it up to the board, etc. and then got the inevitable timeouts during sketch upload (replicating process that would've happened using the TTL interface successfully when defined as a duemilanove w/ atmega328p.).

As a consequence, I didn't see my pin13 light up during the process - and I know I've had issues with time to clear out bits from the RS-485 driver when switching the DE pin state, so I thought I'd add a delay, which is where I hit the real roadblock:

#include <util/delay.h>

...


void putch(char ch) {
#ifndef SOFT_UART

  PORTD |= _BV(PORTD5);
  PORTB |= _BV(PORTB5);
  
  _delay_ms(1);

This triggers an error during hex upload:

avrdude: input file optiboot_nanoMoCo.hex auto detected as Intel Hex
avrdude: ERROR: address 0x8008 out of range at line 33 of optiboot_nanoMoCo.hex
avrdude: write to file 'optiboot_nanoMoCo.hex' failed

Any thoughts on the best way to add a delay here for testing purposes? Or, perhaps, any recommendations towards the overall goal? (Programming over RS-485 interface.)

Thanks!

!c

d'oh - I should do more testing before posting, it seems. =) My problem is not here, but somewhere else. Setting LED_START_FLASHES=3 and LED_DATA_FLASH results in pin13 not flashing, so I think there's a bigger problem somewhere else. I'll post back if I find anything.

!c

Sorry for putting the old topic top here, but did you find a solution?
I'm looking for a bootloader to program Arduino via RS485 and it seems to be that you're the only one who might get it worked until now if google didn't lie to me...

Sorry for not responding sooner...

avrdude: ERROR: address 0x8008 out of range at line 33 of optiboot_nanoMoCo.hex

I think that this means that your bootloader got too big; it has code at 8008, and only 8000 bytes of flash.

Optiboot is currently 504 bytes out of a max size of 512 bytes; you can't just add a bunch of code to it and have things still work! (well, if you changed fuses for a 1K bootloader, you'd have a lot of breathing room...)

Is this problem solved? I also encountered similar problems. 0X8010 error of out of range.

if you change the code, it's your responsibility to either make sure that the binary stays small enough (less than 510 bytes, as reported by the compile phase), or modify the makefile/burn procedures to allow for a larger bootloader.

There were a number of cases where compiler changes caused the same source to expand when compiled with other versions of the compiler; the code is designed to compile with the 4.3.2 compiler that is distributed with the Arduino IDE, and various linux distributions use other versions. See Google Code Archive - Long-term storage for Google Code Project Hosting. for example.

To westfw:
Thanks for your reply.
I very interested in this nanoMoco projecthttp://www.openmoco.org/nanoMoCo, The Motion Enginehttp://dynamicperception.com/software/motion-engine is a firmware for the nanoMoCo boards.
Around it, I will constantly try.But I tried more than a week, still unable to solve the wrong problem.When I used gcc 4.3.2 for Arduino.According to the introduction , run " make 0S=macosx ENV=arduino" in the terminal window (MAC lion 10. 8 ),then Successfully compile this file "optiboot_atmega328.hex", But when I buruing bootloader by Arduino 1.0.1 rc1, I got an out of range error message:
"ardude: ERROR: address 0x8010 out of range at line 33 of /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex".
I was an arduino fans, but I'm a beginner on bootlader. How to properly compile the nanoMoco's bootloader in order to be able to conduct some tests. I put this project file attachment to you,Thank you!

nanoMoco-bootloader-file.zip (30.3 KB)

May I suggest a different solution: hook up the rs485 via 1k resistors in series for the rx/tx and then attach a FTDI Header without said resistors. That way, the FTDI header based signals always take precedence.

Similarly, if the idea is to program via rs485, I suggest also having a way to engage the reset pin. That means setting aside another channel /chip etc. but at least the receiving chip can be the RX-only kind, which are much smaller than the so8's usually associated with full rs485 transceivers.

Lastly, you should go with a full duplex setup for rx/tx programming via rs485, that way you don't have to fiddle with the de pin. More wires but relatively simple to do. My recommendation: use rj45 connectors and cat 5 wires. Two sets of pairs to rx/tx, one pair for reset, the last pair for whatever else you may need (power?)

To Constantin:
I can basically understand your proposal.However, The nanoMoco project is built on the basis of the RS485 communication, Please visit http://www.openmoco.org/nanoMoCo about naoMoCo content.I may not be able to give up the RS485 alone to complete a single interface and control program.At least for now it is not possible. For me, a modified version of the "optiboot bootloader" can not be burned into the chip, it always be a problem.
Faced with the difficulty, I will work hard to solve it.Because when the problem can be solved, I think I can really learn something. Right?

I very interested in this nanoMoco projecthttp://www.openmoco.org/nanoMoCo, The Motion Enginehttp://dynamicperception.com/software/motion-engine is a firmware for the nanoMoCo boards.

So, are you using the nanoMoCo bootloader, or are you modifying your own, or something else? I was able to compile the nanoMoCo bootloader, and it looks like it should fit ok, though I didn't try to actually program it into a chip.

"ardude: ERROR: address 0x8010 out of range at line 33 of /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex".

Shouldn't it be trying to load "optiboot_nanoMoCo.hex" ? That's what the makefile builds for the nanoMoCo target. If I tell it to build an atmega328, the binary is indeed too big:

BillW-MacOSX-2<10050> make nanoMoCo
avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega328p -DF_CPU=16000000L  '-DFORCE_HARD_UART' '-DBAUD_RATE=115200'   -c -o optiboot.o optiboot.c
optiboot.c:229: warning: 'flash_led' declared 'static' but never defined
avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega328p -DF_CPU=16000000L  '-DFORCE_HARD_UART' '-DBAUD_RATE=115200' -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib -o optiboot_nanoMoCo.elf optiboot.o 
avr-size optiboot_nanoMoCo.elf
   text    data     bss     dec     hex filename
 [color=brown]   504       0       0     504     1f8 optiboot_nanoMoCo.elf[/color]
avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_nanoMoCo.elf optiboot_nanoMoCo.hex
avr-objdump -h -S optiboot_nanoMoCo.elf > optiboot_nanoMoCo.lst
rm optiboot.o optiboot_nanoMoCo.elf
BillW-MacOSX-2<10051> make atmega328
avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega328p -DF_CPU=16000000L  '-DLED_DATA_FLASH' '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'   -c -o optiboot.o optiboot.c
avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega328p -DF_CPU=16000000L  '-DLED_DATA_FLASH' '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib -o optiboot_atmega328.elf optiboot.o 
avr-size optiboot_atmega328.elf
   text    data     bss     dec     hex filename
[color=brown]    544       0       0     544     220 optiboot_atmega328.elf[/color]
avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_atmega328.elf optiboot_atmega328.hex
avr-objdump -h -S optiboot_atmega328.elf > optiboot_atmega328.lst
rm optiboot.o optiboot_atmega328.elf
BillW-MacOSX-2<10052>

In this matter, I have two errors. One is : Not seriously check the makefile. Two is: Too believe the readmet.txt.
Extremely thank you, thank you. I have successfully burn bootloader into chip.
Thanks!
All the best!

Sorry, just saw this...

Yes, I didn't change anything in the original README.txt, IIRC.

I should really clean up the bootloader part of the source tree - I don't like it being so out of sync with the core optiboot, but at the same time, I expected it to be extremely rare that anyone actually tried to build and upload the booloader. (We pre-program them with the bootloader.)

Yes, you use make nanoMoCo, or make nanoMoCo_isp

I do realize there are probably easier ways than having to power cycle the board to update the firmware, but we were shooting for a form factor first and foremost, so things like dual interfaces for programming/etc. kinda fell by the wayside.

!c