Skip to content

Commit d14992d

Browse files
committed
[NUCLEO_F103RB] Improvement of gpio and gpio_irq api
1 parent a088e34 commit d14992d

File tree

6 files changed

+129
-128
lines changed

6 files changed

+129
-128
lines changed

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_api.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
*/
3030
#include "gpio_api.h"
3131
#include "pinmap.h"
32+
#include "error.h"
33+
34+
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
3235

3336
uint32_t gpio_set(PinName pin) {
3437
if (pin == NC) return 0;
@@ -38,14 +41,17 @@ uint32_t gpio_set(PinName pin) {
3841
return (uint32_t)(1 << ((uint32_t)pin & 0xF)); // Return the pin mask
3942
}
4043

41-
void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) {
44+
void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) {
45+
GPIO_TypeDef *gpio;
46+
4247
if (pin == NC) return;
4348

4449
uint32_t port_index = STM_PORT(pin);
4550

46-
// Get GPIO structure base address
47-
GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10));
48-
51+
// Enable GPIO clock
52+
uint32_t gpio_add = Set_GPIO_Clock(port_index);
53+
gpio = (GPIO_TypeDef *)gpio_add;
54+
4955
// Fill GPIO object structure for future use
5056
obj->pin = pin;
5157
obj->mask = gpio_set(pin);

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c

Lines changed: 58 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -31,139 +31,96 @@
3131
#include "cmsis.h"
3232

3333
#include "gpio_irq_api.h"
34+
#include "pinmap.h"
3435
#include "error.h"
3536

3637
#define EDGE_NONE (0)
3738
#define EDGE_RISE (1)
3839
#define EDGE_FALL (2)
3940
#define EDGE_BOTH (3)
4041

41-
#define CHANNEL_NUM (16)
42+
#define CHANNEL_NUM (4)
4243

43-
static uint32_t channel_ids[CHANNEL_NUM] = {0};
44+
static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0, 0};
45+
static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0, 0};
46+
static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0, 0};
4447

4548
static gpio_irq_handler irq_handler;
4649

