Xmega CRC engine???

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

I've tried several times now to get the CRC peripheral to work, and haven't gotten anything besides all zeros. FWIW I don't use ASF at all, but afaict I've replicated exactly what it does and still get nothing:

CRC.CTRL = CRC_RESET_RESET0_gc | CRC_SOURCE_IO_gc;

CRC.DATAIN = 0xde; // send data
CRC.DATAIN = 0xad; // send data
CRC.DATAIN = 0xbe; // send data
CRC.DATAIN = 0xef; // send data

CRC.STATUS |= CRC_BUSY_bm; // finish
loop_until_bit_is_clear(CRC.STATUS,CRC_BUSY_bp); // wait for done

// ...printf CHECKSUM3:0

It seems like a pretty simple peripheral, but I've got nothing.

a) does it actually work?
b) is the ASF driver doing anything else I'm missing?

At the moment I'm working with an 128a3u rev G but have used the 192a3u rev G with similar results. Selecting CRC32 and adding excessive delays does nothing either.

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

Yes it works.

When finished stuffing data in, I clear the busy bit. Then I read the checksum.

I think the busy bit will clear itself when using other modes, but when using the IO thing as you and I do, you must clear it to tell the thing you are done feeding it data. As always, I could be wrong. It has never happened yet though. ;)

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

I guess I was right again. ;)
You write a one to the busy bit to clear it.
.

Attachment(s): 

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

steve17 wrote:
I guess I was right again. ;)
You write a one to the busy bit to clear it.
.

Right, so the code I posted should work perfectly, but it's not...

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

I seem to be doing what you do, except I use my own symbols.

I'm using the A4U chips.

I don't wait for the busy to clear. I just assume I cleared it. It seems like your wait ougnt to work.

I then fetch the CHECKSUM0_CHECKSUM1 pair as a 16 bit word.

I'm not sure what you fetch.

Otherwise all I can think of is the chip is bad or the symbols in the iox....h file are bad.

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

Try setting the reset bit and the source bit separately in case the reset bit clears the source bit as well.

Works for me on a 128A3U.

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

mojo-chan wrote:
Try setting the reset bit and the source bit separately in case the reset bit clears the source bit as well.

That seems to have done it, thanks! I consider that a bug in the datasheet then. It says "the CRC registers will be reset after 1 clock cycle", but resetting the *entire* module's registers to zero is not even remotely what that implies, given the effective definition of "reset" used in other peripherals... It should very clearly state that it resets every register *including* itself.

Now to figure out how to replicate the the CRC elsewhere (host-side, Python), since even though it claims to be polynomial 0x8408 with an 0xffff start (RESET1), the avr-libc _crc_ccitt_update() does not seem to produce the same thing...

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

omegahacker wrote:
That seems to have done it, thanks! I consider that a bug in the datasheet then. It says "the CRC registers will be reset after 1 clock cycle", but resetting the *entire* module's registers to zero is not even remotely what that implies, given the effective definition of "reset" used in other peripherals... It should very clearly state that it resets every register *including* itself.

No, that is exactly how I would interpret it. If you look at the functionality of the reset bits in other peripherals they all reset every register, including sub-channels and the like.

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

This baffled me for a while too.
The fix is to set the CTRL registers in two steps or have a nop() in between.

CRC.CTRL = CRC_RESET_RESET0_gc;
CRC.CTRL |= CRC_SOURCE_IO_gc;

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

Hello

I've done it as you said but failed !

 

Did i have any mistake?

void CRC_check_Rest(void){
CRC.CTRL  = CRC_RESET1_bm|CRC_RESET0_bm;
         CRC.CTRL  |= CRC_SOURCE0_bm;
}
void CRC_ENG(unsigned char b){
    CRC.DATAIN=b;
      CRC.STATUS|=CRC_BUSY_bm;
}
unsigned int CRC_check(unsigned char frame_index , unsigned char Modbus_frame[])
{
CRC_check_Rest();
for(i=0; i<=frame_index; i++)
        {
                CRC_ENG(Modbus_frame[i]);

        }
        CRC = ((U16 )CRC.CHECKSUM0)&0x00ff;
        CRC|= ((U16 )CRC.CHECKSUM1)<<8;

        return CRC
}        

Best Regards.

 

Last Edited: Mon. Aug 1, 2016 - 05:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This works:

 

	CRC.CTRL = CRC_RESET_RESET1_gc;
	CRC.CTRL = CRC_SOURCE_IO_gc;

	for (i = 0; i < length_bytes; i++)
		CRC.DATAIN = *ptr++;

	CRC.CTRL = 0;	// disable CRC module for a tiny amount of power saving
	return ((uint16_t)CRC.CHECKSUM0 | ((uint16_t)CRC.CHECKSUM1 << 8));

 

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

mojo-chan wrote:

This works:

 

	CRC.CTRL = CRC_RESET_RESET1_gc;
	CRC.CTRL = CRC_SOURCE_IO_gc;

	for (i = 0; i < length_bytes; i++)
		CRC.DATAIN = *ptr++;

	CRC.CTRL = 0;	// disable CRC module for a tiny amount of power saving
	return ((uint16_t)CRC.CHECKSUM0 | ((uint16_t)CRC.CHECKSUM1 << 8));

 

Thank you mojo

after a day stocking in CRC engine i realized that  there is no just one CRC_16!

I want to use it in modbus RTU .

But CRC engine generate CRC_CCITT.

and they are different.

so unfortunately we can't use CRC engine for modbus.

 

 

 

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

Hi all!

 

Maybe this is a bit off-topic as it's not a source of problems here but in other cases it could be. I saw this twice:

CRC.STATUS |= CRC_BUSY_bm;

This is not the right way of clearing this bit. To clear one have only to write 1 to that flag bit and 0s to others so the right way is

CRC.STATUS = CRC_BUSY_bm;

 

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

tyg wrote:

Hi all!

 

Maybe this is a bit off-topic as it's not a source of problems here but in other cases it could be. I saw this twice:

CRC.STATUS |= CRC_BUSY_bm;

This is not the right way of clearing this bit. To clear one have only to write 1 to that flag bit and 0s to others so the right way is

CRC.STATUS = CRC_BUSY_bm;

 

You are right .thanks for sharing .