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.
RS232 na ST7Flite39 z użyciem przerwań.
-
krzysztof-u
- -
- Posty: 6
- Rejestracja: 05 cze 2009, 19:36
- Lokalizacja: Słupsk
Z jakiego kompilatora korzystasz? U mnie (Raisonance) wynik kompilacji jest następujacy :
Jednak sporo zależy od reszty kodu. Zamieść może większy kawałek kodu, łącznie z deklaracją zmiennej temp.
Kod: Zaznacz cały
0000 B640 LD A,SCISR
0002 B641 LD A,SCIDR
0004 B700 F LD temp,A-
krzysztof-u
- -
- Posty: 6
- Rejestracja: 05 cze 2009, 19:36
- Lokalizacja: Słupsk
Korzystam z CXST7 firmy Cosmic pod ST Visual Develop.
To funkcja obsługi przerwania:
A to w asemblerze:
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.
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
}
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
Nie wiem tylko jak się odwołać do zmiennej zadeklarowanej wcześniej w C.
Za bardzo komplikujesz sprawę.
Tutaj :
już realizujesz dostęp do SCISR, więc po tym wystarczy tylko zapisać SCIDR. Sztuczny odczyt SCISR nie jest już konieczny.
Tutaj :
Kod: Zaznacz cały
if(SCISR & (1<<SCISR_TDRE)) -
krzysztof-u
- -
- Posty: 6
- Rejestracja: 05 cze 2009, 19:36
- Lokalizacja: Słupsk
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.
-
krzysztof-u
- -
- Posty: 6
- Rejestracja: 05 cze 2009, 19:36
- Lokalizacja: Słupsk
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.
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.