Skip to content

Commit b5c7229

Browse files
Ambiq Apollo3: Make SFW_ARTEMIS use arduino uno form factor, fix GPIO IRQ API
1 parent 912f208 commit b5c7229

File tree

5 files changed

+125
-63
lines changed

5 files changed

+125
-63
lines changed

hal/include/hal/gpio_irq_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef void (*gpio_irq_handler)(uintptr_t context, gpio_irq_event event);
4949
* # Defined behavior
5050
* * ::gpio_irq_init initializes the GPIO IRQ pin
5151
* * ::gpio_irq_init attaches the interrupt handler
52+
* * ::gpio_irq_init enables the IRQ
5253
* * ::gpio_irq_free releases the GPIO IRQ pin
5354
* * ::gpio_irq_set enables/disables pin IRQ event
5455
* * ::gpio_irq_enable enables GPIO IRQ

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_SFE_ARTEMIS/PinNames.h

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,68 +39,82 @@ extern "C"
3939
typedef enum
4040
{
4141
// Digital naming
42-
D0 = 25,
43-
D1 = 24,
44-
D2 = 35,
45-
D3 = 4,
46-
D4 = 22,
47-
D5 = 23,
48-
D6 = 27,
49-
D7 = 28,
50-
D8 = 32,
51-
D9 = 12,
52-
D10 = 13,
53-
D11 = 7,
54-
D12 = 6,
55-
D13 = 5,
56-
D14 = 40,
57-
D15 = 39,
58-
D16 = 29,
59-
D17 = 11,
60-
D18 = 34,
61-
D19 = 33,
62-
D20 = 16,
63-
D21 = 31,
64-
65-
// Analog naming
66-
A0 = D16,
67-
A1 = D17,
68-
A2 = D18,
69-
A3 = D19,
70-
A4 = D20,
71-
A5 = D21,
72-
A6 = D2,
73-
// A7 = ??
74-
A8 = D8,
75-
A9 = D9,
76-
A10 = D10,
42+
p0 = 25,
43+
p1 = 24,
44+
p2 = 35,
45+
p3 = 4,
46+
p4 = 22,
47+
p5 = 23,
48+
p6 = 27,
49+
p7 = 28,
50+
p8 = 32,
51+
p9 = 12,
52+
p10 = 13,
53+
p11 = 7,
54+
p12 = 6,
55+
p13 = 5,
56+
p14 = 40,
57+
p15 = 39,
58+
p16 = 29,
59+
p17 = 11,
60+
p18 = 34,
61+
p19 = 33,
62+
p20 = 16,
63+
p21 = 31,
64+
65+
#ifdef TARGET_FF_ARDUINO_UNO
66+
// Arduino form factor pins
67+
ARDUINO_UNO_D0 = p0,
68+
ARDUINO_UNO_D1 = p1,
69+
ARDUINO_UNO_D2 = p2,
70+
ARDUINO_UNO_D3 = p3,
71+
ARDUINO_UNO_D4 = p4,
72+
ARDUINO_UNO_D5 = p5,
73+
ARDUINO_UNO_D6 = p6,
74+
ARDUINO_UNO_D7 = p7,
75+
ARDUINO_UNO_D8 = p8,
76+
ARDUINO_UNO_D9 = p9,
77+
ARDUINO_UNO_D10 = p10,
78+
ARDUINO_UNO_D11 = p11,
79+
ARDUINO_UNO_D12 = p12,
80+
ARDUINO_UNO_D13 = p13,
81+
ARDUINO_UNO_D14 = p14,
82+
ARDUINO_UNO_D15 = p15,
83+
84+
ARDUINO_UNO_A0 = p16,
85+
ARDUINO_UNO_A1 = p17,
86+
ARDUINO_UNO_A2 = p18,
87+
ARDUINO_UNO_A3 = p19,
88+
ARDUINO_UNO_A4 = p20,
89+
ARDUINO_UNO_A5 = p21,
90+
ARDUINO_UNO_A6 = p2,
91+
#endif
7792

7893
// UART
7994
SERIAL_TX = AM_BSP_PRIM_UART_TX_PIN,
8095
SERIAL_RX = AM_BSP_PRIM_UART_RX_PIN,
8196
CONSOLE_TX = SERIAL_TX,
8297
CONSOLE_RX = SERIAL_RX,
8398

84-
SERIAL1_TX = D1,
85-
SERIAL1_RX = D0,
99+
SERIAL1_TX = p1,
100+
SERIAL1_RX = p0,
86101

87102
// Not connected
88103
NC = NC_VAL
89104
} PinName;
90105

