📄 serial.c
字号:
if ( ! Angel_FindParam( AP_BAUD_RATE, conf, &speed ) )
{
LogWarning(LOG_SERIAL, ("serial_set_params: Speed parameter not found in config\n"));
return DE_OKAY;
}
switch (speed)
{
case 1200:
baud_word = BAUD_DEB;
break;
case 9600:
baud_word = BAUD_009;
break;
case 19200:
baud_word = BAUD_019;
break;
case 38400:
baud_word = BAUD_038;
break;
case 57600:
baud_word = BAUD_057;
break;
case 115200:
baud_word = BAUD_115;
break;
default: return DE_BAD_OP;
}
LogInfo(LOG_SERIAL, ("serial_set_params: Speed %d (csr: 0x%x, acr: 0x%x)\n",
speed, baud_value, acr));
/* Enable the transmitter to enable the TXEMPTY to be set */
/* Has no effect if the transmitter is already enabled */
usart_pt->US_CR = ENABLETX ;
if ( usart_pt->US_BRGR == 0 )
{
usart_pt->US_BRGR = baud_word;
}
/* Wait for the end of transmission (interrupts must be enabled) */
while (( usart_pt->US_CSR & TXEMPTY ) == 0 ) ;
/* Reset the queue tx deferred flag */
queue_tx_deferred = FALSE ;
angel_DeviceStatus[DI_SERIAL] |= SER_TX_KICKSTART;
/* Disable receiver and transmitter */
usart_pt->US_CR = DISABLERX|DISABLERX ;
/* Check that the PDC System isn't interfering */
usart_pt->US_RPR = 0;
usart_pt->US_RCR = 0;
usart_pt->US_TPR = 0;
usart_pt->US_TPR = 0;
/* Disable all interrupts on the USART */
usart_pt->US_IDR = 0x3FF;
/* Disable the USART0 interrupt */
/* aic_pt->AIC_IDCR = 1<<IRQ_ANGEL ; */
/* Reset the receiver and the transmitter */
usart_pt->US_CR = RESETRX | RESETTX ;
/* Wait for the resets to be effective : at least one bit period */
for ( i = (usart_pt->US_BRGR*16) ; i > 0 ; i -- ) ;
/* Enable pads as peripheral */
*PIO_PDR_USART = PIO_USART_ANGEL ;
usart_pt->US_MR = INTCLK | /* Internal Clock */
CHAR8BIT | /* 8 bit Chars */
ASYNC | /* Asynch clock mode */
NOPARITY | /* No Parity */
STOP1BIT | /* 1 Stop Bit */
NORMAL; /* Channel Mode */
/* Disable the Reception Timeout */
usart_pt->US_RTOR = 0 ;
usart_pt->US_BRGR = baud_word;
usart_pt->US_IER = OVRE | FRAME | PARE | RXRDY ;
/* Setup the USART0 interrupt in the AIC */
aic_pt->AIC_SMR[IRQ_ANGEL] = 0x07;
aic_pt->AIC_SVR[IRQ_ANGEL] = (int) angel_DeviceInterruptHandler ;
/* Re-enable the USART 0 interrupt */
aic_pt->AIC_IECR = 1<<IRQ_ANGEL ;
/* Enable receiver and transmitter */
usart_pt->US_CR = ENABLETX | ENABLERX ;
return DE_OKAY;
}
/*
* Set the LED on the PIE board - uses serial chip controller (!!!)
*/
void set_led( char state)
{
*PIO_PER = ( LED2BIT | LED1BIT );
if ( state & LED1)
*PIO_SODR = LED1BIT;
if ( state & LED2)
*PIO_SODR = LED2BIT;
}
/*
* Set the LED on the PIE board - uses serial chip controller (!!!)
*/
void clear_led( char state)
{
*PIO_PER = ( LED2BIT | LED1BIT );
if ( state & LED1)
*PIO_CODR = LED1BIT;
if ( state & LED2)
*PIO_CODR = LED2BIT;
}
/*
* implementation of device control for serial driver
*
* devid is guaranteed to be in range but op is not checked as
* individual devices can extend the range of operations
*/
static DevError serial_Control(DeviceID devid,
DeviceControl op, void *arg)
{
DevError ret_code;
LogInfo(LOG_SERIAL, ("serial_Control: op %d arg %x\n", op, arg ));
/* we only implement the standard ones here */
switch( op )
{
case DC_INIT:
ret_code = serial_init(devid);
break;
case DC_RESET:
ret_code = serial_reset(devid);
break;
case DC_RECEIVE_MODE:
ret_code = serial_recv_mode(devid, (DevRecvMode)((int)arg));
break;
case DC_SET_PARAMS:
ret_code = serial_set_params(devid, (const ParameterConfig *)arg);
break;
case DC_SET_LED:
break;
default:
ret_code = DE_BAD_OP;
break;
}
return ret_code;
}
/* Loop Number for a Wait of a character */
#define SR_POLL_TIMEOUT_COUNT 100
static char rx_preread_char;
/*
* Function: serial_rx_processing
* Purpose: Read a stream of characters from the unbuffered
* serial port
*
* Params: (via args)
* Input: device ident of the serial device
*
* Returns: Nothing
*/
static void serial_rx_processing(void *args)
{
StructUSART *usart_pt = USART_ANGEL_BASE ;
DeviceID devid = (DeviceID)args;
bool done = FALSE ;
bool timeout = FALSE ;
unsigned int i ;
while (( timeout == FALSE ) && ( done == FALSE ))
{
if ( ringBufFull( &serial_rx_ring ))
{
LogError(LOG_SERIAL, ("rx ring buffer overflow\n" ));
done = TRUE ;
}
else
{
/* Put the new character in the ring buffer */
ringBufPutChar( &serial_rx_ring, rx_preread_char ) ;
/* If character is end of packet or ring buffer is nearly full */
if (( rx_preread_char == serial_ETX ) ||
(ringBufCount( &serial_rx_ring ) >= RING_HIGH_WATER_MARK ))
{
/* Start RX processing */
serial_ctrl.rx_processing((void *)devid);
/* Exit */
done = TRUE ;
}
else
{
i = 0 ;
/* Wait for a new character */
while ((( usart_pt->US_CSR & RXRDY ) == 0 ) && ( i++ < SR_POLL_TIMEOUT_COUNT )) ;
/* If timeout has occured */
if ( i >= SR_POLL_TIMEOUT_COUNT )
{
/* Exit */
timeout = TRUE ;
}
else
{
/* Read received character */
rx_preread_char = usart_pt->US_RHR ;
}
}
}
}
/* Reenable Receiver Interrupt */
usart_pt->US_IER = RXRDY | FRAME | OVRE | PARE ;
}
/*
* interrupt handler for serial driver
*/
#pragma no_check_stack
void angel_SerialIntHandler( unsigned ident, unsigned data,
unsigned empty_stack )
{
StructUSART *usart_pt = USART_ANGEL_BASE ;
StructAIC *aic_pt = AIC_BASE ;
word ser_status ;
bool serialize_rx = FALSE ;
IGNORE( data );
// Add IVR Writting for Protect Mode support
aic_pt->AIC_IVR = (u_int) aic_pt ;
ser_status = ( usart_pt->US_CSR & usart_pt->US_IMR ) ;
if (( ser_status & NASTYERR ) != 0 )
{
LogWarning(LOG_SERIAL, ( "Nasty serial chip error %02x\n", ser_status ));
usart_pt->US_CR = RESETSTAT;
if (( ser_status & (FRAME|PARE)) != 0 )
{
/* Remove the wrong character */
rx_preread_char = usart_pt->US_RHR ;
ser_status &= ~RXRDY ;
}
}
if (( ser_status & RXRDY ) != 0 )
{
rx_preread_char = usart_pt->US_RHR ;
serialize_rx = TRUE ;
/* Disable Receiver Interrupt */
usart_pt->US_IDR = RXRDY | FRAME | OVRE | PARE ;
}
if (( ser_status & TXRDY ) != 0 )
{
if ( ringBufNotEmpty( &serial_tx_ring ) )
{
/* send a packet char to UART */
usart_pt->US_THR = ringBufGetChar( &serial_tx_ring ) ;
}
#ifdef NEVER
/*
* if we have reached to low-water mark in the
* ring buffer then it is time to ask for a refill,
* as long as there is more of the packet to come
*/
if ( ringBufCount ( &serial_tx_ring ) < 5 /*RING_LOW_WATER_MARK */)
{
queue_tx_deferred = TRUE;
}
#endif
/* is it time to give up yet? */
if ( ringBufEmpty( &serial_tx_ring ) )
{
usart_pt->US_IDR = TXRDY ;
queue_tx_deferred = TRUE;
}
}
/* Signify End of Interrupt to the Interrupt Controller */
aic_pt->AIC_EOICR = (int) aic_pt ;
/* If receive serialization requested and receiver interrupt enabled */
if ( serialize_rx == TRUE )
{
/* serialise to polled serial rx */
Angel_SerialiseTask( 0, serial_rx_processing, (void *)DI_SERIAL, empty_stack );
}
/* If we got here then we may need to queue deferred tx processing */
if ( queue_tx_deferred == TRUE )
{
queue_tx_deferred = FALSE ;
Angel_SerialiseTask( 0, serial_ctrl.tx_processing, DI_SERIAL, empty_stack );
}
}
#if PROFILE_SUPPORTED
void Angel_ProfileTimerStart(int interval)
{
/* interval is the desired interrupt interval (in microseconds) */
/* (we assume r0 < 2^16, and measure interval in units of 2^-20 */
/* seconds for ease of calculation). */
unsigned t1 = interval * (TimerFreq % 0x10000),
t2 = interval * (TimerFreq / 0x10000);
t1 = (t1 >> 20) + (t2 >> 4);
if (t1 == 0) t1 = 1;
AT91Serial->CTUR = t1 >> 8;
AT91Serial->CTLR = t1 & 255;
AT91Serial->CR = StartTimer;
/* This needs to be atomic wrt serial driver activity */
Angel_EnterSVC();
IMR_set(IMRTimer);
Angel_ExitToUSR();
}
void Angel_ProfileTimerStop(void)
{
/* This needs to be atomic wrt serial driver activity */
Angel_EnterSVC();
IMR_clr(IMRTimer);
Angel_ExitToUSR();
}
void Angel_TimerIntHandler(unsigned ident, unsigned data, unsigned empty_stack)
{
unsigned pc = Angel_MutexSharedTempRegBlocks[0].r[15];
IGNORE(ident);
IGNORE(data);
IGNORE(empty_stack);
if (angel_profilestate.enabled) {
unsigned *map = angel_profilestate.map;
int size = angel_profilestate.numentries;
int low = 0,
high = size-1;
if (map[low] <= pc && pc < map[high]) {
int i;
for (;;) {
i = (high + low) / 2;
if (pc >= map[i]) {
if (pc < map[i+1]) {
i++; break;
} else
low = i;
} else if (pc >= map[i-1])
break;
else
high = i;
}
angel_profilestate.counts[i-1]++;
}
}
AT91Serial->CR = ResetTimer; /* clear the interrupt */
}
#endif /* PROFILE_SUPPORTED */
#pragma check_stack
/* EOF serial.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -