📄 cs8900.c
字号:
{
int j,i;
unsigned short status;
/* Reset chip */
WritePPRegister(PP_SelfCtl, (unsigned short)PP_SelfCtl_Reset);
/* Wait about 125 msec for chip resetting in progress */
// 省略
Delay(10);
/* check the PP_SelfStat_InitD bit if the chip successflly reset */
for (i=0;i<10;i++)
{
for (j=0; j<3000; j++)
{
status=(ReadPPRegister(PP_SelfStat) & PP_SelfStat_InitD);
if ( status != 0 )
{
return 0 /* successful */;
}
}
}
return -1; /* fail */
}
//获取要传送数据的总长度,host传到cs的数据长度
U16 get_frame_len(unsigned char *dataBuf)
{
U16 *ptr = (U16*)dataBuf;
ptr += 6;
return *ptr;
}
/**************************************************************************/
/* cs8900_poll_send(): Transmit a frame in Poll mode. */
/**************************************************************************/
int cs8900_poll_send(unsigned char *dataBuf)
{
int len;
unsigned short *sdata;
unsigned short stat;
unsigned long i;
int total_len = get_frame_len(dataBuf) + 14;
// Uart_Printf("ss%d\n", total_len);
/****** Step 0: First thing to do is to disable all interrupts at processor level.*/
/****** Step 1: Write the TX command */
if ( gPrevTxBidFail )
{
/* Previous BidForTX has reserved the Tx FIFO on CS8900, must clear off it.*/
/* Setting PP_TxCmd_Force bit will cause CS8900 to release the previous reserved Tx buffer.*/
CS8900_TxCMD = (unsigned short) PP_TxCmd_TxStart_Full | PP_TxCmd_Force;
gPrevTxBidFail=0;
}
else
{
CS8900_TxCMD = (unsigned short) PP_TxCmd_TxStart_Full;
}
printf("\n----------Start Translate--------\n");
/****** Step 2: Bid for Tx ******/
/* Write the frame length (number of bytes to TX) */
/* Note: After the frame length has been written, CS8900 reserves Tx buffer for this bid no
matter PP_BusStat_TxRDY is set or not.*/
CS8900_TxLEN = total_len;
/* Read BusST to verify it is set as Rdy4Tx. */
stat = ReadPPRegister(PP_BusStat);
/****** Step 3: check if TxBidErr happens ******/
if ( stat & PP_BusStat_TxBid )
{ /*TxBidErr happens only if Tx_length is too small or too large. */
printf(" Tx Bid Error! TxLEN=%d \n", total_len);
printf("----------End Translate-------------\n");
/****** Step 3.1: enable interrupts at processor level if it is disabled in step 0.******/
/*enable( ); */
return -1;
}
/****** Step 4: check if chip is ready for Tx now ******/
/* If Bid4Tx not ready, skip the frame */
// while ( (stat & PP_BusStat_TxRDY) == 0);
if ( (stat & PP_BusStat_TxRDY) == 0)
{
/* If not ready for Tx now, abort this frame.*/
/* Note: Another alternative is to poll PP_BusStat_TxRDY until it is set, if you don't want to
abort Tx frames.*/
gPrevTxBidFail=1;/* set to 1, and next time if cs8900_poll_send() is called, it can
set PP_TxCmd_Force to clear off the reserved Tx buffer in CS8900 chip.*/
printf("Tx Bid Not Ready4Tx! \n");
printf("------End Translate-------\n");
/****** Step 4.1: enable interrupts at processor level if it is disabled in step 0.******/
return -1;
}
printf("Start to Translate\n");
/****** Step 5: copy Tx data into CS8900's buffer*/
/* This actually starts the Txmit*/
sdata = (unsigned short *)dataBuf;
len = total_len;
if (len > 0)
{
/* Output contiguous words, two bytes at a time. */
while (len > 1)
{
CS8900_RTDATA = *sdata;
sdata++;
len -= 2;
printf(".");
}
/* If Odd bytes, copy the last one byte to chip.*/
if (len == 1)
{
CS8900_RTDATA = (*sdata) & 0x00ff;
}
}
printf("\nEnding Translate\n");
/****** Step 5.1: enable interrupts at processor level if it is disabled in step 0.******/
/*enable( ); */
/****** Step 6: Poll the TxEvent Reg for the TX completed status */
/* This step is optional. If you don't wait until Tx compelete, the next cs8900_poll_send()
Bid For Tx may encounter Not Ready For Tx because CS8900 is still Tx'ing.*/
for ( i=0; i<30000; i++)
{
stat = ReadPPRegister(PP_TER);
if ( stat != 0x0008 )
{
break;
}
}
/* Tx compelete without error, return total_length Tx'ed */
if ( (stat & PP_TER_TxOK) || (stat == 0x0008) )
{
printf("Translate successful \n");
printf("----------End Translate-------\n");
return total_len; /* return successful*/
}
/* Tx with Errors */
printf("Tx Error! TxEvent=%x \n", stat);
printf("----------End Translat--------\n");
return -1; /* return failed*/
}
/**************************************************************************************/
/* cs8900_poll_recv(): can be used to receive a frame in Poll mode. */
/**************************************************************************************/
int cs8900_poll_recv( unsigned char *dataBuf)
{
unsigned short stat, totalLen, val;
int leftLen;
unsigned short *data;
unsigned char *cp;
/****** Step 1: check RxEvent Register ******/
stat = ReadPPRegister(PP_RER);
/****** Step 2: Determine if there is Rx event. ******/
/* If nothing happened, then return. 0x0004 is the register ID.
If some bits in Bit 6 - Bit 15 are set, some Rx event happened. */
if ( stat == 0x0004 )
{
return 0;
}
/****** Step 3: Determine if there is Rx Error. ******/
/* If RxOk bit is not set, Rx Error occurred */
if ( !(stat & PP_RER_RxOK) )
{
if ( stat & PP_RER_CRC)
{
printf("cs8900_poll_recv(): received frame with CRC error.\n");
}
else if ( stat & PP_RER_RUNT)
{
printf("cs8900_poll_recv(): received frame with RUNT error.\n");
}
else if (stat & PP_RER_EXTRA )
{
printf("cs8900_poll_recv(): received frame with EXTRA error.\n");
}
else
printf("cs8900_poll_recv(): Unknown Error: stat=%x \n", stat);
/****** Step 4: skip this received error frame. ******/
/* Note: Must skip this received error frame. Otherwise, CS8900 hangs here. */
/* Read the length of Rx frame */
totalLen= ReadPPRegister(PP_Rx_LENGTH);
/* Write Skip1 to RxCfg Register and also keep the current configuration.*/
val = ReadPPRegister(PP_RxCFG);
val |= PP_RxCFG_Skip1;
WritePPRegister(PP_RxCFG, val);
return -1; /* return failed */
}
printf("\n--------Start Receive Data--------------\n");
/****** Step 5: Read the length of Rx frame ******/
totalLen = ReadPPRegister(PP_Rx_LENGTH);
/* uncomment printf for debugger purpose.*/
printf("RxEvent - stat: %x, len: %d\n", stat, totalLen);
/****** Step 6: Read the Rx data from Chip and store it to user buffer ******/
data = (unsigned short *)dataBuf;
leftLen = totalLen;
/* read 2 bytes at a time */
while (leftLen >= 2)
{
*data++ = CS8900_RTDATA;
leftLen -= 2;
}
/* if odd bytes, read the last byte from chip*/
if (leftLen == 1)
{
/* Read the last byte from chip*/
val = CS8900_RTDATA;
/* point to the last one byte of the user buffer*/
cp = (unsigned char *)data;
/* truncate the word (2-bytes) read from chip to one byte */
*cp = (unsigned char)(val & 0xff);
}
return (int)totalLen;
}
/**************************************************************************************/
/* 发送数据,长度为dataLen */
/*参数pData 为host准备发送的缓冲区,dataLen为本缓冲区欲发送数据的长度,在发送函数里,总的数据长度应length+物理地址长度+目的地址长度+数据长度位(2)*/
/**************************************************************************************/
//使用gTxDataBuf作为发送缓冲区
S16 s3c2410_eth_send(const char*pData,const U16 dataLen)
{
unsigned char *pRoller;
U16 *temp;
S16 stat;
int i;
pRoller=(unsigned char * )gTxDataBuf;
//写目的地址
memcpy(pRoller, EtherDesAddr, 6);
pRoller +=6;
//写源地址
memcpy(pRoller, EtherAddr, 6);
pRoller +=6;
temp = (U16 *)pRoller;
* temp = dataLen;
pRoller+=2;
memcpy(pRoller, pData,dataLen);
/* for (i = 0; i < 6; i ++)
Uart_Printf("%x", gTxDataBuf[i]);
Uart_Printf("\n");
for (; i < 12; i ++)
Uart_Printf("%x", gTxDataBuf[i]);
Uart_Printf("\n");
Uart_Printf("%d\n", (int *)gTxDataBuf[i ++]);
for (; i < dataLen + 15; i ++)
Uart_Printf("%c", gTxDataBuf[i]);
Uart_Printf("\n"); */
stat = cs8900_poll_send((unsigned char * )gTxDataBuf);
return stat;
}
/*
//发送数据
int data_send_cs()
{
creat_send_data();
}*/
/*
//创建用来发送的数据,把要出送的数据组装成以太网桢
void creat_send_data(void)
{
unsigned char *pRoller;
pRoller = (unsigned char * )gTxDataBuf;
//写目的地址
memcpy(pRoller, EtherDesAddr, 6);
pRoller +=6;
//写源地址
memcpy(pRoller, EtherAddr, 6);
pRoller +=6;
}
*/
//接收包,阻塞函数,一直等到有数据过来,要么错误要么正确
S16 s3c2410_eth_receive(unsigned char* dataBuf)
{
unsigned short stat = 0;
printf("\nReceive Pool \n");
while (stat == 0)
{
stat = cs8900_poll_recv(dataBuf);
printf(".");
}
printf("\n");
if (stat >0)
{
printf("Receive data OK,Length is %d\n",stat);
}
else
{
printf("Receive data Error\n");
}
printf("--------End Receive Data--------------\n");
return (int)stat;
}
//判断电缆是否插好
int s3c2410_line_plug()
{
U16 stat;
stat = ReadPPRegister(PP_LineStat);
//电缆没有插好
if (!(stat & PP_LineStat_LinkOK)) {
Uart_Printf("电缆没有插好!\n");
return -1;
}
else
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -