#include "main.h" #include "board.h" #include "connector.h" #include "debug.h" #include "serial_control.h" #include "usart.h" #include #include #include #include #include // Кольцевой буфер для отладочных сообщений #define DEBUG_BUFFER_SIZE 1024 #define DEBUG_BUFFER_MAX_COUNT 128 typedef struct { uint8_t buffer[DEBUG_BUFFER_SIZE]; volatile uint16_t write_index; volatile uint16_t read_index; volatile uint16_t count; } DebugBuffer_t; static DebugBuffer_t debug_buffer = { .buffer = {0}, .write_index = 0, .read_index = 0, .count = 0 }; #if defined(__GNUC__) int _write(int fd, char * ptr, int len) { debug_buffer_add((const uint8_t*)ptr, len); return len; } #endif // Добавляет данные в кольцевой буфер void debug_buffer_add(const uint8_t* data, uint16_t len) { __disable_irq(); for (uint16_t i = 0; i < len; i++) { // Если буфер полон, перезаписываем старые данные if (debug_buffer.count >= DEBUG_BUFFER_SIZE) { debug_buffer.read_index = (debug_buffer.read_index + 1) % DEBUG_BUFFER_SIZE; debug_buffer.count--; } debug_buffer.buffer[debug_buffer.write_index] = data[i]; debug_buffer.write_index = (debug_buffer.write_index + 1) % DEBUG_BUFFER_SIZE; debug_buffer.count++; } __enable_irq(); } // Возвращает количество доступных данных в буфере uint16_t debug_buffer_available(void) { __disable_irq(); uint16_t count = debug_buffer.count; __enable_irq(); return count; } // Отправляет один пакет данных из буфера через SC_SendPacket (не более 250 байт) void debug_buffer_send(void) { __disable_irq(); // Если буфер пуст, ничего не делаем if (debug_buffer.count == 0) { __enable_irq(); return; } // Определяем сколько байт можно отправить (не более 250) uint16_t bytes_to_send = debug_buffer.count; if (bytes_to_send > DEBUG_BUFFER_MAX_COUNT) { bytes_to_send = DEBUG_BUFFER_MAX_COUNT; } // Вычисляем сколько байт до конца буфера uint16_t bytes_to_end = DEBUG_BUFFER_SIZE - debug_buffer.read_index; // Отправляем только непрерывный блок (до конца буфера или до bytes_to_send) if (bytes_to_send > bytes_to_end) { bytes_to_send = bytes_to_end; } // Отправляем данные напрямую из буфера if(bytes_to_send == debug_buffer.count){ SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG); }else{ SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG_CONTINUE); } debug_buffer.read_index = (debug_buffer.read_index + bytes_to_send) % DEBUG_BUFFER_SIZE; debug_buffer.count -= bytes_to_send; __enable_irq(); } #define LOG_BUFFER_SIZE 128 uint8_t log_buffer[LOG_BUFFER_SIZE]; // Кастомный printf с приоритетом лога int log_printf(LogLevel_t level, const char *format, ...) { va_list args; int result; // Добавляем приоритет первым байтом log_buffer[0] = (uint8_t)level; // Форматируем строку начиная со второго байта va_start(args, format); result = vsnprintf((char*)&log_buffer[1], LOG_BUFFER_SIZE - 2, format, args); va_end(args); // Проверяем, не переполнился ли буфер if (result < 0) { return result; } // Ограничиваем размер, чтобы оставить место для нуль-терминатора if (result >= (LOG_BUFFER_SIZE - 2)) { result = LOG_BUFFER_SIZE - 2; } // Добавляем нуль-терминатор в конец log_buffer[result + 1] = '\0'; // Отправляем в буфер (приоритет + строка + нуль-терминатор) debug_buffer_add(log_buffer, result + 2); return result; }