⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sh4uart.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -