Mega2560 .hex question

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

Hello All.  I just got my Mega2560 card and thought a particular function would be in a library already. Maybe I am missing it!

 

I would like to be able to send data back to the PC over serial port in Intel Hex record format.  The Arduino obviously has this built in to send things to the 2560 board.  I need to read out some pretty exotic and ancient ROMS and would like the output to the PC to have some form of checksum.  The .hex format would be great as it is supported by everything.

 

Feel free to call me a noob, but please point me down the right road if you can!

 

Joe

 

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

The Arduino obviously has this built in to send things to the 2560 board.

Guess again. Arduino simply uses avrdude.exe to read .hex and then send on to the Arduino bootloader and in turn avrdude.exe is built against libbfd.

 

I don't think you are going to fit a copy of libbfd into an AVR (not even a 256K one).

 

Is there some reason the AVR cannot just send binary and then have a bin2hex (probably based on libbfd in fact) run on the receiving PC?

 

Libbfd: https://www.cs.utah.edu/dept/old...

 

I guess you could put a simple Intel Hex encoder into an AVR (all you are doing is converting bytes to hex - you could do that with itoa(,,16)) but all Intel Hex really contains is the data and location info. If you arrange to send a base address, length and then a block of N bytes you might as well just send binary then spawn(bin2hex) at the PC.

 

PS I just googled for "c code to generate intel hex" the top hit was this:

 

https://www.pjrc.com/tech/8051/i...

 

The hexout() in that is pretty much all you need.

void hexout(fhex, byte, memory_location, end)
FILE *fhex;  /* the file to put intel hex into */
int byte, memory_location, end;
{
	static int byte_buffer[MAXHEXLINE];
	static int last_mem, buffer_pos, buffer_addr;
	static int writing_in_progress=0;
	register int i, sum;

	if (!writing_in_progress) {
		/* initial condition setup */
		last_mem = memory_location-1;
		buffer_pos = 0;
		buffer_addr = memory_location;
		writing_in_progress = 1;
		}

	if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \
	 || ((end) && (buffer_pos > 0)) ) {
		/* it's time to dump the buffer to a line in the file */
		fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr);
		sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255);
		for (i=0; i < buffer_pos; i++) {
			fprintf(fhex, "%02X", byte_buffer[i]&255);
			sum += byte_buffer[i]&255;
		}
		fprintf(fhex, "%02X\n", (-sum)&255);
		buffer_addr = memory_location;
		buffer_pos = 0;
	}

	if (end) {
		fprintf(fhex, ":00000001FF\n");  /* end of file marker */
		fclose(fhex);
		writing_in_progress = 0;
	}
		
	last_mem = memory_location;
	byte_buffer[buffer_pos] = byte & 255;
	buffer_pos++;
}

Wow, pre-ANSI C, thus proving that nothing in this world is ever new!

Last Edited: Wed. Sep 24, 2014 - 01:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

The Arduino obviously has this built in to send things to the 2560 board.

Guess again. Arduino simply uses avrdude.exe to read .hex and then send on to the Arduino bootloader and in turn avrdude.exe is built against libbfd.

 

PS I just googled for "c code to generate intel hex" the top hit was this:

 

https://www.pjrc.com/tech/8051/ihex.c

 

Wow, pre-ANSI C, thus proving that nothing in this world is ever new!

 

Yea, I spotted that also. I do appreciate the pointer though. I was hoping to see a 'sketch' version of that. I'll have to figure out the string functions and other bits from the SDK, which I would be doing anyway if I didn't want to be lazy.. should be easy as I'm used to writing pre-ansi C anyways *Amiga C compiler* :).

I'm trying to get data from some old ROMS that are > 64K, thus I need the extra record types for extending the address range.  I have sent binary before, but i prefer ASCII as then I can use some pretty lax terminal settings to capture data without loss. I really want a checksum though just to be safe.

 

I guess an arduino is just the atmel chip with a bootloader already programmed so the end user does not need JTAG or ICP to get started? A nice idea when most kids nowadays would use a soldering iron to light a joint instead of soldering one.

 

Joe

Last Edited: Wed. Sep 24, 2014 - 04:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was hoping to see a 'sketch' version of that.

Eh? A "sketch" is C. That is C. What is the difference?

 

As to making it ANSI C. That's just to do with the routine interface. Also FILE and fprintf() make no sense on an AVR (there's no file system) so I'd suggest you send the output to a buffer instead. With that in mind:

void hexout(char * buff, int byte, int memory_location, int end)
{
	static int byte_buffer[MAXHEXLINE];
	static int last_mem, buffer_pos, buffer_addr;
	static int writing_in_progress=0;
	register int i, sum;

	if (!writing_in_progress) {
		/* initial condition setup */
		last_mem = memory_location-1;
		buffer_pos = 0;
		buffer_addr = memory_location;
		writing_in_progress = 1;
		}

	if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \
	 || ((end) && (buffer_pos > 0)) ) {
		/* it's time to dump the buffer to a line in the file */
		sprintf(buff, ":%02X%04X00", buffer_pos, buffer_addr);
		sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255);
		for (i=0; i < buffer_pos; i++) {
			sprintf(buff, "%02X", byte_buffer[i]&255);
			sum += byte_buffer[i]&255;
		}
		sprintf(buff, "%02X\n", (-sum)&255);
		buffer_addr = memory_location;
		buffer_pos = 0;
	}

	if (end) {
		sprintf(fhex, ":00000001FF\n");  /* end of file marker */
		writing_in_progress = 0;
	}
		
	last_mem = memory_location;
	byte_buffer[buffer_pos] = byte & 255;
	buffer_pos++;
}

However that could require a big buff[] passed to it so I think I'd just strip out the core and do a line at a time.

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

Thanks for the snippet.  I had worked it out last night to send 16 bytes at a time and basically let the terminal program on the PC be the 'filesystem'.  I meant that a 'sketch' is not C in that there is no main(). I am sure the compiler just has a standard main() and calls setup() and loop() after its own initialization.

 

I've decided I want to just write sketches for each type of chip I might want to copy, and figure out how to use avrdude to send them directly to the mega2560 from a PC with a tiny GUI program.  Is there a way to start the code immediately without having to hit the reset switch? It seems the normal IDE that comes with the mega from aurdino site does it, but sending same file from avrdude does not.  (I am probably missing something easy again, sigh).

 

Thanks