📄 sh4uart.c
字号:
/* * Generic UART Serial driver for SH-4 processors * * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed. * Author: Alexandra Kossovsky <sasha@oktet.ru> * * COPYRIGHT (c) 1989-2000. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * * http://www.rtems.com/license/LICENSE. * * $Id: sh4uart.c,v 1.4.4.1 2003/09/04 18:46:00 joel Exp $ * */#include <rtems.h>#include <termios.h>#include <rtems/libio.h>#include <bsp.h>#include "sh/sh4uart.h"#ifndef SH4_UART_INTERRUPT_LEVEL#define SH4_UART_INTERRUPT_LEVEL 4#endif/* Forward function declarations */static rtems_isrsh4uart1_interrupt_transmit(rtems_vector_number vec);static rtems_isrsh4uart1_interrupt_receive(rtems_vector_number vec);static rtems_isrsh4uart2_interrupt_transmit(rtems_vector_number vec);static rtems_isrsh4uart2_interrupt_receive(rtems_vector_number vec);/* * sh4uart_init -- * This function verifies the input parameters and perform initialization * of the SH-4 on-chip UART descriptor structure. * * PARAMETERS: * uart - pointer to the UART channel descriptor structure * tty - pointer to termios structure * chn - channel number (SH4_SCI/SH4_SCIF -- 1/2) * int_driven - interrupt-driven (1) or polled (0) I/O mode * * RETURNS: * RTEMS_SUCCESSFUL if all parameters are valid, or error code */rtems_status_codesh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven){ if (uart == NULL) return RTEMS_INVALID_ADDRESS; if ((chn != SH4_SCI) && (chn != SH4_SCIF)) return RTEMS_INVALID_NUMBER; uart->chn = chn; uart->tty = tty; uart->int_driven = int_driven;#if 0 sh4uart_poll_write(uart, "init", 4);#endif return RTEMS_SUCCESSFUL;}/* * sh4uart_get_Pph -- * Get current peripheral module clock. * * PARAMETERS: none; * Cpu clock is get from CPU_CLOCK_RATE_HZ marco * (defined in bspopts.h, included from bsp.h) * * RETURNS: * peripheral module clock in Hz. */rtems_unsigned32sh4uart_get_Pph(void){ rtems_unsigned16 frqcr = *(volatile rtems_unsigned16 *)SH7750_FRQCR; rtems_unsigned32 Pph = CPU_CLOCK_RATE_HZ; switch (frqcr & SH7750_FRQCR_IFC) { case SH7750_FRQCR_IFCDIV1: break; case SH7750_FRQCR_IFCDIV2: Pph *= 2; break; case SH7750_FRQCR_IFCDIV3: Pph *= 3; break; case SH7750_FRQCR_IFCDIV4: Pph *= 4; break; case SH7750_FRQCR_IFCDIV6: Pph *= 6; break; case SH7750_FRQCR_IFCDIV8: Pph *= 8; break; default: /* unreachable */ break; } switch (frqcr & SH7750_FRQCR_PFC) { case SH7750_FRQCR_PFCDIV2: Pph /= 2; break; case SH7750_FRQCR_PFCDIV3: Pph /= 3; break; case SH7750_FRQCR_PFCDIV4: Pph /= 4; break; case SH7750_FRQCR_PFCDIV6: Pph /= 6; break; case SH7750_FRQCR_PFCDIV8: Pph /= 8; break; default: /* unreachable */ break; } return Pph;}/* * sh4uart_set_baudrate -- * Program the UART timer to specified baudrate * * PARAMETERS: * uart - pointer to UART descriptor structure * baud - termios baud rate (B50, B9600, etc...) * * ALGORITHM: * see SH7750 Hardware Manual. * * RETURNS: * none */static voidsh4uart_set_baudrate(sh4uart *uart, speed_t baud){ rtems_unsigned32 rate; rtems_signed16 div; int n; rtems_unsigned32 Pph = sh4uart_get_Pph(); switch (baud) { case B50: rate = 50; break; case B75: rate = 75; break; case B110: rate = 110; break; case B134: rate = 134; break; case B150: rate = 150; break; case B200: rate = 200; break; case B300: rate = 300; break; case B600: rate = 600; break; case B1200: rate = 1200; break; case B2400: rate = 2400; break; case B4800: rate = 4800; break; case B9600: rate = 9600; break; case B19200: rate = 19200; break; case B38400: rate = 38400; break; case B57600: rate = 57600; break;#ifdef B115200 case B115200: rate = 115200; break;#endif#ifdef B230400 case B230400: rate = 230400; break;#endif default: rate = 9600; break; } for (n = 0; n < 4; n++) { div = Pph / (32 * (1 << (2 * n)) * rate) - 1; if (div < 0x100) break; } /* Set default baudrate if specified baudrate is impossible */ if (n >= 4) sh4uart_set_baudrate(uart, B9600); SCSMR(uart->chn) &= ~SH7750_SCSMR_CKS; SCSMR(uart->chn) |= n << SH7750_SCSMR_CKS_S; SCBRR(uart->chn) = div; /* Whait at least 1 bit interwal */ rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));}/* * sh4uart_reset -- * This function perform the hardware initialization of SH-4 * on-chip UART controller using parameters * filled by the sh4uart_init function. * * PARAMETERS: * uart - pointer to UART channel descriptor structure * * RETURNS: * RTEMS_SUCCESSFUL if channel is initialized successfully, error * code in other case */rtems_status_codesh4uart_reset(sh4uart *uart){ register int chn; register int int_driven; rtems_status_code rc; if (uart == NULL) return RTEMS_INVALID_ADDRESS; chn = uart->chn; int_driven = uart->int_driven; SCSCR(chn) = 0x0; /* Is set properly at the end of this function */ SCSMR(chn) = 0x0; /* 8-bit, non-parity, 1 stop bit, pf/1 clock */ if (chn == SH4_SCIF) SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST | SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4; if (chn == SH4_SCI) SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO; else SCSPTR2 = SH7750_SCSPTR2_RTSDT; if (int_driven) { rtems_unsigned16 ipr; if (chn == SH4_SCI) { ipr = IPRB; ipr &= ~SH7750_IPRB_SCI1; ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S; IPRB = ipr; rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit, SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI), &uart->old_handler_transmit); if (rc != RTEMS_SUCCESSFUL) return rc; rc = rtems_interrupt_catch(sh4uart1_interrupt_receive, SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI), &uart->old_handler_receive); if (rc != RTEMS_SUCCESSFUL) return rc; } else { ipr = IPRC; ipr &= ~SH7750_IPRC_SCIF; ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S; IPRC = ipr; rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit, SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI), &uart->old_handler_transmit); if (rc != RTEMS_SUCCESSFUL) return rc; rc = rtems_interrupt_catch(sh4uart2_interrupt_receive, SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI), &uart->old_handler_receive); if (rc != RTEMS_SUCCESSFUL) return rc; } uart->tx_buf = NULL; uart->tx_ptr = uart->tx_buf_len = 0; } sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately, it is differ to termios default */ SCSCR(chn) = SH7750_SCSCR_TE | SH7750_SCSCR_RE | (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) | (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0); return RTEMS_SUCCESSFUL;}/* * sh4uart_disable -- * This function disable the operations on SH-4 UART controller * * PARAMETERS: * uart - pointer to UART channel descriptor structure * disable_port - disable receive and transmit on the port * * RETURNS: * RTEMS_SUCCESSFUL if UART closed successfuly, or error code in * other case */rtems_status_codesh4uart_disable(sh4uart *uart, int disable_port){ rtems_status_code rc; if (disable_port) SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); if (uart->int_driven) { rc = rtems_interrupt_catch(uart->old_handler_transmit, uart->chn == SH4_SCI ? SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI, NULL); if (rc != RTEMS_SUCCESSFUL) return rc; rc = rtems_interrupt_catch(uart->old_handler_receive, uart->chn == SH4_SCI ? SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI, NULL); if (rc != RTEMS_SUCCESSFUL) return rc; } return RTEMS_SUCCESSFUL;}/* * sh4uart_set_attributes -- * This function parse the termios attributes structure and perform * the appropriate settings in hardware. * * PARAMETERS: * uart - pointer to the UART descriptor structure * t - pointer to termios parameters * * RETURNS: * RTEMS_SUCCESSFUL */rtems_status_codesh4uart_set_attributes(sh4uart *uart, const struct termios *t){ int level; speed_t baud; rtems_unsigned16 smr; smr = (rtems_unsigned16)(*(rtems_unsigned8 *)SH7750_SCSMR(uart->chn)); baud = cfgetospeed(t); /* Set flow control XXX*/ if ((t->c_cflag & CRTSCTS) != 0) { } /* Set character size -- only 7 or 8 bit */ switch (t->c_cflag & CSIZE) { case CS5: case CS6: case CS7: smr |= SH7750_SCSMR_CHR_7; break; case CS8: smr &= ~SH7750_SCSMR_CHR_7; break; } /* Set number of stop bits */ if ((t->c_cflag & CSTOPB) != 0) smr |= SH7750_SCSMR_STOP_2; else smr &= ~SH7750_SCSMR_STOP_2; /* Set parity mode */ if ((t->c_cflag & PARENB) != 0) { smr |= SH7750_SCSMR_PE; if ((t->c_cflag & PARODD) != 0) smr |= SH7750_SCSMR_PM_ODD; else smr &= ~SH7750_SCSMR_PM_ODD; } else smr &= ~SH7750_SCSMR_PE; rtems_interrupt_disable(level); /* wait untill all data is transmitted */ rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100)); /* disable operations */ SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); sh4uart_set_baudrate(uart, baud); SCSMR(uart->chn) = (rtems_unsigned8)smr; /* enable operations */ SCSCR(uart->chn) |= SH7750_SCSCR_TE | SH7750_SCSCR_RE; rtems_interrupt_enable(level); return RTEMS_SUCCESSFUL;}/* * sh4uart_handle_error -- * Perfoms error (Overrun, Framing & Parity) handling * * PARAMETERS: * uart - pointer to UART descriptor structure * * RETURNS: * nothing */voidsh4uart_handle_error(sh4uart *uart){#if 0 int status_reg = SCSSR(uart->chn);#endif if(uart->chn == SH4_SCI) { SCSSR1 &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER); } else { SCSSR2 &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER); SCLSR2 &= ~(SH7750_SCLSR2_ORER); }}/* * sh4uart_poll_read -- * This function tried to read character from SH-4 UART and perform * error handling. When parity or framing error occured, return * value dependent on termios input mode flags: * - received character, if IGNPAR == 1 * - 0, if IGNPAR == 0 and PARMRK == 0 * - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and * PARMRK == 1 * * PARAMETERS: * uart - pointer to UART descriptor structure * * RETURNS: * code of received character or -1 if no characters received. */intsh4uart_poll_read(sh4uart *uart){ int chn = uart->chn; int error_occured = 0; int parity_error = 0; int break_occured = 0; int ch; if (uart->parerr_mark_flag == 1) { uart->parerr_mark_flag = 0; return 0; } if (chn == SH4_SCI)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -