Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Really simple bitshift not working on AVR32

Status
Not open for further replies.

sebmaster

Member level 1
Member level 1
Joined
Mar 9, 2008
Messages
38
Helped
2
Reputation
4
Reaction score
0
Trophy points
1,286
Visit site
Activity points
1,719
Hello,

I have an AVR32 which needs to send 21 bit words (miniumum) to a CPLD.

I intend to use the SPI bus for this and have managed to set it all up, with a word size of 11 bit.

The idea is I take an integer, take the top 11 bits, shift it left 11 places, take the top 11 bits again, then send the two values in the reverse order I got them (the SPI sends data LSB first).

However my program is not working and I can't figure out why not, looking at the SPI output on a scope the LSBs (the first 21 bits sent) are always zero.

My test value is 0xFFFFFFFF so I should have to do a 16 bit shift before the value of the lower word starts dropping below its maximum surely?

Here is my code:
Code:
	spi_status_t 	response;
	unsigned short 	word_high = (data & 0xFFE0);
	data = data << 11; //shift left by 11 places to get next 11 bit word.
	unsigned short  word_low = (data & 0xFFE0);

	response = spi_write( spi, word_low);

	if( response == SPI_OK )
	{	while( spi_writeEndCheck(spi) == 0){}
		return spi_write( spi, word_high);
	}
	else
		return response;

The uC I am using is an Atmel AVR32 UC3B. The architecture is big-endian.

Can anyone see any obvious mistakes?
 

I assume 'unsigned short' is 16-bits?

If data is 0xffffffff, (64-bits)
Then
word_high = (unsigned short)(data & 0xffe00000);

data <<= 11;

word_low = (unsigned short)(data & 0xffe00000);
 

    sebmaster

    Points: 2
    Helpful Answer Positive Rating
Hi btbass,

I made the changes as you suggested (while kicking myself hard for the 0xffe0/0xffe00000 mistake) but now both shorts show a value of 0 in the debugger.

When I alter the mask to read 0xFFE0000F the short takes a value of 15.

I am sure my device is big-endian, page 5 of this document from Atmel certainly says so: http://www.atmel.com/dyn/resources/prod_documents/doc32000.pdf, yet what with the SPI bus pushing data out LSB first (when I was sure the datasheet diagrams showed MSB first) im starting to doubt it.

Is it possible that my device could be big-endian, yet when type-casting to a smaller type the (device/compiler?) starts at the highest address (LSBs)?

EDIT: OK, I just thought what would be the result if every programming language in the world truncated the LSBs instead of the MSBs when doing a downsizing typecast (for starters half of anything I ever wrote wouldnt work!) so I think ill go alter my program before I make myself look any more stupid!

Thank you!
 

Im sure the compiler should take care of the endiness?
Another approach is

word_high = (uint16_t)(0xffe0 & (data >> 16));
word_low = (uint16_t)(0xffe0 & data);
 

Hi btbass,

I think it must do. I was just confused because I was picturing the typecast truncating the 16 LSBs (I still don't know where I got that idea from).

Now I mask off all but them, shift out that value, right shift 11 places and do the same again, looking at the scope it appears to work.

The other point of confusion was the order the SPI bus uses, it is MSB first unlike I gathered before due to my previous mistake.

It appears to send data MSB first but truncates the MSBs of the value, so cuts off the top 5 bits but sends the rest MSB first when I have a word size of 11.

Now I just wish I hadn't modified my CPLD program to accept LSB first....

Thanks for your help, I dont know how long I would have been floundering around for!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top