Skip to content

Commit dc733d8

Browse files
authored
Merge pull request #12477 from fkjagodzinski/hal-gpio-get_capabilities
HAL: Add a get_capabilities() function to GPIO API
2 parents 8c17270 + 09ecd2f commit dc733d8

File tree

11 files changed

+231
-218
lines changed

11 files changed

+231
-218
lines changed

TESTS/mbed_hal_fpga_ci_test_shield/gpio/gpio_fpga_test.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* mbed Microcontroller Library
2-
* Copyright (c) 2019 ARM Limited
2+
* Copyright (c) 2019-2020 ARM Limited
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,14 @@ extern "C" {
3333
*/
3434
void fpga_test_basic_input_output(PinName pin);
3535

36+
/* Test input pull modes.
37+
*
38+
* Given a GPIO instance configured with an input pull mode,
39+
* when basic input operations are performed,
40+
* then all operations succeed.
41+
*/
42+
void fpga_test_input_pull_modes(PinName pin);
43+
3644
/* Test explicit input initialization.
3745
*
3846
* Given a GPIO instance,

TESTS/mbed_hal_fpga_ci_test_shield/gpio/main.cpp

Lines changed: 152 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, Arm Limited and affiliates.
2+
* Copyright (c) 2019-2020, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -56,61 +56,23 @@ void fpga_test_basic_input_output(PinName pin)
5656
// Select GPIO0.
5757
tester.select_peripheral(MbedTester::PeripheralGPIO);
5858

59-
// Initialize GPIO pin with a generic init fun.
6059
gpio_t gpio;
61-
// Test gpio_is_connected() returned value.
60+
// Initialize GPIO pin with a generic init fun.
6261
gpio_init(&gpio, NC);
62+
// Test gpio_is_connected() returned value.
6363
TEST_ASSERT_EQUAL_INT(0, gpio_is_connected(&gpio));
6464
gpio_free(&gpio);
6565
gpio_init(&gpio, pin);
6666
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
6767

68-
// Some targets don't support input pull mode.
69-
#if !defined(TARGET_NANO100) && \
70-
!defined(TARGET_NUC472) && \
71-
!defined(TARGET_M451)
7268
// Test GPIO used as an input.
7369
gpio_dir(&gpio, PIN_INPUT);
74-
75-
// Test input, pull-up mode.
76-
gpio_mode(&gpio, PullUp);
77-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
78-
wait_us(HI_Z_READ_DELAY_US);
79-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
80-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
81-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
82-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
83-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
84-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
85-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
86-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
87-
wait_us(HI_Z_READ_DELAY_US);
88-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
89-
90-
// Test input, pull-down mode.
91-
gpio_mode(&gpio, PullDown);
92-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
93-
wait_us(HI_Z_READ_DELAY_US);
94-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
95-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
96-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
97-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
98-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
99-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
100-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
101-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
102-
wait_us(HI_Z_READ_DELAY_US);
103-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
104-
105-
// Test input, pull-none mode.
106-
gpio_mode(&gpio, PullNone);
10770
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
10871
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
10972
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
11073
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
11174
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
11275
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
113-
#endif
11476

11577
// Test GPIO used as an output.
11678
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
@@ -125,6 +87,85 @@ void fpga_test_basic_input_output(PinName pin)
12587
gpio_free(&gpio);
12688
}
12789

90+
/* Test input pull modes.
91+
*
92+
* Given a GPIO instance configured with an input pull mode,
93+
* when basic input operations are performed,
94+
* then all operations succeed.
95+
*/
96+
void fpga_test_input_pull_modes(PinName pin)
97+
{
98+
// Reset everything and set all tester pins to hi-Z.
99+
tester.reset();
100+
101+
// Map pins for test.
102+
tester.pin_map_set(pin, MbedTester::LogicalPinGPIO0);
103+
104+
// Select GPIO0.
105+
tester.select_peripheral(MbedTester::PeripheralGPIO);
106+
107+
gpio_t gpio;
108+
// Initialize GPIO pin with a generic init fun.
109+
gpio_init(&gpio, pin);
110+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
111+
gpio_dir(&gpio, PIN_INPUT);
112+
gpio_capabilities_t gcap = {};
113+
gpio_get_capabilities(&gpio, &gcap);
114+
115+
// Test input, pull-up mode.
116+
if (gcap.pull_up) {
117+
gpio_mode(&gpio, PullUp);
118+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
119+
wait_us(HI_Z_READ_DELAY_US);
120+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
121+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
122+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
123+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
124+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
125+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
126+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
127+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
128+
wait_us(HI_Z_READ_DELAY_US);
129+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
130+
} else {
131+
utest_printf("skipped PullUp,");
132+
}
133+
134+
// Test input, pull-down mode.
135+
if (gcap.pull_down) {
136+
gpio_mode(&gpio, PullDown);
137+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
138+
wait_us(HI_Z_READ_DELAY_US);
139+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
140+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
141+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
142+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
143+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
144+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
145+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
146+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
147+
wait_us(HI_Z_READ_DELAY_US);
148+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
149+
} else {
150+
utest_printf("skipped PullDown,");
151+
}
152+
153+
// Test input, pull-none mode.
154+
if (gcap.pull_none) {
155+
gpio_mode(&gpio, PullNone);
156+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
157+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
158+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
159+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio));
160+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
161+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio));
162+
} else {
163+
utest_printf("skipped PullNone,");
164+
}
165+
166+
gpio_free(&gpio);
167+
}
168+
128169
/* Test explicit input initialization.
129170
*
130171
* Given a GPIO instance,
@@ -143,42 +184,62 @@ void fpga_test_explicit_input(PinName pin)
143184
tester.select_peripheral(MbedTester::PeripheralGPIO);
144185

145186
gpio_t gpio;
187+
gpio_init(&gpio, pin);
188+
gpio_capabilities_t gcap = {};
189+
gpio_get_capabilities(&gpio, &gcap);
190+
gpio_free(&gpio);
146191

147192
// Initialize GPIO pin as an input, pull-up mode.
148-
memset(&gpio, 0, sizeof gpio);
149-
gpio_init_in_ex(&gpio, pin, PullUp);
150-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
151-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
152-
wait_us(HI_Z_READ_DELAY_US);
153-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
154-
gpio_free(&gpio);
193+
if (gcap.pull_up) {
194+
memset(&gpio, 0, sizeof gpio);
195+
gpio_init_in_ex(&gpio, pin, PullUp);
196+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
197+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
198+
wait_us(HI_Z_READ_DELAY_US);
199+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
200+
gpio_free(&gpio);
201+
} else {
202+
utest_printf("skipped PullUp,");
203+
}
155204

156205
// Initialize GPIO pin as an input, pull-down mode.
157-
memset(&gpio, 0, sizeof gpio);
158-
gpio_init_in_ex(&gpio, pin, PullDown);
159-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
160-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
161-
wait_us(HI_Z_READ_DELAY_US);
162-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
163-
gpio_free(&gpio);
206+
if (gcap.pull_down) {
207+
memset(&gpio, 0, sizeof gpio);
208+
gpio_init_in_ex(&gpio, pin, PullDown);
209+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
210+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
211+
wait_us(HI_Z_READ_DELAY_US);
212+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
213+
gpio_free(&gpio);
214+
} else {
215+
utest_printf("skipped PullDown,");
216+
}
164217

165218
// Initialize GPIO pin as an input, pull-up mode.
166-
memset(&gpio, 0, sizeof gpio);
167-
gpio_init_inout(&gpio, pin, PIN_INPUT, PullUp, 0);
168-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
169-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
170-
wait_us(HI_Z_READ_DELAY_US);
171-
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
172-
gpio_free(&gpio);
219+
if (gcap.pull_up) {
220+
memset(&gpio, 0, sizeof gpio);
221+
gpio_init_inout(&gpio, pin, PIN_INPUT, PullUp, 0);
222+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
223+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
224+
wait_us(HI_Z_READ_DELAY_US);
225+
TEST_ASSERT_EQUAL_INT(1, gpio_read(&gpio)); // hi-Z, pulled up
226+
gpio_free(&gpio);
227+
} else {
228+
utest_printf("skipped PullUp,");
229+
}
173230

174231
// Initialize GPIO pin as an input, pull-down mode.
175-
memset(&gpio, 0, sizeof gpio);
176-
gpio_init_inout(&gpio, pin, PIN_INPUT, PullDown, 0);
177-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
178-
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
179-
wait_us(HI_Z_READ_DELAY_US);
180-
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
181-
gpio_free(&gpio);
232+
if (gcap.pull_down) {
233+
memset(&gpio, 0, sizeof gpio);
234+
gpio_init_inout(&gpio, pin, PIN_INPUT, PullDown, 0);
235+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
236+
tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, false);
237+
wait_us(HI_Z_READ_DELAY_US);
238+
TEST_ASSERT_EQUAL_INT(0, gpio_read(&gpio)); // hi-Z, pulled down
239+
gpio_free(&gpio);
240+
} else {
241+
utest_printf("skipped PullDown,");
242+
}
182243
}
183244

184245
/* Test explicit output initialization.
@@ -199,6 +260,10 @@ void fpga_test_explicit_output(PinName pin)
199260
tester.select_peripheral(MbedTester::PeripheralGPIO);
200261

201262
gpio_t gpio;
263+
gpio_init(&gpio, pin);
264+
gpio_capabilities_t gcap = {};
265+
gpio_get_capabilities(&gpio, &gcap);
266+
gpio_free(&gpio);
202267

203268
// Initialize GPIO pin as an output, output value = 0.
204269
memset(&gpio, 0, sizeof gpio);
@@ -222,28 +287,28 @@ void fpga_test_explicit_output(PinName pin)
222287
gpio_free(&gpio);
223288

224289
// Initialize GPIO pin as an output, output value = 1.
225-
memset(&gpio, 0, sizeof gpio);
226-
gpio_init_inout(&gpio, pin, PIN_OUTPUT, PullNone, 1);
227-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
228-
TEST_ASSERT_EQUAL_INT(1, tester.gpio_read(MbedTester::LogicalPinGPIO0));
229-
gpio_free(&gpio);
230-
231-
// Initialize GPIO pin as an output, output value = 0.
232-
memset(&gpio, 0, sizeof gpio);
233-
gpio_init_inout(&gpio, pin, PIN_OUTPUT, PullNone, 0);
234-
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
235-
TEST_ASSERT_EQUAL_INT(0, tester.gpio_read(MbedTester::LogicalPinGPIO0));
236-
gpio_free(&gpio);
290+
if (gcap.pull_none) {
291+
memset(&gpio, 0, sizeof gpio);
292+
gpio_init_inout(&gpio, pin, PIN_OUTPUT, PullNone, 1);
293+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
294+
TEST_ASSERT_EQUAL_INT(1, tester.gpio_read(MbedTester::LogicalPinGPIO0));
295+
gpio_free(&gpio);
296+
297+
// Initialize GPIO pin as an output, output value = 0.
298+
memset(&gpio, 0, sizeof gpio);
299+
gpio_init_inout(&gpio, pin, PIN_OUTPUT, PullNone, 0);
300+
TEST_ASSERT_NOT_EQUAL(0, gpio_is_connected(&gpio));
301+
TEST_ASSERT_EQUAL_INT(0, tester.gpio_read(MbedTester::LogicalPinGPIO0));
302+
gpio_free(&gpio);
303+
} else {
304+
utest_printf("skipped gpio_init_inout,");
305+
}
237306
}
238307

239308
Case cases[] = {
240-
Case("generic init, input & output", all_ports<GPIOPort, DefaultFormFactor, fpga_test_basic_input_output>),
241-
// Some targets don't support input pull mode.
242-
#if !defined(TARGET_NANO100) && \
243-
!defined(TARGET_NUC472) && \
244-
!defined(TARGET_M451)
309+
Case("basic input & output", all_ports<GPIOPort, DefaultFormFactor, fpga_test_basic_input_output>),
310+
Case("input pull modes", all_ports<GPIOPort, DefaultFormFactor, fpga_test_input_pull_modes>),
245311
Case("explicit init, input", all_ports<GPIOPort, DefaultFormFactor, fpga_test_explicit_input>),
246-
#endif
247312
Case("explicit init, output", all_ports<GPIOPort, DefaultFormFactor, fpga_test_explicit_output>),
248313
};
249314

hal/gpio_api.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/** \addtogroup hal */
33
/** @{*/
44
/* mbed Microcontroller Library
5-
* Copyright (c) 2006-2013 ARM Limited
5+
* Copyright (c) 2006-2020 ARM Limited
66
* SPDX-License-Identifier: Apache-2.0
77
*
88
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -46,6 +46,8 @@ extern "C" {
4646
* * ::gpio_init_out_ex inits the pin as an output and sets the output value
4747
* * ::gpio_init_inout inits the pin to be input/output and set pin mode and value
4848
* * The GPIO operations ::gpio_write, ::gpio_read take less than 20us to complete
49+
* * The function ::gpio_get_capabilities fills the given
50+
* `gpio_capabilities_t` instance according to pin capabilities.
4951
*
5052
* # Undefined behavior
5153
* * Calling any ::gpio_mode, ::gpio_dir, ::gpio_write or ::gpio_read on a gpio_t object that was initialized
@@ -65,6 +67,14 @@ extern "C" {
6567
*
6668
*/
6769

