summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/gen68340/timer/timer.c
blob: 3331385976a0e1806ccb061e9407352db8a536a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
 * ATTENTION: AS MC68349 has no built-in Timer, the following code doesn't work
 * 	      in a MC68349. You can't use FIFO full mode for the moment, but
 *	      it should be easy to fix this by using an external timer
 *
 * Use TIMER 1 for TIMEOUT when using FIFO FULL mode in UART driver
 * Use TIMER 2 for timing test suites
 *
 * Geoffroy Montel
 * France Telecom - CNET/DSM/TAM/CAT
 * 4, rue du Clos Courtel
 * 35512 CESSON-SEVIGNE
 * FRANCE
 *
 * e-mail: g_montel@yahoo.com
 *
 *  $Id$
 */

/*
 *
 *  Input parameters:  NONE
 *
 *  Output parameters:  NONE
 *
 *  NOTE: It is important that the timer start/stop overhead be
 *        determined when porting or modifying this code.
 *
 *  COPYRIGHT (c) 1989-1999.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 */

#include <rtems.h>
#include <bsp.h>
#include <m340uart.h>
#include <m340timer.h>
#include <m68340.h>

#define TIMER1_VECTOR 122
#define TIMER1_IRQ_LEVEL 5
#define TIMER1_INTERRUPT_ARBITRATION 5

#define TIMER2_VECTOR 123
#define TIMER2_IRQ_LEVEL 4
#define TIMER2_INTERRUPT_ARBITRATION 4

#define CLOCK_SPEED 25		/* in Mhz */

#define max(a,b) (((a)>(b)) ? (a) : (b))

void (*Restart_Fifo_Full_A_Timer)(void);
void (*Restart_Check_A_Timer)(void);
void (*Restart_Fifo_Full_B_Timer)(void);
void (*Restart_Check_B_Timer)(void);

int preload = 0;

/******************************************************
  Name: __Restart_Fifo_Full_Timer
  Input parameters: -
  Output parameters: -
  Description: when a character is received, sets
               the TIMER to raise an interrupt at
	       TIMEOUT.
	       It's necessary to prevent from not
	       getting n-1 characters (with n the
               Uart Fifo size)
 *****************************************************/
void __Restart_Fifo_Full_Timer (void)
{
 TSR1 |= m340_TO;
 TCR1 &= ~m340_CPE;
 WPREL11 = preload;
 TCR1 |= m340_CPE;
}

/******************************************************
  Name: __Restart_Fifo_Full_Timer
  Input parameters: -
  Output parameters: -
  Description: when no character has been received
               recently, check now and then if whether
	       a there's a character in the FIFO
 *****************************************************/
void __Restart_Check_Timer (void)
{
 TSR1 |= m340_TO;
 TCR1 &= ~m340_CPE;
 WPREL11 = 0xFFFF;
 TCR1 |= m340_CPE;
}

/******************************************************
  Name: __do_nothing
  Input parameters: -
  Output parameters: -
  Description: we always restart the fifo full timer
	       with a call to Restart_*_Timer
	       if we do not use FIFO full, Restart_*_Timer
	       are set to do __do_nothing
 *****************************************************/
void __do_nothing (void)
{
}

#define Fifo_Full_on_A (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL && m340_uart_config[UART_CHANNEL_A].enable && m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
#define Fifo_Full_on_B (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL && m340_uart_config[UART_CHANNEL_B].enable && m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)

/******************************************************
  Name: Fifo_Full_benchmark_timer_initialize
  Input parameters: -
  Output parameters: -
  Description: initialize Timer 1 for FIFO full mode
 *****************************************************/
