Atmel SAM G55 CRCCU CRC32 calculation not replicateable - atmel

We are using an Atmel SAM G55 in one of our applications. At some point, we want to calculate a CRC32 on an x86 system and pass it to the G55 (Arm 32Bit).
For the G55 we use the CRCCU to compute the CRC32:
uint32_t crccu_crc32(uint8_t *p_buffer, uint32_t ul_length, uint32_t *pcrc)
{
uint32_t ul_crc;
uint32_t ul_timeout = 0;
if (*pcrc == ~0) {
/* Reset the CRCCU */
crccu_reset(CRCCU);
}
memset((void *)&_crc_dscr, 0, sizeof(crccu_dscr_type_t));
_crc_dscr.ul_tr_addr = (uint32_t) p_buffer;
/* Transfer width: byte, interrupt enable */
_crc_dscr.ul_tr_ctrl = (uint32_t)ul_length | (2 << 24);
/* Configure CRCCU mode */
crccu_configure_mode(CRCCU, CRCCU_MR_ENABLE | CRCCU_MR_PTYPE_CCITT8023 | CRCCU_MR_DIVIDER(0));
/* Start the CRC calculation */
crccu_enable_dma(CRCCU);
/* Wait for calculation ready */
while ((crccu_get_dma_status(CRCCU) == CRCCU_DMA_SR_DMASR) &&
(ul_timeout++ < 0xFFFFFFFF)) {
}
if (ul_timeout == 0xFFFFFFFF) {
return 1;
}
/* Get CRC value */
*pcrc = crccu_read_crc_value(CRCCU);
return 0;
}
This function is loosely related to the CRC-HAL of ASF4 and works fine (at least we think so).
However, we are not able to calculate the same CRC32 on our x86 machine.
To test the CRC32 calculation we use the following test-array:
uint32_t chksmtest[8] = {6448116,148714,884134,43,5487416,45486,8484384,64817};
Calculating the CRC32 with the CRCCU yields 0x4d4ee8cc as result.
We tried several CRC32 implementations on our x86 machine and can not replicate this result. We know the the CRCCU calculates the CRC32 LSB first (G55 reference page 901) and the polynomial is 0x04C11DB7 (G55 reference page 916).
Even with reversing the bit and/or byte order, we are not able to replicate the result. Which CRC32 implementation do we have to use, to archive the same result as the CRCCU? We tried the libiberty implementation as well as the W3 implementation.

Your hardware is computing a non-reflected 32-bit CRC using the polynomial 0x04c11db7, with an initial value of 0xffffffff and no final exclusive or. That CRC has a name: CRC-32/MPEG-2.
As noted, the 32-bit values you are providing are processed in little-endian order, with the least significant byte first.
If and only if the C code below is run on a little-endian machine (e.g. x86), it will produce your desired result:
#include <stddef.h>
unsigned crc32_mpeg2(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffffffff;
while (len--) {
crc ^= (unsigned)(*data++) << 24;
for (unsigned k = 0; k < 8; k++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x4c11db7 : crc << 1;
}
return crc & 0xffffffff;
}
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t chksmtest[8] =
{6448116,148714,884134,43,5487416,45486,8484384,64817};
printf("0x%08x\n", crc32_mpeg2(crc32_mpeg2(0, NULL, 0), chksmtest, 8 * 4));
return 0;
}
Output:
0x4d4ee8cc
The above is a simple bit-wise implementation. You can look at crcany for the generation of more efficient CRC implementations in software for that CRC.

Related

How to write 16bit integer to SRAM via Arduino?

