mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	test(freertos): add a test case for the DSP coprocessor
This commit is contained in:
		
							
								
								
									
										101
									
								
								components/freertos/test_apps/freertos/port/test_dsp_in_task.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								components/freertos/test_apps/freertos/port/test_dsp_in_task.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "sdkconfig.h"
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include "soc/soc_caps.h"
 | 
			
		||||
#include "freertos/FreeRTOS.h"
 | 
			
		||||
#include "freertos/task.h"
 | 
			
		||||
#include "freertos/semphr.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "test_utils.h"
 | 
			
		||||
 | 
			
		||||
#if SOC_CPU_HAS_DSP
 | 
			
		||||
 | 
			
		||||
#define TEST_NUM_TASKS       4
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    int32_t  id;
 | 
			
		||||
    uint32_t result;
 | 
			
		||||
    TaskHandle_t main;
 | 
			
		||||
    SemaphoreHandle_t sem;
 | 
			
		||||
} dsp_params_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Multiplies the given ID by a constant.
 | 
			
		||||
 *
 | 
			
		||||
 * @param id Value to multiply
 | 
			
		||||
 */
 | 
			
		||||
uint32_t dsp_id_mul(uint32_t id);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief DSP Assembly routine need to access this constant, make it public.
 | 
			
		||||
 * It will be used as a multiplier.
 | 
			
		||||
 */
 | 
			
		||||
const uint32_t g_dsp_constant = 100000;
 | 
			
		||||
 | 
			
		||||
static void pinned_task(void *arg)
 | 
			
		||||
{
 | 
			
		||||
    dsp_params_t *param = (dsp_params_t*) arg;
 | 
			
		||||
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
 | 
			
		||||
 | 
			
		||||
    param->result = dsp_id_mul(param->id);
 | 
			
		||||
 | 
			
		||||
    /* Indicate done and wait to be deleted */
 | 
			
		||||
    xSemaphoreGive((SemaphoreHandle_t)param->sem);
 | 
			
		||||
    vTaskSuspend(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("DSP: Usage in task", "[freertos]")
 | 
			
		||||
{
 | 
			
		||||
    TaskHandle_t task_handles[CONFIG_FREERTOS_NUMBER_OF_CORES][TEST_NUM_TASKS];
 | 
			
		||||
    dsp_params_t params[CONFIG_FREERTOS_NUMBER_OF_CORES][TEST_NUM_TASKS];
 | 
			
		||||
 | 
			
		||||
    SemaphoreHandle_t done_sem = xSemaphoreCreateCounting(TEST_NUM_TASKS, 0);
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(NULL, done_sem);
 | 
			
		||||
 | 
			
		||||
    // Create test tasks for each core
 | 
			
		||||
    for (int i = 0; i < CONFIG_FREERTOS_NUMBER_OF_CORES; i++) {
 | 
			
		||||
        for (int j = 0; j < TEST_NUM_TASKS; j++) {
 | 
			
		||||
            params[i][j] = (dsp_params_t) {
 | 
			
		||||
                .id = i * TEST_NUM_TASKS + j + 1,
 | 
			
		||||
                .sem = done_sem,
 | 
			
		||||
            };
 | 
			
		||||
            TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(pinned_task, "task", 4096, (void *) ¶ms[i][j], UNITY_FREERTOS_PRIORITY + 1, &task_handles[i][j], i));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Start the created tasks
 | 
			
		||||
    for (int i = 0; i < CONFIG_FREERTOS_NUMBER_OF_CORES; i++) {
 | 
			
		||||
        for (int j = 0; j < TEST_NUM_TASKS; j++) {
 | 
			
		||||
            xTaskNotifyGive(task_handles[i][j]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Wait for the tasks to complete
 | 
			
		||||
    for (int i = 0; i < CONFIG_FREERTOS_NUMBER_OF_CORES * TEST_NUM_TASKS; i++) {
 | 
			
		||||
        xSemaphoreTake(done_sem, portMAX_DELAY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Delete the tasks
 | 
			
		||||
    for (int i = 0; i < CONFIG_FREERTOS_NUMBER_OF_CORES; i++) {
 | 
			
		||||
        for (int j = 0; j < TEST_NUM_TASKS; j++) {
 | 
			
		||||
            vTaskDelete(task_handles[i][j]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check the values
 | 
			
		||||
    for (int i = 0; i < CONFIG_FREERTOS_NUMBER_OF_CORES; i++) {
 | 
			
		||||
        for (int j = 0; j < TEST_NUM_TASKS; j++) {
 | 
			
		||||
            dsp_params_t* param = ¶ms[i][j];
 | 
			
		||||
            TEST_ASSERT_EQUAL(param->id * g_dsp_constant, param->result);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vSemaphoreDelete(done_sem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* SOC_CPU_HAS_DSP */
 | 
			
		||||
@@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
    #include "soc/soc_caps.h"
 | 
			
		||||
 | 
			
		||||
#if SOC_CPU_HAS_DSP
 | 
			
		||||
 | 
			
		||||
    #include "riscv/csr_dsp.h"
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Let's allow a small subset of registers to be used in the macro below
 | 
			
		||||
     */
 | 
			
		||||
    .set regnum_a0, 10
 | 
			
		||||
    .set regnum_a1, 11
 | 
			
		||||
    .set regnum_a2, 12
 | 
			
		||||
    .set regnum_a3, 13
 | 
			
		||||
    .set regnum_a4, 14
 | 
			
		||||
    .set regnum_a5, 15
 | 
			
		||||
    .set regnum_a6, 16
 | 
			
		||||
    .set regnum_a7, 17
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief The toolchain doesn't support DSP instructions yet, define it as a constant.
 | 
			
		||||
     */
 | 
			
		||||
    .macro macs32  _rs1, _rs2
 | 
			
		||||
        .word ( ( regnum_\_rs1 << 15 ) | ( regnum_\_rs2 << 20) | 0b100<<12 | 0b1011011 )
 | 
			
		||||
    .endm
 | 
			
		||||
 | 
			
		||||
    .global g_dsp_constant
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief Multiply the given ID by the global constant defined as g_dsp_constant.
 | 
			
		||||
     * NOTE: The goal of the function is not to be fast and efficient, on the contrary, it needs to be
 | 
			
		||||
     * slow and long so that it will be preempted.
 | 
			
		||||
     *
 | 
			
		||||
     * Parameters:
 | 
			
		||||
     *  a0: 32-bit id
 | 
			
		||||
     *
 | 
			
		||||
     * Returns:
 | 
			
		||||
     *  a0: multiplied value
 | 
			
		||||
     */
 | 
			
		||||
    .globl dsp_id_mul
 | 
			
		||||
dsp_id_mul:
 | 
			
		||||
    csrw 0x809, zero    // SAR = 0
 | 
			
		||||
    csrw 0x806, zero    // XACC_L
 | 
			
		||||
    csrw 0x807, zero    // XACC_H
 | 
			
		||||
    li a1, 1
 | 
			
		||||
    /* Load the constant in a2 */
 | 
			
		||||
    lw a2, (g_dsp_constant)
 | 
			
		||||
1:
 | 
			
		||||
    // Perform ACC += a0 (=id) * a1 (=1)
 | 
			
		||||
    macs32 a1, a0
 | 
			
		||||
    addi a2, a2, -1
 | 
			
		||||
    bnez a2, 1b
 | 
			
		||||
    // Get the lowest bits
 | 
			
		||||
    csrr a0, 0x806    // XACC_L
 | 
			
		||||
    ret
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // SOC_CPU_HAS_DSP
 | 
			
		||||
		Reference in New Issue
	
	Block a user