Commit 97e514aa authored by Martin Vítek's avatar Martin Vítek

Add working TX driven by interrupt

parent aed650b1
......@@ -357,12 +357,12 @@ namespace ENC28J60_namespace
}
void ENC28J60::rx_handler(ethernet_frame& buffer)
void ENC28J60::rx_handler(ethernet_frame& frame)
{
}
void ENC28J60::tx_handler(ethernet_frame& buffer)
void ENC28J60::tx_handler(ethernet_frame& frame)
{
if (flag_tx_done)
{
......@@ -400,6 +400,88 @@ namespace ENC28J60_namespace
}
}
bool ENC28J60::tx_frame(ethernet_frame* frame)
{
const uint8_t control_byte = 0; //Use settings from MACON3
//FIXME: add check of end of wr buffer (wrap to beginning), or better, set TX buffer to fit one ethernet frame
//TODO: it should be possible to write to the wr buffer when TX is happening -> increase data rate
uint16_t start_address;
uint16_t end_address;
//ETXST should be even
if (eth_tx_buffer_start%2 != 0) start_address = eth_tx_buffer_start +1;
else start_address = eth_tx_buffer_start;
end_address = start_address + 14 + frame->payload.length; //Start = control_byte, 14=dest+src+type
if (end_address > 0x1FFF)
{
debug.error("Frame is bigger than TX buffer");
return false;
}
//Write EWRPT pointer (where to start writing)
write_control_register(EWRPTL, start_address&0xFF);
write_control_register(EWRPTH, start_address>>8);
//Write ETXST pointer (where is control byte followed by eth frame)
write_control_register(ETXSTL, start_address&0xFF);
write_control_register(ETXSTH, start_address>>8);
//Write ETXND pointer (where is end of frame)
write_control_register(ETXNDL, end_address&0xFF);
write_control_register(ETXNDH, end_address>>8);
//Write control byte
write_buffer_memory(&control_byte, 1);
//Write ethernet frame
//TODO: write frame in one continuous operation -> speed-up
write_buffer_memory(frame->dest_address, 6);
write_buffer_memory(frame->src_address, 6);
write_buffer_memory((uint8_t*)&(frame->type_length), 2);
write_buffer_memory(frame->payload.data, frame->payload.length);
//Reset transmit logic - fix for errata, issue 12
bit_field_set_in_register(ECON1, TXRST_bm);
bit_field_clear_in_register(ECON1, TXRST_bm);
bit_field_clear_in_register(EIR, TXERIF_bm | TXIF_bm);
//Start transmission
bit_field_set_in_register(ECON1, TXRTS_bm);
}
bool ENC28J60::tx_was_successuful()
{
if (read_control_register(ESTAT) & TXABRT_bm)
{
//TODO: check for abort cause and retransmit packet
uint16_t packet_end_address;
packet_end_address = read_control_register(ETXNDL);
packet_end_address |= ((uint16_t)read_control_register(ETXNDH))<<8;
//Read back status vector
write_control_register(ERDPTL, (packet_end_address+1)&0xFF);
write_control_register(ERDPTH, (packet_end_address+1)>>8);
tx_status_vector status;
read_buffer_memory(status.vector, 7);
debug.tx_status(status);
return false;
}
else
{
return true;
}
}
void ENC28J60::get_interrupt_source()
{
interrupt_flags flags;
......
......@@ -115,8 +115,11 @@ namespace ENC28J60_namespace
void tx_frame_blocking(const ethernet_frame &frame);
bool rx_frame_blocking(ethernet_frame &frame);
void tx_handler(ethernet_frame& buffer);
void rx_handler(ethernet_frame& buffer);
void tx_handler(ethernet_frame& frame);
void rx_handler(ethernet_frame& frame);
bool tx_frame(ethernet_frame* frame);
bool tx_was_successuful();
//Interrupt handler
inline void interrupt_handler();
......
#include "NixieStack.h"
#include <cstdint>
#include <cstring>
#include <machine/endian.h>
#include "fifo.h"
#include "CircularBuffer.h"
#include "ethernet_frame.h"
#include "NetworkTypes.h"
#include "ARP.h"
#include "ENC28J60.h"
#include "Debug.h"
#include "NixieClock.h"
using namespace ENC28J60_namespace;
NixieStack::NixieStack(): mac(0),
ip(0),
arp(mac, ip),
rx_buffer(),
tx_buffer()
NixieStack stack(eth);
NixieStack::NixieStack(ENC28J60& eth): eth(eth),
mac(0),
ip(0),
link_is_up(false),
arp(mac, ip),
rx_buffer(),
tx_buffer()
{
}
......@@ -26,3 +35,82 @@ void NixieStack::set_IP(const uint8_t (&ip)[4])
{
this->ip.set(ip);
}
void NixieStack::check_link()
{
if (eth.flag_link_changed)
{
if (eth.check_link())
{
link_is_up = true;
debug.info("Link up");
}
else
{
link_is_up = false;
debug.info("Link down");
}
eth.flag_link_changed = false;
}
}
void NixieStack::rx_handler()
{
}
void NixieStack::tx_handler()
{
if (eth.flag_tx_done)
{
//TX was done, check if it was successful
if (eth.waiting_for_tx_end)
{
//TODO: check for abort cause and retransmit packet
if (eth.tx_was_successuful())
{
debug.info("TX was successful");
}
else debug.error("TX was not successful");
eth.waiting_for_tx_end = false;
}
//There is pending packet for transmission
if (tx_buffer.check() && link_is_up && !eth.waiting_for_tx_end)
{
if (!eth.tx_frame(tx_buffer.read()))
{
//TODO: Add some reaction if tx wasn't successful
}
tx_buffer.read_advance();
eth.flag_tx_done = false;
eth.waiting_for_tx_end = true;
}
}
}
void NixieStack::test_tx()
{
ethernet_frame* frame = tx_buffer.write();
const uint8_t dst[6] = {0x00, 0x30, 0x4F, 0x08, 0x35, 0x9C};
const uint8_t src[6] = {0x54, 0x10, 0xEC, 0x20, 0xE5, 0xBD};
const uint8_t data[0x10] = {0x45, 0x00, 0x00, 0x28, 0x7b, 0x6c, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0x0A, 0x14, 0x46, 0x25};
memcpy(frame->dest_address, dst, sizeof(frame->dest_address));
memcpy(frame->src_address, src, sizeof(frame->src_address));
frame->type_length = __htons(IPV4);
memcpy(frame->payload.data, data, sizeof(data));
frame->payload.length = sizeof(data);
tx_buffer.write_advance();
}
......@@ -3,30 +3,46 @@
#include <cstdint>
#include <machine/endian.h>
#include "fifo.h"
#include "CircularBuffer.h"
#include "ethernet_frame.h"
#include "NetworkTypes.h"
#include "ARP.h"
#include "ENC28J60.h"
using namespace ENC28J60_namespace;
class NixieStack
{
private:
ENC28J60& eth;
MAC mac;
IP ip;
bool link_is_up;
ARP_protocol arp;
public:
fifo<ethernet_frame, 5> rx_buffer;
fifo<ethernet_frame, 2> tx_buffer;
CircularBuffer<ethernet_frame, 5> rx_buffer;
CircularBuffer<ethernet_frame, 2> tx_buffer;
public:
NixieStack();
NixieStack(ENC28J60& eth);
void set_MAC(const uint8_t (&mac)[6]);
void set_IP(const uint8_t (&ip)[4]);
void check_link();
void rx_handler();
void tx_handler();
//For testing
void test_tx();
};
extern NixieStack stack;
......@@ -79,19 +79,19 @@ int main(void)
nixie.get_mac();
stack.test_tx();
time_t old = 0;
//eth.tx_frame_blocking(packet);
while (true)
{
nixie.display_handler();
nixie.separator.pulsing_handler();
eth.get_interrupt_source();
eth.rx_handler(stack.rx_buffer.read());
eth.tx_handler(stack.tx_buffer.read());
stack.check_link();
stack.rx_handler();
stack.tx_handler();
if (adc.done)
{
......@@ -119,17 +119,7 @@ int main(void)
}
}
if (eth.flag_link_changed)
{
if (eth.check_link())
{
debug.info("Link up");
}
else debug.info("Link down");
eth.flag_link_changed = false;
}
/*
if (clock() > old)
......
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