CRC calculation

General discussion on mikroPascal PRO for ARM.
Post Reply
Author
Message
mironso
Posts: 8
Joined: 15 Apr 2015 10:14

CRC calculation

#1 Post by mironso » 15 May 2015 08:48

Hi,
I'm wondering, have you implemented function for CRC calculation in mikroPascal PRO for ARM?
In the datasheet (datasheet for STM32F415xx/STM32F417xx), I have found that STM32F415xx have CRC calculation unit (first page).
Was looking in library manager without success. Need to check CRC from received message - calculate CRC and then compare with CRC in message. If they are equal - can perform other operations.
Using mikroPascal PRO for ARM v420.

Best regards,

Mironso.

User avatar
Aleksandar.Mitrovic
mikroElektronika team
Posts: 1697
Joined: 11 Mar 2015 12:48

Re: CRC calculation

#2 Post by Aleksandar.Mitrovic » 18 May 2015 15:03

Hi Mironso,

Unfortunately currently we do not have this CRC (Cyclic Redundancy Check) function in our Libraries.

I will suggest our Development team to consider adding this function in our compilers.

Best regards,
Aleksandar

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: CRC calculation

#3 Post by aCkO » 18 May 2015 18:24

mironso wrote:I'm wondering, have you implemented function for CRC calculation in mikroPascal PRO for ARM?
This can be easily achieved in software. However, unlike the HW CRC unit, there are many ways to calculate CRC (look-up table or bit-by-bit). Also, checksum length can vary. I guess you need CRC32 since it's the most popular one.

Here's the code:

Code: Select all

const _CRC32_POLY_REVERSE : dword = $EDB88320;

function CRC32_Custom(data_in : ^byte; len, poly : dword; ) : dword;
var
  lsb, j : byte;
  crc    : dword;
begin
  crc := $FFFFFFFF;
  
  while len > 0 do
  begin
    crc := crc xor data_in^;
    
    for j := 0 to 7 do
    begin
      lsb := crc and 1;
      crc := crc shr 1;
      
      if lsb = 1 then crc := crc xor poly;
    end;
    
    Inc(data_in);
    Dec(len);
  end;
  
  result := not crc;
end;

function CRC32(data_in : ^byte; len : dword) : dword;
begin
  result := CRC32_Custom(data_in, len, _CRC32_POLY_REVERSE);
end;
Usage:

Code: Select all

var
  msg : string[9];
  csum       : dword;
begin
   msg := '123456789';

   csum := CRC32(@msg, sizeof(msg) - 1);         // exclude terminator
                                                 // csum = $CBF43926
end.
If you can spare 1K of ROM space, then you can use the table look-up method which is much faster.

Regards

mironso
Posts: 8
Joined: 15 Apr 2015 10:14

Re: CRC calculation

#4 Post by mironso » 19 May 2015 12:38

Hi,

@Aleksandar: if you can suggest 2 types, CRC16 and CRC32. I needed CRC16 (modbus). Found it on net, had some difficulties to implement (lack of programming exp and specification of project), but now its working.

@aCko: thanks for example. Although it's not what I wanted, but was not specific what I wanted, wish you express my gratitude for your effort. Will save your example for further usage.

My goal was to calculate CRC from received msg and compare it against CRC included into msg.

If someone is interested, I can post my example.

Best regards,
Mironso.

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: CRC calculation

#5 Post by yo2lio » 19 May 2015 21:29

Hi,

You have here CRC16 and CRC32, enjoy:

Code: Select all

unit crc16_lib;

function get_crc16(var d_in : array[$FFFF] of byte; n : word) : word;
function get_crc16_pt(d_in : ^byte; n : word) : word;
function get_crc32(var d_in : array[$FFFF] of byte; n : word) : dword;
function get_crc32_pt(d_in : ^byte; n : word) : dword;