70+
/** GPIO capabilities for a given pin
71+
*/
72+
typedef struct {
73+
uint8_t pull_none : 1;
74+
uint8_t pull_down : 1;
75+
uint8_t pull_up : 1;
76+
} gpio_capabilities_t;
77+
6878
/** Set the given pin as GPIO
6979
*
7080
* @param pin The pin to be set as GPIO
@@ -164,6 +174,10 @@ void gpio_init_out_ex(gpio_t *gpio, PinName pin, int value);
164174
*/
165175
void gpio_init_inout(gpio_t *gpio, PinName pin, PinDirection direction, PinMode mode, int value);
166176

177+
/** Fill the given gpio_capabilities_t instance according to pin capabilities.
178+
*/
179+
void gpio_get_capabilities(gpio_t *gpio, gpio_capabilities_t *cap);
180+
167181
/** Get the pins that support all GPIO tests
168182
*
169183
* Return a PinMap array of pins that support GPIO. The

hal/mbed_gpio.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* mbed Microcontroller Library
2-
* Copyright (c) 2006-2013 ARM Limited
2+
* Copyright (c) 2006-2020 ARM Limited
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,6 +68,15 @@ void gpio_init_inout(gpio_t *gpio, PinName pin, PinDirection direction, PinMode
6868
}
6969
}
7070

71+
// To be re-implemented in the target layer if required.
72+
MBED_WEAK void gpio_get_capabilities(gpio_t *gpio, gpio_capabilities_t *cap)
73+
{
74+
(void)gpio; // By default, every pin supports all basic input pull modes.
75+
cap->pull_none = 1;
76+
cap->pull_down = 1;
77+
cap->pull_up = 1;
78+
}
79+
7180
#ifdef TARGET_FF_ARDUINO
7281

7382
typedef enum {

0 commit comments

Comments
 (0)