Beispiel #1
0
static void
avr_timer_configure(
		avr_timer_t * p,
		uint32_t clock,
		uint32_t top,
		uint8_t reset)
{
	p->tov_cycles = 0;
	p->tov_top = top;

	p->tov_cycles = clock * (top+1);

	AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles = %dusec\n",
			__FUNCTION__, p->name, (p->io.avr->frequency / (float)p->tov_cycles),
			(int)p->tov_cycles, (int)avr_cycles_to_usec(p->io.avr, p->tov_cycles));

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
		if (!p->comp[compi].r_ocr)
			continue;
		uint32_t ocr = _timer_get_ocr(p, compi);
		uint32_t comp_cycles = clock * (ocr + 1);

		p->comp[compi].comp_cycles = 0;

		if (p->trace & (avr_timer_trace_compa << compi))
			printf("%s-%c clock %f top %d OCR%c %d\n", __FUNCTION__, p->name,
				(float)(p->io.avr->frequency / clock), top, 'A'+compi, ocr);

		if (ocr && ocr <= top) {
			p->comp[compi].comp_cycles = comp_cycles; // avr_hz_to_cycles(p->io.avr, fa);

			if (p->trace & (avr_timer_trace_compa << compi)) printf(
					"TIMER: %s-%c %c %.2fHz = %d cycles\n",
					__FUNCTION__, p->name,
					'A'+compi, (float)(p->io.avr->frequency / ocr),
					(int)p->comp[compi].comp_cycles);
		}
	}

	if (p->tov_cycles > 1) {
		if (reset)
		{
			avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p);
			// calling it once, with when == 0 tells it to arm the A/B/C timers if needed
			p->tov_base = 0;
			avr_timer_tov(p->io.avr, p->io.avr->cycle, p);
		}
		else
		{
			uint64_t orig_tov_base = p->tov_base;
			avr_cycle_timer_register(p->io.avr, p->tov_cycles - (p->io.avr->cycle - orig_tov_base), avr_timer_tov, p);
			// calling it once, with when == 0 tells it to arm the A/B/C timers if needed
			p->tov_base = 0;
			avr_timer_tov(p->io.avr, orig_tov_base, p);
		}
	}
}
Beispiel #2
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 #3
0
static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	avr_core_watch_write(avr, addr, v);
	uint16_t tcnt = _timer_get_tcnt(p);

	if (!p->tov_top)
		return;
		
	if (tcnt >= p->tov_top)
		tcnt = 0;
	
	// this involves some magicking
	// cancel the current timers, recalculate the "base" we should be at, reset the
	// timer base as it should, and re-schedule the timers using that base.
	
	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);

	uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top;

//	printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles);

	// this reset the timers bases to the new base
	if (p->tov_cycles > 1) {
		avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p);
		p->tov_base = 0;
		avr_timer_tov(avr, avr->cycle - cycles, p);
	}

//	tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles;
//	printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt);	
}
Beispiel #4
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);
    }
}
/**
 * Lowers the card presence signal.
 * This causes the clock to start, which initiates
 * the clock-and-data transfer.
 *
 * @param struct avr_t *avr The AVR this card reader is interfacing with.
 * @param avr_cycle_count_t when The number of cycles since this function call was registered.
 * @param void *param The card_reader struct to raise the card presence signal on.
 * @return avr_cycle_count_t The value of the card presence pin.
 */
