2525#include "gpio_api.h"
2626#include "PeripheralPins.h"
2727
28+ #include <string.h>
29+
2830/** Set the given pin as GPIO
2931 *
3032 * @param pin The pin to be set as GPIO
@@ -55,6 +57,7 @@ int gpio_is_connected(const gpio_t *obj)
5557void gpio_init (gpio_t * obj , PinName pin )
5658{
5759 MBED_ASSERT (obj != NULL );
60+ memset (obj , 0 , sizeof (gpio_t ));
5861 obj -> pad = (ap3_uart_pad_t )pin ;
5962 return ;
6063}
@@ -66,94 +69,50 @@ void gpio_init(gpio_t *obj, PinName pin)
6669void gpio_mode (gpio_t * obj , PinMode mode )
6770{
6871 MBED_ASSERT (gpio_is_connected (obj ));
69- MBED_ASSERT (mode < (PinMode )PinModeElements );
7072 am_hal_gpio_pincfg_allow_t pinConfigBools = {0 };
7173
7274 obj -> cfg .uFuncSel = AP3_PINCFG_FUNCSEL_GPIO ; // gpio
7375
74- if (mode & (PinMode )PowerSwNone ) {
75- obj -> cfg .ePowerSw = AM_HAL_GPIO_PIN_POWERSW_NONE ;
76- pinConfigBools .ePowerSw = true;
77- }
78- if (mode & (PinMode )PowerSwVDD ) {
79- obj -> cfg .ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VDD ;
80- pinConfigBools .ePowerSw = true;
81- }
82- if (mode & (PinMode )PowerSwVSS ) {
83- obj -> cfg .ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VSS ;
84- pinConfigBools .ePowerSw = true;
85- }
76+ // Configure pull-up or pull-down
77+ pinConfigBools .ePullup = true;
8678
87- if (mode & (PinMode )PullNone ) {
79+ if (!(mode & OpenDrain ) && obj -> isOutput ) {
80+ // Push-pull output, do not allow pullup
8881 obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE ;
89- pinConfigBools .ePullup = true;
9082 }
91- if (mode & (PinMode )PullUp ) {
92- obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK ;
93- pinConfigBools .ePullup = true;
94- }
95- if (mode & (PinMode )PullDown ) {
83+ else if (mode & (PinMode )PullUp ) {
84+ MBED_ASSERT (obj -> pad != IO_20 ); // pullup not supported on IO 20
85+
86+ if (obj -> pad == IO_0 || obj -> pad == IO_1 || obj -> pad == IO_5 || obj -> pad == IO_6 || obj -> pad == IO_8
87+ || obj -> pad == IO_9 || obj -> pad == IO_25 || obj -> pad == IO_27 || obj -> pad == IO_39 ||
88+ obj -> pad == IO_40 || obj -> pad == IO_42 || obj -> pad == IO_43 || obj -> pad == IO_48 || obj -> pad == IO_49 ) {
89+ // These pads (with I2C support) need a different constant to get the same resistance
90+ obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_24K ;
91+ }
92+ else {
93+ obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK ;
94+ }
95+ }
96+ else if (mode & (PinMode )PullDown ) {
97+ MBED_ASSERT (obj -> pad == IO_20 ); // pulldown only supported on IO 20
9698 obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLDOWN ;
97- pinConfigBools .ePullup = true;
98- }
99-
100- if (mode & (PinMode )DriveStrength2mA ) {
101- obj -> cfg .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA ;
102- pinConfigBools .eDriveStrength = true;
10399 }
104- if (mode & (PinMode )DriveStrength4mA ) {
105- obj -> cfg .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA ;
106- pinConfigBools .eDriveStrength = true;
107- }
108- if (mode & (PinMode )DriveStrength8mA ) {
109- obj -> cfg .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA ;
110- pinConfigBools .eDriveStrength = true;
111- }
112- if (mode & (PinMode )DriveStrength12mA ) {
113- obj -> cfg .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA ;
114- pinConfigBools .eDriveStrength = true;
115- }
116-
117- if (mode & (PinMode )OutDisable ) {
118- obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE ;
119- pinConfigBools .eGPOutcfg = true;
120- }
121- if (mode & (PinMode )OutPushPull ) {
122- obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ;
123- pinConfigBools .eGPOutcfg = true;
124- }
125- if (mode & (PinMode )OutOpenDrain ) {
126- obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN ;
127- pinConfigBools .eGPOutcfg = true;
128- }
129- if (mode & (PinMode )OutTristate ) {
130- obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE ;
131- pinConfigBools .eGPOutcfg = true;
100+ else {
101+ obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE ;
132102 }
133103
134- if (mode & (PinMode )InAuto ) {
135- obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_AUTO ;
136- pinConfigBools .eGPInput = true;
137- }
138- if (mode & (PinMode )InNone ) {
139- obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE ;
140- pinConfigBools .eGPInput = true;
104+ // Configure output type
105+ obj -> openDrain = mode & OpenDrain ;
106+ pinConfigBools .eGPOutcfg = true;
107+ if (obj -> isOutput ) {
108+ obj -> cfg .eGPOutcfg = obj -> openDrain ? AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN : AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ;
141109 }
142- if (mode & (PinMode )InEnable ) {
143- obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE ;
144- pinConfigBools .eGPInput = true;
110+ else {
111+ obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE ;
145112 }
146113
147- if (mode & (PinMode )ReadPin ) {
148- obj -> cfg .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN ;
149- pinConfigBools .eGPRdZero = true;
150- }
151- if (mode & (PinMode )ReadZero ) {
152- obj -> cfg .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_ZERO ;
153- pinConfigBools .eGPRdZero = true;
154- }
155114
156- ap3_hal_gpio_pinconfig_partial ((uint32_t )(obj -> pad ), obj -> cfg , pinConfigBools ); //padRegMsk.byte, GPConfigMsk.byte, padAltCfgMsk.byte); // apply configuration
115+ MBED_ASSERT ( ap3_hal_gpio_pinconfig_partial ((uint32_t )(obj -> pad ), obj -> cfg , pinConfigBools ) == AM_HAL_STATUS_SUCCESS );
157116}
158117
159118/** Set the pin direction
@@ -167,23 +126,33 @@ void gpio_dir(gpio_t *obj, PinDirection direction)
167126 MBED_ASSERT (direction < (PinDirection )PIN_DIR_ELEMENTS );
168127 am_hal_gpio_pincfg_allow_t pinConfigBools = {0 };
169128
129+ // Always enable the input on the pin, so that we can read it if it is open drain.
130+ pinConfigBools .eGPInput = true;
131+ pinConfigBools .eGPRdZero = true;
132+ obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE ;
133+ obj -> cfg .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN ;
134+
170135 if (direction == (PinDirection )PIN_INPUT ) {
171- obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE ;
172- pinConfigBools .eGPInput = true;
136+ obj -> isOutput = false;
173137 obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE ;
174138 pinConfigBools .eGPOutcfg = true;
175139 } else if (direction == (PinDirection )PIN_OUTPUT ) {
176- obj -> cfg .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ;
140+ obj -> isOutput = true;
141+ obj -> cfg .eGPOutcfg = obj -> openDrain ? AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN : AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ;
177142 pinConfigBools .eGPOutcfg = true;
178143 obj -> cfg .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA ;
179144 pinConfigBools .eDriveStrength = true;
180- obj -> cfg .eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE ;
181- pinConfigBools .eGPInput = true;
145+
146+ // Clear any configured pullup if set to open-drain
147+ if (!obj -> openDrain ) {
148+ pinConfigBools .ePullup = true;
149+ obj -> cfg .ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE ;
150+ }
182151 } else {
183152 MBED_ASSERT (false);
184153 }
185154
186- ap3_hal_gpio_pinconfig_partial ((uint32_t )(obj -> pad ), obj -> cfg , pinConfigBools ); //padRegMsk.byte, GPConfigMsk.byte, padAltCfgMsk.byte); // apply configuration
155+ ap3_hal_gpio_pinconfig_partial ((uint32_t )(obj -> pad ), obj -> cfg , pinConfigBools );
187156}
188157
189158/** Set the output value
@@ -205,12 +174,8 @@ void gpio_write(gpio_t *obj, int value)
205174int gpio_read (gpio_t * obj )
206175{
207176 MBED_ASSERT (gpio_is_connected (obj ));
208- uint32_t ui32BaseAddr = (obj -> pad ) / 8 ;
209- uint32_t ui32BaseShift = (((obj -> pad ) % 8 ) * 4 ) + 1 ;
210- uint8_t output = ((AM_REGVAL (& GPIO -> CFGA + ui32BaseAddr ) >> ui32BaseShift ) & 0x03 );
211177
212- return (output ) ? (int )am_hal_gpio_output_read (obj -> pad ) : (int )am_hal_gpio_input_read (obj -> pad );
213- return 0 ;
178+ return am_hal_gpio_input_read (obj -> pad );
214179}
215180
216181/** Get the pins that support all GPIO tests
0 commit comments