source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/WInterrupts.c@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 5.3 KB
Line 
1/*
2 Copyright (c) 2014 Arduino. 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.
12 See the GNU 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 St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "WInterrupts.h"
20#include "variant.h"
21#include "wiring_digital.h"
22
23#include <string.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29static struct
30{
31 uint32_t _ulPin ;
32 voidFuncPtr _callback ;
33} callbacksInt[EXTERNAL_NUM_INTERRUPTS] ;
34
35/* Configure I/O interrupt sources */
36static void __initialize()
37{
38#if 0
39 int i ;
40
41 for ( i = 0 ; i < EXTERNAL_NUM_INTERRUPTS ; i++ )
42 {
43 callbacksInt[i]._callback = NULL ;
44 }
45#else
46 memset( callbacksInt, 0, sizeof( callbacksInt ) ) ;
47#endif
48
49 NVIC_DisableIRQ( EIC_IRQn ) ;
50 NVIC_ClearPendingIRQ( EIC_IRQn ) ;
51 NVIC_SetPriority( EIC_IRQn, 0 ) ;
52 NVIC_EnableIRQ( EIC_IRQn ) ;
53
54
55
56 // Enable GCLK for IEC (External Interrupt Controller)
57 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_EIC )) ;
58
59 // Enable EIC
60 EIC->CTRL.bit.ENABLE = 1 ;
61
62 while ( EIC->STATUS.bit.SYNCBUSY == 1 )
63 {
64 // Waiting for synchronisation
65 }
66
67}
68
69/*
70 * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.
71 * Replaces any previous function that was attached to the interrupt.
72 */
73
74void attachInterrupt( uint32_t ulPin, voidFuncPtr callback, uint32_t ulMode )
75{
76 static int enabled = 0 ;
77 uint32_t ulConfig ;
78 uint32_t ulPos ;
79
80 if ( digitalPinToInterrupt( ulPin ) == NOT_AN_INTERRUPT )
81 {
82 return ;
83 }
84
85 if ( !enabled )
86 {
87 __initialize() ;
88 enabled = 1 ;
89 }
90
91 // Assign pin to EIC
92 pinPeripheral( ulPin, PIO_EXTINT ) ;
93
94 // Assign callback to interrupt
95 callbacksInt[digitalPinToInterrupt( ulPin )]._ulPin = ulPin ;
96 callbacksInt[digitalPinToInterrupt( ulPin )]._callback = callback ;
97
98 // Check if normal interrupt or NMI
99 if ( ulPin != 2 )
100 {
101 // Look for right CONFIG register to be addressed
102 if ( digitalPinToInterrupt( ulPin ) > EXTERNAL_INT_7 )
103 {
104 ulConfig = 1 ;
105 }
106 else
107 {
108 ulConfig = 0 ;
109 }
110
111 // Configure the interrupt mode
112 ulPos = ((digitalPinToInterrupt( ulPin ) - (8*ulConfig) ) << 2) ;
113 switch ( ulMode )
114 {
115 case LOW:
116 EIC->CONFIG[ulConfig].reg |= EIC_CONFIG_SENSE0_LOW_Val << ulPos ;
117 break ;
118
119 case HIGH:
120 EIC->CONFIG[ulConfig].reg |= EIC_CONFIG_SENSE0_HIGH_Val << ulPos ;
121 break ;
122
123 case CHANGE:
124 EIC->CONFIG[ulConfig].reg |= EIC_CONFIG_SENSE0_BOTH_Val << ulPos ;
125 break ;
126
127 case FALLING:
128 EIC->CONFIG[ulConfig].reg |= EIC_CONFIG_SENSE0_FALL_Val << ulPos ;
129 break ;
130
131 case RISING:
132 EIC->CONFIG[ulConfig].reg |= EIC_CONFIG_SENSE0_RISE_Val << ulPos ;
133 break ;
134 }
135
136 // Enable the interrupt
137 EIC->INTENSET.reg = EIC_INTENSET_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
138 }
139 else // Handles NMI on pin 2
140 {
141 // Configure the interrupt mode
142 switch ( ulMode )
143 {
144 case LOW:
145 EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_LOW ;
146 break ;
147
148 case HIGH:
149 EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_HIGH ;
150 break ;
151
152 case CHANGE:
153 EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_BOTH ;
154 break ;
155
156 case FALLING:
157 EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_FALL ;
158 break ;
159
160 case RISING:
161 EIC->NMICTRL.reg= EIC_NMICTRL_NMISENSE_RISE ;
162 break ;
163 }
164
165 // Enable the interrupt
166 EIC->INTENSET.reg = EIC_INTENSET_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
167 }
168}
169
170/*
171 * \brief Turns off the given interrupt.
172 */
173void detachInterrupt( uint32_t ulPin )
174{
175/*
176 // Retrieve pin information
177 Pio *pio = g_APinDescription[pin].pPort;
178 uint32_t mask = g_APinDescription[pin].ulPin;
179
180 // Disable interrupt
181 pio->PIO_IDR = mask;
182*/
183 if ( digitalPinToInterrupt( ulPin ) == NOT_AN_INTERRUPT )
184 {
185 return ;
186 }
187
188 EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ;
189}
190
191/*
192 * External Interrupt Controller NVIC Interrupt Handler
193 */
194void EIC_Handler( void )
195{
196 uint32_t ul ;
197
198 // Test NMI first
199 if ( (EIC->NMIFLAG.reg & EIC_NMIFLAG_NMI) == EIC_NMIFLAG_NMI )
200 {
201 // Call the callback function if assigned
202 if ( callbacksInt[EXTERNAL_INT_NMI]._callback != NULL )
203 {
204 callbacksInt[EXTERNAL_INT_NMI]._callback() ;
205 }
206
207 // Clear the interrupt
208 EIC->NMIFLAG.reg = EIC_NMIFLAG_NMI ;
209 }
210
211 // Test the 16 normal interrupts
212 for ( ul = EXTERNAL_INT_0 ; ul < EXTERNAL_INT_NMI ; ul++ )
213 {
214 if ( (EIC->INTFLAG.reg & ( 1 << ul ) ) != 0 )
215 {
216 // Call the callback function if assigned
217 if ( callbacksInt[ul]._callback != NULL )
218 {
219 callbacksInt[ul]._callback() ;
220 }
221
222 // Clear the interrupt
223 EIC->INTFLAG.reg = 1 << ul ;
224 }
225 }
226}
227
228#ifdef __cplusplus
229}
230#endif
Note: See TracBrowser for help on using the repository browser.