Skip to content

Commit

Permalink
[sival, pwm] Adds smoketest
Browse files Browse the repository at this point in the history
Signed-off-by: Douglas Reis <[email protected]>
  • Loading branch information
engdoreis committed Nov 25, 2024
1 parent 6ef5887 commit 4e228e9
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 0 deletions.
40 changes: 40 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2827,6 +2827,46 @@ opentitan_test(
],
)

opentitan_test(
name = "pwm_smoketest",
srcs = ["pwm_smoketest.c"],
exec_env = dicts.add(
EARLGREY_TEST_ENVS,
EARLGREY_SILICON_OWNER_ROM_EXT_ENVS,
{
"//hw/top_earlgrey:fpga_cw340_rom_with_fake_keys": None,
"//hw/top_earlgrey:silicon_owner_sival_rom_ext": None,
"//hw/top_earlgrey:fpga_cw310_sival": None,
}
),
fpga = fpga_params(
test_cmd = """
--bootstrap="{firmware}"
"{firmware:elf}"
""",
test_harness = "//sw/host/tests/chip/pwm_smoketest",
),
silicon = silicon_params(
test_cmd = """
--bootstrap="{firmware}"
"{firmware:elf}"
""",
test_harness = "//sw/host/tests/chip/pwm_smoketest",
),
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:pwm",
"//sw/device/lib/dif:gpio",
"//sw/device/lib/runtime:hart",
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:irq",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/lib/testing/test_framework:ottf_utils",
],
)

cc_library(
name = "pwrmgr_sleep_resets_lib",
srcs = ["pwrmgr_sleep_resets_lib.c"],
Expand Down
112 changes: 112 additions & 0 deletions sw/device/tests/pwm_smoketest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include <stdint.h>

#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_gpio.h"
#include "sw/device/lib/dif/dif_pinmux.h"
#include "sw/device/lib/dif/dif_pwm.h"
#include "sw/device/lib/runtime/hart.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "sw/device/lib/testing/test_framework/ottf_utils.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"

enum {
kDefaultTimeoutMicros = 50000,
};

OTTF_DEFINE_TEST_CONFIG();

static volatile const uint8_t kClocksHz[] = {20, 50, 100, 200};
static volatile const uint8_t kDutyCycles[] = {10, 30, 50, 70, 90};

// This function assumes that DEC_RESN = 0.
static dif_pwm_config_t compute_clk_config(uint32_t pwm_clk) {
enum {
// Theres a trade off on the precision of the clock and the precision of the
// dutycycle, the higher the kDutyCycleResulution the more precise is the
// the dutycycle and less precise is the pwm frequency.
// By experimentation kDutyCycleResulution would generate an error of 2.5%
// on the frequency and 6% on the dutycycle.
kDutyCycleResulution = 4,
kBeatsPerCycle = 2 << (kDutyCycleResulution + 1), // 2 ^ (DC_RESN + 1)
};
return (dif_pwm_config_t){
.beats_per_pulse_cycle = kBeatsPerCycle,
.clock_divisor =
((uint32_t)kClockFreqAonHz / (kBeatsPerCycle * pwm_clk)) - 1};
}

bool test_main(void) {
dif_pwm_t pwm;
mmio_region_t addr = mmio_region_from_addr(TOP_EARLGREY_PWM_AON_BASE_ADDR);
CHECK_DIF_OK(dif_pwm_init(addr, &pwm));

dif_pinmux_t pinmux;
addr = mmio_region_from_addr(TOP_EARLGREY_PINMUX_AON_BASE_ADDR);
CHECK_DIF_OK(dif_pinmux_init(addr, &pinmux));
CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, kTopEarlgreyPinmuxMioOutIoa8,
kTopEarlgreyPinmuxOutselPwmAonPwm0));

dif_gpio_t gpio;
addr = mmio_region_from_addr(TOP_EARLGREY_GPIO_BASE_ADDR);
CHECK_DIF_OK(dif_gpio_init(addr, &gpio));
CHECK_DIF_OK(dif_gpio_output_set_enabled_all(&gpio, 0x1));

LOG_INFO("Use IOA7 to let host know when sleep is active.");
CHECK_DIF_OK(dif_pinmux_input_select(&pinmux,
kTopEarlgreyPinmuxPeripheralInGpioGpio0,
kTopEarlgreyPinmuxInselIoa7));

for (size_t i = 0; i < ARRAYSIZE(kClocksHz); ++i) {
dif_pwm_config_t pwm_config = compute_clk_config(kClocksHz[i]);
LOG_INFO("div: %d", pwm_config.clock_divisor);
for (size_t j = 0; j < ARRAYSIZE(kDutyCycles); ++j) {
dif_pwm_channel_config_t channel_config = {
.duty_cycle_a =
pwm_config.beats_per_pulse_cycle * kDutyCycles[j] / 100,
.duty_cycle_b = 0,
.phase_delay = 0,
.mode = kDifPwmModeFirmware,
.polarity = kDifPwmPolarityActiveHigh,
.blink_parameter_x = 0,
.blink_parameter_y = 0,
};
LOG_INFO("dity_cycle: %d", channel_config.duty_cycle_a);

CHECK_DIF_OK(dif_pwm_configure(&pwm, pwm_config));
CHECK_DIF_OK(
dif_pwm_configure_channel(&pwm, kDifPwmChannel0, channel_config));

// The goes low when the host is sampling.
bool not_sampling = true;
do {
CHECK_DIF_OK(dif_gpio_read(&gpio, 0, &not_sampling));
if (not_sampling) { // Debauce
busy_spin_micros(500);
CHECK_DIF_OK(dif_gpio_read(&gpio, 0, &not_sampling));
}
} while (not_sampling);

CHECK_DIF_OK(dif_pwm_phase_cntr_set_enabled(&pwm, kDifToggleEnabled));
CHECK_DIF_OK(dif_pwm_channel_set_enabled(&pwm, kDifPwmChannel0,
kDifToggleEnabled));

// The goes high when the host stop sampling.
do {
CHECK_DIF_OK(dif_gpio_read(&gpio, 0, &not_sampling));
} while (!not_sampling);

CHECK_DIF_OK(dif_pwm_channel_set_enabled(&pwm, kDifPwmChannel0,
kDifToggleDisabled));
CHECK_DIF_OK(dif_pwm_phase_cntr_set_enabled(&pwm, kDifToggleDisabled));
LOG_INFO("Sync: Disabled pwm");
}
}
return true;
}

0 comments on commit 4e228e9

Please sign in to comment.