47-
static void handle_interrupt_in(uint32_t channel) {
48-
if (channel_ids[channel] == 0) return;
50+
static void handle_interrupt_in(uint32_t irq_index) {
4951

50-
uint32_t exti_line = (uint32_t)(1 << channel);
51-
if (EXTI_GetITStatus(exti_line) != RESET)
52+
// Retrieve the gpio and pin that generate the irq
53+
GPIO_TypeDef *gpio = (GPIO_TypeDef *)(channel_gpio[irq_index]);
54+
uint32_t pin = (uint32_t)(1 << channel_pin[irq_index]);
55+
56+
// Clear interrupt flag
57+
if (EXTI_GetITStatus(pin) != RESET)
5258
{
53-
EXTI_ClearITPendingBit(exti_line);
59+
EXTI_ClearITPendingBit(pin);
5460
}
5561

56-
// Warning:
57-
// On this device we don't know if a rising or falling event occured.
58-
// In case both rise and fall events are set, only the FALL event will be reported.
59-
if (EXTI->FTSR & (uint32_t)(1 << channel)) {
60-
irq_handler(channel_ids[channel], IRQ_FALL);
62+
if (channel_ids[irq_index] == 0) return;
63+
64+
// Check which edge has generated the irq
65+
if ((gpio->IDR & pin) == 0) {
66+
irq_handler(channel_ids[irq_index], IRQ_FALL);
6167
}
62-
else {
63-
irq_handler(channel_ids[channel], IRQ_RISE);
68+
else {
69+
irq_handler(channel_ids[irq_index], IRQ_RISE);
6470
}
6571
}
6672

73+
// The irq_index is passed to the function
6774
static void gpio_irq0(void) {handle_interrupt_in(0);}
6875
static void gpio_irq1(void) {handle_interrupt_in(1);}
6976
static void gpio_irq2(void) {handle_interrupt_in(2);}
7077
static void gpio_irq3(void) {handle_interrupt_in(3);}
71-
static void gpio_irq4(void) {handle_interrupt_in(4);}
72-
static void gpio_irq5(void) {handle_interrupt_in(5);}
73-
static void gpio_irq6(void) {handle_interrupt_in(6);}
74-
static void gpio_irq7(void) {handle_interrupt_in(7);}
75-
static void gpio_irq8(void) {handle_interrupt_in(8);}
76-
static void gpio_irq9(void) {handle_interrupt_in(9);}
77-
static void gpio_irq10(void) {handle_interrupt_in(10);}
78-
static void gpio_irq11(void) {handle_interrupt_in(11);}
79-
static void gpio_irq12(void) {handle_interrupt_in(12);}
80-
static void gpio_irq13(void) {handle_interrupt_in(13);}
81-
static void gpio_irq14(void) {handle_interrupt_in(14);}
82-
static void gpio_irq15(void) {handle_interrupt_in(15);}
78+
79+
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
8380

8481
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
85-
IRQn_Type irq_n = (IRQn_Type)0;
82+
IRQn_Type irq_n = (IRQn_Type)0;
8683
uint32_t vector = 0;
87-
84+
uint32_t irq_index;
85+
8886
if (pin == NC) return -1;
8987

9088
uint32_t port_index = STM_PORT(pin);
9189
uint32_t pin_index = STM_PIN(pin);
92-
93-
// Select irq number and vector
94-
switch (pin_index) {
95-
case 0:
96-
irq_n = EXTI0_IRQn;
90+
91+
// Select irq number and interrupt routine
92+
switch (pin) {
93+
case PC_13: // User button
94+
irq_n = EXTI15_10_IRQn;
9795
vector = (uint32_t)&gpio_irq0;
96+
irq_index = 0;
9897
break;
99-
case 1:
100-
irq_n = EXTI1_IRQn;
101-
vector = (uint32_t)&gpio_irq1;
102-
break;
103-
case 2:
104-
irq_n = EXTI2_IRQn;
105-
vector = (uint32_t)&gpio_irq2;
106-
break;
107-
case 3:
98+
case PB_3:
10899
irq_n = EXTI3_IRQn;
109-
vector = (uint32_t)&gpio_irq3;
100+
vector = (uint32_t)&gpio_irq1;
101+
irq_index = 1;
110102
break;
111-
case 4:
103+
case PB_4:
112104
irq_n = EXTI4_IRQn;
113-
vector = (uint32_t)&gpio_irq4;
105+
vector = (uint32_t)&gpio_irq2;
106+
irq_index = 2;
114107
break;
115-
case 5:
116-
irq_n = EXTI9_5_IRQn;
117-
vector = (uint32_t)&gpio_irq5;
118-
break;
119-
case 6:
108+
case PB_5:
120109
irq_n = EXTI9_5_IRQn;
121-
vector = (uint32_t)&gpio_irq6;
122-
break;
123-
case 7:
124-
irq_n = EXTI9_5_IRQn;
125-
vector = (uint32_t)&gpio_irq7;
126-
break;
127-
case 8:
128-
irq_n = EXTI9_5_IRQn;
129-
vector = (uint32_t)&gpio_irq8;
130-
break;
131-
case 9:
132-
irq_n = EXTI9_5_IRQn;
133-
vector = (uint32_t)&gpio_irq9;
110+
vector = (uint32_t)&gpio_irq3;
111+
irq_index = 3;
134112
break;
135-
case 10:
136-
irq_n = EXTI15_10_IRQn;
137-
vector = (uint32_t)&gpio_irq10;
138-
break;
139-
case 11:
140-
irq_n = EXTI15_10_IRQn;
141-
vector = (uint32_t)&gpio_irq11;
142-
break;
143-
case 12:
144-
irq_n = EXTI15_10_IRQn;
145-
vector = (uint32_t)&gpio_irq12;
146-
break;
147-
case 13:
148-
irq_n = EXTI15_10_IRQn;
149-
vector = (uint32_t)&gpio_irq13;
150-
break;
151-
case 14:
152-
irq_n = EXTI15_10_IRQn;
153-
vector = (uint32_t)&gpio_irq14;
154-
break;
155-
case 15:
156-
irq_n = EXTI15_10_IRQn;
157-
vector = (uint32_t)&gpio_irq15;
158-
break;
159113
default:
114+
error("This pin is not supported with InterruptIn.\n");
160115
return -1;
161116
}
117+
118+
// Enable GPIO clock
119+
uint32_t gpio_add = Set_GPIO_Clock(port_index);
162120

163-
// Enable GPIO and AFIO clocks
164-
RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE);
121+
// Enable AFIO clock
165122
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
166-
123+
167124
// Connect EXTI line to pin
168125
GPIO_EXTILineConfig(port_index, pin_index);
169126

@@ -186,20 +143,23 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
186143
NVIC_SetVector(irq_n, vector);
187144
NVIC_EnableIRQ(irq_n);
188145

189-
// Save for future use
190-
obj->ch = pin_index;
146+
// Save informations for future use
191147
obj->irq_n = irq_n;
148+
obj->irq_index = irq_index;
192149
obj->event = EDGE_NONE;
150+
channel_ids[irq_index] = id;
151+
channel_gpio[irq_index] = gpio_add;
152+
channel_pin[irq_index] = pin_index;
193153

194-
channel_ids[obj->ch] = id;
195-
196154
irq_handler = handler;
197155

198156
return 0;
199157
}
200158

201159
void gpio_irq_free(gpio_irq_t *obj) {
202-
channel_ids[obj->ch] = 0;
160+
channel_ids[obj->irq_index] = 0;
161+
channel_gpio[obj->irq_index] = 0;
162+
channel_pin[obj->irq_index] = 0;
203163
// Disable EXTI line
204164
EXTI_InitTypeDef EXTI_InitStructure;
205165
EXTI_StructInit(&EXTI_InitStructure);
@@ -210,7 +170,9 @@ void gpio_irq_free(gpio_irq_t *obj) {
210170
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
211171
EXTI_InitTypeDef EXTI_InitStructure;
212172

213-
EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << obj->ch);
173+
uint32_t pin_index = channel_pin[obj->irq_index];
174+
175+
EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index);
214176
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
215177

216178
if (event == IRQ_RISE) {

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ extern "C" {
4040
#endif
4141

4242
struct gpio_irq_s {
43-
uint32_t ch;
4443
IRQn_Type irq_n;
45-
uint32_t event; // 0=none, 1=rise, 2=fall, 3=rise+fall
44+
uint32_t irq_index;
45+
uint32_t event;
4646
};
4747

4848
struct port_s {

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,28 +43,58 @@ static const uint32_t AF_mapping[] = {
4343
GPIO_Remap_I2C1 // 8
4444
};
4545

46+
// Not an API function
47+
// Enable GPIO clock and return GPIO base address
48+
uint32_t Set_GPIO_Clock(uint32_t port_idx) {
49+
uint32_t gpio_add = 0;
50+
switch (port_idx) {
51+
case PortA:
52+
gpio_add = GPIOA_BASE;
53+
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
54+
break;
55+
case PortB:
56+
gpio_add = GPIOB_BASE;
57+
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
58+
break;
59+
case PortC:
60+
gpio_add = GPIOC_BASE;
61+
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
62+
break;
63+
case PortD:
64+
gpio_add = GPIOD_BASE;
65+
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
66+
break;
67+
default:
68+
error("Port number is not correct.");
69+
break;
70+
}
71+
return gpio_add;
72+
}
73+
4674
/**
47-
* Set the pin function (input, output, alternate function or analog) + output speed + AF
75+
* Configure pin (input, output, alternate function or analog) + output speed + AF
4876
*/
4977
void pin_function(PinName pin, int data) {
78+
GPIO_TypeDef *gpio;
79+
GPIO_InitTypeDef GPIO_InitStructure;
80+
5081
if (pin == NC) return;
5182

52-
// Get the pin mode and alternate-function number
83+
// Get the pin informations
5384
uint32_t mode = STM_PIN_MODE(data);
5485
uint32_t afnum = STM_PIN_AFNUM(data);
5586

5687
uint32_t port_index = STM_PORT(pin);
5788
uint32_t pin_index = STM_PIN(pin);
58-
59-
// Get GPIO structure base address
60-
GPIO_TypeDef *gpio = ((GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10)));
6189

62-
// Enable GPIO and AFIO clocks
63-
RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE);
90+
// Enable GPIO clock
91+
uint32_t gpio_add = Set_GPIO_Clock(port_index);
92+
gpio = (GPIO_TypeDef *)gpio_add;
93+
94+
// Enable AFIO clock
6495
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
6596

6697
// Configure GPIO
67-
GPIO_InitTypeDef GPIO_InitStructure;
6898
GPIO_InitStructure.GPIO_Pin = (uint16_t)(1 << pin_index);
6999
GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)mode;
70100
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
@@ -86,21 +116,20 @@ void pin_function(PinName pin, int data) {
86116
}
87117

88118
/**
89-
* Set the pin mode (open-drain/push-pull + pull-up/pull-down)
119+
* Configure pin pull-up/pull-down
90120
*/
91121
void pin_mode(PinName pin, PinMode mode) {
92-
if (pin == NC) return;
93-
122+
GPIO_TypeDef *gpio;
94123
GPIO_InitTypeDef GPIO_InitStructure;
95124

125+
if (pin == NC) return;
126+
96127
uint32_t port_index = STM_PORT(pin);
97128
uint32_t pin_index = STM_PIN(pin);
98-
99-
// Get GPIO structure base address
100-
GPIO_TypeDef *gpio = ((GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10)));
101129

102130
// Enable GPIO clock
103-
RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE);
131+
uint32_t gpio_add = Set_GPIO_Clock(port_index);
132+
gpio = (GPIO_TypeDef *)gpio_add;
104133

105134
// Configure open-drain and pull-up/down
106135
switch (mode) {

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/port_api.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,26 @@
3030
#include "port_api.h"
3131
#include "pinmap.h"
3232
#include "gpio_api.h"
33+
#include "error.h"
3334

3435
#if DEVICE_PORTIN || DEVICE_PORTOUT
3536

37+
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
38+
3639
// high nibble = port number (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...)
3740
// low nibble = pin number
3841
PinName port_pin(PortName port, int pin_n) {
3942
return (PinName)(pin_n + (port << 4));
4043
}
4144

4245
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
43-
46+
GPIO_TypeDef *gpio;
47+
4448
uint32_t port_index = (uint32_t)port; // (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...)
4549

4650
// Enable GPIO clock
47-
RCC_APB2PeriphClockCmd((RCC_APB2Periph_GPIOA << port_index), ENABLE);
48-
49-
// Get GPIO structure base address
50-
GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10));
51+
uint32_t gpio_add = Set_GPIO_Clock(port_index);
52+
gpio = (GPIO_TypeDef *)gpio_add;
5153

5254
// Fill PORT object structure for future use
5355
obj->port = port;

0 commit comments

Comments
 (0)