Skip to content

Commit

Permalink
[SiVal, pwm] Add pwm_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 7fffc15 commit aa19b72
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 46 deletions.
17 changes: 17 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2836,17 +2836,34 @@ opentitan_test(
{
"//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",
],
)

Expand Down
122 changes: 76 additions & 46 deletions sw/device/tests/pwm_smoketest.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,77 +5,107 @@
#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"

OTTF_DEFINE_TEST_CONFIG();

static const uint32_t kClocksKhz[] = [1, 5, 10];
static const uint32_t kDutyCicles[] = [0, 50, 100];

// Test harness will backdoor write to this variable.
static volatile uint8_t backdoor_start = false;

enum {
kDefaultTimeoutMicros = 50000,
};

static status_t pwm_pinmux(void) {

dif_pinmux_t pinmux;
mmio_region_t base_addr =
mmio_region_from_addr(TOP_EARLGREY_PINMUX_AON_BASE_ADDR);
CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux));

TRY(dif_pinmux_output_select(&pinmux, kTopEarlgreyPinmuxMioOutIoa8,
kTopEarlgreyPinmuxOutselPwmAonPwm0));
OTTF_DEFINE_TEST_CONFIG();

return OK_STATUS();
}
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 uint32_t compute_clk_div(uint32_t pwm_clk) {
return kClockFreqAonHz / (2 * pwm_clk)
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 base_addr = mmio_region_from_addr(TOP_EARLGREY_PWM_AON_BASE_ADDR);
CHECK_DIF_OK(dif_pwm_init(base_addr, &pwm));
CHECK_STATUS_OK(pwm_pinmux());

for (size_t i = 0; i < ARRAYSIZE(kClocksKhz);++i){

dif_pwm_config_t pwm_config = {
.clock_divisor = compute_clk_div(kClocksKhz[i] * 1000),
.beats_per_pulse_cycle = 100,
};
for (size_t j = 0; j < ARRAYSIZE(kDutyCicles);++j){
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 / (100 / kDutyCicles[j]) ,
.duty_cycle_b = 0,
.phase_delay = 0,
.mode = kDifPwmModeFirmware,
.polarity = kDifPwmPolarityActiveHigh,
.blink_parameter_x = 0,
.blink_parameter_y = 0,
.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,
};

OTTF_WAIT_FOR(backdoor_start, kDefaultTimeoutMicros);
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));
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));
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);

busy_spin_micros(50 * 1000);
backdoor_start = false;
CHECK_DIF_OK(dif_pwm_channel_set_enabled(&pwm, kDifPwmChannel0, kDifToggleDisable));
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;
Expand Down

0 comments on commit aa19b72

Please sign in to comment.