Skip to content

Commit af51027

Browse files
committed
[STM32] Fix pull over write to all families
This applies the same fix as was done for F4 to solve issue #2638. The fix applies ell to all other families excpet STM32F1. Basically, to avoid over-writing the pull-up/-down settings, we read the current state from HW.
1 parent 9976738 commit af51027

File tree

14 files changed

+135
-27
lines changed

14 files changed

+135
-27
lines changed

targets/TARGET_STM/TARGET_STM32F0/gpio_irq_api.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static void gpio_irq2(void) {
127127
}
128128

129129
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
130+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
130131

131132
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
132133
IRQn_Type irq_n = (IRQn_Type)0;
@@ -196,8 +197,8 @@ void gpio_irq_free(gpio_irq_t *obj) {
196197
gpio_channel->channel_gpio[gpio_idx] = 0;
197198
gpio_channel->channel_pin[gpio_idx] = 0;
198199

199-
// Disable EXTI line
200-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
200+
// Disable EXTI line, but don't change pull-up config
201+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
201202
obj->event = EDGE_NONE;
202203
}
203204

@@ -245,7 +246,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
245246
}
246247
}
247248

248-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
249+
pin_function_gpiomode(obj->pin, mode);
249250
}
250251

251252
void gpio_irq_enable(gpio_irq_t *obj) {

targets/TARGET_STM/TARGET_STM32F0/pinmap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,20 @@ void pin_mode(PinName pin, PinMode mode) {
138138
if (pupd > 2) pupd = 0; // Open-drain = No pull-up/No pull-down
139139
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
140140
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
141+
}
142+
143+
/* Internal function for setting the gpiomode/function
144+
* without changing Pull mode
145+
*/
146+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
147+
148+
/* Read current pull state from HW to avoid over-write*/
149+
uint32_t port_index = STM_PORT(pin);
150+
uint32_t pin_index = STM_PIN(pin);
151+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
152+
uint32_t temp = gpio->PUPDR;
153+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
141154

155+
/* Then re-use global function for updating the mode part*/
156+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
142157
}

targets/TARGET_STM/TARGET_STM32F2/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static void gpio_irq6(void)
163163
}
164164

165165
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
166+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
166167

167168
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
168169
{
@@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
267268
gpio_channel->channel_gpio[gpio_idx] = 0;
268269
gpio_channel->channel_pin[gpio_idx] = 0;
269270

270-
// Disable EXTI line
271-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
271+
// Disable EXTI line, but don't change pull-up config
272+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
272273
obj->event = EDGE_NONE;
273274
}
274275

275276
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
276277
{
277278
uint32_t mode = STM_MODE_IT_EVT_RESET;
278-
uint32_t pull = GPIO_NOPULL;
279279

280280
if (enable) {
281281
if (event == IRQ_RISE) {
@@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
317317
}
318318
}
319319

320-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
320+
pin_function_gpiomode(obj->pin, mode);
321321
}
322322

323323
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32F2/pinmap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,20 @@ void pin_mode(PinName pin, PinMode mode)
178178
}
179179
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
180180
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
181+
}
182+
183+
/* Internal function for setting the gpiomode/function
184+
* without changing Pull mode
185+
*/
186+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
187+
188+
/* Read current pull state from HW to avoid over-write*/
189+
uint32_t port_index = STM_PORT(pin);
190+
uint32_t pin_index = STM_PIN(pin);
191+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
192+
uint32_t temp = gpio->PUPDR;
193+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
181194

195+
/* Then re-use global function for updating the mode part*/
196+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
182197
}

targets/TARGET_STM/TARGET_STM32F3/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static void gpio_irq6(void)
163163
}
164164

165165
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
166+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
166167

167168
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
168169
{
@@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
267268
gpio_channel->channel_gpio[gpio_idx] = 0;
268269
gpio_channel->channel_pin[gpio_idx] = 0;
269270

270-
// Disable EXTI line
271-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
271+
// Disable EXTI line, but don't change pull-up config
272+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
272273
obj->event = EDGE_NONE;
273274
}
274275

