Re: Přerušení od USART na AT91SAM7Sxxx

Tomáš Hamouz hamouz na alsoft.cz
Středa Červen 16 12:45:44 CEST 2010


mpc> Napište sem i inicializační sekvenci.

V podstatě toto. Je to inliniované, některé části jsou vyčleněny jako
samostatná procedura, ale to funkčnost určitě neovliví.

Tomáš

======
void uart0_init(uint16_t bauddiv)
{
   // flush receive buffer
   rx0Head = rx0Tail = 0;
   rxLastTraffic = 0;

   // enable the clock of UART0
   AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_US0);
   // enable uart pins on PIO
   *AT91C_PIOA_PDR = AT91C_PA5_RXD0 | AT91C_PA6_TXD0;
   // select peripheral connection
   *AT91C_PIOA_ASR = AT91C_PA5_RXD0 | AT91C_PA6_TXD0;
   // disable I/O pullup
   *AT91C_PIOA_PPUDR = AT91C_PA5_RXD0;

   // reset the UART
   pUSART0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS |AT91C_US_TXDIS;
   // set serial line mode
   pUSART0->US_MR = AT91C_US_USMODE_NORMAL |    // Normal Mode
                    AT91C_US_CLKS_CLOCK |       // Clock = MCK
                    AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT;   // user-defined data parameters
   // set the baud rate
   pUSART0->US_BRGR = bauddiv;
   // enable the uart
   pUSART0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;

   // attach interrupt handler
   // first disable the interrupt at the AIC
   AT91C_BASE_AIC->AIC_IDCR = (1<<AT91C_ID_US0);
   // set a new interrupt handler routine pointer
   AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0] = (unsigned int)uart0_irq_handler;
   // configure the interrupt - edge mode is not recommended!
   AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0] = UART0_INTERRUPT_LEVEL|AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL;
   // clear the interrupt flag in the AIC
   AT91C_BASE_AIC->AIC_ICCR = (1<<AT91C_ID_US0);
   // enable the interrupt at the AIC
   AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_US0);
   
   // enable receive interrupt
   pUSART0->US_IER = AT91C_US_RXRDY;
}






mpc> Dne 16.6.2010 11:36, Tomáš Hamouz napsal(a):
>> 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;
>> }
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> HW-list mailing list  -  sponsored by www.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>>    


mpc> _______________________________________________
mpc> HW-list mailing list  -  sponsored by www.HW.cz
mpc> Hw-list na list.hw.cz
mpc> http://list.hw.cz/mailman/listinfo/hw-list




More information about the Hw-list mailing list