source: rtems/c/src/lib/libbsp/shared/src/irq-server.c @ 8634637

4.104.115
Last change on this file since 8634637 was 8634637, checked in by Joel Sherrill <joel.sherrill@…>, on 09/08/09 at 13:35:07

2009-09-08 Sebastian Huber <sebastian.huber@…>

  • include/irq-config.h, include/irq-generic.h, include/irq-info.h, src/irq-generic.c, src/irq-info.c, src/irq-legacy.c, src/irq-shell.c: Format, cleanup and documentation.
  • src/irq-server.c: New file.
  • include/bootcard.h, include/stackalloc.h, src/stackalloc.c, bsplibc.c: Update for heap API changes. Documentation.
  • Property mode set to 100644
File size: 5.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup bsp_interrupt
5 *
6 * @brief Generic BSP interrupt server implementation.
7 */
8
9/*
10 * Copyright (c) 2009
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.com/license/LICENSE.
20 */
21
22#include <stdlib.h>
23
24#include <bsp/irq-generic.h>
25
26typedef struct bsp_interrupt_server_entry {
27  rtems_vector_number vector;
28  rtems_interrupt_handler handler;
29  void *arg;
30  struct bsp_interrupt_server_entry *volatile next;
31} bsp_interrupt_server_entry;
32
33static rtems_id bsp_interrupt_server_semaphore = RTEMS_ID_NONE;
34
35/* LIFO list head */
36static bsp_interrupt_server_entry *volatile
37bsp_interrupt_server_list_head = NULL;
38
39static rtems_status_code bsp_interrupt_server_is_initialized(void)
40{
41  if (bsp_interrupt_server_semaphore != RTEMS_ID_NONE) {
42    return RTEMS_SUCCESSFUL;
43  } else {
44    return RTEMS_INCORRECT_STATE;
45  }
46}
47
48static void bsp_interrupt_server_trigger(rtems_vector_number vector, void *arg)
49{
50  bsp_interrupt_server_entry *e = arg;
51  rtems_interrupt_level level;
52
53  bsp_interrupt_vector_disable(e->vector);
54
55  /* Add interrupt server entry to the list */
56  rtems_interrupt_disable(level);
57  e->next = bsp_interrupt_server_list_head;
58  bsp_interrupt_server_list_head = e;
59  rtems_interrupt_enable(level);
60
61  rtems_semaphore_release(bsp_interrupt_server_semaphore);
62}
63
64static void bsp_interrupt_server_task(rtems_task_argument arg)
65{
66  rtems_status_code sc = RTEMS_SUCCESSFUL;
67  rtems_id sema = bsp_interrupt_server_semaphore;
68  rtems_interrupt_level level;
69  bsp_interrupt_server_entry *e = NULL;
70
71  while (true) {
72    sc = rtems_semaphore_obtain(sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
73    if (sc != RTEMS_SUCCESSFUL) {
74      break;
75    }
76
77    /* Fetch next interrupt server entry from the list */
78    rtems_interrupt_disable(level);
79    e = bsp_interrupt_server_list_head;
80    bsp_interrupt_server_list_head = e->next;
81    rtems_interrupt_enable(level);
82
83    (*e->handler)(e->vector, e->arg);
84
85    bsp_interrupt_vector_enable(e->vector);
86  }
87
88  rtems_task_delete(RTEMS_SELF);
89}
90
91typedef struct {
92  rtems_interrupt_handler handler;
93  void *arg;
94  bsp_interrupt_server_entry *entry;
95} bsp_interrupt_server_iterate_entry;
96
97static void bsp_interrupt_server_per_handler_routine(
98  void *iterate_arg,
99  const char *info,
100  rtems_option options,
101  rtems_interrupt_handler handler,
102  void *handler_arg
103)
104{
105  bsp_interrupt_server_iterate_entry *ie = iterate_arg;
106  bsp_interrupt_server_entry *e = handler_arg;
107
108  if (handler == bsp_interrupt_server_trigger) {
109    if (e->handler == ie->handler && e->arg == ie->arg) {
110      ie->entry = e;
111    }
112  }
113}
114
115rtems_status_code rtems_interrupt_server_handler_install(
116  rtems_id server,
117  rtems_vector_number vector,
118  const char *info,
119  rtems_option options,
120  rtems_interrupt_handler handler,
121  void *arg
122)
123{
124  rtems_status_code sc = RTEMS_SUCCESSFUL;
125  bsp_interrupt_server_entry *e = NULL;
126
127  sc = bsp_interrupt_server_is_initialized();
128  if (sc != RTEMS_SUCCESSFUL) {
129    return sc;
130  }
131
132  if (RTEMS_INTERRUPT_IS_SHARED(options)) {
133    return RTEMS_NOT_IMPLEMENTED;
134  }
135
136  e = malloc(sizeof(bsp_interrupt_server_entry));
137  if (e == NULL) {
138    return RTEMS_NO_MEMORY;
139  }
140
141  e->vector = vector;
142  e->handler = handler;
143  e->arg = arg;
144
145  sc = rtems_interrupt_handler_install(
146    vector,
147    info,
148    options,
149    bsp_interrupt_server_trigger,
150    e
151  );
152  if (sc != RTEMS_SUCCESSFUL) {
153    free(e);
154
155    return sc;
156  }
157
158  return RTEMS_SUCCESSFUL;
159}
160
161rtems_status_code rtems_interrupt_server_handler_remove(
162  rtems_id server,
163  rtems_vector_number vector,
164  rtems_interrupt_handler handler,
165  void *arg
166)
167{
168  rtems_status_code sc = RTEMS_SUCCESSFUL;
169  bsp_interrupt_server_iterate_entry ie = {
170    .handler = handler,
171    .arg = arg,
172    .entry = NULL
173  };
174
175  sc = bsp_interrupt_server_is_initialized();
176  if (sc != RTEMS_SUCCESSFUL) {
177    return sc;
178  }
179
180  /* Query corresponding interrupt server entry */
181  sc = rtems_interrupt_handler_iterate(
182    vector,
183    bsp_interrupt_server_per_handler_routine,
184    &ie
185  );
186  if (sc != RTEMS_SUCCESSFUL) {
187    return sc;
188  } else if (ie.entry == NULL) {
189    return RTEMS_INVALID_ID;
190  }
191
192  sc = rtems_interrupt_handler_remove(
193    vector,
194    ie.entry->handler,
195    ie.entry->arg
196  );
197  if (sc != RTEMS_SUCCESSFUL) {
198    return sc;
199  }
200
201  free(ie.entry);
202
203  return RTEMS_SUCCESSFUL;
204}
205
206rtems_status_code rtems_interrupt_server_initialize(
207  rtems_task_priority priority,
208  size_t stack_size,
209  rtems_mode modes,
210  rtems_attribute attributes,
211  rtems_id *server
212)
213{
214  rtems_status_code sc = RTEMS_SUCCESSFUL;
215  rtems_id sema_id = RTEMS_ID_NONE;
216  rtems_id task_id = RTEMS_ID_NONE;
217  rtems_interrupt_level level;
218
219  sc = rtems_semaphore_create(
220    rtems_build_name('I', 'R', 'Q', 'S'),
221    0,
222    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE,
223    0,
224    &sema_id
225  );
226  if (sc != RTEMS_SUCCESSFUL) {
227    return sc;
228  }
229
230  sc = rtems_task_create(
231    rtems_build_name('I', 'R', 'Q', 'S'),
232    priority,
233    stack_size,
234    modes,
235    attributes,
236    &task_id
237  );
238  if (sc != RTEMS_SUCCESSFUL) {
239    rtems_semaphore_delete(sema_id);
240
241    return sc;
242  }
243
244  /* Initialize global data (this must be done before the task starts) */
245  rtems_interrupt_disable(level);
246  if (bsp_interrupt_server_semaphore == RTEMS_ID_NONE) {
247    bsp_interrupt_server_semaphore = sema_id;
248    sc = RTEMS_SUCCESSFUL;
249  } else {
250    sc = RTEMS_INCORRECT_STATE;
251  }
252  rtems_interrupt_enable(level);
253  if (sc != RTEMS_SUCCESSFUL) {
254    rtems_semaphore_delete(sema_id);
255    rtems_task_delete(task_id);
256
257    return sc;
258  }
259
260  sc = rtems_task_start(
261    task_id,
262    bsp_interrupt_server_task,
263    0
264  );
265  if (sc != RTEMS_SUCCESSFUL) {
266    /* In this case we could also panic */
267    bsp_interrupt_server_semaphore = RTEMS_ID_NONE;
268    rtems_semaphore_delete(sema_id);
269    rtems_task_delete(task_id);
270
271    return sc;
272  }
273
274  return RTEMS_SUCCESSFUL;
275}
Note: See TracBrowser for help on using the repository browser.