The base of the problem: I have an Arduino Due and a MPU6050 accelerometer and an 23lcv512. MPU gives me 16bit signed integer. I would like to save the datas to the SRAM and after the measurement read them back and via Serial send it to PC. Sending to PC is not a problem. The problem is that this SRAM has 128k pcs 8bit address. My numbers are 16 bit. I can't write them directly. Here is my code. I tested the RAM with this code:
`
void loop() {
int i = 0;
Serial.print("Write Byte: ");
for (i = 0; i < 70000; i++) {
//Serial.print("Write Byte: ");
//Serial.print(i);
//Serial.println();
SRAM.writeByte(START_ADDRESS, i);
START_ADDRESS = START_ADDRESS + 1;
}
Serial.print("Write End");
i = 0;
START_ADDRESS = 0;
for (i = 0; i < 300; i++) {
Serial.print("Read Byte: ");
Serial.print(SRAM.readByte(START_ADDRESS));
Serial.println();
Serial.println();
START_ADDRESS = START_ADDRESS + 1;
delay(100);
}
}`
I added the 23LC library. If it's run reads back the numbers from the RAM but after 255 it starts to read 0 again. I know why does it happen. But I don't know howto solve the problem.
I tried to use the writeBlock command but it only works for me with char variables. Char variable requires more space than integers. I have not too much.
Is there anyone who can write a sample code which can write 16 bit signed integer to sram?
I've commented the most obvious problems in your original code below:
void loop() {
int i = 0;
Serial.print("Write Byte: ");
for (i = 0; i < 70000; i++) { // since i is a 16bit int, 70,000 is out of range.
SRAM.writeByte(START_ADDRESS, i); // cool you wrote 1 byte, where is the other write?
START_ADDRESS = START_ADDRESS + 1; // try to keep all caps names for constants.
// this will make your code easier to read, trust me!
}
Serial.print("Write End");
i = 0;
START_ADDRESS = 0;
for (i = 0; i < 300; i++) {
Serial.print("Read Byte: ");
Serial.print(SRAM.readByte(START_ADDRESS)); // you read 1 byte, you can't expect a 16 bit
// value out of that.
Serial.println();
Serial.println();
START_ADDRESS = START_ADDRESS + 1;
delay(100);
}
}
Here's a more sound approach, it stores unsigned ints, but that can easily be changed to signed ints.
#define SRAM_SIZE (128UL << 10) // we have 128K of SRAM available.
// The U and L make this value an unsigned long.
// ALWAYS use unsigned values for addresses.
void loop()
{
Serial.print(F("Writing sequential numbers into SRAM...")); // _always_ store string constants in flash.
// save your RAM for more interesting stuff.
for (unsigned long i = 0; i < SRAM_SIZE; i += 2) // filling SRAM
{
// this is the (truncated from 0-65535) value we'll write.
unsigned int value = static_cast<unsigned int>(i & 0xFFFF);
SRAM.writeByte(i, value & 0xFF); // write lowest 8 bits
SRAM.writeByte(i + 1, (value >> 8) & 0xFF); // write next 8 bits.
}
Serial.println(F("done."));
// read back
Serial.println(F("SRAM contents (16-bits unsigned values):"));
for (unsigned long i = 0; i < SRAM_SIZE; i += 2) // reading all SRAM in 16-bit chunks.
{
Serial.print(i, HEX);
Serial.print(F(": "));
// read two consecutive bytes and pack them into a 16-bit integer.
unsigned int value = SRAM.readByte(i) + (static_cast<unsigned int>(SRAM.readByte(i+1)) << 8); // the cast is necessary.
Serial.println(value);
}
delay(100);
}

Arduino SD card fails to write when used with another SPI device

