error in passing arg

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

Hi All,

I have a problem that I can't figure out. I am passing an unsigned int to a crc check routine that I have written (yes I'm aware there is a gnu function). But for some reason, this code generates an error in the passing of the argument. This can be seen in AVR Studio 4.12..

I have attached the code incase anyone else can see what's going on from the assembler. It doesn't seem to make sense to me!

Here is the code that doesn't work:

Code in main.c ...


 #include 
 #include 
 #include 
 #include  

 #include "crc.h"

unsigned char buffer_debug[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 11 };

unsigned int result;

int main( void )
{
	/* Comms is now setup, and we can send the initialising command
	for the bootloader */
	result = crc_ccit_check( buffer_debug );
	
	while(1){}
	/* return an exit code */
	return(0x0001);
 }

and the code in crc.c

#include 
#include 
#include 

unsigned int	crc	= 0x0000;
 
const unsigned int  crc_ccit_div	= 0x1021; 



unsigned int crc_ccit_update( unsigned int c, unsigned char dt )
{
	/* setup the bit counter */
	unsigned char bit_count = 8;
	
	/* xor the crc with the data (shifted to the high byte */
	c = c ^ ((unsigned int)( dt << 8 ));
	
	/* loop for 8 bits */
	while( bit_count != 0 )
	{
		
		if( c & 0x8000 )
			c = ( c << 1 ) ^ crc_ccit_div;
		else
			c <<= 1;
		
		/* move to the next bit */
		bit_count--;		
	}
	
	/* return the crc value */
	return(c);
} 

 
 
 
 /* Cyclic Redundancy Check */
unsigned char crc_ccit_check( unsigned char *buf )
{
 /* start a btye counter */
 unsigned int i;
 unsigned int tmp_crc;
 unsigned char tmp_char;
	
	for( i=0; i<10; i++)
	{
		tmp_char = *buf;
		
		/* Start from the end and work backwards!!*/
		tmp_crc = crc_ccit_update( crc, tmp_char );
		
		crc = tmp_crc;
		
		buf++;
	}

	if( crc ==  *(buf+(SPM_PAGESIZE/2) ) ) return( 0x01 );
	else return( 0x00 );
}

Now, when I simulate this, as soon as the code enters crc_ccit_update, the argument c is passed as 1, not 0 as it should be. In assembler, the code seems to fetch R22 into R18, crc appears to be R18:19 so it messes up the argument...

hmm, after writing this I have a thought that it may be because I am manipulating c and returning it, rather than defining another local. I will check that now.

I'm sure it's something I'm doing and I can't see the wood for the tree's, but I can't figure it out! Has anyone else got some clues?

This is compiled for an ATMEGA128.

BTW, In the bulletin board, when you attach a file and then preview the post, the attachment information is not kept.

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

I just built this and ran in the simulator and as expected, on entry to crc_ccit_update the value in c is 1

Why would you expect it to be otherwise? - it's the first character from your buffer_debug[] array. It's working exactly as written.

Cliff

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

Hi Cliff,

buffer_debug is passed to arg dt. crc is passed to arg c and is initialiased as 0, and this is what is passed to argument c. dt is always correct.

Well, this can be fixed by :


unsigned int crc_ccit_update( unsigned int c, unsigned char dt )
{
	/* setup the bit counter */
	unsigned char bit_count = 8;
	unsigned int  rt;
	
	/* xor the crc with the data (shifted to the high byte */
	rt = c ^ ((unsigned int)( dt << 8 ));
	
	/* loop for 8 bits */
	while( bit_count != 0 )
	{
		
		if( rt & 0x8000 )
			rt = ( rt << 1 ) ^ crc_ccit_div;
		else
			rt <<= 1;
		
		/* move to the next bit */
		bit_count--;		
	}
	
	/* return the crc value */
	return(rt);
}

Interestingly, rt is initialised to the previous values that I was getting for arg c. Of course, this doesn't matter as it's immediately given a value that it needs from the first equation, and now c is correct.

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

Oh right, I see what you mean now. Sorry for my misunderstanding.

Working through it, it looks like a fault in Studio as when you hover the cursor over 'c' the pop-up says it's being held in R19:R18 and the value is 1 but at that stage 'c' is still in the R25:R24 that was passed into the routine and R91:R18 are actually being used to hold 'dt' which is being shifted right 8 times.

So maybe this is a Studio fault or is Studio's knowledge of where variables are being held encoded in the .elf in which case it may be a problem in the GCC tools.

Or maybe this is just beyond the scope for Studio to show. The fact is that within the following code generated from that line the shifted 'dt' in R19:R18 is XORd with the 'c' value in R25:R24 but then the "result" is finally in R19:R18

So I think the confusion arises because in the same single line of C a register pair is eventually used for two different things.

Cliff

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

Hi Cliff,

Thanks for your insights, it's helped a lot!

I think the wood for the trees is correct in this case, as your quite right in that it seems AVR Studio is not showing the values due to how the code is optimised.

The result of either the first or the second code is the same!! That'll teach me to get hooked upon one small issue rather than checking the result of the complete routine!

Thanks a lot, I will bear this in mind in future.

Best Regards,

Brian.