Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
static void
_avr_io_command_write (struct avr_t *avr, avr_io_addr_t addr, uint8_t v, void *param)
{
  AVR_LOG (avr, LOG_TRACE, "%s %02x\n", __FUNCTION__, v);
  switch (v)
    {
    case SIMAVR_CMD_VCD_START_TRACE:
      if (avr->vcd)
        avr_vcd_start (avr->vcd);
      break;
      
    case SIMAVR_CMD_VCD_STOP_TRACE:
      if (avr->vcd)
        avr_vcd_stop (avr->vcd);
      break;
      
    case SIMAVR_CMD_UART_LOOPBACK:
      {
        avr_irq_t *src = avr_io_getirq (avr, AVR_IOCTL_UART_GETIRQ ('0'), UART_IRQ_OUTPUT);
        avr_irq_t *dst = avr_io_getirq (avr, AVR_IOCTL_UART_GETIRQ ('0'), UART_IRQ_INPUT);
        if (src && dst)
          {
            AVR_LOG (avr, LOG_TRACE, "%s activating uart local echo IRQ src %p dst %p\n",
                     __FUNCTION__, src, dst);
            avr_connect_irq (src, dst);
          }
      }
      break;
    }
}
Esempio n. 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);
    }
}
Esempio n. 5
0
void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v)
{
	if (addr > avr->ramend) {
		AVR_LOG(avr, LOG_ERROR, "CORE: *** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x out of ram\n",
				avr->pc, _avr_sp_get(avr), avr->flash[avr->pc + 1] | (avr->flash[avr->pc]<<8), addr, v);
		CRASH();
	}
	if (addr < 32) {
		AVR_LOG(avr, LOG_ERROR, "CORE: *** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x low registers\n",
				avr->pc, _avr_sp_get(avr), avr->flash[avr->pc + 1] | (avr->flash[avr->pc]<<8), addr, v);
		CRASH();
	}
#if AVR_STACK_WATCH
	/*
	 * this checks that the current "function" is not doctoring the stack frame that is located
	 * higher on the stack than it should be. It's a sign of code that has overrun it's stack
	 * frame and is munching on it's own return address.
	 */
	if (avr->trace_data->stack_frame_index > 1 && addr > avr->trace_data->stack_frame[avr->trace_data->stack_frame_index-2].sp) {
		printf( FONT_RED "%04x : munching stack SP %04x, A=%04x <= %02x\n" FONT_DEFAULT, avr->pc, _avr_sp_get(avr), addr, v);
	}
#endif

	if (avr->gdb) {
		avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_WRITE);
	}

	avr->data[addr] = v;
}
Esempio n. 6
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);
	}	
}
Esempio n. 7
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]);
}
Esempio n. 8
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);
}
Esempio n. 9
0
void
avr_register_io_write(
		avr_t *avr,
		avr_io_addr_t addr,
		avr_io_write_t writep,
		void * param)
{
	avr_io_addr_t a = AVR_DATA_TO_IO(addr);

	if (a >= MAX_IOs) {
		AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): IO address 0x%04x out of range (max 0x%04x).\n",
					a, MAX_IOs);
		abort();
	}
	/*
	 * Verifying that some other piece of code is not installed to watch write
	 * on this address. If there is, this code installs a "dispatcher" callback
	 * instead to handle multiple clients, otherwise, it continues as usual
	 */
	if (avr->io[a].w.param || avr->io[a].w.c) {
		if (avr->io[a].w.param != param || avr->io[a].w.c != writep) {
			// if the muxer not already installed, allocate a new slot
			if (avr->io[a].w.c != _avr_io_mux_write) {
				int no = avr->io_shared_io_count++;
				if (avr->io_shared_io_count > 4) {
					AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many shared IO registers.\n");
					abort();
				}
				AVR_LOG(avr, LOG_TRACE, "IO: avr_register_io_write(%04x): Installing muxer on register.\n", addr);
				avr->io_shared_io[no].used = 1;
				avr->io_shared_io[no].io[0].param = avr->io[a].w.param;
				avr->io_shared_io[no].io[0].c = avr->io[a].w.c;
				avr->io[a].w.param = (void*)(intptr_t)no;
				avr->io[a].w.c = _avr_io_mux_write;
			}
			int no = (intptr_t)avr->io[a].w.param;
			int d = avr->io_shared_io[no].used++;
			if (avr->io_shared_io[no].used > 4) {
				AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many callbacks on %04x.\n", addr);
				abort();
			}
			avr->io_shared_io[no].io[d].param = param;
			avr->io_shared_io[no].io[d].c = writep;
			return;
		}
	}

	avr->io[a].w.param = param;
	avr->io[a].w.c = writep;
}
Esempio n. 10
0
int avr_init(avr_t * avr)
{
	avr->flash = malloc(avr->flashend + 1);
	memset(avr->flash, 0xff, avr->flashend + 1);
	avr->codeend = avr->flashend;
	avr->data = malloc(avr->ramend + 1);
	memset(avr->data, 0, avr->ramend + 1);
#ifdef CONFIG_SIMAVR_TRACE
	avr->trace_data = calloc(1, sizeof(struct avr_trace_data_t));
#endif

	AVR_LOG(avr, LOG_TRACE, "%s init\n", avr->mmcu);

	// cpu is in limbo before init is finished.
	avr->state = cpu_Limbo;
	avr->frequency = 1000000;	// can be overridden via avr_mcu_section
	avr_cmd_init(avr);
	avr_interrupt_init(avr);
	if (avr->custom.init)
		avr->custom.init(avr, avr->custom.data);
	if (avr->init)
		avr->init(avr);
	// set default (non gdb) fast callbacks
	avr->run = avr_callback_run_raw;
	avr->sleep = avr_callback_sleep_raw;
	// number of address bytes to push/pull on/off the stack
	avr->address_size = avr->eind ? 3 : 2;
	avr->log = 1;
	avr_reset(avr);
	return 0;
}
Esempio n. 11
0
static avr_cycle_count_t avr_progen_clear(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_flash_t * p = (avr_flash_t *)param;
	avr_regbit_clear(p->io.avr, p->selfprgen);
	AVR_LOG(avr, LOG_WARNING, "FLASH: avr_progen_clear - SPM not received, clearing PRGEN bit\n");
	return 0;
}
Esempio n. 12
0
static void avr_uart_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;

	if (addr == p->r_udr) {
		avr_core_watch_write(avr, addr, v);

		if ( p->udrc.vector)
			avr_regbit_clear(avr, p->udrc.raised);
		avr_cycle_timer_register_usec(avr,
				p->usec_per_byte, avr_uart_txc_raise, p); // should be uart speed dependent

		if (p->flags & AVR_UART_FLAG_STDIO) {
			const int maxsize = 256;
			if (!p->stdio_out)
				p->stdio_out = malloc(maxsize);
			p->stdio_out[p->stdio_len++] = v < ' ' ? '.' : v;
			p->stdio_out[p->stdio_len] = 0;
			if (v == '\n' || p->stdio_len == maxsize) {
				p->stdio_len = 0;
				AVR_LOG(avr, LOG_TRACE, FONT_GREEN "%s\n" FONT_DEFAULT, p->stdio_out);
			}
		}
		TRACE(printf("UDR%c(%02x) = %02x\n", p->name, addr, v);)
		// tell other modules we are "outputting" a byte
		if (avr_regbit_get(avr, p->txen))
Esempio n. 13
0
// no sanity checks checking here, on purpose
static void
avr_cycle_timer_insert(
		avr_t * avr,
		avr_cycle_count_t when,
		avr_cycle_timer_t timer,
		void * param)
{
	avr_cycle_timer_pool_t * pool = &avr->cycle_timers;

	when += avr->cycle;

	avr_cycle_timer_slot_p t = pool->timer_free;

	if (!t) {
		AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: ran out of timers (%d)!\n", __func__, MAX_CYCLE_TIMERS);
		return;
	}
	// detach head
	pool->timer_free = t->next;
	t->next = NULL;
	t->timer = timer;
	t->param = param;
	t->when = when;

	// find its place in the list
	avr_cycle_timer_slot_p loop = pool->timer, last = NULL;
	while (loop) {
		if (loop->when > when)
			break;
		last = loop;
		loop = loop->next;
	}
	INSERT(pool->timer, last, t);
}
Esempio n. 14
0
void
avr_reset (avr_t * avr)
{
  AVR_LOG (avr, LOG_TRACE, "%s reset\n", avr->mmcu);

  avr->state = cpu_Running;

  for (int i = 0x20; i <= MAX_IOs; i++)
    avr->data[i] = 0;
  _avr_sp_set (avr, avr->ramend);
  avr->pc = 0;
  for (int i = 0; i < 8; i++)
    avr->sreg[i] = 0;

  avr_interrupt_reset (avr);
  avr_cycle_timer_reset (avr);
  if (avr->reset)
    avr->reset (avr);

  avr_io_t *port = avr->io_port;
  while (port)
    {
      if (port->reset)
        port->reset (port);
      port = port->next;
    }
}
Esempio n. 15
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);
	}
}
Esempio n. 16
0
void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, avr_flashaddr_t address)
{
	if ((address + size) > avr->flashend+1) {
		AVR_LOG(avr, LOG_ERROR, "avr_loadcode(): Attempted to load code of size %d but flash size is only %d.\n",
			size, avr->flashend + 1);
		abort();
	}
	memcpy(avr->flash + address, code, size);
}
Esempio n. 17
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);
		}
	}
}
Esempio n. 18
0
void
avr_register_io_read(
		avr_t *avr,
		avr_io_addr_t addr,
		avr_io_read_t readp,
		void * param)
{
	avr_io_addr_t a = AVR_DATA_TO_IO(addr);
	if (avr->io[a].r.param || avr->io[a].r.c) {
		if (avr->io[a].r.param != param || avr->io[a].r.c != readp) {
			AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(): Already registered, refusing to override.\n");
			AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(%04x : %p/%p): %p/%p\n", a,
					avr->io[a].r.c, avr->io[a].r.param, readp, param);
			abort();
		}
	}
	avr->io[a].r.param = param;
	avr->io[a].r.c = readp;
}
Esempio n. 19
0
void avr_callback_run_gdb(avr_t * avr)
{
	avr_gdb_processor(avr, avr->state == cpu_Stopped);

	if (avr->state == cpu_Stopped)
		return ;

	// if we are stepping one instruction, we "run" for one..
	int step = avr->state == cpu_Step;
	if (step)
		avr->state = cpu_Running;
	
	avr_flashaddr_t new_pc = avr->pc;

	if (avr->state == cpu_Running) {
		new_pc = avr_run_one(avr);
#if CONFIG_SIMAVR_TRACE
		avr_dump_state(avr);
#endif
	}

	// if we just re-enabled the interrupts...
	// double buffer the I flag, to detect that edge
	if (avr->sreg[S_I] && !avr->i_shadow)
		avr->interrupts.pending_wait++;
	avr->i_shadow = avr->sreg[S_I];

	// run the cycle timers, get the suggested sleep time
	// until the next timer is due
	avr_cycle_count_t sleep = avr_cycle_timer_process(avr);

	avr->pc = new_pc;

	if (avr->state == cpu_Sleeping) {
		if (!avr->sreg[S_I]) {
			if (avr->log)
				AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n");
			avr->state = cpu_Done;
			return;
		}
		/*
		 * try to sleep for as long as we can (?)
		 */
		avr->sleep(avr, sleep);
		avr->cycle += 1 + sleep;
	}
	// Interrupt servicing might change the PC too, during 'sleep'
	if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
		avr_service_interrupts(avr);
	
	// if we were stepping, use this state to inform remote gdb
	if (step)
		avr->state = cpu_StepDone;

}
Esempio n. 20
0
void
avr_sadly_crashed (avr_t * avr, uint8_t signal)
{
  AVR_LOG (avr, LOG_ERROR, "%s\n", __FUNCTION__);
  avr->state = cpu_Stopped;
  if (avr->gdb_port && !avr->gdb)
    // enable gdb server, and wait
    avr_gdb_init (avr);
  if (!avr->gdb)
    avr->state = cpu_Crashed;
}
Esempio n. 21
0
static void
avr_usb_udaddr_write(
    struct avr_t * avr,
    avr_io_addr_t addr,
    uint8_t v,
    void * param)
{
    if (v & 0x80)
        AVR_LOG(avr, LOG_TRACE, "USB: Activate address %d\n", v & 0x7f);
    avr_core_watch_write(avr, addr, v);
}
Esempio n. 22
0
avr_t *
avr_make_mcu_by_name(
		const char *name)
{
	avr_kind_t * maker = NULL;
	for (int i = 0; avr_kind[i] && !maker; i++) {
		for (int j = 0; avr_kind[i]->names[j]; j++)
			if (!strcmp(avr_kind[i]->names[j], name)) {
				maker = avr_kind[i];
				break;
			}
	}
	if (!maker) {
		AVR_LOG(((avr_t*)0), LOG_ERROR, "%s: AVR '%s' not known\n", __FUNCTION__, name);
		return NULL;
	}

	avr_t * avr = maker->make();
	AVR_LOG(avr, LOG_TRACE, "Starting %s - flashend %04x ramend %04x e2end %04x\n",
			avr->mmcu, avr->flashend, avr->ramend, avr->e2end);
	return avr;
}
Esempio n. 23
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);
}
Esempio n. 24
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);
	}
}
Esempio n. 25
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);
	}
}
Esempio n. 26
0
uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr)
{
	if (addr > avr->ramend) {
		AVR_LOG(avr, LOG_ERROR, FONT_RED "CORE: *** Invalid read address PC=%04x SP=%04x O=%04x Address %04x out of ram (%04x)\n" FONT_DEFAULT,
				avr->pc, _avr_sp_get(avr), avr->flash[avr->pc + 1] | (avr->flash[avr->pc]<<8), addr, avr->ramend);
		CRASH();
	}

	if (avr->gdb) {
		avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_READ);
	}

	return avr->data[addr];
}
Esempio n. 27
0
static void
avr_timer_write_ocr(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_comp_p comp = (avr_timer_comp_p)param;
	avr_timer_t *timer = comp->timer;
	uint16_t oldv;

	/* check to see if the OCR values actually changed */
	oldv = _timer_get_comp_ocr(avr, comp);
	avr_core_watch_write(avr, addr, v);

	switch (timer->wgm_op_mode_kind) {
		case avr_timer_wgm_normal:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_fc_pwm:	// OCR is not used here
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_ctc:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_pwm:
			if (timer->mode.top != avr_timer_wgm_reg_ocra) {
				avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA));
			} else {
				avr_timer_reconfigure(timer, 0); // if OCRA is the top, reconfigure needed
			}
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		case avr_timer_wgm_fast_pwm:
			if (oldv != _timer_get_comp_ocr(avr, comp))
				avr_timer_reconfigure(timer, 0);
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0,
					_timer_get_ocr(timer, AVR_TIMER_COMPA));
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1,
					_timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n",
					__FUNCTION__, timer->name, timer->mode.kind);
			avr_timer_reconfigure(timer, 0);
			break;
	}
}
Esempio n. 28
0
static void _avr_io_console_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	static char * buf = NULL;
	static int size = 0, len = 0;

	if (v == '\r' && buf) {
		buf[len] = 0;
		AVR_LOG(avr, LOG_OUTPUT, "O:" "%s" "" "\n", buf);
		len = 0;
		return;
	}
	if (len + 1 >= size) {
		size += 128;
		buf = (char*)realloc(buf, size);
	}
	if (v >= ' ')
		buf[len++] = v;
}
Esempio n. 29
0
void
avr_register_vector(
		avr_t *avr,
		avr_int_vector_t * vector)
{
	if (!vector->vector)
		return;

	avr_int_table_p table = &avr->interrupts;

	vector->irq.irq = vector->vector;
	table->vector[table->vector_count++] = vector;
	if (vector->trace)
		printf("%s register vector %d (enabled %04x:%d)\n", __FUNCTION__, vector->vector, vector->enable.reg, vector->enable.bit);

	if (!vector->enable.reg)
		AVR_LOG(avr, LOG_WARNING, "INT: avr_register_vector: No 'enable' bit on vector %d !\n", vector->vector);
}
Esempio n. 30
0
static void _avr_io_console_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	if (v == '\r' && avr->io_console_buffer.buf) {
		avr->io_console_buffer.buf[avr->io_console_buffer.len] = 0;
		AVR_LOG(avr, LOG_OUTPUT, "O:" "%s" "" "\n",
			avr->io_console_buffer.buf);
		avr->io_console_buffer.len = 0;
		return;
	}
	if (avr->io_console_buffer.len + 1 >= avr->io_console_buffer.size) {
		avr->io_console_buffer.size += 128;
		avr->io_console_buffer.buf = (char*)realloc(
			avr->io_console_buffer.buf,
			avr->io_console_buffer.size);
	}
	if (v >= ' ')
		avr->io_console_buffer.buf[avr->io_console_buffer.len++] = v;
}