示例#1
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);
        }
    }
}
示例#2
0
文件: avr_adc.c 项目: kevinf28/simavr
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);
}
示例#3
0
static void avr_watchdog_reset(avr_io_t * port)
{
	avr_watchdog_t * p = (avr_watchdog_t *)port;
	avr_t * avr = p->io.avr;

	if (p->reset_context.wdrf) {
		p->reset_context.wdrf = 0;
		/*
		 * if watchdog reset kicked, then watchdog gets restarted at
		 * fastest interval
		 */
		avr->run = p->reset_context.avr_run;

		avr_regbit_set(avr, p->wde);
		avr_regbit_set(avr, p->wdrf);
		avr_regbit_set_array_from_value(avr, p->wdp, 4, 0);
		
		avr_watchdog_set_cycle_count_and_timer(avr, p, 0, 0);
	}
	/* TODO could now use the two pending/running IRQs to do the same
	 * as before */
	avr_irq_register_notify(p->watchdog.irq, avr_watchdog_irq_notify, p);
}
示例#4
0
static void
avr_watchdog_reset (avr_io_t * port)
{
  avr_watchdog_t *p = (avr_watchdog_t *) port;
  avr_t *avr = p->io.avr;

  if (p->reset_context.wdrf)
    {
      /*
       * if watchdog reset kicked, then watchdog gets restated at fastest interval
       */

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

      avr_regbit_set (avr, p->wde);
      avr_regbit_set (avr, p->wdrf);
      avr_regbit_set_array_from_value (avr, p->wdp, 4, 0);

      avr_watchdog_set_cycle_count_and_timer (avr, p, 0, 0);
    }

  avr_irq_register_notify (&p->watchdog.irq, avr_watchdog_irq_notify, p);
}
示例#5
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;
}