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

📄 drv_serial.c

📁 Atmel公司的AT91 ARM7平台上的串口驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
**
**  Copyright  (c)  2005,  UTStarcom, Inc.
**          All Rights Reserved.
**
**  Subsystem  : PCSI Board Firmware
**  File       : serial.c
**  Created By : 
**  Created On : 01/05/2006
**
**  Purpose:
**    This file provides functions that communicate with SCM based on other Board Firmware
**
****************************************************************************/

#include "string.h"

#include "regs.h"
#include "libs.h"
#include "hw_if.h"
#include "pfs_func.h"

#include "drv_fpga.h"
#include "drv_serial.h"
#include "csc_cmd.h"

#define put_char	AT91F_US_PutChar
#define get_char	AT91F_US_GetChar

LOCAL void cli_cmd_process(void);
#ifdef DEBUG
LOCAL void	dump_buffer1(INT8 *str,UINT8 *ptr,UINT8 len);
LOCAL void	dump_buffer(void);
#endif

/* static variales definition*/
LOCAL	UINT8   tx_enable = 0;
LOCAL	UINT8   state;			/* serial communication state */

LOCAL	UINT8   nack_sent;		/* counter of sent NACK */
LOCAL	UINT8   rcv_full;			/* counter of times of receive buffer full */
LOCAL	UINT8   xmt_full;		/* counter of times of tranmission buffer full */
LOCAL	UINT8   err_count;		/* other error count */

LOCAL	UINT8   received;		/* counter of outstanding packets received */
LOCAL	UINT8   l2_received;		/* packets count */
LOCAL	UINT8   l3_received;		/* packets count */
LOCAL	UINT8	  unknown_cmd;	/* unknown cmd count*/

LOCAL	UINT8   serial_buf[BUF_LENGTH];	/* receive and transmission buffer */
LOCAL	UINT16  xmt_in_ptr,xmt_out_ptr;	/* transmission round buffer input and output pointers */
LOCAL	UINT16  in_rcv_ptr,out_rcv_ptr;	/* receive round buffer input and output pointers */

/* led active/deactive port */
UINT32	comm_cnt = 0;
UINT32	comm_led_timer;
UINT32	alive_led_timer;
INT32		comm_led = 0;
INT32		alive_led = 0;

UINT32	pos;				/* position write to the flash*/
UINT16	seqno;				/* next seqno*/

/* follow reads from CPLD */
UINT8		BOARD_TYPE;		/* board type for board which has extension board id */

UINT8		slot_no;				/* slot number that the board resides in */
UINT8 	dwnl_state;			/*Current firmware download state*/
UINT8 	port_bitmap;		/* port bitmap needs update firmware*/
UINT8		dwnl_port = 0;		/* temp save the port bitmap*/
UINT8		imdt_switch = 0;		/*  Download end immediate switch */

/*used to download PCSI firmware*/
UINT8 poll_addr;
UINT8 download_flag;
UINT8 slot_addr;/*the msg of which slot addr is processing*/
UINT8 led_status;/*led status when download*/

/****************************************************************************
**
**  Function Name: dispatch_to_serial 
**
**  Description:
**		Called when a version or board_type needs to be sent to SCM via serial bus   
**		called by serial_receive_process in main context
**
**  Argument        Type     IO           Description
**  --------------- -------- -- ---------------------------------
**  N/A
**
**  Return Value: N/A
**
****************************************************************************/
UINT8 dispatch_to_serial(UINT8 length, UINT8 *ptr)
{
	UINT8 checksum, tmp,len;
	UINT8 * index;

	/* If enter into multi slot download mode, only response the message sent to itself.
		If in normal mode, only message sent itself it can receive.	*/
	if((download_flag==0)||((download_flag!=0) && (slot_addr==slot_no)))
	{	
		if ( serial_buf[xmt_in_ptr] ) //serial buffer is full
		{
#ifdef DEBUG
			usart_print(DBG_PORT_ID,"********serial buffer is full, lose one msg to CSC: ");
			usart_print(DBG_PORT_ID,byte2hexstr(*ptr));
			usart_print(DBG_PORT_ID,byte2hexstr(*(ptr+1)));
			usart_print(DBG_PORT_ID,byte2hexstr(*(ptr+2)));
			usart_print(DBG_PORT_ID,"  !!!\n");
#endif
			xmt_full++;
			return 0;
		}
		/* too many data in one packet*/
		if ( length > (XMT_BUF-5))
			return 0; 
			
		index = &serial_buf[xmt_in_ptr];
		checksum = 0;
		len = length;
    	index++ ;	/* skip over length field */
		*index++ = ~length;

		while(length)
	 	{
			tmp = *ptr++;
			checksum += tmp;
			*index++ = tmp;
			length--;
		}
		*index++ = checksum;
		*index   = ~checksum;
	 	
		serial_buf[xmt_in_ptr] = len;
		inc_xmt_ptr(xmt_in_ptr);
	}
	return 1;
}

