view ostc4pack/src/OSTC4pack_V4.cpp @ 933:43055e069bd1 Evo_2_23

UART Gnss: Added fletcher calculation: Communication is verified using the Fletcher check. In the example code the commands were har coded including the check bytes. To make definition of new commands easier the check bytes are now calculated at runtime. This may be referted to hardcoded values once the implementation is getting a mature state.
author Ideenmodellierer
date Sun, 08 Dec 2024 17:38:16 +0100
parents 01f40cb1057e
children
line wrap: on
line source

#include <iostream>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */




#include <stdlib.h>

/******************************************************************************/
/*                             Start of crcmodel.h                            */
/******************************************************************************/
/*                                                                            */
/* Author : Ross Williams (ross@guest.adelaide.edu.au.).                      */
/* Date   : 3 June 1993.                                                      */
/* Status : Public domain.                                                    */
/*                                                                            */
/* Description : This is the header (.h) file for the reference               */
/* implementation of the Rocksoft^tm Model CRC Algorithm. For more            */
/* information on the Rocksoft^tm Model CRC Algorithm, see the document       */
/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross        */
/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in   */
/* "ftp.adelaide.edu.au/pub/rocksoft".                                        */
/*                                                                            */
/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.    */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/* How to Use This Package                                                    */
/* -----------------------                                                    */
/* Step 1: Declare a variable of type cm_t. Declare another variable          */
/*         (p_cm say) of type p_cm_t and initialize it to point to the first  */
/*         variable (e.g. p_cm_t p_cm = &cm_t).                               */
/*                                                                            */
/* Step 2: Assign values to the parameter fields of the structure.            */
/*         If you don't know what to assign, see the document cited earlier.  */
/*         For example:                                                       */
/*            p_cm->cm_width = 16;                                            */
/*            p_cm->cm_poly  = 0x8005L;                                       */
/*            p_cm->cm_init  = 0L;                                            */
/*            p_cm->cm_refin = TRUE;                                          */
/*            p_cm->cm_refot = TRUE;                                          */
/*            p_cm->cm_xorot = 0L;                                            */
/*         Note: Poly is specified without its top bit (18005 becomes 8005).  */
/*         Note: Width is one bit less than the raw poly width.               */
/*                                                                            */
/* Step 3: Initialize the instance with a call cm_ini(p_cm);                  */
/*                                                                            */
/* Step 4: Process zero or more message bytes by placing zero or more         */
/*         successive calls to cm_nxt. Example: cm_nxt(p_cm,ch);              */
/*                                                                            */
/* Step 5: Extract the CRC value at any time by calling crc = cm_crc(p_cm);   */
/*         If the CRC is a 16-bit value, it will be in the bottom 16 bits.    */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/* Design Notes                                                               */
/* ------------                                                               */
/* PORTABILITY: This package has been coded very conservatively so that       */
/* it will run on as many machines as possible. For example, all external     */
/* identifiers have been restricted to 6 characters and all internal ones to  */
/* 8 characters. The prefix cm (for Crc Model) is used as an attempt to avoid */
/* namespace collisions. This package is endian independent.                  */
/*                                                                            */
/* EFFICIENCY: This package (and its interface) is not designed for           */
/* speed. The purpose of this package is to act as a well-defined reference   */
/* model for the specification of CRC algorithms. If you want speed, cook up  */
/* a specific table-driven implementation as described in the document cited  */
/* above. This package is designed for validation only; if you have found or  */
/* implemented a CRC algorithm and wish to describe it as a set of parameters */
/* to the Rocksoft^tm Model CRC Algorithm, your CRC algorithm implementation  */
/* should behave identically to this package under those parameters.          */
/*                                                                            */
/******************************************************************************/

/* The following #ifndef encloses this entire */
/* header file, rendering it indempotent.     */
#ifndef CM_DONE
#define CM_DONE

/******************************************************************************/

/* The following definitions are extracted from my style header file which    */
/* would be cumbersome to distribute with this package. The DONE_STYLE is the */
/* idempotence symbol used in my style header file.                           */

#ifndef DONE_STYLE

typedef unsigned long   ulong;
typedef unsigned char * p_ubyte_;

#ifndef TRUE
#define FALSE 0
#define TRUE  1
#endif

