Skip to content

Commit 04be03f

Browse files
committed
bsp: ab32vg1 board support gpio interrupt
1 parent 7598581 commit 04be03f

File tree

3 files changed

+243
-10
lines changed

3 files changed

+243
-10
lines changed

bsp/bluetrum/libraries/hal_drivers/drv_gpio.c

Lines changed: 217 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Change Logs:
77
* Date Author Notes
88
* 2020-11-19 greedyhao first version
9+
* 2025-05-15 kurisaW support gpio interrupt
910
*/
1011

1112
#include "drv_gpio.h"
@@ -40,6 +41,10 @@ static const hal_sfr_t port_sfr[] =
4041
GPIOF_BASE,
4142
};
4243

44+
// Static variables
45+
static struct ab32_pin_irq pin_irq_table[8] = {0}; // For WAKEUP_CRICUIT_0 to _7
46+
static rt_mq_t gpio_irq_mq = RT_NULL;
47+
4348
static rt_uint8_t _pin_port(rt_uint32_t pin)
4449
{
4550
rt_uint8_t port = 0;
@@ -99,21 +104,21 @@ static rt_base_t ab32_pin_get(const char *name)
99104
return pin;
100105
}
101106

102-
static void ab32_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
107+
static void ab32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
103108
{
104109
rt_uint8_t port = PIN_PORT(pin);
105110
rt_uint8_t gpio_pin = pin - port_table[port].total_pin;
106111
hal_gpio_write(PORT_SFR(port), gpio_pin, (rt_uint8_t)value);
107112
}
108113

109-
static rt_ssize_t ab32_pin_read(rt_device_t dev, rt_base_t pin)
114+
static int ab32_pin_read(rt_device_t dev, rt_base_t pin)
110115
{
111116
rt_uint8_t port = PIN_PORT(pin);
112117
rt_uint8_t gpio_pin = pin - port_table[port].total_pin;
113118
return hal_gpio_read(PORT_SFR(port), gpio_pin);
114119
}
115120

116-
static void ab32_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
121+
static void ab32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
117122
{
118123
struct gpio_init gpio_init;
119124
rt_uint8_t port = PIN_PORT(pin);
@@ -147,22 +152,224 @@ static void ab32_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
147152
hal_gpio_init(PORT_SFR(port), &gpio_init);
148153
}
149154

150-
static rt_err_t ab32_pin_attach_irq(struct rt_device *device, rt_base_t pin,
151-
rt_uint8_t mode, void (*hdr)(void *args), void *args)
155+
static rt_err_t get_port_pin(rt_base_t pin, rt_uint8_t *port, rt_uint8_t *hw_pin)
156+
{
157+
rt_uint8_t i;
158+
for (i = 0; i < sizeof(port_table) / sizeof(port_table[0]); i++)
159+
{
160+
if (pin >= port_table[i].total_pin &&
161+
pin < port_table[i].total_pin + port_table[i].delta_pin)
162+
{
163+
*port = i;
164+
*hw_pin = pin - port_table[i].total_pin + port_table[i].start_pin;
165+
return RT_EOK;
166+
}
167+
}
168+
return -RT_EINVAL;
169+
}
170+
171+
static rt_int32_t get_wakeup_circuit(rt_base_t pin)
172+
{
173+
/* Special interrupt pins */
174+
if (pin == PIN_NUM(0, 7)) return WAKEUP_CRICUIT_0; // PA7
175+
if (pin == PIN_NUM(1, 1)) return WAKEUP_CRICUIT_1; // PB1
176+
if (pin == PIN_NUM(1, 2)) return WAKEUP_CRICUIT_2; // PB2
177+
if (pin == PIN_NUM(1, 3)) return WAKEUP_CRICUIT_3; // PB3
178+
if (pin == PIN_NUM(1, 4)) return WAKEUP_CRICUIT_4; // PB4
179+
/* WAKEUP_CRICUIT_5 is for RTC (WKO), assuming not a GPIO pin */
180+
/* Other pins use WAKEUP_CRICUIT_6 (falling) or WAKEUP_CRICUIT_7 (rising) */
181+
return -1; // Will be handled in attach_irq based on mode
182+
}
183+
184+
static rt_uint32_t get_edge_select_bit(rt_uint8_t circuit)
185+
{
186+
switch (circuit)
187+
{
188+
case WAKEUP_CRICUIT_0: return WAKEUP_EDGE_SELECT_0;
189+
case WAKEUP_CRICUIT_1: return WAKEUP_EDGE_SELECT_1;
190+
case WAKEUP_CRICUIT_2: return WAKEUP_EDGE_SELECT_2;
191+
case WAKEUP_CRICUIT_3: return WAKEUP_EDGE_SELECT_3;
192+
case WAKEUP_CRICUIT_4: return WAKEUP_EDGE_SELECT_4;
193+
case WAKEUP_CRICUIT_5: return WAKEUP_EDGE_SELECT_5;
194+
case WAKEUP_CRICUIT_6: return WAKEUP_EDGE_SELECT_6;
195+
case WAKEUP_CRICUIT_7: return WAKEUP_EDGE_SELECT_7;
196+
default: return 0;
197+
}
198+
}
199+
200+
RT_SECTION(".irq.gpio")
201+
static void ab32_pin_irq_handler(void)
202+
{
203+
rt_interrupt_enter();
204+
rt_uint32_t pending = WKUPEDG;
205+
rt_uint8_t circuit = 0;
206+
207+
for (circuit = 0; circuit <= WAKEUP_CRICUIT_7; circuit++)
208+
{
209+
if (pending & (BIT(circuit) << WAKEUP_INT_ENABLE))
210+
{
211+
/* clear pending interrupt */
212+
WKUPCPND = (BIT(circuit) << WAKEUP_INT_ENABLE);
213+
rt_mq_send(gpio_irq_mq, &circuit, sizeof(circuit));
214+
}
215+
}
216+
rt_interrupt_leave();
217+
}
218+
219+
static void ab32_pin_irq_thread(void *parameter)
152220
{
153-
return -RT_ERROR;
221+
rt_uint8_t circuit;
222+
while (1)
223+
{
224+
if (rt_mq_recv(gpio_irq_mq, &circuit, sizeof(circuit), RT_WAITING_FOREVER) == RT_EOK)
225+
{
226+
if (circuit <= WAKEUP_CRICUIT_7 && pin_irq_table[circuit].hdr)
227+
{
228+
pin_irq_table[circuit].hdr(pin_irq_table[circuit].args);
229+
}
230+
}
231+
}
154232
}
155233

156-
static rt_err_t ab32_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
234+
static rt_err_t ab32_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
235+
rt_uint32_t mode, void (*hdr)(void *args), void *args)
157236
{
158-
return -RT_ERROR;
237+
rt_uint8_t port, hw_pin;
238+
rt_int32_t circuit;
239+
uint8_t pin_mode;
240+
241+
if (get_port_pin(pin, &port, &hw_pin) != RT_EOK)
242+
{
243+
return -RT_EINVAL;
244+
}
245+
246+
circuit = get_wakeup_circuit(pin);
247+
if(circuit == -1)
248+
{
249+
circuit = (mode == PIN_IRQ_MODE_FALLING) ? WAKEUP_CRICUIT_6 : WAKEUP_CRICUIT_7;
250+
}
251+
252+
/* store handler and arguments */
253+
pin_irq_table[circuit].hdr = hdr;
254+
pin_irq_table[circuit].args = args;
255+
256+
/* The interrupt source in the port is: Port_intsrc = {PG[4:0], PF[5:0], PE[7:0], PB[4:0], PA[7:0]}. */
257+
/* Such as:the interrupt source number of PA0 is 0, interrupt source number of PG4 is 31. */
258+
PORTINTEN |= BIT(pin); // Enable interrupt
259+
PORTINTEDG |= BIT(pin); // Edge trigger
260+
261+
return RT_EOK;
262+
}
263+
264+
static rt_err_t ab32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
265+
{
266+
rt_uint8_t port, hw_pin;
267+
rt_int32_t circuit;
268+
269+
if (get_port_pin(pin, &port, &hw_pin) != RT_EOK)
270+
{
271+
return -RT_EINVAL;
272+
}
273+
274+
circuit = get_wakeup_circuit(pin);
275+
if (circuit < 0)
276+
{
277+
/* assume previously assigned to WAKEUP_CRICUIT_6 or _7 */
278+
/* check both circuits for handler */
279+
if (pin_irq_table[WAKEUP_CRICUIT_6].hdr)
280+
circuit = WAKEUP_CRICUIT_6;
281+
else if (pin_irq_table[WAKEUP_CRICUIT_7].hdr)
282+
circuit = WAKEUP_CRICUIT_7;
283+
else
284+
return RT_EOK;
285+
}
286+
287+
PORTINTEN &= ~BIT(circuit);
288+
WKUPCON &= ~BIT(circuit);
289+
WKUPCPND = BIT(get_edge_select_bit(circuit));
290+
291+
/* clear handler */
292+
pin_irq_table[circuit].hdr = RT_NULL;
293+
pin_irq_table[circuit].args = RT_NULL;
294+
295+
return RT_EOK;
159296
}
160297

