📄 socket.c
字号:
switch (func) {
case SEL_CONTROL : // socket status information
val = idmr(SOCK_STATUS(s));
break;
case SEL_SEND : // Calculate send free buffer size
read_4reg( SHADOW_TXWR_PTR(s), wr_ptr.cVal, TX_WR_PTR(s,0) );
read_4reg( SHADOW_TXACK_PTR(s), ack_ptr.cVal, TX_ACK_PTR(s,0) );
if (wr_ptr.lVal >= ack_ptr.lVal)
val = SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal);
else
val = SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal);
#ifdef DEBUG_SOCK
printf("\n\r[%d] WR=0x%08lx AK=0x%08lx", (int)s, (u32)wr_ptr.lVal, (u32)ack_ptr.lVal);
#endif
break;
case SEL_RECV : // Calculate received data size
read_4reg( SHADOW_RXWR_PTR(s), wr_ptr.cVal, RX_WR_PTR(s,0) );
read_4reg( SHADOW_RXRD_PTR(s), rd_ptr.cVal, RX_RD_PTR(s,0) );
if (wr_ptr.lVal == rd_ptr.lVal)
val = 0;
else if (wr_ptr.lVal > rd_ptr.lVal)
val = wr_ptr.lVal - rd_ptr.lVal;
else
val = 0 - rd_ptr.lVal + wr_ptr.lVal;
#ifdef DEBUG_SOCK
printf("\n\r[%d] WR=0x%08lx RD=0x%08lx (len=%04x)", (int)s, (u32)wr_ptr.lVal, (u32)rd_ptr.lVal, (u16)val);
#endif
break;
default :
val = -1;
break;
}
return(val);
}
/*
*********************************************************************************************************
* Internal function for sending TCP data.
*
* Description : Called by the SOCK_send() function for TCP transmission.
* It first calculates the free transmit buffer size
* and compares it with the size of the data to be transmitted to determine the transmission size.
* After calculating the data size, it copies data from TX_WR_PTR.
* It waits if there is a previous send command in process.
* When the send command is cleared, it updates the TX_WR_PTR up to the size to be transmitted and performs the send command.
* Arguments : s - channel number
* buf - Pointer pointing data to send
* len - data size to send
* Returns : Succeeded: sent data size, Failed: -1
* Note : Internal Function
*********************************************************************************************************
*/
int send_in(SOCKET s, u8 * buf, u16 len, u8 flag, u8 isTcp)
{
xdata u16 size;
xdata u8 * send_ptr;
xdata union un_l2cval wr_ptr, rd_ptr;
#ifdef DEBUG_SOCK
xdata u16 free_check_retry=0;
xdata u16 retry=0;
#endif
xdata u16 bufaddr;
S_START:
read_4reg( SHADOW_TXWR_PTR(s), wr_ptr.cVal, TX_WR_PTR(s,0) );
if(isTcp)
{
read_4reg( SHADOW_TXACK_PTR(s), rd_ptr.cVal, TX_ACK_PTR(s,0) );
}
else
{
read_4reg( SHADOW_TXRD_PTR(s), rd_ptr.cVal, TX_RD_PTR(s,0) );
}
// Calculate send free buffer size
if (wr_ptr.lVal >= rd_ptr.lVal)
size = SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal);
else
size = SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal);
// Recalulate after some delay because of error in pointer calculation
if (size > SSIZE[s]) {
if (isTcp)
{
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED) return -1;
}
#ifdef DEBUG_SOCK
printf("\n\rsend_in: ch=%d : err in ptr wr=0x%08lx rd=0x%08lx", (int)s, wr_ptr.lVal, rd_ptr.lVal);
#endif
wait_1ms(1);
#ifdef DEBUG_SOCK
retry++;
#endif
goto S_START;
}
#ifdef DEBUG_SOCK
if(retry){
printf("\n\rsend_in: pointer err cnt = %u", retry);
}
#endif
// Wait when previous sending has not finished yet and there's no free buffer
if (size == 0) {
if (isTcp)
{
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED) return -1;
}
wait_1ms(1);
#ifdef DEBUG_SOCK
free_check_retry++;
#endif
goto S_START;
} else if (size < len) {
len = size;
}
#ifdef DEBUG_SOCK
if(free_check_retry){
printf("\n\rsend_in: buf free check cnt = %u", free_check_retry);
}
#endif
// Calculate pointer to data copy
send_ptr = (u8 *)(SBUFBASEADDRESS[s] + (u16)(wr_ptr.lVal & SMASK[s]));
if (flag == SEND_NODELAY) {
write_data(s, buf, send_ptr, len); // copy data
while (idmr(COMMAND(s)) & CSEND) { // Confirm previous send command
if (isTcp) {
if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED) return -1;
}
else {
if (select(s, SEL_CONTROL) == SOCK_CLOSED) return -1;
}
}
wr_ptr.lVal = wr_ptr.lVal + len; // update tx_wr_ptr
write_4reg(wr_ptr.cVal, TX_WR_PTR(s,0));
wait_1us(1);
idmw(COMMAND(s), CSEND); // SEND
}
else { // SEND_DELAY
// save network target buffer address
bufaddr = (u16)send_ptr;
bufaddr_h = (u8)(bufaddr >> 8);
bufaddr_l = (u8) bufaddr;
// save network write pointer
tx_wr_ptr_save.lVal = wr_ptr.lVal + len;
}
return(len);
}
/*
*********************************************************************************************************
* Copies the receive buffer data of the W3100A to the system buffer.
*
* Description : Copies the receive buffer data of the W3100A to the system buffer.
* It is called from the SOCK_recv()or SOCK_recvfrom() function.
* Arguments : s - channel number
* src - receive buffer pointer of W3100A
* dst - system buffer pointer
* len - data size to copy
* Returns : copied data size
* Note : Internal Function
*********************************************************************************************************
*/
u16 read_data(SOCKET s, u8 * src, u8 * dst, u16 len)
{
u16 xsrc;
xdata u16 i, size, size1;
if (len == 0) return 0;
xsrc = (u16)src;
if ((((u32)src & RMASK[s]) + len) > RSIZE[s]) {
size = RSIZE[s] - ((u32)src & RMASK[s]);
for (i = 0; i < size; i++) {
//*dst++ = XBYTE[xsrc++];
*dst++ = idmr(xsrc++);
}
size1 = len - size;
xsrc = (u16)RBUFBASEADDRESS[s];
for (i = 0; i < size1; i++) {
//*dst++ = XBYTE[xsrc++];
*dst++ = idmr(xsrc++);
}
}
else {
for (i = 0; i < len; i++) {
//*dst++ = XBYTE[xsrc++];
*dst++ = idmr(xsrc++);
}
}
return len;
}
/*
*********************************************************************************************************
* Copies the system buffer data to the transmit buffer of the W3100A.
*
* Description : Copies the system buffer data to the transmit buffer of the W3100A.
* It is called from the send_in()or sendto_in() function.
* Arguments : s - channel number
* src - system buffer pointer
* dst - send buffer pointer of W3100A
* len - data size to copy
* Returns : copied data size
* Note : Internal Function
*********************************************************************************************************
*/
u16 write_data(SOCKET s, u8 * src, u8 * dst, u16 len)
{
xdata u16 i, size, size1;
u16 xdst;
if (len == 0) return 0;
#ifdef DEBUG_SOCK
printf("\n\rwrite_data: src=0x%04x dst=0x%04x len=%d\n\r", (u16)src, (u16)dst, len);
#endif
xdst = (u16)dst;
if ((((u32)xdst & SMASK[s]) + len) > SSIZE[s]) {
size = SSIZE[s] - ((u32)xdst & SMASK[s]);
for (i = 0; i < size; i++) {
//XBYTE[xdst++] = *src++;
idmw( xdst++, *src++ );
}
size1 = len - size;
xdst = (u16)SBUFBASEADDRESS[s];
for (i = 0; i < size1; i++) {
//XBYTE[xdst++] = *src++;
idmw( xdst++, *src++ );
}
}
else {
for (i = 0; i < len; i++) {
//XBYTE[xdst++] = *src++;
idmw( xdst++, *src++ );
}
}
return len;
}
/*
*********************************************************************************************************
* Create random value for initial Seq# when establishing TCP connection
*
* Description : In this function, you can add some source codes to create random number for initial Seq#
* In real, TCP initial SEQ# should be random value.
* (Currently, we're using static value in EVB/DK.)
* Arguments : s - channel number
* Returns : None
* Note : API Function
*********************************************************************************************************
*/
void initseqnum(SOCKET s)
{
SEQ_NUM.lVal++; // Designate initial seq#
// If you have random number generation function,
// assign random number instead of SEQ_NUM.lVal++.
//SEQ_NUM.lVal=0xffffffff;
write_4reg(SEQ_NUM.cVal, TX_WR_PTR(s,0));
wait_1us(2);
write_4reg(SEQ_NUM.cVal, TX_RD_PTR(s,0));
wait_1us(2);
write_4reg(SEQ_NUM.cVal, TX_ACK_PTR(s,0));
wait_1us(2);
}
/*
*********************************************************************************************************
wait_1us is working for 4us when input, i, is 2
*********************************************************************************************************
*/
volatile void wait_1us(int i)
{
// xdata u16 j;
// for(j=0;j<i;j++);
i++;
return;
}
/*
*********************************************************************************************************
*********************************************************************************************************
*/
volatile void wait_1ms(int i)
{
u16 n = WAIT1MS_40MHZ;
u16 x;
while(i-- > 0)
{
n = WAIT1MS_40MHZ;
for(x=0;x<WAIT1MS_40MHZ;x++)
n--;
}
}
/*
*********************************************************************************************************
*********************************************************************************************************
*/
void enable(void)
{
EX1 = 1;
}
/*
*********************************************************************************************************
*********************************************************************************************************
*/
void disable(void)
{
EX1 = 0;
}
void lan_int_enable(void)
{
lan_enable();
enable();
dv03_enable();
}
void lan_int_disable(void)
{
lan_enable();
disable();
dv03_enable();
}
//=========================================================
//
//=========================================================
void read_4reg(u16 shadow, u8* val, u16 addr)
{
u8 k;
disable();
k = idmr(shadow);
wait_1us(2);
val[0] = idmr(addr+0);
val[1] = idmr(addr+1);
val[2] = idmr(addr+2);
val[3] = idmr(addr+3);
enable();
#ifdef DEBUG_GPIO
if((val[0]+val[1]+val[2]+val[3])==0)
{
P16_WZREG0 = HIGH;
delay_time(10, 1);
//printf("\n\rWZNET REG OFF=%04x VAL=0x00000000", addr);
P16_WZREG0 = LOW;
}
#endif
}
//=========================================================
//
//=========================================================
void write_4reg(u8* val, u16 addr)
{
disable();
idmw(addr+0, val[0]);
idmw(addr+1, val[1]);
idmw(addr+2, val[2]);
idmw(addr+3, val[3]);
enable();
}
#endif // LANIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -