From 14e71a3ccc8e79175e6489ce1fd2e6c34a89ce49 Mon Sep 17 00:00:00 2001 From: "ru.sadekov" Date: Fri, 24 Oct 2025 09:04:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=B0=20=D0=B2=20git?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CMakeLists.txt | 34 +++++++++++ src/fifo/fifo.c | 1 + src/fifo/fifo.h | 7 +++ src/fifo/fifo_type.h | 21 +++++++ src/hdlc/hdlc.c | 68 ++++++++++++++++++++++ src/hdlc/hdlc.h | 22 ++++++++ src/hdlc/hdlc_type.h | 24 ++++++++ src/main.c | 68 ++++++++++++++++++++++ src/main.h | 23 ++++++++ src/tools.c | 52 +++++++++++++++++ src/worker/worker.c | 74 ++++++++++++++++++++++++ src/worker/worker.h | 39 +++++++++++++ src/worker/worker_master.c | 112 +++++++++++++++++++++++++++++++++++++ src/worker/worker_slave.c | 27 +++++++++ src/worker/worker_tools.c | 40 +++++++++++++ src/worker/worker_type.h | 28 ++++++++++ 17 files changed, 641 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/fifo/fifo.c create mode 100644 src/fifo/fifo.h create mode 100644 src/fifo/fifo_type.h create mode 100644 src/hdlc/hdlc.c create mode 100644 src/hdlc/hdlc.h create mode 100644 src/hdlc/hdlc_type.h create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/tools.c create mode 100644 src/worker/worker.c create mode 100644 src/worker/worker.h create mode 100644 src/worker/worker_master.c create mode 100644 src/worker/worker_slave.c create mode 100644 src/worker/worker_tools.c create mode 100644 src/worker/worker_type.h diff --git a/.gitignore b/.gitignore index dc84959..d0c4049 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ +*.zip diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..18a2b6b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 4.1 FATAL_ERROR) + +set(PROJECT_NAME testKodBez) +set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) + +project(${PROJECT_NAME} LANGUAGES C) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_C_STANDARD_REQUIRED ON) + +add_executable(${PROJECT_NAME} ${SOURCE_DIR}/main.c) + +set(HEADERS + ${SOURCE_DIR} + ${SOURCE_DIR}/hdlc + ${SOURCE_DIR}/worker + ${SOURCE_DIR}/fifo +) + +set(SOURCES + ${SOURCE_DIR}/main.c + ${SOURCE_DIR}/tools.c + ${SOURCE_DIR}/hdlc/hdlc.c + ${SOURCE_DIR}/worker/worker.c + ${SOURCE_DIR}/worker/worker_tools.c + ${SOURCE_DIR}/worker/worker_master.c + ${SOURCE_DIR}/worker/worker_slave.c + ${SOURCE_DIR}/fifo/fifo.c +) + +target_include_directories(${PROJECT_NAME} PRIVATE ${HEADERS}) +target_sources(${PROJECT_NAME} PRIVATE ${SOURCES}) + +set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "bin") diff --git a/src/fifo/fifo.c b/src/fifo/fifo.c new file mode 100644 index 0000000..49d7e6d --- /dev/null +++ b/src/fifo/fifo.c @@ -0,0 +1 @@ +#include "fifo.h" diff --git a/src/fifo/fifo.h b/src/fifo/fifo.h new file mode 100644 index 0000000..091dcc7 --- /dev/null +++ b/src/fifo/fifo.h @@ -0,0 +1,7 @@ +#pragma once +#ifndef FIFO_H +#define FIFO_H + +#include "fifo_type.h" + +#endif // FIFO_H \ No newline at end of file diff --git a/src/fifo/fifo_type.h b/src/fifo/fifo_type.h new file mode 100644 index 0000000..ca97fc7 --- /dev/null +++ b/src/fifo/fifo_type.h @@ -0,0 +1,21 @@ +#pragma once +#ifndef FIFO_TYPE_H +#define FIFO_TYPE_H + +#include + +// Структура FIFO +typedef enum { + FIFOS_empty = 0, + FIFOS_ready, + FIFOS_full, + FIFOS_error +} fifoState; + +typedef struct { + uint8_t data[8]; + uint8_t pointer; + fifoState state; +} fifo_s; + +#endif // FIFO_TYPE_H \ No newline at end of file diff --git a/src/hdlc/hdlc.c b/src/hdlc/hdlc.c new file mode 100644 index 0000000..30741dd --- /dev/null +++ b/src/hdlc/hdlc.c @@ -0,0 +1,68 @@ +#include "main.h" +#include "hdlc.h" +#include "hdlc_type.h" + +typedef enum { + HDLCCFT_info = 0, + HDLCCFT_control, + HDLCCFT_unnumbered, + HDLCCFT_undefined +} controlFieldType_e; + + +controlFieldType_e HDLC_checkControlField (uint16_t value); +int HDLC_printControlField (hdlcControlField16b_s field); + + +controlFieldType_e HDLC_checkControlField (uint16_t value) { + controlFieldType_e controlFieldType; + // Определяем тип информационного кадра: + // 0b0... - информационный, + // 0b10... - управляющий, + // 0b11... - ненумерованный + + if (((value >> 7) & 1) == 0) { + controlFieldType = HDLCCFT_info; + } else { + if (((value >> 6) & 1) == 0) { + controlFieldType = HDLCCFT_control; + } else { + controlFieldType = HDLCCFT_unnumbered; + } + } + + return controlFieldType; +} + + +int HDLC_printControlField (hdlcControlField16b_s field) { + printf ("HDLC: Printing fields:\n"); + printf ("HDLC: .. Type:\n"); + printf ("HDLC: .. Send sequence: %d\n", field.bits.sendSequence); + printf ("HDLC: .. Poll/Final: %d\n", field.bits.pollFinal); + printf ("HDLC: .. Receive sequence: %d\n", field.bits.receiveSequence); + + return 0; +} + + +hdlcControlField16b_s HDLC_parseControlField (uint16_t value) { + hdlcControlField16b_s fieldUnion; + // fieldUnion.value = TOOL_reverseBits16(value); + fieldUnion.value = value; + + HDLC_printControlField(fieldUnion); + + return fieldUnion; + +} + + +int HDLC_isControlFieldValid (uint16_t value) { + if ((HDLC_checkControlField != HDLCCFT_info) || (value == 0)) { + printf ("HDLC: Wrong control field:\n"); + // Так как обрабатывается только вариант с информационным пакетом + return -1; + } + return 0; +} \ No newline at end of file diff --git a/src/hdlc/hdlc.h b/src/hdlc/hdlc.h new file mode 100644 index 0000000..5ae1eab --- /dev/null +++ b/src/hdlc/hdlc.h @@ -0,0 +1,22 @@ +#pragma once +#ifndef HDLC_H +#define HDLC_H + +#include +#include "hdlc_type.h" + +typedef union { + struct __attribute__((packed)) { + uint8_t receiveSequence : 7; + uint8_t pollFinal : 1; + uint8_t sendSequence : 7; + uint8_t type : 1; + } bits; + uint16_t value; +} hdlcControlField16b_s; + +int HDLC_isControlFieldValid (uint16_t value); +hdlcControlField16b_s HDLC_parseControlField (uint16_t value); + + +#endif // HDLC_H \ No newline at end of file diff --git a/src/hdlc/hdlc_type.h b/src/hdlc/hdlc_type.h new file mode 100644 index 0000000..a3c867e --- /dev/null +++ b/src/hdlc/hdlc_type.h @@ -0,0 +1,24 @@ +#pragma once +#ifndef HDLC_TYPE_H +#define HDLC_TYPE_H + +#include "fifo_type.h" + +#define hdlcInfoLength 16 + +// Структура пакета (фрейма) HDLC +// Флаг FD | Адрес | Управляющее поле | Информационное поле | FCS | Флаг FD +// 8 бит | кратно 8 | 8 или 16 бит | 0 или более бит, кратно 8 | 16 бит | 8 бит +typedef struct { + const uint8_t flag; + const uint16_t address; + uint16_t control; + uint8_t info[hdlcInfoLength]; + uint16_t fcs; + // const uint8_t closeFlag; +} hdlcPacket_s; + + +static const uint8_t hdlcFlag = 0b01111110; + +#endif // HDLC_TYPE_H \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..fb6451e --- /dev/null +++ b/src/main.c @@ -0,0 +1,68 @@ +#include "main.h" + +#if __cplusplus +#pragma message ("plus") +#else +#pragma message ("pure") +#endif + + +// Перечисление статусов машины состояния +enum bigLoopOsState_e { + OS_first = 0, + OS_masterWorker, + OS_slaveWorker, + OS_wait, + OS_last +} bigLoopOsState; + +// Текстовые надписи соответствующие статусам машины состояния +const char* bigLoopOsStateNames[OS_last] = { + "starting...", + "master worker", + "slave worker", + "waiting" +}; + + +// BIG LOOP OS +int main(void) { + bigLoopOsState = OS_first; + while(1) { + if (bigLoopOsState == OS_last) { + bigLoopOsState = OS_first; + } + + printf("OS: Current state is: %s\n", bigLoopOsStateNames[bigLoopOsState]); + switch (bigLoopOsState) { + case OS_first: + break; + + case OS_masterWorker: + WORK_master(); + break; + + case OS_slaveWorker: + WORK_slave(); + break; + + case OS_wait: + sleep (1); + break; + + default: + printf("OS: Wrong state, going to first state"); + bigLoopOsState = OS_first; + sleep (3); + printf("\033[2J\033[H"); + break; + } + + bigLoopOsState++; + + // Для контроля + sleep (1); + } + + return 0; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..11f16f2 --- /dev/null +++ b/src/main.h @@ -0,0 +1,23 @@ +#pragma once +#ifndef MAIN_H +#define MAIN_H + +#include +#include +#include +#include +#include + +// Конфигурация +static const uint16_t hdlcMasterAddress = 0b10000000; +static const uint16_t hdlcSlaveAddress = 0b11000000; + +// Вспомогательные функции +uint16_t CRC16_compute(uint8_t *data, size_t length); +uint16_t TOOL_reverseBits16(uint16_t value); + +// Потоки ОС +int WORK_master(void); +int WORK_slave(void); + +#endif //MAIN_H \ No newline at end of file diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..9e97a3f --- /dev/null +++ b/src/tools.c @@ -0,0 +1,52 @@ +// Файл с общими функциями и конфигурацией + +#include "main.h" + + +// Вычисление контрольной суммы CRC16 +uint16_t CRC16_compute(uint8_t *data, size_t length) { + const uint16_t CRC16_poly = 0x8005; + const uint16_t CRC16_initVal = 0xffff; + + uint16_t crc = CRC16_initVal; + size_t i, j; + + for (i = 0; i < length; i++) { + crc ^= (uint16_t)data[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x0001) != 0) { + crc = (crc >> 1) ^ CRC16_poly; + } else { + crc >>= 1; + } + } + } + + return crc; +} + + +uint16_t TOOL_reverseBits16(uint16_t value) { + uint16_t reversed = 0; + for (int i = 0; i < 16; i++) { + if ((value >> i) & 1) { + reversed |= (1 << (15 - i)); + } + } + return reversed; +} + +uint16_t TOOL_reverseBitsN(uint16_t value, uint8_t n) { + if ((n > 15) || (n < 2)) { + return -1; + } + + uint16_t reversed = 0; + for (int i = 0; i < n; i++) { + if ((value >> i) & 1) { + reversed |= (1 << (n - 1 - i)); + } + } + return reversed; +} + diff --git a/src/worker/worker.c b/src/worker/worker.c new file mode 100644 index 0000000..a661164 --- /dev/null +++ b/src/worker/worker.c @@ -0,0 +1,74 @@ +#include +#include "main.h" +#include "worker.h" + +#include "hdlc.h" +#include "fifo.h" + +int WORK_prepareTestPackage(uint8_t *buffer, size_t size) { + memset(buffer, 0, size); + for (size_t i = 0; i < size; i++) { + buffer[i] = i; + } + return 0; +} + + +// Подготовка пакета для отправки +int WORK_preparePackage(workerHost_s *worker) { + worker->packet->control = 0b0100110011110000; + WORK_prepareTestPackage(worker->packet->info, hdlcInfoLength); + // memcpy(packet->info, testInfo, hdlcInfoLength); + worker->packet->fcs = CRC16_compute(worker->packet->info, hdlcInfoLength); + return 0; + +} + + +int WORK_execute(int (*callback)(workerHost_s*), workerHost_s *worker) { + if (callback == NULL) { + return -1; + } + int res = callback(worker); + return res; +} + + +// Отправка пакета +int WORK_sendPackage(workerHost_s *worker) { + + return 0; +} + + +// Ожидание пакета +int WORK_waitPackage(workerHost_s *worker) { + return 0; +} + + +int WORK_receivePackage(workerHost_s *worker) { + return 0; +} + + +int WORK_parsePackage(workerHost_s *worker) { + return 0; +} + + +int WORK_checkPackage(workerHost_s *worker) { + // Проверка поля управления + if (HDLC_isControlFieldValid(worker->packet->control)){ + printf("WORKX: Package is info. Parsing...\n"); + hdlcControlField16b_s field = HDLC_parseControlField (worker->packet->control); + printf("WORKX: Package has been parsed...\n"); + + } + + // Проверка контрольной суммы + + printf("WORKX: Package checked\n"); + return 0; +} + diff --git a/src/worker/worker.h b/src/worker/worker.h new file mode 100644 index 0000000..b76770f --- /dev/null +++ b/src/worker/worker.h @@ -0,0 +1,39 @@ +#pragma once +#ifndef WORKER_H +#define WORKER_H + +#include +#include +#include +#include + +#include "hdlc_type.h" + +#include "fifo_type.h" + +// Структура устройства +typedef struct { + hdlcPacket_s *packet; + fifo_s *fifo; + uint8_t *byteBuffer; + bool isInitialized; +} workerHost_s; + +#define workByteBufferSize 128 + +int WORK_printBlocks(workerHost_s *worker, uint8_t mode); +int WORK_execute(int (*callback)(workerHost_s*), workerHost_s *worker); + +int WORK_preparePackage(workerHost_s *worker); +int WORK_sendPackage(workerHost_s *worker); +int WORK_waitPackage(workerHost_s *worker); +int WORK_receivePackage(workerHost_s *worker); +int WORK_checkPackage(workerHost_s *worker); +int WORK_parsePackage(workerHost_s *worker); + +int WORK_prepareTestPackage(uint8_t *buffer, size_t size); + + +#endif //WORKER_H + + diff --git a/src/worker/worker_master.c b/src/worker/worker_master.c new file mode 100644 index 0000000..0d9d4b0 --- /dev/null +++ b/src/worker/worker_master.c @@ -0,0 +1,112 @@ +#include "main.h" +#include "worker.h" +#include "worker_type.h" + +#include + +static hdlcPacket_s hdlcMasterPacket = {hdlcFlag, hdlcMasterAddress}; +static fifo_s hdlcMasterFifo; +static workerHost_s hdlcMaster = {0}; + +workerHost_s* WORK_masterInit () { + if (!hdlcMaster.isInitialized) { + printf("WORKM: Starting master worker initialization\n"); + hdlcMaster.packet = &hdlcMasterPacket; + hdlcMaster.fifo = &hdlcMasterFifo; + hdlcMaster.isInitialized = true; + printf("WORKM: Master initialization done\n"); + WORK_printBlocks(&hdlcMaster, 3); + + return &hdlcMaster; + } + return NULL; +} + + +static uint8_t masterBuffer[workByteBufferSize]; + + +int WORK_master (void) { + static workerState_e masterState = WORKSTATE_first;; + + printf("WORKM: In master worker\n"); + + int res = 0; + + switch (masterState) { + case WORKSTATE_first: + masterState=WORKSTATE_initializing; + break; + + // Инициализация хоста + case WORKSTATE_initializing: + printf("WORKM: Initializing\n"); + if (WORK_masterInit() != NULL) { + masterState=WORKSTATE_preparingPackage; + } + break; + + // Подготовка пакета + case WORKSTATE_preparingPackage: + printf("WORKM: Preparing package\n"); + res = WORK_execute(WORK_preparePackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_sendingPackage; + } + break; + + // Отправка пакета + case WORKSTATE_sendingPackage: + printf("WORKM: Sending package\n"); + res = WORK_execute(WORK_sendPackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_waitingPackage; + } + break; + + // Ожидание ответа + case WORKSTATE_waitingPackage: + printf("WORKM: Waiting package\n"); + res = WORK_execute(WORK_waitPackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_receivingPackage; + } + break; + + // Получение пакета + case WORKSTATE_receivingPackage: + printf("WORKM: Receiving package\n"); + res = WORK_execute(WORK_receivePackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_parsingPackage; + } + break; + + // Парсинг пакета + case WORKSTATE_parsingPackage: + printf("WORKM: Parsing package\n"); + res = WORK_execute(WORK_parsePackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_checkingPackage; + } + break; + + // Проверка пакета + case WORKSTATE_checkingPackage: + printf("WORKM: Checking package\n"); + res = WORK_execute(WORK_checkPackage, &hdlcMaster); + if (res == 0) { + masterState=WORKSTATE_last; + } + break; + + // Цикл завершён, повторяем + case WORKSTATE_last: + printf("WORKM: Job done. Starting from the beginning\n"); + masterState = WORKSTATE_preparingPackage; + break; + } + + return 0; +} + diff --git a/src/worker/worker_slave.c b/src/worker/worker_slave.c new file mode 100644 index 0000000..d262b17 --- /dev/null +++ b/src/worker/worker_slave.c @@ -0,0 +1,27 @@ +#include "main.h" +#include "worker.h" + +static hdlcPacket_s hdlcSlavePacket = {hdlcFlag, hdlcSlaveAddress}; +static fifo_s hdlcSlaveFifo; +static workerHost_s hdlcSlave = {0}; + +workerHost_s* WORK_slaveInit () { + if (!hdlcSlave.isInitialized) { + printf("WORKM: Starting slave worker initialization\n"); + hdlcSlave.packet = &hdlcSlavePacket; + hdlcSlave.fifo = &hdlcSlaveFifo; + hdlcSlave.isInitialized = true; + printf("WORKS: Slave initialization done\n"); + WORK_printBlocks(&hdlcSlave, 3); + } + + return &hdlcSlave; +} + + +int WORK_slave(void) { + WORK_slaveInit(); + printf("WORKS: In slave worker\n"); + + return 0; +} \ No newline at end of file diff --git a/src/worker/worker_tools.c b/src/worker/worker_tools.c new file mode 100644 index 0000000..2b029aa --- /dev/null +++ b/src/worker/worker_tools.c @@ -0,0 +1,40 @@ +#include "worker.h" + + +// Параметрический вывод пакета worker +int WORK_printBlocks(workerHost_s *worker, uint8_t mode) { + if (worker == NULL) { + return -1; + } + + if (mode > 0) { + printf("TOOL: Packet consists of several units:\n"); + } + + // Вывод содержимого пакета + if (mode & 1) { + printf("TOOL: .. Packet:\n"); + printf("TOOL: .... Address: %d \n", worker->packet->address); + printf("TOOL: .... Flag: %d \n", worker->packet->flag); + printf("TOOL: .... Conrol Field: %d \n", worker->packet->control); + printf("TOOL: .... Info Field: %d \n", worker->packet->info); + printf("TOOL: .... FCS: %d \n", worker->packet->fcs); + } + + // Вывод содержимого буфера fifo + if (mode & 3) { + size_t size = sizeof(worker->fifo->data) / sizeof(worker->fifo->data[0]); + + printf("TOOL: .. FIFO:\n"); + printf("TOOL: .... Data (%d items): ", size); + for (size_t i = 0; i < size; i++) { + printf("%02X ", worker->fifo->data[i]); + } + printf("\n"); + + printf("TOOL: .. Pointer: %d ", worker->fifo->pointer); + } + + return 0; +} + diff --git a/src/worker/worker_type.h b/src/worker/worker_type.h new file mode 100644 index 0000000..d87edc1 --- /dev/null +++ b/src/worker/worker_type.h @@ -0,0 +1,28 @@ +#pragma once +#ifndef WORKER_TYPE_H +#define WORKER_TYPE_H + +// Перечисление статусов машины состояния +typedef enum { + WORKE_first = 0, + WORKE_masterWorker, + WORKE_slaveWorker, + WORKE_wait, + WORKE_last +} workerState_e; + +// Перечисление статусов хоста +typedef enum { + WORKSTATE_first = 0, + WORKSTATE_initializing, + WORKSTATE_preparingPackage, + WORKSTATE_sendingPackage, + WORKSTATE_waitingPackage, + WORKSTATE_receivingPackage, + WORKSTATE_checkingPackage, + WORKSTATE_parsingPackage, + WORKSTATE_last +} workerHostState_e; + + +#endif // WORKER_TYPE_H \ No newline at end of file