libpynq  (release 5EID0-2023 version 0.3.0 of 2024-04-25 09:42 )
interrupt.c
Go to the documentation of this file.
1 /*
2 Copyright (c) 2023 Eindhoven University of Technology
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
21 */
23 #include <fcntl.h>
24 #include <gpio.h>
25 #include <log.h>
26 #include <platform.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <util.h>
33 
34 #define DOMAIN "Interrupt"
35 
36 extern uint32_t *gpio;
37 extern uint32_t *intc0;
38 
39 static bool gpio_initialized = false;
40 
42  if (gpio_initialized == false) {
43  pynq_error("Interrupts have not been initialized. Call "
44  "gpio_interupt_init() first.\n");
45  }
46 }
47 
49  int fd = open("/dev/uio1", O_RDWR, O_CLOEXEC);
50  if (fd < 0) {
51  pynq_error("failed to open interrupts\n");
52  }
53  int32_t m = 1;
54  write(fd, &m, 4);
55  gpio_initialized = true;
56  return fd;
57 }
58 
61  int pin_bank = pin % 32;
62  int bank = pin < 32 ? 0 : 1;
63  if (bank == 0) {
64  printf("interrupt set 0: %08X %08X\r\n", pin, pin_bank);
65  intc0[0] |= (1 << pin_bank);
66  } else {
67  printf("interrupt set 1: %08X %08X\r\n", pin, pin_bank);
68  intc0[1] |= (1 << (pin_bank));
69  }
70 }
71 
74  intc0[0] &= ~(1 << pin);
75 }
76 
79  intc0[0] = 0;
80  intc0[1] = 0;
81 }
82 
83 uint64_t gpio_get_interrupt(void) {
85  uint64_t retv = intc0[3];
86  retv <<= 32;
87  retv |= intc0[2];
88  return retv;
89 }
90 
91 void gpio_ack_interrupt(void) {
93  intc0[2] = 1;
94 }
95 
97  // TODO check if interrupts are initialized when using other interrupt
98  // functions
99  uint64_t retv = intc0[1];
100  retv <<= 32;
101  retv |= intc0[0];
102  if (pin < 64) {
103  uint64_t bitMask = 1ULL << pin;
104  if (!(bitMask & retv)) {
105  pynq_error("Pin %d is not enabled. Enable by using "
106  "gpio_enable_interrupt(pin). \n",
107  pin);
108  }
109  } else {
110  if (retv == 0) {
111  pynq_error("No interrupts enabled. Enable by using "
112  "gpio_enable_interrupt(pin). \n");
113  }
114  }
115 }
116 
119  // printf("11c: %08X\r\n", gpio[0x11c / 4]);
120  // printf("128: %08X\r\n", gpio[0x128 / 4]);
121  // printf("120: %08X\r\n", gpio[0x120 / 4]);
122  printf("interrupt 0: %08X %08X\r\n", intc0[0], intc0[2]);
123  printf("interrupt 1: %08X %08X\r\n", intc0[1], intc0[3]);
124 }
125 
126 void findSetBitPositions(uint64_t word, uint8_t *positions) {
127  int index = 0;
128  int count = 0;
129  while (word) {
130  if (word & 1) {
131  positions[count++] = index;
132  }
133  word >>= 1;
134  index++;
135  }
136 }
137 
141  if (pin > 63) {
142  while (1) {
143  uint64_t interrupt = gpio_get_interrupt();
144  if (interrupt != 0) {
145  break;
146  }
147  }
148  } else {
149  while (1) {
150  uint64_t interrupt = gpio_get_interrupt();
151  uint64_t bitMask = 1ULL << pin;
152  if (bitMask & interrupt) {
153  break;
154  }
155  sleep_msec(100);
156  }
157  }
158 }
159 
160 uint8_t *gpio_get_interrupt_pins(uint8_t *positions) {
162  verify_interrupt_request(64); // check if any interupt pin is enabled
163  // uint8_t *positions = (uint8_t *)malloc(64 * sizeof(uint8_t));
164  uint64_t pin = (uint64_t)((uint64_t)(intc0[3]) << 32 | intc0[2]);
165  findSetBitPositions(pin, positions);
166  // printf("Interrupted pin(s): ");
167  bool empty = true;
168  for (int i = 0; i < 64; i++) {
169  if (positions[i] != 0) {
170  empty = false;
171  // printf("%d ", positions[i]);
172  break;
173  }
174  }
175  if (empty) {
176  printf("WARNING: gpio_get_interrupt_pins: No pins interrupted. ");
177  }
178  printf("\n");
179  return (positions);
180 }
gpio_get_interrupt_pins
uint8_t * gpio_get_interrupt_pins(uint8_t *positions)
Gets all pins on which an interrupt occurred.
Definition: interrupt.c:10
check_initialization
void check_initialization(void)
Definition: interrupt.c:41
verify_interrupt_request
void verify_interrupt_request(const io_t pin)
Checks for error in enabled pin. Terminates the process if the pin is not enabled.
Definition: interrupt.c:4
pynq_error
#define pynq_error(...)
Definition: log.h:118
arm_shared_memory_system.h
intc0
uint32_t * intc0
Definition: gpio.c:33
sleep_msec
void sleep_msec(int msec)
Wait for msec milliseconds.
Definition: util.c:2
gpio_ack_interrupt
void gpio_ack_interrupt(void)
acknowledges the raised interrupts and resets the interrupt word. Allows new interrupts to occur on t...
Definition: interrupt.c:3
gpio_disable_all_interrupts
void gpio_disable_all_interrupts(void)
Disables all interrupts from being raised.
Definition: interrupt.c:8
gpio
uint32_t * gpio
Definition: gpio.c:32
gpio_wait_for_interrupt
void gpio_wait_for_interrupt(const io_t pin)
Waits untill an interrupt occurs on the specified pin or if the value of pin is larger than 63,...
Definition: interrupt.c:11
findSetBitPositions
void findSetBitPositions(uint64_t word, uint8_t *positions)
Definition: interrupt.c:126
gpio_print_interrupt
void gpio_print_interrupt(void)
prints the current interrupt word
Definition: interrupt.c:5
pin
Definition: switchbox.c:99
gpio_enable_interrupt
void gpio_enable_interrupt(const io_t pin)
enables a specific pin to raise interrupts.
Definition: interrupt.c:6
gpio_interrupt_init
int gpio_interrupt_init(void)
Enables interrupts to be set and read.
Definition: interrupt.c:2
log.h
gpio.h
gpio_get_interrupt
uint64_t gpio_get_interrupt(void)
Definition: interrupt.c:9
io_t
io_t
Definition: pinmap.h:45
util.h
gpio_disable_interrupt
void gpio_disable_interrupt(const io_t pin)
Disables interrupts from occuring on the specific pin. Hereafter, the pin will not trigger an interru...
Definition: interrupt.c:7