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; }
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; }
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; }
static avr_cycle_count_t avr_wdce_clear( struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_watchdog_t * p = (avr_watchdog_t *)param; avr_regbit_clear(p->io.avr, p->wdce); return 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))
static uint8_t avr_spi_read(struct avr_t * avr, avr_io_addr_t addr, void * param) { avr_spi_t * p = (avr_spi_t *)param; uint8_t v = p->input_data_register; p->input_data_register = 0; avr_regbit_clear(avr, p->spi.raised); // printf("avr_spi_read = %02x\n", v); return v; }
static void avr_adc_reset(avr_io_t * port) { avr_adc_t * p = (avr_adc_t *)port; // stop ADC avr_cycle_timer_cancel(p->io.avr, avr_adc_int_raise, p); avr_regbit_clear(p->io.avr, p->adsc); for (int i = 0; i < ADC_IRQ_COUNT; i++) avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p); }
static void avr_twi_write( struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { avr_twi_t * p = (avr_twi_t *)param; uint8_t twen = avr_regbit_get(avr, p->twen); uint8_t twsta = avr_regbit_get(avr, p->twsta); uint8_t twsto = avr_regbit_get(avr, p->twsto); uint8_t twint = avr_regbit_get(avr, p->twi.raised); avr_core_watch_write(avr, addr, v); #if AVR_TWI_DEBUG AVR_TRACE(avr, "%s %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", __func__, v, avr_regbit_get(avr, p->twsta), avr_regbit_get(avr, p->twsto), avr_regbit_get(avr, p->twea), avr_regbit_get(avr, p->twi.raised), avr_regbit_get_raw(p->io.avr, p->twsr), p->state); #endif if (twen != avr_regbit_get(avr, p->twen)) { twen = !twen; if (!twen) { // if we were running, now now are not avr_regbit_clear(avr, p->twea); avr_regbit_clear(avr, p->twsta); avr_regbit_clear(avr, p->twsto); avr_clear_interrupt(avr, &p->twi); avr_core_watch_write(avr, p->r_twdr, 0xff); _avr_twi_status_set(p, TWI_NO_STATE, 0); p->state = 0; p->peer_addr = 0; } AVR_TRACE(avr, "TWEN: %d\n", twen); if (avr->data[p->r_twar]) { AVR_TRACE(avr, "TWEN Slave: %02x&%02x\n", avr->data[p->r_twar] >> 1, avr->data[p->r_twamr] >> 1); p->state |= TWI_COND_SLAVE; }
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); }
void avr_clear_interrupt( avr_t * avr, avr_int_vector_t * vector) { if (!vector) return; if (vector->trace) printf("%s cleared %d\n", __FUNCTION__, vector->vector); vector->pending = 0; avr_raise_irq(&vector->irq, 0); if (vector->raised.reg && !vector->raise_sticky) avr_regbit_clear(avr, vector->raised); }
static void avr_watchdog_irq_notify (struct avr_irq_t *irq, uint32_t value, void *param) { avr_watchdog_t *p = (avr_watchdog_t *) param; avr_t *avr = p->io.avr; /* interrupt handling calls this twice... * first when raised (during queuing), value = 1 * again when cleared (after servicing), value = 0 */ if (!value && avr_regbit_get (avr, p->watchdog.raised)) avr_regbit_clear (avr, p->watchdog.enable); }
static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_adc_t * p = (avr_adc_t *)param; if (avr_regbit_get(avr, p->aden)) { // if the interrupts are not used, still raised the UDRE and TXC flag avr_raise_interrupt(avr, &p->adc); avr_regbit_clear(avr, p->adsc); p->first = 0; p->read_status = 0; if( p->adts_mode == avr_adts_free_running ) avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1); } return 0; }
void avr_clear_interrupt( avr_t * avr, avr_int_vector_t * vector) { if (!vector) return; if (vector->trace) printf("%s cleared %d\n", __FUNCTION__, vector->vector); vector->pending = 0; avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 0); avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING, avr_has_pending_interrupts(avr)); if (vector->raised.reg && !vector->raise_sticky) avr_regbit_clear(avr, vector->raised); }
static void avr_twi_write( struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { avr_twi_t * p = (avr_twi_t *)param; uint8_t twen = avr_regbit_get(avr, p->twen); uint8_t twsta = avr_regbit_get(avr, p->twsta); uint8_t twsto = avr_regbit_get(avr, p->twsto); uint8_t twint = avr_regbit_get(avr, p->twi.raised); avr_core_watch_write(avr, addr, v); #if AVR_TWI_DEBUG printf("avr_twi_write %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", v, avr_regbit_get(avr, p->twsta), avr_regbit_get(avr, p->twsto), avr_regbit_get(avr, p->twea), avr_regbit_get(avr, p->twi.raised), avr_regbit_get_raw(p->io.avr, p->twsr), p->state); #endif if (twen != avr_regbit_get(avr, p->twen)) { twen = !twen; if (!twen) { // if we were running, now now are not avr_regbit_clear(avr, p->twea); avr_regbit_clear(avr, p->twsta); avr_regbit_clear(avr, p->twsto); avr_clear_interrupt(avr, &p->twi); avr_core_watch_write(avr, p->r_twdr, 0xff); _avr_twi_status_set(p, TWI_NO_STATE, 0); p->state = 0; p->peer_addr = 0; } printf("TWEN: %d\n", twen); } if (!twen) return; uint8_t cleared = avr_regbit_get(avr, p->twi.raised); /*int cleared = */avr_clear_interrupt_if(avr, &p->twi, twint); // printf("cleared %d\n", cleared); if (!twsto && avr_regbit_get(avr, p->twsto)) { // generate a stop condition #if AVR_TWI_DEBUG printf("<<<<< I2C stop\n"); #endif if (p->state) { // doing stuff if (p->state & TWI_COND_START) { avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, avr_twi_irq_msg(TWI_COND_STOP, p->peer_addr, 1)); } } p->state = 0; } if (!twsta && avr_regbit_get(avr, p->twsta)) { #if AVR_TWI_DEBUG printf(">>>>> I2C %sstart\n", p->state & TWI_COND_START ? "RE" : ""); #endif // generate a start condition if (p->state & TWI_COND_START) _avr_twi_delay_state(p, 3, TWI_REP_START); else _avr_twi_delay_state(p, 3, TWI_START); p->peer_addr = 0; p->state = TWI_COND_START; } if (cleared && !avr_regbit_get(avr, p->twsta) && !avr_regbit_get(avr, p->twsto)) { // writing or reading a byte if (p->state & TWI_COND_ADDR) { int do_read = p->peer_addr & 1; #if AVR_TWI_DEBUG if (do_read) printf("I2C READ byte from %02x\n", p->peer_addr); else printf("I2C WRITE byte %02x to %02x\n", avr->data[p->r_twdr], p->peer_addr); #endif // a normal data byte uint8_t msgv = do_read ? TWI_COND_READ : TWI_COND_WRITE; if (avr_regbit_get(avr, p->twea)) msgv |= TWI_COND_ACK; p->state &= ~TWI_COND_ACK; // clear ACK bit // if the latch is ready... as set by writing/reading the TWDR if ((p->state & msgv)) { // we send an IRQ and we /expect/ a slave to reply // immediately via an IRQ to set the COND_ACK bit // otherwise it's assumed it's been nacked... avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, avr_twi_irq_msg(msgv, p->peer_addr, avr->data[p->r_twdr])); if (do_read) { // read ? _avr_twi_delay_state(p, 9, msgv & TWI_COND_ACK ? TWI_MRX_DATA_ACK : TWI_MRX_DATA_NACK); } else { _avr_twi_delay_state(p, 9, p->state & TWI_COND_ACK ? TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK); } } #if AVR_TWI_DEBUG else printf("I2C latch is not ready, do nothing\n"); #endif } else { #if AVR_TWI_DEBUG printf("I2C Master address %02x\n", avr->data[p->r_twdr]); #endif // send the address p->state |= TWI_COND_ADDR; p->peer_addr = avr->data[p->r_twdr]; p->state &= ~TWI_COND_ACK; // clear ACK bit // we send an IRQ and we /expect/ a slave to reply // immediately via an IRQ tp set the COND_ACK bit // otherwise it's assumed it's been nacked... avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, avr_twi_irq_msg(TWI_COND_START, p->peer_addr, 0)); if (p->peer_addr & 1) { // read ? p->state |= TWI_COND_READ; // always allow read to start with _avr_twi_delay_state(p, 9, p->state & TWI_COND_ACK ? TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK); } else { _avr_twi_delay_state(p, 9, p->state & TWI_COND_ACK ? TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK); } } p->state &= ~TWI_COND_WRITE; } }