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