Skip to content

Commit

Permalink
GPIO: Use uintptr_t for gpio_irq_api context
Browse files Browse the repository at this point in the history
The HAL gpio_irq_api stores object IDs, which serve as a form of context
for the dispatch of the interrupt handler in the drivers level
InterruptIn Class. The way this is achieved is that the InterruptIn
Class casts its address to uint32_t, which is stored as the ID.
This results in compilation failure when the size of an object pointer
is greater than uint32_t, for example when building on a PC for unit
testing.

In order to allow Unit Testing of the InterruptIn Class, we replace the
use of uint32_t with uintptr_t (type capable of holding a pointer),
which allows portability and expresses intentions more clearly.
In aid of this latter goal, we also replace the use of the name "id"
with "context", to improve clarity - these are addresses of the context
related to that callback.
  • Loading branch information
hazzlim committed Jan 26, 2022
1 parent a580c41 commit f4e5359
Show file tree
Hide file tree
Showing 43 changed files with 233 additions and 233 deletions.
2 changes: 1 addition & 1 deletion drivers/include/drivers/InterruptIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class InterruptIn : private NonCopyable<InterruptIn> {
*/
void disable_irq();

static void _irq_handler(uint32_t id, gpio_irq_event event);
static void _irq_handler(uintptr_t context, gpio_irq_event event);
#if !defined(DOXYGEN_ONLY)
protected:
gpio_t gpio;
Expand Down
6 changes: 3 additions & 3 deletions drivers/source/InterruptIn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ InterruptIn::InterruptIn(PinName pin, PinMode mode) :

void InterruptIn::irq_init(PinName pin)
{
gpio_irq_init(&gpio_irq, pin, (&InterruptIn::_irq_handler), (uint32_t)this);
gpio_irq_init(&gpio_irq, pin, (&InterruptIn::_irq_handler), reinterpret_cast<uintptr_t>(this));
}

InterruptIn::~InterruptIn()
Expand Down Expand Up @@ -95,9 +95,9 @@ void InterruptIn::fall(Callback<void()> func)
core_util_critical_section_exit();
}