275276
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
276277
{
277278
uint32_t mode = STM_MODE_IT_EVT_RESET;
278-
uint32_t pull = GPIO_NOPULL;
279279

280280
if (enable) {
281281
if (event == IRQ_RISE) {
@@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
317317
}
318318
}
319319

320-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
320+
pin_function_gpiomode(obj->pin, mode);
321321
}
322322

323323
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32F3/pinmap.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,19 @@ void pin_mode(PinName pin, PinMode mode)
177177
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
178178
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
179179
}
180+
181+
/* Internal function for setting the gpiomode/function
182+
* without changing Pull mode
183+
*/
184+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
185+
186+
/* Read current pull state from HW to avoid over-write*/
187+
uint32_t port_index = STM_PORT(pin);
188+
uint32_t pin_index = STM_PIN(pin);
189+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
190+
uint32_t temp = gpio->PUPDR;
191+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
192+
193+
/* Then re-use global function for updating the mode part*/
194+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
195+
}

targets/TARGET_STM/TARGET_STM32F7/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static void gpio_irq6(void)
163163
}
164164

165165
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
166+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
166167

167168
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
168169
{
@@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
267268
gpio_channel->channel_gpio[gpio_idx] = 0;
268269
gpio_channel->channel_pin[gpio_idx] = 0;
269270

270-
// Disable EXTI line
271-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
271+
// Disable EXTI line, but don't change pull-up config
272+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
272273
obj->event = EDGE_NONE;
273274
}
274275

275276
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
276277
{
277278
uint32_t mode = STM_MODE_IT_EVT_RESET;
278-
uint32_t pull = GPIO_NOPULL;
279279

280280
if (enable) {
281281
if (event == IRQ_RISE) {
@@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
317317
}
318318
}
319319

320-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
320+
pin_function_gpiomode(obj->pin, mode);
321321
}
322322

323323
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32F7/pinmap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,20 @@ void pin_mode(PinName pin, PinMode mode)
177177
pupd = 0; // Open-drain = No pull-up/No pull-down
178178
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
179179
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
180+
}
181+
182+
/* Internal function for setting the gpiomode/function
183+
* without changing Pull mode
184+
*/
185+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
186+
187+
/* Read current pull state from HW to avoid over-write*/
188+
uint32_t port_index = STM_PORT(pin);
189+
uint32_t pin_index = STM_PIN(pin);
190+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
191+
uint32_t temp = gpio->PUPDR;
192+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
180193

194+
/* Then re-use global function for updating the mode part*/
195+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
181196
}

targets/TARGET_STM/TARGET_STM32L0/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ static void gpio_irq2(void)
131131
}
132132

133133
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
134+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
134135

135136
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
136137
{
@@ -202,15 +203,14 @@ void gpio_irq_free(gpio_irq_t *obj)
202203
gpio_channel->channel_gpio[gpio_idx] = 0;
203204
gpio_channel->channel_pin[gpio_idx] = 0;
204205

205-
// Disable EXTI line
206-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
206+
// Disable EXTI line, but don't change pull-up config
207+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
207208
obj->event = EDGE_NONE;
208209
}
209210

210211
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
211212
{
212213
uint32_t mode = STM_MODE_IT_EVT_RESET;
213-
uint32_t pull = GPIO_NOPULL;
214214

215215
if (enable) {
216216
if (event == IRQ_RISE) {
@@ -252,7 +252,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
252252
}
253253
}
254254

255-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
255+
pin_function_gpiomode(obj->pin, mode);
256256
}
257257

258258
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32L0/pinmap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,20 @@ void pin_mode(PinName pin, PinMode mode)
146146
}
147147
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPD0 << (pin_index * 2)));
148148
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
149+
}
150+
151+
/* Internal function for setting the gpiomode/function
152+
* without changing Pull mode
153+
*/
154+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
155+
156+
/* Read current pull state from HW to avoid over-write*/
157+
uint32_t port_index = STM_PORT(pin);
158+
uint32_t pin_index = STM_PIN(pin);
159+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
160+
uint32_t temp = gpio->PUPDR;
161+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPD0;
149162