/* Change to the second definition if you don't have prototypes. */
#define P_(A) A
/* #define P_(A) () */

/* Uncomment this definition if you don't have void. */
/* typedef int void; */

#endif

/******************************************************************************/

/* CRC Model Abstract Type */
/* ----------------------- */
/* The following type stores the context of an executing instance of the  */
/* model algorithm. Most of the fields are model parameters which must be */
/* set before the first initializing call to cm_ini.                      */
typedef struct
  {
   int   cm_width;   /* Parameter: Width in bits [8,32].       */
   ulong cm_poly;    /* Parameter: The algorithm's polynomial. */
   ulong cm_init;    /* Parameter: Initial register value.     */
   bool  cm_refin;   /* Parameter: Reflect input bytes?        */
   bool  cm_refot;   /* Parameter: Reflect output CRC?         */
   ulong cm_xorot;   /* Parameter: XOR this to output CRC.     */

   ulong cm_reg;     /* Context: Context during execution.     */
  } cm_t;
typedef cm_t *p_cm_t;

/******************************************************************************/

/* Functions That Implement The Model */
/* ---------------------------------- */
/* The following functions animate the cm_t abstraction. */

void cm_ini P_((p_cm_t p_cm));
/* Initializes the argument CRC model instance.          */
/* All parameter fields must be set before calling this. */

void cm_nxt P_((p_cm_t p_cm,int ch));
/* Processes a single message byte [0,255]. */

void cm_blk P_((p_cm_t p_cm,p_ubyte_ blk_adr,ulong blk_len));
/* Processes a block of message bytes. */

ulong cm_crc P_((p_cm_t p_cm));
/* Returns the CRC value for the message bytes processed so far. */

/******************************************************************************/

/* Functions For Table Calculation */
/* ------------------------------- */
/* The following function can be used to calculate a CRC lookup table.        */
/* It can also be used at run-time to create or check static tables.          */

ulong cm_tab P_((p_cm_t p_cm,int index));
/* Returns the i'th entry for the lookup table for the specified algorithm.   */
/* The function examines the fields cm_width, cm_poly, cm_refin, and the      */
/* argument table index in the range [0,255] and returns the table entry in   */
/* the bottom cm_width bytes of the return value.                             */

/******************************************************************************/

/* End of the header file idempotence #ifndef */
#endif

/******************************************************************************/
/*                             End of crcmodel.h                              */
/******************************************************************************/


/******************************************************************************/
/*                             Start of crcmodel.c                            */
/******************************************************************************/
/*                                                                            */
/* Author : Ross Williams (ross@guest.adelaide.edu.au.).                      */
/* Date   : 3 June 1993.                                                      */
/* Status : Public domain.                                                    */
/*                                                                            */
/* Description : This is the implementation (.c) file for the reference       */
/* implementation of the Rocksoft^tm Model CRC Algorithm. For more            */
/* information on the Rocksoft^tm Model CRC Algorithm, see the document       */
/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross        */
/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in   */
/* "ftp.adelaide.edu.au/pub/rocksoft".                                        */
/*                                                                            */
/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.    */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/* Implementation Notes                                                       */
/* --------------------                                                       */
/* To avoid inconsistencies, the specification of each function is not echoed */
/* here. See the header file for a description of these functions.            */
/* This package is light on checking because I want to keep it short and      */
/* simple and portable (i.e. it would be too messy to distribute my entire    */
/* C culture (e.g. assertions package) with this package.                     */
/*                                                                            */
/******************************************************************************/

#include "crcmodel.h"

/******************************************************************************/

/* The following definitions make the code more readable. */

#define BITMASK(X) (1L << (X))
#define MASK32 0xFFFFFFFFL
#define LOCAL static

/******************************************************************************/

ulong reflect P_((ulong v,int b))
{
 int   i;
 ulong t = v;
 for (i=0; i<b; i++)
   {
    if (t & 1L)
       v|=  BITMASK((b-1)-i);
    else
       v&= ~BITMASK((b-1)-i);
    t>>=1;
   }
 return v;
}

/******************************************************************************/

LOCAL ulong widmask (p_cm_t p_cm)
{
 return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L;
}

/******************************************************************************/

void cm_ini (p_cm_t p_cm)
{
 p_cm->cm_reg = p_cm->cm_init;
}

