add hdlc frame
This commit is contained in:
parent
a154d92903
commit
a19da2cbd3
66
hdlc/crc.c
66
hdlc/crc.c
@ -1,66 +0,0 @@
|
||||
#include "crc.h"
|
||||
|
||||
const int8_t size = 2;
|
||||
const CRC_t CRC_INIT = 0xFFFFU;
|
||||
const CRC_t CRC_FINALXOR = 0xFFFFU;
|
||||
const CRC_t CRC_GOOD = 0xF0B8U;
|
||||
|
||||
static const uint16_t CRC_TAB[256U] = {
|
||||
0x0000UL, 0x1189UL, 0x2312UL, 0x329BUL, 0x4624UL, 0x57ADUL, 0x6536UL, 0x74BFUL,
|
||||
0x8C48UL, 0x9DC1UL, 0xAF5AUL, 0xBED3UL, 0xCA6CUL, 0xDBE5UL, 0xE97EUL, 0xF8F7UL,
|
||||
0x1081UL, 0x0108UL, 0x3393UL, 0x221AUL, 0x56A5UL, 0x472CUL, 0x75B7UL, 0x643EUL,
|
||||
0x9CC9UL, 0x8D40UL, 0xBFDBUL, 0xAE52UL, 0xDAEDUL, 0xCB64UL, 0xF9FFUL, 0xE876UL,
|
||||
0x2102UL, 0x308BUL, 0x0210UL, 0x1399UL, 0x6726UL, 0x76AFUL, 0x4434UL, 0x55BDUL,
|
||||
0xAD4AUL, 0xBCC3UL, 0x8E58UL, 0x9FD1UL, 0xEB6EUL, 0xFAE7UL, 0xC87CUL, 0xD9F5UL,
|
||||
0x3183UL, 0x200AUL, 0x1291UL, 0x0318UL, 0x77A7UL, 0x662EUL, 0x54B5UL, 0x453CUL,
|
||||
0xBDCBUL, 0xAC42UL, 0x9ED9UL, 0x8F50UL, 0xFBEFUL, 0xEA66UL, 0xD8FDUL, 0xC974UL,
|
||||
0x4204UL, 0x538DUL, 0x6116UL, 0x709FUL, 0x0420UL, 0x15A9UL, 0x2732UL, 0x36BBUL,
|
||||
0xCE4CUL, 0xDFC5UL, 0xED5EUL, 0xFCD7UL, 0x8868UL, 0x99E1UL, 0xAB7AUL, 0xBAF3UL,
|
||||
0x5285UL, 0x430CUL, 0x7197UL, 0x601EUL, 0x14A1UL, 0x0528UL, 0x37B3UL, 0x263AUL,
|
||||
0xDECDUL, 0xCF44UL, 0xFDDFUL, 0xEC56UL, 0x98E9UL, 0x8960UL, 0xBBFBUL, 0xAA72UL,
|
||||
0x6306UL, 0x728FUL, 0x4014UL, 0x519DUL, 0x2522UL, 0x34ABUL, 0x0630UL, 0x17B9UL,
|
||||
0xEF4EUL, 0xFEC7UL, 0xCC5CUL, 0xDDD5UL, 0xA96AUL, 0xB8E3UL, 0x8A78UL, 0x9BF1UL,
|
||||
0x7387UL, 0x620EUL, 0x5095UL, 0x411CUL, 0x35A3UL, 0x242AUL, 0x16B1UL, 0x0738UL,
|
||||
0xFFCFUL, 0xEE46UL, 0xDCDDUL, 0xCD54UL, 0xB9EBUL, 0xA862UL, 0x9AF9UL, 0x8B70UL,
|
||||
0x8408UL, 0x9581UL, 0xA71AUL, 0xB693UL, 0xC22CUL, 0xD3A5UL, 0xE13EUL, 0xF0B7UL,
|
||||
0x0840UL, 0x19C9UL, 0x2B52UL, 0x3ADBUL, 0x4E64UL, 0x5FEDUL, 0x6D76UL, 0x7CFFUL,
|
||||
0x9489UL, 0x8500UL, 0xB79BUL, 0xA612UL, 0xD2ADUL, 0xC324UL, 0xF1BFUL, 0xE036UL,
|
||||
0x18C1UL, 0x0948UL, 0x3BD3UL, 0x2A5AUL, 0x5EE5UL, 0x4F6CUL, 0x7DF7UL, 0x6C7EUL,
|
||||
0xA50AUL, 0xB483UL, 0x8618UL, 0x9791UL, 0xE32EUL, 0xF2A7UL, 0xC03CUL, 0xD1B5UL,
|
||||
0x2942UL, 0x38CBUL, 0x0A50UL, 0x1BD9UL, 0x6F66UL, 0x7EEFUL, 0x4C74UL, 0x5DFDUL,
|
||||
0xB58BUL, 0xA402UL, 0x9699UL, 0x8710UL, 0xF3AFUL, 0xE226UL, 0xD0BDUL, 0xC134UL,
|
||||
0x39C3UL, 0x284AUL, 0x1AD1UL, 0x0B58UL, 0x7FE7UL, 0x6E6EUL, 0x5CF5UL, 0x4D7CUL,
|
||||
0xC60CUL, 0xD785UL, 0xE51EUL, 0xF497UL, 0x8028UL, 0x91A1UL, 0xA33AUL, 0xB2B3UL,
|
||||
0x4A44UL, 0x5BCDUL, 0x6956UL, 0x78DFUL, 0x0C60UL, 0x1DE9UL, 0x2F72UL, 0x3EFBUL,
|
||||
0xD68DUL, 0xC704UL, 0xF59FUL, 0xE416UL, 0x90A9UL, 0x8120UL, 0xB3BBUL, 0xA232UL,
|
||||
0x5AC5UL, 0x4B4CUL, 0x79D7UL, 0x685EUL, 0x1CE1UL, 0x0D68UL, 0x3FF3UL, 0x2E7AUL,
|
||||
0xE70EUL, 0xF687UL, 0xC41CUL, 0xD595UL, 0xA12AUL, 0xB0A3UL, 0x8238UL, 0x93B1UL,
|
||||
0x6B46UL, 0x7ACFUL, 0x4854UL, 0x59DDUL, 0x2D62UL, 0x3CEBUL, 0x0E70UL, 0x1FF9UL,
|
||||
0xF78FUL, 0xE606UL, 0xD49DUL, 0xC514UL, 0xB1ABUL, 0xA022UL, 0x92B9UL, 0x8330UL,
|
||||
0x7BC7UL, 0x6A4EUL, 0x58D5UL, 0x495CUL, 0x3DE3UL, 0x2C6AUL, 0x1EF1UL, 0x0F78UL
|
||||
};
|
||||
|
||||
void crc_init(CRC16_CCITT* crc_obj) {
|
||||
crc_obj->crc = CRC_INIT;
|
||||
crc_obj->size = 2;
|
||||
}
|
||||
|
||||
void crc_update(CRC16_CCITT* crc_obj, uint8_t data) {
|
||||
crc_obj->crc = (crc_obj->crc >> 8U) ^ CRC_TAB[(crc_obj->crc ^ data) & CRC_FINALXOR];
|
||||
}
|
||||
|
||||
bool crc_good(const CRC16_CCITT* crc_obj) {
|
||||
return crc_obj->crc == 0xF0B8U;
|
||||
}
|
||||
|
||||
void crc_final(CRC16_CCITT* crc_obj) {
|
||||
crc_obj->crc ^= CRC_FINALXOR;
|
||||
}
|
||||
|
||||
uint8_t crc_get(const CRC16_CCITT* crc_obj, int8_t pos) {
|
||||
if (pos == 0){
|
||||
return crc_obj->crc;
|
||||
} else{
|
||||
return crc_obj->crc >> 8U;
|
||||
}
|
||||
}
|
25
hdlc/crc.h
25
hdlc/crc.h
@ -1,25 +0,0 @@
|
||||
//
|
||||
// Created by 79513 on 13.06.2023.
|
||||
//
|
||||
|
||||
#ifndef CRC16_CCITT_H_
|
||||
#define CRC16_CCITT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef uint16_t CRC_t;
|
||||
|
||||
typedef struct {
|
||||
const CRC_t* CRC_TAB;
|
||||
CRC_t crc;
|
||||
int size;
|
||||
} CRC16_CCITT;
|
||||
|
||||
void crc_init(CRC16_CCITT* crc_obj);
|
||||
void crc_update(CRC16_CCITT* crc_obj, uint8_t data);
|
||||
bool crc_good(const CRC16_CCITT* crc_obj);
|
||||
void crc_final(CRC16_CCITT* crc_obj);
|
||||
uint8_t crc_get(const CRC16_CCITT* crc_obj, int8_t pos);
|
||||
|
||||
#endif
|
167
hdlc/hdlc.h
167
hdlc/hdlc.h
@ -1,167 +0,0 @@
|
||||
#ifndef HDLC_H_
|
||||
#define HDLC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "crc.h"
|
||||
|
||||
#define HDLC_TEMPLATE \
|
||||
int16_t (*readByte)(void), \
|
||||
void (*writeByte)(uint8_t data), \
|
||||
uint16_t rxBuffLen, \
|
||||
struct CRC
|
||||
|
||||
#define HDLC_TEMPLATETYPE \
|
||||
readByte, \
|
||||
writeByte, \
|
||||
rxBuffLen, \
|
||||
CRC
|
||||
|
||||
struct HDLC {
|
||||
const uint8_t DATAINVBIT;
|
||||
const uint8_t DATASTART;
|
||||
const uint8_t DATAESCAPE;
|
||||
const uint8_t* DATAESCAPELIST;
|
||||
|
||||
int16_t (*readByte)(void);
|
||||
void (*writeByte)(uint8_t data);
|
||||
uint16_t rxBuffLen;
|
||||
CRC16_CCITT rxcrc;
|
||||
|
||||
const uint16_t RXBFLEN;
|
||||
|
||||
int8_t status;
|
||||
uint16_t len;
|
||||
CRC16_CCITT txcrc;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
void escapeAndWriteByte(struct HDLC* hdlc, uint8_t data) {
|
||||
const uint8_t* escapeList = hdlc->DATAESCAPELIST;
|
||||
while (*escapeList != 0) {
|
||||
if (data == *escapeList) {
|
||||
hdlc->writeByte(hdlc->DATAESCAPE);
|
||||
data ^= hdlc->DATAINVBIT;
|
||||
break;
|
||||
}
|
||||
escapeList++;
|
||||
}
|
||||
hdlc->writeByte(data);
|
||||
}
|
||||
|
||||
#define ESCAPED (-1)
|
||||
#define RECEIVING 0
|
||||
#define OK 1
|
||||
#define CRCERR 2
|
||||
|
||||
void HDLC_init(struct HDLC* hdlc){
|
||||
hdlc->len = 0U;
|
||||
hdlc->status = RECEIVING;
|
||||
crc_init(&hdlc->rxcrc);
|
||||
};;
|
||||
|
||||
void HDLC_transmitStart(struct HDLC *hdlc);
|
||||
void HDLC_transmitStart(struct HDLC *hdlc) {
|
||||
hdlc->writeByte(hdlc->DATASTART);
|
||||
crc_init(&hdlc->txcrc);
|
||||
}
|
||||
|
||||
void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data);
|
||||
void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data){
|
||||
escapeAndWriteByte(hdlc, data);
|
||||
crc_update(&hdlc->txcrc, data);
|
||||
}
|
||||
|
||||
void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len);
|
||||
void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len){
|
||||
const uint8_t* data = (const uint8_t*)vdata;
|
||||
while(len)
|
||||
{
|
||||
HDLC_transmitByte(hdlc, *data);
|
||||
++data;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
|
||||
void HDLC_transmitEnd(struct HDLC *hdlc);
|
||||
void HDLC_transmitEnd(struct HDLC *hdlc){
|
||||
crc_final(&hdlc->txcrc);
|
||||
for(int i = 0; i < hdlc->txcrc.size; ++i)
|
||||
escapeAndWriteByte(hdlc, hdlc->txcrc.crc);
|
||||
|
||||
hdlc->writeByte(hdlc->DATASTART);
|
||||
}
|
||||
|
||||
void HDLC_transmitBlock(struct HDLC* hdlc, const void* vdata, uint16_t len){
|
||||
HDLC_transmitStart(hdlc);
|
||||
HDLC_transmitBytes(hdlc, vdata, len);
|
||||
HDLC_transmitEnd(hdlc);
|
||||
}
|
||||
|
||||
uint16_t HDLC_receive(struct HDLC* hdlc);
|
||||
uint16_t HDLC_receive(struct HDLC* hdlc){
|
||||
int16_t c = hdlc->readByte();
|
||||
if(c == -1)
|
||||
return 0U;
|
||||
|
||||
if(hdlc->status >= OK)
|
||||
HDLC_init(hdlc);
|
||||
|
||||
uint16_t retv = 0U;
|
||||
|
||||
if(c == hdlc->DATASTART)
|
||||
{
|
||||
if(hdlc->status == RECEIVING && hdlc->len != 0U)
|
||||
{
|
||||
if(crc_good(&hdlc->rxcrc))
|
||||
{
|
||||
hdlc->status = OK;
|
||||
hdlc->len -= hdlc->rxcrc.size;
|
||||
retv = hdlc->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdlc->status = CRCERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HDLC_init(hdlc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hdlc->status == ESCAPED)
|
||||
{
|
||||
hdlc->status = RECEIVING;
|
||||
|
||||
c ^= hdlc->DATAINVBIT;
|
||||
crc_update(&hdlc->rxcrc, c);
|
||||
if (hdlc->len < hdlc->RXBFLEN)
|
||||
hdlc->data[hdlc->len] = c;
|
||||
++hdlc->len;
|
||||
}
|
||||
else if(c != hdlc->DATAESCAPE)
|
||||
{
|
||||
crc_update(&hdlc->rxcrc, c);
|
||||
if(hdlc->len < hdlc->RXBFLEN)
|
||||
hdlc->data[hdlc->len] = c;
|
||||
++hdlc->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdlc->status = ESCAPED;
|
||||
}
|
||||
}
|
||||
|
||||
return retv;
|
||||
}
|
||||
uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]);
|
||||
uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]){
|
||||
const uint16_t datalen = (hdlc->len > hdlc->RXBFLEN) ? hdlc->RXBFLEN : hdlc->len;
|
||||
memcpy(buff, hdlc->data, datalen);
|
||||
return datalen;
|
||||
}
|
||||
uint16_t HDLC_copyReceivedMessage2(const struct HDLC* hdlc, uint8_t* buff, uint16_t pos, uint16_t num);
|
||||
|
||||
#endif /* HDLC_H_ */
|
78
hdlc/hdlc_frame.c
Normal file
78
hdlc/hdlc_frame.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include "hdlc_frame.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define START_FLAG 0x7E
|
||||
#define END_FLAG 0x7E
|
||||
#define ESCAPE_FLAG 0x7D
|
||||
#define ESCAPE_XOR 0x20
|
||||
|
||||
void initialize_frame(HDLCFrame* frame, uint8_t address, uint8_t control, uint8_t* data, size_t data_length) {
|
||||
frame->address = address;
|
||||
frame->control = control;
|
||||
frame->data = data;
|
||||
frame->data_length = data_length;
|
||||
}
|
||||
|
||||
uint16_t calculate_fcs(HDLCFrame* frame) {
|
||||
uint16_t fcs = 0xFFFF;
|
||||
uint8_t* data_bytes = malloc(frame->data_length + 2);
|
||||
data_bytes[0] = frame->address;
|
||||
data_bytes[1] = frame->control;
|
||||
|
||||
for (size_t i = 0; i < frame->data_length; i++) {
|
||||
data_bytes[i + 2] = frame->data[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < frame->data_length + 2; i++) {
|
||||
uint8_t byte = data_bytes[i];
|
||||
fcs = (fcs >> 8) ^ (fcs << 8) ^ byte;
|
||||
fcs &= 0xFFFF;
|
||||
}
|
||||
|
||||
free(data_bytes);
|
||||
return fcs;
|
||||
}
|
||||
|
||||
void create_frame(HDLCFrame* frame, uint8_t** frame_data, size_t* frame_length) {
|
||||
*frame_length = 4 + frame->data_length;
|
||||
*frame_data = malloc(*frame_length);
|
||||
(*frame_data)[0] = START_FLAG;
|
||||
(*frame_data)[1] = frame->address;
|
||||
(*frame_data)[2] = frame->control;
|
||||
|
||||
size_t index = 3;
|
||||
for (size_t i = 0; i < frame->data_length; i++) {
|
||||
uint8_t byte = frame->data[i];
|
||||
if (byte == START_FLAG || byte == END_FLAG || byte == ESCAPE_FLAG) {
|
||||
(*frame_data)[index++] = ESCAPE_FLAG;
|
||||
(*frame_data)[index++] = byte ^ ESCAPE_XOR;
|
||||
} else {
|
||||
(*frame_data)[index++] = byte;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t fcs = calculate_fcs(frame);
|
||||
(*frame_data)[index++] = fcs & 0xFF;
|
||||
(*frame_data)[index] = END_FLAG;
|
||||
}
|
||||
|
||||
HDLCFrame* create_u_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length) {
|
||||
HDLCFrame* frame = malloc(sizeof(HDLCFrame));
|
||||
initialize_frame(frame, address, control, data, data_length);
|
||||
return frame;
|
||||
}
|
||||
|
||||
HDLCFrame* create_s_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length, uint8_t receive_sequence_number, uint8_t send_sequence_number) {
|
||||
HDLCFrame* frame = malloc(sizeof(HDLCFrame));
|
||||
initialize_frame(frame, address, control, data, data_length);
|
||||
frame->control |= (receive_sequence_number << 2) & 0xFC;
|
||||
frame->control |= (send_sequence_number << 1) & 0xFE;
|
||||
return frame;
|
||||
}
|
||||
|
||||
HDLCFrame* create_i_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length, uint8_t sequence_number) {
|
||||
HDLCFrame* frame = malloc(sizeof(HDLCFrame));
|
||||
initialize_frame(frame, address, control, data, data_length);
|
||||
frame->control |= (sequence_number << 1) & 0xFE;
|
||||
return frame;
|
||||
}
|
21
hdlc/hdlc_frame.h
Normal file
21
hdlc/hdlc_frame.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef HDLC_FRAME_H
|
||||
#define HDLC_FRAME_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t address;
|
||||
uint8_t control;
|
||||
uint8_t* data;
|
||||
size_t data_length;
|
||||
} HDLCFrame;
|
||||
|
||||
void initialize_frame(HDLCFrame* frame, uint8_t address, uint8_t control, uint8_t* data, size_t data_length);
|
||||
uint16_t calculate_fcs(HDLCFrame* frame);
|
||||
void create_frame(HDLCFrame* frame, uint8_t** frame_data, size_t* frame_length);
|
||||
|
||||
HDLCFrame* create_u_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length);
|
||||
HDLCFrame* create_s_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length, uint8_t receive_sequence_number, uint8_t send_sequence_number);
|
||||
HDLCFrame* create_i_frame(uint8_t address, uint8_t control, uint8_t* data, size_t data_length, uint8_t sequence_number);
|
||||
|
||||
#endif
|
33
hdlc/main.c
33
hdlc/main.c
@ -1,33 +0,0 @@
|
||||
#include "hdlc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
struct HDLC hdlc;
|
||||
|
||||
void hdlc_sendMsg() {
|
||||
uint8_t msg[] = "Hello world!";
|
||||
HDLC_transmitBlock(&hdlc, msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void hdlc_receiveMsg() {
|
||||
int16_t resp = HDLC_receive(&hdlc);
|
||||
if(resp != 0U)
|
||||
{
|
||||
uint8_t buff[hdlc.RXBFLEN];
|
||||
uint16_t size = HDLC_copyReceivedMessage(&hdlc, buff);
|
||||
|
||||
printf("Msg[%u]=%s\n", size, buff);
|
||||
}
|
||||
}
|
||||
|
||||
//нужно указать 2 функции на чтение и запись байтов, чтобы работало
|
||||
int main(void)
|
||||
{
|
||||
HDLC_init(&hdlc);
|
||||
|
||||
hdlc_sendMsg();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
hdlc_receiveMsg();
|
||||
}
|
||||
}
|
47
hdlc/test_hdlc_frame.c
Normal file
47
hdlc/test_hdlc_frame.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "hdlc_frame.h"
|
||||
|
||||
void print_frame(uint8_t* frame_data, size_t frame_length) {
|
||||
printf("Сформированный кадр:\n");
|
||||
for (size_t i = 0; i < frame_length; i++) {
|
||||
printf("%02X ", frame_data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
uint8_t address = 0x01;
|
||||
uint8_t control = 0x02;
|
||||
uint8_t data[] = {0x10, 0x20, 0x30};
|
||||
size_t data_length = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
HDLCFrame* u_frame = create_u_frame(address, control, data, data_length);
|
||||
uint8_t* u_frame_data;
|
||||
size_t u_frame_length;
|
||||
create_frame(u_frame, &u_frame_data, &u_frame_length);
|
||||
print_frame(u_frame_data, u_frame_length);
|
||||
free(u_frame_data);
|
||||
free(u_frame);
|
||||
|
||||
uint8_t receive_sequence_number = 0x01;
|
||||
uint8_t send_sequence_number = 0x02;
|
||||
HDLCFrame* s_frame = create_s_frame(address, control, data, data_length, receive_sequence_number, send_sequence_number);
|
||||
uint8_t* s_frame_data;
|
||||
size_t s_frame_length;
|
||||
create_frame(s_frame, &s_frame_data, &s_frame_length);
|
||||
print_frame(s_frame_data, s_frame_length);
|
||||
free(s_frame_data);
|
||||
free(s_frame);
|
||||
|
||||
uint8_t sequence_number = 0x03;
|
||||
HDLCFrame* i_frame = create_i_frame(address, control, data, data_length, sequence_number);
|
||||
uint8_t* i_frame_data;
|
||||
size_t i_frame_length;
|
||||
create_frame(i_frame, &i_frame_data, &i_frame_length);
|
||||
print_frame(i_frame_data, i_frame_length);
|
||||
free(i_frame_data);
|
||||
free(i_frame);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user