#include <zephyr/kernel.h>
#include <string.h>
/* Размеры массивов (кратно 4 байтам для выравнивания) */
#define RESAMPLE_BUF_SIZE 160
#define FLOOD_ARRAY_SIZE (256 * 1024) /* 256 КБ (заведомо больше D-Cache) */
#define STACK_SIZE 2048
#define TEST_THREAD_PRIO 5
/* Флуд-буфер, который принудительно размещается в SDRAM */
static uint32_t flood_buffer[FLOOD_ARRAY_SIZE] __attribute__((section(".sdram_data")));
volatile uint32_t flood_dummy_sink;
/* Буферы для ресемплера */
/* В зависимости от Теста 1 или 2, линкер положит их в SDRAM или DTCM */
static int16_t resample_in_buf[RESAMPLE_BUF_SIZE];
static int16_t resample_out_buf[RESAMPLE_BUF_SIZE * 2];
/* Прототип функции из PJMEDIA resamplesubs.c */
extern int res_Resample(const int16_t X[], int16_t Y[], double pFactor,
uint16_t nx, int LargeF, int Interp);
/* --- Поток 1: Вычислительное ядро (Resample) --- */
K_THREAD_STACK_DEFINE(resample_stack, STACK_SIZE);
struct k_thread resample_thread_data;
void resample_test_thread(void *p1, void *p2, void *p3)
{
/* Заполняем входной буфер тестовым сигналом */
for (int i = 0; i < RESAMPLE_BUF_SIZE; i++) {
resample_in_buf[i] = (int16_t)(i * 100);
}
while (1) {
/* Вызываем ресемплер с использованием Large Filter (LargeF = 1) */
/* pFactor = 2.0 (Up-sampling), nx = 160, Interp = 1 */
res_Resample(resample_in_buf, resample_out_buf, 2.0,
RESAMPLE_BUF_SIZE, 1, 1);
/* Уступаем квант времени планировщику, чтобы дать поработать вредителю */
k_yield();
}
}
/* --- Поток 2: Интенсивное чтение (Вредитель шины SEMC) --- */
K_THREAD_STACK_DEFINE(flooder_stack, STACK_SIZE);
struct k_thread flooder_thread_data;
void memory_flooder_thread(void *p1, void *p2, void *p3)
{
while (1) {
/* Непрерывное линейное чтение всего огромного массива */
for (int i = 0; i < FLOOD_ARRAY_SIZE; i++) {
flood_dummy_sink = flood_buffer[i];
}
k_yield();
}
}
/* --- Главный поток инициализации --- */
int main(void)
{
printk("Starting SEMC Bus Torture Test...\n");
/* Инициализируем флуд-массив мусором во избежание оптимизаций компилятора */
for (int i = 0; i < FLOOD_ARRAY_SIZE; i++) {
flood_buffer[i] = i * 3;
}
/* Запускаем поток ресемплера */
k_thread_create(&resample_thread_data, resample_stack,
K_THREAD_STACK_SIZEOF(resample_stack),
resample_test_thread, NULL, NULL, NULL,
TEST_THREAD_PRIO, 0, K_NO_WAIT);
k_thread_name_set(&resample_thread_data, "torture_res");
/* Запускаем поток-вредитель */
k_thread_create(&flooder_thread_data, flooder_stack,
K_THREAD_STACK_SIZEOF(flooder_stack),
memory_flooder_thread, NULL, NULL, NULL,
TEST_THREAD_PRIO, 0, K_NO_WAIT);
k_thread_name_set(&flooder_thread_data, "torture_flood");
return 0;
}