4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr 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 version 3 of the License, or
11 (at your option) any later version.
13 simavr 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 simavr. If not, see <http://www.gnu.org/licenses/>.
25 #include "avr_watchdog.h"
27 static avr_cycle_count_t avr_watchdog_timer(struct avr_t * avr, avr_cycle_count_t when, void * param)
29 avr_watchdog_t * p = (avr_watchdog_t *)param;
31 printf("WATCHDOG timer fired.\n");
32 avr_raise_interrupt(avr, &p->watchdog);
34 if (!avr_regbit_get(avr, p->watchdog.enable)) {
35 printf("WATCHDOG timer fired and interrupt is not enabled. Quitting\n");
36 avr_sadly_crashed(avr, 10);
42 static avr_cycle_count_t avr_wdce_clear(struct avr_t * avr, avr_cycle_count_t when, void * param)
44 avr_watchdog_t * p = (avr_watchdog_t *)param;
45 avr_regbit_clear(p->io.avr, p->wdce);
49 static void avr_watchdog_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
51 avr_watchdog_t * p = (avr_watchdog_t *)param;
52 // backup the registers
53 // uint8_t wd = avr->data[p->wdce.reg];
54 uint8_t wdce_o = avr_regbit_get(avr, p->wdce); // old
55 uint8_t wde_o = avr_regbit_get(avr, p->wde);
58 // printf("avr_watchdog_write %02x\n", v);
59 for (int i = 0; i < 4; i++)
60 wdp_o[i] = avr_regbit_get(avr, p->wdp[i]);
62 avr->data[p->wdce.reg] = v;
63 uint8_t wdce_n = avr_regbit_get(avr, p->wdce); // new
65 if (wdce_o /* || wdce_n */) {
66 // make sure bit gets reset eventually
68 avr_cycle_timer_register(avr, 4, avr_wdce_clear, p);
70 uint8_t wdp = avr_regbit_get_array(avr, p->wdp, 4);
71 p->cycle_count = 2048 << wdp;
72 p->cycle_count = (p->cycle_count * avr->frequency) / 128000;
73 if (avr_regbit_get(avr, p->wde)) {
74 printf("Watchdog reset to %d cycles @ 128kz (* %d) = %d CPU cycles)\n", 2048 << wdp, 1 << wdp, (int)p->cycle_count);
75 avr_cycle_timer_register(avr, p->cycle_count, avr_watchdog_timer, p);
77 printf("Watchdog disabled\n");
78 avr_cycle_timer_cancel(avr, avr_watchdog_timer, p);
82 avr_regbit_setto(avr, p->wde, wde_o);
83 for (int i = 0; i < 4; i++)
84 avr_regbit_setto(avr, p->wdp[i], wdp_o[i]);
85 v = avr->data[p->wdce.reg];
87 avr_core_watch_write(avr, addr, v);
91 * called by the core when a WTD instruction is found
93 static int avr_watchdog_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
95 avr_watchdog_t * p = (avr_watchdog_t *)port;
98 if (ctl == AVR_IOCTL_WATCHDOG_RESET) {
99 if (avr_regbit_get(p->io.avr, p->wde))
100 avr_cycle_timer_register(p->io.avr, p->cycle_count, avr_watchdog_timer, p);
107 static void avr_watchdog_reset(avr_io_t * port)
109 // avr_watchdog_t * p = (avr_watchdog_t *)port;
113 static avr_io_t _io = {
115 .reset = avr_watchdog_reset,
116 .ioctl = avr_watchdog_ioctl,
119 void avr_watchdog_init(avr_t * avr, avr_watchdog_t * p)
123 avr_register_io(avr, &p->io);
124 avr_register_vector(avr, &p->watchdog);
126 avr_register_io_write(avr, p->wdce.reg, avr_watchdog_write, p);