Přerušení od USART na AT91SAM7Sxxx

Tomáš Hamouz hamouz na alsoft.cz
Středa Červen 16 11:36:58 CEST 2010


Zdravím

Potřeboval bych poradit, kde co dělám špatně.
Jedná se o procesor AT91SAM7S256, tedy ARM architektura.

Ztrácí se mi přerušení od USARTu, takže nastává overun.
Neděje se to vždy, občas přijde celý datagram (cca 50B) v pořádku,
občas ho to nerazegistruje vůbec, většinou z něj zbyde jen část.
Ta část je náhodná, občas chybí začátek, občas konec (zůstane jen
poslední znak), občas uprostřed. Nedaří se mi najít souvislost
s jinými procesy.


Konfigurace:
  timer po 1ms, priorita 7
  externí cca po 10ms, priorita 5
  usart nastavený na 115200, priorita přerušení 6, level sensitive
  hodiny 48MHz

Pokud snížím rychlost, situace se ještě zhorší.
Obslužná procedura jen ukládá přijaté znaky do 256B kruhového bufferu.
Datagram může být max. cca 100B.

Na pozadí běží SPI a I2C komunikace.

Poradíte kde ještě hledat? Ostatní interrupty se zdají být v pořádku,
čas (odvozený od timeru) nijak nekulhá.

Tomáš



Raději přikládám i kód interruptu:
============
static volatile uint8_t rx0Buf[UART_RX_BUFFER_SIZE];    // kruhovy buffer
static volatile uint8_t rx0Head;                // ukazatele do bufferu
static volatile uint8_t rx0Tail;
static volatile uint32_t rxLastTraffic;         // cas posledniho prijateho znaku
static volatile uint32_t rxOverflow = 0;        // citac celkoveho poctu ztracenych znaku

void  __attribute__ ((interrupt ("IRQ"))) uart0_irq_handler()
{
   unsigned int status;
   uint8_t tmphead;
   uint8_t nxthead;
   volatile uint8_t c;
   
   status  = pUSART0->US_CSR;
   if (status & AT91C_US_RXRDY)
   {
      // overrun occured?
      if (status & AT91C_US_OVRE)
         rxOverflow++;  // treat overrun as overflow

      // calculate buffer index
      tmphead = rx0Head;
      nxthead = (tmphead + 1) & UART_RX_BUFFER_MASK;
      c = pUSART0->US_RHR;
      if (nxthead == rx0Tail)
      {
         // ERROR! Receive buffer overflow
         rxOverflow++;
      }
      else
      {
         rx0Buf[tmphead] = c;
         rx0Head = nxthead;             // Store new index
      }

      // mark last received timestamp
      rxLastTraffic = getSystemTickCount();  // jen precte pocet ms
   }

   // reset error status bits
   pUSART0->US_CR = AT91C_US_RSTSTA;

   // clear AIC
   AT91C_BASE_AIC->AIC_EOICR = 0;
}

  
  





More information about the Hw-list mailing list