Skip to content

Commit 1d851a5

Browse files
Apollo3: Simplify and standardize pin modes
1 parent 4a331c7 commit 1d851a5

File tree

2 files changed

+66
-150
lines changed

2 files changed

+66
-150
lines changed

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c

Lines changed: 49 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
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)
5557
void 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)
6669
void 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)
205174
int 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

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h

Lines changed: 17 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -43,78 +43,29 @@ typedef enum {
4343
PIN_DIR_ELEMENTS
4444
} PinDirection;
4545

46-
enum sPinMode {
47-
sPowerSwNone = 0x00,
48-
sPowerSwVDD,
49-
sPowerSwVSS,
50-
sPullNone,
51-
sPullUp,
52-
sPullDown,
53-
sPullUp1K5,
54-
sPullUp6K,
55-
sPullUp12K,
56-
sPullUp24K,
57-
sDriveStrength2mA,
58-
sDriveStrength4mA,
59-
sDriveStrength8mA,
60-
sDriveStrength12mA,
61-
sOutDisable,
62-
sOutPushPull,
63-
sOutOpenDrain,
64-
sOutTristate,
65-
sInAuto,
66-
sInNone,
67-
sInEnable,
68-
sReadPin,
69-
sReadZero,
70-
71-
sPinModeElements
72-
};
73-
74-
#define PinModeEntry(e) e = (1 << s##e)
75-
7646
typedef enum {
77-
PinModeEntry(PowerSwNone),
78-
PinModeEntry(PowerSwVDD),
79-
PinModeEntry(PowerSwVSS),
80-
PowerSwDefault = PowerSwNone,
81-
82-
PinModeEntry(PullNone),
83-
PinModeEntry(PullUp),
84-
PinModeEntry(PullDown),
85-
PinModeEntry(PullUp1K5),
86-
PinModeEntry(PullUp6K),
87-
PinModeEntry(PullUp12K),
88-
PinModeEntry(PullUp24K),
89-
PullDefault = PullNone,
90-
91-
PinModeEntry(DriveStrength2mA),
92-
PinModeEntry(DriveStrength4mA),
93-
PinModeEntry(DriveStrength8mA),
94-
PinModeEntry(DriveStrength12mA),
95-
DriveStrengthDefault = DriveStrength12mA,
96-
97-
PinModeEntry(OutDisable),
98-
PinModeEntry(OutPushPull),
99-
PinModeEntry(OutOpenDrain),
100-
PinModeEntry(OutTristate),
101-
OutDefault = OutPushPull,
102-
103-
PinModeEntry(InAuto),
104-
PinModeEntry(InNone),
105-
PinModeEntry(InEnable),
106-
InDefault = InEnable,
107-
108-
PinModeEntry(ReadPin),
109-
PinModeEntry(ReadZero),
110-
ReadDefault = ReadPin,
111-
112-
PinModeEntry(PinModeElements)
47+
48+
PullNone = 0,
49+
50+
// Supported on all IOs except IO 20. Actual resistance 13-27kOhm
51+
PullUp = 1 << 0,
52+
53+
// Only supported on IO 20, Actual resistance 26-40kOhm
54+
PullDown = 1 << 1,
55+
56+
OpenDrain = 1 << 2,
57+
OpenDrainPullUp = OpenDrain | PullUp, ///< Open-drain mode with pull up
58+
OpenDrainPullDown = OpenDrain | PullDown, ///< Open-drain mode with pull down
59+
OpenDrainNoPull = OpenDrain, ///< Open-drain mode with no pullup/pulldown
60+
61+
PullDefault = PullNone
11362
} PinMode;
11463

11564
typedef struct _gpio_t {
11665
ap3_gpio_pad_t pad;
11766
am_hal_gpio_pincfg_t cfg;
67+
bool openDrain;
68+
bool isOutput;
11869
} gpio_t;
11970

12071
typedef struct ap3_gpio_irq_control_t {

0 commit comments

Comments
 (0)