void comm_led_callback(UINT32 i)
{
	i=i;
	start_timer(comm_led_timer);
	if(comm_cnt>5)
	{
		if(comm_led==1)
		{
			comm_led=0;
			set_usart_led(0,comm_led);
		}
	}
	else
	{
		comm_cnt++;
		comm_led=!comm_led;
		set_usart_led(0,comm_led);
	}
}

void alive_led_callback(UINT32 i)
{
	i=i;
	if(comm_cnt>5)
	{
		start_timer_chgtm(alive_led_timer,FAST_BLINK);
	}
	else
	{
		start_timer_chgtm(alive_led_timer,ALIVE_BLINK);
	}
	alive_led=!alive_led;
	set_usart_led(1,alive_led);
}

/****************************************************************************
**
**  Function Name: serial_init 
**
**  Description:
**		init serial bus parameters  
**		called by main in basic loop 
**
**  Argument        Type     IO           Description
**  --------------- -------- -- ---------------------------------
**  N/A
**
**  Return Value: N/A
**
****************************************************************************/
void serial_init (void)
{   
	UINT8 i;

	AT91F_PIO_CfgOutput( AT91C_BASE_PIO, IO_COMM_CTL);
	release_bus; 
	
	disable_pare;
	disable_rcv;
	disable_tx;
	init_xmt_ptr(xmt_in_ptr);
	init_xmt_ptr(xmt_out_ptr);
	init_rcv_ptr(in_rcv_ptr);
	init_rcv_ptr(out_rcv_ptr);

	for( i = 0; i < XMT_QUE; i++)	
	{
		serial_buf[xmt_in_ptr] = 0;
		inc_xmt_ptr(xmt_in_ptr);
	}

	init_xmt_ptr(xmt_in_ptr);

	dwnl_state=DWNL_IDLE;
	seqno=1;
	pos=0;
	
	state = STATE_IDLE;

	nack_sent	= 0;
	rcv_full	= 0;
	xmt_full	= 0;
	err_count = 0;

	received = 0;
	l2_received = 0;
	l3_received = 0;
	unknown_cmd = 0;

	/* read board info */
	slot_no			= get_slot_id();
	if (app_boot())
	{
		BOARD_TYPE		= APP_BOARD_TYPE;
	}
	else
	{
		BOARD_TYPE		= DNLD_BOARD_TYPE;;
	}
	
	download_flag=1;/*need to download when init*/
	
	comm_led_timer=alloc_timer_urgent(NORMAL_BLINK, (tm_handler) comm_led_callback, 0);
	start_timer(comm_led_timer);

	alive_led_timer=alloc_timer_urgent(ALIVE_BLINK, (tm_handler) alive_led_callback, 0);
	start_timer(alive_led_timer);
	
	led_status=0;
	
	/*enable parity error interrupt*/
	enable_pare;
}

