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

📄 serial.c

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 C
📖 第 1 页 / 共 2 页
字号:
      }   }   else   {      ret_code = DE_INVAL;   }   return ret_code;}/* * Set Speed control operation */static DevError c501uart_set_params(DeviceID devid, const ParameterConfig * conf){   word speed;   word baud_word;   word control_reg;   const unsigned int port = SerCtrl(devid)->port;   C501UARTReg *const serchip = c501uart_Address(port);   if (!Angel_FindParam(AP_BAUD_RATE, conf, &speed))   {      LogWarning(LOG_SERIAL, ("c501uart_set_params: Speed parameter not found in config\n"));      return DE_OKAY;   }   switch (speed)   {      case 1200:	 baud_word = C501_BAUD_1200;	 break;      case 2400:	 baud_word = C501_BAUD_2400;	 break;      case 4800:	 baud_word = C501_BAUD_4800;	 break;      case 9600:	 baud_word = C501_BAUD_9600;	 break;      case 19200:	 baud_word = C501_BAUD_19200;	 break;      case 38400:	 baud_word = C501_BAUD_38400;	 break;      case 57600:	 baud_word = C501_BAUD_57600;	 break;      case 115200:	 baud_word = C501_BAUD_115200;	 break;      default:	 return DE_BAD_OP;   }       LogInfo(LOG_SERIAL, ("c501uart_set_params: Speed %d (div %d)\n", speed, baud_word));    /* wait for current transmits to complete */   serial_tx_drain(devid);	/* This could really hurt with interrupts                                   disabled, so do it here */   /* disable interrupts */   Angel_EnterCriticalSection();       /* disable chip */   control_reg = c501uart_GetControlReg(serchip);   c501uart_SetControlReg(serchip, 0);   /* Set port for 8 bit, one stop, no parity  */   c501uart_SetLineControl( serchip, (ULCR8bits));   /* Enable interrupt operation on UART, needed for normal operation */   c501uart_SetControlReg( serchip, (UCRRxM | UCRTxM));   /* Set baud rate  */   c501uart_SetBaudRate( serchip, baud_word );   c501uart_SetControlReg(serchip, control_reg);   EnableInterruptNum( DEBUG_COMPORT_RX_INT );       Angel_LeaveCriticalSection();       LogInfo(LOG_SERIAL, ("c501uart_set_params: CR %x\n", control_reg));       return DE_OKAY;}/* *  Function: c501uart_ResetDriver *   Purpose: Give the UART a hardware reset * *    Params: *       Input: devid   device ID of the driver * *              port    Serial port identifier * *   Returns: Nothing */static void c501uart_ResetDriver(const unsigned int devid,                                 const unsigned int port){   C501UARTReg *const serchip = c501uart_Address(port);   DisableInterruptNum( DEBUG_COMPORT_RX_INT );   LogInfo(LOG_SERIAL, ("c501uart_ResetDriver: select 9600\n"));   /*    * set 9600 baud, take chip out of loopback (if in it) & enable.    */   /* Set port for 8 bit, one stop, no parity  */   c501uart_SetLineControl( serchip, (ULCR8bits));   /* Enable interrupt operation on UART, needed for normal operation */   c501uart_SetControlReg( serchip, (UCRRxM | UCRRxSI | UCRTxM));   /* Set baud rate  */   c501uart_SetBaudRate( serchip, C501_BAUD_9600 );   /*    * set default angel config    */   (void)c501uart_set_params(devid, &(angel_Device[devid]->default_config));}/* * Reset control operation */static DevError c501uart_reset(DeviceID devid){   const unsigned int port = SerCtrl(devid)->port;   c501uart_ResetDriver(devid, port);  /* low_level reset */   /* reset private flags (LEAVE lowest 8 bits alone) */   angel_DeviceStatus[devid] &= 0xFF;   c501uart_ControlRx(devid);   return DE_OKAY;}static DevErrorc501uart_set_led(DeviceID devid, int state){   IGNORE(devid);   IGNORE(state);   return DE_OKAY;}/* * implementation of device control for serial driver * * devid is guaranteed to be in range but op is not checked as * individual devices can extend the range of operations */static DevError c501uart_Control(DeviceID devid,                 DeviceControl op, void *arg){   DevError ret_code;   LogInfo(LOG_SERIAL, ("c501uart_Control: op %d arg %x\n", op, arg));   /* we only implement the standard ones here */   switch (op)   {      case DC_INIT:	 ret_code = c501uart_init(devid);	 break;      case DC_RESET:	 ret_code = c501uart_reset(devid);	 break;      case DC_RECEIVE_MODE:	 ret_code = c501uart_recv_mode(devid, (DevRecvMode) ((int)arg));	 break;      case DC_SET_PARAMS:	 ret_code = c501uart_set_params(devid, (const ParameterConfig *)arg);	 break;      case DC_SET_LED:	 ret_code = c501uart_set_led(devid, (int)arg);	 break;      default:	 ret_code = DE_BAD_OP;	 break;   }   return ret_code;}/* *  Function: int_* *   Purpose: Set of handlers for the uart interrupts. *              These routines do all the urgent processing required *              for the interrupt condition, and then schedule deferred *              routines for the non-urgent processing. * *  Pre-conditions: Processor is in IRQ / FIQ mode. * *    Params: *       Input: devid           device ID of the driver * *              port            serial port identifier * *              serchip         address of the controller for the given port * *              empty_stack     top of the stack * *   Returns: Nothing */static void int_txrdy(const unsigned int devid,          const unsigned int port,          C501UARTReg * const serchip,          const unsigned int empty_stack){   bool queue_tx_deferred = FALSE;   volatile unsigned int *const status = angel_DeviceStatus + devid;   RingBuffer *ring = c501uart_TxRingBuf(port);   if ((*status & SER_TX_FLOW_CONTROL) != 0  )   {       c501uart_SerPutChar(serchip, ((*status & SER_RX_DISABLED) != 0) ? 			  serial_XOFF : serial_XON);      *status &= ~SER_TX_FLOW_CONTROL;          } /* end if driver wants to send flow control to host */   else   {      if ( ringBufNotEmpty(ring) )      {	 c501uart_SerPutChar(serchip, ringBufGetChar(ring));	 /*	  * If we have reached to low-water mark in the ring buffer then it	  * is time to ask for a refill, as long as there is more of the	  * packet to come */	 if ( (ringBufCount(ring) < RING_LOW_WATER_MARK) && 	      ((*status & SER_TX_EOD) == 0) )	 {	    queue_tx_deferred = TRUE;	 }      } /* end if there's data to send */      if ( ringBufEmpty(ring) )      {	 /*	  * If the end of the packet has been sent, then queue deferred	  * processing of this fact */	 if ((*status & SER_TX_EOD) != 0)	 {	    /* Turn of interrupts at the IC */	    DisableInterruptNum( DEBUG_COMPORT_TX_INT );	    angel_DeviceStatus[devid] &= ~SER_TX_IRQ_EN;	    queue_tx_deferred = TRUE;	    *status &= ~SER_TX_DATA;	 }	 else	 {	    /*	     * queue_tx_deferred will already be set, but we need to set a	     * flag to tell fill_tx_ring that it needs to restart character	     * Tx.  */	    *status |= SER_TX_KICKSTART;    	 }      } /* end if there's nothing left to tx */   } /* end else normal tx operation */   if (queue_tx_deferred && ((*status & SER_TX_QUEUED) == 0))   {      *status |= SER_TX_QUEUED;      /*       * NOTE - this routine will never return       */      Angel_SerialiseISR(SerCtrl(devid)->tx_processing, (void *)devid);   }}#define	RXIntPendMask	(1 << DEBUG_COMPORT_RX_INT)#define	TXIntPendMask	(1 << DEBUG_COMPORT_TX_INT)static void int_rxrdy(const unsigned int devid,          const unsigned int port,          C501UARTReg * const serchip,          const unsigned int empty_stack){   bool queue_rx_processing = FALSE;   volatile unsigned int *const status = angel_DeviceStatus + devid;   RingBuffer *ring = c501uart_RxRingBuf(port);   unsigned char sr, ch;   /*    * Unfortunately there is no FIFO on the C501, so only handle one    * character at a time.  */   ch = c501uart_SerGetChar(serchip);   sr = c501uart_GetLineStatus(serchip);   if ( (sr == 0) && ( !ringBufFull(ring) ) )   {      ringBufPutChar(ring, ch);      if ( (serial_ETX == ch) || 	   (ringBufCount(ring) >= RING_HIGH_WATER_MARK ) )      {	 queue_rx_processing = TRUE;      }   } /* end if OK to copy char into ring */   else   {      queue_rx_processing = TRUE;      ringBufSetOvr(ring);      ringBufPutChar(ring, ch);   } /* else this is an overflow / error condition */   if ( queue_rx_processing && ((*status & SER_RX_QUEUED) == 0) )   {      *status |= SER_RX_QUEUED;      /*       * NOTE - this routine will never return       */      Angel_SerialiseISR(SerCtrl(devid)->rx_processing, (void *)devid);   } /* end if need to assign a task to process this buffer */}/* *  Function: angel_C501UARTIntHandler *   Purpose: Entry point for interrupts from the C501UART UART *            See documentation for angel_IntHandlerFn in devdriv.h */void angel_C501UARTIntHandler(unsigned int ident, unsigned int devid,                         unsigned int empty_stack){   unsigned int intsrc;   const unsigned int port = SerCtrl(devid)->port;   C501UARTReg *const serchip = c501uart_Address(port);   IGNORE(ident);      intsrc = c501uart_GetInterruptStatus(serchip);   /* We handle RX traffic first, so clear that interrupt, if applicable */   if ( (RXIntPendMask & ReadInterruptStatus()) != 0 )   {      ClearInterruptStatusMask( RXIntPendMask );   }   if ( (intsrc & (USROverrun | USRFraming | USRBreak)) != 0 )   {      /* No need to waste time, let the angel driver know they have a	 problem with this packet */      RingBuffer *ring = c501uart_RxRingBuf(port);      volatile unsigned int *const DriverStatus = angel_DeviceStatus + devid;      /* Set overrun flag, so the reader function notes that there's an	 error on the read. */      ringBufSetOvr( ring );      ringBufPutChar( ring, c501uart_SerGetChar(serchip) );      if ( (*DriverStatus & SER_RX_QUEUED) == 0 )      {	 *DriverStatus |= SER_RX_QUEUED;	 /*	  * NOTE - this routine will never return	  */	 Angel_SerialiseISR(SerCtrl(devid)->rx_processing, (void *)devid);      }      /* It'd be nice to know the scheduler would make sure this error is	 handled immediately */   } /* end if receive error */   if ( (intsrc & USRRxData) != 0 )   {      /*  Handle the incoming data */      int_rxrdy(devid, port, serchip, empty_stack);   }   /* Now handle TX traffic, so clear that interrupt, if applicable */      if ( (TXIntPendMask & ReadInterruptStatus()) != 0 )   {      ClearInterruptStatusMask( TXIntPendMask );      if ( (intsrc & USRTxHoldEmpty) != 0 )      {	 /*  Feed the uart */	 int_txrdy(devid, port, serchip, empty_stack);      }   } /* end if there's a pending TX interrupt */   else   {      if ( ((intsrc & USRTxHoldEmpty) != 0) && 	   (angel_DeviceStatus[devid] & SER_TX_DATA))      {	 int_txrdy(devid, port, serchip, empty_stack);      }	/* end if there's an opportunity to piggy back a xmit cycle */   }}#if DEBUG == 1/* Routines for logging debug information to a seperate serial port */void logserial_Reset(int port, int baudvalue){    C501UARTReg *const serchip = (C501UARTReg *)port;   /* Disable interrupts  */    c501uart_SetControlReg( serchip, 0 );   /* Set port for 8 bit, one stop, no parity  */    c501uart_SetLineControl( serchip, (ULCR8bits));   /* Enable interrupt operation on UART, needed for normal operation */    c501uart_SetControlReg( serchip, (UCRRxM | UCRTxM));   /* Set baud rate  */    c501uart_SetBaudRate( serchip, baudvalue );}#endif/* EOF serial.c */

⌨️ 快捷键说明

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