Commit c4918050 authored by Flavio Ceolin's avatar Flavio Ceolin Committed by Anas Nashif
Browse files

tests: pm: Add multicore test



A simple test respects per cpu power states.

Signed-off-by: default avatarFlavio Ceolin <flavio.ceolin@intel.com>
parent 5e07fabe
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
# Copyright (c) 2021 Intel Corporation.
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(power_management_multicore_test)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
+4 −0
Original line number Diff line number Diff line
CONFIG_ZTEST=y
CONFIG_PM=y
CONFIG_PM_POLICY_APP=y
CONFIG_MP_NUM_CPUS=2
+120 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2021 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <kernel.h>
#include <ztest.h>
#include <pm/pm.h>

BUILD_ASSERT(CONFIG_MP_NUM_CPUS == 2, "Invalid number of cpus");

#define NUM_OF_ITERATIONS (5)

#define THRESHOLD (10)

/* Arbitrary times to trigger different power states.  It is by the
 * application to sleep and the policy to define which power state
 * to use. They have no relationship with any platform.
 */
#define ACTIVE_MSEC (40)
#define ACTIVE_TIMEOUT K_MSEC(40)
#define IDLE_MSEC (60 + THRESHOLD)
#define IDLE_TIMEOUT K_MSEC(60)
#define SUSPEND_TO_IDLE_MSEC (100 + THRESHOLD)
#define SUSPEND_TO_IDLE_TIMEOUT K_MSEC(100)
#define STANDBY_TIMEOUT K_MSEC(200)


static enum pm_state state_testing[2];

void pm_power_state_set(struct pm_state_info info)
{
	switch (state_testing[_current_cpu->id]) {
	case PM_STATE_ACTIVE:
		zassert_equal(PM_STATE_ACTIVE, info.state, NULL);
		break;
	case  PM_STATE_RUNTIME_IDLE:
		zassert_equal(PM_STATE_RUNTIME_IDLE, info.state, NULL);
		break;
	case  PM_STATE_SUSPEND_TO_IDLE:
		zassert_equal(PM_STATE_SUSPEND_TO_IDLE, info.state, NULL);
		break;
	case  PM_STATE_STANDBY:
		zassert_equal(_current_cpu->id, 1U, NULL);
		zassert_equal(PM_STATE_STANDBY, info.state, NULL);
		break;
	default:
		zassert_unreachable(NULL);
		break;
	}
}

void pm_power_state_exit_post_ops(struct pm_state_info info)
{
	/* pm_system_suspend is entered with irq locked
	 * unlock irq before leave pm_system_suspend
	 */
	irq_unlock(0);
}

struct pm_state_info pm_policy_next_state(uint8_t cpu, int ticks)
{
	struct pm_state_info info = {};
	int32_t msecs = k_ticks_to_ms_floor64(ticks);

	if (msecs < ACTIVE_MSEC) {
		info.state = PM_STATE_ACTIVE;
	} else if (msecs <= IDLE_MSEC) {
		info.state = PM_STATE_RUNTIME_IDLE;
	} else if (msecs <= SUSPEND_TO_IDLE_MSEC) {
		info.state = PM_STATE_SUSPEND_TO_IDLE;
	} else {
		if (cpu == 0U) {
			info.state = PM_STATE_SUSPEND_TO_IDLE;
		} else {
			info.state = PM_STATE_STANDBY;
		}
	}

	state_testing[_current_cpu->id] = info.state;

	return info;
}

/*
 * @brief test power idle in multicore
 *
 * @details
 *  - Go over a list of timeouts that should trigger different sleep states
 *  - The test assumes there are two cpus. The cpu 1 has one deeper sleep state than cpu 0.
 *  - Checks that the states given by the policy are properly used in the idle thread.
 *  - Iterate a number of times to stress it.
 *
 * @see pm_policy_next_state()
 * @see pm_power_state_set()
 *
 * @ingroup power_tests
 */
void test_power_idle(void)
{

	for (uint8_t i = 0U; i < NUM_OF_ITERATIONS; i++) {
		k_sleep(ACTIVE_TIMEOUT);

		k_sleep(IDLE_TIMEOUT);

		k_sleep(SUSPEND_TO_IDLE_TIMEOUT);

		k_sleep(STANDBY_TIMEOUT);
	}
}

void test_main(void)
{
	ztest_test_suite(pm_multicore_test,
			 ztest_unit_test(test_power_idle));
	ztest_run_test_suite(pm_multicore_test);
}
+4 −0
Original line number Diff line number Diff line
tests:
  subsys.pm.multicore:
    platform_allow: qemu_x86_64
    tags: pm