После отладки
This commit is contained in:
@@ -1,27 +1,36 @@
|
|||||||
/* Направляет в стандартный вывод данные полученные с
|
/* Направляет в стандартный вывод данные полученные с
|
||||||
параллельной 8-битной шины Raspberry Pi4. Собирать внутри папки WiringPi/examples
|
параллельной 8-битной шины Raspberry Pi4. Собирать внутри папки WiringPi/examples
|
||||||
командой make really-all.
|
командой make really-all.
|
||||||
|
|
||||||
|
Использование:
|
||||||
|
./gpio-interrupt # только stdout
|
||||||
|
./gpio-interrupt /tmp/gpio.log # stdout + лог в файл
|
||||||
|
./gpio-interrupt - # только лог в stdout (stderr)
|
||||||
|
|
||||||
Предварительные условия:
|
Предварительные условия:
|
||||||
- WiringPi должен быть собран из этой версии, в которую добавлена функция digitalReadPins()
|
- WiringPi должен быть собран из этой версии, в которую добавлена функция digitalReadPins()
|
||||||
```
|
make && make install
|
||||||
make && make install
|
|
||||||
```
|
text
|
||||||
- WiringPi должен быть установлен из того deb-пакета который получен из этой версии
|
- WiringPi должен быть установлен из того deb-пакета который получен из этой версии
|
||||||
```
|
make debian && dpkg -i debian-template/WiringPi*.deb
|
||||||
make debian && dpkg -i debian-template/WiringPi*.deb
|
|
||||||
```
|
text
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <wiringPi.h>
|
#include <wiringPi.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
жёлтый д0
|
жёлтый д0
|
||||||
красный такт
|
красный такт
|
||||||
чёрный д1
|
чёрный д1
|
||||||
синий д2
|
синий д2
|
||||||
зелёный д3
|
зелёный д3
|
||||||
@@ -31,129 +40,174 @@
|
|||||||
unsigned int wr_pin = 27; /** Вывод для сигнала записи */
|
unsigned int wr_pin = 27; /** Вывод для сигнала записи */
|
||||||
unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; /** Выводы для данных */
|
unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; /** Выводы для данных */
|
||||||
const size_t out_buffer_len = 32U; /** Размер выходного буфера */
|
const size_t out_buffer_len = 32U; /** Размер выходного буфера */
|
||||||
const size_t fifo_buffer_len = 4096U; /** Размер буфера ПППУ */
|
const size_t fifo_buffer_len = 4096U; /** Размер буфера FIFO */
|
||||||
|
|
||||||
|
|
||||||
struct fifo {
|
struct fifo {
|
||||||
char *buffer; /** Буфер ПППУ */
|
char *buffer; /** Буфер FIFO */
|
||||||
size_t len; /** Длина буфера ПППУ */
|
size_t len; /** Длина буфера FIFO */
|
||||||
size_t wri; /** Указатель записи ПППУ */
|
size_t wri; /** Указатель записи FIFO */
|
||||||
size_t rdi; /** Указатель чтения ПППУ */
|
size_t rdi; /** Указатель чтения FIFO */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void fifo_reset(struct fifo* ff) {
|
void fifo_reset(struct fifo* ff) {
|
||||||
ff->wri = 0U;
|
ff->wri = 0U;
|
||||||
ff->rdi = 0U;
|
ff->rdi = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_init(struct fifo* ff, size_t len) {
|
bool fifo_init(struct fifo* ff, size_t len) {
|
||||||
ff->buffer = malloc(len);
|
ff->buffer = malloc(len);
|
||||||
ff->len = len;
|
ff->len = len;
|
||||||
fifo_reset(ff);
|
fifo_reset(ff);
|
||||||
return ff->buffer != NULL;
|
return ff->buffer != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fifo_uninit(struct fifo* ff) {
|
||||||
void fifo_uninit(struct fifo* ff, size_t len) {
|
free(ff->buffer);
|
||||||
free(ff->buffer);
|
ff->buffer = NULL;
|
||||||
ff->buffer = NULL;
|
fifo_reset(ff);
|
||||||
fifo_reset(ff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_is_full(struct fifo *ff) {
|
bool fifo_is_full(struct fifo *ff) {
|
||||||
return ((ff->wri + 1U) % ff->len) == ff->rdi;
|
return ((ff->wri + 1U) % ff->len) == ff->rdi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t fifo_available(struct fifo *ff) {
|
size_t fifo_available(struct fifo *ff) {
|
||||||
bool v = ff->wri >= ff->rdi;
|
bool v = ff->wri >= ff->rdi;
|
||||||
return (ff->wri - ff->rdi) * v + (ff->wri + ff->len - ff->rdi) * (!v);
|
return (ff->wri - ff->rdi) * v + (ff->wri + ff->len - ff->rdi) * (!v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_can_write(struct fifo *ff, size_t len) {
|
bool fifo_can_write(struct fifo *ff, size_t len) {
|
||||||
return (ff->len - fifo_available(ff)) > len;
|
return (ff->len - fifo_available(ff)) > len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_can_read(struct fifo *ff, size_t len) {
|
bool fifo_can_read(struct fifo *ff, size_t len) {
|
||||||
return fifo_available(ff) >= len;
|
return fifo_available(ff) >= len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) {
|
bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) {
|
||||||
if (!fifo_can_read(ff, len)) {
|
if (!fifo_can_read(ff, len)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(buffer, &ff->buffer[ff->rdi], len);
|
memcpy(buffer, &ff->buffer[ff->rdi], len);
|
||||||
ff->rdi = (ff->rdi + len) % ff->len;
|
ff->rdi = (ff->rdi + len) % ff->len;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) {
|
bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) {
|
||||||
if (!fifo_can_write(ff, len)) {
|
if (!fifo_can_write(ff, len)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(&ff->buffer[ff->wri], buffer, len);
|
memcpy(&ff->buffer[ff->wri], buffer, len);
|
||||||
ff->wri = (ff->wri + len) % ff->len;
|
ff->wri = (ff->wri + len) % ff->len;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct fifo isr_ff;
|
static struct fifo isr_ff;
|
||||||
|
|
||||||
int c = 0;
|
|
||||||
void isr_handle(void) {
|
void isr_handle(void) {
|
||||||
char byte_read = 0x0f & digitalReadPins(pins, sizeof pins / sizeof pins[0]);
|
char byte_read = 0x0f & digitalReadPins(pins, sizeof pins / sizeof pins[0]);
|
||||||
fifo_try_write(&isr_ff, &byte_read, 1);
|
fifo_try_write(&isr_ff, &byte_read, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
FILE *log_file = NULL;
|
||||||
|
const char *log_path = NULL;
|
||||||
|
|
||||||
int main(void) {
|
// Обработка аргументов командной строки
|
||||||
|
if (argc > 1) {
|
||||||
|
log_path = argv[1];
|
||||||
|
|
||||||
if (!fifo_init(&isr_ff, fifo_buffer_len)) {
|
if (strcmp(log_path, "-") == 0) {
|
||||||
perror("не выполнено fifo_init()\n");
|
// Логировать в stderr (чтобы не мешать stdout)
|
||||||
exit(EXIT_FAILURE);
|
log_file = stderr;
|
||||||
}
|
fprintf(stderr, "=== GPIO Monitor started (logging to stderr) ===\n");
|
||||||
|
} else {
|
||||||
if (wiringPiSetup() == -1) {
|
// Открываем файл для логирования
|
||||||
perror("не выполнено wiringPiSetup()\n");
|
log_file = fopen(log_path, "a");
|
||||||
exit(EXIT_FAILURE);
|
if (!log_file) {
|
||||||
}
|
perror("Ошибка открытия лог-файла");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
/** Сигнал записи */
|
}
|
||||||
pinMode(wr_pin, INPUT);
|
fprintf(stderr, "=== GPIO Monitor started (logging to %s) ===\n", log_path);
|
||||||
pullUpDnControl(wr_pin, PUD_UP);
|
fprintf(log_file, "\n=== Session started: %ld ===\n", (long)time(NULL));
|
||||||
|
fflush(log_file);
|
||||||
/** Шина данных 8 бит */
|
}
|
||||||
for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i ++) {
|
} else {
|
||||||
unsigned int pin = pins[i];
|
fprintf(stderr, "=== GPIO Monitor started (stdout only) ===\n");
|
||||||
pinMode(pin, INPUT);
|
}
|
||||||
pullUpDnControl(pin, PUD_UP);
|
|
||||||
}
|
// Инициализация FIFO
|
||||||
|
if (!fifo_init(&isr_ff, fifo_buffer_len)) {
|
||||||
int rc = wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle);
|
perror("не выполнено fifo_init()\n");
|
||||||
if (rc != 0) {
|
exit(EXIT_FAILURE);
|
||||||
perror("не выполнено wiringPiISR()\n");
|
}
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
// Инициализация WiringPi
|
||||||
char buffer [out_buffer_len];
|
if (wiringPiSetup() == -1) {
|
||||||
while (true) {
|
perror("не выполнено wiringPiSetup()\n");
|
||||||
bool is_read = fifo_try_read(&isr_ff, buffer, sizeof buffer);
|
exit(EXIT_FAILURE);
|
||||||
if (is_read) {
|
}
|
||||||
//fwrite(buffer, 1U, sizeof buffer, stdout);
|
|
||||||
for (int i = 0; i < sizeof buffer; i ++) {
|
// Настройка пина записи
|
||||||
printf("%02d: %02x\n", i, buffer[i]);
|
pinMode(wr_pin, INPUT);
|
||||||
}
|
pullUpDnControl(wr_pin, PUD_UP);
|
||||||
fflush(stdout);
|
|
||||||
}
|
// Настройка шины данных 8 бит
|
||||||
else {
|
for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) {
|
||||||
usleep(10000);
|
unsigned int pin = pins[i];
|
||||||
}
|
pinMode(pin, INPUT);
|
||||||
}
|
pullUpDnControl(pin, PUD_UP);
|
||||||
return EXIT_SUCCESS;
|
}
|
||||||
|
|
||||||
|
// Регистрация обработчика прерываний
|
||||||
|
int rc = wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle);
|
||||||
|
if (rc != 0) {
|
||||||
|
perror("не выполнено wiringPiISR()\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "GPIO pins initialized, waiting for interrupts...\n");
|
||||||
|
|
||||||
|
char buffer[out_buffer_len];
|
||||||
|
unsigned long total_bytes = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
bool is_read = fifo_try_read(&isr_ff, buffer, sizeof buffer);
|
||||||
|
if (is_read) {
|
||||||
|
total_bytes += sizeof buffer;
|
||||||
|
|
||||||
|
// Логирование в файл или stderr
|
||||||
|
if (log_file) {
|
||||||
|
fprintf(log_file, "--- Packet #%lu (%zu bytes) ---\n",
|
||||||
|
total_bytes / sizeof buffer, sizeof buffer);
|
||||||
|
for (int i = 0; i < sizeof buffer; i++) {
|
||||||
|
fprintf(log_file, " [%02d] = 0x%02x (%3d)\n",
|
||||||
|
i, (unsigned char)buffer[i], (unsigned char)buffer[i]);
|
||||||
|
}
|
||||||
|
fflush(log_file);
|
||||||
|
|
||||||
|
// Краткая сводка на экран
|
||||||
|
fprintf(stderr, "."); // Прогресс-индикатор
|
||||||
|
if (total_bytes % (32 * 10) == 0) {
|
||||||
|
fprintf(stderr, " [%lu bytes]\n", total_bytes);
|
||||||
|
}
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Бинарные данные в stdout для Go-сервера
|
||||||
|
fwrite(buffer, 1U, sizeof buffer, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
usleep(10000); // 10ms задержка, если данных нет
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очистка (теоретически недостижимо, но для порядка)
|
||||||
|
if (log_file && log_file != stderr) {
|
||||||
|
fclose(log_file);
|
||||||
|
}
|
||||||
|
fifo_uninit(&isr_ff);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user