CONST
  Table16: ARRAY[0..255] OF WORD =
 ($0000,$C0C1,$C181,$0140,$C301,$03C0,$0280,$C241,$C601,$06C0,$0780,
  $C741,$0500,$C5C1,$C481,$0440,$CC01,$0CC0,$0D80,$CD41,$0F00,$CFC1,
  $CE81,$0E40,$0A00,$CAC1,$CB81,$0B40,$C901,$09C0,$0880,$C841,$D801,
  $18C0,$1980,$D941,$1B00,$DBC1,$DA81,$1A40,$1E00,$DEC1,$DF81,$1F40,
  $DD01,$1DC0,$1C80,$DC41,$1400,$D4C1,$D581,$1540,$D701,$17C0,$1680,
  $D641,$D201,$12C0,$1380,$D341,$1100,$D1C1,$D081,$1040,$F001,$30C0,
  $3180,$F141,$3300,$F3C1,$F281,$3240,$3600,$F6C1,$F781,$3740,$F501,
  $35C0,$3480,$F441,$3C00,$FCC1,$FD81,$3D40,$FF01,$3FC0,$3E80,$FE41,
  $FA01,$3AC0,$3B80,$FB41,$3900,$F9C1,$F881,$3840,$2800,$E8C1,$E981,
  $2940,$EB01,$2BC0,$2A80,$EA41,$EE01,$2EC0,$2F80,$EF41,$2D00,$EDC1,
  $EC81,$2C40,$E401,$24C0,$2580,$E541,$2700,$E7C1,$E681,$2640,$2200,
  $E2C1,$E381,$2340,$E101,$21C0,$2080,$E041,$A001,$60C0,$6180,$A141,
  $6300,$A3C1,$A281,$6240,$6600,$A6C1,$A781,$6740,$A501,$65C0,$6480,
  $A441,$6C00,$ACC1,$AD81,$6D40,$AF01,$6FC0,$6E80,$AE41,$AA01,$6AC0,
  $6B80,$AB41,$6900,$A9C1,$A881,$6840,$7800,$B8C1,$B981,$7940,$BB01,
  $7BC0,$7A80,$BA41,$BE01,$7EC0,$7F80,$BF41,$7D00,$BDC1,$BC81,$7C40,
  $B401,$74C0,$7580,$B541,$7700,$B7C1,$B681,$7640,$7200,$B2C1,$B381,
  $7340,$B101,$71C0,$7080,$B041,$5000,$90C1,$9181,$5140,$9301,$53C0,
  $5280,$9241,$9601,$56C0,$5780,$9741,$5500,$95C1,$9481,$5440,$9C01,
  $5CC0,$5D80,$9D41,$5F00,$9FC1,$9E81,$5E40,$5A00,$9AC1,$9B81,$5B40,
  $9901,$59C0,$5880,$9841,$8801,$48C0,$4980,$8941,$4B00,$8BC1,$8A81,
  $4A40,$4E00,$8EC1,$8F81,$4F40,$8D01,$4DC0,$4C80,$8C41,$4400,$84C1,
  $8581,$4540,$8701,$47C0,$4680,$8641,$8201,$42C0,$4380,$8341,$4100,
  $81C1,$8081,$4040); code;

CONST
  Table32: ARRAY[0..255] OF DWORD =
(0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D); code;
 
implementation

function get_crc16(var d_in : array[$FFFF] of byte; n : word) : word;
var i : word;
begin
  result := $FFFF;
  i := 0;
  while i < n do
    begin
      result := Hi(result) XOR Table16[d_in[i] XOR Lo(result)];
      inc(i);
    end;
end;

function get_crc16_pt(d_in : ^byte; n : word) : word;
var i : word;
begin
  result := $FFFF;
  i := 0;
  while i < n do
    begin
      result := Hi(result) XOR Table16[d_in^ XOR Lo(result)];
      inc(d_in);
      inc(i);
    end;
end;

function get_crc32(var d_in : array[$FFFF] of byte; n : word) : dword;
var i : word;
begin
  result := $FFFFFFFF;
  i := 0;
  while i < n do
    begin
      result := Table32[d_in[i] XOR Lo(result)] XOR (result shr 8);
      inc(i);
    end;
  result := result XOR $FFFFFFFF;
end;

function get_crc32_pt(d_in : ^byte; n : word) : dword;
var i : word;
begin
  result := $FFFFFFFF;
  i := 0;
  while i < n do
    begin
      result := Table32[d_in^ XOR Lo(result)] XOR (result shr 8);
      inc(i);
    end;
  result := result XOR $FFFFFFFF;
end;

end.
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: CRC calculation

#6 Post by aCkO » 19 May 2015 21:43

mironso wrote:@aCko: thanks for example. Although it's not what I wanted, but was not specific what I wanted, wish you express my gratitude for your effort. Will save your example for further usage.
The quality of expected answer depends on user's ability to precisely describe the problem. I see that yo2lio already posted the table look-up method. To generate CRC16 MODBUS checksum "manually" you just need to make 2 cosmetic changes to the code I posted: adjust the data types and change the polynomial.

Here's the complete code:

Code: Select all

const _CRC16_POLY_MODBUS : word = $A001;

function CRC16_Custom(data_in : ^byte; len, poly : word; ) : word;
var
  lsb, j : byte;
  crc    : word;
begin
  crc := $FFFF;
  
  while len > 0 do
  begin
    crc := crc xor data_in^;
    
    for j := 0 to 7 do
    begin
      lsb := crc and $0001;
      crc := crc shr 1;
      
      if lsb = 1 then crc := crc xor poly;
    end;
    
    Inc(data_in);
    Dec(len);
  end;
  
  result := crc;
end;

function CRC16(data_in : ^byte; len : word) : word;
begin
  result := CRC16_Custom(data_in, len, _CRC16_POLY_MODBUS);
end;
Usage:

Code: Select all

var
  msg : string[9];
  csum       : word;
begin
   msg := '123456789';

   csum := CRC16(@msg, sizeof(msg) - 1);         // exclude terminator
                                                 // csum = $4B37
end.
Regards

mironso
Posts: 8
Joined: 15 Apr 2015 10:14

Re: CRC calculation

#7 Post by mironso » 09 Jun 2015 11:59

Hi guys,
have been away for a while. Thanks for your effort providing CRC calculation. Have been created some modified version for my needs.
CRC that you give here, will serve me in the future, for sure, and will help other member(s) also.

Thanks to community for fast reply(ies).

Malcolm_M
Posts: 184
Joined: 12 May 2007 13:01
Location: Bristol, UK

Re: CRC calculation

#8 Post by Malcolm_M » 07 Dec 2016 21:16

Many thanks aCkO, using your CRC16 MODBUS.

Post Reply

Return to “mikroPascal PRO for ARM General”