[ECOS] AT91 serial port usage (and other AT91 stuff)

harri.siirtola@vtt.fi harri.siirtola@vtt.fi
Mon Oct 29 09:15:00 GMT 2001


At 09:36 14.8.2001 -0600, Gary Thomas wrote:
>
>On 14-Aug-2001 Jonathan Larmour wrote:
>> The only oddities I see are:
>> 
>> - start_xmit and stop_xmit both write the same thing to the IER which seems
>> curious, but possible
>
>The 'stop_write' function should really write to IDR (Interrupt Disable Register)

There are some significant improvements that should be added to the AT91 port. I've modified at91_serial.c like this:

In variable declarations:

#define	SERIAL_RINGBUFSIZE	32


static unsigned char Rx_Ringbuf_0[SERIAL_RINGBUFSIZE];
static unsigned char *Ser0_Dptr = Rx_Ringbuf_0;
static cyg_uint32 CCnt_0 = SERIAL_RINGBUFSIZE;

static unsigned char Rx_Ringbuf_1[SERIAL_RINGBUFSIZE];
static unsigned char *Ser1_Dptr = Rx_Ringbuf_1;
static cyg_uint32 CCnt_1 = SERIAL_RINGBUFSIZE;


In function at91_serial_config_port:

if (base == AT91_USART0) {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_0);
HAL_WRITE_UINT32(base+AT91_US_RCR, SERIAL_RINGBUFSIZE);
} else {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_1);
HAL_WRITE_UINT32(base+AT91_US_RCR, SERIAL_RINGBUFSIZE);
}


In at91_serial_DSR:

if (stat & AT91_US_IER_RxRDY) {
if (base == AT91_USART0) {
do {
HAL_READ_UINT32(base+AT91_US_RCR, c);
if (CCnt_0 == c) {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_0);
HAL_WRITE_UINT32(base+AT91_US_RCR, (cyg_uint32)SERIAL_RINGBUFSIZE);
CCnt_0 = SERIAL_RINGBUFSIZE;
Ser0_Dptr = Rx_Ringbuf_0;
break;
}
(chan->callbacks->rcv_char)(chan, *(Ser0_Dptr++));
CCnt_0--;
if (CCnt_0 == 0) {
CCnt_0 = SERIAL_RINGBUFSIZE;
Ser0_Dptr = Rx_Ringbuf_0;
}
if (c == 0) {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_0);
HAL_WRITE_UINT32(base+AT91_US_RCR, (cyg_uint32)SERIAL_RINGBUFSIZE);
}
} while (true);
} else {
do {
HAL_READ_UINT32(base+AT91_US_RCR, c);
if (CCnt_1 == c) {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_1);
HAL_WRITE_UINT32(base+AT91_US_RCR, (cyg_uint32)SERIAL_RINGBUFSIZE);
CCnt_1 = SERIAL_RINGBUFSIZE;
Ser1_Dptr = Rx_Ringbuf_1;
break;
}
(chan->callbacks->rcv_char)(chan, *(Ser1_Dptr++));
CCnt_1--;
if (CCnt_1 == 0) {
CCnt_1 = SERIAL_RINGBUFSIZE;
Ser1_Dptr = Rx_Ringbuf_1;
}
if (c == 0) {
HAL_WRITE_UINT32(base+AT91_US_RPR, (cyg_uint32)Rx_Ringbuf_1);
HAL_WRITE_UINT32(base+AT91_US_RCR, (cyg_uint32)SERIAL_RINGBUFSIZE);
}
} while (true);
}


The AT91 port seems to use a FIFO-like approach in polling the RX register. My approach uses the Peripheral Data Controller (it's like DMA), otherwise overruns are inevitable with greater transfer rates. Transmit functions should also utilize the PDC, just write the data pointer to US_TPR and char count to US_TCR and transmit occurs in the background. Much less overhead, too.

Another thing to be done in hardware initialization:


void AT91_pio_init(void)
{
CYG_ADDRESS pio = AT91_PIO;
CYG_ADDRESS ps = AT91_PS;

HAL_WRITE_UINT32(pio+AT91_PIO_PER, 0xFFFFFFFF);	// PIO enable
HAL_WRITE_UINT32(pio+AT91_PIO_PDR, (P22 | P21 | P15 | P14));	// Disable PIO control of all USART Tx & Rx pins
HAL_WRITE_UINT32(ps+AT91_PS_PCER, 0x7C);				// Enable all clocks
}


The Angel monitor does all this so the EB40 card works until you ditch Angel... The clock enable is especially important as you cannot write to USART registers without enabling the clocks.

So if someone just had the time to finish this... I can't get the proper copyright assignment from my employer.

Later,
Harri




More information about the Ecos-discuss mailing list