/******************************************************************************/

void cm_nxt (p_cm_t p_cm,int ch)
{
 int   i;
 ulong uch  = (ulong) ch;
 ulong topbit = BITMASK(p_cm->cm_width-1);

 if (p_cm->cm_refin) uch = reflect(uch,8);
 p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
 for (i=0; i<8; i++)
   {
    if (p_cm->cm_reg & topbit)
       p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
    else
       p_cm->cm_reg <<= 1;
    p_cm->cm_reg &= widmask(p_cm);
   }
}

/******************************************************************************/

void cm_blk (p_cm_t p_cm,p_ubyte_ blk_adr,ulong blk_len)
{
 while (blk_len--) cm_nxt(p_cm,*blk_adr++);
}

/******************************************************************************/

ulong cm_crc (p_cm_t p_cm)
{
 if (p_cm->cm_refot)
    return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width);
 else
    return p_cm->cm_xorot ^ p_cm->cm_reg;
}

/******************************************************************************/

ulong cm_tab (p_cm_t p_cm,int index)
{
 int   i;
 ulong r;
 ulong topbit = BITMASK(p_cm->cm_width-1);
 ulong inbyte = (ulong) index;

 if (p_cm->cm_refin) inbyte = reflect(inbyte,8);
 r = inbyte << (p_cm->cm_width-8);
 for (i=0; i<8; i++)
    if (r & topbit)
       r = (r << 1) ^ p_cm->cm_poly;
    else
       r<<=1;
 if (p_cm->cm_refin) r = reflect(r,p_cm->cm_width);
 return r & widmask(p_cm);
}

/******************************************************************************/
/*                             End of crcmodel.c                              */
/******************************************************************************/

#define uint32_t unsigned int
#define uint8_t unsigned char

uint32_t	CRC_CalcBlockCRC(uint32_t *buffer, uint32_t words)
 {
 cm_t        crc_model;
 uint32_t      word_to_do;
 uint8_t       byte_to_do;
 int         i;
 
     // Values for the STM32F generator.
 
     crc_model.cm_width = 32;            // 32-bit CRC
     crc_model.cm_poly  = 0x04C11DB7;    // CRC-32 polynomial
     crc_model.cm_init  = 0xFFFFFFFF;    // CRC initialized to 1's
     crc_model.cm_refin = FALSE;         // CRC calculated MSB first
     crc_model.cm_refot = FALSE;         // Final result is not bit-reversed
     crc_model.cm_xorot = 0x00000000;    // Final result XOR'ed with this
 
     cm_ini(&crc_model);
 
     while (words--)
     {
         // The STM32F10x hardware does 32-bit words at a time!!!
 
         word_to_do = *buffer++;
 
         // Do all bytes in the 32-bit word.
 
         for (i = 0; i < sizeof(word_to_do); i++)
         {
             // We calculate a *byte* at a time. If the CRC is MSB first we
             // do the next MS byte and vica-versa.
 
             if (crc_model.cm_refin == FALSE)
             {
                 // MSB first. Do the next MS byte.
 
                 byte_to_do = (uint8_t) ((word_to_do & 0xFF000000) >> 24);
                 word_to_do <<= 8;
             }
             else
             {
                 // LSB first. Do the next LS byte.
 
                 byte_to_do = (uint8_t) (word_to_do & 0x000000FF);
                 word_to_do >>= 8;
             }
 
             cm_nxt(&crc_model, byte_to_do);
         }
     }
 
     // Return the final result.
 
     return (cm_crc(&crc_model));
 }
 

unsigned checksum(void *buffer, size_t len, unsigned int seed)
{
      unsigned char *buf = (unsigned char *)buffer;
      size_t i;

      for (i = 0; i < len; ++i)
            seed += (unsigned int)(*buf++);
      return seed;
}

unsigned int crc32c_checksum(unsigned char* message, int length) {
   int i, j;
   unsigned int byte, crc, mask;
   static unsigned int table[256] = {0};

   /* Set up the table, if necessary. */

   if (table[1] == 0) {
      for (byte = 0; byte <= 255; byte++) {
         crc = byte;
         for (j = 7; j >= 0; j--) {    // Do eight times.
            mask = -(crc & 1);
            crc = (crc >> 1) ^ (0xEDB88320 & mask);
         }
         table[byte] = crc;
      }
   }

   /* Through with table setup, now calculate the CRC. */
   i = 0;
   crc = 0xFFFFFFFF;
   while (length--) {
      byte = message[i];
      crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
      i = i + 1;
   }
   return ~crc;
}






