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

📄 sci.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
字号:
/* * /dev/sci[0|1] for Hitachi SH 704X * * The SH doesn't have a designated console device. Therefore we "alias"  * another device as /dev/console and revector all calls to /dev/console  * to this device. * * This approach is similar to installing a sym-link from one device to  * another device. If rtems once will support sym-links for devices files,  * this implementation could be dropped. * *  Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de) * *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *  * *  COPYRIGHT (c) 1998. *  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. * *  Modified to reflect sh7045 processor: *  John M. Mills (jmills@tga.com) *  TGA Technologies, Inc. *  100 Pinnacle Way, Suite 140 *  Norcross, GA 30071 U.S.A. * *  This modified file may be copied and distributed in accordance *  the above-referenced license. It is provided for critique and *  developmental purposes without any warranty nor representation *  by the authors or by TGA Technologies. * *  $Id: sci.c,v 1.9.2.1 2003/09/04 18:45:57 joel Exp $ */#include <rtems.h>#include <stdlib.h>#include <rtems/libio.h>#include <iosupp.h>#include <rtems/score/sh_io.h>#include <rtems/score/ispsh7045.h>#include <rtems/score/iosh7045.h>#include <sh/sh7_sci.h>#include <sh/sh7_pfc.h>#include <sh/sci.h>#ifndef STANDALONE_EVB#define STANDALONE_EVB 0#endif/* * NOTE: Some SH variants have 3 sci devices */  #define SCI_MINOR_DEVICES       2  /* * FIXME: sh7045 register names match Hitachi data book, *  but conflict with RTEMS sh7032 usage. */#define SH_SCI_BASE_0   SCI_SMR0#define SH_SCI_BASE_1   SCI_SMR1#define SH_SCI_DEF_COMM_0   B9600 | CS8#define SH_SCI_DEF_COMM_1   B38400 | CS8/*  #define SH_SCI_DEF_COMM_1   B9600 | CS8 */struct scidev_t {  char *			name ;  unsigned32			addr ;  rtems_device_minor_number	minor ;  unsigned short		opened ;  tcflag_t			cflags ;} sci_device[SCI_MINOR_DEVICES] ={  { "/dev/sci0", SH_SCI_BASE_0, 0, 0, SH_SCI_DEF_COMM_0 },  { "/dev/sci1", SH_SCI_BASE_1, 1, 0, SH_SCI_DEF_COMM_1 }} ;/*  local data structures maintain hardware configuration */#if UNUSEDstatic sci_setup_t sio_param[2];#endif/*  imported from scitab.rel */extern int _sci_get_brparms(  tcflag_t      cflag,  unsigned char *smr,  unsigned char *brr );/* Translate termios' tcflag_t into sci settings */static int _sci_set_cflags(  struct scidev_t      *sci_dev,  tcflag_t      c_cflag ){  unsigned8	smr ;  unsigned8	brr ;    if ( c_cflag & CBAUD )  {    if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )      return -1 ;  }                      if ( c_cflag & CSIZE )  {    if ( c_cflag & CS8 )      smr &= ~SCI_SEVEN_BIT_DATA;    else if ( c_cflag & CS7 )      smr |= SCI_SEVEN_BIT_DATA;    else      return -1 ;  }  if ( c_cflag & CSTOPB )    smr |= SCI_STOP_BITS_2;  else    smr &= ~SCI_STOP_BITS_2;  if ( c_cflag & PARENB )    smr |= SCI_PARITY_ON ;  else    smr &= ~SCI_PARITY_ON ;  if ( c_cflag & PARODD )    smr |= SCI_ODD_PARITY ;  else    smr &= ~SCI_ODD_PARITY;      write8( smr, sci_dev->addr + SCI_SMR );  write8( brr, sci_dev->addr + SCI_BRR );    return 0 ;}/* * local functions operate SCI ports 0 and 1 * called from polling routines or ISRs */rtems_boolean wrtSCI0(unsigned char ch){  unsigned8 temp;  rtems_boolean result=FALSE;  if ((read8(SCI_SSR0) & SCI_TDRE) != 0x00) {    /* Write the character to the TDR */    write8(ch, SCI_TDR0);    /* Clear the TDRE bit */    temp = read8(SCI_SSR0) & ~SCI_TDRE;    write8(temp, SCI_SSR0);    result = TRUE;  }  return result;} /* wrtSCI0 */rtems_boolean wrtSCI1(unsigned char ch){  unsigned8 temp;  rtems_boolean result=FALSE;  if ((read8(SCI_SSR1) & SCI_TDRE) != 0x00) {     /* Write the character to the TDR */     write8(ch, SCI_TDR1);     /* Clear the TDRE bit */     temp = read8(SCI_SSR1) & ~SCI_TDRE;     write8(temp, SCI_SSR1);     result = TRUE;  }  return result;} /* wrtSCI1 *//* polled output steers byte to selected port */void sh_sci_outbyte_polled(  rtems_device_minor_number  minor,  char ch ){	if (minor == 0) /* blocks until port ready */		while (wrtSCI0(ch) != TRUE); /* SCI0*/	else		while (wrtSCI1(ch) != TRUE); /* SCI1*/} /* sh_sci_outbyte_polled *//* * Initial version calls polled output driver and blocks */void outbyte(  rtems_device_minor_number  minor,  char ch){	sh_sci_outbyte_polled(minor, (unsigned char)ch);} /* outbyte */rtems_boolean rdSCI0(unsigned char *ch){  unsigned8 temp;  rtems_boolean result=FALSE;  if ((read8(SCI_SSR0) & SCI_RDRF) != 0x00) {    /* read input */    *ch = read8(SCI_RDR0);    /* Clear RDRF flag */    temp = read8(SCI_SSR0) & ~SCI_RDRF;    write8(temp, SCI_SSR0);    /* Check for transmission errors */    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){        /* TODO: report to RTEMS transmission error */        /* clear error flags*/        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);        write8(temp, SCI_SSR0);    }    result = TRUE;  }  return result;} /* rdSCI0 */rtems_boolean rdSCI1(unsigned char *ch){  unsigned8 temp;  rtems_boolean result=FALSE;  if ((read8(SCI_SSR1) & SCI_RDRF) != 0x00) {    /* read input */    *ch = read8(SCI_RDR1);    /* Clear RDRF flag */    temp= read8(SCI_SSR1) & ~SCI_RDRF;    write8(temp, SCI_SSR1);    /* Check for transmission errors */    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){        /* TODO: report to RTEMS transmission error */        /* clear error flags*/        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);        write8(temp, SCI_SSR1);    }    result = TRUE;  }  return result;} /* rdSCI1 *//* initial version pulls byte from selected port */char sh_sci_inbyte_polled(    rtems_device_minor_number  minor ){	char ch;		if (minor == 0) /* blocks until char.ready */		while (rdSCI0(&ch) != TRUE); /* SCI0 */	else		while (rdSCI1(&ch) != TRUE); /* SCI1 */	return ch;} /* sh_sci_inbyte_polled *//* Initial version calls polled input driver */char inbyte(  rtems_device_minor_number  minor ){	char ch;	ch = sh_sci_inbyte_polled(minor);	return ch;} /* inbyte *//*  sh_sci_initialize * *  This routine initializes (registers) the sh_sci IO drivers. * *  Input parameters: ignored * *  Output parameters:  NONE * *  Return values: RTEMS_SUCCESSFUL *   if all sci[...] register, else calls *   rtems_fatal_error_occurred(status) * */rtems_device_driver sh_sci_initialize(  rtems_device_major_number  major,  rtems_device_minor_number  minor,  void                      *arg ){  rtems_device_driver status;  rtems_device_minor_number i;  rtems_driver_name_t driver;      /*   * register all possible devices.   * the initialization of the hardware is done by sci_open   *   * One of devices could be previously registered by console   * initialization therefore we check it everytime   */  for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )  {    status = rtems_io_lookup_name(        sci_device[i].name,        &driver);    if( status != RTEMS_SUCCESSFUL )    {        /* OK. We assume it is not registered yet. */        status = rtems_io_register_name(            sci_device[i].name,            major,            sci_device[i].minor );        if (status != RTEMS_SUCCESSFUL)            rtems_fatal_error_occurred(status);    }  }  /* non-default hardware setup occurs in sh_sci_open() */  return RTEMS_SUCCESSFUL;}/* *  Open entry point *   Sets up port and pins for selected sci. */rtems_device_driver sh_sci_open(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg ){  unsigned8 temp8;  unsigned16 temp16;    unsigned 	a ;   /* check for valid minor number */   if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))   {     return RTEMS_INVALID_NUMBER;   }   /* device already opened */  if ( sci_device[minor].opened > 0 )  {    sci_device[minor].opened++ ;    return RTEMS_SUCCESSFUL ;  }      /* set PFC registers to enable I/O pins */  if ((minor == 0)) {    temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */    temp16 &= ~(PA2MD1 | PA2MD0);    temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */    write16(temp16, PFC_PACRL2);      } else if (minor == 1) {      temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */    temp16 &= ~(PA5MD1 | PA5MD0);    temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */    write16(temp16, PFC_PACRL2);  } /* add other devices and pins as req'd. */  /* set up SCI registers */      write8(0x00, sci_device[minor].addr + SCI_SCR);	 /* Clear SCR */                                                   /* set SMR and BRR */    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );    for(a=0; a < 10000L; a++) {                      /* Delay */      asm volatile ("nop");    }    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */	   sci_device[minor].addr + SCI_SCR);    /* clear error flags */    temp8 = read8(sci_device[minor].addr + SCI_SSR);    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)){        temp8 = read8(sci_device[minor].addr + SCI_RDR);   /* flush input */        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* clear some flags */        write8(temp8 & ~(SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER),                sci_device[minor].addr + SCI_SSR);        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* check if everything is OK */    }        /* Clear RDRF flag */    write8(0x00, sci_device[minor].addr + SCI_TDR);    /* force output */     /* Clear the TDRE bit */     temp8 = read8(sci_device[minor].addr + SCI_SSR) & ~SCI_TDRE;     write8(temp8, sci_device[minor].addr + SCI_SSR);        /* add interrupt setup if required */    sci_device[minor].opened++ ;  return RTEMS_SUCCESSFUL ;} /* *  Close entry point */rtems_device_driver sh_sci_close(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  /* FIXME: Incomplete */  if ( sci_device[minor].opened > 0 )    sci_device[minor].opened-- ;  else    return RTEMS_INVALID_NUMBER ;      return RTEMS_SUCCESSFUL ;}/* * read bytes from the serial port. We only have stdin. */rtems_device_driver sh_sci_read(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  rtems_libio_rw_args_t *rw_args;  char *buffer;  int maximum;  int count = 0;   rw_args = (rtems_libio_rw_args_t *) arg;  buffer = rw_args->buffer;  maximum = rw_args->count;  for (count = 0; count < maximum; count++) {    buffer[ count ] = inbyte(minor);    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {      buffer[ count++ ]  = '\n';      break;    }  }  rw_args->bytes_moved = count;  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;}/* * write bytes to the serial port. Stdout and stderr are the same.  */rtems_device_driver sh_sci_write(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  int count;  int maximum;  rtems_libio_rw_args_t *rw_args;  char *buffer;  rw_args = (rtems_libio_rw_args_t *) arg;  buffer = rw_args->buffer;  maximum = rw_args->count;  for (count = 0; count < maximum; count++) {    if ( buffer[ count ] == '\n') {      outbyte(minor, '\r');    }    outbyte( minor, buffer[ count ] );  }  rw_args->bytes_moved = maximum;  return 0;}/* *  IO Control entry point */rtems_device_driver sh_sci_control(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  /* Not yet supported */  return RTEMS_SUCCESSFUL ;}/* * Termios polled first open */static int _sh_sci_poll_first_open(int major, int minor, void *arg){    return sh_sci_open(major, minor, arg);}/* * Termios general last close */static int _sh_sci_last_close(int major, int minor, void *arg){    return sh_sci_close(major, minor, arg);}/* * Termios polled read */static int _sh_sci_poll_read(int minor){    int value = -1;    char ch;        if( minor == 0 ){        if( rdSCI0( &ch ) )            value = (int) ch;    }else if( minor == 1 ){        if( rdSCI1( &ch ) )            value = (int) ch;    }    return value;}/* * Termios polled write  */static int _sh_sci_poll_write(int minor, const char *buf, int len){    int count;        for(count = 0; count < len; count++)        outbyte( minor, buf[count] );    return count;}/* * Termios set attributes */static int _sh_sci_set_attributes( int minor, const struct termios *t){    return _sci_set_cflags( &sci_device[ minor ], t->c_cflag);}const rtems_termios_callbacks sci_poll_callbacks = {    _sh_sci_poll_first_open,    /* FirstOpen*/    _sh_sci_last_close,         /* LastClose*/    _sh_sci_poll_read,          /* PollRead  */    _sh_sci_poll_write,         /* Write */    _sh_sci_set_attributes,     /* setAttributes */    NULL,                       /* stopRemoteTX */    NULL,                       /* StartRemoteTX */    0                           /* outputUsesInterrupts */};/* FIXME: not yet supported */const rtems_termios_callbacks sci_interrupt_callbacks;const rtems_termios_callbacks* sh_sci_get_termios_handlers( rtems_boolean poll ){    return poll ?        &sci_poll_callbacks :        &sci_interrupt_callbacks;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -