135 lines
2.8 KiB
C
135 lines
2.8 KiB
C
/*
|
||
* eth_checksum.c
|
||
*
|
||
* Created on: 13 мар. 2023 г.
|
||
* Author: sychev
|
||
*/
|
||
#include "free_rtos/ethernet_ip/eth_checksum.h"
|
||
#include "free_rtos/base/swap.h"
|
||
|
||
#include <arm_acle.h>
|
||
#include <string.h>
|
||
|
||
uint16_t eth_calcChksum(uint32_t sum, uint8_t * const data, uint16_t len)
|
||
{
|
||
uint16_t i;
|
||
uint16_t size = len - 1;
|
||
|
||
if ( !len )
|
||
return 0;
|
||
|
||
for ( i = 0; i < size; i+=2 )
|
||
sum += ((uint16_t)data[i] << 8) + data[i+1];
|
||
|
||
if (len & 0x01)
|
||
sum += (uint16_t)data[i] << 8;
|
||
|
||
while ( sum >> 16 )
|
||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||
|
||
return ~sum;
|
||
}
|
||
|
||
uint16_t eth_calcChksum2(uint32_t sum, uint8_t * const hdata, uint16_t hlen, uint8_t * const data, uint16_t len)
|
||
{
|
||
uint16_t i;
|
||
uint16_t hsize = hlen - 1;
|
||
uint16_t size = len - 1;
|
||
|
||
if ( (hlen == 0) || (len == 0) )
|
||
return 0;
|
||
|
||
for ( i = 0; i < hsize; i+=2 )
|
||
sum += ((uint16_t)hdata[i] << 8) + hdata[i+1];
|
||
|
||
if (hlen & 0x01)
|
||
sum += (uint16_t)hdata[i] << 8;
|
||
|
||
for ( i = 0; i < size; i+=2 )
|
||
sum += ((uint16_t)data[i] << 8) + data[i+1];
|
||
|
||
if (len & 0x01)
|
||
sum += (uint16_t)data[i] << 8;
|
||
|
||
while ( sum >> 16 )
|
||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||
|
||
return ~sum;
|
||
}
|
||
|
||
uint32_t calcSum(void * const buffer, uint32_t sum, void * const data, uint16_t len)
|
||
{
|
||
uint8_t* buffer_start;
|
||
uint8_t* data_start;
|
||
uint32_t value;
|
||
|
||
buffer_start = (uint8_t*)buffer;
|
||
data_start = (uint8_t*)data;
|
||
value = 0x00000000;
|
||
|
||
#define SIZE sizeof(uint32_t)
|
||
while(len >= SIZE) {
|
||
len -= SIZE;
|
||
|
||
memcpy(&value, data_start, SIZE);
|
||
data_start += SIZE;
|
||
|
||
memcpy(buffer_start, &value, SIZE);
|
||
buffer_start += SIZE;
|
||
|
||
value = __rev16(value);
|
||
sum += (value&0xFFFF) + (value>>16);
|
||
}
|
||
#undef SIZE
|
||
|
||
#define SIZE sizeof(uint16_t)
|
||
if(len >= SIZE) {
|
||
len -= SIZE;
|
||
value = 0x00000000;
|
||
|
||
memcpy(&value, data_start, SIZE);
|
||
data_start += SIZE;
|
||
|
||
memcpy(buffer_start, &value, SIZE);
|
||
buffer_start += SIZE;
|
||
|
||
sum += __rev16(value);
|
||
}
|
||
#undef SIZE
|
||
|
||
#define SIZE sizeof(uint8_t)
|
||
if(len >= SIZE) {
|
||
len -= SIZE;
|
||
value = 0x00000000;
|
||
|
||
memcpy(&value, data_start, SIZE);
|
||
data_start += SIZE;
|
||
|
||
memcpy(buffer_start, &value, SIZE);
|
||
buffer_start += SIZE;
|
||
|
||
sum += __rev16(value);
|
||
}
|
||
#undef SIZE
|
||
|
||
return sum;
|
||
}
|
||
|
||
uint16_t eth_calcChksum3(void * const buffer, uint32_t sum, void * const hdata, uint16_t hlen, void * const data, uint16_t len)
|
||
{
|
||
if(hdata != 0) {
|
||
sum = calcSum(buffer, sum, hdata, hlen);
|
||
|
||
}
|
||
|
||
if(data != 0) {
|
||
sum = calcSum((uint8_t*)buffer + hlen, sum, data, len);
|
||
}
|
||
|
||
while (sum >> 16) {
|
||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||
}
|
||
|
||
return ~sum;
|
||
}
|