RS232 na ST7Flite39 z użyciem przerwań.

Dyskusje ogólne na temat "cyfrówki" czyli wszystko o TTL/CMOS, językach VHDL i VERILOG, bramkach, rejestrach, przerzutnikach... Dobre miejsce na pytania odnośnie uniwersalnych programatorów (np. Willem) a także podłączania własnych peryferiów do komputera PC.
ODPOWIEDZ
krzysztof-u
-
Posty: 6
Rejestracja: 05 cze 2009, 19:36
Lokalizacja: Słupsk

RS232 na ST7Flite39 z użyciem przerwań.

Post autor: krzysztof-u » 11 cze 2009, 22:23

Witam.
Zabrałem się za pisanie biblioteki do obsługi interfejsu SCI w ww. kontrolerze w języku C.
Transmisja i odbiór są realizowane w przerwaniach. Tu mam problem. W procedurze obsługi przerwania wywołanego pojawieniem się odebranego znaku w buforze muszę skasować flagę przerwania (RDRF). Skasować ją można sekwencją:

- odczyt SCISR
- odczyt SCIDR

Robię tak, ale po podejrzeniu wygenerowanego pliku asemblerowego rozdziela mi te dwie operacje innymi:
w C robię tak:

temp = SCISR;
temp = SCIDR;

W asm otrzymuję to:

1823 ; 189 temp = SCISR;
1825 01b4 96 ld x,s
1826 01b5 b640 ld a,_SCISR
1827 01b7 d70103 ld (OFST-1,x),a
1828 ; 190 temp = SCIDR; //read data
1830 01ba 96 ld x,s
1831 01bb b641 ld a,_SCIDR
1832 01bd d70103 ld (OFST-1,x),a

Wie ktoś może jak to zrobić prawidłowo ?
Myślałem o wstawce w asemblerze, ale nie wiem jak się odwołać do zmiennych zadeklarowanych przed nią w C.

Awatar użytkownika
radzio
Użytkownik
Posty: 573
Rejestracja: 07 gru 2004, 23:06
Lokalizacja: Sosnowiec
Kontakt:

Post autor: radzio » 12 cze 2009, 7:30

Z jakiego kompilatora korzystasz? U mnie (Raisonance) wynik kompilacji jest następujacy :

Kod: Zaznacz cały

0000 B640                              LD     A,SCISR
0002 B641                              LD     A,SCIDR
0004 B700       F                      LD     temp,A
Jednak sporo zależy od reszty kodu. Zamieść może większy kawałek kodu, łącznie z deklaracją zmiennej temp.

krzysztof-u
-
Posty: 6
Rejestracja: 05 cze 2009, 19:36
Lokalizacja: Słupsk

Post autor: krzysztof-u » 12 cze 2009, 9:22

Korzystam z CXST7 firmy Cosmic pod ST Visual Develop.
To funkcja obsługi przerwania:

Kod: Zaznacz cały

@interrupt void LinSciInterrupt(void) {
	unsigned char temp;
	#ifdef UART_0_TX
	unsigned char temp2;
	if(SCISR & (1<<SCISR_TDRE)) {
		if(uart_0_out_filling) {
			temp2 = uart_0_out_buff[uart_0_out_rd_ptr];
			temp = SCISR;
			SCIDR = temp2;
			uart_0_out_rd_ptr >= (UART_0_OUT_BUFF_SIZE - 1) ? uart_0_out_rd_ptr = 0 : uart_0_out_rd_ptr++;
			uart_0_out_filling--;
		}
		else {  
			UART_0_TX_TDR_EMPTY_INT_DISABLE;            
		}
	}
	#endif
}
A to w asemblerze:

Kod: Zaznacz cały


