📄 drv_serial.c
字号:
/****************************************************************************
**
** 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 + -