source: soft/giet_vm/giet_drivers/xcu_driver.c @ 275

Last change on this file since 275 was 275, checked in by cfuguet, 10 years ago
  • Adding volatile attribute for pointers used to address memory mapped hardware registers.
  • Removing the activation of interruptions before the execution of the ctx_switch function on the ioc_access function. This is to avoid been interrupted during the modification of task context variables.
File size: 11.3 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : xcu_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.
8// This driver supports the SoCLib vci_xicu, that is a vectorised interrupt
9// controler supporting IPI (Inter Processor Interrupts) and integrated timers.
10//
11// It can exist several interrupt controller unit in the architecture
12// (one per cluster), and each one can contain several channels.
13// The number of XICU channels is equal to NB_PROCS_MAX, because there is
14// one private XICU channel per processor in a cluster.
15////////////////////////////////////////////////////////////////////////////////
16// The virtual base address of the segment associated to the component is:
17//
18//      seg_xcu_base + cluster_xy * vseg_cluster_increment
19//
20// The seg_xcu_base and vseg_cluster_increment values must be defined
21// in giet_vsegs.ld file.
22////////////////////////////////////////////////////////////////////////////////
23
24#include <giet_config.h>
25#include <xcu_driver.h>
26#include <tty_driver.h>
27#include <mapping_info.h>
28#include <utils.h>
29
30#if !defined(X_SIZE)
31# error: You must define X_SIZE in the hard_config.h file
32#endif
33
34#if !defined(Y_SIZE)
35# error: You must define X_SIZE in the hard_config.h file
36#endif
37
38#if !defined(X_WIDTH)
39# error: You must define X_WIDTH in the hard_config.h file
40#endif
41
42#if !defined(Y_WIDTH)
43# error: You must define X_WIDTH in the hard_config.h file
44#endif
45
46#if !defined(NB_PROCS_MAX)
47# error: You must define NB_PROCS_MAX in the hard_config.h file
48#endif
49
50#if !defined( USE_XICU )
51# error: You must define USE_XICU in the hard_config.h file
52#endif
53
54////////////////////////////////////////////////////////////////////////////////
55//     _xcu_set_mask()
56// This function set the mask register for the XICU channel identified
57// by the cluster index and the processor index.
58// All '1' bits are set / all '0' bits are not modified.
59// Returns 0 if success, > 0 if error.
60////////////////////////////////////////////////////////////////////////////////
61unsigned int _xcu_set_mask( unsigned int cluster_xy, 
62                            unsigned int proc_id,
63                            unsigned int value,
64                            unsigned int irq_type ) 
65{
66    // parameters checking
67    unsigned int x = cluster_xy >> Y_WIDTH;
68    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
69    if (x >= X_SIZE)             return 1; 
70    if (y >= Y_SIZE)             return 1; 
71    if (proc_id >= NB_PROCS_MAX) return 1; 
72
73#if USE_XICU
74    volatile unsigned int* xcu_address =
75        (unsigned int *) ((unsigned int)&seg_xcu_base + 
76        (cluster_xy * (unsigned int)&vseg_cluster_increment));
77
78    unsigned int func;
79    if      (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE;
80    else if (irq_type == IRQ_TYPE_SWI) func = XICU_MSK_WTI_ENABLE;
81    else                               func = XICU_MSK_HWI_ENABLE;
82    xcu_address[XICU_REG(func,proc_id)] = value;
83    return 0;
84#else
85    _tty_get_lock( 0 );
86    _puts("[GIET ERROR] _xcu_set_mask should not be used if USE_XICU is not set\n");
87    _tty_release_lock( 0 );
88    return 1;
89#endif
90}
91
92////////////////////////////////////////////////////////////////////////////////
93//     _xcu_get_index()
94// This function returns the index of the highest priority (smaller index)
95// - active HWI (Hardware Interrupt), or
96// - active PTI (Timer Interrupt), or
97// - active SWI (Software Interrupt).
98// The ICU channel is identified by the cluster index and the processor index.
99// Returns 0 if success, > 0 if error.
100////////////////////////////////////////////////////////////////////////////////
101unsigned int _xcu_get_index( unsigned int cluster_xy, 
102                             unsigned int proc_id, 
103                             unsigned int * buffer) 
104{
105    // parameters checking
106    unsigned int x = cluster_xy >> Y_WIDTH;
107    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
108    if (x >= X_SIZE)             return 1; 
109    if (y >= Y_SIZE)             return 1; 
110    if (proc_id >= NB_PROCS_MAX) return 1; 
111
112#if USE_XICU
113    volatile unsigned int* xcu_address =
114        (unsigned int *) ((unsigned int)&seg_xcu_base + 
115        (cluster_xy * (unsigned int)&vseg_cluster_increment));
116
117    unsigned int prio = xcu_address[XICU_REG(XICU_PRIO, proc_id)];
118    unsigned int pti_ok = (prio & 0x00000001);
119    unsigned int hwi_ok = (prio & 0x00000002);
120    unsigned int swi_ok = (prio & 0x00000004);
121    unsigned int pti_id = (prio & 0x00001F00) >> 8;
122    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
123    unsigned int swi_id = (prio & 0x1F000000) >> 24;
124    if      (pti_ok)  *buffer = pti_id;
125    else if (hwi_ok)  *buffer = hwi_id;
126    else if (swi_ok)  *buffer = swi_id; 
127    else              *buffer = 32; 
128    return 0;
129#else
130    _tty_get_lock( 0 );
131    _puts("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n");
132    _tty_release_lock( 0 );
133    return 1;
134#endif
135}
136
137////////////////////////////////////////////////////////////////////////////////
138//     _xcu_send_ipi()
139// This function can be used only in an architecture using  XICU components.
140// It writes the "wdata" value in the mailbox defined by the cluster index
141// and the processor index.
142// Returns 0 if success, > 0 if error.
143////////////////////////////////////////////////////////////////////////////////
144unsigned int _xcu_send_ipi( unsigned int cluster_xy,
145                            unsigned int proc_id,
146                            unsigned int wdata )
147{ 
148    // parameters checking
149    unsigned int x = cluster_xy >> Y_WIDTH;
150    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
151    if (x >= X_SIZE)             return 1; 
152    if (y >= Y_SIZE)             return 1; 
153    if (proc_id >= NB_PROCS_MAX) return 1; 
154
155#if USE_XICU
156    volatile unsigned int* xcu_address =
157        (unsigned int *) ((unsigned int)&seg_xcu_base + 
158        (cluster_xy * (unsigned int)&vseg_cluster_increment));
159
160    xcu_address[XICU_REG(XICU_WTI_REG, proc_id)] = wdata;
161    return 0; 
162#else
163    _tty_get_lock( 0 );
164    _puts("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n");
165    _tty_release_lock( 0 );
166    return 1;
167#endif
168} 
169
170////////////////////////////////////////////////////////////////////////////////
171//    _xcu_timer_start()
172// This function activates a timer contained in XICU by writing in the
173// proper register the period value.
174// Returns 0 if success, > 0 if error.
175////////////////////////////////////////////////////////////////////////////////
176unsigned int _xcu_timer_start( unsigned int cluster_xy,
177                               unsigned int pti_index,
178                               unsigned int period )
179{
180    // parameters checking
181    unsigned int x = cluster_xy >> Y_WIDTH;
182    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
183    if (x >= X_SIZE)             return 1; 
184    if (y >= Y_SIZE)             return 1; 
185
186#if USE_XICU
187    volatile unsigned int* xcu_address =
188        (unsigned int *) ((unsigned int)&seg_xcu_base + 
189        (cluster_xy * (unsigned int)&vseg_cluster_increment));
190
191    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
192    return 0;
193#else
194    _tty_get_lock( 0 );
195    _puts("[GIET ERROR] _xcu_timer_start should not be used if USE_XICU is not set\n");
196    _tty_release_lock( 0 );
197    return 1;
198#endif
199}
200
201//////////////////////////////////////////////////////////////////////////////
202//     _xcu_timer_stop()
203// This function desactivates a timer in XICU component
204// by writing in the proper register.
205// Returns 0 if success, > 0 if error.
206//////////////////////////////////////////////////////////////////////////////
207unsigned int _xcu_timer_stop( unsigned int cluster_xy, 
208                              unsigned int pti_index) 
209{
210    // parameters checking
211    unsigned int x = cluster_xy >> Y_WIDTH;
212    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
213    if (x >= X_SIZE)             return 1; 
214    if (y >= Y_SIZE)             return 1; 
215
216#if USE_XICU
217    volatile unsigned int * xcu_address =
218        (unsigned int *) ((unsigned int)&seg_xcu_base + 
219        (cluster_xy * (unsigned int)&vseg_cluster_increment));
220
221    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
222    return 0;
223#else
224    _tty_get_lock( 0 );
225    _puts("[GIET ERROR] _xcu_timer_stop should not be used if USE_XICU is not set\n");
226    _tty_release_lock( 0 );
227    return 1;
228#endif
229}
230
231//////////////////////////////////////////////////////////////////////////////
232//     _xcu_timer_reset_irq()
233// This function acknowlegge a timer interrupt in XICU
234// component by reading in the proper register.
235// It can be used by both the isr_switch() for a "system" timer,
236// or by the _isr_timer() for an "user" timer.
237// Returns 0 if success, > 0 if error.
238//////////////////////////////////////////////////////////////////////////////
239unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
240                                   unsigned int pti_index ) 
241{
242    // parameters checking
243    unsigned int x = cluster_xy >> Y_WIDTH;
244    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
245    if (x >= X_SIZE)             return 1; 
246    if (y >= Y_SIZE)             return 1; 
247
248#if USE_XICU
249    volatile unsigned int * xcu_address =
250        (unsigned int *) ((unsigned int)&seg_xcu_base +
251        (cluster_xy * (unsigned int)&vseg_cluster_increment));
252
253    xcu_address[XICU_REG(XICU_PTI_ACK, pti_index)];
254    return 0;
255#else
256    _tty_get_lock( 0 );
257    _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
258    _tty_release_lock( 0 );
259    return 1;
260#endif
261}
262
263//////////////////////////////////////////////////////////////////////////////
264//     _xcu_timer_reset_cpt()
265// This function resets a timer counter. To do so, we re-write the period
266// in the proper register, what causes the count to restart.
267// The period value is read from the same (TIMER_PERIOD) register,
268// this is why in appearance we do nothing useful (read a value
269// from a register and write this value in the same register)
270// This function is called during a context switch (user or preemptive)
271/////////////////////////////////////////////////////////////////////////////
272unsigned int _xcu_timer_reset_cpt( unsigned int cluster_xy, 
273                                   unsigned int pti_index ) 
274{
275    // parameters checking
276    unsigned int x = cluster_xy >> Y_WIDTH;
277    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
278    if (x >= X_SIZE)             return 1; 
279    if (y >= Y_SIZE)             return 1; 
280
281#if USE_XICU
282    volatile unsigned int * xcu_address =
283        (unsigned int *) ((unsigned int) &seg_xcu_base + 
284        (cluster_xy * (unsigned int)&vseg_cluster_increment));
285
286    unsigned int period = xcu_address[XICU_REG(XICU_PTI_PER, pti_index)];
287
288    // we write 0 first because if the timer is currently running,
289    // the corresponding timer counter is not reset
290    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = 0;
291    xcu_address[XICU_REG(XICU_PTI_PER, pti_index)] = period;
292    return 0;
293#else
294    _tty_get_lock( 0 );
295    _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
296    _tty_release_lock( 0 );
297    return 1;
298#endif
299}
300
301
302// Local Variables:
303// tab-width: 4
304// c-basic-offset: 4
305// c-file-offsets:((innamespace . 0)(inline-open . 0))
306// indent-tabs-mode: nil
307// End:
308// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
309
Note: See TracBrowser for help on using the repository browser.