RTV forum PL | NewsGroups PL

Jak skonfigurować przerwanie UART TX w ARM LPC2148 dla poprawnej transmisji?

Przerwanie Uart TX w ARM

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Jak skonfigurować przerwanie UART TX w ARM LPC2148 dla poprawnej transmisji?

Piotr \"Pitlab\" Laskowsk
Guest

Thu Dec 04, 2008 2:59 pm   



Witajcie
Zaczynam zabawę z ARM LPC2148. Nie mogę sobie poradzić z transmisją przez
UART w trybie przerwań.
Do tej pory w 8051 czy AVR robiłem bufor nadawczy i odbiorczy. Wysyłając
kilka znaków wpisywałem do bufora i inicjowałem transmisję a w obsłudze
przerwania z bufora były pobierane kolejne znaki aż do opróżnienia.
Analogicznie z odbiorem - przychodziło do bufora a w wolnej chwili
odczytywałem to co przyszło.

W ARM poradziłem sobie z transmisją przychodzącą ale już drugi dzień siedzę
i nie mogę uzyskać przerwania od wysłania znaku. Jeżeli pierwszy bajt danych
wrzucę "ręcznie" do U0THR to wychodzi na zewnątrz, ale nie jest poprawnie
zgłaszane przerwanie.

W U0IER mam włączone zezwolenia na przerwania od nadawania i odbioru:
UIER_ERB | UIER_THRE

Zainstalowałem sobie ewaluacyjną wersję CrossStudio i debuguję rejestry. Po
wysłaniu znaku widzę w U0IIR InterruptPending = 0 (jest przerwanie),
Interrupt_Identification = 1 (THRE), czyli niby wszystko OK, ale nie ustawia
się bit przerwania od UARTA w VICIRQStatus (= 0).
Doszedłem do etapu że wchodzę do obsługi przerwania, dochodzę do makra
IS_ENTRY i po przejściu kasują mi się flagi w U0IIR i nie ma śladu po
przerwaniu. Oczywiście nie moze być poprawnie obsłużone.
Jeżeli przychodzi znak z zewnątrz, jest odpowiednia flaga w VICIRQStatus,
poprawnie wchodzę do obsługi przerwania i odczytuję znak.

Próbowałem debugować różne przykładowe programy z takim samym efektem.

