avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p);
}
+static const char * irq_names[ADC_IRQ_COUNT] = {
+ [ADC_IRQ_ADC0] = "16<adc0",
+ [ADC_IRQ_ADC1] = "16<adc1",
+ [ADC_IRQ_ADC2] = "16<adc2",
+ [ADC_IRQ_ADC3] = "16<adc3",
+ [ADC_IRQ_ADC4] = "16<adc4",
+ [ADC_IRQ_ADC5] = "16<adc5",
+ [ADC_IRQ_ADC6] = "16<adc6",
+ [ADC_IRQ_ADC7] = "16<adc7",
+ [ADC_IRQ_TEMP] = "16<temp",
+ [ADC_IRQ_IN_TRIGGER] = "<trigger_in",
+ [ADC_IRQ_OUT_TRIGGER] = ">trigger_out",
+};
+
static avr_io_t _io = {
.kind = "adc",
.reset = avr_adc_reset,
+ .irq_names = irq_names,
};
void avr_adc_init(avr_t * avr, avr_adc_t * p)
};
// Get the internal IRQ corresponding to the INT
-#define AVR_IOCTL_ADC_GETIRQ AVR_IOCTL_DEF('a','d','c','i')
+#define AVR_IOCTL_ADC_GETIRQ AVR_IOCTL_DEF('a','d','c',' ')
/*
* Definition of a ADC mux mode.
}
}
+static const char * irq_names[EXTINT_COUNT] = {
+ [EXTINT_IRQ_OUT_INT0] = "<int0",
+ [EXTINT_IRQ_OUT_INT1] = "<int1",
+ [EXTINT_IRQ_OUT_INT2] = "<int2",
+ [EXTINT_IRQ_OUT_INT3] = "<int3",
+ [EXTINT_IRQ_OUT_INT4] = "<int4",
+ [EXTINT_IRQ_OUT_INT5] = "<int5",
+ [EXTINT_IRQ_OUT_INT6] = "<int6",
+ [EXTINT_IRQ_OUT_INT7] = "<int7",
+};
+
static avr_io_t _io = {
.kind = "extint",
.reset = avr_extint_reset,
+ .irq_names = irq_names,
};
void avr_extint_init(avr_t * avr, avr_extint_t * p)
};
// Get the internal IRQ corresponding to the INT
-#define AVR_IOCTL_EXTINT_GETIRQ() AVR_IOCTL_DEF('e','x','t','i')
+#define AVR_IOCTL_EXTINT_GETIRQ() AVR_IOCTL_DEF('i','n','t',' ')
/*
* This module is just a "relay" for the pin change IRQ in the IO port
return res;
}
+static const char * irq_names[IOPORT_IRQ_COUNT] = {
+ [IOPORT_IRQ_PIN0] = "=pin0",
+ [IOPORT_IRQ_PIN1] = "=pin1",
+ [IOPORT_IRQ_PIN2] = "=pin2",
+ [IOPORT_IRQ_PIN3] = "=pin3",
+ [IOPORT_IRQ_PIN4] = "=pin4",
+ [IOPORT_IRQ_PIN5] = "=pin5",
+ [IOPORT_IRQ_PIN6] = "=pin6",
+ [IOPORT_IRQ_PIN7] = "=pin7",
+ [IOPORT_IRQ_PIN_ALL] = "=all",
+ [IOPORT_IRQ_DIRECTION_ALL] = ">ddr",
+};
+
static avr_io_t _io = {
- .kind = "io",
+ .kind = "port",
.reset = avr_ioport_reset,
.ioctl = avr_ioport_ioctl,
+ .irq_names = irq_names,
};
void avr_ioport_init(avr_t * avr, avr_ioport_t * p)
avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
}
+static const char * irq_names[SPI_IRQ_COUNT] = {
+ [SPI_IRQ_INPUT] = "8<in",
+ [SPI_IRQ_OUTPUT] = "8<out",
+};
+
static avr_io_t _io = {
.kind = "spi",
.reset = avr_spi_reset,
+ .irq_names = irq_names,
};
void avr_spi_init(avr_t * avr, avr_spi_t * p)
}
+static const char * irq_names[TIMER_IRQ_COUNT] = {
+ [TIMER_IRQ_OUT_PWM0] = "8>pwm0",
+ [TIMER_IRQ_OUT_PWM1] = "8>pwm1",
+ [TIMER_IRQ_OUT_COMP + 0] = ">compa",
+ [TIMER_IRQ_OUT_COMP + 1] = ">compb",
+ [TIMER_IRQ_OUT_COMP + 2] = ">compc",
+};
+
static avr_io_t _io = {
.kind = "timer",
.reset = avr_timer_reset,
+ .irq_names = irq_names,
};
void avr_timer_init(avr_t * avr, avr_timer_t * p)
return res;
}
+static const char * irq_names[UART_IRQ_COUNT] = {
+ [UART_IRQ_INPUT] = "8<in",
+ [UART_IRQ_OUTPUT] = "8>out",
+ [UART_IRQ_OUT_XON] = ">xon",
+ [UART_IRQ_OUT_XOFF] = ">xoff",
+};
+
static avr_io_t _io = {
.kind = "uart",
.reset = avr_uart_reset,
.ioctl = avr_uart_ioctl,
+ .irq_names = irq_names,
};
void avr_uart_init(avr_t * avr, avr_uart_t * p)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "sim_io.h"
int
{
avr_io_addr_t a = AVR_DATA_TO_IO(addr);
if (avr->io[a].irq == NULL) {
- avr->io[a].irq = avr_alloc_irq(&avr->irq_pool, 0, 9, NULL /* TODO: names*/);
+ avr->io[a].irq = avr_alloc_irq(&avr->irq_pool, 0, 9, NULL);
// mark the pin ones as filtered, so they only are raised when changing
for (int i = 0; i < 8; i++)
avr->io[a].irq[i].flags |= IRQ_FLAG_FILTERED;
avr_io_t * io,
uint32_t ctl,
int count,
- avr_irq_t * irqs)
+ avr_irq_t * irqs )
{
// allocate this module's IRQ
io->irq_count = count;
- io->irq = irqs ? irqs :
- avr_alloc_irq(&io->avr->irq_pool, 0,
- count, NULL /* TODO: names*/);
+
+ if (!irqs) {
+ const char ** irq_names = NULL;
+
+ if (io->irq_names) {
+ irq_names = malloc(count * sizeof(char*));
+ memset(irq_names, 0, count * sizeof(char*));
+ char buf[64];
+ for (int i = 0; i < count; i++) {
+ /*
+ * this bit takes the io module 'kind' ("port")
+ * the IRQ name ("=0") and the last character of the ioctl ('p','o','r','A')
+ * to create a full name "=porta.0"
+ */
+ char * dst = buf;
+ // copy the 'flags' of the name out
+ const char * kind = io->irq_names[i];
+ while (!isalpha(*kind))
+ *dst++ = *kind++;
+ // add avr name
+// strcpy(dst, io->avr->mmcu);
+ strcpy(dst, "avr");
+ dst += strlen(dst);
+ *dst ++ = '.';
+ // add module 'kind'
+ strcpy(dst, io->kind);
+ dst += strlen(dst);
+ // add port name, if any
+ if ((ctl & 0xff) > ' ')
+ *dst ++ = tolower(ctl & 0xff);
+ *dst ++ = '.';
+ // add the rest of the irq name
+ strcpy(dst, kind);
+ dst += strlen(dst);
+ *dst = 0;
+
+// printf("%s\n", buf);
+ irq_names[i] = strdup(buf);
+ }
+ }
+ irqs = avr_alloc_irq(&io->avr->irq_pool, 0,
+ count, irq_names);
+ if (irq_names) {
+ for (int i = 0; i < count; i++)
+ free((char*)irq_names[i]);
+ free((char*)irq_names);
+ }
+ }
+
+ io->irq = irqs;
io->irq_ioctl_get = ctl;
return io->irq;
}
avr_t * avr; // avr we are attached to
const char * kind; // pretty name, for debug
+ const char ** irq_names; // IRQ names
+
uint32_t irq_ioctl_get; // used to get irqs from this module
int irq_count; // number of (optional) irqs
struct avr_irq_t * irq; // optional external IRQs
avr_io_t * io,
uint32_t ctl,
int count,
- avr_irq_t * irqs);
+ avr_irq_t * irqs );
// register a callback for when IO register "addr" is read
void
void * param; // "notify" parameter
} avr_irq_hook_t;
+static void
+_avr_irq_pool_add(
+ avr_irq_pool_t * pool,
+ avr_irq_t * irq)
+{
+ if ((pool->count & 0xf) == 0) {
+ pool->irq = (avr_irq_t**)realloc(pool->irq,
+ (pool->count + 16) * sizeof(avr_irq_t *));
+ }
+ pool->irq[pool->count++] = irq;
+ irq->pool = pool;
+}
+
+static void
+_avr_irq_pool_remove(
+ avr_irq_pool_t * pool,
+ avr_irq_t * irq)
+{
+ for (int i = 0; i < pool->count; i++)
+ if (pool->irq[i] == irq) {
+ pool->irq[i] = 0;
+ return;
+ }
+}
+
void
avr_init_irq(
avr_irq_pool_t * pool,
for (int i = 0; i < count; i++) {
irq[i].irq = base + i;
+ if (pool)
+ _avr_irq_pool_add(pool, &irq[i]);
+ if (names && names[i])
+ irq[i].name = strdup(names[i]);
}
}
if (!irq || !count)
return;
for (int i = 0; i < count; i++) {
+ avr_irq_t * iq = irq + i;
+ if (iq->pool)
+ _avr_irq_pool_remove(iq->pool, iq);
+ if (iq->name)
+ free((char*)iq->name);
+ iq->name = NULL;
// purge hooks
- avr_irq_hook_t *hook = irq->hook;
+ avr_irq_hook_t *hook = iq->hook;
while (hook) {
avr_irq_hook_t * next = hook->next;
free(hook);
hook = next;
}
- irq->hook = NULL;
+ iq->hook = NULL;
}
// if that irq list was allocated by us, free it
if (irq->flags & IRQ_FLAG_ALLOC)