示例#1
0
unsigned int enc28j60_receive_packet(unsigned int maxlen, unsigned char *buffer)
{
	unsigned int rxstat;
	unsigned int len;

	//packet in buffer ?	
	if ((enc28j60_read_address(ENC28J60_REG_EIR) & (1<<ENC28J60_BIT_PKTIF)) == 0){
		//double check!	
		//errata says that PKTIF does not work as it should 
		//->check packetcount too:
		if (enc28j60_read_address(ENC28J60_REG_EPKTCNT) == 0)
			return 0;
	}

	//set read pointer to next packet;
	enc28j60_write_address(ENC28J60_REG_ERDPTL, (enc28j60_next_packet_ptr));
	enc28j60_write_address(ENC28J60_REG_ERDPTH, (enc28j60_next_packet_ptr)>>8);

	//now read the transmit status vector
	//read next packet ptr
	enc28j60_next_packet_ptr  = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
	enc28j60_next_packet_ptr |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;

	//read packet length
	len  = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
	len |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;
	
	//read rx stat
	rxstat  = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
	rxstat |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;

	//limit read bytecount
	if (len>maxlen)
		len = maxlen;

	//transfer packet from enc28j60 to our buffer
	enc28j60_read_buffer(buffer,len);

	//mark packet as processed (free mem)

	//ERRATA says we need to check packet pointer:
	if ((enc28j60_next_packet_ptr- 1 < ENC28J60_RX_BUFFER_START) || (enc28j60_next_packet_ptr- 1 > ENC28J60_RX_BUFFER_END)){
		enc28j60_write_address(ENC28J60_REG_ERXRDPTL, LO8(ENC28J60_RX_BUFFER_END));
		enc28j60_write_address(ENC28J60_REG_ERXRDPTH, HI8(ENC28J60_RX_BUFFER_END));
	}else{
		enc28j60_write_address(ENC28J60_REG_ERXRDPTL, LO8(enc28j60_next_packet_ptr- 1));
		enc28j60_write_address(ENC28J60_REG_ERXRDPTH, HI8(enc28j60_next_packet_ptr- 1));
	}

	//decrement packet counter:
	enc28j60_spi_write_word(ENC28J60_OP_BFS|ENC28J60_REG_ECON2, (1<<ENC28J60_BIT_PKTDEC));

	return len;
}
/**
 * Fetches a pending packet from the RAM buffer of the ENC28J60.
 *
 * The packet is written into the given buffer and the size of the packet
 * (ethernet header plus payload, exclusive the CRC) is returned.
 *
 * Zero is returned in the following cases:
 * - There is no packet pending.
 * - The packet is too large to completely fit into the buffer.
 * - Some error occured.
 *
 * \param[out] buffer The pointer to the buffer which receives the packet.
 * \param[in] buffer_len The length of the buffer.
 * \returns The packet size in bytes on success, \c 0 in the cases noted above.
 */
uint16_t enc28j60_receive_packet(uint8_t* buffer, uint16_t buffer_len)
{
    if(!enc28j60_read(EPKTCNT))
        return 0;

    /* set read pointer */
    enc28j60_write(ERDPTL, packet_ptr & 0xff);
    enc28j60_write(ERDPTH, packet_ptr >> 8);

    /* read pointer to next packet */
    packet_ptr = ((uint16_t) enc28j60_read_buffer_byte()) |
                 ((uint16_t) enc28j60_read_buffer_byte()) << 8;

    /* read packet length */
    uint16_t packet_len = ((uint16_t) enc28j60_read_buffer_byte()) |
                          ((uint16_t) enc28j60_read_buffer_byte()) << 8;
    packet_len -= 4; /* ignore CRC */

    /* read receive status */
    enc28j60_read_buffer_byte();
    enc28j60_read_buffer_byte();

    /* read packet */
    if(packet_len <= buffer_len)
        enc28j60_read_buffer(buffer, packet_len);

    /* free packet memory */
    /* DS80349C.errata #14 */
    uint16_t packet_ptr_errata = packet_ptr - 1;
    if(packet_ptr_errata < RX_START || packet_ptr_errata > RX_END)
        packet_ptr_errata = RX_END;
    enc28j60_write(ERXRDPTL, packet_ptr_errata & 0xff);
    enc28j60_write(ERXRDPTH, packet_ptr_errata >> 8);

    /* decrement packet counter */
    enc28j60_set_bits(ECON2, (1 << ECON2_PKTDEC));

    if(packet_len <= buffer_len)
        return packet_len;
    else
        return 0;
}