1680                     ; 146 @interrupt void LinSciInterrupt(void) {
1681                     	switch	.text
1682  012e               _LinSciInterrupt:
1684       00000103      OFST:	set	259
1685  012e 88            	push	a
1686  012f 88            	push	a
1687  0130 88            	push	a
1690                     ; 155 	if(SCISR & (1<<SCISR_TDRE)) {
1692  0131 b640          	ld	a,_SCISR
1693  0133 a580          	bcp	a,#128
1694  0135 2730          	jreq	L5101
1695                     ; 156 		if(uart_0_out_filling) {
1697  0137 3d00          	tnz	_uart_0_out_filling
1698  0139 272a          	jreq	L7101
1699                     ; 157 			temp2 = uart_0_out_buff[uart_0_out_rd_ptr];
1701  013b be01          	ld	x,_uart_0_out_rd_ptr
1702  013d e603          	ld	a,(_uart_0_out_buff,x)
1703  013f 96            	ld	x,s
1704  0140 d70101        	ld	(OFST-2,x),a
1705                     ; 158 			temp = SCISR;
1707  0143 96            	ld	x,s
1708  0144 b640          	ld	a,_SCISR
1709  0146 d70102        	ld	(OFST-1,x),a
1710                     ; 159 			SCIDR = temp2;
1712  0149 96            	ld	x,s
1713  014a d60101        	ld	a,(OFST-2,x)
1714  014d b741          	ld	_SCIDR,a
1715                     ; 165 			uart_0_out_rd_ptr >= (UART_0_OUT_BUFF_SIZE - 1) ? uart_0_out_rd_ptr = 0 : uart_0_out_rd_ptr++;
1717  014f b601          	ld	a,_uart_0_out_rd_ptr
1718  0151 a107          	cp	a,#7
1719  0153 2507          	jrult	L44
1720  0155 3f01          	clr	_uart_0_out_rd_ptr
1721  0157 b601          	ld	a,_uart_0_out_rd_ptr
1722  0159 5f            	clr	x
1723  015a 2005          	jra	L64
1724  015c               L44:
1725  015c b601          	ld	a,_uart_0_out_rd_ptr
1726  015e 3c01          	inc	_uart_0_out_rd_ptr
1727  0160 5f            	clr	x
1728  0161               L64:
1729                     ; 166 			uart_0_out_filling--;
1731  0161 3a00          	dec	_uart_0_out_filling
1733  0163 2002          	jra	L5101
1734  0165               L7101:
1735                     ; 169 			UART_0_TX_TDR_EMPTY_INT_DISABLE;            
1737  0165 1f44          	bres	_SCICR2,#7
Zauważyłem że w asm do rejestrów można odwoływać się przez _NAZWAREJESTRU.
Nie wiem tylko jak się odwołać do zmiennej zadeklarowanej wcześniej w C.

Awatar użytkownika
radzio
Użytkownik
Posty: 573
Rejestracja: 07 gru 2004, 23:06
Lokalizacja: Sosnowiec
Kontakt:

Post autor: radzio » 12 cze 2009, 9:43

Za bardzo komplikujesz sprawę.
Tutaj :

Kod: Zaznacz cały

 if(SCISR & (1<<SCISR_TDRE)) 
już realizujesz dostęp do SCISR, więc po tym wystarczy tylko zapisać SCIDR. Sztuczny odczyt SCISR nie jest już konieczny.

krzysztof-u
-
Posty: 6
Rejestracja: 05 cze 2009, 19:36
Lokalizacja: Słupsk

Post autor: krzysztof-u » 12 cze 2009, 10:01

Tylko że pomiędzy dostępem do SCISR, a zapisem do SCIDR są jeszcze inne instrukcje (warunek, sprawdzenie miejsca w buforze). Czy taka sekwencja, dostęp do SCISR i Zapis SCIDR, rozdzielone innymi instrukcjami też kasuje flagę :?: W pdfie nie wyjaśniają tego dokładnie i przyjąłem że muszą być po kolei. Dzisiaj po południu będę miał płytkę z procesorem to sprawdzę i dam znać co wyszło.

Awatar użytkownika
radzio
Użytkownik
Posty: 573
Rejestracja: 07 gru 2004, 23:06
Lokalizacja: Sosnowiec
Kontakt:

Post autor: radzio » 12 cze 2009, 10:11

Kolejnosć warunków chyba mógłbyś zamienić, bo teraz jak stwierdzisz brak bufora to flagi i tak nie wyzerujesz. Pozatym nie za bardzo mi się podoba wynik kompilacji - masz włączoną optymalizację kodu?

krzysztof-u
-
Posty: 6
Rejestracja: 05 cze 2009, 19:36
Lokalizacja: Słupsk

Post autor: krzysztof-u » 12 cze 2009, 10:39

Samo sprawdzenie źródła przerwania if(SCISR & (1<<SCISR_RDRF)) tworzy 3 instrukcje, a sprawdzać muszę bo przerwanie od SCI jest jedno i w nim dopiero sprawdzam czy to od odbioru, nadawania, czy błędów, więc tu sekwencji kasowania flagi nie wygeneruję.
Co do optymalizacji to mam wszystko wyłączone, model pamięci short.
Tu widać jedną z zalet asemblera, ale nie uśmiecha mi się przepisywać całości (to tylko fragment) w asm.

ODPOWIEDZ