avr_cycle_count_t card_reader_lower_presence_signal(struct avr_t *avr, avr_cycle_count_t when, void *param) {
	card_reader_t *self = (card_reader_t *) param;

	avr_raise_irq(avr_io_getirq(self->avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 2), 0);
	avr_raise_irq(avr_io_getirq(self->avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 3), 0);
	avr_cycle_timer_register(avr, self->clock->signal_time, card_reader_clock_tick, self->clock);

	return 0;
}
Beispiel #6
0
void
avr_cycle_timer_register_usec(
		avr_t * avr,
		uint32_t when,
		avr_cycle_timer_t timer,
		void * param)
{
	avr_cycle_timer_register(avr, avr_usec_to_cycles(avr, when), timer, param);
}
Beispiel #7
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!
}
Beispiel #8
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);
}
Beispiel #9
0
static void
avr_adc_write_adcsra(
		struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_adc_configure_trigger(avr, addr, v, param);
	
	avr_adc_t * p = (avr_adc_t *)param;
	uint8_t adsc = avr_regbit_get(avr, p->adsc);
	uint8_t aden = avr_regbit_get(avr, p->aden);

	avr->data[p->adsc.reg] = v;

	// can't write zero to adsc
	if (adsc && !avr_regbit_get(avr, p->adsc)) {
		avr_regbit_set(avr, p->adsc);
		v = avr->data[p->adsc.reg];
	}
	if (!aden && avr_regbit_get(avr, p->aden)) {
		// first conversion
		p->first = 1;
		AVR_LOG(avr, LOG_TRACE, "ADC: Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
	}
	if (aden && !avr_regbit_get(avr, p->aden)) {
		// stop ADC
		avr_cycle_timer_cancel(avr, avr_adc_int_raise, p);
		avr_regbit_clear(avr, p->adsc);
		v = avr->data[p->adsc.reg];	// Peter Ross [email protected]
	}
	if (!adsc && avr_regbit_get(avr, p->adsc)) {
		// start one!
		uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
		union {
			avr_adc_mux_t mux;
			uint32_t v;
		} e = { .mux = p->muxmode[muxi] };
		avr_raise_irq(p->io.irq + ADC_IRQ_OUT_TRIGGER, e.v);

		// clock prescaler are just a bit shift.. and 0 means 1
		uint32_t div = avr_regbit_get_array(avr, p->adps, ARRAY_SIZE(p->adps));
		if (!div) div++;

		div = avr->frequency >> div;
		if (p->first)
			AVR_LOG(avr, LOG_TRACE, "ADC: starting at %uKHz\n", div / 13 / 100);
		div /= p->first ? 25 : 13;	// first cycle is longer

		avr_cycle_timer_register(avr,
				avr_hz_to_cycles(avr, div),
				avr_adc_int_raise, p);
	}
	avr_core_watch_write(avr, addr, v);
}
Beispiel #10
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_cycle_timer_register(p->io.avr, p->cycle_count, avr_watchdog_timer, p);
		res = 0;
	}

	return res;
}
Beispiel #11
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);
        }
    }
}
Beispiel #12
0
static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top)
{
	float t = clock / (float)(top+1);
	float frequency = p->io.avr->frequency;

	p->tov_cycles = 0;
	p->tov_top = top;

	p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t);

	AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles = %dusec\n",
			__FUNCTION__, p->name, t, (int)p->tov_cycles,
			(int)avr_cycles_to_usec(p->io.avr, p->tov_cycles));

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
		if (!p->comp[compi].r_ocr)
			continue;
		uint32_t ocr = _timer_get_ocr(p, compi);
		float fc = clock / (float)(ocr+1);

		p->comp[compi].comp_cycles = 0;
	//	printf("%s-%c clock %d top %d OCR%c %d\n", __FUNCTION__, p->name, clock, top, 'A'+compi, ocr);

		if (ocr && ocr <= top) {
			p->comp[compi].comp_cycles = frequency / fc; // avr_hz_to_cycles(p->io.avr, fa);
			AVR_LOG(p->io.avr, LOG_TRACE, "TIMER: %s-%c %c %.2fHz = %d cycles\n", 
					__FUNCTION__, p->name,
					'A'+compi, fc, (int)p->comp[compi].comp_cycles);
		}
	}

	if (p->tov_cycles > 1) {
		avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p);
		// calling it once, with when == 0 tells it to arm the A/B/C timers if needed
		p->tov_base = 0;
		avr_timer_tov(p->io.avr, p->io.avr->cycle, p);
	}
}