mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 14:01:53 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 Unit tests for FreeRTOS preemption
 | 
						|
*/
 | 
						|
 | 
						|
#include <esp_types.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#include "freertos/FreeRTOS.h"
 | 
						|
#include "freertos/task.h"
 | 
						|
#include "freertos/semphr.h"
 | 
						|
#include "freertos/queue.h"
 | 
						|
#include "unity.h"
 | 
						|
#include "soc/cpu.h"
 | 
						|
#include "hal/cpu_hal.h"
 | 
						|
#include "test_utils.h"
 | 
						|
#include "sdkconfig.h"
 | 
						|
 | 
						|
static volatile bool trigger;
 | 
						|
static volatile bool flag;
 | 
						|
 | 
						|
/* Task:
 | 
						|
   - Waits for 'trigger' variable to be set
 | 
						|
   - Reads the cycle count on this CPU
 | 
						|
   - Pushes it into a queue supplied as a param
 | 
						|
   - Busy-waits until the main task terminates it
 | 
						|
*/
 | 
						|
static void task_send_to_queue(void *param)
 | 
						|
{
 | 
						|
    QueueHandle_t queue = (QueueHandle_t) param;
 | 
						|
    uint32_t ccount;
 | 
						|
 | 
						|
    while(!trigger) {}
 | 
						|
 | 
						|
    ccount = cpu_hal_get_cycle_count();
 | 
						|
    flag = true;
 | 
						|
    xQueueSendToBack(queue, &ccount, 0);
 | 
						|
    /* This is to ensure that higher priority task
 | 
						|
       won't wake anyhow, due to this task terminating.
 | 
						|
 | 
						|
       The task runs until terminated by the main task.
 | 
						|
    */
 | 
						|
    while(1) {}
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Yield from lower priority task, same CPU", "[freertos]")
 | 
						|
{
 | 
						|
    /* Do this 3 times, mostly for the benchmark value - the first
 | 
						|
       run includes a cache miss so uses more cycles than it should. */
 | 
						|
    for (int i = 0; i < 3; i++) {
 | 
						|
        TaskHandle_t sender_task;
 | 
						|
        QueueHandle_t queue = xQueueCreate(1, sizeof(uint32_t));
 | 
						|
        flag = false;
 | 
						|
        trigger = false;
 | 
						|
 | 
						|
        /* "yield" task sits on our CPU, lower priority to us */
 | 
						|
        xTaskCreatePinnedToCore(task_send_to_queue, "YIELD", 2048, (void *)queue, UNITY_FREERTOS_PRIORITY - 1, &sender_task, UNITY_FREERTOS_CPU);
 | 
						|
 | 
						|
        vTaskDelay(1); /* make sure everything is set up */
 | 
						|
        trigger = true;
 | 
						|
 | 
						|
        uint32_t yield_ccount, now_ccount, delta;
 | 
						|
        TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) );
 | 
						|
        now_ccount = cpu_hal_get_cycle_count();
 | 
						|
        TEST_ASSERT( flag );
 | 
						|
 | 
						|
        delta = now_ccount - yield_ccount;
 | 
						|
        printf("Yielding from lower priority task took %u cycles\n", delta);
 | 
						|
        TEST_ASSERT(delta < 10000);
 | 
						|
 | 
						|
        vTaskDelete(sender_task);
 | 
						|
        vQueueDelete(queue);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#if (portNUM_PROCESSORS == 2) && !CONFIG_FREERTOS_TASK_FUNCTIONS_INTO_FLASH
 | 
						|
TEST_CASE("Yield from lower priority task, other CPU", "[freertos]")
 | 
						|
{
 | 
						|
    uint32_t trigger_ccount, yield_ccount, now_ccount, delta;
 | 
						|
 | 
						|
    /* Do this 3 times, mostly for the benchmark value - the first
 | 
						|
       run includes a cache miss so uses more cycles than it should. */
 | 
						|
    for (int i = 0; i < 3; i++) {
 | 
						|
        TaskHandle_t sender_task;
 | 
						|
        QueueHandle_t queue = xQueueCreate(1, sizeof(uint32_t));
 | 
						|
        trigger = false;
 | 
						|
        flag = false;
 | 
						|
 | 
						|
        /* "send_to_queue" task sits on the other CPU, lower priority to us */
 | 
						|
        xTaskCreatePinnedToCore(task_send_to_queue, "YIELD", 2048, (void *)queue, UNITY_FREERTOS_PRIORITY - 1,
 | 
						|
                                &sender_task, !UNITY_FREERTOS_CPU);
 | 
						|
 | 
						|
        vTaskDelay(2); /* make sure everything is set up */
 | 
						|
        trigger = true;
 | 
						|
        trigger_ccount = cpu_hal_get_cycle_count();
 | 
						|
 | 
						|
        // yield_ccount is not useful in this test as it's the other core's CCOUNT
 | 
						|
        // so we use trigger_ccount instead
 | 
						|
        TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) );
 | 
						|
        now_ccount = cpu_hal_get_cycle_count();
 | 
						|
        TEST_ASSERT( flag );
 | 
						|
 | 
						|
        delta = now_ccount - trigger_ccount;
 | 
						|
        printf("Yielding from task on other core took %u cycles\n", delta);
 | 
						|
        TEST_ASSERT(delta < 10000);
 | 
						|
 | 
						|
        vQueueDelete(queue);
 | 
						|
        vTaskDelete(sender_task);
 | 
						|
    }
 | 
						|
}
 | 
						|
#endif
 |