/****************************************************************************
**
**  Function Name: serial_bus_int 
**
**  Description:
**     Back plane serial bus comm Interrupt Service Routine 
**
**  Argument        Type     IO           Description
**  --------------- -------- -- ---------------------------------
**  N/A
**
**  Return Value: N/A 
**
****************************************************************************/
//*----------------------------------------------------------------------------
//* Function Name       : serial_bus_int
//* Object              : C handler interrupt function called by the interrupts 
//*                       assembling routine
//* Input Parameters    : <RTC_pt> time rtc descriptor
//* Output Parameters   : increment count_timer0_interrupt
//*----------------------------------------------------------------------------
void serial_bus_int (AT91PS_USART USART_pt)/*  interrupt SIO_VECTOR using SERIAL_BANK */
{
	register unsigned char ch;
	LOCAL	UINT8   checksum;		/* check sum duration receiving */
	LOCAL	UINT8   rcv_length;		/* packet length of receiving */
	LOCAL	UINT8   xmt_length;		/* packet length of transmitting */
	UINT32 	status;

	/* get Usart status register*/
	status = USART_pt->US_CSR;
	/*address interrupt, if PARE is 1, it's address frame*/
    if( status & AT91C_US_PARE )
    {
		ch = get_char(USART_pt);
		release_bus;
		/*error process*/
		if(state != STATE_IDLE)	
		{
			err_count++;
			reset_xmt_ptr(xmt_out_ptr);
			reset_rcv_ptr(in_rcv_ptr);
		}
		/*multi slot listen mode*/
		if(download_flag)
		{
			state = STATE_RCV_SLOT;
			poll_addr=ch;
			enable_rcv;
		}
		/*if it's not under download mode, only receive own message*/
		else
		{
		      if(ch == slot_no)
		      {
				state = STATE_RCV_SLOT;
				enable_rcv;    	/*enable 8 bits interrupt   */
		       }
		       else
		       {
				state = STATE_IDLE;
				disable_rcv;   	/* disable 8 bits interrupt  */
		       }
		}
    }
    /*if PARE is 0,it's data frame*/
    else if(status & AT91C_US_RXRDY/* RCV int*/ )
    {  
		ch = get_char(USART_pt);
		/*multi slot listen mode*/
		if(download_flag)
		{
        	switch(state)
			{
		        case    STATE_IDLE:
		            break;
		        case    STATE_RCV_SLOT:
		            if( ch == poll_addr)    
					   state = STATE_RCV_LENGTH;
		            else    
		            {
		               disable_rcv;
		               state = STATE_IDLE;
		            }
		            break;
				case    STATE_RCV_LENGTH:
				    comm_cnt=0;
				    if( ch == 0) //it is our turn to send some data if we have   
				    {
					   if(poll_addr==slot_no)
					   {
				          seize_bus;  
				          if( serial_buf[xmt_out_ptr] )    /* send data to master*/
				          {                   
							     enable_tx;
							     put_char(USART_pt, slot_no);
							     xmt_length = serial_buf[xmt_out_ptr] + 4;
							     state = STATE_XMT_MSG; 
				          }
				          else        /* send board type only to master*/
				          {                          
							     enable_tx;
							     put_char(USART_pt, BOARD_TYPE);
							     state = STATE_XMT_BOARD;
				          }
					    }
				        else
					       disable_rcv;
				    }
				    /*polling me, return board_type*/
				    else
				    if (ch == 0xff)    /*send board type and its complement to master*/
				    {
					   if(poll_addr==slot_no)
						 {
							   seize_bus;  
								enable_tx;
								put_char(USART_pt, BOARD_TYPE);
								state = STATE_XMT_1STBOARD;  /*enable transmission*/
								disable_rcv;
						 }
					else
					   disable_rcv;
				    }
				    else    /* normal data packet from master*/
				       {                   
				          if(ch >= RCV_BUF )
					      {
					         err_count++;
					      }
				          else 
						  if(received == RCV_QUE)	/* need more considerations */
						  {
						     rcv_full++;
						     reset_rcv_ptr(in_rcv_ptr);
						     disable_rcv;
						  }
				          else
				          {
				             rcv_length = ch;
				             checksum = 00; 
				             serial_buf[in_rcv_ptr++] = ch;
				             state = STATE_RCV_DATA;
				          }
				        }
				    break;
				   
		        case    STATE_RCV_DATA:
						serial_buf[in_rcv_ptr++] = ch;
						checksum += ch;
						if( --rcv_length == 0)	
						   state = STATE_RCV_1STCHECK;
					   break;

		        case    STATE_RCV_1STCHECK:
						if( ch == checksum)
				   	   state = STATE_RCV_2NDCHECK;
						else
						{
						   if(poll_addr==slot_no)
						   {
						     seize_bus;
						     disable_rcv;
						     enable_tx;
						     put_char(USART_pt, NACK);
							  reset_rcv_ptr(in_rcv_ptr);
							  state = STATE_XMT_NACK;
							  nack_sent++;
						   }
						   else
						     disable_rcv;
						}
				    break;

		        case    STATE_RCV_2NDCHECK:
		            if( (ch&checksum))    
		            {
					   	if(poll_addr==slot_no)
					   	{
						     seize_bus;
							  disable_rcv;
							  enable_tx;
							  put_char(USART_pt, NACK);
							  reset_rcv_ptr(in_rcv_ptr);
							  state = STATE_XMT_NACK;
							  nack_sent++;
						   }
					   	else
						  	  disable_rcv;
		            }
		            else    /*  checksum correct */
		            {   
						   l2_received++;
						   if(received < RCV_QUE)
						      received ++; 
						   else
						      rcv_full++;

⌨️ 快捷键说明

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