Konfiguracja UARTa wygląda tak: Uart0Init(B9600, UART_8N1, UART_FIFO_1)
////////////////////////////////////////////////////////////////////////////////
uint16_t Uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode)
{
U0IER = 0x00; // disable all interrupts
U0IIR; // clear interrupt ID
U0RBR; // clear receive register
U0LSR; // clear line status register

// set the baudrate
U0LCR = ULCR_DLAB_ENABLE; // select divisor latches
U0DLL = (uint8_t)baud; // set for baud low byte
U0DLM = (uint8_t)(baud >> Cool; // set for baud high byte

// set the number of characters and other
// user specified operating parameters
U0LCR = (mode & ~ULCR_DLAB_ENABLE);
U0FCR = fmode;

//initialize the interrupt vector
VICIntSelect &= ~VIC_BIT(UART0_INT); // UART0 selected as IRQ
VICVectCntl0 = VIC_ENABLE | UART0_INT;
VICVectAddr0 = (uint32_t)Uart0ISR; // address of the ISR
VICIntEnable = VIC_BIT(UART0_INT); // UART0 interrupt enabled

//inicjuj zmienne obsługi buforów kołowych
wsk_ob0n = 0;
wsk_nb0n = 0;
wsk_ob0o = 0;
wsk_nb0o = 0;

U0FCR = 1;

//włacz przerwania
U0IER = UIER_ERB | UIER_THRE;
return (TRUE);
}

wysyłanie znaku mam zrobione taką procedurą:
////////////////////////////////////////////////////////////////////////////////
void PutChar0 (uint8_t ch)
{
unsigned cpsr;

while (buf0_nad_size == UART0_TX_BUFFER_SIZE); // czekaj az bedzie miejsce
w buforze

cpsr = disableIRQ(); // disable global interrupts
U0IER &= ~UIER_THRE; //wyłącz przerwanie wysyłania
restoreIRQ(cpsr); // restore global interrupts

//sprawdź czy trwa wysyłanie danych
if (uart0_tx_running)
{
uart0_tx_buf[wsk_nb0n++] = ch;
if (wsk_nb0n == UART0_TX_BUFFER_SIZE)
wsk_nb0n = 0;
buf0_nad_size++;
}
else
{
// set running flag and write to output register
uart0_tx_running = TRUE;
U0THR = (uint8_t)ch;
}

cpsr = disableIRQ(); // disable global interrupts
U0IER |= UIER_THRE; //włącz przerwanie wysyłania
restoreIRQ(cpsr); // restore global interrupts
}

Jeżeli możecie wskazać jakąś ścieżkę, albo podrzucić działający przykład,
będę wdzięczny.

--
Piotrek.
http://www.pitlab.pl

Konop
Guest

Thu Dec 04, 2008 4:45 pm   



Piotr "Pitlab" Laskowski pisze:
[quote:c161b26d40]Witajcie
Zaczynam zabawę z ARM LPC2148. Nie mogę sobie poradzić z transmisją przez
UART w trybie przerwań.
Do tej pory w 8051 czy AVR robiłem bufor nadawczy i odbiorczy. Wysyłając
kilka znaków wpisywałem do bufora i inicjowałem transmisję a w obsłudze
przerwania z bufora były pobierane kolejne znaki aż do opróżnienia.
Analogicznie z odbiorem - przychodziło do bufora a w wolnej chwili
odczytywałem to co przyszło.

W ARM poradziłem sobie z transmisją przychodzącą ale już drugi dzień siedzę
i nie mogę uzyskać przerwania od wysłania znaku. Jeżeli pierwszy bajt danych
wrzucę "ręcznie" do U0THR to wychodzi na zewnątrz, ale nie jest poprawnie
zgłaszane przerwanie.

W U0IER mam włączone zezwolenia na przerwania od nadawania i odbioru:
UIER_ERB | UIER_THRE

Zainstalowałem sobie ewaluacyjną wersję CrossStudio i debuguję rejestry. Po
wysłaniu znaku widzę w U0IIR InterruptPending = 0 (jest przerwanie),
Interrupt_Identification = 1 (THRE), czyli niby wszystko OK, ale nie ustawia
się bit przerwania od UARTA w VICIRQStatus (= 0).
Doszedłem do etapu że wchodzę do obsługi przerwania, dochodzę do makra
IS_ENTRY i po przejściu kasują mi się flagi w U0IIR i nie ma śladu po
przerwaniu. Oczywiście nie moze być poprawnie obsłużone.
Jeżeli przychodzi znak z zewnątrz, jest odpowiednia flaga w VICIRQStatus,
poprawnie wchodzę do obsługi przerwania i odczytuję znak.

Próbowałem debugować różne przykładowe programy z takim samym efektem.

Konfiguracja UARTa wygląda tak: Uart0Init(B9600, UART_8N1, UART_FIFO_1)
////////////////////////////////////////////////////////////////////////////////
uint16_t Uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode)
{
U0IER = 0x00; // disable all interrupts
U0IIR; // clear interrupt ID
U0RBR; // clear receive register
U0LSR; // clear line status register

// set the baudrate
U0LCR = ULCR_DLAB_ENABLE; // select divisor latches
U0DLL = (uint8_t)baud; // set for baud low byte
U0DLM = (uint8_t)(baud >> Cool; // set for baud high byte

// set the number of characters and other
// user specified operating parameters
U0LCR = (mode & ~ULCR_DLAB_ENABLE);
U0FCR = fmode;

//initialize the interrupt vector
VICIntSelect &= ~VIC_BIT(UART0_INT); // UART0 selected as IRQ
VICVectCntl0 = VIC_ENABLE | UART0_INT;
VICVectAddr0 = (uint32_t)Uart0ISR; // address of the ISR
VICIntEnable = VIC_BIT(UART0_INT); // UART0 interrupt enabled

//inicjuj zmienne obsługi buforów kołowych
wsk_ob0n = 0;
wsk_nb0n = 0;
wsk_ob0o = 0;
wsk_nb0o = 0;

U0FCR = 1;

//włacz przerwania
U0IER = UIER_ERB | UIER_THRE;
return (TRUE);
}

wysyłanie znaku mam zrobione taką procedurą:
////////////////////////////////////////////////////////////////////////////////
void PutChar0 (uint8_t ch)
{
unsigned cpsr;

while (buf0_nad_size == UART0_TX_BUFFER_SIZE); // czekaj az bedzie miejsce
w buforze

cpsr = disableIRQ(); // disable global interrupts
U0IER &= ~UIER_THRE; //wyłącz przerwanie wysyłania
restoreIRQ(cpsr); // restore global interrupts

//sprawdź czy trwa wysyłanie danych
if (uart0_tx_running)
{
uart0_tx_buf[wsk_nb0n++] = ch;
if (wsk_nb0n == UART0_TX_BUFFER_SIZE)
wsk_nb0n = 0;
buf0_nad_size++;
}
else
{
// set running flag and write to output register
uart0_tx_running = TRUE;
U0THR = (uint8_t)ch;
}

cpsr = disableIRQ(); // disable global interrupts
U0IER |= UIER_THRE; //włącz przerwanie wysyłania
restoreIRQ(cpsr); // restore global interrupts
}

Jeżeli możecie wskazać jakąś ścieżkę, albo podrzucić działający przykład,
będę wdzięczny.

[/quote:c161b26d40]
Ja się bawiłem LPC2378 i 2364, one są nowsze, mają trochę rozbudowane
peryferia, więc to może nie działać... ale poszukaj w dokumentacji Smile..
te LPC23xx miały wbudowany taki bufor do nadawania i do odbierania... I
pierwszy znak jaki wpisywało się do U0THR trafiał od razu do nadajnika,
kolejne (jeśli były wpisane do U0THR zanim pierwszy się "nadał")
trafiały do kolejki FIFO... natomiast przerwanie było zgłaszane tylko po
opróżnieniu FIFO... mówiąc inaczej - jeśli wysyłałeś po 1 znaku - nie
było zgłaszane przerwanie... trzeba po prostu zrobić inną filozofię Smile...
Ewentualnie poszukaj w rejestrach do UARTa jakiś odpowiadających za to
"kiedy zgłaszane jest przerwanie"... może tam znajdziesz jednak coś
odpowiedniego Smile..
Ja piszę z pamięci, więc jak będą jakieś nieścisłości, to przepraszam...

Pozdrawiam
Konop

Piotr \"Pitlab\" Laskowsk
Guest

Thu Dec 04, 2008 5:25 pm   



Quote:
LPC23xx miały wbudowany taki bufor do nadawania i do odbierania... I
pierwszy znak jaki wpisywało się do U0THR trafiał od razu do nadajnika,
kolejne (jeśli były wpisane do U0THR zanim pierwszy się "nadał") trafiały
do kolejki FIFO... natomiast przerwanie było zgłaszane tylko po
opróżnieniu FIFO... mówiąc inaczej - jeśli wysyłałeś po 1 znaku - nie było
zgłaszane przerwanie... trzeba po prostu zrobić inną filozofię Smile...

O dzięki! to brzmi bardzo rozsądnie. Tutaj też jest FIFO, chociaż jest
ustawione na rozmiar jednego znaku, więc prawdopodobnie wystarczy wpisać 2
znaki. Spróbuję usiaść do tego w nocy.

--
Piotrek.
http://www.pitlab.pl

Paweł Cern
Guest

Thu Dec 04, 2008 8:20 pm   



Użytkownik "Piotr "Pitlab" Laskowski" <pitlab@pulapka.wp.pl> napisał w
wiadomości news:gh8o4c$91i$1@mx1.internetia.pl...
Quote:
Witajcie
Zaczynam zabawę z ARM LPC2148. Nie mogę sobie poradzić z transmisją przez
UART w trybie przerwań.
Do tej pory w 8051 czy AVR robiłem bufor nadawczy i odbiorczy. Wysyłając
kilka znaków wpisywałem do bufora i inicjowałem transmisję a w obsłudze
przerwania z bufora były pobierane kolejne znaki aż do opróżnienia.
Analogicznie z odbiorem - przychodziło do bufora a w wolnej chwili
odczytywałem to co przyszło.

....

....

Zobacz czy są jakieś erraty do tego układu. Bawiłem się kiedyś starszym LPC
(chyba LPC2136) i z erraty wynikało, że układ został straszliwie skopany,
trzeba było robić wiele obejść a niektóre rzeczy nie dawały się zrealizować.
Lepszym wyborem jest Atmel.

PC

Konop
Guest

Thu Dec 04, 2008 10:43 pm   



Paweł Cern pisze:
Quote:

Użytkownik "Piotr "Pitlab" Laskowski" <pitlab@pulapka.wp.pl> napisał w
wiadomości news:gh8o4c$91i$1@mx1.internetia.pl...
Witajcie
Zaczynam zabawę z ARM LPC2148. Nie mogę sobie poradzić z transmisją
przez UART w trybie przerwań.
Do tej pory w 8051 czy AVR robiłem bufor nadawczy i odbiorczy.
Wysyłając kilka znaków wpisywałem do bufora i inicjowałem transmisję a
w obsłudze przerwania z bufora były pobierane kolejne znaki aż do
opróżnienia. Analogicznie z odbiorem - przychodziło do bufora a w
wolnej chwili odczytywałem to co przyszło.

...
...

Zobacz czy są jakieś erraty do tego układu. Bawiłem się kiedyś starszym
LPC (chyba LPC2136) i z erraty wynikało, że układ został straszliwie
skopany, trzeba było robić wiele obejść a niektóre rzeczy nie dawały się
zrealizować. Lepszym wyborem jest Atmel.

Może masz rację z tym Atmelem, ale trzeba przyznać, że Philips/NXP wiele
poprawił Smile... pierwsze wersje miały skopane dużo, kolejne trochę
mniej.. te 23xx są już chyba OK Smile... Tzn. nie słyszałem, żeby ktoś
narzekał Wink... no ale rozumiem, pewnie jakbym się zraził na początku, to
bym patrzył tak samo, jak Ty ;)

