ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_interface_gpio_interrupt_test.c
Go to the documentation of this file.
2#if RUUVI_RUN_TESTS
4#include "ruuvi_driver_test.h"
9#include <stdlib.h>
10
11static uint8_t num_int_trigs = 0;
12static ri_gpio_evt_t last_evt;
13
14void on_interrupt (ri_gpio_evt_t evt)
15{
16 num_int_trigs ++;
17 last_evt = evt;
18}
19
20
30 const rd_test_gpio_cfg_t cfg)
31{
32 rd_status_t status = RD_SUCCESS;
33 const uint8_t interrupt_table_size = RI_GPIO_INTERRUPT_TEST_TABLE_SIZE;
35
36 if ( ( (cfg.input % 32) + ( (cfg.input >> 8) * 32)) > interrupt_table_size
37 || ( (cfg.output % 32) + ( (cfg.input >> 8) * 32)) > interrupt_table_size)
38 {
39 status |= RD_ERROR_NO_MEM;
40 }
41
42 if (RD_SUCCESS == status)
43 {
44 // - Initialization must return @c RD_ERROR_INVALID_STATE if GPIO is uninitialized
45 status |= ri_gpio_uninit();
46 status |= ri_gpio_interrupt_init (interrupt_table, interrupt_table_size);
47
48 if (RD_ERROR_INVALID_STATE != status)
49 {
51 }
52 else
53 {
54 status = RD_SUCCESS;
55 }
56 }
57
58 if (RD_SUCCESS == status)
59 {
60 // - Initialization must return @c RD_SUCCESS on first call.
61 status = ri_gpio_init();
62 status |= ri_gpio_interrupt_init (interrupt_table, interrupt_table_size);
63
64 if (RD_SUCCESS != status)
65 {
67 }
68 else
69 {
70 // - Initialization must return @c RD_ERROR_INVALID_STATE on second call.
71 status = ri_gpio_interrupt_init (interrupt_table, interrupt_table_size);
72
73 if (RD_ERROR_INVALID_STATE != status)
74 {
76 }
77
78 // - Initialization must return @c RD_SUCCESS after uninitializtion.
79 status = ri_gpio_interrupt_uninit();
80 status |= ri_gpio_interrupt_init (interrupt_table, interrupt_table_size);
81
82 if (RD_SUCCESS != status)
83 {
85 return RD_ERROR_SELFTEST;
86 }
87 }
88 }
89
90 if (RD_SUCCESS == status)
91 {
92 // - Initialization must return @c RD_ERROR_NULL if interrupt handler table is @c NULL.
93 status = ri_gpio_interrupt_init (NULL, interrupt_table_size);
94
95 if (RD_ERROR_NULL != status)
96 {
98 }
99 else
100 {
101 status = RD_SUCCESS;
102 }
103 }
104
105 status |= ri_gpio_interrupt_uninit();
106 status |= ri_gpio_uninit();
107 return status;
108}
109
111 const rd_test_gpio_cfg_t cfg)
112{
113 rd_status_t status = RD_SUCCESS;
114 const uint8_t interrupt_table_size = RI_GPIO_INTERRUPT_TEST_TABLE_SIZE;
116 interrupt_table[RI_GPIO_INTERRUPT_TEST_TABLE_SIZE] = {0};
117
118 if ( ( (cfg.input % 32) + ( (cfg.input >> 8) * 32)) > interrupt_table_size
119 || ( (cfg.output % 32) + ( (cfg.input >> 8) * 32)) > interrupt_table_size)
120 {
121 return RD_ERROR_NO_MEM;
122 }
123
124 // - Return RD_ERROR_INVALID_STATE if GPIO or GPIO_INTERRUPT are not initialized
127 status |= ri_gpio_interrupt_enable (cfg.input,
129
130 if (RD_ERROR_INVALID_STATE != status)
131 {
133 }
134 else
135 {
136 status = RD_SUCCESS;
137 }
138
139 if (RD_SUCCESS == status)
140 {
141 // - Interrupt function shall be called exactly once when input is configured as low-to-high while input is low and
142 // input goes low-to-high, high-to-low.
143 num_int_trigs = 0;
144 status = ri_gpio_init();
145 status |= ri_gpio_interrupt_init (interrupt_table, interrupt_table_size);
146 status |= ri_gpio_configure (cfg.output,
148 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
149 status |= ri_gpio_interrupt_enable (cfg.input,
151 status |= ri_gpio_write (cfg.output, RI_GPIO_HIGH);
152 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
153
154 if (RD_SUCCESS != status || 1 != num_int_trigs)
155 {
157 status |= RD_ERROR_SELFTEST;
158 }
159 }
160
161 if (RD_SUCCESS == status)
162 {
163 // - Interrupt function shall not be called after interrupt has been disabled
164 status |= ri_gpio_interrupt_disable (cfg.input);
165 status |= ri_gpio_write (cfg.output, RI_GPIO_HIGH);
166 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
167
168 if (RD_SUCCESS != status || 1 != num_int_trigs)
169 {
171 status |= RD_ERROR_SELFTEST;
172 }
173
174 // - Interrupt function maybe be called once or twice when input is configured as high-to-low while input is low and
175 // input goes low-to-high, high-to-low. i.e. Triggering during activation of test.
176 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
177 num_int_trigs = 0;
178 status |= ri_gpio_interrupt_enable (cfg.input,
180 status |= ri_gpio_write (cfg.output, RI_GPIO_HIGH);
181 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
182
183 if (RD_SUCCESS != status
184 || ( (1 != num_int_trigs) && (2 != num_int_trigs)))
185 {
187 status |= RD_ERROR_SELFTEST;
188 }
189
190 // - Interrupt function shall be called exactly twice when input is configured as toggle while input is low and
191 // input goes low-to-high, high-to-low.
192 status = ri_gpio_write (cfg.output, RI_GPIO_LOW);
193 status |= ri_gpio_interrupt_disable (cfg.input);
194 num_int_trigs = 0;
195 status |= ri_gpio_interrupt_enable (cfg.input,
197 status |= ri_gpio_write (cfg.output, RI_GPIO_HIGH);
198 status |= ri_gpio_write (cfg.output, RI_GPIO_LOW);
199
200 if (RD_SUCCESS != status || 2 != num_int_trigs)
201 {
203 status |= RD_ERROR_SELFTEST;
204 }
205
206 // - Interrupt pin shall be at logic HIGH when interrupt is enabled with a pull-up and the pin is not loaded externally
207 status = ri_gpio_configure (cfg.output,
209 status |= ri_gpio_interrupt_disable (cfg.input);
210 num_int_trigs = 0;
211 status |= ri_gpio_interrupt_enable (cfg.input,
213 ri_gpio_state_t state;
214 status |= ri_gpio_read (cfg.output, &state);
215
216 if (RD_SUCCESS != status || RI_GPIO_HIGH != state)
217 {
219 status |= RD_ERROR_SELFTEST;
220 }
221
222 // - Interrupt pin shall be at logic LOW when interrupt is enabled with a pull-down and the pin is not loaded externally
224 status |= ri_gpio_interrupt_disable (cfg.input);
225 num_int_trigs = 0;
226 status |= ri_gpio_interrupt_enable (cfg.input,
228 on_interrupt);
229 status |= ri_gpio_read (cfg.output, &state);
230
231 if (RD_SUCCESS != status || RI_GPIO_LOW != state)
232 {
234 status |= RD_ERROR_SELFTEST;
235 }
236 }
237
238 status |= ri_gpio_interrupt_disable (cfg.input);
239 status |= ri_gpio_interrupt_uninit();
240 status |= ri_gpio_uninit();
241 return status;
242}
244 const ri_gpio_id_t input, const ri_gpio_id_t output)
245{
246 rd_status_t status;
248 cfg.input = input;
249 cfg.output = output;
250 printfp ("\"gpio_interrupt\":{\r\n");
251 printfp ("\"init\":");
252 status = ri_gpio_interrupt_test_init (cfg);
253
254 if (RD_SUCCESS == status)
255 {
256 printfp ("\"pass\",\r\n");
257 }
258 else
259 {
260 printfp ("\"fail\",\r\n");
261 }
262
263 printfp ("\"enable\":");
264 status = ri_gpio_interrupt_test_enable (cfg);
265
266 if (RD_SUCCESS == status)
267 {
268 printfp ("\"pass\"\r\n");
269 }
270 else
271 {
272 printfp ("\"fail\"\r\n");
273 }
274
275 printfp ("},\r\n");
276 return (RD_SUCCESS != status);
277}
278#endif
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_NO_MEM
No Memory for operation.
#define RD_ERROR_SELFTEST
Self-test fail.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
rd_status_t ri_gpio_uninit(void)
Uninitializes GPIO module. Call this to reset GPIO to High-Z mode. After uninitialization all GPIO pi...
rd_status_t ri_gpio_interrupt_enable(const ri_gpio_id_t pin, const ri_gpio_slope_t slope, const ri_gpio_mode_t mode, const ri_gpio_interrupt_fp_t handler)
Enable interrupt on a pin.
rd_status_t ri_gpio_interrupt_test_init(const rd_test_gpio_cfg_t cfg)
Test GPIO interrupt initialization.
rd_status_t ri_gpio_configure(const ri_gpio_id_t pin, const ri_gpio_mode_t mode)
Configure a pin of a port into a mode. If there are several ports the platform driver must implement ...
#define RI_GPIO_INTERRUPT_TEST_TABLE_SIZE
Fixed 64 interrupt table size, adjust this if some device has more than 2 ports with 32 gpios each.
rd_status_t ri_gpio_interrupt_init(ri_gpio_interrupt_fp_t *const interrupt_table, const uint16_t max_interrupts)
Initialize interrupt functionality to GPIO. Takes address of interrupt table as a pointer to avoid ty...
void(* ri_gpio_interrupt_fp_t)(const ri_gpio_evt_t)
rd_status_t ri_gpio_interrupt_test_enable(const rd_test_gpio_cfg_t cfg)
Test enabling interrupt on a pin.
rd_status_t ri_gpio_interrupt_uninit(void)
Uninitialize interrupt functionality of GPIO.
rd_status_t ri_gpio_interrupt_disable(const ri_gpio_id_t pin)
Disable interrupt on a pin.
rd_status_t ri_gpio_init(void)
Initializes GPIO module. Call this before other GPIO functions. After initialization all GPIO pins sh...
bool ri_gpio_interrupt_run_integration_test(const rd_test_print_fp printfp, const ri_gpio_id_t input, const ri_gpio_id_t output)
Run all GPIO interrupt integration tests.
rd_status_t ri_gpio_read(const ri_gpio_id_t pin, ri_gpio_state_t *const p_state)
Read state of a pin of a port into bool high If there are several ports the platform driver must impl...
rd_status_t ri_gpio_write(const ri_gpio_id_t pin, const ri_gpio_state_t state)
Write a pin of a port into given state If there are several ports the platform driver must implement ...
void(* rd_test_print_fp)(const char *const msg)
function pointer to print test information
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Functions for testing drivers.
uint16_t ri_gpio_id_t
port<<8 + pin
@ RI_GPIO_MODE_OUTPUT_STANDARD
Push-pull output, can be written.
@ RI_GPIO_MODE_INPUT_PULLUP
Input, can be read. Pulled up by internal resistor, value depends on IC.
@ RI_GPIO_MODE_INPUT_NOPULL
Input, can be read. No pull resistors.
@ RI_GPIO_MODE_INPUT_PULLDOWN
Input, can be read. Pulled dpwn by internal resistor, value depends on IC.
ri_gpio_state_t
States of GPIO pins.
@ RI_GPIO_LOW
GPIO electrically low.
@ RI_GPIO_HIGH
GPIO electrically high.
structure to configure GPIO test with input and output. These GPIOs must be physically connected on b...
ri_gpio_id_t input
Input pin used in test. Must be interrupt-capable.
ri_gpio_id_t output
Output pin used in test. Must be PWM-capable.