tests/intel_adsp: Add clock calibration test
Now that we have easy access to code on the host, it's trivial to check the clock against host timestamps with high precision. Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
005e12bdac
commit
3da9c9213e
5 changed files with 55 additions and 1 deletions
|
@ -32,6 +32,7 @@ void z_cavs_ipc_isr(const void *devarg)
|
||||||
const struct device *dev = devarg;
|
const struct device *dev = devarg;
|
||||||
const struct cavs_ipc_config *config = dev->config;
|
const struct cavs_ipc_config *config = dev->config;
|
||||||
struct cavs_ipc_data *devdata = dev->data;
|
struct cavs_ipc_data *devdata = dev->data;
|
||||||
|
|
||||||
volatile struct cavs_ipc *regs = config->regs;
|
volatile struct cavs_ipc *regs = config->regs;
|
||||||
k_spinlock_key_t key = k_spin_lock(&devdata->lock);
|
k_spinlock_key_t key = k_spin_lock(&devdata->lock);
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,8 @@ async def ipc_delay_done():
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
dsp.HIPCTDA = 1<<31
|
dsp.HIPCTDA = 1<<31
|
||||||
|
|
||||||
|
ipc_timestamp = 0
|
||||||
|
|
||||||
# Super-simple command language, driven by the test code on the DSP
|
# Super-simple command language, driven by the test code on the DSP
|
||||||
def ipc_command(data, ext_data):
|
def ipc_command(data, ext_data):
|
||||||
send_msg = False
|
send_msg = False
|
||||||
|
@ -338,6 +340,12 @@ def ipc_command(data, ext_data):
|
||||||
send_msg = True
|
send_msg = True
|
||||||
elif data == 3: # set ADSPCS
|
elif data == 3: # set ADSPCS
|
||||||
dsp.ADSPCS = ext_data
|
dsp.ADSPCS = ext_data
|
||||||
|
elif data == 4: # echo back microseconds since last timestamp command
|
||||||
|
global ipc_timestamp
|
||||||
|
t = round(time.time() * 1e6)
|
||||||
|
ext_data = t - ipc_timestamp
|
||||||
|
ipc_timestamp = t
|
||||||
|
send_msg = True
|
||||||
else:
|
else:
|
||||||
log.warning(f"cavstool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}")
|
log.warning(f"cavstool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}")
|
||||||
|
|
||||||
|
|
|
@ -96,4 +96,8 @@ void test_host_ipc(void)
|
||||||
zassert_true(ret, "send failed");
|
zassert_true(ret, "send failed");
|
||||||
zassert_true(done_flag, "done interrupt failed to fire");
|
zassert_true(done_flag, "done interrupt failed to fire");
|
||||||
zassert_true(cavs_ipc_is_complete(CAVS_HOST_DEV), "sync message incomplete");
|
zassert_true(cavs_ipc_is_complete(CAVS_HOST_DEV), "sync message incomplete");
|
||||||
|
|
||||||
|
/* Clean up. Further tests might want to use IPC */
|
||||||
|
cavs_ipc_set_message_handler(CAVS_HOST_DEV, NULL, NULL);
|
||||||
|
cavs_ipc_set_done_handler(CAVS_HOST_DEV, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,43 @@
|
||||||
*/
|
*/
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <ztest.h>
|
#include <ztest.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
|
static bool clock_msg(const struct device *dev, void *arg,
|
||||||
|
uint32_t data, uint32_t ext_data)
|
||||||
|
{
|
||||||
|
*(uint32_t *)arg = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_clock_calibrate(void)
|
||||||
|
{
|
||||||
|
static volatile uint32_t host_dt;
|
||||||
|
uint32_t cyc0, cyc1, hz, diff;
|
||||||
|
|
||||||
|
/* Prime the host script's timestamp */
|
||||||
|
cyc0 = k_cycle_get_32();
|
||||||
|
cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_TIMESTAMP, 0);
|
||||||
|
|
||||||
|
k_msleep(1000);
|
||||||
|
host_dt = 0;
|
||||||
|
cavs_ipc_set_message_handler(CAVS_HOST_DEV, clock_msg, (void *)&host_dt);
|
||||||
|
|
||||||
|
/* Now do it again, but with a handler to catch the result */
|
||||||
|
cyc1 = k_cycle_get_32();
|
||||||
|
cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_TIMESTAMP, 0);
|
||||||
|
WAIT_FOR(host_dt != 0);
|
||||||
|
cavs_ipc_set_message_handler(CAVS_HOST_DEV, NULL, NULL);
|
||||||
|
|
||||||
|
hz = 1000000ULL * (cyc1 - cyc0) / host_dt;
|
||||||
|
printk("CLOCK: %lld Hz\n", (1000000ULL * (cyc1 - cyc0)) / host_dt);
|
||||||
|
|
||||||
|
/* Make sure we're within 1% of spec */
|
||||||
|
diff = abs(hz - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
|
||||||
|
zassert_true((hz / MIN(1, diff)) > 100, "clock rate wrong");
|
||||||
|
}
|
||||||
|
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(intel_adsp,
|
ztest_test_suite(intel_adsp,
|
||||||
|
@ -12,7 +47,8 @@ void test_main(void)
|
||||||
ztest_unit_test(test_cpu_halt),
|
ztest_unit_test(test_cpu_halt),
|
||||||
ztest_unit_test(test_post_boot_ipi),
|
ztest_unit_test(test_post_boot_ipi),
|
||||||
ztest_unit_test(test_cpu_behavior),
|
ztest_unit_test(test_cpu_behavior),
|
||||||
ztest_unit_test(test_host_ipc)
|
ztest_unit_test(test_host_ipc),
|
||||||
|
ztest_unit_test(test_clock_calibrate)
|
||||||
);
|
);
|
||||||
|
|
||||||
ztest_run_test_suite(intel_adsp);
|
ztest_run_test_suite(intel_adsp);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#ifndef ZEPHYR_TESTS_INTEL_ADSP_TESTS_H
|
#ifndef ZEPHYR_TESTS_INTEL_ADSP_TESTS_H
|
||||||
#define ZEPHYR_TESTS_INTEL_ADSP_TESTS_H
|
#define ZEPHYR_TESTS_INTEL_ADSP_TESTS_H
|
||||||
|
|
||||||
|
#include <cavs_ipc.h>
|
||||||
|
|
||||||
/* Helper to escape from infinite polling loops with a test failure
|
/* Helper to escape from infinite polling loops with a test failure
|
||||||
* instead of a hang. Spins with a relaxation loop so that it works
|
* instead of a hang. Spins with a relaxation loop so that it works
|
||||||
* in interrupt context and doesn't stress shared resources like SRAM
|
* in interrupt context and doesn't stress shared resources like SRAM
|
||||||
|
@ -33,6 +35,9 @@ enum cavstool_cmd {
|
||||||
|
|
||||||
/* The host writes the given value to ADSPCS */
|
/* The host writes the given value to ADSPCS */
|
||||||
IPCCMD_ADSPCS,
|
IPCCMD_ADSPCS,
|
||||||
|
|
||||||
|
/* The host emits a (real/host time) timestamp into the log stream */
|
||||||
|
IPCCMD_TIMESTAMP,
|
||||||
};
|
};
|
||||||
|
|
||||||
void test_post_boot_ipi(void);
|
void test_post_boot_ipi(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue