Skip to content

Commit 52c4383

Browse files
author
Kyle Wenner
committed
initial commit for gpio irq, ambiq apollo3
1 parent 2641b73 commit 52c4383

File tree

6 files changed

+341
-79
lines changed

6 files changed

+341
-79
lines changed

.mbedignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
features/

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ typedef enum {
147147
#define __IOM __IO
148148
#endif
149149

150+
#ifdef OVERFLOW
151+
#undef OVERFLOW
152+
#endif
150153

151154
/* ======================================== Start of section using anonymous unions ======================================== */
152155
#if defined (__CC_ARM)

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ void gpio_dir(gpio_t *obj, PinDirection direction){
102102
MBED_ASSERT(gpio_is_connected(obj));
103103
MBED_ASSERT(direction < (PinDirection)PIN_DIR_ELEMENTS);
104104

105-
if( direction & (PinDirection)PIN_INPUT ){
105+
if( direction == (PinDirection)PIN_INPUT ){
106106
obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE;
107107
obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE;
108108
}
109-
else if ( direction & (PinDirection)PIN_OUTPUT ){
109+
else if ( direction == (PinDirection)PIN_OUTPUT ){
110110
obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
111111
obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA;
112112
obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE;
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#include "gpio_irq_api.h"
2+
#include "objects.h"
3+
4+
#if DEVICE_INTERRUPTIN
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir);
12+
13+
/** GPIO IRQ HAL structure. gpio_irq_s is declared in the target's HAL
14+
*/
15+
typedef struct gpio_irq_s gpio_irq_t;
16+
17+
typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event);
18+
extern void am_gpio_isr(void);
19+
static ap3_gpio_irq_control_t gpio_irq_control[AP3_GPIO_MAX_PADS];
20+
21+
/**
22+
* \defgroup hal_gpioirq GPIO IRQ HAL functions
23+
*
24+
* # Defined behavior
25+
* * ::gpio_irq_init initializes the GPIO IRQ pin
26+
* * ::gpio_irq_init attaches the interrupt handler
27+
* * ::gpio_irq_free releases the GPIO IRQ pin
28+
* * ::gpio_irq_set enables/disables pin IRQ event
29+
* * ::gpio_irq_enable enables GPIO IRQ
30+
* * ::gpio_irq_disable disables GPIO IRQ
31+
*
32+
* # Undefined behavior
33+
* * Calling other function before ::gpio_irq_init
34+
*
35+
* @{
36+
*/
37+
38+
/** Initialize the GPIO IRQ pin
39+
*
40+
* @param obj The GPIO object to initialize
41+
* @param pin The GPIO pin name
42+
* @param handler The handler to be attached to GPIO IRQ
43+
* @param id The object ID (id != 0, 0 is reserved)
44+
* @return -1 if pin is NC, 0 otherwise
45+
*/
46+
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
47+
{
48+
//grab the correct irq control object
49+
ap3_gpio_irq_control_t control = gpio_irq_control[pin];
50+
51+
//Register locally
52+
control.pad = pin;
53+
control.handler = handler;
54+
control.id = id;
55+
control.events = IRQ_NONE;
56+
57+
//Attach to object
58+
obj->control = &control;
59+
60+
//Make sure the interrupt is set to none to reflect the new events value
61+
ap3_gpio_enable_interrupts(control.pad, AM_HAL_GPIO_PIN_INTDIR_NONE);
62+
63+
//Enable GPIO IRQ's in the NVIC
64+
NVIC_SetVector((IRQn_Type)GPIO_IRQn, (uint32_t)am_gpio_isr);
65+
NVIC_EnableIRQ((IRQn_Type)GPIO_IRQn);
66+
return 0;
67+
}
68+
69+
void am_gpio_isr(void)
70+
{
71+
//call the handler for the interrupt
72+
uint64_t gpio_int_mask = 0x00;
73+
am_hal_gpio_interrupt_status_get(true, &gpio_int_mask);
74+
uint32_t pinNum = 0;
75+
while (gpio_int_mask)
76+
{
77+
if (gpio_int_mask |= 0x0000000000000001)
78+
{
79+
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pinNum));
80+
ap3_gpio_irq_control_t irq_ctrl = gpio_irq_control[pinNum];
81+
((gpio_irq_handler)irq_ctrl.handler)(irq_ctrl.id, irq_ctrl.events);
82+
}
83+
gpio_int_mask >>= 1;
84+
pinNum++;
85+
}
86+
}
87+
88+
/** Release the GPIO IRQ PIN
89+
*
90+
* @param obj The gpio object
91+
*/
92+
void gpio_irq_free(gpio_irq_t *obj)
93+
{
94+
}
95+
96+
/** Enable/disable pin IRQ event
97+
*
98+
* @param obj The GPIO object
99+
* @param event The GPIO IRQ event
100+
* @param enable The enable flag
101+
*/
102+
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
103+
{
104+
//Clear state
105+
obj->control->events &= (~event);
106+
if (enable)
107+
{
108+
//Reset if enabled
109+
obj->control->events |= event;
110+
}
111+
112+
// Map enabled events to a value the reflects the ambiq hal/register values
113+
am_hal_gpio_intdir_e ap3_int_dir = 0x00;
114+
switch (obj->control->events)
115+
{
116+
case IRQ_NONE:
117+
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_NONE;
118+
break;
119+
case IRQ_RISE:
120+
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
121+
break;
122+
case IRQ_FALL:
123+
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_HI2LO;
124+
break;
125+
case (IRQ_RISE | IRQ_FALL):
126+
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_BOTH;
127+
break;
128+
}
129+
130+
ap3_gpio_enable_interrupts(obj->control->pad, ap3_int_dir);
131+
}
132+
133+
/** Enable GPIO IRQ
134+
*
135+
* This is target dependent, as it might enable the entire port or just a pin
136+
* @param obj The GPIO object
137+
*/
138+
void gpio_irq_enable(gpio_irq_t *obj)
139+
{
140+
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad));
141+
am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(obj->control->pad));
142+
}
143+
144+
/** Disable GPIO IRQ
145+
*
146+
* This is target dependent, as it might disable the entire port or just a pin
147+
* @param obj The GPIO object
148+
*/
149+
void gpio_irq_disable(gpio_irq_t *obj)
150+
{
151+
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad));
152+
am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(obj->control->pad));
153+
}
154+
155+
/**@}*/
156+
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir)
157+
{
158+
uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg;
159+
uint32_t ui32Funcsel, ui32PowerSw;
160+
bool bClearEnable = false;
161+
162+
#ifndef AM_HAL_DISABLE_API_VALIDATION
163+
if (ui32Pin >= AM_HAL_GPIO_MAX_PADS)
164+
{
165+
return AM_HAL_STATUS_INVALID_ARG;
166+
}
167+
#endif // AM_HAL_DISABLE_API_VALIDATION
168+
169+
//
170+
// Initialize the PADREG accumulator variables.
171+
//
172+
ui32GPCfg = ui32Padreg = ui32AltPadCfg = 0;
173+
174+
//
175+
// Map the requested interrupt direction settings into the Apollo3
176+
// GPIOCFG register field, which is a 4-bit field:
177+
// [INTD(1):OUTCFG(2):INCFG(1)].
178+
// Bit0 of eIntDir maps to GPIOCFG.INTD (b3).
179+
// Bit1 of eIntDir maps to GPIOCFG.INCFG (b0).
180+
//
181+
ui32GPCfg |= (((eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | (((eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S);
182+
183+
//
184+
// At this point, the configuration variable, ui32GpioCfg
185+
// value is set (at bit position 0) and ready to write
186+
// to their respective register bitfields.
187+
//
188+
uint32_t ui32GPCfgAddr;
189+
uint32_t ui32GPCfgClearMask;
190+
uint32_t ui32GPCfgShft;
191+
192+
ui32GPCfgShft = ((ui32Pin & 0x7) << 2);
193+
194+
ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3);
195+
196+
ui32GPCfgClearMask = ~((uint32_t)0xF << ui32GPCfgShft);
197+
198+
//
199+
// Get the new values into their rightful bit positions.
200+
//
201+
ui32GPCfg <<= ui32GPCfgShft;
202+
203+
AM_CRITICAL_BEGIN
204+
205+
if (bClearEnable)
206+
{
207+
//
208+
// We're configuring a mode that requires clearing the Enable bit.
209+
//
210+
am_hal_gpio_output_tristate_disable(ui32Pin);
211+
}
212+
213+
GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key;
214+
215+
// Here's where the magic happens
216+
AM_REGVAL(ui32GPCfgAddr) = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgClearMask) | ui32GPCfg;
217+
218+
GPIO->PADKEY = 0;
219+
220+
AM_CRITICAL_END
221+
222+
return AM_HAL_STATUS_SUCCESS;
223+
224+
} // am_hal_gpio_pinconfig()
225+
226+
#ifdef __cplusplus
227+
}
228+
#endif
229+
/** @}*/
230+
#endif //DEVICE_INTERRUPTIN

0 commit comments

Comments
 (0)