Chyba optimalizace, nebo moje?

Pavel Hudecek edizon na seznam.cz
Úterý Duben 20 23:58:10 CEST 2021


Dobrý den všem,
Na konci uvedený program měla být ukázka pro děti, ale funguje, jen když je optimalizace o0, v ostatních případech po stisku tlačítka chcípne přerušení. Udělal jsem něco špatně, nebo objevil chybu kompileru?
(bez cli/sei funguje, samozřejmě s občasnými chybami)

Díky,
PH

// úloha prerus4:
// změřit dobu stisku tlačítka a potom blikat s čekáním stejnou dobu, jaká byla naměřena

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU		(20000000UL/6)
#include <util/delay.h>

#define LED_bit		5	// bit s LEDkou
#define TL_bit		4	// bit s tlačítkem
#define TEST_bit	3	// bit testu přerušení

#define TL_jeStisk	((PORTB.IN & (1<<TL_bit)) == 0)		// podmínka právě je stisklé tlačítko
#define TL_neniStisk ((PORTB.IN & (1<<TL_bit)) != 0)	// podmínka není stisklé

volatile unsigned int ms=0;

void cekej(unsigned int n) { // ==========================================
	__asm__("cli");
	ms=0;
	__asm__("sei");
	
	while(1) {
		__asm__("cli");
		if (ms>=n) break;
		__asm__("sei");
	}
	__asm__("sei");
}

void cekejNaTl() { // ====================================================
	while(TL_jeStisk) cekej(0);
	while(TL_neniStisk) cekej(0);
}

int main(void) { // ======================================================
	unsigned int t=0;

	PORTB.OUTSET	= 1<<LED_bit;		// nastavit na 1, aby LEDka nesvítila od začátku
	PORTB.DIR		= (1<<LED_bit) | (1<<TEST_bit);		// zapnout výstup pro LED a test
	PORTB.PIN3CTRL	= 0;
	PORTB.PIN4CTRL	= PORT_PULLUPEN_bm;	// zapnout pull-up pro tlačítko
	
	TCA0_SINGLE_CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc;		// použít přímo frekvenci procesoru (děleno 1)
	TCA0_SINGLE_CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;	// NORMAL - jen čítat
	TCA0_SINGLE_PER = F_CPU / 1000UL;					// perioda čítání bude tisícina F_CPU
	TCA0_SINGLE_INTCTRL = TCA_SINGLE_OVF_bm;			// přerušení od přetečení periody
	TCA0_SINGLE_INTFLAGS = TCA_SINGLE_OVF_bm;			// smazat případné předchozí visící přerušení 
	TCA0_SINGLE_CTRLA |= TCA_SINGLE_ENABLE_bm;			// povolit čítač
	__asm__("sei");
	
	while (1) { // ---------------------------------------------------
		cekejNaTl();
		__asm__("cli");
		ms=0;
		__asm__("sei");
		while(TL_jeStisk);
		__asm__("cli");
		t=ms;
		__asm__("sei");
		while(1) {
			PORTB.OUTTGL = 1<<LED_bit;
			cekej(t);
			// při čekání se zastaví přerušení kvůli chybě optimalizace? - nutno přenastavit na -O0
		}
	}
}

ISR (TCA0_OVF_vect) { // =================================================
	PORTB.OUTTGL = (1<<TEST_bit);
	ms++;
	
	TCA0_SINGLE_INTFLAGS = TCA_SINGLE_OVF_bm;
}
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20210420/8518389f/attachment.html>


Další informace o konferenci Hw-list