Skip to content

Commit 88baee7

Browse files
author
David Hunt
committed
ATLEDGE-84 - Interrupt framework
Arduino functions implemented: * attachInterrupt(Arduino_Pin, handler, mode): * it works for all Arduino GPIO (IO0 - IO19) * CHANGE mode is supported only for SoC GPIOs (hardware limitation: SS doesn't support interrupt generation on both rising and falling edges.) * detachInterrupt() * interrupts() * noInterrupts() Above functions behaviour is according to Arduino website description. For details please see below references: http://www.arduino.cc/en/Reference/AttachInterrupt http://www.arduino.cc/en/Reference/DetachInterrupt http://www.arduino.cc/en/Reference/Interrupts http://www.arduino.cc/en/Reference/NoInterrupts This implementation uses ss_gpio and soc_gpio drivers from thunderdome. Signed-off-by: Bogdan Pricop <bogdan.pricop@emutex.com>
2 parents ac134d6 + 79d1ab1 commit 88baee7

File tree

13 files changed

+251
-134
lines changed

13 files changed

+251
-134
lines changed

cores/arduino/WInterrupts.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
Copyright (c) 2015 Intel Corporation. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+
18+
*/
19+
20+
#include "WInterrupts.h"
21+
#include "wiring_digital.h"
22+
#include "gpio.h"
23+
#include "interrupt.h"
24+
25+
/* Saves the interrupt state from STATUS32 register before disabling the
26+
* interrupts */
27+
static uint32_t irq_flags;
28+
/* Works kinda like a semaphore: make sure one has called noInterrupts() before
29+
* interrupts() */
30+
static uint32_t noInterrupts_executed;
31+
32+
void attachInterrupt(uint32_t pin, void(*callback)(void), uint32_t mode)
33+
{
34+
if (pin >= NUM_DIGITAL_PINS) {
35+
#ifdef DEBUG
36+
__asm__("flag 0x01") ; /* Halt the CPU */
37+
#endif
38+
return;
39+
}
40+
PinDescription *p = &g_APinDescription[pin];
41+
gpio_cfg_data_t config;
42+
DRIVER_API_RC ret;
43+
44+
/* First de-config the GPIO in case it was previously configured as IRQ */
45+
if (p->ulGPIOType == SS_GPIO)
46+
ret = ss_gpio_deconfig(p->ulGPIOPort, p->ulGPIOId);
47+
else
48+
ret = soc_gpio_deconfig(p->ulGPIOPort, p->ulGPIOId);
49+
#ifdef DEBUG
50+
if (ret != DRV_RC_OK)
51+
__asm__("flag 0x01") ; /* Halt the CPU */
52+
#endif
53+
54+
switch (mode) {
55+
case LOW:
56+
config.int_type = LEVEL;
57+
config.int_polarity = ACTIVE_LOW;
58+
break;
59+
case HIGH:
60+
config.int_type = LEVEL;
61+
config.int_polarity = ACTIVE_HIGH;
62+
break;
63+
case RISING:
64+
config.int_type = EDGE;
65+
config.int_polarity = ACTIVE_HIGH;
66+
break;
67+
case FALLING:
68+
config.int_type = EDGE;
69+
config.int_polarity = ACTIVE_LOW;
70+
break;
71+
case CHANGE:
72+
if (p->ulGPIOType == SOC_GPIO) {
73+
config.int_type = DOUBLE_EDGE;
74+
config.int_polarity = ACTIVE_LOW;
75+
} else { /* ARC GPIOs don't support both edges IRQ */
76+
config.int_type = EDGE;
77+
config.int_polarity = ACTIVE_LOW;
78+
}
79+
break;
80+
default:
81+
#ifdef DEBUG
82+
__asm__("flag 0x01"); /* Halt the CPU */
83+
#endif
84+
return;
85+
}
86+
config.gpio_type = GPIO_INTERRUPT;
87+
config.int_debounce = DEBOUNCE_ON;
88+
config.int_ls_sync = LS_SYNC_OFF;
89+
config.gpio_cb = callback;
90+
91+
if (p->ulGPIOType == SS_GPIO)
92+
ret = ss_gpio_set_config(p->ulGPIOPort, p->ulGPIOId, &config);
93+
else
94+
ret = soc_gpio_set_config(p->ulGPIOPort, p->ulGPIOId, &config);
95+
#ifdef DEBUG
96+
if (ret != DRV_RC_OK)
97+
__asm__("flag 0x01") ; /* Halt the CPU */
98+
#endif
99+
}
100+
101+
102+
void detachInterrupt(uint32_t pin)
103+
{
104+
if (pin >= NUM_DIGITAL_PINS) {
105+
#ifdef DEBUG
106+
__asm__("flag 0x01") ; /* Halt the CPU */
107+
#endif
108+
return;
109+
}
110+
PinDescription *p = &g_APinDescription[pin];
111+
DRIVER_API_RC ret;
112+
113+
if (p->ulGPIOType == SS_GPIO)
114+
ret = ss_gpio_deconfig(p->ulGPIOPort, p->ulGPIOId);
115+
else
116+
ret = soc_gpio_deconfig(p->ulGPIOPort, p->ulGPIOId);
117+
#ifdef DEBUG
118+
if (ret != DRV_RC_OK)
119+
__asm__("flag 0x01") ; /* Halt the CPU */
120+
#endif
121+
}
122+
123+
124+
void interrupts(void)
125+
{
126+
if (noInterrupts_executed) {
127+
noInterrupts_executed = 0;
128+
interrupt_unlock(irq_flags);
129+
}
130+
}
131+
132+
void noInterrupts(void)
133+
{
134+
if (!noInterrupts_executed) {
135+
noInterrupts_executed = 1;
136+
irq_flags = interrupt_lock();
137+
}
138+
}

cores/arduino/WInterrupts.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
2929

3030
void detachInterrupt(uint32_t pin);
3131

32+
void interrupts(void);
33+
34+
void noInterrupts(void);
35+
3236
#ifdef __cplusplus
3337
}
3438
#endif