91106
// LEDs
92-
#define LED1 D13 // Blue LED
107+
#define LED1 p13 // Blue LED
93108

94109
// I2C bus
95-
#define I2C_SCL D15
96-
#define I2C_SDA D14
110+
// note: I2C_SCL and I2C_SDA defines are provided by the FF_ARDUINO_UNO header
97111
#define QWIIC_SCL I2C_SCL
98112
#define QWIIC_SDA I2C_SDA
99113

100114
// SPI bus
101-
#define SPI_CLK D13
102-
#define SPI_SDO D11
103-
#define SPI_SDI D12
115+
#define SPI_CLK p13
116+
#define SPI_SDO p11
117+
#define SPI_SDI p12
104118

105119
#if defined(MBED_CONF_TARGET_STDIO_UART_TX)
106120
#define STDIO_UART_TX MBED_CONF_TARGET_STDIO_UART_TX

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern "C"
3131
{
3232
#endif
3333

34+
static void ap3_gpio_update_int_en(gpio_irq_t *obj);
3435
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir);
3536
/** GPIO IRQ HAL structure. gpio_irq_s is declared in the target's HAL
3637
*/
@@ -70,20 +71,19 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uintpt
7071
//grab the correct irq control object
7172
ap3_gpio_irq_control_t *control = &gpio_irq_control[pin];
7273

73-
//Register locally
74+
// Register locally
7475
control->pad = pin;
7576
control->handler = handler;
7677
control->id = context;
7778
control->events = IRQ_NONE;
7879

79-
//Attach to object
80+
// Attach to object
8081
obj->control = control;
8182

82-
//Make sure the interrupt is set to none to reflect the new events value
83-
ap3_gpio_enable_interrupts(control->pad, AM_HAL_GPIO_PIN_INTDIR_NONE);
83+
// Start with the IRQ "enabled", but don't actually enable it till something is attached
84+
obj->irq_requested_enabled = true;
8485

85-
//Enable GPIO IRQ's in the NVIC
86-
gpio_irq_enable(obj);
86+
// Make sure the GPIO IRQ is enabled in NVIC
8787
NVIC_SetVector((IRQn_Type)GPIO_IRQn, (uint32_t)am_gpio_isr);
8888
NVIC_EnableIRQ((IRQn_Type)GPIO_IRQn);
8989
return 0;
@@ -99,7 +99,18 @@ void am_gpio_isr(void)
9999
if (gpio_int_mask & 0x0000000000000001) {
100100
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pinNum));
101101
ap3_gpio_irq_control_t irq_ctrl = gpio_irq_control[pinNum];
102-
((gpio_irq_handler)irq_ctrl.handler)(irq_ctrl.id, irq_ctrl.events);
102+
103+
uint8_t event = irq_ctrl.events;
104+
if(event == (IRQ_RISE | IRQ_FALL))
105+
{
106+
// This pin is configured for both rise and fall events. However, this MCU does not have separate
107+
// status registers for tracking rising/falling interrupts.
108+
// So, read the pin to figure out which interrupt happened. It's not totally foolproof but
109+
// it should work in most cases.
110+
event = am_hal_gpio_input_read(irq_ctrl.pad) ? IRQ_RISE : IRQ_FALL;
111+
}
112+
113+
((gpio_irq_handler)irq_ctrl.handler)(irq_ctrl.id, event);
103114
}
104115
gpio_int_mask >>= 1;
105116
pinNum++;
@@ -112,6 +123,8 @@ void am_gpio_isr(void)
112123
*/
113124
void gpio_irq_free(gpio_irq_t *obj)
114125
{
126+
// Make sure interrupt can't trigger
127+
gpio_irq_disable(obj);
115128
}
116129

