diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..033bde8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/bin/test-kod-bez", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ], + "preLaunchTask": "CMake: build" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..660b946 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "files.associations": { + "worker_type.h": "c", + "main.h": "c", + "stdio.h": "c", + "stdint.h": "c", + "stdbool.h": "c", + "unistd.h": "c", + "stdlib.h": "c", + "time.h": "c", + "hdlc_type.h": "c", + "hdlc.h": "c", + "fifo_type.h": "c", + "chrono": "c", + "span": "c", + "worker.h": "c" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 18a2b6b..0b98859 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 4.1 FATAL_ERROR) -set(PROJECT_NAME testKodBez) +set(PROJECT_NAME test-kod-bez) 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 11) set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) add_executable(${PROJECT_NAME} ${SOURCE_DIR}/main.c) @@ -29,6 +29,9 @@ set(SOURCES ) target_include_directories(${PROJECT_NAME} PRIVATE ${HEADERS}) +# target_compile_definitions(${PROJECT_NAME} PRIVATE __USE_POSIX199309 __USE_ISOC11) +target_compile_definitions(${PROJECT_NAME} PRIVATE _POSIX_C_SOURCE=199309L _ISOC11_SOURCE) + 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 index 49d7e6d..8eb42d8 100644 --- a/src/fifo/fifo.c +++ b/src/fifo/fifo.c @@ -1 +1,2 @@ #include "fifo.h" + diff --git a/src/fifo/fifo.h b/src/fifo/fifo.h index 091dcc7..2684fa9 100644 --- a/src/fifo/fifo.h +++ b/src/fifo/fifo.h @@ -4,4 +4,5 @@ #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 index ca97fc7..fa14505 100644 --- a/src/fifo/fifo_type.h +++ b/src/fifo/fifo_type.h @@ -4,7 +4,7 @@ #include -// Структура FIFO +// Структура состояний FIFO typedef enum { FIFOS_empty = 0, FIFOS_ready, @@ -12,6 +12,7 @@ typedef enum { FIFOS_error } fifoState; +// Структура FIFO typedef struct { uint8_t data[8]; uint8_t pointer; diff --git a/src/hdlc/hdlc.c b/src/hdlc/hdlc.c index 30741dd..a62e065 100644 --- a/src/hdlc/hdlc.c +++ b/src/hdlc/hdlc.c @@ -2,40 +2,11 @@ #include "hdlc.h" #include "hdlc_type.h" -typedef enum { - HDLCCFT_info = 0, - HDLCCFT_control, - HDLCCFT_unnumbered, - HDLCCFT_undefined -} controlFieldType_e; + +int HDLC_printControlField (hdlcControlField16b_u field); -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) { +int HDLC_printControlField (hdlcControlField16b_u field) { printf ("HDLC: Printing fields:\n"); printf ("HDLC: .. Type:\n"); printf ("HDLC: .. Send sequence: %d\n", field.bits.sendSequence); @@ -46,8 +17,8 @@ int HDLC_printControlField (hdlcControlField16b_s field) { } -hdlcControlField16b_s HDLC_parseControlField (uint16_t value) { - hdlcControlField16b_s fieldUnion; +hdlcControlField16b_u HDLC_parseControlField (uint16_t value) { + hdlcControlField16b_u fieldUnion; // fieldUnion.value = TOOL_reverseBits16(value); fieldUnion.value = value; @@ -58,8 +29,8 @@ hdlcControlField16b_s HDLC_parseControlField (uint16_t value) { } -int HDLC_isControlFieldValid (uint16_t value) { - if ((HDLC_checkControlField != HDLCCFT_info) || (value == 0)) { +int HDLC_isControlFieldValid (uint16_t value) { + if ((value == 0xffff) || (value == 0)) { printf ("HDLC: Wrong control field:\n"); // Так как обрабатывается только вариант с информационным пакетом return -1; diff --git a/src/hdlc/hdlc.h b/src/hdlc/hdlc.h index 5ae1eab..7906e85 100644 --- a/src/hdlc/hdlc.h +++ b/src/hdlc/hdlc.h @@ -5,6 +5,7 @@ #include #include "hdlc_type.h" +// Cтруктура поля управления typedef union { struct __attribute__((packed)) { uint8_t receiveSequence : 7; @@ -13,10 +14,10 @@ typedef union { uint8_t type : 1; } bits; uint16_t value; -} hdlcControlField16b_s; +} hdlcControlField16b_u; int HDLC_isControlFieldValid (uint16_t value); -hdlcControlField16b_s HDLC_parseControlField (uint16_t value); +hdlcControlField16b_u 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 index a3c867e..46bc790 100644 --- a/src/hdlc/hdlc_type.h +++ b/src/hdlc/hdlc_type.h @@ -4,16 +4,22 @@ #include "fifo_type.h" -#define hdlcInfoLength 16 + +// ---------------------------------------------------------------------------------- +// Фрейм HDLC +// Флаг FD | Адрес | Управляющее поле | Информационное поле | FCS | Флаг FD +// 8 бит | кратно 8 | 8 или 16 бит | 0 или более байт | 16 бит | 8 бит +// ---------------------------------------------------------------------------------- + +#define HDLC_INFO_LENGTH 16 +#define HDLC_PACKET_LENGTH 2+2+HDLC_INFO_LENGTH+2 // Структура пакета (фрейма) HDLC -// Флаг FD | Адрес | Управляющее поле | Информационное поле | FCS | Флаг FD -// 8 бит | кратно 8 | 8 или 16 бит | 0 или более бит, кратно 8 | 16 бит | 8 бит typedef struct { const uint8_t flag; - const uint16_t address; + uint16_t address; uint16_t control; - uint8_t info[hdlcInfoLength]; + uint8_t info[HDLC_INFO_LENGTH]; uint16_t fcs; // const uint8_t closeFlag; } hdlcPacket_s; diff --git a/src/main.c b/src/main.c index fb6451e..abe03a4 100644 --- a/src/main.c +++ b/src/main.c @@ -47,13 +47,13 @@ int main(void) { break; case OS_wait: - sleep (1); + TOOL_msleep(1000); break; default: printf("OS: Wrong state, going to first state"); bigLoopOsState = OS_first; - sleep (3); + TOOL_msleep(3000); printf("\033[2J\033[H"); break; } @@ -61,7 +61,7 @@ int main(void) { bigLoopOsState++; // Для контроля - sleep (1); + TOOL_msleep(100); } return 0; diff --git a/src/main.h b/src/main.h index 11f16f2..45cd698 100644 --- a/src/main.h +++ b/src/main.h @@ -6,7 +6,6 @@ #include #include #include -#include // Конфигурация static const uint16_t hdlcMasterAddress = 0b10000000; @@ -15,6 +14,7 @@ static const uint16_t hdlcSlaveAddress = 0b11000000; // Вспомогательные функции uint16_t CRC16_compute(uint8_t *data, size_t length); uint16_t TOOL_reverseBits16(uint16_t value); +void TOOL_msleep(long milliseconds); // Потоки ОС int WORK_master(void); diff --git a/src/tools.c b/src/tools.c index 9e97a3f..44d4eab 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1,6 +1,7 @@ // Файл с общими функциями и конфигурацией #include "main.h" +#include // Вычисление контрольной суммы CRC16 @@ -50,3 +51,17 @@ uint16_t TOOL_reverseBitsN(uint16_t value, uint8_t n) { return reversed; } + +void TOOL_msleep(long milliseconds) { + struct timespec ts; + ts.tv_sec = milliseconds / 1000; // Seconds part + ts.tv_nsec = (milliseconds % 1000) * 1000000; // Nanoseconds part + + // nanosleep can be interrupted by signals, so we loop if interrupted + while (nanosleep(&ts, &ts) == -1) { + // If interrupted, remaining time is in ts, so we continue sleeping + // unless an actual error occurred (other than EINTR) + // For simplicity, this example assumes EINTR is the only -1 cause. + } +} + diff --git a/src/worker/worker.c b/src/worker/worker.c index a661164..3cb5ec1 100644 --- a/src/worker/worker.c +++ b/src/worker/worker.c @@ -5,37 +5,22 @@ #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) { + printf("WORKX: .. Preparing package\n"); worker->packet->control = 0b0100110011110000; - WORK_prepareTestPackage(worker->packet->info, hdlcInfoLength); - // memcpy(packet->info, testInfo, hdlcInfoLength); - worker->packet->fcs = CRC16_compute(worker->packet->info, hdlcInfoLength); + WORK_fillBuffer8b(worker->packet->info, HDLC_INFO_LENGTH); + // memcpy(packet->info, testInfo, HDLC_INFO_LENGTH); + worker->packet->fcs = CRC16_compute(worker->packet->info, HDLC_INFO_LENGTH); 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) { + printf("WORKX: .. Sending package\n"); return 0; } @@ -43,32 +28,117 @@ int WORK_sendPackage(workerHost_s *worker) { // Ожидание пакета int WORK_waitPackage(workerHost_s *worker) { + printf("WORKX: .. Waiting for a package\n"); return 0; } int WORK_receivePackage(workerHost_s *worker) { + printf("WORKX: .. Receiving package\n"); + // Receiving in buffer + + WORK_testFill(worker->byteBuffer, WORK_BYTE_BUFFER_SIZE); + return 0; } int WORK_parsePackage(workerHost_s *worker) { + printf("WORKX: .. Parsing package\n"); + + uint8_t *first = NULL, *last = NULL; + // Поиск пакета в массиве + for (size_t i = 0; i < WORK_BYTE_BUFFER_SIZE; i++) { + if (worker->byteBuffer[i] == worker->packet->flag) { + if (!first) { + first = &worker->byteBuffer[i]; + first++; // Скипаем байт флага + } else if (!last) { + last = &worker->byteBuffer[i]; + last--; + } + } + } + + // Разбор пакета в структуру + if (first && last) { + if (last > first) { + size_t len = last - first; + // Так как может быть меньше в теории + if (len <= HDLC_PACKET_LENGTH) { + if (len > 2) { // Считываем адрес + worker->packet->address = ((uint16_t)*first << 8) | *(first+1); + first += 2; + } + if (len > 4) { // Считываем управляющее поле + worker->packet->control = ((uint16_t)*first << 8) | *(first+1); + first += 2; + } + if (len > 6) { // Считываем контрольную сумму + worker->packet->fcs = ((uint16_t)*(last-1) << 8) | *last; + last -= 2; + } + if ((len > 8) && (last > first)) { // Считываем информационный пакет + int j = 0; + // От переполнения + if (last-first >= HDLC_INFO_LENGTH) { + return -1; + } + + // Заполнение данными + for (uint8_t* i = first; i <= last; ++i) { + worker->packet->info[j] = *i; + j++; + } + + // Чистка хвоста + for (; j < HDLC_INFO_LENGTH; ++j) { + worker->packet->info[j] = 0; + } + } + } + } + } + + // HDLC_parseControlField (worker->packet->control); + // printf("WORKX: .. Info value: %d\n", field.value); + 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: .. Checking package\n"); + int res = 0; + res = HDLC_isControlFieldValid(worker->packet->control); + // Проверка поля управления + if (res != 0) { + return res; } + printf("WORKX: .. Package is info ...\n"); // Проверка контрольной суммы - printf("WORKX: Package checked\n"); + printf("WORKX: .. Package checked\n"); return 0; } + + +// Вызов функций обработчика хоста +int WORK_execute(int (*callback)(workerHost_s*), workerHost_s *worker) { + if (callback == NULL) { + printf("WORKX: .. Wrong object\n"); + return -1; + } + + int res = callback(worker); + + if (res != 0) { + printf("WORKX: .. Error\n"); + } + + return res; +} + diff --git a/src/worker/worker.h b/src/worker/worker.h index b76770f..263ff6e 100644 --- a/src/worker/worker.h +++ b/src/worker/worker.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "hdlc_type.h" @@ -19,9 +20,8 @@ typedef struct { bool isInitialized; } workerHost_s; -#define workByteBufferSize 128 +#define WORK_BYTE_BUFFER_SIZE 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); @@ -31,8 +31,11 @@ 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); +int WORK_fillBuffer8b(uint8_t *buffer, size_t size); +// tools +int WORK_printBlocks(workerHost_s *worker, uint8_t mode); +int WORK_testFill(uint8_t* buffer, size_t bufferSize); #endif //WORKER_H diff --git a/src/worker/worker_master.c b/src/worker/worker_master.c index 0d9d4b0..abc888f 100644 --- a/src/worker/worker_master.c +++ b/src/worker/worker_master.c @@ -7,103 +7,101 @@ static hdlcPacket_s hdlcMasterPacket = {hdlcFlag, hdlcMasterAddress}; static fifo_s hdlcMasterFifo; static workerHost_s hdlcMaster = {0}; +static uint8_t masterBuffer[WORK_BYTE_BUFFER_SIZE]; workerHost_s* WORK_masterInit () { if (!hdlcMaster.isInitialized) { - printf("WORKM: Starting master worker initialization\n"); + printf("WMAST: Starting master worker initialization\n"); hdlcMaster.packet = &hdlcMasterPacket; hdlcMaster.fifo = &hdlcMasterFifo; hdlcMaster.isInitialized = true; - printf("WORKM: Master initialization done\n"); + hdlcMaster.byteBuffer = masterBuffer; + printf("WMAST: Master initialization done\n"); WORK_printBlocks(&hdlcMaster, 3); return &hdlcMaster; } + // Ошибка в пакете, повторная инициализация + hdlcMaster.isInitialized = false; return NULL; } -static uint8_t masterBuffer[workByteBufferSize]; - - int WORK_master (void) { - static workerState_e masterState = WORKSTATE_first;; + static workerHostState_e masterState = WORKSTATE_first; + if (masterState >= WORKSTATE_last) { + masterState = WORKSTATE_first; + } - printf("WORKM: In master worker\n"); + printf("WMAST: In master worker\n"); int res = 0; switch (masterState) { case WORKSTATE_first: - masterState=WORKSTATE_initializing; + masterState = WORKSTATE_initializing; break; // Инициализация хоста case WORKSTATE_initializing: - printf("WORKM: Initializing\n"); if (WORK_masterInit() != NULL) { - masterState=WORKSTATE_preparingPackage; + masterState = WORKSTATE_preparingPackage; } break; // Подготовка пакета case WORKSTATE_preparingPackage: - printf("WORKM: Preparing package\n"); res = WORK_execute(WORK_preparePackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_sendingPackage; + masterState = WORKSTATE_sendingPackage; } break; // Отправка пакета case WORKSTATE_sendingPackage: - printf("WORKM: Sending package\n"); res = WORK_execute(WORK_sendPackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_waitingPackage; + masterState = WORKSTATE_waitingPackage; } break; // Ожидание ответа case WORKSTATE_waitingPackage: - printf("WORKM: Waiting package\n"); res = WORK_execute(WORK_waitPackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_receivingPackage; + masterState = WORKSTATE_receivingPackage; } break; // Получение пакета case WORKSTATE_receivingPackage: - printf("WORKM: Receiving package\n"); res = WORK_execute(WORK_receivePackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_parsingPackage; + masterState = WORKSTATE_parsingPackage; } break; // Парсинг пакета case WORKSTATE_parsingPackage: - printf("WORKM: Parsing package\n"); res = WORK_execute(WORK_parsePackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_checkingPackage; + masterState = WORKSTATE_checkingPackage; } break; // Проверка пакета case WORKSTATE_checkingPackage: - printf("WORKM: Checking package\n"); res = WORK_execute(WORK_checkPackage, &hdlcMaster); if (res == 0) { - masterState=WORKSTATE_last; + masterState = WORKSTATE_last; } break; // Цикл завершён, повторяем case WORKSTATE_last: - printf("WORKM: Job done. Starting from the beginning\n"); - masterState = WORKSTATE_preparingPackage; + printf("WMAST: Job done. Starting from the beginning\n"); + masterState = WORKSTATE_first; + // Либо переходить сразу на подготовку пакета break; } diff --git a/src/worker/worker_slave.c b/src/worker/worker_slave.c index d262b17..1851d5c 100644 --- a/src/worker/worker_slave.c +++ b/src/worker/worker_slave.c @@ -7,11 +7,11 @@ static workerHost_s hdlcSlave = {0}; workerHost_s* WORK_slaveInit () { if (!hdlcSlave.isInitialized) { - printf("WORKM: Starting slave worker initialization\n"); + printf("WSLAV: Starting slave worker initialization\n"); hdlcSlave.packet = &hdlcSlavePacket; hdlcSlave.fifo = &hdlcSlaveFifo; hdlcSlave.isInitialized = true; - printf("WORKS: Slave initialization done\n"); + printf("WSLAV Slave initialization done\n"); WORK_printBlocks(&hdlcSlave, 3); } @@ -21,7 +21,7 @@ workerHost_s* WORK_slaveInit () { int WORK_slave(void) { WORK_slaveInit(); - printf("WORKS: In slave worker\n"); + printf("WSLAV: 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 index 2b029aa..435751c 100644 --- a/src/worker/worker_tools.c +++ b/src/worker/worker_tools.c @@ -38,3 +38,30 @@ int WORK_printBlocks(workerHost_s *worker, uint8_t mode) { return 0; } + +// Тестовое заполнение буфера +int WORK_testFill(uint8_t* buffer, size_t bufferSize) { + static uint8_t testbuffer[50] = { + 0xaa,0xbb, + 0x7e, + 0xa1, 0xa2, + 0xc1, 0xc2, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xde, + 0xcc, 0xcd, + 0x7e + }; + for (int i = 0; i < 50; i++) { + buffer[i] = testbuffer[i]; + } + return 0; +} + + +// Заполнение массива +int WORK_fillBuffer8b(uint8_t *buffer, size_t size) { + memset(buffer, 0, size); + for (size_t i = 0; i < size; i++) { + buffer[i] = i; + } + return 0; +} \ No newline at end of file diff --git a/src/worker/worker_type.h b/src/worker/worker_type.h index d87edc1..97ef96f 100644 --- a/src/worker/worker_type.h +++ b/src/worker/worker_type.h @@ -2,16 +2,16 @@ #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 { +// WORKE_first = 0, +// WORKE_masterWorker, +// WORKE_slaveWorker, +// WORKE_wait, +// WORKE_last +// } workerState_e; -// Перечисление статусов хоста +// Перечисление статусов конкретного хоста typedef enum { WORKSTATE_first = 0, WORKSTATE_initializing,