Добавил filo, fifo. Настройка коммуникации

This commit is contained in:
ru.sadekov 2025-10-28 09:40:27 +03:00
parent c719f259ed
commit 7b6eaa563b
13 changed files with 406 additions and 107 deletions

View File

@ -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"
}
}

View File

@ -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,13 +30,13 @@ 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->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;
}

View File

@ -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;

90
src/filo/filo.c Normal file
View File

@ -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;
}

27
src/filo/filo.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#ifndef FILO_H
#define FILO_H
#include "filo_type.h"
#include <stddef.h>
// Размер 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

16
src/filo/filo_type.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#ifndef FILO_TYPE_H
#define FILO_TYPE_H
#include <stdint.h>
// Структура состояний FILO
typedef enum {
FILOS_empty = 0,
FILOS_ready,
FILOS_full,
FILOS_error
} filoState_e;
#endif // FILO_TYPE_H

View File

@ -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:

View File

@ -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);

View File

@ -6,12 +6,44 @@
#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);
@ -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) {

View File

@ -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);

View File

@ -4,108 +4,105 @@
#include <string.h>
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;
}

View File

@ -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;
}

View File

@ -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