www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR32 UC3A1512 USART1 TXEMPTY Interrupt Problem


Autor: Billy __ (slowflyer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hab da ein Problem mit dem TXEMPTY Interrupt des UC3A1512 (AVR32).

Ich möchte auf einer Leitung senden und empfangen, dafür schalte ich den 
Transmitter zum Senden an und für den Empfang ab (Master Slave 
Kommunikation). Um einen Datenblock zu senden verwende ich den TXRDY 
Interrupt (was wunderbar funktioniert) zum Abschalten des Transmitters 
hätte ich gerne den TXEMPTY Interrupt verwendet um den Sender 
abzuschalten und auf Empfang zu schalten. In der Theorie sollte das 
gehen (bereits in einem AVR realisiert) doch nun zur Praxis:

TXEMPTY Interrupt ist aktiviert und in der ISR behandelt. Das Problem 
ist: die Stelle in  der ISR , die dafür vorgesehen ist (siehe Pfeil in 
der ISR), wird nicht angesprungen. Warum?

hier ein paar Codeteile:

Initialisierung:
init_usart1()
{
static const gpio_map_t USART1_GPIO_MAP =
  {
    {USART1_RX_PIN, USART1_RX_FUNCTION},
    {USART1_TX_PIN, USART1_TX_FUNCTION}
  };
  
  // Options for debug USART.
  usart_options_t USART1_options =
  {
    .baudrate = USART1_BAUDRATE,
    .charlength = 8,
    .paritytype = USART_NO_PARITY,
    .stopbits = USART_1_STOPBIT,
    .channelmode = USART_NORMAL_CHMODE
  };

  // Setup GPIO
  gpio_enable_module(USART1_GPIO_MAP, sizeof(USART1_GPIO_MAP) / sizeof(USART1_GPIO_MAP[0]));
  
  
  // Initialize it in RS232 mode.
  usart_init_rs232(USART1, &USART1_options, FPBA);
  USART1->cr = AVR32_USART_CR_RXEN_MASK|AVR32_USART_CR_TXDIS_MASK;
  
  // Init interrupt and timeout
  INTC_register_interrupt(&USART1_isr, AVR32_USART2_IRQ, AVR32_INTC_INT1);
  USART1->ier = AVR32_USART_IER_RXRDY_MASK|AVR32_USART_IER_TXRDY_MASK|AVR32_USART_IER_TIMEOUT_MASK|AVR32_USART_IER_TXEMPTY_MASK;
  USART1->rtor = 50;
  USART1->ttgr = 1;

ISR:
__attribute__((__interrupt__)) void USART1_isr( void )
{

  unsigned char cs = 0;
  int rx_char = 0, i;
  
  if (USART1->csr & AVR32_USART_CSR_TIMEOUT_MASK)
  {
    USART1->cr |= AVR32_USART_CR_STTTO_MASK;
    
    //TODO empfang

    // disable receiver
    USART1->idr = AVR32_USART_IDR_RXRDY_MASK;
  }
  else if (USART1->csr & AVR32_USART_CSR_TXRDY_MASK)
  {
    if (tx_ptr < length) 
    {
      USART1->thr = (tx_buffer[tx_ptr++] << AVR32_USART_THR_TXCHR_OFFSET) & AVR32_USART_THR_TXCHR_MASK;
    }
  }
  else if (USART1->csr & AVR32_USART_CSR_TXEMPTY_MASK)
  {
    // disable transmitter
-->    USART1->cr = AVR32_USART_CR_TXDIS_MASK;
  }
  else if (USART1->csr & AVR32_USART_CSR_RXRDY_MASK)
  {
    if ( usart_read_char(USART1, &rx_char) == USART_SUCCESS)
    {
        rx_buffer[rx_ptr++] = (char) rx_char;
    }
  }
}

Hat jemand eine Idee oder Hinweis woran es scheitert?

Gruß Willi

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Prozessor kenne ich nur vom oberflächlichen Lesen des Datenblattes. 
Was mich zunächst wundert: gibt es nur einen Interruptvector für USART1? 
Keinen für Rx1, Tx1 und TxEmpty1?

Egal.
Stimmt der Wert von AVR32_USART_CSR_TXEMPTY_MASK? Hast Du die Abfrage 
auf TxE mal ganz an den Anfang der Int-Routine gestellt? Wird das 
enable-Bit vielleicht irgendwo gelöscht? Sind Lesezugriffe auf 
USART1->csr vielleicht destruktiv? Könntest Du TxE explizit noch einmal 
aktivieren, wenn der Puffer der zu sendenen Zeichen leer ist (tx_ptr >= 
length)?

Autor: Billy __ (slowflyer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> Was mich zunächst wundert: gibt es nur einen Interruptvector für USART1?
> Keinen für Rx1, Tx1 und TxEmpty1?

Genau so ist es (werden durch Abfragen des CSR in der ISR unterschieden)

> Stimmt der Wert von AVR32_USART_CSR_TXEMPTY_MASK?

Stimmt (als 0x00000200 definiert in der Header-Datei), vgl. Datenblatt

> Hast Du die Abfrage
> auf TxE mal ganz an den Anfang der Int-Routine gestellt? Wird das
> enable-Bit vielleicht irgendwo gelöscht? Sind Lesezugriffe auf
> USART1->csr vielleicht destruktiv?

Das glaub ich weniger, denn sonst würde der Empfangs-Interrupt auch nie 
durchkommen (am Ende).

> Könntest Du TxE explizit noch einmal
> aktivieren, wenn der Puffer der zu sendenen Zeichen leer ist (tx_ptr >=
> length)?

Auch schon probiert, leider ohne Erfolg

Ich seh schon, wird eine harte Nuss...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das glaub ich weniger, ...

Ich glaube an nichts und mache es daher trotzdem.

Ein weiter Schritt wäre, am Anfang gleich mit:

unsigned long csr_temp = USART1->csr;

den aktuellen Wert zu retten und mit diesem die Vergleiche 
durchzuführen. Da Du offensichtlich keine großen Möglichkeiten zur 
Fehlersuche hast, könntest Du auch an einem Ausgang eine LED aktivieren, 
sobald ein TxEmpty-Zustand erkannt wird (nicht wieder löschen!). Damit 
könnte festgestellt werden, ob jemals das Bit überhaupt gesetzt wurde.

....

Autor: Sab (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"RS485 AVR32* "
Der mode ist z.B für RS458
Google mal mit dem stichwort RS485 AVR32.
Aber im Google "CodeSearch".
Da sind die Code Beispiele für diesen Mode drin.
Die IRQ Vectoren ca 10 Stück.

Autor: Sab (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So solten die Suchergebnisse dan kommen.
Du soltest das z.B auf RS485 einstellen.
Um das z.B Transmit Register Empty zu bekommen.
/*---------------------------------------------------------------------- 
-----+
 | 
|
 |                         TRANSMIT/RECEIVE FUNCTIONS         |
 | 
|
 +----------------------------------------------------------------------- 
----*/

/**
 * Description: While in RS485-mode, receviers only accept data 
addressed to them.
 *              A packet/char with the address tag set has to preceed 
any data.
 *              usart_send_addr() is used to address a receiver. This 
receiver should read
 *              all the following data, until an address packet 
addresses someone else.
 * Arguments:   *usart:  Base address of the usart
 *              addr: the address of the target device
 * Returns:     USART_SUCCESS if the current mode is RS485
 *              USART_MODE_FAULT if called while in wrong mode
 */
int usart_send_addr(volatile struct avr32_usart_t * usart, int addr);


/*!
 * If the transmitter is ready; write the given character to the TX 
buffer
 * 'param *usart  Base address of the usart
 * 'param c       The character (up to 9 bits) to transmit
 * 'return        USART_SUCCESS when the transmitter is ready
 *                USART_TX_BUSY when the transmitter is busy
 */

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sab

Deinem Vorschlag folgend, habe ich versucht über die Suchmaschine etwas 
in Erfahrung zu bringen: ohne Erfolg.
Hast Du vielleicht eine Quelle beim Hersteller, wo man die erwähnten 
"IRQ Vectoren ca 10 Stück" dokumentiert hat. Im Datenblatt des 
AT32UC3A... scheinen sie nicht aufgeführt zu sein.

Autor: Billy __ (slowflyer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt mal folgendes ausprobiert:

- hab die if else if else Verschachtelungen in der ISR in ganz normale 
if if if aufgebrochen

- CSR habe ich in eine Variable eingelesen und diese auf die Int-Flags 
geprüft (falls das Lesen destruktiv wirkt)

Und siehe da! Es geht juhu!!!

Welche von beiden Maßnahmen nun geholfen hat, weiss ich nicht (evtl. 
sogar beide). Hab jetzt auch kaum Zeit um es herauszufinden. Mal sehen 
vielleicht mal in einer etwas ruhigeren Minute. Im Moment bin ich 
einfach nur froh, dass es tut.

Danke für die Hinweise, ich hätt mir sonst einen Wolf gesucht

Gruß Willi

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe Deine Erfolgsmeldung erst heute gelesen - nun ist ja gut!
Ich tippe ja auf das destruktive Lesen des Status. Was mich aber nach 
wie vor irritiert, daß es nur einen Interruptvektor für die USART gibt. 
Das erinnert doch sehr an 8051 & Co.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.