|
8 | 8 | #include <stdbool.h> |
9 | 9 | #include <stdint.h> |
10 | 10 |
|
11 | | -// Check that we can write and read some GPIO registers |
12 | | -static bool reg_test(gpio_t gpio) |
| 11 | +// Drive a pattern (val) |
| 12 | +static void drive(gpio_t gpio, uint32_t masked_reg, uint32_t val) |
13 | 13 | { |
14 | | - uint32_t hal_val; |
| 14 | + gpio_write(gpio, masked_reg, 0XFFFF0000 | val); |
| 15 | +} |
15 | 16 |
|
16 | | - // Inputs |
17 | | - hal_val = 0; |
18 | | - for (int ii = 0; ii < GPIO_NUM_PINS; ii++) { |
19 | | - hal_val |= (gpio_read_pin(gpio, ii) << ii); |
20 | | - } |
21 | | - if (hal_val != DEV_READ(gpio + GPIO_REG_DATA_IN)) { |
22 | | - return false; |
| 17 | +// Wait for an expected pattern (compare_val). |
| 18 | +static void wait(gpio_t gpio, uint32_t compare_val) |
| 19 | +{ |
| 20 | + while (DEV_READ(gpio + GPIO_REG_DATA_IN) != compare_val) { |
23 | 21 | } |
| 22 | +} |
| 23 | + |
| 24 | +// Verifies GPIOs in partially output and input direction. The test distributes GPIOs as four equal |
| 25 | +// quarters. The idea is to drive first quarter of GPIOs as outputs and wait for a pattern to appear |
| 26 | +// on the second quarter of pins as inputs. Next, drive a pattern on the third quarter and waits for a |
| 27 | +// pattern to appear on the fourth quarter as inputs. Repeat the same process second time but with a |
| 28 | +// different pattern. |
| 29 | +// |
| 30 | +// The pattern driven on the outputs is going to be walking 1's (1, 10, 0100, 1000, ...) first and |
| 31 | +// then walking 0's (1110, 1101, 1011, 0111, ...) whereas it is all 1's then all 0's sequence for |
| 32 | +// the inputs. |
| 33 | +// |
| 34 | +// 1- Walk 1's on the first quarter of GPIOs in output mode. |
| 35 | +// 2- top_chip_dv_gpio_base_vseq will wait for walking 1's pattern to appear on the pads. Once it |
| 36 | +// sees that pattern, it will drive all 1's on to the second quarter. |
| 37 | +// 4- gpio_test waits for the pattern 0x0000FF80 on the GPIO pads by reading DATA_IN register. Then |
| 38 | +// it will walk 1's on the third quarter of pins and waits for pattern 0xFF80FF80. |
| 39 | +// 5- On the other side, the vseq waits for the walking 1's pattern on the third quarter of pins and |
| 40 | +// drive all 1's on the fourth quarter. |
| 41 | +// 6- After all that, gpio_test start to write 1's to the first and third quarter of pins in order to |
| 42 | +// drive walking 0's. Everything beyond that is similar but the expected driven sequence is going |
| 43 | +// to be 0's on the inputs and walking 0's on the outputs. |
| 44 | +static bool gpio_test(gpio_t gpio) |
| 45 | +{ |
| 46 | + // Enable the first and third quarter of pins in output mode |
| 47 | + gpio_set_all_oe(gpio, 0x00FF00FF); |
24 | 48 |
|
25 | | - // Outputs |
26 | | - hal_val = 0xC1A0; // Ciao! |
27 | | - for (int nn = 0; nn < 2; nn++) { |
28 | | - for (int ii = 0; ii < GPIO_NUM_PINS; ii++) { |
29 | | - gpio_write_pin(gpio, ii, ((hal_val >> ii) & 0x1)); |
| 49 | + // Current GPIOs pads state : 0x00000000 |
| 50 | + // |
| 51 | + // Walk 1's on the first quarter. vseq drives the second quarter with all 1's. Hence, the |
| 52 | + // expected value to wait for is 0xFF80, |
| 53 | + for (int i = 0; i < GPIO_NUM_PINS / 4; i++) { |
| 54 | + drive(gpio, GPIO_REG_MASKED_OUT_LOWER, 1 << i); |
| 55 | + if (i == ((GPIO_NUM_PINS / 4) - 1)) { |
| 56 | + wait(gpio, 0xFF80); |
30 | 57 | } |
31 | | - if (hal_val != DEV_READ(gpio + GPIO_REG_DIRECT_OUT)) { |
32 | | - return false; |
| 58 | + } |
| 59 | + |
| 60 | + // Current GPIOs pads state : 0x0000FF80 |
| 61 | + // |
| 62 | + // Walk 1's on the third quarter. vseq drives the fourth quarter with all 1's. Additionally, the |
| 63 | + // pads contains 0xFF80 by now on the first two quarters. Hence, the expected value to wait for |
| 64 | + // is 0xFF80FF80, |
| 65 | + for (int i = 0; i < GPIO_NUM_PINS / 4; i++) { |
| 66 | + drive(gpio, GPIO_REG_MASKED_OUT_UPPER, 1 << i); |
| 67 | + if (i == ((GPIO_NUM_PINS / 4) - 1)) { |
| 68 | + wait(gpio, 0xFF80FF80); |
33 | 69 | } |
34 | | - hal_val = ~hal_val; // invert to check for constant bits |
35 | 70 | } |
36 | 71 |
|
37 | | - // Output enables |
38 | | - hal_val = 0xB7EE; // Byee! |
39 | | - for (int nn = 0; nn < 2; nn++) { |
40 | | - for (int ii = 0; ii < GPIO_NUM_PINS; ii++) { |
41 | | - gpio_set_oe_pin(gpio, ii, ((hal_val >> ii) & 0x1)); |
| 72 | + // Current GPIOs pads state : 0xFF80FF80 |
| 73 | + // |
| 74 | + // Now, set the first and third quarter (which are enabled as outputs) to all 1's in order to |
| 75 | + // walk 0's on them. |
| 76 | + gpio_write(gpio, GPIO_REG_DIRECT_OUT, 0x00FF00FF); |
| 77 | + |
| 78 | + // Current GPIOs pads state : 0xFFFFFFFF |
| 79 | + // |
| 80 | + // Walk 0's on the first quarter of pins. vseq drives the second quarter with all 0's. |
| 81 | + // Hence, the expected value to wait for is 0xFFFF007F. |
| 82 | + for (int i = 0; i < GPIO_NUM_PINS / 4; i++) { |
| 83 | + drive(gpio, GPIO_REG_MASKED_OUT_LOWER, ~(1 << i)); |
| 84 | + if (i == ((GPIO_NUM_PINS / 4) - 1)) { |
| 85 | + wait(gpio, 0xFFFF007F); |
42 | 86 | } |
43 | | - if (hal_val != DEV_READ(gpio + GPIO_REG_DIRECT_OE)) { |
44 | | - return false; |
| 87 | + } |
| 88 | + |
| 89 | + // Current GPIOs pads state : 0xFFFF007F |
| 90 | + // |
| 91 | + // Walk 0's on the third quarter of pins. vseq drives the fourth quarter with all 0's. |
| 92 | + // Hence, the expected value to wait for is 0x007F007F. |
| 93 | + for (int i = 0; i < GPIO_NUM_PINS / 4; i++) { |
| 94 | + drive(gpio, GPIO_REG_MASKED_OUT_UPPER, ~(1 << i)); |
| 95 | + if (i == ((GPIO_NUM_PINS / 4) - 1)) { |
| 96 | + wait(gpio, 0x007F007F); |
45 | 97 | } |
46 | | - hal_val = ~hal_val; // invert to check for constant bits |
47 | 98 | } |
48 | 99 |
|
| 100 | + // Current GPIOs pads state : 0x007F007F |
| 101 | + |
49 | 102 | return true; |
50 | 103 | } |
51 | 104 |
|
52 | 105 | bool test_main() |
53 | 106 | { |
54 | 107 | gpio_t gpio = mocha_system_gpio(); |
55 | | - return reg_test(gpio); |
| 108 | + return gpio_test(gpio); |
56 | 109 | } |
0 commit comments