Pozdrawiam!
Konop

Piotr \"Pitlab\" Laskowsk
Guest

Thu Dec 04, 2008 11:28 pm   



Quote:
Zobacz czy są jakieś erraty do tego układu. Bawiłem się kiedyś starszym
LPC (chyba LPC2136) i z erraty wynikało, że układ został straszliwie
skopany, trzeba było robić wiele obejść a niektóre rzeczy nie dawały się
zrealizować. Lepszym wyborem jest Atmel.

Właśnie przejrzałem erratę, ale nie wspomina o problemach z UARTem.
Zrobiłem kilka prób z wysyłaniem paczek danych i widzę że coś zaczyna się
dziać z przerwaniem. Jeszcze nie jest to czego oczekuję, ale może jeszcze
nie wszystko rozumiem. Dokumentacja jest jednak dosyć uboga, jest tylko
suchy opis rejestrów. Noty aplikacyjne kończą się na wpisaniu pojedyńczego
znaku do rejestru wysyłającego bez użycia przerwań. Jeszcze muszę znaleźć
jakąś dokumentację do standardowego uarta 550, bo piszą że zaimplementowany
w kontrolerze jest jego odpowiednikiem.
Co do Atmela: Rozpisałem sobie "konkurs użyteczności w moim projekcie" na 3
ARMy od Atmela, NXP i AD. Porównywałem głównie pod kątem dopasowania
peryferiów, bo to jest aplikacja mocno "usprzętowiona". Seria LPC wydała mi
się najodpowiedniejsza z podwójnym UARTem i SPI, pełniejszym USB, bateryjnym
podtrzymaniem zegara. Teraz zdaję sobie sprawę że porównywanie na tym
poziomie abstrakcji jest dosyć pobieżne, ale dopóki nie zacznie się pracy z
układem większości problemów nie da się zobaczyć :-)

--
Piotrek.
http://www.pitlab.pl

Adam Dybkowski
Guest

Fri Dec 05, 2008 12:42 am   



Paweł Cern pisze:

Quote:
Zobacz czy są jakieś erraty do tego układu. Bawiłem się kiedyś starszym
LPC (chyba LPC2136) i z erraty wynikało, że układ został straszliwie
skopany, trzeba było robić wiele obejść a niektóre rzeczy nie dawały się
zrealizować. Lepszym wyborem jest Atmel.

Nie mów hop.
Atmel także ma pokaźne erraty w prockach serii AT91SAM7 a jeszcze
grubsze w AT91SAM9. Do tego dochodzą błędy nie opisane w erratach, na
których już w firmie zęby sobie połamaliśmy (np. dziwaczne zachowanie
polaryzacji linii zegara SPI przed pierwszym dostępem do danego urządzenia).

--
Adam Dybkowski
http://dybkowski.net/

Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.

elektroda NewsGroups Forum Index - Elektronika Polska - Jak skonfigurować przerwanie UART TX w ARM LPC2148 dla poprawnej transmisji?

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map