📄 sdc.c
字号:
DV_DEVICE_ENTRY *device;
INT deviceVector;
#endif /* NU_ENABLE_PPP */
/* Find the port stucture for this vector. */
receive = 0;
while ((SDC_Port_List[receive] != NU_NULL) &&
(SDC_Port_List[receive] -> vector != vector) &&
(receive < SD_MAX_UARTS) )
receive++;
/* See if we found one. Better have since we got an interrupt
from one. */
if (SDC_Port_List[receive] -> vector == vector)
{
/* Point our local structure to it. */
uart = SDC_Port_List[receive];
vector_found = NU_TRUE;
}
#ifdef NU_ENABLE_PPP
else
{
/* Find the device for this interrupt */
/*************** Begin Port Specific Section *************/
/* Since there is only one interrupt for the UART (as opposed
to seperate Rx,Tx,etc.) the deviceVector used to determine
the PPP device will be the same as the vector that activated
this LISR. */
deviceVector = vector;
/**************** End Port Specific Section **************/
if ( (device = DEV_Get_Dev_For_Vector(deviceVector)) != NU_NULL)
{
/* Get the address of the uart structure for this device. */
uart = &((PPP_LAYER *) device->ppp_layer)->uart;
vector_found = NU_TRUE;
}
}
#endif /* NU_ENABLE_PPP */
if (vector_found == NU_TRUE)
{
/**************** Begin Port Specific Section **************/
/* Read the Interrupt Identification Register (iir) and Line Status
Register (lsr) into local copies for processing and to clear
them. */
iir = SD_INBYTE (uart->base_address + SD_IIR_OFFSET);
/* Process all interrupts in the UART */
while ((iir&SD_IIR_INT_PENDING_MASK)==0)
{
/* Determint if interrupt is Rx using iir value. */
if (iir & SD_IIR_INT_RX)
{
/* Process every character in the receive FIFO */
do
{
/* Check for Line Status errors */
lsr = SD_INBYTE (uart->base_address + SD_LSR_OFFSET);
/* Check for a damaged or incorrectly received character */
if (lsr & (SD_LSR_FRAME_ERR | SD_LSR_PARITY_ERR))
{
if (lsr & SD_LSR_FRAME_ERR)
{
uart->frame_errors++;
}
if (lsr & SD_LSR_PARITY_ERR)
{
uart->parity_errors++;
}
/* Consume the character to clear the error bits */
receive = SD_INBYTE (uart->base_address + SD_DATA_OFFSET);
}
else
{
/* If an overrun has occured, log it */
if (lsr & SD_LSR_OVERRUN_ERR)
{
uart->overrun_errors++;
}
switch(uart->communication_mode)
{
case SERIAL_MODE:
/* Put char into buffer */
receive = SD_INBYTE (uart->base_address + SD_DATA_OFFSET);
if (uart->rx_buffer_status != NU_BUFFER_FULL)
{
/* Put the character into the buffer */
uart->rx_buffer[uart->rx_buffer_write++] = receive;
/* If write pointer is at end, wrap it around */
uart->rx_buffer_write %= uart->sd_buffer_size;
/* Set status field based on latest character */
if (uart->rx_buffer_write == uart->rx_buffer_read)
uart->rx_buffer_status = NU_BUFFER_FULL;
else
uart->rx_buffer_status = NU_BUFFER_DATA;
}
break;
#ifdef NU_ENABLE_PPP
/* call PPP processing functions */
case MDM_NETWORK_COMMUNICATION:
/* Call this devices receive routine */
device->dev_receive(device);
break;
case MDM_TERMINAL_COMMUNICATION:
default:
MDM_Receive(device);
break;
#endif /* NU_ENABLE_PPP */
} /* end switch */
} /* end else */
/* Read lsr to get next pending interrupt and clear it. */
lsr = SD_INBYTE (uart->base_address + SD_LSR_OFFSET);
} while (lsr & SD_USR_RXRDY);
} /* end Rx interrupt */
/* Determine if interrupt is Tx using iir value. */
else if (iir & SD_IIR_INT_TX)
{
if (uart->communication_mode == SERIAL_MODE)
{
/* update read pointer */
uart->tx_buffer_read++;
/* Check for wrap of buffer. */
uart->tx_buffer_read %= uart->sd_buffer_size;
/* Update the status. */
if (uart->tx_buffer_write == uart->tx_buffer_read)
{
uart->tx_buffer_status = NU_BUFFER_EMPTY;
/* Since it is now empty turn off the TX
interrupt, we do not need it anymore. */
SD_OUTBYTE (uart->base_address + SD_IER_OFFSET,
(SD_INBYTE(uart->base_address + SD_IER_OFFSET)
& ~(SD_IER_ENABLE_TX)));
}
else
{
/* Update the status. */
uart->tx_buffer_status = NU_BUFFER_DATA;
/* Get next CHAR to be sent. */
ch = uart->tx_buffer[uart->tx_buffer_read];
/* Send the next byte in the queue. */
SD_OUTBYTE (uart->base_address + SD_DATA_OFFSET,ch);
}
}
#ifdef NU_ENABLE_PPP
else
{
#ifndef PPP_POLLED_TX
/* Check for a transmit interrupt. */
/* Is there another byte in the TX buffer to send? */
if (uart->tx_buffer_read != uart->tx_buffer_write)
{
/* Send the next byte in the queue. */
SD_OUTBYTE (uart->base_address + SD_DATA_OFFSET,
uart->tx_buffer[uart->tx_buffer_read++]);
/* Check for wrap of ring buffer. */
uart->tx_buffer_read %= uart->sd_buffer_size;
}
else
{
SD_OUTBYTE (uart->base_address + SD_IER_OFFSET,
(SD_INBYTE(uart->base_address + SD_IER_OFFSET)
& ~(SD_IER_ENABLE_TX)));
/* Only activate the HISR if we are tranmitting
network data. */
if (uart->communication_mode == MDM_NETWORK_COMMUNICATION)
{
/* Add this device to the list of PPP devices that have finished
sending a packet. */
_ppp_tx_dev_ptr_queue [_ppp_tx_dev_ptr_queue_write++] = device;
/* Activate the HISR that will take care of processing the
next packet in queue, if one is ready. */
NU_Activate_HISR (&PPP_TX_HISR);
/* Check for wrap of ring buffer. */
_ppp_tx_dev_ptr_queue_write %= PPP_MAX_TX_QUEUE_PTRS;
}
}
#endif /* PPP_POLLED_TX */
}
#endif /* NU_ENABLE_PPP */
} /* end Tx interrupt */
/* Read iir value again. */
iir = SD_INBYTE (uart->base_address + SD_IIR_OFFSET);
} /* end while */
/* Send the PIC 'EOI' End of interrupt */
SD_OUTBYTE(SD_BASE + SD_PIC1_BASE_OFFSET, SD_PIC_EOI);
/**************** End Port Specific Section **************/
} /* end (vector_found == NU_TRUE) */
/* No port is associated with the vector */
else
{
ERC_System_Error(NU_UNHANDLED_INTERRUPT);
}
}
/****************************************************************************
* FUNCTION
*
* SDC_Set_Baud_Rate
*
* DESCRIPTION
*
* This function sets the UART buad rate.
*
* INPUTS
*
* UINT32 : The new baud rate.
* SD_PORT * : Serial port to set the baud rate.
*
* OUTPUTS
*
* none
*
****************************************************************************/
static VOID SDC_Set_Baud_Rate(UINT32 baud_rate, SD_PORT *uart)
{
UINT16 baud_div; /* baud rate divisor */
CHAR lcr;
/**************** Begin Port Specific Section **************/
/* Set the baud rate */
baud_div = EXT_SERIAL_CLOCK / baud_rate;
/* Set the divisor latch bit. */
lcr = SD_INBYTE(uart->base_address + SD_LCR_OFFSET);
SD_OUTBYTE(uart->base_address + SD_LCR_OFFSET, lcr | SD_LCR_DLAB);
/* First write the LSB of the baud rate divisor. */
SD_OUTBYTE(uart->base_address + SD_DATA_OFFSET, baud_div & 0xff);
/* Now write the MSB of the baud rate divisor. */
SD_OUTBYTE(uart->base_address + SD_IER_OFFSET, (baud_div >> 8) & 0xff);
/* Now that the baud rate has been set turn off DLAB to reference data in
line control */
SD_OUTBYTE(uart->base_address + SD_LCR_OFFSET, lcr);
/**************** End Port Specific Section ****************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -