source: soft/giet_vm/giet_drivers/tim_driver.c @ 269

Last change on this file since 269 was 263, checked in by alain, 11 years ago

Introducing support for TSAR fixed format cluster index (cluster_xy)
We have now 4 parameters defined in map.xml:

  • X_WIDTH, Y_WIDTH define the fixed format (typically X_WIDTH = 4 / Y_WIDTH = 4)
  • X_SIZE, Y_SIZE define the actual TSAR 2D mesh variable size (from 1 to 16)
File size: 7.3 KB
RevLine 
[258]1//////////////////////////////////////////////////////////////////////////////////////
2// File     : timer_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////////
7// The timer_driver.c and timer_driver.h files are part ot the GIET-VM nano-kernel.
8// This driver supports the SoCLib vci_multi_timer component.
9//
10// It can exist several multi_timers in the architecture (at most one per cluster),
11// and each one can contain several timers (called channels).
12//
13// There is two types of timers:
14// - "system" timers : one per processor, used for context switch.
15//   local_id in [0, NB_PROCS_MAX-1],
16// - "user" timers : requested by the task in the mapping_info data structure.
17//   For each user timer, the timer_id is stored in the context of the task.
[263]18// The global index is cluster_xy * (NB_PROCS_MAX + NB_TIM_CHANNELS) + local_id
[258]19//
20// The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in the
21// hard_config.h file.
22//
23// The register offsets must be defined in the hwr_mapping.h file.
24/////////////////////////////////////////////////////////////////////////////////////
25// The virtual base address of the segment associated to a channel is:
26//
[263]27//     seg_tim_base + cluster_xy * vseg_cluster_increment + TIMER_SPAN * timer_id
[258]28//
29// The seg_tim_base and vseg_cluster_increment values must be defined
30// in the giet_vsegs.ld file.
31/////////////////////////////////////////////////////////////////////////////////////
32
33#include <giet_config.h>
34#include <tim_driver.h>
35#include <utils.h>
36
[263]37#if !defined(X_SIZE)
38# error: You must define X_SIZE in the hard_config.h file
[258]39#endif
40
[263]41#if !defined(Y_SIZE)
42# error: You must define X_SIZE in the hard_config.h file
[258]43#endif
44
[263]45#if !defined(X_WIDTH)
46# error: You must define X_WIDTH in the hard_config.h file
47#endif
48
49#if !defined(Y_WIDTH)
50# error: You must define X_WIDTH in the hard_config.h file
51#endif
52
[258]53#if !defined(NB_PROCS_MAX)
54# error: You must define NB_PROCS_MAX in the hard_config.h file
55#endif
56
57#if !defined(NB_TIM_CHANNELS)
58#define NB_TIM_CHANNELS 0
59#endif
60
61#if ( (NB_TIM_CHANNELS + NB_PROC_MAX) > 32 )
62# error: NB_TIM_CHANNELS + NB_PROCS_MAX cannot be larger than 32
63#endif
64
65///////////////////  Timer global variables ////////////////////////////////////////
66
67#define in_unckdata __attribute__((section (".unckdata")))
68
69#if (NB_TIM_CHANNELS > 0)
[263]70in_unckdata volatile unsigned char _user_timer_event[X_SIZE*Y_SIZE*NB_TIM_CHANNELS] 
71                            = { [0 ... ((X_SIZE*Y_SIZE*NB_TIM_CHANNELS) - 1)] = 0 };
[258]72#endif
73
74////////////////////////////////////////////////////////////////////////////////////
75//     _timer_start()
76// This function activates a timer in the vci_timer component
77// by writing in the proper register the period value.
78// It can be used by both the kernel to initialise a "system" timer,
79// or by a task (through a system call) to configure an "user" timer.
80// Returns 0 if success, > 0 if error.
81//////////////////////////////////////////////////////////////////////////////
[263]82unsigned int _timer_start( unsigned int cluster_xy, 
[258]83                           unsigned int local_id, 
84                           unsigned int period) 
85{
86    // parameters checking
[263]87    unsigned int x = cluster_xy >> Y_WIDTH;
88    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
89    if (x >= X_SIZE)                  return 1; 
90    if (y >= Y_SIZE)                  return 1; 
[258]91    if (local_id >= NB_TIM_CHANNELS)  return 1;
92
93    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
[263]94                                  (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]95
96    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
97    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3;
98    return 0;
99}
100
101//////////////////////////////////////////////////////////////////////////////
102//     _timer_stop()
103// This function desactivates a timer in the vci_timer component
104// by writing in the proper register.
105// Returns 0 if success, > 0 if error.
106//////////////////////////////////////////////////////////////////////////////
[263]107unsigned int _timer_stop( unsigned int cluster_xy, 
[258]108                          unsigned int local_id) 
109{
110    // parameters checking
[263]111    unsigned int x = cluster_xy >> Y_WIDTH;
112    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
113    if (x >= X_SIZE)                  return 1; 
114    if (y >= Y_SIZE)                  return 1; 
[258]115    if (local_id >= NB_TIM_CHANNELS)  return 1;
116
117    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
[263]118                                  (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]119
120    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
121    return 0;
122}
123
124//////////////////////////////////////////////////////////////////////////////
125//     _timer_reset_irq()
126// This function acknowlegge a timer interrupt in the vci_timer 
127// component by writing in the proper register.
128// It can be used by both the isr_switch() for a "system" timer,
129// or by the _isr_timer() for an "user" timer.
130// Returns 0 if success, > 0 if error.
131//////////////////////////////////////////////////////////////////////////////
[263]132unsigned int _timer_reset_irq( unsigned int cluster_xy, 
[258]133                               unsigned int local_id ) 
134{
135    // parameters checking
[263]136    unsigned int x = cluster_xy >> Y_WIDTH;
137    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
138    if (x >= X_SIZE)                  return 1; 
139    if (y >= Y_SIZE)                  return 1; 
[258]140    if (local_id >= NB_TIM_CHANNELS)  return 1;
141
142    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
[263]143                                   (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]144
145    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
146    return 0;
147}
148
149/////////////////////////////////////////////////////////////////////////////
150//     _timer_reset_cpt()
151// This function resets the timer counter. To do so, we re-write the period
152// in the proper register, what causes the count to restart.
153// The period value is read from the same (TIMER_PERIOD) register,
154// this is why in appearance we do nothing useful (read a value
155// from a register and write this value in the same register)
156// This function is called during a context switch (user or preemptive)
157//////////////////////////////////////////////////////////////////////i//////
[263]158unsigned int _timer_reset_cpt( unsigned int cluster_xy, 
[258]159                               unsigned int local_id) 
160{
161    // parameters checking
[263]162    unsigned int x = cluster_xy >> Y_WIDTH;
163    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
164    if (x >= X_SIZE)                  return 1; 
165    if (y >= Y_SIZE)                  return 1; 
[258]166    if (local_id >= NB_TIM_CHANNELS)  return 1;
167
168    // We suppose that the TIMER_MODE register value is 0x3
169    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
[263]170                                   (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]171
172    unsigned int period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
173    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
174    return 0;
175}
176
177
178// Local Variables:
179// tab-width: 4
180// c-basic-offset: 4
181// c-file-offsets:((innamespace . 0)(inline-open . 0))
182// indent-tabs-mode: nil
183// End:
184// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
185
Note: See TracBrowser for help on using the repository browser.