ser_mcf5272_uart.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 947 行 · 第 1/3 页
C
947 行
UART driver.
INPUT:
Pointer to the the device table.
RETURN:
Returns true if the initialization is successful. Otherwise, it retuns false
*/
static bool MCF5272_uart_init(struct cyg_devtab_entry * tab)
{
serial_channel *chan = (serial_channel *)tab->priv;
MCF5272_uart_info_t *MCF5272_uart_chan = (MCF5272_uart_info_t *)chan->dev_priv;
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
/* Instantiation of the UART channel 0 data strucutre. This data */
/* structure contains channel information. */
if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL0_NAME) == 0)
{
/* Initiliaze the UART information data to all zeros. */
memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
/* Set the base address of the UART registers to differentiate */
/* itself from the different regusters for the other UART port. */
MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[0];
/* Set the UART interrupt vector number. */
MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART1;
/* Set the autobaud state to idle. */
MCF5272_uart_chan->autobaud_state = AB_IDLE;
/* Initilize the UART 0 output pins */
MCF5272_SIM->gpio.pbcnt = MCF5272_GPIO_PBCNT_URT0_EN |
((MCF5272_SIM->gpio.pbcnt) & ~MCF5272_GPIO_PBCNT_URT0_MSK);
}
#endif
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
/* Instantiation of the UART channel 1 data strucutre. This data structure contains
channel information.
*/
if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL1_NAME) == 0)
{
/* Initiliaze the UART information data to all zeros. */
memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
/* Set the base address of the UART registers to differentiate */
/* itself from the different regusters for the other UART port. */
MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[1];
/* Set the UART interrupt vector number. */
MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART2;
/* Set the autobaud state to idle. */
MCF5272_uart_chan->autobaud_state = AB_IDLE;
/* Initilize the UART 1 output pins */
MCF5272_SIM->gpio.pdcnt = MCF5272_GPIO_PDCNT_URT1_EN |
((MCF5272_SIM->gpio.pdcnt) & ~MCF5272_GPIO_PDCNT_URT1_MSK);
}
#endif
if (chan->out_cbuf.len > 0) {
/* If the the buffer is greater than zero, then the driver will */
/* use interrupt driven I/O. Hence, the driver creates an */
/* interrupt context for the UART device. */
cyg_drv_interrupt_create(MCF5272_uart_chan->uart_vector,
MCF5272_UART_PRIORITY_LEVEL, // Priority - Level 2
(cyg_addrword_t)chan, // Data item passed to interrupt handler
MCF5272_uart_ISR,
MCF5272_uart_DSR,
&MCF5272_uart_chan->serial_interrupt_handle,
&MCF5272_uart_chan->serial_interrupt);
cyg_drv_interrupt_attach(MCF5272_uart_chan->serial_interrupt_handle);
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
}
// Configure Serial device.
return(MCF5272_uart_config_port(chan, &chan->config));
}
/******************************************************************************************************
MCF5272_uart_config_port() - Configure the UART port.
Internal function to actually configure the hardware to desired baud rate, etc.
INPUT:
chan - The channel information
new_confg - The port configuration which include the desired baud rate, etc.
RETURN:
Returns true if the port configuration is successful. Otherwise, it retuns false
*/
static bool MCF5272_uart_config_port(serial_channel *chan,
cyg_serial_info_t *new_config)
{
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
uint8 mode_reg = 0;
uint32 ubgs;
unsigned int baud_divisor;
/* Get the divisor from the baudrate table which will use to */
/* configure the port's baud rate. */
baud_divisor = baud_rates_table[new_config->baud];
/* If the divisor is zeor, we dont' configure the port. */
if (baud_divisor == 0) return false;
/* Save the configuration value for later use. */
port->config = *new_config;
/* We first write the reset values into the device and then configure */
/* the device the we way we want to use it. */
/* Reset Transmitter */
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_TX);
/* Reset Receiver */
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_RX);
/* Reset Mode Register */
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_MR);
/* Translate the parity configuration to UART mode bits. */
switch(port->config.parity)
{
default:
case CYGNUM_SERIAL_PARITY_NONE:
mode_reg = 0 | MCF5272_UART_UMR1_PM_NONE;
break;
case CYGNUM_SERIAL_PARITY_EVEN:
mode_reg = 0 | MCF5272_UART_UMR1_PM_EVEN;
break;
case CYGNUM_SERIAL_PARITY_ODD:
mode_reg = 0 | MCF5272_UART_UMR1_PM_ODD;
break;
case CYGNUM_SERIAL_PARITY_MARK:
mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_HI;
break;
case CYGNUM_SERIAL_PARITY_SPACE:
mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_LO;
break;
}
/* Translate the number of bits per character configuration to UART mode bits. */
switch(port->config.word_length)
{
case CYGNUM_SERIAL_WORD_LENGTH_5:
mode_reg |= MCF5272_UART_UMR1_BC_5;
break;
case CYGNUM_SERIAL_WORD_LENGTH_6:
mode_reg |= MCF5272_UART_UMR1_BC_6;
break;
case CYGNUM_SERIAL_WORD_LENGTH_7:
mode_reg |= MCF5272_UART_UMR1_BC_7;
break;
default:
case CYGNUM_SERIAL_WORD_LENGTH_8:
mode_reg |= MCF5272_UART_UMR1_BC_8;
break;
}
/* Configure the parity and the bits per character */
MCF5272_UART_WRITE(port->base->umr, mode_reg);
/* Translate the stop bit length to UART mode bits. */
switch(port->config.stop)
{
default:
case CYGNUM_SERIAL_STOP_1:
mode_reg = MCF5272_UART_UMR2_STOP_BITS_1;
break;
case CYGNUM_SERIAL_STOP_1_5:
mode_reg = MCF5272_UART_UMR2_STOP_BITS_15;
break;
case CYGNUM_SERIAL_STOP_2:
mode_reg = MCF5272_UART_UMR2_STOP_BITS_2;
break;
}
/* No echo or loopback */
MCF5272_UART_WRITE(port->base->umr, 0 | MCF5272_UART_UMR2_CM_NORMAL | mode_reg);
/* Set Rx and Tx baud by timer */
MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCSR_RCS(0xD) |
MCF5272_UART_UCSR_TCS(0xD));
/* Mask all USART interrupts */
MCF5272_UART_WRITE(port->base->uisr_uimr, 0);
/* Calculate baud settings */
ubgs = (uint16)((CYGHWR_HAL_SYSTEM_CLOCK_MHZ*1000000)/
(baud_divisor * 32));
/* Program the baud settings to the device. */
MCF5272_UART_WRITE(port->base->udu, (uint8)((ubgs & 0xFF00) >> 8));
MCF5272_UART_WRITE(port->base->udl, (uint8)(ubgs & 0x00FF));
/* Enable receiver and transmitter */
MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCR_TXRXEN);
/* Enable both transmit and receive interrupt. */
port->imr_mirror = MCF5272_UART_UIMR_TXRDY | MCF5272_UART_UIMR_FFULL |
MCF5272_UART_UIMR_DB;
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
return true; /* Returns true to indicate a successful configuration */
}
/*******************************************************************************
MCF5272_uart_lookup() - This routine is called when the device is "looked" up
(i.e. attached)
INPUT:
tab - pointer to a pointer of the device table
sub_tab - Pointer to the sub device table.
name - name of the device
RETURN:
always return ENOERR
*/
static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
serial_channel *chan = (serial_channel *)(*tab)->priv;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
return ENOERR;
}
/*******************************************************************************
MCF5272_uart_putc() - Send a character to the device output buffer.
INPUT:
chan - pointer to the serial private data.
c - the character to output
RETURN:
'true' if character is sent to device, return 'false' when we've
ran out of buffer space in the device itself.
*/
static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c)
{
CYG_INTERRUPT_STATE int_state;
MCF5272_uart_info_t *port = (MCF5272_uart_info_t *)chan->dev_priv;
/* Make sure the transmitter is not full. If it is full, return false. */
if (!(MCF5272_UART_READ(port->base->usr_ucsr) & MCF5272_UART_USR_TXRDY))
return false;
/* Enable transmit interrupt. */
HAL_DISABLE_INTERRUPTS(int_state);
port->imr_mirror |= MCF5272_UART_UIMR_TXRDY;
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
HAL_RESTORE_INTERRUPTS(int_state);
/* Enable the UART transmit. */
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXRXEN);
/* Send the character */
MCF5272_UART_WRITE(port->base->urb_utb, c);
return true ;
}
/******************************************************************************************************
MCF5272_uart_getc() - Fetch a character from the device input bufferand return it to the alling
routine. Wait until there is a character ready.
INPUT:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?