I have an ADXL355 accelerometer attached to an Adafruit Feather Adalogger. I can configure and read the sensor. I can also write binary values to the SD card. The problem occurs when I try to read from the sensor and then write that data to the SD card. The only thing I can think of is I'm somehow messing up the SPI communication but I can't see where. I looked through pins_arduino.h for my board and the SD Card (pin 4) is on a different register than pin 10 so I don't see how I'm breaking things.
My operations proceed like this. Global sensor creation, Serial.begin, SD.begin, SPI.begin, Test sensor connection, Create file for output on SD card, Initialize sensor, Read sensor FIFO, Write to file, repeat last 2 forever.
The file is created but remains at 0 file size, ie nothing is actually written to the card.
The sensor can operate at 4 kHz which was hard to achieve using the digitalWrite functions so I switched to using the port registers on the Feather. I do it like this:
#include <SM_ADXL355_SPI_fast.h>
#include <SPI.h>
#include <SD.h>
#define cardSelect 4
ADXL355_SPIF adxl355(&DDRB, &PORTB, _BV(6)); // values taken from pins_arduino.h, tested and working on pin 10
void setup() {
Serial.begin(57600);
while(!Serial){
// wait for Serial
}
SD.begin(cardSelect);
SPI.begin();
while(!adxl355.TestConnection()){
delay(1000);
}
adxl355.OpenFile("TestSPI.bin");
adxl355.Initialize(1, 10, 0); // set range to 2g's, frequency to 4 Hz and filter to off
}
void loop() {
while(true){ // avoid Arduino overhead of their loop function
adxl355.ReadFIFO();
adxl355.WriteFIFOToFile();
}
}
Here is the ADXL constructor
ADXL355_SPIF::ADXL355_SPIF(volatile uint8_t * outReg, volatile uint8_t * outPort, uint8_t bitValue) : sensorOutReg(outReg), sensorPort(outPort), sensorBitValue(bitValue){
*sensorOutReg |= sensorBitValue;
*sensorPort |= sensorBitValue;
sensorWriteCount = 0;
}
TestConnection tests that the DeviceID reads 0xAD. Initialize sets the G range, sample rate in Hz and filter. I have tested these with serial output and they work properly.
OpenFile looks like this:
bool ADXL355_SPIF::OpenFile(const String& fileName){
sensorFile = SD.open(fileName, FILE_WRITE);
if (!sensorFile){
Serial.print("Could not create file: ");
Serial.println(fileName);
return false;
}
return true;
}
After running this a file does get created on the SD card called "TESTSPI.BIN" with 0 file size.
ReadFIFO reads the numbers of entries in FIFO, stored as fifoCount and then populates a buffer (sensorFIFO[32][3]) with the values from the FIFO. I've printed this buffer to Serial to show that it's working. Here is that function
void ADXL355_SPIF::ReadFIFO(){
ReadRegister(ADXL355_RA_FIFO_ENTRIES, 1);
fifoCount = buffer[0];
ReadFIFOInternal();
return;
}
void ADXL355_SPIF::ReadFIFOInternal(){
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
*sensorPort &= ~sensorBitValue;
uint8_t spiCommand = ADXL355_RA_FIFO_DATA << 1 | ADXL355_READ;
SPI.transfer(spiCommand);
int i = 0;
unsigned long tempV;
unsigned long value;
while(i < fifoCount){
for (int ptr = 0; ptr < 3; ++ptr){
buffer[0] = SPI.transfer(0x0);
value = buffer[0];
value <<= 12;
tempV = SPI.transfer(0x0);
tempV <<= 4;
value |= tempV;
tempV = SPI.transfer(0x0);
tempV >>=4;
value |= tempV;
if (buffer[0] & 0x80) {
value |= 0xFFF00000;
}
long lValue = static_cast<long>(value);
sensorFIFO[i][ptr] = scaleFactor * lValue;
}
i += 3;
}
SPI.endTransaction();
*sensorPort |= sensorBitValue;
return;
}
Here is WriteFIFOToFile:
void ADXL355_SPIF::WriteFIFOToFile(){
if (fifoCount > 0){
sensorFile.write(reinterpret_cast<const char *>(&sensorFIFO), 4 * fifoCount);
}
sensorWriteCount += fifoCount;
if (sensorWriteCount >= 100){
sensorFile.flush();
sensorWriteCount = 0;
}
}
After allowing this to run for a while the file size is always 0. I tried a simple binary write function just to test the card. It looks like this and it worked.
#include <SD.h>
#define cardSelectPin 4
const float pi=3.14159;
File oFile;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while(!Serial){
// wait for serial
}
SD.begin(cardSelectPin);
oFile = SD.open("Test.bin", FILE_WRITE);
Serial.println(sizeof(int));
Serial.println(sizeof(float));
float testFloat[32][3];
for (int i = 0; i < 32; ++i){
for (int j = 0; j < 3; ++j){
testFloat[i][j] = pi * (i + 1) + j;
}
}
oFile.write(reinterpret_cast<const char *>(&testFloat), sizeof(float) * 96);
oFile.close();
Serial.println("Finished writing file.");
}
void loop() {
// put your main code here, to run repeatedly:
}
The problem was that flush was not being called correctly. I had created a buffer to hold data from the FIFO and it would flush the card when it would get full enough such that a subsequent read would overflow. At that time it would call flush. This is what was intended with the variable sensorWriteCount. This variable was of type uint8_t when it should have been a uint16_t.
Changing to the correct type fixed the problem. I would have deleted this question because it boils down to a typo, but once an answer has been posted the system doesn't allow that.
The only difference between the not-working sketch and the working one is the closing of the sd card. The sd card MUST be closed, I had the same problem you have and I assume that the file gets its boundaries written in its filesystem at file close call.
To solve your issue, use a push button. When you push it, it will close the file and stop reading/processing sensors. You can also use this button to start reading and recording sensors data on sd card again (toggle).

