Ejemplo n.º 1
0
/*
 * write to the TIFR register. Watch for code that writes "1" to clear
 * pending interrupts.
 */
static void
avr_timer_write_pending(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	// save old bits values
	uint8_t ov = avr_regbit_get(avr, p->overflow.raised);
	uint8_t ic = avr_regbit_get(avr, p->icr.raised);
	uint8_t cp[AVR_TIMER_COMP_COUNT];

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
		cp[compi] = avr_regbit_get(avr, p->comp[compi].interrupt.raised);

	// write the value
	avr_core_watch_write(avr, addr, v);

	// clear any interrupts & flags
	avr_clear_interrupt_if(avr, &p->overflow, ov);
	avr_clear_interrupt_if(avr, &p->icr, ic);

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
		avr_clear_interrupt_if(avr, &p->comp[compi].interrupt, cp[compi]);
}
Ejemplo n.º 2
0
static uint8_t avr_uart_rxc_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	uint8_t v = avr_core_watch_read(avr, addr);

	//static uint8_t old = 0xff; if (v != old) printf("UCSRA read %02x\n", v); old = v;
	//
	// if RX is enabled, and there is nothing to read, and
	// the AVR core is reading this register, it's probably
	// to poll the RXC TXC flag and spinloop
	// so here we introduce a usleep to make it a bit lighter
	// on CPU and let data arrive
	//
	uint8_t ri = !avr_regbit_get(avr, p->rxen) || !avr_regbit_get(avr, p->rxc.raised);
	uint8_t ti = !avr_regbit_get(avr, p->txen) || !avr_regbit_get(avr, p->txc.raised);

	if (p->flags & AVR_UART_FLAG_POOL_SLEEP) {

		if (ri && ti)
			usleep(1);
	}
	// if reception is idle and the fifo is empty, tell whomever there is room
	if (avr_regbit_get(avr, p->rxen) && uart_fifo_isempty(&p->input)) {
		avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0);
		avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1);
	}

	return v;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