void Fifo_Full_benchmark_timer_initialize (void)
{
   float max_baud_rate;
   int prescaler_output_tap = -1;
   int nb_of_clock_ticks = 0;

   /*
    *  USE TIMER 1 for UART FIFO FULL mode
    */

   if ( Fifo_Full_on_A || Fifo_Full_on_B )
      {
	/* Disable the timer */
	TCR1 &= ~m340_SWR;

	/* Reset the interrupts */
	TSR1 &= ~(m340_TO | m340_TG | m340_TC);

	/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
	   set interrupt arbitration */
	TMCR1 = TIMER1_INTERRUPT_ARBITRATION;

	/* interrupt priority level and interrupt vector */
	TIR1 = TIMER1_VECTOR | (TIMER1_IRQ_LEVEL << 8);

	/* compute prescaler */
   	if ( Fifo_Full_on_A && Fifo_Full_on_B)
		max_baud_rate = max(m340_uart_config[UART_CHANNEL_A].rx_baudrate, m340_uart_config[UART_CHANNEL_B].rx_baudrate);
	else if ( Fifo_Full_on_A )
		max_baud_rate = m340_uart_config[UART_CHANNEL_A].rx_baudrate;
	     else max_baud_rate = m340_uart_config[UART_CHANNEL_B].rx_baudrate;

	/* find out config */
	nb_of_clock_ticks = (10/max_baud_rate)*(CLOCK_SPEED*1000000)*1.2;
	if (nb_of_clock_ticks < 0xFFFF) {
	   preload = nb_of_clock_ticks;
	   prescaler_output_tap = -1;
	} else if (nb_of_clock_ticks/2 < 0xFFFF) {
	   preload = nb_of_clock_ticks/2;
	   prescaler_output_tap = m340_Divide_by_2;
	} else if (nb_of_clock_ticks/4 < 0xFFFF) {
	   preload = nb_of_clock_ticks/4;
	   prescaler_output_tap = m340_Divide_by_4;
	} else if (nb_of_clock_ticks/8 < 0xFFFF) {
	   preload = nb_of_clock_ticks/8;
	   prescaler_output_tap = m340_Divide_by_16;
	} else if (nb_of_clock_ticks/16 < 0xFFFF) {
	   preload = nb_of_clock_ticks/16;
	   prescaler_output_tap = m340_Divide_by_16;
	} else if (nb_of_clock_ticks/32 < 0xFFFF) {
	   preload = nb_of_clock_ticks/32;
	   prescaler_output_tap = m340_Divide_by_32;
	} else if (nb_of_clock_ticks/64 < 0xFFFF) {
	   preload = nb_of_clock_ticks/64;
	   prescaler_output_tap = m340_Divide_by_64;
	} else if (nb_of_clock_ticks/128 < 0xFFFF) {
	   preload = nb_of_clock_ticks/128;
	   prescaler_output_tap = m340_Divide_by_128;
	} else if (nb_of_clock_ticks/256 < 0xFFFF) {
	   preload = nb_of_clock_ticks/256;
	   prescaler_output_tap = m340_Divide_by_256;
	}

	/* Input Capture/Output Compare (ICOC) */
	TCR1 = m340_SWR | m340_TO_Enabled | m340_ICOC;
	if (prescaler_output_tap!=-1) TCR1 |= prescaler_output_tap | m340_PSE;

	/* install interrupt vector */
	{
         rtems_isr_entry old_handler;
	 rtems_status_code sc;

	 extern void _Debug_ISR_Handler_Console(void);

	 sc = rtems_interrupt_catch (InterruptHandler,
	  			     TIMER1_VECTOR,
				     &old_handler);

	 /* uncomment this if you want to pass control to your own ISR handler
	    it may be usefull to do so to check for performances with an oscilloscope */
	 /*
	 {
	  proc_ptr ignored;
	  _CPU_ISR_install_raw_handler( TIMER1_VECTOR, _Debug_ISR_Handler_Console, &ignored );
	 }
	 */
        }
       } /* fifo full mode on a uart */

       /* install routines */
       Restart_Check_A_Timer = Fifo_Full_on_A ? __Restart_Check_Timer : __do_nothing;
       Restart_Fifo_Full_A_Timer = Fifo_Full_on_A ? __Restart_Fifo_Full_Timer : __do_nothing;
       Restart_Check_B_Timer = Fifo_Full_on_B ? __Restart_Check_Timer : __do_nothing;
       Restart_Fifo_Full_B_Timer = Fifo_Full_on_B ? __Restart_Fifo_Full_Timer : __do_nothing;
       /* start checking timer */
       Restart_Check_A_Timer();
       Restart_Check_B_Timer();
}

/******************************************************
  Name: benchmark_timer_initialize
  Input parameters: -
  Output parameters: -
  Description: init Timer for timing test suites
 *****************************************************/
void benchmark_timer_initialize (void)
{
	/* Disable the timer */
	TCR2 &= ~m340_SWR;

	/* Reset the interrupts */
	TSR2 &= ~(m340_TO | m340_TG | m340_TC);

	/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
	   set interrupt arbitration */
	TMCR1 = TIMER2_INTERRUPT_ARBITRATION;

	/* interrupt priority level and interrupt vector */
	TIR1 = TIMER2_VECTOR | (TIMER2_IRQ_LEVEL << 8);

	/* Init the stop bit for normal operation, ignore FREEZE, user privileges,
	   set interrupt arbitration */
	TMCR2 = TIMER2_INTERRUPT_ARBITRATION;

	/* Preload register 1 */
	WPREL21 = 0xFFFF;

	/* Input Capture/Output Compare (ICOC) */
	TCR2 = m340_SWR | m340_ICOC | m340_PSE | m340_Divide_by_16 | m340_CPE;
}

/******************************************************
  Name: benchmark_timer_read
  Input parameters: -
  Output parameters: -
  Description: Return timer value in microsecond units
 *****************************************************/
int
benchmark_timer_read (void)
{
 /* there's CLOCK_SPEED / 16 micro seconds between two timer register decrement */
 return (((0xFFFF - TCNTR2) * CLOCK_SPEED) / 16);
}

/******************************************************
  Name: benchmark_timer_disable_subtracting_average_overhead
  Input parameters: -
  Output parameters: -
  Description: -
 *****************************************************/
void
benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
{
}