Using MSPf5529 with UART returns spacing cedilla in Mac

I'm trying to use the MSPF5529 with my mac. I've downloaded code composer studio and can easily access the chip as well as blink lights and any other application I need.
The goal is for me to print a message using UART through serial communication on my Mac. I am currently using an application called "goSerial" in order to communicate with the chip. My code below initializes UART, takes in a single character, and then it is supposed to print out a character, and then blink a light. However, instead, the code takes in the character, and prints out a strange symbol, called a spacing cedilla, with a hex value of 0xFC, and then blinks the light.
This symbol appears regardless of which character I put into the MSP430 buffer.
My code is listed below. Has anyone had this problem before? How do I solve this?
void Init_UART(void);
void OUTA_UART(unsigned char A);
unsigned char INCHAR_UART(void);
#include "msp430f5529.h"
#include "stdio.h"
int main(void){
volatile unsigned char a;
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD;
Init_UART();
a=INCHAR_UART();
a=INCHAR_UART();
OUTA_UART(a);
// go blink the light to indicate code is running
P1DIR |= 0x01;
for (;;){
P1OUT ^= 0x01; i = 10000;
do i--;
while (i != 0); }
}
void OUTA_UART(unsigned char A){
while ((UCA1STAT&UCBUSY));
// send the data to the transmit buffer
UCA1TXBUF =A;
}
unsigned char INCHAR_UART(void){
while ((UCA1STAT&UCBUSY) == 0);
// go get the char from the receive buffer
return (UCA1RXBUF);
}
void Init_UART(void){
P4SEL |= 0x30; // Port 4.4 and port 4.5 controls the transfer
UCA1CTL1|= UCSWRST; // Put state machine in reset
UCA1CTL1|= UCSSEL_1; //Choose 32765Hz
UCA0BR0=3; // Baud rate = 9600
UCA0BR1=0; // Choose 32765 hz
UCA1MCTL=0x06; // Modulation UCBRSx=3, UCBFx = 0
UCA1CTL1 &= ~UCSWRST; // Put USCI in operation mode
}
The UCBUSY flag is not very useful, and cannot be used like this.
That a byte has been received is indicated by UCRXIFG:
while (!(UCA1IFG & UCRXIFG)) ;
return UCA1RXBUF;
That a byte can be sent is indicated by UCTXIFG:
while (!(UCA1IFG & UCTXIFG)) ;
UCA1TXBUF = a;

ATTiny array update error