static void
avr_adc_irq_notify(
		struct avr_irq_t * irq, uint32_t value, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;
	avr_t * avr = p->io.avr;

	switch (irq->irq) {
		case ADC_IRQ_ADC0 ... ADC_IRQ_ADC7: {
			p->adc_values[irq->irq] = value;
		} 	break;
		case ADC_IRQ_TEMP: {
			p->temp = value;
		}	break;
		case ADC_IRQ_IN_TRIGGER: {
			if (avr_regbit_get(avr, p->adate)) {
				// start a conversion only if it's not running
				// otherwise ignore the trigger
				if(!avr_regbit_get(avr, p->adsc) ) {
			  		uint8_t addr = p->adsc.reg;
					if (addr) {
						uint8_t val = avr->data[addr] | (1 << p->adsc.bit);
						// write ADSC to ADCSRA
						avr_adc_write_adcsra(avr, addr, val, param);
					}
				}
			}
		}	break;
	}
}
Ejemplo n.º 5
0
static void
avr_watchdog_set_cycle_count_and_timer (avr_t * avr, avr_watchdog_t * p, uint8_t was_enabled, int8_t old_wdp)
{
  // If nothing else, always ensure we have a valid cycle count...
  uint8_t wdp = avr_regbit_get_array (avr, p->wdp, 4);

  p->cycle_count = 2048 << wdp;
  p->cycle_count = (p->cycle_count * avr->frequency) / 128000;

  uint8_t wde = avr_regbit_get (avr, p->wde);
  uint8_t wdie = avr_regbit_get (avr, p->watchdog.enable);

  uint8_t enable_changed = (was_enabled != (wde || wdie));

  uint8_t wdp_changed = ((old_wdp >= 0) ? (wdp != old_wdp) : 0);

  if (!enable_changed && !wdp_changed)
    return;

  static char *message[2][2] = { {0, "reset"}, {"enabled", "enabled and set"} };

  if (wde || wdie)
    {
      AVR_LOG (avr, LOG_TRACE, "WATCHDOG: %s to %d cycles @ 128kz (* %d) = %d CPU cycles.\n",
               message[enable_changed][wdp_changed], 2048 << wdp, 1 << wdp, (int) p->cycle_count);

      avr_cycle_timer_register (avr, p->cycle_count, avr_watchdog_timer, p);
    }
  else if (enable_changed)
    {
      AVR_LOG (avr, LOG_TRACE, "WATCHDOG: disabled\n");
      avr_cycle_timer_cancel (avr, avr_watchdog_timer, p);
    }
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
static int avr_flash_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
{
	if (ctl != AVR_IOCTL_FLASH_SPM)
		return -1;

	avr_flash_t * p = (avr_flash_t *)port;
	avr_t * avr = p->io.avr;

	avr_flashaddr_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8);
	if (avr->rampz)
		z |= avr->data[avr->rampz] << 16;
	uint16_t r01 = avr->data[0] | (avr->data[1] << 8);

//	printf("AVR_IOCTL_FLASH_SPM %02x Z:%04x R01:%04x\n", avr->data[p->r_spm], z,r01);
	avr_cycle_timer_cancel(avr, avr_progen_clear, p);
	avr_regbit_clear(avr, p->selfprgen);
	if (avr_regbit_get(avr, p->pgers)) {
		z &= ~1;
		AVR_LOG(avr, LOG_TRACE, "FLASH: Erasing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize);
		for (int i = 0; i < p->spm_pagesize; i++)
			avr->flash[z++] = 0xff;
	} else if (avr_regbit_get(avr, p->pgwrt)) {
		z &= ~1;
		AVR_LOG(avr, LOG_TRACE, "FLASH: Writing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize);
	} else if (avr_regbit_get(avr, p->blbset)) {
		AVR_LOG(avr, LOG_TRACE, "FLASH: Setting lock bits (ignored)\n");
	} else {
		z &= ~1;
		avr->flash[z++] = r01;
		avr->flash[z] = r01 >> 8;
	}
	return 0;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
static void
avr_watchdog_write (avr_t * avr, avr_io_addr_t addr, uint8_t v, void *param)
{
  avr_watchdog_t *p = (avr_watchdog_t *) param;

  uint8_t old_wde = avr_regbit_get (avr, p->wde);
  uint8_t old_wdie = avr_regbit_get (avr, p->watchdog.enable);
  uint8_t old_wdce = avr_regbit_get (avr, p->wdce);

  uint8_t was_enabled = (old_wde || old_wdie);

  uint8_t old_v = avr->data[addr];   // allow gdb to see write...
  avr_core_watch_write (avr, addr, v);

  if (old_wdce)
    {
      uint8_t old_wdp = avr_regbit_get_array (avr, p->wdp, 4);

      // wdrf (watchdog reset flag) must be cleared before wde can be cleared.
      if (avr_regbit_get (avr, p->wdrf))
        avr_regbit_set (avr, p->wde);

      avr_watchdog_set_cycle_count_and_timer (avr, p, was_enabled, old_wdp);
    }
  else
    {
      /* easier to change only what we need rather than check and reset 
       * locked/read-only bits.
       */
      avr->data[addr] = old_v;

      uint8_t wdce_v = avr_regbit_from_value (avr, p->wdce, v);
      uint8_t wde_v = avr_regbit_from_value (avr, p->wde, v);

      if (wdce_v && wde_v)
        {
          avr_regbit_set (avr, p->wdce);

          avr_cycle_timer_register (avr, 4, avr_wdce_clear, p);
        }
      else
        {
          if (wde_v)   // wde can be set but not cleared
            avr_regbit_set (avr, p->wde);

          avr_regbit_setto_raw (avr, p->watchdog.enable, v);

          avr_watchdog_set_cycle_count_and_timer (avr, p, was_enabled, -1);
        }
    }
}
Ejemplo n.º 10
0
static void
avr_timer_write(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;

	uint8_t as2 = avr_regbit_get(avr, p->as2);
	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	avr_core_watch_write(avr, addr, v);

	uint8_t new_as2 = avr_regbit_get(avr, p->as2);
	uint8_t new_cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t new_mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	// only reconfigure the timer if "relevant" bits have changed
	// this prevent the timer reset when changing the edge detector
	// or other minor bits
	if (new_cs != cs || new_mode != mode || new_as2 != as2) {
	/* cs */
		if (new_cs == 0) {
			// cancel everything
			avr_timer_cancel_all_cycle_timers(avr, p, 1);

			AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n",
					__func__, p->name);
			return;
		}

		if (new_as2) {
			// AVR clock and external 32KHz source does not have
			// to be synced. To obtain better simulation results
			// p->tov_base type must be float or avr->frequency
			// must be multiple of 32768.
			p->cs_div_value = (uint32_t)((uint64_t)avr->frequency * (1 << p->cs_div[new_cs]) / 32768);
		} else {
			p->cs_div_value = 1 << p->cs_div[new_cs];
		}

	/* mode */
		p->mode = p->wgm_op[new_mode];
		p->wgm_op_mode_kind = p->mode.kind;
		p->wgm_op_mode_size = (1 << p->mode.size) - 1;

		avr_timer_reconfigure(p, 1);
	}
}
Ejemplo n.º 11
0
/*
 * called by the core when a WTD instruction is found
 */
static int
avr_watchdog_ioctl (struct avr_io_t *port, uint32_t ctl, void *io_param)
{
  avr_watchdog_t *p = (avr_watchdog_t *) port;
  int res = -1;

  if (ctl == AVR_IOCTL_WATCHDOG_RESET)
    {
      if (avr_regbit_get (p->io.avr, p->wde) || avr_regbit_get (p->io.avr, p->watchdog.enable))
        avr_cycle_timer_register (p->io.avr, p->cycle_count, avr_watchdog_timer, p);
      res = 0;
    }

  return res;
}
Ejemplo n.º 12
0
int
avr_is_interrupt_enabled(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	return avr_regbit_get(avr, vector->enable);
}
Ejemplo n.º 13
0
static uint8_t avr_uart_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;

	// clear the rxc bit in case the code is using polling
	avr_regbit_clear(avr, p->rxc.raised);

	if (!avr_regbit_get(avr, p->rxen)) {
		avr->data[addr] = 0;
		// made to trigger potential watchpoints
		avr_core_watch_read(avr, addr);
		return 0;
	}
	uint8_t v = uart_fifo_read(&p->input);

//	TRACE(printf("UART read %02x %s\n", v, uart_fifo_isempty(&p->input) ? "EMPTY!" : "");)
	avr->data[addr] = v;
	// made to trigger potential watchpoints
	v = avr_core_watch_read(avr, addr);

	// trigger timer if more characters are pending
	if (!uart_fifo_isempty(&p->input))
		avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p);

	return v;
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
static void
avr_twi_irq_input(
		struct avr_irq_t * irq,
		uint32_t value,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;
	avr_t * avr = p->io.avr;

	// check to see if we are enabled
	if (!avr_regbit_get(avr, p->twen))
		return;
	avr_twi_msg_irq_t msg;
	msg.u.v = value;

	// receiving an acknowledge bit
	if (msg.u.twi.msg & TWI_COND_ACK) {
#if AVR_TWI_DEBUG
		printf("I2C received ACK:%d\n", msg.u.twi.data & 1);
#endif
		if (msg.u.twi.data & 1)
			p->state |= TWI_COND_ACK;
		else
			p->state &= ~TWI_COND_ACK;
	}
	// receive a data byte from a slave
	if (msg.u.twi.msg & TWI_COND_READ) {
#if AVR_TWI_DEBUG
		printf("I2C received %02x\n", msg.u.twi.data);
#endif
		avr->data[p->r_twdr] = msg.u.twi.data;
	}
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
static void
avr_timer_comp_on_tov(
		avr_timer_t *p,
		avr_cycle_count_t when,
		uint8_t comp)
{
	avr_t * avr = p->io.avr;

	// 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
			break;
		case avr_timer_com_toggle: // toggle on compare match => on tov do nothing
			break;
		case avr_timer_com_clear: // clear on compare match => set on tov
			avr_raise_irq(irq, 1);
			break;
		case avr_timer_com_set: // set on compare match => clear on tov
			avr_raise_irq(irq, 0);
			break;
	}
}
Ejemplo n.º 18
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.º 19
0
static void avr_timer_reconfigure(avr_timer_t * p)
{
	avr_t * avr = p->io.avr;

	avr_timer_wgm_t zero={0};
	p->mode = zero;
	// cancel everything
	p->comp[AVR_TIMER_COMPA].comp_cycles = 0;
	p->comp[AVR_TIMER_COMPB].comp_cycles = 0;
	p->comp[AVR_TIMER_COMPC].comp_cycles = 0;
	p->tov_cycles = 0;
	
	avr_cycle_timer_cancel(avr, avr_timer_tov, p);
	avr_cycle_timer_cancel(avr, avr_timer_compa, p);
	avr_cycle_timer_cancel(avr, avr_timer_compb, p);
	avr_cycle_timer_cancel(avr, avr_timer_compc, p);

	long clock = avr->frequency;

	// only can exists on "asynchronous" 8 bits timers
	if (avr_regbit_get(avr, p->as2))
		clock = 32768;

	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	if (cs == 0) {
		AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", __FUNCTION__, p->name);
		return;
	}

	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
	uint8_t cs_div = p->cs_div[cs];
	uint32_t f = clock >> cs_div;

	p->mode = p->wgm_op[mode];
	//printf("%s-%c clock %d, div %d(/%d) = %d ; mode %d\n", __FUNCTION__, p->name, clock, cs, 1 << cs_div, f, mode);
	switch (p->mode.kind) {
		case avr_timer_wgm_normal:
			avr_timer_configure(p, f, (1 << p->mode.size) - 1);
			break;
		case avr_timer_wgm_fc_pwm:
			avr_timer_configure(p, f, (1 << p->mode.size) - 1);
			break;
		case avr_timer_wgm_ctc: {
			avr_timer_configure(p, f, _timer_get_ocr(p, AVR_TIMER_COMPA));
		}	break;
		case avr_timer_wgm_pwm: {
			uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p);
			avr_timer_configure(p, f, top);
		}	break;
		case avr_timer_wgm_fast_pwm:
			avr_timer_configure(p, f, (1 << p->mode.size) - 1);
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n",
					__FUNCTION__, p->name, mode, p->mode.kind);
	}	
}
Ejemplo n.º 20
0
/*
 * prevent code from rewriting out status bits, since we actualy use them!
 */
