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

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

This is a major release, including a deep restructuration of code.
The main evolutions are

  • use of the Tsar preloader to load the GIET boot-loader from disk
  • introduction of a FAT32 file system library,
  • use of this fat32 library by the boot-loader to load the map.bin data structure, and the various .elf files
  • reorganisation of drivers (one file per peripheral).
  • introduction of drivers for new peripherals: vci_chbuf_dma and vci_multi_ahci.
  • introduction of a new physical memory allocator in the boot code.

This release has been tested on the tsar_generic_iob architecture,
for the two following mappings: 4c_1p_iob_four.xml and 4c_1p_iob_sort.xml

File size: 6.7 KB
Line 
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.
18// The global index is cluster_id * (NB_PROCS_MAX + NB_TIM_CHANNELS) + local_id
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//
27//     seg_tim_base + cluster_id * vseg_cluster_increment + TIMER_SPAN * timer_id
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
37#if !defined(NB_CLUSTERS)
38# error: You must define NB_CLUSTERS in the hard_config.h file
39#endif
40
41#if (NB_CLUSTERS > 256)
42# error: NB_CLUSTERS cannot be larger than 256!
43#endif
44
45#if !defined(NB_PROCS_MAX)
46# error: You must define NB_PROCS_MAX in the hard_config.h file
47#endif
48
49#if (NB_PROCS_MAX > 8)
50# error: NB_PROCS_MAX cannot be larger than 8!
51#endif
52
53#if !defined(NB_TIM_CHANNELS)
54#define NB_TIM_CHANNELS 0
55#endif
56
57#if ( (NB_TIM_CHANNELS + NB_PROC_MAX) > 32 )
58# error: NB_TIM_CHANNELS + NB_PROCS_MAX cannot be larger than 32
59#endif
60
61#if !defined( USE_XICU )
62# error: You must define USE_XICU in the hard_config.h file
63#endif
64
65///////////////////  Timer global variables ////////////////////////////////////////
66
67#define in_unckdata __attribute__((section (".unckdata")))
68
69#if (NB_TIM_CHANNELS > 0)
70in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS * NB_TIM_CHANNELS] 
71                            = { [0 ... ((NB_CLUSTERS * NB_TIM_CHANNELS) - 1)] = 0 };
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//////////////////////////////////////////////////////////////////////////////
82unsigned int _timer_start( unsigned int cluster_id, 
83                           unsigned int local_id, 
84                           unsigned int period) 
85{
86    // parameters checking
87    if (cluster_id >= NB_CLUSTERS)    return 1;
88    if (local_id >= NB_TIM_CHANNELS)  return 1;
89
90    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
91                                  (cluster_id * (unsigned int)&vseg_cluster_increment));
92
93    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
94    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3;
95    return 0;
96}
97
98//////////////////////////////////////////////////////////////////////////////
99//     _timer_stop()
100// This function desactivates a timer in the vci_timer component
101// by writing in the proper register.
102// Returns 0 if success, > 0 if error.
103//////////////////////////////////////////////////////////////////////////////
104unsigned int _timer_stop( unsigned int cluster_id, 
105                          unsigned int local_id) 
106{
107    // parameters checking
108    if (cluster_id >= NB_CLUSTERS)    return 1;
109    if (local_id >= NB_TIM_CHANNELS)  return 1;
110
111    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
112                                  (cluster_id * (unsigned int)&vseg_cluster_increment));
113
114    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
115    return 0;
116}
117
118//////////////////////////////////////////////////////////////////////////////
119//     _timer_reset_irq()
120// This function acknowlegge a timer interrupt in the vci_timer 
121// component by writing in the proper register.
122// It can be used by both the isr_switch() for a "system" timer,
123// or by the _isr_timer() for an "user" timer.
124// Returns 0 if success, > 0 if error.
125//////////////////////////////////////////////////////////////////////////////
126unsigned int _timer_reset_irq( unsigned int cluster_id, 
127                               unsigned int local_id ) 
128{
129    // parameters checking
130    if (cluster_id >= NB_CLUSTERS)    return 1;
131    if (local_id >= NB_TIM_CHANNELS)  return 1;
132
133    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
134                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
135
136    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
137    return 0;
138}
139
140/////////////////////////////////////////////////////////////////////////////
141//     _timer_reset_cpt()
142// This function resets the timer counter. To do so, we re-write the period
143// in the proper register, what causes the count to restart.
144// The period value is read from the same (TIMER_PERIOD) register,
145// this is why in appearance we do nothing useful (read a value
146// from a register and write this value in the same register)
147// This function is called during a context switch (user or preemptive)
148//////////////////////////////////////////////////////////////////////i//////
149unsigned int _timer_reset_cpt( unsigned int cluster_id, 
150                               unsigned int local_id) 
151{
152    // parameters checking
153    if (cluster_id >= NB_CLUSTERS)    return 1;
154    if (local_id >= NB_TIM_CHANNELS)  return 1;
155
156    // We suppose that the TIMER_MODE register value is 0x3
157    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
158                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
159
160    unsigned int period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
161    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
162    return 0;
163}
164
165
166// Local Variables:
167// tab-width: 4
168// c-basic-offset: 4
169// c-file-offsets:((innamespace . 0)(inline-open . 0))
170// indent-tabs-mode: nil
171// End:
172// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
173
Note: See TracBrowser for help on using the repository browser.