I am making a persistence of vision display using an ATTiny85, programmed with Arduino using the arduino-tiny core.
It consists of a stick with 16 LEDs on it which is spun round quickly to 'draw' a picture in the air. The display buffer is represented by an array, the next index of which is output every time the timer fires. It uses a hall sensor wired to INT0 to sense top dead centre, where it zeroes the array index.
It is an 8 bit processor and I have 16 LEDs connected to LED drivers, so I actually use two arrays for the display.
So the weird thing is that when I initialised the display with a cross pattern, it displayed a bunch of broken lines; so I zeroed it first in case memory had some random stuff in it. Now it doesn't display anything (even though I write the cross pattern to it straight after zeroing it). I have no idea what is happening, any ideas?
I had it previously outputting just the index value, and the picture it traces appears to look like counting binary, so I think the hardware is working.
Note that I'm not using digitalWrite because it disables interrupts which might throw the timing off.
Here is the code: (sorry it's quite a lot)
#define COLUMNCOUNT 180
const int datapin = 4;
const int clockpin = 0;
const int latchpin = 1;
const int rxpin = 3;
const int hallpin = 2;
volatile int columns0[COLUMNCOUNT];
volatile int columns1[COLUMNCOUNT];
volatile int counter = 0;
void setup()
{
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(rxpin, INPUT);
pinMode(hallpin, INPUT);
//make sure the arrays are all zeroed
for (int i = 0; i < COLUMNCOUNT; i++)
{
columns0[i] = 0;
columns1[i] = 0;
}
//make a cross pattern
columns0[0] = 255;
columns1[0] = 255;
columns0[45] = 255;
columns1[45] = 255;
columns0[90] = 255;
columns1[90] = 255;
columns0[135] = 255;
columns1[135] = 255;
//turn on the timer (prescale CK/16)
OCR1A = 255;
OCR1C = 255;
TCNT1 = 0;
TIMSK = _BV(OCIE1A);
TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS10);
GIMSK = _BV(INT0);
sei();
}
void loop()
{
//nothing to do here
}
ISR(TIMER1_COMPA_vect)
{
if (counter < COLUMNCOUNT)
counter++;
outputWord(columns0[counter], columns1[counter]);
}
ISR(INT0_vect)
{
counter = 0;
}
void outputByte(int b)
{
int currentBit;
for (int i = 0; i < 8; i++)
{
currentBit = (b & 128) == 128;
PORTB = _BV(clockpin) | (currentBit ? _BV(datapin) : 0);
PORTB = PORTB ^ _BV(clockpin);
b <<= 1;
}
}
void outputWord(int hi, int lo)
{
outputByte(hi);
outputByte(lo);
PORTB = _BV(latchpin);
PORTB = 0;
}
Per C standard, global variables are initialised to 0. As such,
//make sure the arrays are all zeroed
for (int i = 0; i < COLUMNCOUNT; i++)
{
columns0[i] = 0;
columns1[i] = 0;
}
is not necessary. That action is taken care of automatically when the __do_clear_bss section is executed.
Also, as per C standard, the int type must be at least 16 bits wide. In AVR, the minimum is used. If you are using the free software toolchain, it contains inttypes.h which provides the functionality offered by stdint.h and some extra stuff. This was mentioned in another answer.
The statement:
PORTB = PORTB ^ _BV(clockpin);
can be rewritten as:
PINB = _BV(clockpin);
which compiles to only 1 instruction, as per Atmel's datasheets.
Macros provided by pgmspace.h can read from flash. Notice that you can not change the contents of flash as your program runs in most AVR chips.
Beware local/global variables and stack/heap collisions when handling this much data.
I've figured it out: it's an SRAM issue. The ATTiny85 only has 512 bytes of SRAM, so it can't hold all that data in memory at the same time. I'm investigating storing the data in flash memory using the PROGMEM directive instead.
I am also doing a Persistance of Vision (POV) with the Attiny44. (I am programming it via the Arduino as an ISP)
user Ben Jackson's tip for conserving SRAM memory was spot on: I originally was using "int"'s for my arrays and my Attiny would bug out if I tried to include additional arrays- However when I simply declared all of my arrays as "unsigned char"'s my code worked fabulously as it should!
Next time I will either order attiny45's or similar for more SRAM memory, and continue to use unsigned char's for my array declarations.
Thanks for the discussion guys!

Enable data memory PIC 18F4550

I'm using the PIC18F4550 from microchip with the c compiler: by default the 'program memory' is used, but now I want to use the 'data memory' because it gives me a big more functionality, can enyone just tell me how can I to that in the program language C.
That the code:
#pragma code
/******************************************************************************/
void main (void)
{
TRISD = 0x00; // PORTD als uitgang
TRISB = 0b00110000; // RB4 en RB5 als ingang
TRISA = 0x00; // RA output
RCONbits.IPEN = 0; // prioriteit uit
INTCONbits.GIE = 1; // enable interrupt
INTCONbits.RBIE = 1; // interrupt portB aan
while(1)
{
_asm sleep _endasm
}
}
#pragma interrupt ISR
void ISR (void)
{
int rood[] = {0,0,1,0,1,0,1,0,1,0,1,1,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,};
if (INTCONbits.RBIF==1)
{
if(PORTBbits.RB5==0) // S3 ingedrukt ?
{
int i = 0;
int b;
do {
LATAbits.LATA2 = rood[i];
LATDbits.LATD1 ^= 1;
b = 0;
do {
b++;
}while(b <= 1500);
i++;
}while(rood[i] <= 50);
//LATDbits.LATD1 ^= 1; // D2 togglen
}
}
INTCONbits.RBIF = 0;
}
The data sheets for this device seem to indicate that the Data Memory is static ram, and that there is no data path from there to the instruciton decode logic, ie, the data memory cannot be used to store program code for execution. If that was your goal, you are out of luck.
In terms of allocating volatile storage, since the program memory does not appear to include any RAM, my guess is that the C compiler will automatically allocate all variables, etc from the data ram.
That leaves only the choice between the "data" EEPROM and the "program" flash for storage of non-volatile (or semi-volatile) data. There you may have to dig into the documentation - it could be this is done with compiler pragmas, or a linker map file, or it could be that access has to be handled indirectly and explicitly through registers.

Resources