void InterruptIn::_irq_handler(uint32_t id, gpio_irq_event event)
void InterruptIn::_irq_handler(uintptr_t context, gpio_irq_event event)
{
InterruptIn *handler = (InterruptIn *)id;
InterruptIn *handler = reinterpret_cast<InterruptIn *>(context);
switch (event) {
case IRQ_RISE:
if (handler->_rise) {
Expand Down
6 changes: 3 additions & 3 deletions hal/include/hal/gpio_irq_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ typedef enum {
*/
typedef struct gpio_irq_s gpio_irq_t;

typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event);
typedef void (*gpio_irq_handler)(uintptr_t context, gpio_irq_event event);

/**
* \defgroup hal_gpioirq GPIO IRQ HAL functions
Expand Down Expand Up @@ -75,10 +75,10 @@ typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event);
* @param obj The GPIO object to initialize
* @param pin The GPIO pin name
* @param handler The handler to be attached to GPIO IRQ
* @param id The object ID (id != 0, 0 is reserved)
* @param context The context to be passed back to the handler (context != 0, 0 is reserved)
* @return -1 if pin is NC, 0 otherwise
*/
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id);
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uintptr_t context);

/** Release the GPIO IRQ PIN
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using namespace utest::v1;
MbedTester tester(DefaultFormFactor::pins(), DefaultFormFactor::restricted_pins());

static volatile uint32_t call_counter;
void test_gpio_irq_handler(uint32_t id, gpio_irq_event event)
void test_gpio_irq_handler(uintptr_t context, gpio_irq_event event)
{
call_counter++;
}
Expand All @@ -63,8 +63,8 @@ void fpga_gpio_irq_test(PinName pin)
gpio_init_in(&gpio, pin);

gpio_irq_t gpio_irq;
uint32_t id = 123;
TEST_ASSERT_EQUAL(0, gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, id));
uintptr_t context = 123;
TEST_ASSERT_EQUAL(0, gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, context));

gpio_irq_set(&gpio_irq, IRQ_RISE, true);
gpio_irq_enable(&gpio_irq);
Expand Down
20 changes: 10 additions & 10 deletions targets/TARGET_ARM_FM/TARGET_FVP_MPS2/gpio_irq_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#define CMSDK_GPIO_1 CMSDK_GPIO1
#define PININT_IRQ 0

static uint32_t channel_ids[CHANNEL_NUM] = {0};
static uintptr_t channel_contexts[CHANNEL_NUM] = {0};
static gpio_irq_handler irq_handler;

static inline void handle_interrupt_in(uint32_t channel)
Expand All @@ -35,31 +35,31 @@ static inline void handle_interrupt_in(uint32_t channel)
// * There is no user handler
// * It is a level interrupt, not an edge interrupt
if (ch_bit < 16) {
if (((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_ids[channel] == 0) || ((CMSDK_GPIO_0->INTTYPESET) == 0)) {
if (((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_contexts[channel] == 0) || ((CMSDK_GPIO_0->INTTYPESET) == 0)) {
return;
}

if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
irq_handler(channel_contexts[channel], IRQ_RISE);
CMSDK_GPIO_0->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
irq_handler(channel_contexts[channel], IRQ_FALL);
}
CMSDK_GPIO_0->INTCLEAR = ch_bit;
}

if (ch_bit >= 16) {
if (((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_ids[channel] == 0) || ((CMSDK_GPIO_1->INTTYPESET) == 0)) {
if (((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_contexts[channel] == 0) || ((CMSDK_GPIO_1->INTTYPESET) == 0)) {
return;
}

if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
irq_handler(channel_contexts[channel], IRQ_RISE);
CMSDK_GPIO_1->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
irq_handler(channel_contexts[channel], IRQ_FALL);
}
CMSDK_GPIO_1->INTCLEAR = ch_bit;
}
Expand Down Expand Up @@ -195,7 +195,7 @@ void gpio1_irq15(void)
}


int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uintptr_t context)
{
if (pin == NC) {
return -1;
Expand All @@ -206,8 +206,8 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
int found_free_channel = 0;
int i = 0;
for (i = 0; i < CHANNEL_NUM; i++) {
if (channel_ids[i] == 0) {
channel_ids[i] = id;
if (channel_contexts[i] == 0) {
channel_contexts[i] = context;
obj->ch = i;
found_free_channel = 1;
break;
Expand Down
8 changes: 4 additions & 4 deletions targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_irq_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
struct gpio_irq_handler_t {
gpio_irq_handler handler;
gpio_irq_event event;
uint32_t id;
uintptr_t context;
};

/* Handlers registered */
Expand Down Expand Up @@ -69,7 +69,7 @@ static void handler(struct arm_gpio_dev_t* dev, uint32_t gpio_number,

exp_pin_number = exp_pin_base + pin_number;

gpio_irq[exp_pin_number].handler(gpio_irq[exp_pin_number].id,
gpio_irq[exp_pin_number].handler(gpio_irq[exp_pin_number].context,
gpio_irq[exp_pin_number].event);
}

Expand Down Expand Up @@ -102,7 +102,7 @@ void PORT3_ALL_IRQHandler(void)
#endif /* ARM_GPIO3 */

int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
uint32_t id)
uintptr_t context)
{
struct arm_gpio_dev_t *gpio_dev;

Expand Down Expand Up @@ -146,7 +146,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,

/* Save the handler and id into the global structure */
gpio_irq[pin].handler = handler;
gpio_irq[pin].id = id;
gpio_irq[pin].context = context;

return 0;
} else {
Expand Down
20 changes: 10 additions & 10 deletions targets/TARGET_ARM_SSG/TARGET_MPS2/gpio_irq_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#define CMSDK_GPIO_1 CMSDK_GPIO1
#define PININT_IRQ 0

static uint32_t channel_ids[CHANNEL_NUM] = {0};
static uintptr_t channel_contexts[CHANNEL_NUM] = {0};
static gpio_irq_handler irq_handler;

static inline void handle_interrupt_in(uint32_t channel) {
Expand All @@ -34,27 +34,27 @@ static inline void handle_interrupt_in(uint32_t channel) {
// * There is no user handler
// * It is a level interrupt, not an edge interrupt
if (ch_bit <16){
if ( ((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_ids[channel] == 0) || ((CMSDK_GPIO_0->INTTYPESET) == 0) ) return;
if ( ((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_contexts[channel] == 0) || ((CMSDK_GPIO_0->INTTYPESET) == 0) ) return;

if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
irq_handler(channel_contexts[channel], IRQ_RISE);
CMSDK_GPIO_0->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
irq_handler(channel_contexts[channel], IRQ_FALL);
}
CMSDK_GPIO_0->INTCLEAR = ch_bit;
}

if (ch_bit>=16) {
if ( ((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_ids[channel] == 0) || ((CMSDK_GPIO_1->INTTYPESET) == 0) ) return;
if ( ((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_contexts[channel] == 0) || ((CMSDK_GPIO_1->INTTYPESET) == 0) ) return;

if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
irq_handler(channel_contexts[channel], IRQ_RISE);
CMSDK_GPIO_1->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
irq_handler(channel_contexts[channel], IRQ_FALL);
}
CMSDK_GPIO_1->INTCLEAR = ch_bit;
}
Expand Down Expand Up @@ -94,7 +94,7 @@ void gpio1_irq14(void) {handle_interrupt_in(30);}
void gpio1_irq15(void) {handle_interrupt_in(31);}


int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uintptr_t context) {
if (pin == NC) {return -1;}
else {

Expand All @@ -103,8 +103,8 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
int found_free_channel = 0;
int i = 0;
for (i=0; i<CHANNEL_NUM; i++) {
if (channel_ids[i] == 0) {
channel_ids[i] = id;
if (channel_contexts[i] == 0) {
channel_contexts[i] = context;
obj->ch = i;
found_free_channel = 1;
break;
Expand Down
2 changes: 1 addition & 1 deletion targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/gpio_irq_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "mbed_error.h"

int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
uint32_t id)
uintptr_t context)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
Expand Down
2 changes: 1 addition & 1 deletion targets/TARGET_ARM_SSG/TARGET_MUSCA_S1/gpio_irq_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "mbed_error.h"

int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
uint32_t id)
uintptr_t context)
{
/* Due to a HW limitation, GPIO in Musca-S1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntD
*/
typedef struct gpio_irq_s gpio_irq_t;

typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event);
typedef void (*gpio_irq_handler)(uintptr_t context, gpio_irq_event event);
extern void am_gpio_isr(void);
static ap3_gpio_irq_control_t gpio_irq_control[AP3_GPIO_MAX_PADS];

Expand All @@ -62,18 +62,18 @@ static ap3_gpio_irq_control_t gpio_irq_control[AP3_GPIO_MAX_PADS];
* @param obj The GPIO object to initialize
* @param pin The GPIO pin name
* @param handler The handler to be attached to GPIO IRQ
* @param id The object ID (id != 0, 0 is reserved)
* @param context The context to be passed back to the handler (context != 0, 0 is reserved)
* @return -1 if pin is NC, 0 otherwise
*/
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uintptr_t context)
{
//grab the correct irq control object
ap3_gpio_irq_control_t *control = &gpio_irq_control[pin];

//Register locally
control->pad = pin;
control->handler = handler;
control->id = id;
control->id = context;
control->events = IRQ_NONE;

//Attach to object
Expand Down
Loading

0 comments on commit f4e5359

Please sign in to comment.