117130
/** Enable/disable pin IRQ event
@@ -121,20 +134,21 @@ void gpio_irq_free(gpio_irq_t *obj)
121134
* @param enable The enable flag
122135
*/
123136
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
124-
{
125-
//Clear state
126-
obj->control->events &= (~event);
137+
{
127138
if (enable) {
128-
//Reset if enabled
129139
obj->control->events |= event;
130140
}
141+
else {
142+
obj->control->events &= ~event;
143+
}
131144

132-
// Map enabled events to a value the reflects the ambiq hal/register values
145+
// Map enabled events to a value the reflects the ambiq hal/register values.
146+
// Note that we don't want to actually set INTDIR_NONE, because this disables reading the pin (!!)
147+
// So instead, if asked to disable the IRQ, we leave LO2HIGH interrupt enabled in the PINCFG register but
148+
// don't enable the interrupt for this pin in the register
133149
am_hal_gpio_intdir_e ap3_int_dir = 0x00;
134150
switch (obj->control->events) {
135151
case IRQ_NONE:
136-
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_NONE;
137-
break;
138152
case IRQ_RISE:
139153
ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
140154
break;
@@ -146,7 +160,17 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
146160
break;
147161
}
148162

163+
// If switching to NONE, disable the IRQ first
164+
if(obj->control->events == IRQ_NONE) {
165+
ap3_gpio_update_int_en(obj);
166+
}
167+
149168
ap3_gpio_enable_interrupts(obj->control->pad, ap3_int_dir);
169+
170+
// Otherwise enable IRQ now
171+
if(obj->control->events != IRQ_NONE) {
172+
ap3_gpio_update_int_en(obj);
173+
}
150174
}
151175

152176
/** Enable GPIO IRQ
@@ -156,8 +180,8 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
156180
*/
157181
void gpio_irq_enable(gpio_irq_t *obj)
158182
{
159-
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad));
160-
am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(obj->control->pad));
183+
obj->irq_requested_enabled = true;
184+
ap3_gpio_update_int_en(obj);
161185
}
162186

163187
/** Disable GPIO IRQ
@@ -167,11 +191,27 @@ void gpio_irq_enable(gpio_irq_t *obj)
167191
*/
168192
void gpio_irq_disable(gpio_irq_t *obj)
169193
{
170-
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad));
171-
am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(obj->control->pad));
194+
obj->irq_requested_enabled = false;
195+
ap3_gpio_update_int_en(obj);
172196
}
173197

174198
/**@}*/
199+
200+
// Based on the enabled events and irq_requested_enabled, enable or disable the IRQ
201+
static void ap3_gpio_update_int_en(gpio_irq_t *obj)
202+
{
203+
if(obj->irq_requested_enabled && obj->control->events != IRQ_NONE) {
204+
// Enable!
205+
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad));
206+
am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(obj->control->pad));
207+
}
208+
else {
209+
// Disable
210+
am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(obj->control->pad));
211+
}
212+
}
213+
214+
175215
uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir)
176216
{
177217
uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg;
@@ -208,7 +248,8 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntD
208248

209249
ui32GPCfgShft = ((ui32Pin & 0x7) << 2);
210250

211-
ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3);
251+
// 8 pins per register, and each register is 32 bits wide
252+
ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + (ui32Pin / 8) * sizeof(uint32_t);
212253

213254
ui32GPCfgClearMask = ~((uint32_t)0xF << ui32GPCfgShft);
214255

targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "am_hal_gpio.h"
2828
#include "PinNames.h"
2929

30+
#include <stdbool.h>
31+
3032
#ifdef __cplusplus
3133
extern "C"
3234
{
@@ -124,6 +126,7 @@ typedef struct ap3_gpio_irq_control_t {
124126

125127
typedef struct gpio_irq_s {
126128
ap3_gpio_irq_control_t *control;
129+
bool irq_requested_enabled;
127130
} gpio_irq_s;
128131

129132
#define AP3_PINCFG_FUNCSEL_GPIO 3

targets/targets.json5

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9665,7 +9665,10 @@ mode is recommended for target MCUs with small amounts of flash and RAM.",
96659665
},
96669666
"SFE_ARTEMIS": { // AKA SparkFun RedBoard Artemis
96679667
"inherits": ["AMA3B1KK"],
9668-
"image_url": "https://cdn.sparkfun.com/r/455-455/assets/parts/1/4/0/1/9/15444-SparkFun_RedBoard_Artemis-01.jpg"
9668+
"image_url": "https://cdn.sparkfun.com/r/455-455/assets/parts/1/4/0/1/9/15444-SparkFun_RedBoard_Artemis-01.jpg",
9669+
"supported_form_factors": [
9670+
"ARDUINO_UNO"
9671+
]
96699672
},
96709673
"SFE_ARTEMIS_ATP": { // AKA SparkFun RedBoard Artemis ATP
96719674
"inherits": ["AMA3B1KK"],

0 commit comments

Comments
 (0)