1 /* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
6 This file is part of the program GDB, the GNU debugger.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either vertimn 2 of the License, or
11 (at your option) any later vertimn.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "sim-assert.h"
32 m68hc11tim - m68hc11 timer devices
37 Implements the m68hc11 timer as described in Chapter 10
50 Reset the timer device. This port must be connected to
51 the cpu-reset output port.
65 static const struct hw_port_descriptor m68hc11tim_ports
[] =
67 { "reset", RESET_PORT
, 0, input_port
, },
72 /* Timer Controller information. */
75 unsigned long cop_delay
;
76 unsigned long rti_delay
;
77 unsigned long ovf_delay
;
78 signed64 clock_prescaler
;
81 /* Periodic timers. */
82 struct hw_event
*rti_timer_event
;
83 struct hw_event
*cop_timer_event
;
84 struct hw_event
*tof_timer_event
;
85 struct hw_event
*cmp_timer_event
;
90 /* Finish off the partially created hw device. Attach our local
91 callbacks. Wire up our port names etc. */
93 static hw_io_read_buffer_method m68hc11tim_io_read_buffer
;
94 static hw_io_write_buffer_method m68hc11tim_io_write_buffer
;
95 static hw_port_event_method m68hc11tim_port_event
;
96 static hw_ioctl_method m68hc11tim_ioctl
;
98 #define M6811_TIMER_FIRST_REG (M6811_TCTN)
99 #define M6811_TIMER_LAST_REG (M6811_PACNT)
103 attach_m68hc11tim_regs (struct hw
*me
,
104 struct m68hc11tim
*controller
)
106 hw_attach_address (hw_parent (me
), 0, io_map
,
107 M6811_TIMER_FIRST_REG
,
108 M6811_TIMER_LAST_REG
- M6811_TIMER_FIRST_REG
+ 1,
114 m68hc11tim_finish (struct hw
*me
)
116 struct m68hc11tim
*controller
;
118 controller
= HW_ZALLOC (me
, struct m68hc11tim
);
119 me
->overlap_mode_hw
= 1;
120 set_hw_data (me
, controller
);
121 set_hw_io_read_buffer (me
, m68hc11tim_io_read_buffer
);
122 set_hw_io_write_buffer (me
, m68hc11tim_io_write_buffer
);
123 set_hw_ports (me
, m68hc11tim_ports
);
124 set_hw_port_event (me
, m68hc11tim_port_event
);
126 set_hw_ioctl (me
, m68hc11tim_ioctl
);
128 me
->to_ioctl
= m68hc11tim_ioctl
;
131 /* Preset defaults. */
132 controller
->clock_prescaler
= 1;
133 controller
->tcnt_adjust
= 0;
135 /* Attach ourself to our parent bus. */
136 attach_m68hc11tim_regs (me
, controller
);
141 /* An event arrives on an interrupt port. */
144 m68hc11tim_port_event (struct hw
*me
,
151 struct m68hc11tim
*controller
;
155 controller
= hw_data (me
);
157 cpu
= STATE_CPU (sd
, 0);
162 HW_TRACE ((me
, "Timer reset"));
164 /* Cancel all timer events. */
165 if (controller
->rti_timer_event
)
167 hw_event_queue_deschedule (me
, controller
->rti_timer_event
);
168 controller
->rti_timer_event
= 0;
170 if (controller
->cop_timer_event
)
172 hw_event_queue_deschedule (me
, controller
->cop_timer_event
);
173 controller
->cop_timer_event
= 0;
175 if (controller
->tof_timer_event
)
177 hw_event_queue_deschedule (me
, controller
->tof_timer_event
);
178 controller
->tof_timer_event
= 0;
180 if (controller
->cmp_timer_event
)
182 hw_event_queue_deschedule (me
, controller
->cmp_timer_event
);
183 controller
->cmp_timer_event
= 0;
186 /* Reset the state of Timer registers. This also restarts
187 the timer events (overflow and RTI clock). */
189 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
190 (unsigned_word
) M6811_TMSK2
, 1);
191 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
192 (unsigned_word
) M6811_TFLG2
, 1);
193 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
194 (unsigned_word
) M6811_PACTL
, 1);
199 hw_abort (me
, "Event on unknown port %d", my_port
);
213 m68hc11tim_timer_event (struct hw
*me
, void *data
)
216 struct m68hc11tim
*controller
;
218 enum event_type type
;
220 struct hw_event
**eventp
;
221 int check_interrupt
= 0;
227 controller
= hw_data (me
);
229 cpu
= STATE_CPU (sd
, 0);
230 type
= (enum event_type
) ((long) data
) & 0x0FF;
236 eventp
= &controller
->cop_timer_event
;
237 delay
= controller
->cop_delay
;
242 eventp
= &controller
->rti_timer_event
;
243 delay
= controller
->rti_delay
;
244 if (((long) (data
) & 0x0100) == 0)
246 cpu
->ios
[M6811_TFLG2
] |= M6811_RTIF
;
252 eventp
= &controller
->tof_timer_event
;
253 delay
= controller
->ovf_delay
;
254 cpu
->ios
[M6811_TFLG2
] |= M6811_TOF
;
258 eventp
= &controller
->cmp_timer_event
;
260 /* Get current free running counter. */
261 tcnt
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
262 / controller
->clock_prescaler
);
265 flags
= cpu
->ios
[M6811_TMSK1
];
269 /* Scan each output compare register to see if one matches
270 the free running counter. Set the corresponding OCi flag
271 if the output compare is enabled. */
272 for (i
= M6811_TOC1
; i
<= M6811_TOC5
; i
+= 2, mask
>>= 1)
274 unsigned short compare
;
276 compare
= (cpu
->ios
[i
] << 8) + cpu
->ios
[i
+1];
277 if (compare
== tcnt
&& (flags
& mask
))
279 cpu
->ios
[M6811_TFLG1
] |= mask
;
283 /* Compute how many times for the next match. */
285 compare
= compare
- tcnt
;
287 compare
= compare
- tcnt
+ 65536;
292 delay
= delay
* controller
->clock_prescaler
;
294 /* Deactivate the compare timer if no output compare is enabled. */
295 if ((flags
& 0xF0) == 0)
306 hw_event_queue_deschedule (me
, *eventp
);
312 *eventp
= hw_event_queue_schedule (me
, delay
,
313 m68hc11tim_timer_event
,
318 interrupts_update_pending (&cpu
->cpu_interrupts
);
322 /* Descriptions of the Timer I/O ports. These descriptions are only used to
323 give information of the Timer device under GDB. */
324 io_reg_desc tmsk2_desc
[] = {
325 { M6811_TOI
, "TOI ", "Timer Overflow Interrupt Enable" },
326 { M6811_RTII
, "RTII ", "RTI Interrupt Enable" },
327 { M6811_PAOVI
, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
328 { M6811_PAII
, "PAII ", "Pulse Accumulator Interrupt Enable" },
329 { M6811_PR1
, "PR1 ", "Timer prescaler (PR1)" },
330 { M6811_PR0
, "PR0 ", "Timer prescaler (PR0)" },
331 { M6811_TPR_1
, "TPR_1 ", "Timer prescaler div 1" },
332 { M6811_TPR_4
, "TPR_4 ", "Timer prescaler div 4" },
333 { M6811_TPR_8
, "TPR_8 ", "Timer prescaler div 8" },
334 { M6811_TPR_16
, "TPR_16", "Timer prescaler div 16" },
338 io_reg_desc tflg2_desc
[] = {
339 { M6811_TOF
, "TOF ", "Timer Overflow Bit" },
340 { M6811_RTIF
, "RTIF ", "Read Time Interrupt Flag" },
341 { M6811_PAOVF
, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
342 { M6811_PAIF
, "PAIF ", "Pulse Accumulator Input Edge" },
346 io_reg_desc pactl_desc
[] = {
347 { M6811_DDRA7
, "DDRA7 ", "Data Direction for Port A bit-7" },
348 { M6811_PAEN
, "PAEN ", "Pulse Accumulator System Enable" },
349 { M6811_PAMOD
, "PAMOD ", "Pulse Accumulator Mode" },
350 { M6811_PEDGE
, "PEDGE ", "Pulse Accumulator Edge Control" },
351 { M6811_RTR1
, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
352 { M6811_RTR0
, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
357 to_realtime (sim_cpu
*cpu
, signed64 t
)
359 return (double) (t
) / (double) (cpu
->cpu_frequency
/ 4);
363 m68hc11tim_print_timer (struct hw
*me
, const char *name
,
364 struct hw_event
*event
)
371 sim_io_printf (sd
, " No %s interrupt will be raised.\n", name
);
379 cpu
= STATE_CPU (sd
, 0);
381 t
= hw_event_remain_time (me
, event
);
382 dt
= to_realtime (cpu
, t
) * 1000.0;
383 sim_io_printf (sd
, " Next %s interrupt in %ld cycles (%3.3f ms)\n",
389 m68hc11tim_info (struct hw
*me
)
394 struct m68hc11tim
*controller
;
398 cpu
= STATE_CPU (sd
, 0);
399 controller
= hw_data (me
);
401 sim_io_printf (sd
, "M68HC11 Timer:\n");
403 base
= cpu_get_io_base (cpu
);
405 val
= cpu
->ios
[M6811_TMSK2
];
406 print_io_byte (sd
, "TMSK2 ", tmsk2_desc
, val
, base
+ M6811_TMSK2
);
407 sim_io_printf (sd
, "\n");
409 val
= cpu
->ios
[M6811_TFLG2
];
410 print_io_byte (sd
, "TFLG2", tflg2_desc
, val
, base
+ M6811_TFLG2
);
411 sim_io_printf (sd
, "\n");
413 val
= cpu
->ios
[M6811_PACTL
];
414 print_io_byte (sd
, "PACTL", pactl_desc
, val
, base
+ M6811_PACTL
);
415 sim_io_printf (sd
, "\n");
417 /* Give info about the next timer interrupts. */
418 m68hc11tim_print_timer (me
, "RTI", controller
->rti_timer_event
);
419 m68hc11tim_print_timer (me
, "COP", controller
->cop_timer_event
);
420 m68hc11tim_print_timer (me
, "OVERFLOW", controller
->tof_timer_event
);
421 m68hc11tim_print_timer (me
, "COMPARE", controller
->cmp_timer_event
);
425 m68hc11tim_ioctl (struct hw
*me
,
426 hw_ioctl_request request
,
429 m68hc11tim_info (me
);
433 /* generic read/write */
436 m68hc11tim_io_read_buffer (struct hw
*me
,
443 struct m68hc11tim
*controller
;
447 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
450 cpu
= STATE_CPU (sd
, 0);
451 controller
= hw_data (me
);
455 /* The cpu_absolute_cycle is updated after each instruction.
456 Reading in a 16-bit register will be split in two accesses
457 but this will be atomic within the simulator. */
459 val
= (uint8
) ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
460 / (controller
->clock_prescaler
* 256));
464 val
= (uint8
) ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
465 / controller
->clock_prescaler
);
469 val
= cpu
->ios
[base
];
472 *((unsigned8
*) dest
) = val
;
477 m68hc11tim_io_write_buffer (struct hw
*me
,
484 struct m68hc11tim
*controller
;
488 int reset_compare
= 0;
490 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
493 cpu
= STATE_CPU (sd
, 0);
494 controller
= hw_data (me
);
496 val
= *((const unsigned8
*) source
);
499 /* Set the timer counter low part, trying to preserve the low part.
500 We compute the absolute cycle adjustment that we have to apply
501 to obtain the timer current value. Computation must be made
502 in 64-bit to avoid overflow problems. */
504 adj
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
505 / (controller
->clock_prescaler
* (signed64
) 256)) & 0x0FF;
506 adj
= cpu
->cpu_absolute_cycle
507 - (adj
* controller
->clock_prescaler
* (signed64
) 256)
508 - ((signed64
) adj
* controller
->clock_prescaler
);
509 controller
->tcnt_adjust
= adj
;
514 adj
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
515 / controller
->clock_prescaler
) & 0x0ff;
516 adj
= cpu
->cpu_absolute_cycle
517 - ((signed64
) val
* controller
->clock_prescaler
* (signed64
) 256)
518 - (adj
* controller
->clock_prescaler
);
519 controller
->tcnt_adjust
= adj
;
525 /* Timer prescaler cannot be changed after 64 bus cycles. */
526 if (cpu
->cpu_absolute_cycle
>= 64)
528 val
&= ~(M6811_PR1
| M6811_PR0
);
529 val
|= cpu
->ios
[M6811_TMSK2
] & (M6811_PR1
| M6811_PR0
);
531 switch (val
& (M6811_PR1
| M6811_PR0
))
543 case M6811_PR1
| M6811_PR0
:
547 if (controller
->clock_prescaler
!= n
)
549 controller
->clock_prescaler
= n
;
550 controller
->ovf_delay
= n
* 65536;
551 m68hc11tim_timer_event (me
, (void*) (OVERFLOW_EVENT
| 0x100));
553 cpu
->ios
[base
] = val
;
554 interrupts_update_pending (&cpu
->cpu_interrupts
);
558 n
= (1 << ((val
& (M6811_RTR1
| M6811_RTR0
))));
559 cpu
->ios
[base
] = val
;
561 controller
->rti_delay
= (long) (n
) * 8192;
562 m68hc11tim_timer_event (me
, (void*) (RTI_EVENT
| 0x100));
569 val
|= cpu
->ios
[M6811_TFLG2
] & M6811_TOF
;
571 /* Clear the Real Time interrupt flag. */
572 if (val
& M6811_RTIF
)
575 val
|= cpu
->ios
[M6811_TFLG2
] & M6811_RTIF
;
577 cpu
->ios
[base
] = val
;
578 interrupts_update_pending (&cpu
->cpu_interrupts
);
586 cpu
->ios
[base
] = val
;
594 /* Re-compute the next timer compare event. */
597 m68hc11tim_timer_event (me
, (void*) (COMPARE_EVENT
));
603 const struct hw_descriptor dv_m68hc11tim_descriptor
[] = {
604 { "m68hc11tim", m68hc11tim_finish
, },