/******************************************************************************/

/* MAIN */
/* ----------------------- */
/*   */


#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
	
	
	if (argc != 3) {
		fprintf(stderr, "Usage: OSTC4pack_V4 <type> <bin file>\n");
		return(-1);
	}

	FILE *fp;
	size_t len;
	unsigned char buf[1050000];
	char *file = argv[2];
	int type =  atoi(argv[1]);
	unsigned int pruefsumme;
	
		//write File with length and cheksum
	char filename[500], filenameout[511];
	sprintf(filename,"%s",file);
	int filelength = strlen(filename);
	filename[filelength -4] = 0;
	
	if (NULL == (fp = fopen(file, "rb")))
	{
	    printf("Unable to open %s for reading\n", file);
	    return -1;
	}
	len = fread(buf, sizeof(char), sizeof(buf), fp);
	printf("%d bytes read (hex: %#x )\n", (uint32_t)len, (uint32_t)len);
//	unsigned int checksum = crc32c_checksum(buf, len);
	unsigned int checksum = CRC_CalcBlockCRC((uint32_t *)buf, (uint32_t)(len/4));
	printf("The checksum of %s is %#x\n", file, checksum);
	
	fclose(fp);
	if(type == 0)
		sprintf(filenameout,"%s_upload.bin",filename);
	else
	if(type == 2)
		sprintf(filenameout,"%s_upload.bin",filename);
	else
		sprintf(filenameout,"%s_upload.bin",filename);
	
	unsigned char buf2[4];
     
     buf2[0] = 0xFF & (len >> 24);;
     buf2[1] = 0xFF & (len >> 16);;
     buf2[2] = 0xFF & (len >> 8);
     buf2[3] = 0xFF & len;
     fp = fopen(filenameout, "wb");
    fwrite(buf2,sizeof(char),4,fp);


	unsigned char buf3offset[4];
	unsigned char bufVersion[4];
	if(type == 2)
	{
		buf3offset[0] = 0x10;
		buf3offset[1] = 0x00;
		buf3offset[2] = 0x03;
		buf3offset[3] = 0x20;
		bufVersion[0] = buf[0x00];
		bufVersion[1] = buf[0x01];
		bufVersion[2] = buf[0x02];
		bufVersion[3] = buf[0x03];
	}
	else
	if(type == 0)
	{
		buf3offset[0] = 0xFE;
		buf3offset[1] = 'R';
		buf3offset[2] = 'T';
		buf3offset[3] = 'E';
		bufVersion[0] = buf[0x5000];
		bufVersion[1] = buf[0x5001];
		bufVersion[2] = buf[0x5002];
		bufVersion[3] = buf[0x5003];
	}
	else
	{
		buf3offset[0] = 0xFF;
		buf3offset[1] = 0;
		buf3offset[2] = 'H';
		buf3offset[3] = 'W';
		bufVersion[0] = buf[0x10000];
		bufVersion[1] = buf[0x10001];
		bufVersion[2] = buf[0x10002];
		bufVersion[3] = buf[0x10003];
	}
	
    fwrite(buf3offset,sizeof(char),4,fp);
    
    pruefsumme = len + (256*256*256*buf3offset[0]) + (256*256*buf3offset[1]) + (256*buf3offset[2]) + buf3offset[3];
    fwrite(&pruefsumme,sizeof(char),4,fp);

    fwrite(bufVersion,sizeof(char),4,fp);

    for(int i = 0;i <len;i++)
    {
    	if(fwrite(&buf[i],1,1,fp) != 1)
     	printf("error writing\n");
	}
     
     
     buf2[0] = 0xFF & (checksum >> 24);// & 0xFF000000;
     buf2[1] =  0xFF & (checksum >> 16);
     buf2[2] = 	0xFF & (checksum >> 8);
     buf2[3] = 0xFF & checksum;
     
    fwrite(buf2,sizeof(char),4,fp);

     fclose(fp);
}