cores/arduino/wiring.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2525
#include "conf.h"
2626
#include "interrupt.h"
2727
#include "aux_regs.h"
28+
#include "board.h"
2829

2930
#define FREQ_MHZ ((ARCV2_TIMER0_CLOCK_FREQ)/1000000)
3031

@@ -37,8 +38,8 @@ void delay(uint32_t msec)
3738

3839
while(timer0_overflows < no_of_irqs){
3940
yield();
40-
/* Enter sleep and enable interrupts and sets interrupts threshold to 3 */
41-
__asm__ volatile ("sleep 0x13");
41+
/* Enable interrupts, sets interrupts threshold to 2 and go to sleep. */
42+
__asm__ volatile ("sleep %0" :: "i" (INTERRUPT_ENABLE | INTERRUPT_THRESHOLD));
4243
}
4344
/* For the last fraction of millisecond don't go to sleep - you'll wake up
4445
* too late - just spin */

cores/arduino/wiring_constants.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,6 @@ enum BitOrder {
7777
#define degrees(rad) ((rad)*RAD_TO_DEG)
7878
#define sq(x) ((x)*(x))
7979

80-
#define interrupts() __enable_irq()
81-
#define noInterrupts() __disable_irq()
82-
8380
#define lowByte(w) ((uint8_t) ((w) & 0xff))
8481
#define highByte(w) ((uint8_t) ((w) >> 8))
8582

system/libarc32_edu/bootcode/conf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2121
#define _ARCV2_CONF__H_
2222

2323

24-
#define _WRS_CONFIG_NUM_IRQS 64
24+
#define SS_NUM_IRQS 53
25+
#define SS_NUM_EXCEPTIONS 16
2526

2627
#define _RAM_END (0xa8010000 + 0x4000)
2728

system/libarc32_edu/bootcode/interrupt.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1919
#include "conf.h"
2020
#include "aux_regs.h"
2121
#include "interrupt.h"
22+
#include "board.h"
2223

23-
#define INTERRUPT_ENABLE (1 << 4)
24-
#define INTERRUPT_THRESHOLD (3)
2524

2625
struct _IsrTableEntry
2726
{
2827
void *arg;
2928
void (*isr)(void);
3029
};
3130

32-
struct _IsrTableEntry __attribute__((section(".data"))) _IsrTable[_WRS_CONFIG_NUM_IRQS];
31+
struct _IsrTableEntry __attribute__((section(".data"))) _IsrTable[SS_NUM_IRQS];
3332

3433
static void _dummy_isr(void)
3534
{
@@ -46,16 +45,16 @@ static void _dummy_isr(void)
4645
__attribute__ ((interrupt ("ilink")))
4746
void _do_isr(void)
4847
{
49-
unsigned int irq_cause = aux_reg_read(ARC_V2_ICAUSE) - 16;
48+
unsigned int irq_cause = aux_reg_read(ARC_V2_ICAUSE) - SS_NUM_EXCEPTIONS;
5049
if (_IsrTable[irq_cause].isr != 0x00)
5150
_IsrTable[irq_cause].isr();
52-
else
53-
_dummy_isr();
51+
else
52+
_dummy_isr();
5453
}
5554

5655
void interrupt_connect(unsigned int irq, void (*isr)(void), void *arg)
5756
{
58-
int index = irq - 16;
57+
int index = irq - SS_NUM_EXCEPTIONS;
5958
unsigned int flags = interrupt_lock();
6059
_IsrTable[index].isr = isr;
6160
_IsrTable[index].arg = arg;
@@ -64,15 +63,14 @@ void interrupt_connect(unsigned int irq, void (*isr)(void), void *arg)
6463

6564
void interrupt_disconnect(unsigned int irq)
6665
{
67-
int index = irq - 16;
66+
int index = irq - SS_NUM_EXCEPTIONS;
6867
_IsrTable[index].isr = _dummy_isr;
6968
}
7069

7170
void interrupt_enable(unsigned int irq)
7271
{
7372
unsigned int flags = interrupt_lock();
7473
aux_reg_write (ARC_V2_IRQ_SELECT, irq);
75-
aux_reg_write (ARC_V2_IRQ_PRIORITY, 1);
7674
aux_reg_write (ARC_V2_IRQ_TRIGGER, ARC_V2_INT_LEVEL);
7775
aux_reg_write (ARC_V2_IRQ_ENABLE, ARC_V2_INT_ENABLE);
7876
interrupt_unlock(flags);
@@ -97,17 +95,17 @@ void interrupt_priority_set (int irq, unsigned char priority)
9795
void interrupt_unit_device_init(void)
9896
{
9997
int irq_index;
100-
for (irq_index = 16; irq_index < 256; irq_index++)
98+
int min_irq_no = VECTOR_FROM_IRQ(0);
99+
int max_irq_no = VECTOR_FROM_IRQ(SS_NUM_IRQS);
100+
for (irq_index = min_irq_no; irq_index < max_irq_no; irq_index++)
101101
{
102102
aux_reg_write(ARC_V2_IRQ_SELECT, irq_index);
103103
aux_reg_write(ARC_V2_IRQ_PRIORITY, 1);
104104
aux_reg_write(ARC_V2_IRQ_ENABLE, ARC_V2_INT_DISABLE);
105105
aux_reg_write(ARC_V2_IRQ_TRIGGER, ARC_V2_INT_LEVEL);
106106
}
107-
108107
/* Setup automatic (hardware) context saving feature */
109-
aux_reg_write(ARC_V2_AUX_IRQ_CTRL,AUX_IRQ_CTRL_SAVE_ALL);
110-
108+
aux_reg_write(ARC_V2_AUX_IRQ_CTRL, AUX_IRQ_CTRL_SAVE_ALL);
111109
/* Configure the interrupt priority threshold and enable interrupts */
112110
__builtin_arc_seti(INTERRUPT_ENABLE | INTERRUPT_THRESHOLD);
113111
}

system/libarc32_edu/bootcode/interrupt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1919
#ifndef __INTERRUPT_H__
2020
#define __INTERRUPT_H__
2121

22+
#define INTERRUPT_ENABLE (1 << 4)
23+
/* According to IRQ_BUILD register the ARC core has only 2 interrupt priority
24+
* levels (0 and 1).
25+
* */
26+
#define INTERRUPT_THRESHOLD (2)
27+
28+
2229
extern void interrupt_connect(unsigned int irq, void (*isr)(void), void *arg);
2330
extern void interrupt_disconnect(unsigned int irq);
2431
extern void interrupt_enable(unsigned int irq);

system/libarc32_edu/common/board.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ This header file is used to specify and describe board-level aspects for the
4040
#define _BOARD__H_
4141

4242
#include <misc/util.h>
43+
#include <stdint.h>
4344

4445
/* default system clock */
4546

system/libarc32_edu/drivers/gpio.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
#include "data_type.h"
2929

30-
typedef void (*gpio_callback_fn)( uint32_t , void*);
30+
typedef void (*gpio_callback_fn)(void);
3131

3232
/*!
3333
* GPIO types
@@ -81,7 +81,6 @@ typedef struct gpio_cfg_data {
8181
INT_DEBOUNCE int_debounce; /*!< GPIO debounce configuration */
8282
INT_LS_SYNC int_ls_sync; /*!< GPIO ls sync configuration */
8383
gpio_callback_fn gpio_cb; /*!< Callback function called when an interrupt is triggered on this pin */
84-
void *gpio_cb_arg; /*!< Data passed as an argument for the callback function */
8584
} gpio_cfg_data_t;
8685

8786
/*!
@@ -96,7 +95,6 @@ typedef struct gpio_port_cfg_data {
9695
uint32_t int_debounce; /*!< GPIO debounce configuration (0=OFF, 1=ON) */
9796
uint32_t int_ls_sync; /*!< GPIO ls sync configuration (0=OFF, 1=ON) */
9897
gpio_callback_fn gpio_cb[32]; /*!< Callback function called when an interrupt is triggered on this pin */
99-
void *gpio_cb_arg[32]; /*!< Data passed as an argument for the callback function */
10098
} gpio_port_cfg_data_t;
10199

102100
#endif /* GPIO_IFACE_H_ */

0 commit comments

Comments
 (0)