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
), M6811_IO_LEVEL
, 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 set_hw_data (me
, controller
);
120 set_hw_io_read_buffer (me
, m68hc11tim_io_read_buffer
);
121 set_hw_io_write_buffer (me
, m68hc11tim_io_write_buffer
);
122 set_hw_ports (me
, m68hc11tim_ports
);
123 set_hw_port_event (me
, m68hc11tim_port_event
);
125 set_hw_ioctl (me
, m68hc11tim_ioctl
);
127 me
->to_ioctl
= m68hc11tim_ioctl
;
130 /* Preset defaults. */
131 controller
->clock_prescaler
= 1;
132 controller
->tcnt_adjust
= 0;
134 /* Attach ourself to our parent bus. */
135 attach_m68hc11tim_regs (me
, controller
);
140 /* An event arrives on an interrupt port. */
143 m68hc11tim_port_event (struct hw
*me
,
150 struct m68hc11tim
*controller
;
154 controller
= hw_data (me
);
156 cpu
= STATE_CPU (sd
, 0);
161 HW_TRACE ((me
, "Timer reset"));
163 /* Cancel all timer events. */
164 if (controller
->rti_timer_event
)
166 hw_event_queue_deschedule (me
, controller
->rti_timer_event
);
167 controller
->rti_timer_event
= 0;
169 if (controller
->cop_timer_event
)
171 hw_event_queue_deschedule (me
, controller
->cop_timer_event
);
172 controller
->cop_timer_event
= 0;
174 if (controller
->tof_timer_event
)
176 hw_event_queue_deschedule (me
, controller
->tof_timer_event
);
177 controller
->tof_timer_event
= 0;
179 if (controller
->cmp_timer_event
)
181 hw_event_queue_deschedule (me
, controller
->cmp_timer_event
);
182 controller
->cmp_timer_event
= 0;
185 /* Reset the state of Timer registers. This also restarts
186 the timer events (overflow and RTI clock). */
188 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
189 (unsigned_word
) M6811_TMSK2
, 1);
190 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
191 (unsigned_word
) M6811_TFLG2
, 1);
192 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
193 (unsigned_word
) M6811_PACTL
, 1);
198 hw_abort (me
, "Event on unknown port %d", my_port
);
212 m68hc11tim_timer_event (struct hw
*me
, void *data
)
215 struct m68hc11tim
*controller
;
217 enum event_type type
;
219 struct hw_event
**eventp
;
220 int check_interrupt
= 0;
226 controller
= hw_data (me
);
228 cpu
= STATE_CPU (sd
, 0);
229 type
= (enum event_type
) ((long) data
) & 0x0FF;
235 eventp
= &controller
->cop_timer_event
;
236 delay
= controller
->cop_delay
;
241 eventp
= &controller
->rti_timer_event
;
242 delay
= controller
->rti_delay
;
243 if (((long) (data
) & 0x0100) == 0)
245 cpu
->ios
[M6811_TFLG2
] |= M6811_RTIF
;
251 eventp
= &controller
->tof_timer_event
;
252 delay
= controller
->ovf_delay
;
253 cpu
->ios
[M6811_TFLG2
] |= M6811_TOF
;
257 eventp
= &controller
->cmp_timer_event
;
259 /* Get current free running counter. */
260 tcnt
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
261 / controller
->clock_prescaler
);
264 flags
= cpu
->ios
[M6811_TMSK1
];
268 /* Scan each output compare register to see if one matches
269 the free running counter. Set the corresponding OCi flag
270 if the output compare is enabled. */
271 for (i
= M6811_TOC1
; i
<= M6811_TOC5
; i
+= 2, mask
>>= 1)
273 unsigned short compare
;
275 compare
= (cpu
->ios
[i
] << 8) + cpu
->ios
[i
+1];
276 if (compare
== tcnt
&& (flags
& mask
))
278 cpu
->ios
[M6811_TFLG1
] |= mask
;
282 /* Compute how many times for the next match. */
284 compare
= compare
- tcnt
;
286 compare
= compare
- tcnt
+ 65536;
291 delay
= delay
* controller
->clock_prescaler
;
293 /* Deactivate the compare timer if no output compare is enabled. */
294 if ((flags
& 0xF0) == 0)
305 hw_event_queue_deschedule (me
, *eventp
);
311 *eventp
= hw_event_queue_schedule (me
, delay
,
312 m68hc11tim_timer_event
,
317 interrupts_update_pending (&cpu
->cpu_interrupts
);
321 /* Descriptions of the Timer I/O ports. These descriptions are only used to
322 give information of the Timer device under GDB. */
323 io_reg_desc tmsk2_desc
[] = {
324 { M6811_TOI
, "TOI ", "Timer Overflow Interrupt Enable" },
325 { M6811_RTII
, "RTII ", "RTI Interrupt Enable" },
326 { M6811_PAOVI
, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
327 { M6811_PAII
, "PAII ", "Pulse Accumulator Interrupt Enable" },
328 { M6811_PR1
, "PR1 ", "Timer prescaler (PR1)" },
329 { M6811_PR0
, "PR0 ", "Timer prescaler (PR0)" },
330 { M6811_TPR_1
, "TPR_1 ", "Timer prescaler div 1" },
331 { M6811_TPR_4
, "TPR_4 ", "Timer prescaler div 4" },
332 { M6811_TPR_8
, "TPR_8 ", "Timer prescaler div 8" },
333 { M6811_TPR_16
, "TPR_16", "Timer prescaler div 16" },
337 io_reg_desc tflg2_desc
[] = {
338 { M6811_TOF
, "TOF ", "Timer Overflow Bit" },
339 { M6811_RTIF
, "RTIF ", "Read Time Interrupt Flag" },
340 { M6811_PAOVF
, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
341 { M6811_PAIF
, "PAIF ", "Pulse Accumulator Input Edge" },
345 io_reg_desc pactl_desc
[] = {
346 { M6811_DDRA7
, "DDRA7 ", "Data Direction for Port A bit-7" },
347 { M6811_PAEN
, "PAEN ", "Pulse Accumulator System Enable" },
348 { M6811_PAMOD
, "PAMOD ", "Pulse Accumulator Mode" },
349 { M6811_PEDGE
, "PEDGE ", "Pulse Accumulator Edge Control" },
350 { M6811_RTR1
, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
351 { M6811_RTR0
, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
356 to_realtime (sim_cpu
*cpu
, signed64 t
)
358 return (double) (t
) / (double) (cpu
->cpu_frequency
/ 4);
362 m68hc11tim_print_timer (struct hw
*me
, const char *name
,
363 struct hw_event
*event
)
370 sim_io_printf (sd
, " No %s interrupt will be raised.\n", name
);
378 cpu
= STATE_CPU (sd
, 0);
380 t
= hw_event_remain_time (me
, event
);
381 dt
= to_realtime (cpu
, t
) * 1000.0;
382 sim_io_printf (sd
, " Next %s interrupt in %ld cycles (%3.3f ms)\n",
388 m68hc11tim_info (struct hw
*me
)
393 struct m68hc11tim
*controller
;
397 cpu
= STATE_CPU (sd
, 0);
398 controller
= hw_data (me
);
400 sim_io_printf (sd
, "M68HC11 Timer:\n");
402 base
= cpu_get_io_base (cpu
);
404 val
= cpu
->ios
[M6811_TMSK2
];
405 print_io_byte (sd
, "TMSK2 ", tmsk2_desc
, val
, base
+ M6811_TMSK2
);
406 sim_io_printf (sd
, "\n");
408 val
= cpu
->ios
[M6811_TFLG2
];
409 print_io_byte (sd
, "TFLG2", tflg2_desc
, val
, base
+ M6811_TFLG2
);
410 sim_io_printf (sd
, "\n");
412 val
= cpu
->ios
[M6811_PACTL
];
413 print_io_byte (sd
, "PACTL", pactl_desc
, val
, base
+ M6811_PACTL
);
414 sim_io_printf (sd
, "\n");
416 /* Give info about the next timer interrupts. */
417 m68hc11tim_print_timer (me
, "RTI", controller
->rti_timer_event
);
418 m68hc11tim_print_timer (me
, "COP", controller
->cop_timer_event
);
419 m68hc11tim_print_timer (me
, "OVERFLOW", controller
->tof_timer_event
);
420 m68hc11tim_print_timer (me
, "COMPARE", controller
->cmp_timer_event
);
424 m68hc11tim_ioctl (struct hw
*me
,
425 hw_ioctl_request request
,
428 m68hc11tim_info (me
);
432 /* generic read/write */
435 m68hc11tim_io_read_buffer (struct hw
*me
,
442 struct m68hc11tim
*controller
;
446 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
449 cpu
= STATE_CPU (sd
, 0);
450 controller
= hw_data (me
);
454 /* The cpu_absolute_cycle is updated after each instruction.
455 Reading in a 16-bit register will be split in two accesses
456 but this will be atomic within the simulator. */
458 val
= (uint8
) ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
459 / (controller
->clock_prescaler
* 256));
463 val
= (uint8
) ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
464 / controller
->clock_prescaler
);
468 val
= cpu
->ios
[base
];
471 *((unsigned8
*) dest
) = val
;
476 m68hc11tim_io_write_buffer (struct hw
*me
,
483 struct m68hc11tim
*controller
;
487 int reset_compare
= 0;
489 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
492 cpu
= STATE_CPU (sd
, 0);
493 controller
= hw_data (me
);
495 val
= *((const unsigned8
*) source
);
498 /* Set the timer counter low part, trying to preserve the low part.
499 We compute the absolute cycle adjustment that we have to apply
500 to obtain the timer current value. Computation must be made
501 in 64-bit to avoid overflow problems. */
503 adj
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
504 / (controller
->clock_prescaler
* (signed64
) 256)) & 0x0FF;
505 adj
= cpu
->cpu_absolute_cycle
506 - (adj
* controller
->clock_prescaler
* (signed64
) 256)
507 - ((signed64
) adj
* controller
->clock_prescaler
);
508 controller
->tcnt_adjust
= adj
;
513 adj
= ((cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
514 / controller
->clock_prescaler
) & 0x0ff;
515 adj
= cpu
->cpu_absolute_cycle
516 - ((signed64
) val
* controller
->clock_prescaler
* (signed64
) 256)
517 - (adj
* controller
->clock_prescaler
);
518 controller
->tcnt_adjust
= adj
;
524 /* Timer prescaler cannot be changed after 64 bus cycles. */
525 if (cpu
->cpu_absolute_cycle
>= 64)
527 val
&= ~(M6811_PR1
| M6811_PR0
);
528 val
|= cpu
->ios
[M6811_TMSK2
] & (M6811_PR1
| M6811_PR0
);
530 switch (val
& (M6811_PR1
| M6811_PR0
))
542 case M6811_PR1
| M6811_PR0
:
546 if (controller
->clock_prescaler
!= n
)
548 controller
->clock_prescaler
= n
;
549 controller
->ovf_delay
= n
* 65536;
550 m68hc11tim_timer_event (me
, (void*) (OVERFLOW_EVENT
| 0x100));
552 cpu
->ios
[base
] = val
;
553 interrupts_update_pending (&cpu
->cpu_interrupts
);
557 n
= (1 << ((val
& (M6811_RTR1
| M6811_RTR0
))));
558 cpu
->ios
[base
] = val
;
560 controller
->rti_delay
= (long) (n
) * 8192;
561 m68hc11tim_timer_event (me
, (void*) (RTI_EVENT
| 0x100));
568 val
|= cpu
->ios
[M6811_TFLG2
] & M6811_TOF
;
570 /* Clear the Real Time interrupt flag. */
571 if (val
& M6811_RTIF
)
574 val
|= cpu
->ios
[M6811_TFLG2
] & M6811_RTIF
;
576 cpu
->ios
[base
] = val
;
577 interrupts_update_pending (&cpu
->cpu_interrupts
);
585 cpu
->ios
[base
] = val
;
593 /* Re-compute the next timer compare event. */
596 m68hc11tim_timer_event (me
, (void*) (COMPARE_EVENT
));
602 const struct hw_descriptor dv_m68hc11tim_descriptor
[] = {
603 { "m68hc11tim", m68hc11tim_finish
, },