From 83959e3da8e3186c874b31f411461d26caedcafe Mon Sep 17 00:00:00 2001 From: Maxim Date: Tue, 9 Jun 2026 15:45:31 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=20=D0=B4=D0=B2=D1=83=D0=BC=D1=8F=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/gpio-interrupt.c | 146 ++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 15 deletions(-) diff --git a/examples/gpio-interrupt.c b/examples/gpio-interrupt.c index 216f8fb..b46aa9c 100644 --- a/examples/gpio-interrupt.c +++ b/examples/gpio-interrupt.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* @@ -41,6 +42,16 @@ unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; // 8-битная шин const size_t out_buffer_len = 32U; // Размер логируемого пакета const size_t fifo_buffer_len = 4096U; // Размер ПППУ в байтах +// Режимы работы +typedef enum { + MODE_FILL, // Заполнение пауз последним байтом (оригинальное поведение) + MODE_SLEEP // Сон при отсутствии данных (энергоэффективный) +} run_mode_t; + +// Глобальные настройки +static run_mode_t run_mode = MODE_SLEEP; // По умолчанию энергоэффективный режим +static bool debug_mode = false; + struct fifo { char *buffer; @@ -105,6 +116,11 @@ static struct fifo isr_ff; static unsigned long long last_time_us = 0; static const long debounce_us = 5000; // 5 мс +// Диагностика +static unsigned long total_bytes = 0; +static unsigned long interrupts_processed = 0; +static unsigned long loop_iterations = 0; + // Обработчик прерывания void isr_handle(void) { unsigned long long now_us; @@ -115,19 +131,128 @@ void isr_handle(void) { if (now_us - last_time_us < debounce_us) return; last_time_us = now_us; + interrupts_processed++; char byte_read = 0xff & digitalReadPins(pins, sizeof pins / sizeof pins[0]); fifo_try_write(&isr_ff, &byte_read, 1); } +// Режим 1: Заполнение пауз последним байтом +void run_mode_fill(void) { + char byte; + char byte_prev = 0; + + while (true) { + if (fifo_try_read(&isr_ff, &byte, 1)) { + fwrite(&byte, 1, 1, stdout); + byte_prev = byte; + total_bytes++; + } else { + fwrite(&byte_prev, 1, 1, stdout); + } + fflush(stdout); + loop_iterations++; + + if (debug_mode && (loop_iterations % 1000000 == 0)) { + fprintf(stderr, "[DEBUG] Mode=fill, iterations=%lu, bytes=%lu\n", + loop_iterations, total_bytes); + } + } +} + +// Режим 2: Сон при отсутствии данных (с минимальной диагностикой) +void run_mode_sleep(void) { + char byte; + int first_bytes_shown = 0; + + // Минимальная диагностика при запуске + fprintf(stderr, "GPIO Monitor: waiting for data on WR pin %d...\n", wr_pin); + fflush(stderr); + + while (true) { + if (fifo_try_read(&isr_ff, &byte, 1)) { + fwrite(&byte, 1, 1, stdout); + fflush(stdout); + total_bytes++; + loop_iterations = 0; + + // Показать первые 10 байт в stderr + if (first_bytes_shown < 10) { + if (first_bytes_shown == 0) { + fprintf(stderr, "First bytes: "); + } + fprintf(stderr, "0x%02x ", (unsigned char)byte); + first_bytes_shown++; + + if (first_bytes_shown == 10) { + fprintf(stderr, "\n"); + fflush(stderr); + } + } + } else { + usleep(1000); + loop_iterations++; + } + + if (debug_mode && (loop_iterations > 0) && (loop_iterations % 10000 == 0)) { + fprintf(stderr, "[DEBUG] Mode=sleep, idle loops=%lu, bytes=%lu\n", + loop_iterations, total_bytes); + } + } +} + +// Парсинг аргументов командной строки +void parse_arguments(int argc, char *argv[]) { + static struct option long_options[] = { + {"mode", required_argument, 0, 'm'}, + {"debug", no_argument, 0, 'd'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + int opt; + int option_index = 0; + + while ((opt = getopt_long(argc, argv, "m:dh", long_options, &option_index)) != -1) { + switch (opt) { + case 'm': + if (strcmp(optarg, "fill") == 0) { + run_mode = MODE_FILL; + } else if (strcmp(optarg, "sleep") == 0) { + run_mode = MODE_SLEEP; + } else { + fprintf(stderr, "Неизвестный режим: %s\n", optarg); + fprintf(stderr, "Доступные режимы: fill, sleep\n"); + exit(EXIT_FAILURE); + } + break; + case 'd': + debug_mode = true; + break; + case 'h': + printf("Использование: %s [OPTIONS]\n\n", argv[0]); + printf("Опции:\n"); + printf(" -m, --mode=MODE Режим работы: fill или sleep\n"); + printf(" fill - заполнение пауз последним байтом\n"); + printf(" sleep - сон при отсутствии данных (по умолчанию)\n"); + printf(" -d, --debug Включить диагностику в stderr\n"); + printf(" -h, --help Показать эту справку\n"); + exit(EXIT_SUCCESS); + break; + default: + fprintf(stderr, "Используйте --help для справки\n"); + exit(EXIT_FAILURE); + } + } +} int main(int argc, char *argv[]) { - // Обработка аргументов + parse_arguments(argc, argv); + if (!fifo_init(&isr_ff, fifo_buffer_len)) { perror("fifo_init()"); exit(EXIT_FAILURE); } - // WiringPi if (wiringPiSetup() == -1) { perror("wiringPiSetup()"); exit(EXIT_FAILURE); @@ -135,30 +260,21 @@ int main(int argc, char *argv[]) { pinMode(wr_pin, INPUT); pullUpDnControl(wr_pin, PUD_UP); - // Настройка шины данных for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) { unsigned int pin = pins[i]; pullUpDnControl(pin, PUD_DOWN); pinMode(pin, INPUT); } - // Прерывание по фронту if (wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle) != 0) { perror("wiringPiISR()"); exit(EXIT_FAILURE); } - char byte_prev = 0; - while (true) { - char byte = 0; - if (fifo_try_read(&isr_ff, &byte, sizeof byte)) { - fwrite(&byte, 1, 1, stdout); - byte_prev = byte; - } - else { - fwrite(&byte_prev, 1, 1, stdout); - } - fflush(stdout); + if (run_mode == MODE_FILL) { + run_mode_fill(); + } else { + run_mode_sleep(); } fifo_uninit(&isr_ff); return EXIT_SUCCESS;