示例#1
0
/*
 * check whether interrupts are pending. If so, check if the interrupt "latency" is reached,
 * and if so triggers the handlers and jump to the vector.
 */
void
avr_service_interrupts(
		avr_t * avr)
{
	if (!avr->sreg[S_I] || !avr->interrupt_state)
		return;

	if (avr->interrupt_state < 0) {
		avr->interrupt_state++;
		if (avr->interrupt_state == 0)
			avr->interrupt_state = avr_has_pending_interrupts(avr);
		return;
	}

	avr_int_table_p table = &avr->interrupts;

	// how many are pending...
	int cnt = avr_int_pending_get_read_size(&table->pending);
	// locate the highest priority one
	int min = 0xff;
	int mini = 0;
	for (int ii = 0; ii < cnt; ii++) {
		avr_int_vector_t * v = avr_int_pending_read_at(&table->pending, ii);
		if (v->vector < min) {
			min = v->vector;
			mini = ii;
		}
	}
	avr_int_vector_t * vector = avr_int_pending_read_at(&table->pending, mini);

	// now move the one at the front of the fifo in the slot of
	// the one we service
	table->pending.buffer[(table->pending.read + mini) % avr_int_pending_fifo_size] =
			avr_int_pending_read(&table->pending);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));

	// if that single interrupt is masked, ignore it and continue
	// could also have been disabled, or cleared
	if (!avr_regbit_get(avr, vector->enable) || !vector->pending) {
		vector->pending = 0;
		avr->interrupt_state = avr_has_pending_interrupts(avr);
	} else {
		if (vector && vector->trace)
			printf("%s calling %d\n", __FUNCTION__, (int)vector->vector);
		_avr_push_addr(avr, avr->pc);
		avr_sreg_set(avr, S_I, 0);
		avr->pc = vector->vector * avr->vector_size;

		avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 1);
		avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, vector->vector);
		if (table->running_ptr == ARRAY_SIZE(table->running)) {
			AVR_LOG(avr, LOG_ERROR, "%s run out of nested stack!", __func__);
		} else {
			table->running[table->running_ptr++] = vector;
		}
		avr_clear_interrupt(avr, vector);
	}
}
示例#2
0
/*
 * check whether interrupts are pending. If so, check if the interrupt "latency" is reached,
 * and if so triggers the handlers and jump to the vector.
 */
void
avr_service_interrupts(
		avr_t * avr)
{
	if (!avr->sreg[S_I])
		return;

	if (avr->interrupt_state) {
		if (avr->interrupt_state < 0) {
			avr->interrupt_state++;
			if (avr->interrupt_state == 0)
				avr->interrupt_state = avr_has_pending_interrupts(avr);
			return;
		}
	} else
		return;

	avr_int_table_p table = &avr->interrupts;

	// how many are pending...
	int cnt = table->pending_w > table->pending_r ?
			table->pending_w - table->pending_r :
			(table->pending_w + INT_FIFO_SIZE) - table->pending_r;
	// locate the highest priority one
	int min = 0xff;
	int mini = 0;
	for (int ii = 0; ii < cnt; ii++) {
		int vi = INT_FIFO_MOD(table->pending_r + ii);
		avr_int_vector_t * v = table->pending[vi];
		if (v->vector < min) {
			min = v->vector;
			mini = vi;
		}
	}
	avr_int_vector_t * vector = table->pending[mini];

	// now move the one at the front of the fifo in the slot of
	// the one we service
	table->pending[mini] = table->pending[table->pending_r++];
	table->pending_r = INT_FIFO_MOD(table->pending_r);

	// if that single interrupt is masked, ignore it and continue
	// could also have been disabled, or cleared
	if (!avr_regbit_get(avr, vector->enable) || !vector->pending) {
		vector->pending = 0;
		avr->interrupt_state = avr_has_pending_interrupts(avr);
	} else {
		if (vector && vector->trace)
			printf("%s calling %d\n", __FUNCTION__, (int)vector->vector);
		_avr_push_addr(avr, avr->pc);
		avr_sreg_set(avr, S_I, 0);
		avr->pc = vector->vector * avr->vector_size;

		avr_clear_interrupt(avr, vector);
	}
}
示例#3
0
/* this is called uppon RETI. */
void
avr_interrupt_reti(
		struct avr_t * avr)
{
	avr_int_table_p table = &avr->interrupts;
	if (table->running_ptr) {
		avr_int_vector_t * vector = table->running[--table->running_ptr];
		avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 0);
	}
	avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING,
			table->running_ptr > 0 ?
					table->running[table->running_ptr-1]->vector : 0);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));
}
示例#4
0
int
avr_clear_interrupt_if(
		avr_t * avr,
		avr_int_vector_t * vector,
		uint8_t old)
{
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));
	if (avr_regbit_get(avr, vector->raised)) {
		avr_clear_interrupt(avr, vector);
		return 1;
	}
	avr_regbit_setto(avr, vector->raised, old);
	return 0;
}
示例#5
0
void
avr_clear_interrupt(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	if (!vector)
		return;
	if (vector->trace)
		printf("%s cleared %d\n", __FUNCTION__, vector->vector);
	vector->pending = 0;

	avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 0);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));

	if (vector->raised.reg && !vector->raise_sticky)
		avr_regbit_clear(avr, vector->raised);
}