| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| #include <assert.h> |
| #include <limits.h> |
| #include <stdbool.h> |
| #include <stdint.h> |
| |
| #include "sw/device/lib/base/math.h" |
| #include "sw/device/lib/base/mmio.h" |
| #include "sw/device/lib/dif/dif_aes.h" |
| #include "sw/device/lib/dif/dif_alert_handler.h" |
| #include "sw/device/lib/dif/dif_clkmgr.h" |
| #include "sw/device/lib/dif/dif_flash_ctrl.h" |
| #include "sw/device/lib/dif/dif_hmac.h" |
| #include "sw/device/lib/dif/dif_kmac.h" |
| #include "sw/device/lib/dif/dif_otbn.h" |
| #include "sw/device/lib/dif/dif_rstmgr.h" |
| #include "sw/device/lib/dif/dif_rv_plic.h" |
| #include "sw/device/lib/dif/dif_spi_host.h" |
| #include "sw/device/lib/dif/dif_usbdev.h" |
| #include "sw/device/lib/runtime/ibex.h" |
| #include "sw/device/lib/runtime/irq.h" |
| #include "sw/device/lib/runtime/log.h" |
| #include "sw/device/lib/testing/alert_handler_testutils.h" |
| #include "sw/device/lib/testing/flash_ctrl_testutils.h" |
| #include "sw/device/lib/testing/rand_testutils.h" |
| #include "sw/device/lib/testing/rv_plic_testutils.h" |
| #include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h" |
| #include "sw/device/lib/testing/test_framework/check.h" |
| #include "sw/device/lib/testing/test_framework/ottf_main.h" |
| |
| #include "aes_regs.h" |
| #include "alert_handler_regs.h" |
| #include "hmac_regs.h" |
| #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" |
| #include "i2c_regs.h" |
| #include "kmac_regs.h" |
| #include "otbn_regs.h" |
| #include "spi_host_regs.h" |
| #include "sw/device/lib/testing/autogen/isr_testutils.h" |
| #include "usbdev_regs.h" |
| |
| OTTF_DEFINE_TEST_CONFIG(); |
| |
| static dif_rv_plic_t plic; |
| static dif_alert_handler_t alert_handler; |
| static dif_clkmgr_t clkmgr; |
| static dif_spi_host_t spi_host0; |
| static dif_spi_host_t spi_host1; |
| static dif_usbdev_t usbdev; |
| static dif_aes_t aes; |
| static dif_hmac_t hmac; |
| static dif_kmac_t kmac; |
| static dif_otbn_t otbn; |
| static dif_rstmgr_t rstmgr; |
| static dif_flash_ctrl_state_t flash_ctrl; |
| |
| static const uint32_t kPlicTarget = kTopEarlgreyPlicTargetIbex0; |
| |
| static plic_isr_ctx_t plic_ctx = { |
| .rv_plic = &plic, |
| .hart_id = kPlicTarget, |
| }; |
| |
| /** |
| * Depends on the clock domain, sometimes alert handler will trigger a spurious |
| * alert after the alert timeout. (Issue #2321) |
| * So we allow class A interrupt to fire after the real timeout interrupt is |
| * triggered. |
| */ |
| static alert_handler_isr_ctx_t alert_handler_ctx = { |
| .alert_handler = &alert_handler, |
| .plic_alert_handler_start_irq_id = kTopEarlgreyPlicIrqIdAlertHandlerClassa, |
| .expected_irq = kDifAlertHandlerIrqClassb, |
| .is_only_irq = false, |
| }; |
| |
| /** |
| * Initialize the peripherals used in this test. |
| */ |
| static void init_peripherals(void) { |
| mmio_region_t base_addr = |
| mmio_region_from_addr(TOP_EARLGREY_RV_PLIC_BASE_ADDR); |
| CHECK_DIF_OK(dif_rv_plic_init(base_addr, &plic)); |
| |
| base_addr = mmio_region_from_addr(TOP_EARLGREY_ALERT_HANDLER_BASE_ADDR); |
| CHECK_DIF_OK(dif_alert_handler_init(base_addr, &alert_handler)); |
| |
| CHECK_DIF_OK(dif_clkmgr_init( |
| mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr)); |
| |
| CHECK_DIF_OK(dif_spi_host_init( |
| mmio_region_from_addr(TOP_EARLGREY_SPI_HOST0_BASE_ADDR), &spi_host0)); |
| |
| CHECK_DIF_OK(dif_spi_host_init( |
| mmio_region_from_addr(TOP_EARLGREY_SPI_HOST1_BASE_ADDR), &spi_host1)); |
| |
| CHECK_DIF_OK(dif_usbdev_init( |
| mmio_region_from_addr(TOP_EARLGREY_USBDEV_BASE_ADDR), &usbdev)); |
| |
| CHECK_DIF_OK( |
| dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes)); |
| |
| CHECK_DIF_OK( |
| dif_hmac_init(mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR), &hmac)); |
| |
| CHECK_DIF_OK( |
| dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac)); |
| |
| CHECK_DIF_OK( |
| dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn)); |
| |
| CHECK_DIF_OK(dif_rstmgr_init( |
| mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr)); |
| |
| // Initialize flash_ctrl |
| CHECK_DIF_OK(dif_flash_ctrl_init_state( |
| &flash_ctrl, |
| mmio_region_from_addr(TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR))); |
| } |
| |
| // List of alerts |
| static const uint32_t aes_alerts[] = {kTopEarlgreyAlertIdAesFatalFault, |
| kTopEarlgreyAlertIdAesRecovCtrlUpdateErr}; |
| static const uint32_t hmac_alerts[] = {kTopEarlgreyAlertIdHmacFatalFault}; |
| static const uint32_t kmac_alerts[] = { |
| kTopEarlgreyAlertIdKmacFatalFaultErr, |
| kTopEarlgreyAlertIdKmacRecovOperationErr}; |
| static const uint32_t otbn_alerts[] = {kTopEarlgreyAlertIdOtbnFatal, |
| kTopEarlgreyAlertIdOtbnRecov}; |
| static const uint32_t spihost0_alerts[] = { |
| kTopEarlgreyAlertIdSpiHost0FatalFault}; |
| static const uint32_t spihost1_alerts[] = { |
| kTopEarlgreyAlertIdSpiHost1FatalFault}; |
| static const uint32_t usbdev_alerts[] = {kTopEarlgreyAlertIdUsbdevFatalFault}; |
| |
| static const uint32_t num_aes_alerts = ARRAYSIZE(aes_alerts); |
| static const uint32_t num_hmac_alerts = ARRAYSIZE(hmac_alerts); |
| static const uint32_t num_kmac_alerts = ARRAYSIZE(kmac_alerts); |
| static const uint32_t num_otbn_alerts = ARRAYSIZE(otbn_alerts); |
| static const uint32_t num_spihost0_alerts = ARRAYSIZE(spihost0_alerts); |
| static const uint32_t num_spihost1_alerts = ARRAYSIZE(spihost1_alerts); |
| static const uint32_t num_usbdev_alerts = ARRAYSIZE(usbdev_alerts); |
| |
| static const size_t num_alerts = |
| ARRAYSIZE(aes_alerts) + ARRAYSIZE(hmac_alerts) + ARRAYSIZE(kmac_alerts) + |
| ARRAYSIZE(otbn_alerts) + ARRAYSIZE(spihost0_alerts) + |
| ARRAYSIZE(spihost1_alerts) + ARRAYSIZE(usbdev_alerts); |
| |
| /** |
| * A structure to keep the info for peripheral IPs |
| */ |
| typedef struct test { |
| /** |
| * Name of the peripheral. |
| */ |
| const char *name; |
| /** |
| * Base address for the peripheral. |
| */ |
| uintptr_t base; |
| /** |
| * Offset to the peripheral's ALERT_TEST register. |
| */ |
| ptrdiff_t offset; |
| /** |
| * Handle to the DIF object for this peripheral. |
| */ |
| void *dif; |
| /** |
| * The fatal_alert pin in peripheral's ALERT_TEST reg |
| */ |
| uint32_t fatal_alert_bit; |
| /** |
| * List of Alert IDs for the peripheral |
| */ |
| const uint32_t *alert_ids; |
| /** |
| * number of alerts for the peripheral |
| */ |
| const uint32_t num_alert_peri; |
| /** |
| * The index of this device's clk in the clock manager. |
| */ |
| uint32_t clk_index; |
| /** |
| * Is the clock hinteable (==true) or gateable(==false). |
| */ |
| bool is_hintable; |
| } test_t; |
| |
| // The array of the peripherals |
| static const test_t kPeripherals[] = { |
| // Hintable clock IPS |
| { |
| .name = "AES", |
| .base = TOP_EARLGREY_AES_BASE_ADDR, |
| .offset = AES_ALERT_TEST_REG_OFFSET, |
| .dif = &aes, |
| .fatal_alert_bit = kDifAesAlertFatalFault, |
| .alert_ids = aes_alerts, |
| .num_alert_peri = num_aes_alerts, |
| .clk_index = kTopEarlgreyHintableClocksMainAes, |
| .is_hintable = true, |
| }, |
| { |
| .name = "HMAC", |
| .base = TOP_EARLGREY_HMAC_BASE_ADDR, |
| .offset = HMAC_ALERT_TEST_REG_OFFSET, |
| .dif = &hmac, |
| .fatal_alert_bit = kDifHmacAlertFatalFault, |
| .alert_ids = hmac_alerts, |
| .num_alert_peri = num_hmac_alerts, |
| .clk_index = kTopEarlgreyHintableClocksMainHmac, |
| .is_hintable = true, |
| }, |
| { |
| .name = "KMAC", |
| .base = TOP_EARLGREY_KMAC_BASE_ADDR, |
| .offset = KMAC_ALERT_TEST_REG_OFFSET, |
| .dif = &kmac, |
| .fatal_alert_bit = kDifKmacAlertFatalFault, |
| .alert_ids = kmac_alerts, |
| .num_alert_peri = num_kmac_alerts, |
| .clk_index = kTopEarlgreyHintableClocksMainKmac, |
| .is_hintable = true, |
| }, |
| { |
| .name = "OTBN", |
| .base = TOP_EARLGREY_OTBN_BASE_ADDR, |
| .offset = OTBN_ALERT_TEST_REG_OFFSET, |
| .dif = &otbn, |
| .fatal_alert_bit = kDifOtbnAlertFatal, |
| .alert_ids = otbn_alerts, |
| .num_alert_peri = num_otbn_alerts, |
| .clk_index = kTopEarlgreyHintableClocksMainOtbn, |
| .is_hintable = true, |
| }, |
| // Gateable clock IPs |
| { |
| .name = "SPI_HOST0", |
| .base = TOP_EARLGREY_SPI_HOST0_BASE_ADDR, |
| .offset = SPI_HOST_ALERT_TEST_REG_OFFSET, |
| .dif = &spi_host0, |
| .fatal_alert_bit = 0, |
| .alert_ids = spihost0_alerts, |
| .num_alert_peri = num_spihost0_alerts, |
| .clk_index = kTopEarlgreyGateableClocksIoPeri, |
| .is_hintable = false, |
| }, |
| { |
| .name = "SPI_HOST1", |
| .base = TOP_EARLGREY_SPI_HOST1_BASE_ADDR, |
| .offset = SPI_HOST_ALERT_TEST_REG_OFFSET, |
| .dif = &spi_host1, |
| .fatal_alert_bit = 0, |
| .alert_ids = spihost1_alerts, |
| .num_alert_peri = num_spihost1_alerts, |
| .clk_index = kTopEarlgreyGateableClocksIoDiv2Peri, |
| .is_hintable = false, |
| }, |
| { |
| .name = "USB", |
| .base = TOP_EARLGREY_USBDEV_BASE_ADDR, |
| .offset = USBDEV_ALERT_TEST_REG_OFFSET, |
| .dif = &usbdev, |
| .fatal_alert_bit = 0, |
| .alert_ids = usbdev_alerts, |
| .num_alert_peri = num_usbdev_alerts, |
| .clk_index = kTopEarlgreyGateableClocksUsbPeri, |
| .is_hintable = false, |
| }, |
| }; |
| |
| /** |
| * Configure and enable alerts of `num_peripheral` peripherals starting from the |
| * `first_peripheral`. |
| * @param num_peripherals The number of peripherals, of which alerts will be |
| * enabled |
| * @param first_peripheral The address of the first peripheral in the range |
| * @param ping_timeout The timeout value for the ping timer object. |
| */ |
| static void alert_handler_config_peripherals(uint32_t num_peripherals, |
| const test_t *first_peripheral, |
| uint32_t ping_timeout) { |
| dif_alert_handler_alert_t alerts[num_alerts]; |
| dif_alert_handler_class_t alert_classes[num_alerts]; |
| |
| // Enable all alerts coming from the chosen peripherals |
| // Configure them as Class A. |
| size_t array_idx = 0; |
| test_t *peri_ptr; |
| for (int ii = 0; ii < num_peripherals; ii++) { |
| peri_ptr = (test_t *)first_peripheral + ii; |
| for (int jj = 0; jj < peri_ptr->num_alert_peri; jj++) { |
| alerts[array_idx] = peri_ptr->alert_ids[jj]; |
| alert_classes[array_idx] = kDifAlertHandlerClassA; |
| array_idx++; |
| } |
| } |
| |
| // Enable the alert_ping_fail local alert and configure that as Class B. |
| dif_alert_handler_local_alert_t loc_alerts[] = { |
| kDifAlertHandlerLocalAlertAlertPingFail}; |
| dif_alert_handler_class_t loc_alert_classes[] = {kDifAlertHandlerClassB}; |
| |
| dif_alert_handler_escalation_phase_t esc_phases[] = { |
| {.phase = kDifAlertHandlerClassStatePhase0, |
| .signal = 0, |
| .duration_cycles = 2000}}; |
| |
| dif_alert_handler_class_config_t class_config = { |
| .auto_lock_accumulation_counter = kDifToggleDisabled, |
| .accumulator_threshold = 0, |
| .irq_deadline_cycles = 10000, |
| .escalation_phases = esc_phases, |
| .escalation_phases_len = ARRAYSIZE(esc_phases), |
| .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1, |
| }; |
| |
| dif_alert_handler_class_config_t class_configs[] = {class_config, |
| class_config}; |
| |
| dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA, |
| kDifAlertHandlerClassB}; |
| dif_alert_handler_config_t config = { |
| .alerts = alerts, |
| .alert_classes = alert_classes, |
| .alerts_len = array_idx, |
| .local_alerts = loc_alerts, |
| .local_alert_classes = loc_alert_classes, |
| .local_alerts_len = ARRAYSIZE(loc_alerts), |
| .classes = classes, |
| .class_configs = class_configs, |
| .classes_len = ARRAYSIZE(class_configs), |
| .ping_timeout = ping_timeout, |
| }; |
| |
| alert_handler_testutils_configure_all(&alert_handler, config, |
| kDifToggleEnabled); |
| // Enables alert handler irq. |
| CHECK_DIF_OK(dif_alert_handler_irq_set_enabled( |
| &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled)); |
| |
| CHECK_DIF_OK(dif_alert_handler_irq_set_enabled( |
| &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled)); |
| } |
| |
| /** |
| * A utility function to enable/disable hintable and gateable clocks |
| */ |
| void set_peripheral_clock(const test_t *peripheral, |
| dif_toggle_t new_clk_state) { |
| dif_toggle_t clk_state; |
| if (peripheral->is_hintable) { |
| // Set the new clock state |
| CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint( |
| &clkmgr, peripheral->clk_index, new_clk_state)); |
| // Verify the new clock state |
| CHECK_DIF_OK(dif_clkmgr_hintable_clock_get_hint( |
| &clkmgr, peripheral->clk_index, &clk_state)); |
| CHECK(clk_state == new_clk_state, |
| "intended_clk_state = %d, received_clk_state = %d", new_clk_state, |
| clk_state); |
| |
| } else { |
| CHECK_DIF_OK(dif_clkmgr_gateable_clock_set_enabled( |
| &clkmgr, peripheral->clk_index, new_clk_state)); |
| // Verify the new clock state |
| CHECK_DIF_OK(dif_clkmgr_gateable_clock_get_enabled( |
| &clkmgr, peripheral->clk_index, &clk_state)); |
| CHECK(clk_state == new_clk_state, |
| "intended_clk_state = %d, received_clk_state = %d", new_clk_state, |
| clk_state); |
| } |
| }; |
| |
| /** |
| * A utility function to wait enough until the alert handler pings a peripheral |
| * alert |
| */ |
| void wait_enough_for_alert_ping() { |
| // wait enough |
| if (kDeviceType == kDeviceFpgaCw310) { |
| // NUM_ALERTS*2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz) |
| // (2**6)*2*4*(2**16)*(400ns) = 12.8s |
| busy_spin_micros(1000 * 12800); |
| } else if (kDeviceType == kDeviceSimDV) { |
| // NUM_ALERTS*2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz) |
| // (2**6)*2*4*(2**3)*(40ns) = 160us |
| busy_spin_micros(160); |
| } else { |
| // Verilator |
| // NUM_ALERTS*2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz) |
| // (2**6)*2*4*(2**16)*(8us) = 256s |
| // This seems to be impractical for the current clock frequency config |
| // of the Verilator tests (kClockFreqPeripheralHz = 125K). |
| LOG_FATAL("SUPPORTED PLATFORMS: DV and FPGA"); |
| LOG_FATAL("TO SUPPORT THE PLATFORM %d, COMPUTE THE RIGHT WAIT-TIME", |
| kDeviceType); |
| } |
| } |
| |
| /** |
| * External ISR. |
| * |
| * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt |
| * line to the CPU, which results in a call to this OTTF ISR. This ISR |
| * overrides the default OTTF implementation. |
| */ |
| void ottf_external_isr(void) { |
| top_earlgrey_plic_peripheral_t peripheral_serviced; |
| dif_alert_handler_irq_t irq_serviced; |
| isr_testutils_alert_handler_isr(plic_ctx, alert_handler_ctx, |
| &peripheral_serviced, &irq_serviced); |
| CHECK(peripheral_serviced == kTopEarlgreyPlicPeripheralAlertHandler, |
| "Interurpt from unexpected peripheral: %d", peripheral_serviced); |
| } |
| |
| enum { |
| // Non-volatile counter for the test steps on FPGA. |
| kCounterTestSteps = 0, |
| }; |
| |
| // This function will run after every device reset |
| bool test_main(void) { |
| init_peripherals(); |
| |
| // A generic loop variable |
| int ii; |
| // To keep the test results |
| bool is_cause; |
| |
| // The test consists of multiple test phases |
| // Each test phase consists of ARRAYSIZE(kPeripherals) steps |
| // At every step, a specific peripheral is tested |
| size_t test_phase; |
| size_t test_step_cnt; |
| size_t peri_idx; |
| |
| // Need a NVM counter to keep the test-step info |
| // between resets on the FPGA. |
| if (kDeviceType == kDeviceFpgaCw310) { |
| // Enable flash access |
| flash_ctrl_testutils_default_region_access(&flash_ctrl, |
| /*rd_en*/ true, |
| /*prog_en*/ true, |
| /*erase_en*/ true, |
| /*scramble_en*/ false, |
| /*ecc_en*/ false, |
| /*he_en*/ false); |
| |
| test_step_cnt = flash_ctrl_testutils_counter_get(kCounterTestSteps); |
| if (test_step_cnt == 256) { |
| flash_ctrl_testutils_counter_init_zero(&flash_ctrl, kCounterTestSteps); |
| test_step_cnt = flash_ctrl_testutils_counter_get(kCounterTestSteps); |
| } |
| } else { |
| // Initialize the test_step counter to zero for the simulation |
| test_step_cnt = 0; |
| } |
| |
| /* TEST PHASE #0: NEGATIVE TESTING (FPGA-ONLY) |
| |
| The timeout value is set to 2 |
| All of the alerts should trigger ping_timeout_alert |
| if they are not clock_gated |
| TEST: for_each_peripheral |
| 1- Disable the clock |
| 2- Enable the corresponding alerts |
| 3- Wait long enough |
| 4- Confirm that ping_timeout has not been triggered |
| 5- Reset the the device to test the next peripheral |
| */ |
| while (test_step_cnt < 1 * ARRAYSIZE(kPeripherals)) { |
| // Run the negative test only on the FPGA |
| // This will save the test time in the simulation |
| if (kDeviceType == kDeviceFpgaCw310) { |
| // Read the test_step_cnt and compute the test phase |
| // amd the peripheral ID to test |
| test_step_cnt = flash_ctrl_testutils_counter_get(kCounterTestSteps); |
| test_phase = test_step_cnt / ARRAYSIZE(kPeripherals); |
| peri_idx = test_step_cnt - (test_phase)*ARRAYSIZE(kPeripherals); |
| |
| // Wait for a random time <= 1024us |
| busy_spin_micros(rand_testutils_gen32_range(1, 1024)); |
| |
| // Disable the clock of the peripheral |
| set_peripheral_clock(&kPeripherals[peri_idx], kDifToggleDisabled); |
| |
| alert_handler_config_peripherals( |
| /*num_peripherals*/ 1, /* *first_peripheral*/ &kPeripherals[peri_idx], |
| /*ping_timeout*/ 2); |
| |
| // wait enough until the alert handler pings the peripheral |
| wait_enough_for_alert_ping(); |
| |
| // Check the ping_timeout alert status |
| CHECK_DIF_OK(dif_alert_handler_local_alert_is_cause( |
| &alert_handler, kDifAlertHandlerLocalAlertAlertPingFail, &is_cause)); |
| CHECK(!is_cause, |
| "Expected response is ping_timeout_fail= 0! But we got " |
| "ping_timrout_fail = 1 for peripheral[%d]", |
| peri_idx); |
| |
| // Enable the clock again |
| set_peripheral_clock(&kPeripherals[peri_idx], kDifToggleEnabled); |
| |
| // Increment the test_step counter |
| flash_ctrl_testutils_counter_increment(&flash_ctrl, kCounterTestSteps); |
| // Request system reset to unlock the alert handler config and test the |
| // next peripheral |
| CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr)); |
| } else { |
| // For the simulation, only increment the test_step counter |
| // to procced to the next phase without resetting the device |
| test_step_cnt++; |
| } |
| } |
| |
| /* TEST PHASE #1: TEST THE REGULAR CONFIG |
| |
| The timeout value is set to 256 |
| None of the alerts should trigger ping_timeout_alert |
| TEST: |
| enable_alerts (all_peripherals, timeout=256) |
| for_each_peripheral |
| 1- wait for random time |
| 2- Disable the peripheral's clock |
| 3- Wait long enough |
| 4- Confirm that ping_timeout has not been triggered |
| */ |
| |
| // Enable and lock the all peripherals' alerts at the beginning of the PHASE |
| // #1 |
| if (test_step_cnt == 1 * ARRAYSIZE(kPeripherals)) { |
| alert_handler_config_peripherals( |
| /*num_peripherals*/ ARRAYSIZE(kPeripherals), |
| /* *first_peripheral*/ &kPeripherals[0], /*ping_timeout*/ 256); |
| } |
| |
| while (test_step_cnt < 2 * ARRAYSIZE(kPeripherals)) { |
| // Read the test_step_cnt and compute the test phase |
| // amd the peripheral ID to test |
| test_phase = test_step_cnt / ARRAYSIZE(kPeripherals); |
| peri_idx = test_step_cnt - (test_phase)*ARRAYSIZE(kPeripherals); |
| |
| // Wait for a random time <= 1024us |
| busy_spin_micros(rand_testutils_gen32_range(1, 1024)); |
| |
| // Disable the clock of the peripheral |
| set_peripheral_clock(&kPeripherals[peri_idx], kDifToggleDisabled); |
| |
| // wait enough until the alert handler pings the peripheral |
| wait_enough_for_alert_ping(); |
| |
| // Check the alert status |
| CHECK_DIF_OK(dif_alert_handler_local_alert_is_cause( |
| &alert_handler, kDifAlertHandlerLocalAlertAlertPingFail, &is_cause)); |
| CHECK(!is_cause, "Expected response: No alert_ping_fail! but we got %d", |
| is_cause); |
| |
| // Enable the clock of the peripheral again |
| set_peripheral_clock(&kPeripherals[peri_idx], kDifToggleEnabled); |
| |
| // Increment the test counter |
| test_step_cnt++; |
| } |
| |
| return true; |
| } |