ser_mcf5272_uart.c
来自「eCos操作系统源码」· 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 + -
显示快捷键?