Commit b5619b36 authored by Martin Vítek's avatar Martin Vítek

Add working RX driven by interrupt

parent 97e514aa
......@@ -60,7 +60,7 @@ void Debug::reg(const char* name, const uint16_t value)
uart.send_new_line();
}
void Debug::frame(const ethernet_frame &frame)
void Debug::frame(const ethernet_frame& frame)
{
uart.send("[FRAME] \n\r");
......@@ -112,6 +112,28 @@ void Debug::frame(const ethernet_frame &frame)
uart.send_new_line();
}
void Debug::frame_type(const ethernet_frame* frame)
{
uart.send("[INFO] ");
uart.send("RX frame type: ");
switch (__htons(frame->type_length))
{
case IPV4: uart.send("IPv4");
break;
case ARP: uart.send("ARP");
break;
case REVERSE_ARP: uart.send("Reverse ARP");
break;
default: uart.send("Unknown");
}
uart.send_new_line();
}
void Debug::tx_status(const ENC28J60_namespace::tx_status_vector& status, bool simple/*= true*/)
{
debug.info("TX status vector: ");
......
......@@ -43,7 +43,8 @@ class Debug
void error(const char* s);
void reg(const char* name, const uint8_t value);
void reg(const char* name, const uint16_t value);
void frame(const ethernet_frame &frame);
void frame(const ethernet_frame& frame);
void frame_type(const ethernet_frame* frame);
void tx_status(const ENC28J60_namespace::tx_status_vector& status, bool simple=true);
void rx_status(const ENC28J60_namespace::rx_status_vector& status, bool simple=true);
void adc();
......
......@@ -354,8 +354,7 @@ namespace ENC28J60_namespace
}
else return false;
}
}
void ENC28J60::rx_handler(ethernet_frame& frame)
{
......@@ -452,8 +451,6 @@ namespace ENC28J60_namespace
bit_field_set_in_register(ECON1, TXRTS_bm);
}
bool ENC28J60::tx_was_successuful()
{
if (read_control_register(ESTAT) & TXABRT_bm)
......@@ -481,6 +478,101 @@ namespace ENC28J60_namespace
return true;
}
}
uint8_t ENC28J60::rx_pending_frames()
{
return read_control_register(EPKTCNT);
}
bool ENC28J60::rx_frame(ethernet_frame* frame)
{
//TODO: next_packet_pointer is not necessary
uint16_t next_packet_pointer;
rx_status_vector status;
//Go to start of packet
write_control_register(ERDPTL, eth_rx_packet_start&0xFF);
write_control_register(ERDPTH, eth_rx_packet_start>>8);
read_buffer_memory(next_packet_pointer);
read_buffer_memory(status.vector, 4);
//Save address of next packet
eth_rx_packet_start = next_packet_pointer;
//CRC error
if (status.bit.crc_error)
{
//Decrement packet count
bit_field_set_in_register(ECON2, PKTDEC_bm);
debug.error("Received frame - mishmash CRC (packet was dropped)");
debug.rx_status(status);
return false;
}
//Length check error
if (status.bit.length_check_error)
{
//Decrement packet count
bit_field_set_in_register(ECON2, PKTDEC_bm);
debug.error("Received frame - length field doesn't correspond with rx bytes");
debug.rx_status(status);
return false;
}
//Packet wasn't received ok
if (!status.bit.received_ok)
{
//Decrement frames count
bit_field_set_in_register(ECON2, PKTDEC_bm);
debug.error("Received frame isn't OK");
debug.rx_status(status);
return false;
}
frame->payload.length = (status.bit.rx_byte_count) - 18; //Payload length including padding
//Destination address
read_buffer_memory(frame->dest_address, 6);
//Source address
read_buffer_memory(frame->src_address, 6);
//Type/length
read_buffer_memory(frame->type_length);
//Data
read_buffer_memory(frame->payload.data, frame->payload.length);
//CRC
//TODO: Who needs CRC?
//read_buffer_memory(frame.crc);
//Free space in buffer - set read pointer to next packet pointer
//Fix from errata, issue 14 - ERXRDPT must be only odd value (and packets starts at even address)
if (next_packet_pointer == eth_rx_buffer_start)
{
write_control_register(ERXRDPTL, eth_rx_buffer_end&0xFF);
write_control_register(ERXRDPTH, eth_tx_buffer_end<<8);
}
else
{
write_control_register(ERXRDPTL, (next_packet_pointer-1)&0xFF);
write_control_register(ERXRDPTH, (next_packet_pointer-1)<<8);
}
//Decrement packet count
bit_field_set_in_register(ECON2, PKTDEC_bm);
return true;
}
void ENC28J60::get_interrupt_source()
{
......
......@@ -114,12 +114,15 @@ namespace ENC28J60_namespace
//RX & TX
void tx_frame_blocking(const ethernet_frame &frame);
bool rx_frame_blocking(ethernet_frame &frame);
void tx_handler(ethernet_frame& frame);
void rx_handler(ethernet_frame& frame);
bool tx_frame(ethernet_frame* frame);
bool tx_was_successuful();
uint8_t rx_pending_frames();
bool rx_frame(ethernet_frame* frame);
//Interrupt handler
inline void interrupt_handler();
......
......@@ -58,7 +58,20 @@ void NixieStack::check_link()
void NixieStack::rx_handler()
{
//There is pending received packet
if (eth.flag_pending_packet)
{
//If was RX successuful
if (eth.rx_frame(rx_buffer.write()))
{
debug.frame_type(rx_buffer.write());
rx_buffer.write_advance();
}
//If there isn't next new frame (not captured by interrupt)
if (!eth.rx_pending_frames()) eth.flag_pending_packet = false;
}
}
void NixieStack::tx_handler()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment