Compare commits

...

3 commits

Author SHA1 Message Date
Stephan I. Böttcher
d20586f0fc leia: '?' query GPIOR 2025-10-29 17:38:17 +01:00
Stephan I. Böttcher
be2d75f3b4 leia: eeprom isr __asm__ selected and tested 2025-10-29 17:20:10 +01:00
Stephan I. Böttcher
344e3a073d leia: do not enable interrupts when reading eeprom 2025-10-29 15:58:52 +01:00

View file

@ -8,7 +8,7 @@
// OCR1A: interrupt: assert STEP // OCR1A: interrupt: assert STEP
// OCR1B: interrupt: deassert STEP, RESET // OCR1B: interrupt: deassert STEP, RESET
// ADC: Three NTCs ADC8,9,10, Iprim ADC3, internals. // ADC: Three NTCs ADC8,9,10, Iprim ADC3, internals.
// Interrupt stores conversionresults and advances channels. // Interrupt stores conversion results and advances channels.
// DAC: Motor current reference. // DAC: Motor current reference.
// TIMER0: ADC conversion cadence, 92µs resolution, range 23ms range. // TIMER0: ADC conversion cadence, 92µs resolution, range 23ms range.
// Interrupt: DAC ramp ticks // Interrupt: DAC ramp ticks
@ -88,8 +88,10 @@ struct stat {
uint16_t adc[16]; // 48 uint16_t adc[16]; // 48
uint16_t dac; // 80 uint16_t dac; // 80
uint8_t adc_idx; // 82 uint8_t adc_idx; // 82
uint8_t pad[45]; //128 uint8_t eewr_n; // 83
}; uint16_t eewr_a; // 84
uint8_t pad[42]; // 86
}; //128
struct vars { struct vars {
struct conf conf; struct conf conf;
@ -143,8 +145,8 @@ const struct conf runcon = {
}, },
.dac_ref = DAC_R | ADC_BG, .dac_ref = DAC_R | ADC_BG,
.adc_incr = 16, // one conversion per channel .adc_incr = 16, // one conversion per channel
.adc_period = TICK_NS(1000000), .adc_period = TICK_NS(10000000),
.dac_step = 0x20, .dac_step = 0x40,
.pad = "\xff\xff\xff\xff\xff\xff", .pad = "\xff\xff\xff\xff\xff\xff",
}; };
@ -575,7 +577,6 @@ ISR(ADC_vect, ISR_NAKED)
static void conf_init() static void conf_init()
{ {
cli();
adc_init(); adc_init();
adc_start(v.stat.adc_idx>>4); adc_start(v.stat.adc_idx>>4);
dac_set(v.conf.dac_ramp); dac_set(v.conf.dac_ramp);
@ -586,16 +587,13 @@ static void conf_init()
// Write EEPROM in interrupt. // Write EEPROM in interrupt.
uint8_t eewr_n; // number of bytes to write #if 0
uint16_t eewr_a; // EEPROM conf base address
#if 1
ISR(EE_READY_vect) ISR(EE_READY_vect)
{ {
uint8_t n = eewr_n; uint8_t n = v.stat.eewr_n;
while (n) { while (n) {
eewr_n = --n; v.stat.eewr_n = --n;
EEAR = eewr_a + n; EEAR = v.stat.eewr_a + n;
EECR |= 1<<EERE; EECR |= 1<<EERE;
uint8_t d = ((uint8_t*)&v.conf)[n]; uint8_t d = ((uint8_t*)&v.conf)[n];
if (EEDR == d) if (EEDR == d)
@ -619,16 +617,16 @@ ISR(EE_READY_vect, ISR_NAKED)
"push r30" "\n\t" "push r30" "\n\t"
"push r31" "\n\t" "push r31" "\n\t"
"cbi %[C], %[IE]" "\n\t" "cbi %[C], %[IE]" "\n\t"
"lds r24, eewr_n" "\n" "lds r24, %[EN]" "\n"
"1:" "\n\t" "1:" "\n\t"
"clr r31" "\n\t" "clr r31" "\n\t"
"cp r24, r31" "\n\t" "cp r24, r31" "\n\t"
"breq 2f" "\n\t" "breq 2f" "\n\t"
"subi r24, 1" "\n\t" "subi r24, 1" "\n\t"
"lds r30, eewr_a" "\n\t" "lds r30, %[EA]" "\n\t"
"add r30, r24" "\n\t" "add r30, r24" "\n\t"
"out %[AL], r30" "\n\t" "out %[AL], r30" "\n\t"
"lds r30, eewr_a+1" "\n\t" "lds r30, %[EA]+1" "\n\t"
"adc r30, r31" "\n\t" "adc r30, r31" "\n\t"
"out %[AH], r30" "\n\t" "out %[AH], r30" "\n\t"
"sbi %[C], %[RE]" "\n\t" "sbi %[C], %[RE]" "\n\t"
@ -650,15 +648,16 @@ ISR(EE_READY_vect, ISR_NAKED)
"subi r30, -1" "\n\t" "subi r30, -1" "\n\t"
"out %[CC], r30" "\n\t" "out %[CC], r30" "\n\t"
"2:" "\n\t" "2:" "\n\t"
"sts eewr_n, r24" "\n\t" "sts %[EN], r24" "\n\t"
"pop r31" "\n\t" "pop r31" "\n\t"
"pop r30" "\n\t" "pop r30" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"out __SREG__, r24" "\n\t" "out __SREG__, r24" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
: :[EN] "+m" (v.stat.eewr_n)
:[V] "m" (v.conf), :[EA] "m" (v.stat.eewr_a),
[V] "m" (v.conf),
[C] "n" (_SFR_IO_ADDR(EECR)), [C] "n" (_SFR_IO_ADDR(EECR)),
[AL] "n" (_SFR_IO_ADDR(EEARL)), [AL] "n" (_SFR_IO_ADDR(EEARL)),
[AH] "n" (_SFR_IO_ADDR(EEARH)), [AH] "n" (_SFR_IO_ADDR(EEARH)),
@ -677,8 +676,8 @@ uint8_t eeprom_save(uint16_t a)
{ {
if (EECR & 1<<EERIE) if (EECR & 1<<EERIE)
return 1; return 1;
eewr_a = a; v.stat.eewr_a = a;
eewr_n = sizeof(struct conf); v.stat.eewr_n = sizeof(struct conf);
GPIOR2 = 0; GPIOR2 = 0;
EECR = 1<<EERIE; EECR = 1<<EERIE;
return 0; return 0;
@ -687,11 +686,8 @@ uint8_t eeprom_save(uint16_t a)
static inline static inline
uint8_t eeprom_load(uint16_t a) uint8_t eeprom_load(uint16_t a)
{ {
cli(); if (EECR & 1<<EEWE)
if (EECR & 1<<EEWE) {
sei();
return 1; return 1;
}
uint8_t n = sizeof(struct conf); uint8_t n = sizeof(struct conf);
uint8_t *c = (uint8_t*)&v.conf; uint8_t *c = (uint8_t*)&v.conf;
while (n--) { while (n--) {
@ -699,22 +695,17 @@ uint8_t eeprom_load(uint16_t a)
EECR |= 1<<EERE; EECR |= 1<<EERE;
*c++ = EEDR; *c++ = EEDR;
} }
sei();
return 0; return 0;
} }
static inline static inline
uint8_t eeprom_read_byte(uint16_t a, uint8_t *r) uint8_t eeprom_read_byte(uint16_t a, uint8_t *r)
{ {
cli(); if (EECR & 1<<EEWE)
if (EECR & 1<<EEWE) {
sei();
return 1; return 1;
}
EEAR = a; EEAR = a;
EECR |= 1<<EERE; EECR |= 1<<EERE;
*r = EEDR; *r = EEDR;
sei();
return 0; return 0;
} }
@ -850,6 +841,8 @@ void reg88(uint8_t *v1, uint8_t *v2, unsigned char *r, const unsigned char *c)
// goes low. // goes low.
// //
// Interrupts // Interrupts
// are enabled only while sleeping, waiting for the SPI master
//
// PCINT2: disable global interrupts // PCINT2: disable global interrupts
// TIMER1_COMPA: assert STEP // TIMER1_COMPA: assert STEP
// TIMER1_COMPB: deassert STEP, RESET // TIMER1_COMPB: deassert STEP, RESET
@ -897,6 +890,10 @@ int main()
resp[1] = error_msg[4]; resp[1] = error_msg[4];
resp[2] = error_msg[5]; resp[2] = error_msg[5];
break; break;
case '?':
resp[1] = GPIOR2;
resp[2] = GPIOR1;
break;
case 'm': reg88(&v.conf.lmask, &v.conf.lval, resp, cmd); break; case 'm': reg88(&v.conf.lmask, &v.conf.lval, resp, cmd); break;
case 'q': reg16(&v.conf.period, resp, cmd); case 'q': reg16(&v.conf.period, resp, cmd);
if (0) case 'l': reg16(&v.conf.slen, resp, cmd); if (0) case 'l': reg16(&v.conf.slen, resp, cmd);