163+
/* Then re-use global function for updating the mode part*/
164+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
150165
}

targets/TARGET_STM/TARGET_STM32L1/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static void gpio_irq6(void)
163163
}
164164

165165
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
166+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
166167

167168
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
168169
{
@@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
267268
gpio_channel->channel_gpio[gpio_idx] = 0;
268269
gpio_channel->channel_pin[gpio_idx] = 0;
269270

270-
// Disable EXTI line
271-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
271+
// Disable EXTI line, but don't change pull-up config
272+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
272273
obj->event = EDGE_NONE;
273274
}
274275

275276
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
276277
{
277278
uint32_t mode = STM_MODE_IT_EVT_RESET;
278-
uint32_t pull = GPIO_NOPULL;
279279

280280
if (enable) {
281281
if (event == IRQ_RISE) {
@@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
317317
}
318318
}
319319

320-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
320+
pin_function_gpiomode(obj->pin, mode);
321321
}
322322

323323
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32L1/pinmap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,20 @@ void pin_mode(PinName pin, PinMode mode)
139139
}
140140
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
141141
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
142+
}
143+
144+
/* Internal function for setting the gpiomode/function
145+
* without changing Pull mode
146+
*/
147+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
148+
149+
/* Read current pull state from HW to avoid over-write*/
150+
uint32_t port_index = STM_PORT(pin);
151+
uint32_t pin_index = STM_PIN(pin);
152+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
153+
uint32_t temp = gpio->PUPDR;
154+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
142155

156+
/* Then re-use global function for updating the mode part*/
157+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
143158
}

targets/TARGET_STM/TARGET_STM32L4/gpio_irq_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static void gpio_irq6(void)
163163
}
164164

165165
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
166+
extern void pin_function_gpiomode(PinName pin, uint32_t gpiomode);
166167

167168
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
168169
{
@@ -267,15 +268,14 @@ void gpio_irq_free(gpio_irq_t *obj)
267268
gpio_channel->channel_gpio[gpio_idx] = 0;
268269
gpio_channel->channel_pin[gpio_idx] = 0;
269270

270-
// Disable EXTI line
271-
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
271+
// Disable EXTI line, but don't change pull-up config
272+
pin_function_gpiomode(obj->pin, STM_MODE_INPUT);
272273
obj->event = EDGE_NONE;
273274
}
274275

275276
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
276277
{
277278
uint32_t mode = STM_MODE_IT_EVT_RESET;
278-
uint32_t pull = GPIO_NOPULL;
279279

280280
if (enable) {
281281
if (event == IRQ_RISE) {
@@ -317,7 +317,7 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
317317
}
318318
}
319319

320-
pin_function(obj->pin, STM_PIN_DATA(mode, pull, 0));
320+
pin_function_gpiomode(obj->pin, mode);
321321
}
322322

323323
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_STM/TARGET_STM32L4/pinmap.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,19 @@ void pin_mode(PinName pin, PinMode mode)
149149
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
150150
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
151151
}
152+
153+
/* Internal function for setting the gpiomode/function
154+
* without changing Pull mode
155+
*/
156+
void pin_function_gpiomode(PinName pin, uint32_t gpiomode) {
157+
158+
/* Read current pull state from HW to avoid over-write*/
159+
uint32_t port_index = STM_PORT(pin);
160+
uint32_t pin_index = STM_PIN(pin);
161+
GPIO_TypeDef *gpio = (GPIO_TypeDef *) Set_GPIO_Clock(port_index);
162+
uint32_t temp = gpio->PUPDR;
163+
uint32_t pull = (temp >> (pin_index * 2U)) & GPIO_PUPDR_PUPDR0;
164+
165+
/* Then re-use global function for updating the mode part*/
166+
pin_function(pin, STM_PIN_DATA(gpiomode, pull, 0));
167+
}

0 commit comments

Comments
 (0)