static void
avr_twi_write_status(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;
	uint8_t sr = avr_regbit_get(avr, p->twsr);
	uint8_t c = avr_regbit_get(avr, p->twps);

	avr_core_watch_write(avr, addr, v);
	avr_regbit_setto(avr, p->twsr, sr);	// force restore

	if (c != avr_regbit_get(avr, p->twps)) {
		// prescaler bits changed...
	}
}
Ejemplo n.º 21
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_has_pending_interrupts(avr))
		return;

	avr_int_table_p table = &avr->interrupts;

	if (!table->pending_wait) {
		table->pending_wait = 2;	// for next one...
		return;
	}
	table->pending_wait--;
	if (table->pending_wait)
		return;

	// 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;
	} else {
		if (vector && vector->trace)
			printf("%s calling %d\n", __FUNCTION__, (int)vector->vector);
		_avr_push_addr(avr, avr->pc);
		avr->sreg[S_I] = 0;
		avr->pc = vector->vector * avr->vector_size;

		avr_clear_interrupt(avr, vector);
	}
}
Ejemplo n.º 22
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]);
    }
}
Ejemplo n.º 23
0
static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;

	uint8_t as2 = avr_regbit_get(avr, p->as2);
	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	avr_core_watch_write(avr, addr, v);

	// only reconfigure the timer if "relevant" bits have changed
	// this prevent the timer reset when changing the edge detector
	// or other minor bits
	if (avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs)) != cs ||
			avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)) != mode ||
					avr_regbit_get(avr, p->as2) != as2) {
		avr_timer_reconfigure(p);
	}
}
Ejemplo n.º 24
0
int
avr_raise_interrupt(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	if (!vector || !vector->vector)
		return 0;
	if (vector->trace)
		printf("%s raising %d (enabled %d)\n", __FUNCTION__, vector->vector, avr_regbit_get(avr, vector->enable));
	if (vector->pending) {
		if (vector->trace)
			printf("%s trying to double raise %d (enabled %d)\n", __FUNCTION__, vector->vector, avr_regbit_get(avr, vector->enable));
		return 0;
	}
	// always mark the 'raised' flag to one, even if the interrupt is disabled
	// this allow "polling" for the "raised" flag, like for non-interrupt
	// driven UART and so so. These flags are often "write one to clear"
	if (vector->raised.reg)
		avr_regbit_set(avr, vector->raised);

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

	// If the interrupt is enabled, attempt to wake the core
	if (avr_regbit_get(avr, vector->enable)) {
		// Mark the interrupt as pending
		vector->pending = 1;

		avr_int_table_p table = &avr->interrupts;

		avr_int_pending_write(&table->pending, vector);

		if (avr->sreg[S_I] && avr->interrupt_state == 0)
			avr->interrupt_state = 1;
		if (avr->state == cpu_Sleeping) {
			if (vector->trace)
				printf("Waking CPU due to interrupt\n");
			avr->state = cpu_Running;	// in case we were sleeping
		}
	}
	// return 'raised' even if it was already pending
	return 1;
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
0
static void avr_flash_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_flash_t * p = (avr_flash_t *)param;

	avr_core_watch_write(avr, addr, v);

//	printf("** avr_flash_write %02x\n", v);

	if (avr_regbit_get(avr, p->selfprgen))
		avr_cycle_timer_register(avr, 4, avr_progen_clear, p); // 4 cycles is very little!
}
Ejemplo n.º 27
0
static void
avr_adc_configure_trigger(
		struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;
	
	uint8_t adate = avr_regbit_get(avr, p->adate);
	uint8_t old_adts = p->adts_mode;
	
	static char * auto_trigger_names[] = {
		"none",
		"free_running",
		"analog_comparator_0",
		"analog_comparator_1",
		"analog_comparator_2",
		"analog_comparator_3",
		"external_interrupt_0",
		"timer_0_compare_match_a",
		"timer_0_compare_match_b",
		"timer_0_overflow",
		"timer_1_compare_match_b",
		"timer_1_overflow",
		"timer_1_capture_event",
		"pin_change_interrupt",
		"psc_module_0_sync_signal",
		"psc_module_1_sync_signal",
		"psc_module_2_sync_signal",
	};
	
	if( adate ) {
		uint8_t adts = avr_regbit_get_array(avr, p->adts, ARRAY_SIZE(p->adts));
		p->adts_mode = p->adts_op[adts];
		
		switch(p->adts_mode) {
			case avr_adts_free_running: {
				// do nothing at free running mode
			}	break;
			// TODO: implement the other auto trigger modes
			default: {
				AVR_LOG(avr, LOG_WARNING,
						"ADC: unimplemented auto trigger mode: %s\n",
						auto_trigger_names[p->adts_mode]);
				p->adts_mode = avr_adts_none;
			}	break;
		}
	} else {
		// TODO: remove previously configured auto triggers
		p->adts_mode = avr_adts_none;
	}
	
	if( old_adts != p->adts_mode )
		AVR_LOG(avr, LOG_TRACE, "ADC: auto trigger configured: %s\n",
				auto_trigger_names[p->adts_mode]);
}
Ejemplo n.º 28
0
static void avr_watchdog_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_watchdog_t * p = (avr_watchdog_t *)param;
	// backup the registers
	// uint8_t wd = avr->data[p->wdce.reg];
	uint8_t wdce_o = avr_regbit_get(avr, p->wdce);	// old
	uint8_t wde_o = avr_regbit_get(avr, p->wde);
	uint8_t wdp_o[4];

