} else {
// Set the real PIN bit. Ignore DDR as it's masked when read.
- avr->data[p->r_pin] &= ~mask;
- if (value)
- avr->data[p->r_pin] |= mask;
+ avr_core_watch_write(avr, p->r_pin,
+ (avr->data[p->r_pin] & ~mask) |
+ (value ? mask : 0));
/* BUG: If DDR bit is set here, there should be no
* interrupt. But a spurious IRQ call by the user
return(avr->flash[addr] | (avr->flash[addr + 1] << 8));
}
+static inline void _call_register_irqs(avr_t * avr, uint16_t addr)
+{
+ if (addr > 31 && addr < 31 + MAX_IOs) {
+ avr_io_addr_t io = AVR_DATA_TO_IO(addr);
+
+ if (avr->io[io].irq) {
+ uint8_t v = avr->data[addr];
+ avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
+ for (int i = 0; i < 8; i++)
+ avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);
+ }
+ }
+}
+
void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v)
{
if (addr > avr->ramend) {
}
avr->data[addr] = v;
+ _call_register_irqs(avr, addr);
}
uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr)
avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_READ);
}
+// _call_register_irqs(avr, addr);
return avr->data[addr];
}
}
if (r > 31) {
avr_io_addr_t io = AVR_DATA_TO_IO(r);
- if (avr->io[io].w.c)
+ if (avr->io[io].w.c) {
avr->io[io].w.c(avr, r, v, avr->io[io].w.param);
- else
+ } else {
avr->data[r] = v;
- if (avr->io[io].irq) {
- avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
- for (int i = 0; i < 8; i++)
- avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);
+ if (avr->io[io].irq) {
+ avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
+ for (int i = 0; i < 8; i++)
+ avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);
+ }
}
} else
avr->data[r] = v;
if (avr->io[io].r.c)
avr->data[addr] = avr->io[io].r.c(avr, addr, avr->io[io].r.param);
-
+#if 0
if (avr->io[io].irq) {
uint8_t v = avr->data[addr];
avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
for (int i = 0; i < 8; i++)
avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);
}
+#endif
}
return avr_core_watch_read(avr, addr);
}
#include "tests.h"
#include "avr_ioport.h"
+#define DDRB_ADDR (0x4 + 32) // From ATM168 header file.
+
/* Start of the IOPORT's IRQ list. */
static avr_irq_t *base_irq;
LOG("5-%02X ", value);
}
+/* IRQ call-back for changes to the simulated DDRB register.
+ * This is to test an IRQ returned by avr_iomem_getirq() and not really
+ * specifically for GPIO.
+ */
+
+static void monitor_ddrb(struct avr_irq_t *irq, uint32_t value, void *param)
+{
+ LOG("BD-%02X ", value);
+}
+
/* This monitors the simulator's idea of the I/O pin states.
* Changes this program makes to inputs are not reported,
* presumably because the simulator "knows" we made them.
/* This string is expected in variable log. */
static const char *log_expected =
- "d-0F P-00 o-0A P-0A I-0A 5-01 o-09 P-29 d-3C 5-00 P-09 o-F0 5-01 P-F0 "
- "I-70 " // Interrupts off testing.
+ "BD-01 d-0F P-00 o-0A P-0A I-0A 5-01 o-09 P-29 d-3C 5-00 P-09 o-F0 5-01 "
+ "P-F0 I-70 " // Interrupts off testing.
"o-E0 P-E0 I-E0 I-E0 " // External interrupt test.
- "d-03 o-01 P-E1 o-03 P-E3 o-00 P-E8 I-E8 "; // Pin change interrupt test.
+ "d-03 o-01 P-E1 o-03 P-E3 o-00 P-E8 I-E8 " // Pin change interrupt test.
+ "BD-FF "; // iomem IRQ test.
int main(int argc, char **argv) {
monitor_5, NULL);
avr_irq_register_notify(base_irq + IOPORT_IRQ_PIN_ALL,
monitor, NULL);
+ avr_irq_register_notify(avr_iomem_getirq(avr, DDRB_ADDR, NULL, 8),
+ monitor_ddrb, NULL);
avr_irq_register_notify(base_irq + IOPORT_IRQ_DIRECTION_ALL,
reg_write, NULL);
avr_irq_register_notify(base_irq + IOPORT_IRQ_REG_PORT,
avr_irq_register_notify(base_irq + IOPORT_IRQ_REG_PIN,
reg_read, NULL);
+ /* Tweak DDRB to confirm IO-memory based IRQs are working. */
+
+ avr_core_watch_write(avr, DDRB_ADDR, 1);
+
+ /* Run ... */
+
tests_assert_uart_receive_avr(avr, 100000, expected, '0');
if (strcmp(log, log_expected))