Beispiel #1
0
static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
{
	avr_extint_t * p = (avr_extint_t *)param;
	avr_t * avr = p->io.avr;

	uint8_t mode = avr_regbit_get_array(avr, p->eint[irq->irq].isc, 2);
	int up = !irq->value && value;
	int down = irq->value && !value;
	switch (mode) {
		case 0:
			// unsupported
			break;
		case 1:
			if (up || down)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
		case 2:
			if (down)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
		case 3:
			if (up)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
	}
}
Beispiel #2
0
static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
{
	avr_extint_t * p = (avr_extint_t *)param;
	avr_t * avr = p->io.avr;

	int up = !irq->value && value;
	int down = irq->value && !value;

	uint8_t isc_bits = p->eint[irq->irq + 1].isc->reg ? 2 : 1;
	uint8_t mode = avr_regbit_get_array(avr, p->eint[irq->irq].isc, isc_bits);

	// Asynchronous interrupts, eg int2 in m16, m32 etc. support only down/up
	if (isc_bits == 1)
		mode +=2;

	switch (mode) {
		case 0:
			// unsupported
			break;
		case 1:
			if (up || down)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
		case 2:
			if (down)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
		case 3:
			if (up)
				avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
			break;
	}
}
Beispiel #3
0
static avr_cycle_count_t avr_uart_txc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	if (avr_regbit_get(avr, p->txen)) {
		// if the interrupts are not used, still raise the UDRE and TXC flag
		avr_raise_interrupt(avr, &p->udrc);
		avr_raise_interrupt(avr, &p->txc);
	}
	return 0;
}
Beispiel #4
0
// timer overflow
static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	int start = p->tov_base == 0;

	if (!start)
		avr_raise_interrupt(avr, &p->overflow);
	p->tov_base = when;

	static const avr_cycle_timer_t dispatch[AVR_TIMER_COMP_COUNT] =
		{ avr_timer_compa, avr_timer_compb, avr_timer_compc };

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
		if (p->comp[compi].comp_cycles) {
			if (p->comp[compi].comp_cycles < p->tov_cycles)
				avr_cycle_timer_register(avr,
					p->comp[compi].comp_cycles,
					dispatch[compi], p);
			else if (p->tov_cycles == p->comp[compi].comp_cycles && !start)
				dispatch[compi](avr, when, param);
		}
	}

	return when + p->tov_cycles;
}
Beispiel #5
0
static avr_cycle_count_t avr_timer_comp(avr_timer_t *p, avr_cycle_count_t when, uint8_t comp)
{
	avr_t * avr = p->io.avr;
	avr_raise_interrupt(avr, &p->comp[comp].interrupt);

	// check output compare mode and set/clear pins
	uint8_t mode = avr_regbit_get(avr, p->comp[comp].com);
	avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp];

	switch (mode) {
		case avr_timer_com_normal: // Normal mode OCnA disconnected
			break;
		case avr_timer_com_toggle: // Toggle OCnA on compare match
			if (p->comp[comp].com_pin.reg)	// we got a physical pin
				avr_raise_irq(irq,
						AVR_IOPORT_OUTPUT | (avr_regbit_get(avr, p->comp[comp].com_pin) ? 0 : 1));
			else // no pin, toggle the IRQ anyway
				avr_raise_irq(irq,
						p->io.irq[TIMER_IRQ_OUT_COMP + comp].value ? 0 : 1);
			break;
		case avr_timer_com_clear:
			avr_raise_irq(irq, 0);
			break;
		case avr_timer_com_set:
			avr_raise_irq(irq, 1);
			break;
	}

	return p->tov_cycles ? 0 :
				p->comp[comp].comp_cycles ?
						when + p->comp[comp].comp_cycles : 0;
}
Beispiel #6
0
static void avr_timer_irq_icp(struct avr_irq_t * irq, uint32_t value, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	avr_t * avr = p->io.avr;

	// input capture disabled when ICR is used as top
	if (p->mode.top == avr_timer_wgm_reg_icr)
		return;
	int bing = 0;
	if (avr_regbit_get(avr, p->ices)) { // rising edge
		if (!irq->value && value)
			bing++;
	} else {	// default, falling edge
		if (irq->value && !value)
			bing++;
	}
	if (!bing)
		return;
	// get current TCNT, copy it to ICR, and raise interrupt
	uint16_t tcnt = _avr_timer_get_current_tcnt(p);
	avr->data[p->r_icr] = tcnt;
	if (p->r_icrh)
		avr->data[p->r_icrh] = tcnt >> 8;
	avr_raise_interrupt(avr, &p->icr);
}
Beispiel #7
0
static avr_cycle_count_t avr_uart_rxc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	if (avr_regbit_get(avr, p->rxen))
		avr_raise_interrupt(avr, &p->rxc);
	return 0;
}
Beispiel #8
0
static avr_cycle_count_t avr_watchdog_timer(
		struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_watchdog_t * p = (avr_watchdog_t *)param;

	if (avr_regbit_get(avr, p->watchdog.enable)) {
		AVR_LOG(avr, LOG_TRACE, "WATCHDOG: timer fired.\n");
		avr_raise_interrupt(avr, &p->watchdog);
		return when + p->cycle_count;
	} else if (avr_regbit_get(avr, p->wde)) {
		AVR_LOG(avr, LOG_TRACE,
				"WATCHDOG: timer fired without interrupt. Resetting\n");

		p->reset_context.avr_run = avr->run;
		p->reset_context.wdrf = 1;

		/* Ideally we would perform a reset here via 'avr_reset'
		 * However, returning after reset would result in an unconsistent state.
		 * It seems our best (and cleanest) solution is to set a temporary call 
		 * back which can safely perform the reset for us...  During reset,
		 * the previous callback can be restored and safely resume.
		 */
		avr->run = avr_watchdog_run_callback_software_reset;
	}

	return 0;
}
Beispiel #9
0
static void
raise_ep_interrupt(
    struct avr_t * avr,
    avr_usb_t * p,
    uint8_t ep,
    enum epints irq)
{
    struct _epstate * epstate = get_epstate(p, ep);
    assert(ep < num_endpoints);
    avr->data[p->r_usbcon + ueint] |= 1 << ep;
    switch (irq) {
    case txini:
    case stalledi:
    case rxouti:
    case nakouti:
    case nakini:
        epstate->ueintx.v |= 1 << irq;
        if (epstate->ueienx.v & (1 << irq))
            avr_raise_interrupt(avr, &p->state->com_vect);
        break;
    case rxstpi:
        epstate->ueintx.v |= 1 << irq;
        if (epstate->ueienx.v & (1 << irq))
            avr_raise_interrupt(avr, &p->state->com_vect);
        break;
    case overfi:
        epstate->uesta0x.overfi = 1;
        if (epstate->ueienx.flerre)
            avr_raise_interrupt(avr, &p->state->com_vect);
        break;
    case underfi:
        epstate->uesta0x.underfi = 1;
        if (epstate->ueienx.flerre)
            avr_raise_interrupt(avr, &p->state->com_vect);
        break;
    default:
        assert(0);
    }
}
Beispiel #10
0
static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
    avr_spi_t * p = (avr_spi_t *)param;

    if (avr_regbit_get(avr, p->spe)) {
        // in master mode, any byte is sent as it comes..
        if (avr_regbit_get(avr, p->mstr)) {
            avr_raise_interrupt(avr, &p->spi);
            avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
        }
    }
    return 0;
}
Beispiel #11
0
static inline void
_avr_twi_status_set(
		avr_twi_t * p,
		uint8_t v,
		int interrupt)
{
	avr_regbit_setto_raw(p->io.avr, p->twsr, v);
#if AVR_TWI_DEBUG
	AVR_TRACE(p->io.avr, "%s %02x\n", __func__, v);
#endif
	avr_raise_irq(p->io.irq + TWI_IRQ_STATUS, v);
	if (interrupt)
		avr_raise_interrupt(p->io.avr, &p->twi);
}
Beispiel #12
0
static avr_cycle_count_t avr_watchdog_timer(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_watchdog_t * p = (avr_watchdog_t *)param;

	printf("WATCHDOG timer fired.\n");
	avr_raise_interrupt(avr, &p->watchdog);

	if (!avr_regbit_get(avr, p->watchdog.enable)) {
		printf("WATCHDOG timer fired and interrupt is not enabled. Quitting\n");
		avr_sadly_crashed(avr, 10);
	}

	return 0;
}
Beispiel #13
0
static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;
	if (avr_regbit_get(avr, p->aden)) {
		// if the interrupts are not used, still raised the UDRE and TXC flag
		avr_raise_interrupt(avr, &p->adc);
		avr_regbit_clear(avr, p->adsc);
		p->first = 0;
		p->read_status = 0;
		if( p->adts_mode == avr_adts_free_running )
			avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1);
	}
	return 0;
}
Beispiel #14
0
static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
{
    avr_spi_t * p = (avr_spi_t *)param;
    avr_t * avr = p->io.avr;

    // check to see if receiver is enabled
    if (!avr_regbit_get(avr, p->spe))
        return;

    // double buffer the input.. ?
    p->input_data_register = value;
    avr_raise_interrupt(avr, &p->spi);

    // if in slave mode,
    // 'output' the byte only when we received one...
    if (!avr_regbit_get(avr, p->mstr)) {
        avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
    }
}
Beispiel #15
0
static void
raise_usb_interrupt(
    avr_usb_t * p,
    enum usbints irq)
{
    uint8_t * Rudien = &p->io.avr->data[p->r_usbcon + udien];
    uint8_t * Rudint = &p->io.avr->data[p->r_usbcon + udint];

    switch (irq) {
    case uprsmi:
    case eorsmi:
    case wakeupi:
    case eorsti:
    case sofi:
    case suspi:
        *Rudint |= 1 << irq;
        if (*Rudien & (1 << irq))
            avr_raise_interrupt(p->io.avr, &p->state->gen_vect);
        break;
    default:
        assert(0);
    }

}