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