Загрузка данных


#include "fsl_debug_console.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_cache.h"

/* Диапазон DDR для проведения измерений (весь этот регион будет циклически перезаписываться) */
#define DDR_TEST_START_ADDR   0x80000000U        /* Начинаем с самого начала DDR */
#define DDR_TEST_SIZE_BYTES   (64 * 1024 * 1024) /* Размер тестового окна: 64 МБ (можно увеличить) */
#define DDR_TEST_SIZE_WORDS   (DDR_TEST_SIZE_BYTES / sizeof(uint32_t))

void run_intense_memtest_loop(uint32_t start_addr, uint32_t words_count);
void print_menu(void);

int main(void)
{
    char input_ch;

    /* Инициализация стандартной периферии и Debug UART */
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();

    PRINTF("\r\n==================================================\r\n");
    PRINTF(" i.MX95 M7: DTCM-Executed DDR Load Generator (BCU)\r\n");
    PRINTF("==================================================\r\n");
    PRINTF("[INFO] Код и стек M7 работают из внутренней памяти DTCM.\r\n");
    PRINTF("[INFO] Целевой регион теста DDR: 0x%08X - 0x%08X (%d МБ)\r\n", 
           DDR_TEST_START_ADDR, 
           DDR_TEST_START_ADDR + DDR_TEST_SIZE_BYTES, 
           DDR_TEST_SIZE_BYTES / (1024 * 1024));

    print_menu();

    while (1)
    {
        /* Ожидаем команду из консоли */
        input_ch = GETCHAR();
        PUTCHAR(input_ch); /* Эхо-вывод */

        if (input_ch == '1') 
        {
            PRINTF("\r\n[START] Запуск непрерывного Memtest. Нажмите 'ANY KEY' для остановки...\r\n");
            PRINTF("--> Фиксируйте пиковое потребление шины DDR в утилите BCU.\r\n");
            
            /* Запуск генератора нагрузки */
            run_intense_memtest_loop(DDR_TEST_START_ADDR, DDR_TEST_SIZE_WORDS);
            
            print_menu();
        }
        else if (input_ch == '2')
        {
            PRINTF("\r\n[IDLE] Тест остановлен. Шина DDR находится в режиме ожидания.\r\n");
            PRINTF("--> Фиксируйте фоновое (холостое) потребление DDR в утилите BCU.\r\n");
            print_menu();
        }
    }
}

void print_menu(void)
{
    PRINTF("\r\nДоступные команды:\r\n");
    PRINTF(" - Включить максимальную нагрузку на DDR (Бесконечный Memtest)\r\n");
    PRINTF(" - Перейти в режим ожидания (DDR Idle)\r\n");
    PRINTF("Выберите действие: ");
}

/**
 * @brief Функция генерации плотного трафика в шину DDR.
 * Код работает из DTCM, поэтому циклы `for` не создают трафика на системной шине,
 * а все обращения к `start_addr` идут напрямую в контроллер DRAM.
 */
void run_intense_memtest_loop(uint32_t start_addr, uint32_t words_count)
{
    volatile uint32_t *ddr_ptr = (volatile uint32_t *)start_addr;
    uint32_t pattern_a = 0x55555555;
    uint32_t pattern_b = 0xAAAAAAAA;
    uint32_t read_val;
    char stop_ch;
    uint32_t iteration = 0;

    while (1)
    {
        iteration++;
        
        /* Шаг 1: Агрессивная запись чередующихся инверсных паттернов */
        for (uint32_t i = 0; i < words_count; i++) 
        {
            ddr_ptr[i] = (i % 2 == 0) ? pattern_a : pattern_b;
        }

        /* Шаг 2: Принудительный сброс D-Cache. 
           Даже когда код выполняется из DTCM, обращения к DDR кэшируются. 
           Вызов этой функции выталкивает измененные строки кэша (Write-Back) в физическую DDR,
           создавая плотный поток транзакций. */
        L1CACHE_CleanInvalidateDCacheByRange(start_addr, words_count * sizeof(uint32_t));

        /* Шаг 3: Чтение данных и верификация (проверка целостности) */
        for (uint32_t i = 0; i < words_count; i++) 
        {
            read_val = ddr_ptr[i];
            uint32_t expected = (i % 2 == 0) ? pattern_a : pattern_b;
            
            if (read_val != expected) 
            {
                PRINTF("\r\n[MEMTEST ERROR] Итерация %d: Ошибка данных по адресу 0x%08X! Прочитано: 0x%08X\r\n", 
                       iteration, (uint32_t)&ddr_ptr[i], read_val);
                return; /* Выход из теста при аппаратной ошибке памяти */
            }
        }

        /* Шаг 4: Проверка нажатия клавиши для прерывания теста (без блокировки выполнения) */
        if (DbgConsole_TryGetChar(&stop_ch) == kStatus_Success)
        {
            PRINTF("\r\n[STOP] Цикл Memtest успешно завершен. Пройдено итераций: %d\r\n", iteration);
            break;
        }
    }
}