Ejemplo n.º 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);
	}
}
Ejemplo n.º 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);
	}
}