diff --git a/.vscode/settings.json b/.vscode/settings.json index a5aeafb..0938b59 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,9 @@ "string.h": "c", "*.ipp": "c", "cstring": "c", - "stddef.h": "c" + "stddef.h": "c", + "coroutine": "c", + "filo.h": "c", + "filo_type.h": "c" } } \ No newline at end of file diff --git a/src/fifo/fifo.c b/src/fifo/fifo.c index 255b712..f6b7b01 100644 --- a/src/fifo/fifo.c +++ b/src/fifo/fifo.c @@ -7,8 +7,6 @@ // FIFO ERROR // } -int FIFO_isUsable(fifo_s* fifo); - // Инициализация fifo int FIFO_init(fifo_s* fifo) { if (fifo != NULL) { @@ -16,6 +14,8 @@ int FIFO_init(fifo_s* fifo) { fifo->data[i] = 0; } fifo->head = 0; + fifo->tail = 0; + fifo->count = 0; fifo->state = FIFOS_empty; fifo->isInitialized = 1; if (FIFO_isUsable(fifo) == 0) { @@ -30,14 +30,14 @@ int FIFO_init(fifo_s* fifo) { int FIFO_put(fifo_s* fifo, uint8_t data) { if (FIFO_isUsable(fifo) == 0) { // Не заполнено if ((fifo->state == FIFOS_empty) || (fifo->state == FIFOS_ready)) { - fifo->data[fifo->head] = data; - - if (fifo->head < FIFO_DATA_SIZE-1) { - fifo->head++; + fifo->data[fifo->tail] = data; + fifo->tail = (fifo->tail + 1) % FIFO_DATA_SIZE; + if (fifo->count < FIFO_DATA_SIZE - 1) { + fifo->count++; fifo->state = FIFOS_ready; } else { - fifo->head = FIFO_DATA_SIZE-1; - fifo->state = FIFOS_full; + fifo->count = FIFO_DATA_SIZE - 1; + fifo->state = FIFOS_full; } return 0; } @@ -50,17 +50,20 @@ int FIFO_put(fifo_s* fifo, uint8_t data) { int FIFO_get(fifo_s* fifo, uint8_t *data) { if (FIFO_isUsable(fifo) == 0) { if ((fifo->state == FIFOS_full) || (fifo->state == FIFOS_ready)) { - *data = fifo->data[fifo->head-1]; - fifo->data[fifo->head-1] = 0; - if (fifo->head > 1) { - fifo->head--; + *data = fifo->data[fifo->head]; + fifo->data[fifo->head] = 0; + fifo->head = (fifo->head + 1) % FIFO_DATA_SIZE; + if (fifo->count > 1) { + fifo->count--; fifo->state = FIFOS_ready; } else { - fifo->head = 0; + fifo->count = 0; fifo->state = FIFOS_empty; + return 1; } return 0; } + return 1; } return -1; } diff --git a/src/fifo/fifo.h b/src/fifo/fifo.h index d3a038d..6ac37d2 100644 --- a/src/fifo/fifo.h +++ b/src/fifo/fifo.h @@ -12,6 +12,8 @@ typedef struct { uint8_t data[FIFO_DATA_SIZE]; uint8_t head; + uint8_t tail; + uint8_t count; fifoState_e state; uint8_t isInitialized; } fifo_s; diff --git a/src/filo/filo.c b/src/filo/filo.c new file mode 100644 index 0000000..c30943c --- /dev/null +++ b/src/filo/filo.c @@ -0,0 +1,90 @@ +#include "filo.h" +#include "stdio.h" + +// if (FILO_get(filo, byte) == 0) { +// OK +// } else { +// FILO ERROR +// } + +int FILO_isUsable(filo_s* filo); + +// Инициализация filo +int FILO_init(filo_s* filo) { + if (filo != NULL) { + for (size_t i = 0; i < FILO_DATA_SIZE; ++i) { + filo->data[i] = 0; + } + filo->head = 0; + filo->state = FILOS_empty; + filo->isInitialized = 1; + if (FILO_isUsable(filo) == 0) { + return 0; + } + } + return -1; +} + + +// Заполнение filo +int FILO_put(filo_s* filo, uint8_t data) { + if (FILO_isUsable(filo) == 0) { // Не заполнено + if ((filo->state == FILOS_empty) || (filo->state == FILOS_ready)) { + filo->data[filo->head] = data; + + if (filo->head < FILO_DATA_SIZE-1) { + filo->head++; + filo->state = FILOS_ready; + } else { + filo->head = FILO_DATA_SIZE-1; + filo->state = FILOS_full; + } + return 0; + } + } + return -1; +} + + +// Получение из filo +int FILO_get(filo_s* filo, uint8_t *data) { + if (FILO_isUsable(filo) == 0) { + if ((filo->state == FILOS_full) || (filo->state == FILOS_ready)) { + *data = filo->data[filo->head-1]; + filo->data[filo->head-1] = 0; + if (filo->head > 1) { + filo->head--; + filo->state = FILOS_ready; + } else { + filo->head = 0; + filo->state = FILOS_empty; + } + return 0; + } + } + return -1; +} + + +int FILO_print(filo_s* filo) { + if (FILO_isUsable(filo) == 0) { + printf("FILO: "); + for (size_t i = 0; i < FILO_DATA_SIZE; i++) { + printf("%d", filo->data[i]); + } + printf("\n"); + return 0; + } + return -1; +} + + +// Проверка доступности filo +int FILO_isUsable(filo_s* filo) { + if (filo != NULL) { + if (filo->isInitialized == 1) { + return 0; + } + } + return -1; +} \ No newline at end of file diff --git a/src/filo/filo.h b/src/filo/filo.h new file mode 100644 index 0000000..d5a93c8 --- /dev/null +++ b/src/filo/filo.h @@ -0,0 +1,27 @@ +#pragma once +#ifndef FILO_H +#define FILO_H + +#include "filo_type.h" +#include + +// Размер FILO +#define FILO_DATA_SIZE 8 + +// Структура FILO +typedef struct { + uint8_t data[FILO_DATA_SIZE]; + uint8_t head; + filoState_e state; + uint8_t isInitialized; +} filo_s; + + +// Функции FILO +int FILO_init(filo_s* filo); +int FILO_put(filo_s* filo, uint8_t data); +int FILO_get(filo_s* filo, uint8_t *data); +int FILO_print(filo_s* filo); +int FILO_isUsable(filo_s* filo); + +#endif // FILO_H \ No newline at end of file diff --git a/src/filo/filo_type.h b/src/filo/filo_type.h new file mode 100644 index 0000000..c0a79e1 --- /dev/null +++ b/src/filo/filo_type.h @@ -0,0 +1,16 @@ +#pragma once +#ifndef FILO_TYPE_H +#define FILO_TYPE_H + +#include + +// Структура состояний FILO +typedef enum { + FILOS_empty = 0, + FILOS_ready, + FILOS_full, + FILOS_error +} filoState_e; + + +#endif // FILO_TYPE_H \ No newline at end of file diff --git a/src/main.c b/src/main.c index 24e24ed..1e36554 100644 --- a/src/main.c +++ b/src/main.c @@ -11,36 +11,42 @@ enum bigLoopOsState_e { // Текстовые надписи соответствующие статусам машины состояния const char* bigLoopOsStateNames[OS_last] = { - "starting...", + "starting", "master worker", "slave worker", - "waiting" + "idle" }; // BIG LOOP OS int main(void) { + // while(true){WORK_master();TOOL_msleep(1000);} + bigLoopOsState = OS_first; while(true) { - if (bigLoopOsState == OS_last) { - bigLoopOsState = OS_first; + if (bigLoopOsState >= OS_last) { + bigLoopOsState = OS_masterWorker; } printf("OS: Current state is: %s\n", bigLoopOsStateNames[bigLoopOsState]); switch (bigLoopOsState) { case OS_first: + printf("\n\n"); break; case OS_masterWorker: WORK_master(); + printf("\n\n"); break; case OS_slaveWorker: WORK_slave(); + printf("\n\n"); break; case OS_wait: TOOL_msleep(1000); + printf("\n\n"); break; default: diff --git a/src/main.h b/src/main.h index a0e4fa5..ee5d20c 100644 --- a/src/main.h +++ b/src/main.h @@ -12,6 +12,7 @@ // Конфигурация static const uint16_t hdlcMasterAddress = 0b10000000; static const uint16_t hdlcSlaveAddress = 0b11000000; +static const uint16_t xorByte = 0xaf; // Вспомогательные функции uint16_t CRC16_compute(uint8_t *data, size_t length); diff --git a/src/worker/worker.c b/src/worker/worker.c index 722e08a..0ce5157 100644 --- a/src/worker/worker.c +++ b/src/worker/worker.c @@ -6,13 +6,45 @@ #include "fifo.h" +workerHost_s* WORK_workerInit (workerHost_s* worker, + hdlcPacket_s* packet, fifo_s* fifo, uint8_t* buffer) { + if (!worker->isInitialized) { + printf("WORKX: Starting master worker initialization\n"); + worker->packet = packet; + worker->fifo = fifo; + worker->isInitialized = true; + worker->byteBuffer = buffer; + + FIFO_init(worker->fifo); + + if (DO_UNIT_TESTS){WORK_testFifo(worker->fifo);} + + printf("WORKX: Master initialization done\n"); + WORK_printBlocks(worker, 3); + + return worker; + } + + // Ошибка в пакете, повторная инициализация + worker->isInitialized = false; + return NULL; + +} + + +int WORK_waitClient (fifo_s *clientFifo) { + printf("WORKX: .. Waiting for a client\n"); + if (FIFO_isUsable(clientFifo) == 0) { + return 0; + } + return -1; +} + + // Подготовка пакета для отправки int WORK_preparePackage(workerHost_s *worker) { printf("WORKX: .. Preparing package\n"); - worker->packet->control = 0b0100110011110000; - WORK_fillBuffer8b(worker->packet->info, HDLC_INFO_LENGTH); - worker->packet->fcs = CRC16_compute(worker->packet->info, HDLC_INFO_LENGTH); - + // Перемещение структуры в массив на передачу size_t structSize = sizeof(hdlcPacket_s); uint8_t tmpPtr = 0; @@ -33,30 +65,67 @@ int WORK_preparePackage(workerHost_s *worker) { // Отправка пакета int WORK_sendPackage(workerHost_s *worker) { printf("WORKX: .. Sending package\n"); - + if (FIFO_isUsable(worker->fifo) == 0) { + if (worker->fifo->count > 0) { + FIFO_put(worker->fifo, &worker->byteBuffer[worker->byteBufferHead]); + if (worker->byteBufferHead < WORK_BYTE_BUFFER_SIZE) { + worker->byteBufferHead++; + } else { + worker->byteBufferHead = 0; + return -2; + } + } else { + // fifo опустошился + return 1; + } + return 0; + } return 0; } // Ожидание пакета -int WORK_waitPackage(workerHost_s *worker) { +inline int WORK_waitPackage(workerHost_s *worker) { printf("WORKX: .. Waiting for a package\n"); if (FIFO_isUsable(worker->fifo) == 0) { + if (worker->fifo->count > 0) { + FIFO_get(worker->fifo, &worker->byteBuffer[worker->byteBufferHead]); + if (worker->byteBufferHead < WORK_BYTE_BUFFER_SIZE) { + worker->byteBufferHead++; + } else { + worker->byteBufferHead = 0; + return -2; + } + } else { + return 1; + } return 0; } return -1; } -int WORK_receivePackage(workerHost_s *worker) { +inline int WORK_receivePackage(workerHost_s *worker) { printf("WORKX: .. Receiving package\n"); // Receiving in buffer - if (DO_UNIT_TESTS){WORK_testFill(worker->byteBuffer, WORK_BYTE_BUFFER_SIZE); return 0;} - - uint8_t buf; - if (FIFO_get(worker->fifo, &buf) == 0) { - // return 0; + static int fifoEmptyCounter = 0; + static int bufPtr = 0; + uint8_t buf = 0; + int res = FIFO_get(worker->fifo, &buf); + // Байт из fifo забран + if (res == 0) { + fifoEmptyCounter = 0; + bufPtr++; + } + // fifo опустошён + if (res == 1) { + fifoEmptyCounter++; + } + if (fifoEmptyCounter > 3) { + fifoEmptyCounter = 0; + bufPtr = 0; + return 0; } return -1; @@ -140,14 +209,24 @@ int WORK_parsePackage(workerHost_s *worker) { } printf("\n"); - return 0; + // Проверка контрольной суммы разобранного пакета + uint16_t crc = worker->packet->fcs; + worker->packet->fcs = 0; + if (CRC16_compute((uint8_t*) worker->packet, sizeof(workerHost_s)) == crc) { + printf("WORKX: .. CRC OK"); + } else { + printf("WORKX: .. WRONG CRC"); + return -1; + } + + return -1; } int WORK_checkPackage(workerHost_s *worker) { printf("WORKX: .. Checking package\n"); int res = 0; - + return 0; res = HDLC_isControlFieldValid(worker->packet->control); // Проверка поля управления if (res != 0) { diff --git a/src/worker/worker.h b/src/worker/worker.h index 48beb7f..1d7fcaf 100644 --- a/src/worker/worker.h +++ b/src/worker/worker.h @@ -17,13 +17,18 @@ typedef struct { hdlcPacket_s *packet; fifo_s *fifo; uint8_t *byteBuffer; + uint8_t byteBufferHead; bool isInitialized; } workerHost_s; #define WORK_BYTE_BUFFER_SIZE 128 +workerHost_s* WORK_workerInit (workerHost_s* worker, + hdlcPacket_s* packet, fifo_s* fifo, uint8_t* buffer); + int WORK_execute(int (*callback)(workerHost_s*), workerHost_s *worker); +int WORK_waitClient (fifo_s *clientFifo); int WORK_preparePackage(workerHost_s *worker); int WORK_sendPackage(workerHost_s *worker); int WORK_waitPackage(workerHost_s *worker); diff --git a/src/worker/worker_master.c b/src/worker/worker_master.c index 4ed7cd4..ad7c20c 100644 --- a/src/worker/worker_master.c +++ b/src/worker/worker_master.c @@ -4,108 +4,105 @@ #include -static hdlcPacket_s hdlcMasterPacket = {hdlcMasterAddress}; -static fifo_s hdlcMasterFifo; +static hdlcPacket_s hdlcMasterPacket = {0}; +fifo_s hdlcMasterFifo; static workerHost_s hdlcMaster = {0}; static uint8_t masterBuffer[WORK_BYTE_BUFFER_SIZE]; - -workerHost_s* WORK_masterInit () { - if (!hdlcMaster.isInitialized) { - printf("WMAST: Starting master worker initialization\n"); - hdlcMaster.packet = &hdlcMasterPacket; - hdlcMaster.fifo = &hdlcMasterFifo; - hdlcMaster.isInitialized = true; - hdlcMaster.byteBuffer = masterBuffer; - FIFO_init(&hdlcMasterFifo); - - if (DO_UNIT_TESTS){WORK_testFifo(hdlcMaster.fifo);} - - printf("WMAST: Master initialization done\n"); - WORK_printBlocks(&hdlcMaster, 3); - - return &hdlcMaster; - } - // Ошибка в пакете, повторная инициализация - hdlcMaster.isInitialized = false; - return NULL; -} +extern fifo_s hdlcSlaveFifo; int WORK_master (void) { - static workerHostState_e masterState = WORKSTATE_first; - if (masterState >= WORKSTATE_last) { - masterState = WORKSTATE_first; + static workerMasterHostState_e masterState = WSMASTER_first; + if (masterState >= WSMASTER_last) { + masterState = WSMASTER_first; } printf("WMAST: In master worker\n"); int res = 0; - switch (masterState) { - case WORKSTATE_first: - masterState = WORKSTATE_initializing; + case WSMASTER_first: + printf("WSLAV: Starting master worker\n"); + masterState = WSMASTER_initializing; break; // Инициализация хоста - case WORKSTATE_initializing: - if (WORK_masterInit() != NULL) { - masterState = WORKSTATE_preparingPackage; - } + case WSMASTER_initializing: + if (WORK_workerInit(&hdlcMaster, + &hdlcMasterPacket, &hdlcMasterFifo, masterBuffer) != NULL) { + masterState = WSMASTER_waitClient; + } + break; + + // Ожидание инициализации клиента + case WSMASTER_waitClient: + res = WORK_waitClient(&hdlcSlaveFifo); + if (res == 0) { + masterState = WSMASTER_preparingPackage; + } break; // Подготовка пакета - case WORKSTATE_preparingPackage: + case WSMASTER_preparingPackage: + hdlcMaster.packet->address = hdlcMasterAddress; + hdlcMaster.packet->control = 0b0100110011110000; + WORK_fillBuffer8b(hdlcMaster.packet->info, HDLC_INFO_LENGTH); + hdlcMaster.packet->fcs = 0; + uint16_t crc = CRC16_compute((uint8_t*) hdlcMaster.packet, sizeof(workerHost_s)); + hdlcMaster.packet->fcs = crc; res = WORK_execute(WORK_preparePackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_sendingPackage; + masterState = WSMASTER_sendingPackage; } break; // Отправка пакета - case WORKSTATE_sendingPackage: + case WSMASTER_sendingPackage: res = WORK_execute(WORK_sendPackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_waitingPackage; + masterState = WSMASTER_waitingPackage; } break; // Ожидание ответа - case WORKSTATE_waitingPackage: + case WSMASTER_waitingPackage: res = WORK_execute(WORK_waitPackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_receivingPackage; + masterState = WSMASTER_receivingPackage; } break; // Получение пакета - case WORKSTATE_receivingPackage: + case WSMASTER_receivingPackage: res = WORK_execute(WORK_receivePackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_parsingPackage; + masterState = WSMASTER_parsingPackage; } break; // Парсинг пакета - case WORKSTATE_parsingPackage: + case WSMASTER_parsingPackage: res = WORK_execute(WORK_parsePackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_checkingPackage; + masterState = WSMASTER_checkingPackage; } break; // Проверка пакета - case WORKSTATE_checkingPackage: + case WSMASTER_checkingPackage: res = WORK_execute(WORK_checkPackage, &hdlcMaster); if (res == 0) { - masterState = WORKSTATE_last; + masterState = WSMASTER_last; + __attribute__((fallthrough)); + } else { + break; } - break; + // Цикл завершён, повторяем - case WORKSTATE_last: + case WSMASTER_last: printf("WMAST: Job done. Starting from the beginning\n"); - masterState = WORKSTATE_first; - // Либо переходить сразу на подготовку пакета + masterState = WSMASTER_preparingPackage; break; } diff --git a/src/worker/worker_slave.c b/src/worker/worker_slave.c index 82d10b8..21e14a0 100644 --- a/src/worker/worker_slave.c +++ b/src/worker/worker_slave.c @@ -1,27 +1,83 @@ #include "main.h" #include "worker.h" +#include "worker_type.h" -static hdlcPacket_s hdlcSlavePacket = {hdlcSlaveAddress}; -static fifo_s hdlcSlaveFifo; +static hdlcPacket_s hdlcSlavePacket = {0}; +fifo_s hdlcSlaveFifo; static workerHost_s hdlcSlave = {0}; - -workerHost_s* WORK_slaveInit () { - if (!hdlcSlave.isInitialized) { - printf("WSLAV: Starting slave worker initialization\n"); - hdlcSlave.packet = &hdlcSlavePacket; - hdlcSlave.fifo = &hdlcSlaveFifo; - hdlcSlave.isInitialized = true; - printf("WSLAV: Slave initialization done\n"); - WORK_printBlocks(&hdlcSlave, 3); - } - - return &hdlcSlave; -} +static uint8_t slaveBuffer[WORK_BYTE_BUFFER_SIZE]; +extern fifo_s hdlcMasterFifo; int WORK_slave(void) { - WORK_slaveInit(); + static workerSlaveHostState_e slaveState = WSSLAVE_first; + if (slaveState >= WSSLAVE_last) { + slaveState = WSSLAVE_first; + } + printf("WSLAV: In slave worker\n"); + int res = 0; + + switch (slaveState) { + case WSSLAVE_first: + printf("WSLAV: Starting slave worker\n"); + break; + + case WSSLAVE_initializing: + if (WORK_workerInit(&hdlcSlave, + &hdlcSlavePacket, &hdlcSlaveFifo, slaveBuffer) != NULL) { + res = 0; + } + break; + + case WSSLAVE_waitClient: + res = WORK_waitClient(&hdlcMasterFifo); + break; + + case WSSLAVE_waitingPackage: + res = WORK_execute(WORK_waitPackage, &hdlcSlave); + break; + + case WSSLAVE_receivingPackage: + res = WORK_execute(WORK_receivePackage, &hdlcSlave); + break; + + case WSSLAVE_checkingPackage: + res = WORK_execute(WORK_checkPackage, &hdlcSlave); + break; + + case WSSLAVE_parsingPackage: + res = WORK_execute(WORK_parsePackage, &hdlcSlave); + break; + + case WSSLAVE_preparingPackage: + hdlcSlave.packet->address = hdlcSlaveAddress; + uint8_t tmp = hdlcSlave.packet->info[0]; + hdlcSlave.packet->info[0] = hdlcSlave.packet->info[1]; + hdlcSlave.packet->info[1] = tmp; + res = WORK_execute(WORK_preparePackage, &hdlcSlave); + break; + + case WSSLAVE_sendingPackage: + res = WORK_execute(WORK_sendPackage, &hdlcSlave); + if (res == 0) { + slaveState = WSSLAVE_last; + __attribute__((fallthrough)); + } else { + break; + } + + case WSSLAVE_last: + printf("WSLAV: Job done. Starting from the beginning\n"); + slaveState = WSSLAVE_waitClient; + break; + + } // switch (slaveState) + + if (res == 0) { + slaveState++; + } + return 0; } \ No newline at end of file diff --git a/src/worker/worker_type.h b/src/worker/worker_type.h index 97ef96f..cf2f964 100644 --- a/src/worker/worker_type.h +++ b/src/worker/worker_type.h @@ -13,16 +13,30 @@ // Перечисление статусов конкретного хоста typedef enum { - WORKSTATE_first = 0, - WORKSTATE_initializing, - WORKSTATE_preparingPackage, - WORKSTATE_sendingPackage, - WORKSTATE_waitingPackage, - WORKSTATE_receivingPackage, - WORKSTATE_checkingPackage, - WORKSTATE_parsingPackage, - WORKSTATE_last -} workerHostState_e; + WSMASTER_first = 0, + WSMASTER_initializing, + WSMASTER_waitClient, + WSMASTER_preparingPackage, + WSMASTER_sendingPackage, + WSMASTER_waitingPackage, + WSMASTER_receivingPackage, + WSMASTER_checkingPackage, + WSMASTER_parsingPackage, + WSMASTER_last +} workerMasterHostState_e; + +typedef enum { + WSSLAVE_first = 0, + WSSLAVE_initializing, + WSSLAVE_waitClient, + WSSLAVE_waitingPackage, + WSSLAVE_receivingPackage, + WSSLAVE_checkingPackage, + WSSLAVE_parsingPackage, + WSSLAVE_preparingPackage, + WSSLAVE_sendingPackage, + WSSLAVE_last +} workerSlaveHostState_e; #endif // WORKER_TYPE_H \ No newline at end of file