//	printf("avr_watchdog_write %02x\n", v);
	for (int i = 0; i < 4; i++)
		wdp_o[i] = avr_regbit_get(avr, p->wdp[i]);

	avr->data[p->wdce.reg] = v;
	uint8_t wdce_n = avr_regbit_get(avr, p->wdce);	// new

	if (wdce_o /* || wdce_n */) {
		// make sure bit gets reset eventually
		if (wdce_n)
			avr_cycle_timer_register(avr, 4, avr_wdce_clear, p);

		uint8_t wdp = avr_regbit_get_array(avr, p->wdp, 4);
		p->cycle_count = 2048 << wdp;
		p->cycle_count = (p->cycle_count * avr->frequency) / 128000;
		if (avr_regbit_get(avr, p->wde)) {
			printf("Watchdog reset to %d cycles @ 128kz (* %d) = %d CPU cycles)\n", 2048 << wdp, 1 << wdp, (int)p->cycle_count);
			avr_cycle_timer_register(avr, p->cycle_count, avr_watchdog_timer, p);
		} else {
			printf("Watchdog disabled\n");
			avr_cycle_timer_cancel(avr, avr_watchdog_timer, p);
		}
	} else {
		// reset old values
		avr_regbit_setto(avr, p->wde, wde_o);
		for (int i = 0; i < 4; i++)
			avr_regbit_setto(avr, p->wdp[i], wdp_o[i]);
		v = avr->data[p->wdce.reg];
	}
	avr_core_watch_write(avr, addr, v);
}
Ejemplo n.º 29
0
int
avr_clear_interrupt_if(
		avr_t * avr,
		avr_int_vector_t * vector,
		uint8_t old)
{
	if (avr_regbit_get(avr, vector->raised)) {
		avr_clear_interrupt(avr, vector);
		return 1;
	}
	avr_regbit_setto(avr, vector->raised, old);
	return 0;
}
Ejemplo n.º 30
0
static void avr_uart_baud_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	avr_core_watch_write(avr, addr, v);
	uint32_t val = avr->data[p->r_ubrrl] | (avr->data[p->r_ubrrh] << 8);
	uint32_t baud = avr->frequency / (val+1);
	if (avr_regbit_get(avr, p->u2x))
		baud /= 8;
	else
		baud /= 16;

	const int databits[] = { 5,6,7,8,  /* 'reserved', assume 8 */8,8,8, 9 };
	int db = databits[avr_regbit_get(avr, p->ucsz) | (avr_regbit_get(avr, p->ucsz2) << 2)];
	int sb = 1 + avr_regbit_get(avr, p->usbs);
	int word_size = 1 /* start */ + db /* data bits */ + 1 /* parity */ + sb /* stops */;

	AVR_LOG(avr, LOG_TRACE, "UART: %c configured to %04x = %d bps (x%d), %d data %d stop\n",
			p->name, val, baud, avr_regbit_get(avr, p->u2x)?2:1, db, sb);
	// TODO: Use the divider value and calculate the straight number of cycles
	p->usec_per_byte = 1000000 / (baud / word_size);
	AVR_LOG(avr, LOG_TRACE, "UART: Roughly %d usec per bytes\n", (int)p->usec_per_byte);
}