161298
static rt_err_t ab32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
162-
rt_uint8_t enabled)
299+
rt_uint32_t enabled)
163300
{
164-
return -RT_ERROR;
301+
rt_uint8_t port, hw_pin;
302+
rt_int32_t circuit;
303+
304+
if (get_port_pin(pin, &port, &hw_pin) != RT_EOK)
305+
{
306+
return -RT_EINVAL;
307+
}
308+
309+
circuit = get_wakeup_circuit(pin);
310+
if (circuit < 0)
311+
{
312+
if (pin_irq_table[WAKEUP_CRICUIT_6].hdr)
313+
{
314+
circuit = WAKEUP_CRICUIT_6;
315+
}
316+
else if (pin_irq_table[WAKEUP_CRICUIT_7].hdr)
317+
{
318+
circuit = WAKEUP_CRICUIT_7;
319+
}
320+
else
321+
return -RT_EINVAL;
322+
}
323+
324+
rt_uint32_t edge_bit = get_edge_select_bit(circuit);
325+
326+
if (enabled == RT_TRUE)
327+
{
328+
WKUPEDG = BIT(circuit) | BIT(edge_bit);
329+
WKUPCON = BIT(circuit) | BIT(WAKEUP_INT_ENABLE);
330+
331+
WKUPCPND = BIT(circuit);
332+
333+
/* install interrupt handler */
334+
rt_hw_interrupt_install(IRQ_GPIO_IRQ, ab32_pin_irq_handler, RT_NULL, "gpio_isr");
335+
rt_hw_irq_enable(IRQ_GPIO_IRQ);
336+
}
337+
else
338+
{
339+
/* disable interrupt */
340+
WKUPCON &= ~BIT(circuit);
341+
}
342+
343+
return RT_EOK;
344+
}
345+
346+
static int ab32_pin_irq_init(void)
347+
{
348+
gpio_irq_mq = rt_mq_create("gpio_irq", sizeof(rt_uint8_t), 128, RT_IPC_FLAG_FIFO);
349+
if (gpio_irq_mq == RT_NULL)
350+
{
351+
return -RT_ENOMEM;
352+
}
353+
354+
rt_thread_t tid = rt_thread_create("gpio_irq",
355+
ab32_pin_irq_thread,
356+
RT_NULL,
357+
512,
358+
15,
359+
5);
360+
if (tid != RT_NULL)
361+
{
362+
rt_thread_startup(tid);
363+
}
364+
else
365+
{
366+
rt_mq_delete(gpio_irq_mq);
367+
return -RT_ENOMEM;
368+
}
369+
370+
return RT_EOK;
165371
}
372+
INIT_PREV_EXPORT(ab32_pin_irq_init);
166373

167374
const static struct rt_pin_ops _ab32_pin_ops =
168375
{

bsp/bluetrum/libraries/hal_drivers/drv_gpio.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,31 @@
2020
#define __AB32_GET_PIN_E(PIN) 13 + PIN
2121
#define __AB32_GET_PIN_F(PIN) 21 + PIN
2222

23+
#define WAKEUP_INT_ENABLE 16
24+
#define WAKEUP_CRICUIT_0 0 // PA7
25+
#define WAKEUP_CRICUIT_1 1 // PB1
26+
#define WAKEUP_CRICUIT_2 2 // PB2
27+
#define WAKEUP_CRICUIT_3 3 // PB3
28+
#define WAKEUP_CRICUIT_4 4 // PB4
29+
#define WAKEUP_CRICUIT_5 5 // WKO (RTC)
30+
#define WAKEUP_CRICUIT_6 6 // Falling edge for other GPIOs
31+
#define WAKEUP_CRICUIT_7 7 // Rising edge for other GPIOs
32+
#define WAKEUP_EDGE_SELECT_0 16
33+
#define WAKEUP_EDGE_SELECT_1 17
34+
#define WAKEUP_EDGE_SELECT_2 18
35+
#define WAKEUP_EDGE_SELECT_3 19
36+
#define WAKEUP_EDGE_SELECT_4 20
37+
#define WAKEUP_EDGE_SELECT_5 21
38+
#define WAKEUP_EDGE_SELECT_6 22
39+
#define WAKEUP_EDGE_SELECT_7 23
40+
41+
// Structure to store IRQ handler and arguments per pin
42+
struct ab32_pin_irq
43+
{
44+
void (*hdr)(void *args);
45+
void *args;
46+
};
47+
2348
int rt_hw_pin_init(void);
2449

2550
#endif // DRV_GPIO_H__

bsp/bluetrum/libraries/hal_libraries/bmsis/include/ab32vg1.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ typedef enum
3030
IRQ_HSUART_VECTOR = 15,
3131
IRQ_RTC_VECTOR = 16, /*!< RTC, LVD and WDT Interrupt */
3232
IRQ_I2S_VECTOR = 17,
33+
IRQ_GPIO_IRQ = 18,
3334
IRQ_TOTAL_NUM = 23,
3435
} irq_type;
3536
#endif // __ASSEMBLER__

0 commit comments

Comments
 (0)