1 /**
2 * \file
3 *
4 * \brief SAM GPIO Driver for SAMB11
5 *
6 * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #include <gpio.h>
47
48 /**
49 * \internal
50 * Internal driver device instance struct.
51 */
52 struct gpio_module _gpio_instances[3];
53 static void (*aon_handle_ext_wakeup_isr)(void) = (void (*)(void))0x1bc51;
54
55 /**
56 * \brief Initializes a gpio pin/group configuration structure to defaults.
57 *
58 * Initializes a given gpio pin/group configuration structure to a set of
59 * known default values. This function should be called on all new
60 * instances of these configuration structures before being modified by the
61 * user application.
62 *
63 * The default configuration is as follows:
64 * \li Input mode with internal pullup enabled
65 *
66 * \param[out] config Configuration structure to initialize to default values.
67 */
gpio_get_config_defaults(struct gpio_config * const config)68 void gpio_get_config_defaults(struct gpio_config *const config)
69 {
70 /* Default configuration values */
71 config->direction = GPIO_PIN_DIR_INPUT;
72 config->input_pull = GPIO_PIN_PULL_UP;
73 config->powersave = false;
74 config->aon_wakeup = false;
75 }
76
77 /**
78 * \brief Writes a gpio pin configuration to the hardware module.
79 *
80 * Writes out a given configuration of a gpio pin configuration to the hardware
81 * module. If the configuration is NULL then it releases the gpio pin.
82 *
83 * \note If the pin direction is set as an output, the pull-up/pull-down input
84 * configuration setting is ignored. Also certain gpio pin is used by
85 * FW and not available for user application. Please \ref gpio_pin
86 * for list of gpio_pin available.
87 *
88 * \param[in] gpio_pin Index of the GPIO pin to configure.
89 * \param[in] config Configuration settings for the pin.
90 *
91 * \return Status of initialization.
92 * \retval STATUS_OK gpio configured correctly
93 * \retval STATUS_ERR_INVALID_ARG Invalid gpio number, Certain gpios
94 * are used by FW and not allowed to change.
95 * \retval STATUS_RESOURCE_NOT_AVAILABLE Requested gpio is already in use.
96 *
97 */
gpio_pin_set_config(const uint8_t gpio_pin,const struct gpio_config * config)98 enum status_code gpio_pin_set_config(const uint8_t gpio_pin,
99 const struct gpio_config *config)
100 {
101 enum status_code status = STATUS_OK;
102
103 /* Following GPIO's should never be modified by user.
104 * GPIO_0 & GPIO_1 are used for SWD.
105 */
106 if ((gpio_pin == PIN_LP_GPIO_0) || \
107 (gpio_pin == PIN_LP_GPIO_1))
108 {
109 status = STATUS_ERR_INVALID_ARG;
110 } else {
111 if (gpio_pin <= 7) {
112 LPMCU_MISC_REGS0->PINMUX_SEL_0.reg &= ~(7 << ((gpio_pin % 8) * 4));
113 } else if (gpio_pin <= 15) {
114 LPMCU_MISC_REGS0->PINMUX_SEL_1.reg &= ~(7 << ((gpio_pin % 8) * 4));
115 } else if (gpio_pin <= 23) {
116 LPMCU_MISC_REGS0->PINMUX_SEL_2.reg &= ~(7 << ((gpio_pin % 8) * 4));
117 } else if (44 <= gpio_pin && gpio_pin < 48) {
118 /* Set GPIO_MSx as digital mode */
119 AON_GP_REGS0->MS_GPIO_MODE.vec.ANALOG_ENABLE_ &= ~(1 << (gpio_pin - PIN_GPIO_MS4));
120 }
121
122 if ((gpio_pin == PIN_AO_GPIO_0) || (gpio_pin == PIN_AO_GPIO_1) ||
123 (gpio_pin == PIN_AO_GPIO_2)) {
124 /* Active Low, Always On Pull Enable Control */
125 if (config->input_pull == GPIO_PIN_PULL_UP) {
126 AON_GP_REGS0->AON_PULL_ENABLE.reg &= ~(1 << (31 - gpio_pin));
127 } else {
128 AON_GP_REGS0->AON_PULL_ENABLE.reg |= 1 << (31 - gpio_pin);
129 }
130 if (config->aon_wakeup) {
131 /* Enable AON_GPIO_x to be a wakeup MCU from sleep mode */
132 AON_GP_REGS0->AON_PINMUX_SEL.reg |= 1 << (4 * (31 - gpio_pin));
133 /* Enable AON_GPIO_x to wake up the BLE domain from sleep mode */
134 AON_PWR_SEQ0->GPIO_WAKEUP_CTRL.bit.BLE_ENABLE = 1;
135 }
136 } else {
137 if(config->direction == GPIO_PIN_DIR_INPUT) {
138 if(gpio_pin < 16) {
139 GPIO0->OUTENCLR.reg = (1 << gpio_pin);
140 } else if (gpio_pin < 32){
141 GPIO1->OUTENCLR.reg = (1 << (gpio_pin % 16));
142 } else {
143 GPIO2->OUTENCLR.reg = (1 << (gpio_pin % 16));
144 }
145 /* pull_enable. */
146 if (gpio_pin < 32) {
147 switch(config->input_pull) {
148 case GPIO_PIN_PULL_NONE:
149 LPMCU_MISC_REGS0->PULL_ENABLE.reg |= (1 << gpio_pin);
150 break;
151 case GPIO_PIN_PULL_UP:
152 LPMCU_MISC_REGS0->PULL_ENABLE.reg &= ~(1 << gpio_pin);
153 break;
154 case GPIO_PIN_PULL_DOWN:
155 /* Set R-Type */
156 LPMCU_MISC_REGS0->RTYPE_PAD_0.reg |= (1 << gpio_pin);
157 /* Set REN */
158 LPMCU_MISC_REGS0->PULL_ENABLE.reg &= ~(1 << gpio_pin);
159 break;
160 default:
161 status = STATUS_ERR_INVALID_ARG;
162 break;
163 }
164 }
165 } else if(config->direction == GPIO_PIN_DIR_OUTPUT) {
166 if (gpio_pin < 16) {
167 GPIO0->OUTENSET.reg = (1 << gpio_pin);
168 } else if (gpio_pin < 32) {
169 GPIO1->OUTENSET.reg = (1 << (gpio_pin % 16));
170 } else {
171 GPIO2->OUTENSET.reg = (1 << (gpio_pin % 16));
172 }
173 }
174 }
175 }
176 return status;
177 }
178
179 /**
180 * \brief Retrieves the state of a gpio pin that is configured as an input.
181 *
182 * Reads the current logic level of a gpio pin and returns the current
183 * level as a boolean value.
184 *
185 * \param[in] gpio_pin Index of the GPIO pin to read.
186 *
187 * \return Status of the gpio pin's input buffer.
188 */
gpio_pin_get_input_level(const uint8_t gpio_pin)189 bool gpio_pin_get_input_level(const uint8_t gpio_pin)
190 {
191 uint32_t regval = 0;
192
193 if (gpio_pin < 16) {
194 regval = GPIO0->DATA.reg;
195 regval &= (1 << gpio_pin);
196 } else if (gpio_pin < 32) {
197 regval = GPIO1->DATA.reg;
198 regval &= (1 << (gpio_pin % 16));
199 } else {
200 regval = GPIO2->DATA.reg;
201 regval &= (1 << (gpio_pin % 16));
202 }
203
204 return regval;
205 }
206
207 /**
208 * \brief Retrieves the state of a gpio pin that is configured as an output.
209 *
210 * Reads the current logical output level of a gpio pin and returns the current
211 * level as a boolean value.
212 *
213 * \param[in] gpio_pin Index of the GPIO pin to read.
214 *
215 * \return Status of the gpio pin's output buffer.
216 */
gpio_pin_get_output_level(const uint8_t gpio_pin)217 bool gpio_pin_get_output_level(const uint8_t gpio_pin)
218 {
219 uint32_t regval = 0;
220
221 if (gpio_pin < 16) {
222 regval = GPIO0->DATAOUT.reg;
223 regval &= (1 << gpio_pin);
224 } else if (gpio_pin < 32) {
225 regval = GPIO1->DATAOUT.reg;
226 regval &= (1 << (gpio_pin % 16));
227 } else {
228 regval = GPIO2->DATAOUT.reg;
229 regval &= (1 << (gpio_pin % 16));
230 }
231
232 return regval;
233 }
234
235 /**
236 * \brief Sets the state of a gpio pin that is configured as an output.
237 *
238 * Sets the current output level of a gpio pin to a given logic level.
239 *
240 * \param[in] gpio_pin Index of the GPIO pin to write to.
241 * \param[in] level Logical level to set the given pin to.
242 */
gpio_pin_set_output_level(const uint8_t gpio_pin,const bool level)243 void gpio_pin_set_output_level(const uint8_t gpio_pin, const bool level)
244 {
245 if (gpio_pin < 16) {
246 if(level) {
247 GPIO0->DATAOUT.reg |= (1 << gpio_pin);
248 } else {
249 GPIO0->DATAOUT.reg &= ~(1 << gpio_pin);
250 }
251 } else if (gpio_pin < 32) {
252 if(level) {
253 GPIO1->DATAOUT.reg |= (1 << (gpio_pin % 16));
254 } else {
255 GPIO1->DATAOUT.reg &= ~(1 << (gpio_pin % 16));
256 }
257 } else {
258 if(level) {
259 GPIO2->DATAOUT.reg |= (1 << (gpio_pin % 16));
260 } else {
261 GPIO2->DATAOUT.reg &= ~(1 << (gpio_pin % 16));
262 }
263 }
264 }
265
266 /**
267 * \brief Toggles the state of a gpio pin that is configured as an output.
268 *
269 * Toggles the current output level of a gpio pin.
270 *
271 * \param[in] gpio_pin Index of the GPIO pin to toggle.
272 */
gpio_pin_toggle_output_level(const uint8_t gpio_pin)273 void gpio_pin_toggle_output_level(const uint8_t gpio_pin)
274 {
275 if (gpio_pin < 16) {
276 GPIO0->DATAOUT.reg ^= (1 << gpio_pin);
277 } else if (gpio_pin < 32) {
278 GPIO1->DATAOUT.reg ^= (1 << (gpio_pin % 16));
279 } else {
280 GPIO2->DATAOUT.reg ^= (1 << (gpio_pin % 16));
281 }
282 }
283
284 /**
285 * \brief Writes a GPIO pin configuration to the hardware module.
286 *
287 * Writes out a given configuration of a GPIO pin configuration to the hardware
288 * module.
289 *
290 * \param[in] gpio_pin Index of the GPIO pin to toggle.
291 * \param[in] pinmux_sel PINMUX selection.
292 */
gpio_pinmux_cofiguration(const uint8_t gpio_pin,uint16_t pinmux_sel)293 void gpio_pinmux_cofiguration(const uint8_t gpio_pin, uint16_t pinmux_sel)
294 {
295 uint8_t megamux_sel = (pinmux_sel >> 8) & 0xFF;
296
297 pinmux_sel &= 0xFF;
298
299 if (gpio_pin <= 7) {
300 LPMCU_MISC_REGS0->PINMUX_SEL_0.reg &= ~(7 << ((gpio_pin % 8) * 4));
301 LPMCU_MISC_REGS0->PINMUX_SEL_0.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
302 if (pinmux_sel == 0x01) {
303 if (gpio_pin <= 3) {
304 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_0.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
305 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_0.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
306 } else if (gpio_pin <= 7) {
307 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_1.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
308 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_1.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
309 }
310 }
311 } else if (gpio_pin <= 15) {
312 LPMCU_MISC_REGS0->PINMUX_SEL_1.reg &= ~(7 << ((gpio_pin % 8) * 4));
313 LPMCU_MISC_REGS0->PINMUX_SEL_1.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
314 if (pinmux_sel == 0x01) {
315 if (gpio_pin <= 11) {
316 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_2.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
317 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_2.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
318 } else if (gpio_pin <= 15) {
319 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_3.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
320 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_3.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
321 }
322 }
323 } else if (gpio_pin <= 23) {
324 LPMCU_MISC_REGS0->PINMUX_SEL_2.reg &= ~(7 << ((gpio_pin % 8) * 4));
325 LPMCU_MISC_REGS0->PINMUX_SEL_2.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
326 if (pinmux_sel == 0x01) {
327 if (gpio_pin <= 19) {
328 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_4.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
329 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_4.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
330 } else if (gpio_pin <= 23) {
331 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_5.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
332 LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_5.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
333 }
334 }
335 }
336 }
337
338 /**
339 * \brief Registers a callback
340 *
341 * Registers a callback function which is implemented by the user.
342 *
343 * \note The callback must be enabled by \ref gpio_enable_callback,
344 * in order for the interrupt handler to call it when the conditions for
345 * the callback type are met.
346 *
347 * \param[in] gpio_pin GPIO pin number
348 * \param[in] callback_func Pointer to callback function
349 * \param[in] callback_type Callback type given by an enum
350 *
351 */
gpio_register_callback(uint8_t gpio_pin,gpio_callback_t callback_func,enum gpio_callback callback_type)352 void gpio_register_callback(uint8_t gpio_pin, gpio_callback_t callback_func,
353 enum gpio_callback callback_type)
354 {
355 /* Sanity check arguments */
356 Assert(callback_func);
357 Assert(gpio_pin < 48);
358
359 uint8_t gpio_port = 0;
360
361 if (gpio_pin < 16) {
362 gpio_port = 0;
363 } else if (gpio_pin < 32) {
364 gpio_port = 1;
365 } else {
366 gpio_port = 2;
367 }
368 switch (callback_type) {
369 case GPIO_CALLBACK_LOW:
370 _gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
371 _gpio_instances[gpio_port].hw->INTPOLCLR.reg = 1 << (gpio_pin % 16);
372 break;
373
374 case GPIO_CALLBACK_HIGH:
375 _gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
376 _gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
377 break;
378
379 case GPIO_CALLBACK_RISING:
380 _gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
381 _gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
382 break;
383
384 case GPIO_CALLBACK_FALLING:
385 _gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
386 _gpio_instances[gpio_port].hw->INTPOLCLR.reg = (1 << (gpio_pin % 16));
387 break;
388
389 case GPIO_CALLBACK_N:
390 break;
391 }
392 /* Register callback function */
393 _gpio_instances[gpio_port].callback[gpio_pin % 16] = callback_func;
394 /* Set the bit corresponding to the gpio pin */
395 _gpio_instances[gpio_port].callback_reg_mask |= (1 << (gpio_pin % 16));
396 }
397
398 /**
399 * \brief Unregisters a callback
400 *
401 * Unregisters a callback function which is implemented by the user.
402 *
403 *
404 * \param[in] gpio_pin GPIO pin number
405 * \param[in] callback_type Callback type given by an enum
406 *
407 */
gpio_unregister_callback(uint8_t gpio_pin,enum gpio_callback callback_type)408 void gpio_unregister_callback(uint8_t gpio_pin,
409 enum gpio_callback callback_type)
410 {
411 /* Sanity check arguments */
412 Assert(callback_func);
413 Assert(gpio_pin < 48);
414
415 uint8_t gpio_port = 0;
416
417 if (gpio_pin < 16) {
418 gpio_port = 0;
419 } else if (gpio_pin < 32) {
420 gpio_port = 1;
421 } else {
422 gpio_port = 2;
423 }
424
425 /* Unregister callback function */
426 _gpio_instances[gpio_port].callback[gpio_pin % 16] = NULL;
427 /* Set the bit corresponding to the gpio pin */
428 _gpio_instances[gpio_port].callback_reg_mask &= ~(1 << (gpio_pin % 16));
429 }
430
431 /**
432 * \brief Enables callback
433 *
434 * Enables the callback function registered by the \ref gpio_register_callback.
435 * The callback function will be called from the interrupt handler when the
436 * conditions for the callback type are met.
437 *
438 * \param[in] gpio_pin GPIO pin
439 */
gpio_enable_callback(uint8_t gpio_pin)440 void gpio_enable_callback(uint8_t gpio_pin)
441 {
442 Assert(gpio_pin < 48);
443
444 uint8_t gpio_port = 0;
445
446 if (gpio_pin < 16) {
447 gpio_port = 0;
448 NVIC_EnableIRQ(GPIO0_IRQn);
449 } else if (gpio_pin < 32) {
450 gpio_port = 1;
451 NVIC_EnableIRQ(GPIO1_IRQn);
452 } else {
453 gpio_port = 2;
454 NVIC_EnableIRQ(GPIO2_IRQn);
455 }
456
457 /* Enable callback */
458 _gpio_instances[gpio_port].callback_enable_mask |= (1 << (gpio_pin % 16));
459 _gpio_instances[gpio_port].hw->INTENSET.reg = (1 << (gpio_pin % 16));
460 }
461
462 /**
463 * \brief Disables callback
464 *
465 * Disables the callback function registered by the \ref usart_register_callback.
466 * The callback function will not be called from the interrupt handler.
467 *
468 * \param[in] gpio_pin GPIO pin
469 */
gpio_disable_callback(uint8_t gpio_pin)470 void gpio_disable_callback(uint8_t gpio_pin)
471 {
472 Assert(gpio_pin < 48);
473
474 uint8_t gpio_port = 0;
475
476 if (gpio_pin < 16) {
477 gpio_port = 0;
478 } else if (gpio_pin < 32) {
479 gpio_port = 1;
480 } else {
481 gpio_port = 2;
482 }
483
484 /* Enable callback */
485 _gpio_instances[gpio_port].callback_enable_mask &= ~(1 << (gpio_pin % 16));
486 _gpio_instances[gpio_port].hw->INTENCLR.reg = (1 << (gpio_pin % 16));
487 }
488
489 /**
490 * \internal GPIO port0 isr handler.
491 *
492 * This function will enter interrupt.
493 *
494 */
gpio_port0_isr_handler(void)495 static void gpio_port0_isr_handler(void)
496 {
497 uint32_t flag = _gpio_instances[0].hw->INTSTATUSCLEAR.reg;
498
499 for (uint8_t i = 0; i < 16; i++){
500 if (flag & (1 << i)) {
501 /* Clear interrupt flag */
502 _gpio_instances[0].hw->INTSTATUSCLEAR.reg = (1 << i);
503 if ((_gpio_instances[0].callback_enable_mask & (1 << i)) && \
504 (_gpio_instances[0].callback_reg_mask & (1 << i)))
505 _gpio_instances[0].callback[i]();
506 break;
507 }
508 }
509 NVIC_ClearPendingIRQ(GPIO0_IRQn);
510 }
511
512 /**
513 * \internal GPIO port1 isr handler.
514 *
515 * This function will enter interrupt.
516 *
517 */
gpio_port1_isr_handler(void)518 static void gpio_port1_isr_handler(void)
519 {
520 uint32_t flag = _gpio_instances[1].hw->INTSTATUSCLEAR.reg;
521
522 for (uint8_t i = 0; i < 16; i++){
523 /* For AON wakeup pin clear interrupt */
524 if (flag & ((1<<15) | (1<<14) | (1<<13))) {
525 aon_handle_ext_wakeup_isr();
526 }
527
528 if (flag & (1 << i)) {
529 /* Clear interrupt flag */
530 _gpio_instances[1].hw->INTSTATUSCLEAR.reg = (1 << i);
531 if ((_gpio_instances[1].callback_enable_mask & (1 << i)) && \
532 (_gpio_instances[1].callback_reg_mask & (1 << i))) {
533 _gpio_instances[1].callback[i]();
534 break;
535 }
536 }
537 }
538 NVIC_ClearPendingIRQ(GPIO1_IRQn);
539 }
540
541 /**
542 * \internal GPIO port2 isr handler.
543 *
544 * This function will enter interrupt.
545 *
546 */
gpio_port2_isr_handler(void)547 static void gpio_port2_isr_handler(void)
548 {
549 uint32_t flag = _gpio_instances[2].hw->INTSTATUSCLEAR.reg;
550
551 for (uint8_t i = 12; i < 16; i++){
552 if (flag & (1 << i)) {
553 /* Clear interrupt flag */
554 _gpio_instances[2].hw->INTSTATUSCLEAR.reg = (1 << i);
555 if ((_gpio_instances[2].callback_enable_mask & (1 << i)) && \
556 (_gpio_instances[2].callback_reg_mask & (1 << i)))
557 _gpio_instances[2].callback[i]();
558 break;
559 }
560 }
561 NVIC_ClearPendingIRQ(GPIO2_IRQn);
562 }
563
564 /**
565 * \internal GPIO callback init.
566 *
567 * This function will init GPIO callback.
568 *
569 */
gpio_init(void)570 void gpio_init(void)
571 {
572 uint8_t i, j;
573
574 for(i = 0; i < 3; i++) {
575 for(j = 0; j < 16; j++) {
576 _gpio_instances[i].callback[j] = NULL;
577 }
578 _gpio_instances[i].callback_enable_mask = 0;
579 _gpio_instances[i].callback_reg_mask = 0;
580 }
581 _gpio_instances[0].hw = (void *)GPIO0;
582 _gpio_instances[1].hw = (void *)GPIO1;
583 _gpio_instances[2].hw = (void *)GPIO2;
584 system_register_isr(RAM_ISR_TABLE_PORT0_COMB_INDEX, (uint32_t)gpio_port0_isr_handler);
585 system_register_isr(RAM_ISR_TABLE_PORT1_COMB_INDEX, (uint32_t)gpio_port1_isr_handler);
586 system_register_isr(RAM_ISR_TABLE_PORT2_COMB_INDEX, (uint32_t)gpio_port2_isr_handler);
587 }
588
589