Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | /* * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ #include "test_shared_irq.h" struct shared_irq_fixture { unsigned int irq1; unsigned int irq2; unsigned int irq1_table_idx; unsigned int irq2_table_idx; unsigned int irq_priority; }; static struct shared_irq_fixture fixture; static void reset_test_vector(void) { int i; for (i = 0; i < TEST_VECTOR_SIZE; i++) { test_vector[i] = 0; } } static void dynamic_shared_irq_suite_after(void *data) { ARG_UNUSED(data); /* note: no need to check the state of the SW ISR tables after * all these disconnect operations. If there's something wrong * it should be detected by dynamic_shared_irq_suite_before(). */ arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_0, 0, 0); arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_1, (void *)1, 0); arch_irq_disconnect_dynamic(fixture.irq2, fixture.irq_priority, test_isr_2, (void *)2, 0); } static void dummy_isr(const void *data) { ARG_UNUSED(data); test_vector[0] = TEST_DUMMY_ISR_VAL; } static unsigned int get_irq_slot(unsigned int start) { unsigned int i, table_idx; for (i = start; i <= CONFIG_GEN_IRQ_START_VECTOR + CONFIG_NUM_IRQS - 1; i++) { table_idx = i - CONFIG_GEN_IRQ_START_VECTOR; if (_sw_isr_table[table_idx].isr == &z_irq_spurious) { test_vector[0] = 0; /* check to see if we can trigger this IRQ */ arch_irq_connect_dynamic(i, IRQ_PRIORITY, dummy_isr, NULL, 0); irq_enable(i); trigger_irq(i); /* wait a bit */ k_busy_wait(100); if (test_vector[0] == TEST_DUMMY_ISR_VAL) { /* found a valid INTID */ irq_disable(i); arch_irq_disconnect_dynamic(i, IRQ_PRIORITY, dummy_isr, NULL, 0); return i; } } } return TEST_INVALID_IRQ; } static void *dynamic_shared_irq_suite_setup(void) { fixture.irq1 = get_irq_slot(CONFIG_GEN_IRQ_START_VECTOR); zassert_true(fixture.irq1 != TEST_INVALID_IRQ, "no suitable value found for irq1"); fixture.irq2 = get_irq_slot(fixture.irq1 + 1); zassert_true(fixture.irq2 != TEST_INVALID_IRQ, "no suitable value found for irq2"); fixture.irq_priority = IRQ_PRIORITY; fixture.irq1_table_idx = fixture.irq1 - CONFIG_GEN_IRQ_START_VECTOR; fixture.irq2_table_idx = fixture.irq2 - CONFIG_GEN_IRQ_START_VECTOR; return NULL; } static void dynamic_shared_irq_suite_before(void *data) { ARG_UNUSED(data); arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_0, 0, 0); zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_0, "wrong _sw_isr_table ISR at irq1"); zassert_true(!_sw_isr_table[fixture.irq1_table_idx].arg, "wrong _sw_isr_table argument at irq1"); zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, "wrong client number at irq1"); arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_1, (void *)1, 0); zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == z_shared_isr, "wrong _sw_isr_table ISR at irq1"); zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == &z_shared_sw_isr_table[fixture.irq1_table_idx], "wrong _sw_isr_table argument at irq1"); zassert_true(z_shared_sw_isr_table[fixture.irq1_table_idx].client_num == 2, "wrong client number at irq1"); zassert_true(client_exists_at_index(test_isr_0, 0, fixture.irq1_table_idx, 0), "unexpected client data for irq1, index 0"); zassert_true(client_exists_at_index(test_isr_1, (void *)1, fixture.irq1_table_idx, 1), "unexpected client data for irq1, index 1"); arch_irq_connect_dynamic(fixture.irq2, fixture.irq_priority, test_isr_2, (void *)2, 0); zassert_true(_sw_isr_table[fixture.irq2_table_idx].isr == test_isr_2, "wrong _sw_isr_table ISR at irq2"); zassert_true(_sw_isr_table[fixture.irq2_table_idx].arg == (void *)2, "wrong _sw_isr_table argument at irq2"); zassert_true(!z_shared_sw_isr_table[fixture.irq2_table_idx].client_num, "wrong client number at irq2"); reset_test_vector(); } /** * @brief Test writing to a vector with a shared interrupt * * @ingroup kernel_interrupt_tests * * @details This tests if interrupts are dynamically shared successfully * (i.e: multiple ISR/arg pairs are called whenever the interrupt * they were registered for is triggered). */ ZTEST(shared_irq_feature, test_dynamic_shared_irq_write) { int i; irq_enable(fixture.irq1); irq_enable(fixture.irq2); trigger_irq(fixture.irq1); trigger_irq(fixture.irq2); /* wait 5ms before checking the results */ k_busy_wait(5000); for (i = 0; i < TEST_VECTOR_SIZE; i++) { zassert_true(test_vector[i] == result_vector[i], "wrong test_vector value at %d: 0x%x vs 0x%x", i, test_vector[i], result_vector[i]); } irq_disable(fixture.irq1); irq_disable(fixture.irq2); } /** * @brief Test writing to a vector after an ISR/arg disconnect. * * @ingroup kernel_interrupt_tests * * @details This tests if ISR/arg pairs are disconnected successfully * and the interrupts are "unshared" whenever a single ISR/arg pair is * left. */ ZTEST(shared_irq_feature, test_dynamic_shared_irq_disconnect_write) { int i; /* remove test_isr_0/NULL pair. After this statement we expect * irq1 to be unshared. */ arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_0, 0, 0); zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_1, "wrong _sw_isr_table ISR at irq1"); zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == (void *)1, "wrong _sw_isr_table arg at irq1"); zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, "wrong client number at irq1"); irq_enable(fixture.irq1); trigger_irq(fixture.irq1); /* wait 5ms before checking the results */ k_busy_wait(5000); for (i = 0; i < TEST_VECTOR_SIZE; i++) { if (i == 1) { zassert_true(test_vector[i] == result_vector[i], "wrong test_vector at %d: 0x%x vs 0x%x", i, test_vector[i], result_vector[i]); continue; } zassert_true(!test_vector[i], "wrong test_vector value at %d: 0x%x vs 0x%x", i, test_vector[i], result_vector[i]); } irq_disable(fixture.irq1); } ZTEST_SUITE(shared_irq_feature, NULL, dynamic_shared_irq_suite_setup, dynamic_shared_irq_suite_before, dynamic_shared_irq_suite_after, NULL); |