I can confirm the problem, as I had the same. The crash basically is a null pointer exception happening when the user application does not pick up the received packets. The intermediate MII task does pick up all the packets, but keeps the first packet in the buffer (because it's not yet delivered to the user application). Therefore this particular slot in the ringbuffer keeps occupied, which then leads to several problems.
Code: Select all
diff --git a/src/trunk/lib_ethernet/src/mii_ethernet_mac.xc b/src/trunk/lib_ethernet/src/mii_ethernet_mac.xc
index d5b06ff..60750d1 100644
--- a/src/trunk/lib_ethernet/src/mii_ethernet_mac.xc
+++ b/src/trunk/lib_ethernet/src/mii_ethernet_mac.xc
@@ -126,6 +126,9 @@ static void mii_ethernet_aux(client mii_if i_mii,
case i_rx[int i].get_packet(ethernet_packet_info_t &desc,
char data[n],
unsigned n):
+
+// debug_printf("i_rx[].get_packet(): incoming_data = %x\n", incoming_data);
+
if (client_state[i].status_update_state == STATUS_UPDATE_PENDING) {
data[0] = link_status;
data[1] = link_speed;
@@ -272,7 +275,7 @@ static void mii_ethernet_aux(client mii_if i_mii,
update_client_state(client_state, i_rx, n_rx);
}
break;
- case mii_incoming_packet(mii_info):
+ case incoming_data == NULL => mii_incoming_packet(mii_info):
int * unsafe data;
int nbytes;
unsigned timestamp;
@@ -280,6 +283,7 @@ static void mii_ethernet_aux(client mii_if i_mii,
if (incoming_data) {
// Can only handle one packet at a time at this level
+// debug_printf("mii_incoming_packet: incoming_data != 0 (= %x) -> release packet\n", incoming_data);
i_mii.release_packet(data);
break;
}
@@ -315,6 +319,7 @@ static void mii_ethernet_aux(client mii_if i_mii,
}
}
if (incoming_tcount == 0) {
+// debug_printf("mii_incoming_packet: incoming_tcount = 0 -> release packet\n", incoming_data);
i_mii.release_packet(incoming_data);
incoming_data = null;
}
diff --git a/src/trunk/lib_ethernet/src/mii_lite_driver.xc b/src/trunk/lib_ethernet/src/mii_lite_driver.xc
index 284ee19..0df759f 100644
--- a/src/trunk/lib_ethernet/src/mii_lite_driver.xc
+++ b/src/trunk/lib_ethernet/src/mii_lite_driver.xc
@@ -8,6 +8,9 @@
#include "print.h"
#include "mii_buffering.h"
+#define DEBUG_UNIT LIB_ETHERNET
+#include "debug_print.h"
+
// TODO: implement mii_driver straight in mii_lld.
void mii_lite_driver(in buffered port:32 p_rxd,
in port p_rxdv,
@@ -142,6 +145,8 @@ static int get(int addr) {
void mii_lite_buffer_init(struct mii_lite_data_t &this,
chanend c_in, chanend c_notifications,
chanend c_out, int buffer[], int number_words) {
+// debug_printf("mii_lite_buffer_init()\n");
+
int address;
this.notify_seen = 1;
this.notify_last = 1;
@@ -174,6 +179,10 @@ void mii_notify(struct mii_lite_data_t &this, chanend c_notifications) {
this.notify_last = !this.notify_last;
outuchar(c_notifications, this.notify_last);
}
+// else
+// {
+// debug_printf("mii_notify: notify_last != notify_seen -> Skipping notification!\n");
+// }
}
select mii_notified(struct mii_lite_data_t &this, chanend c_notifications) {
@@ -185,6 +194,9 @@ case inuchar_byref(c_notifications, this.notify_seen):
{char * unsafe, unsigned, unsigned} mii_lite_get_in_buffer(struct mii_lite_data_t &this,
chanend c_notifications) {
unsafe {
+
+// debug_printf("mii_lite_get_in_buffer(): read_bank_rd_ptr = %d, read_bank_wr_ptr = %d\n", this.read_bank_rd_ptr, this.read_bank_wr_ptr);
+
if (this.read_bank_rd_ptr != this.read_bank_wr_ptr) {
unsigned bank = (this.read_bank >> this.read_bank_rd_ptr) & 0x1;
unsigned n_bytes = get(this.read_ptr[bank]);
@@ -205,7 +217,10 @@ case inuchar_byref(c_notifications, this.notify_seen):
}
if (this.read_bank_rd_ptr != this.read_bank_wr_ptr)
+ {
+// debug_printf("mii_lite_get_in_buffer(): rd_ptr != wr_ptr -> More packets -> Sending another notification.\n");
mii_notify(this, c_notifications);
+ }
unsigned time_stamp = get(ret_val);
@@ -214,6 +229,7 @@ case inuchar_byref(c_notifications, this.notify_seen):
}
}
+// debug_printf("mii_lite_get_in_buffer(): Returning NULL\n");
return {(char * unsafe) 0, 0, 0};
}
}
@@ -221,6 +237,8 @@ case inuchar_byref(c_notifications, this.notify_seen):
#pragma unsafe arrays
static void mii_commit_buffer(struct mii_lite_data_t &this, unsigned int current_buffer,
unsigned int length, chanend c_notifications) {
+// debug_printf("mii_commit_buffer(%x) [bank = %d]\n", current_buffer, (int)(current_buffer < this.first_ptr[1] ? 0 : 1));
+// debug_printf(" read_bank_rd_ptr = %d, read_bank_wr_ptr = %d\n", this.read_bank_rd_ptr, this.read_bank_wr_ptr);
int bn = current_buffer < this.first_ptr[1] ? 0 : 1;
set(this.wr_ptr[bn]-4, length); // record length of current packet.
this.wr_ptr[bn] = this.wr_ptr[bn] + ((length+3)&~3) + 4; // new end pointer.
@@ -309,10 +327,33 @@ void mii_lite_restart_buffer(struct mii_lite_data_t &this) {
this.next_buffer = this.wr_ptr[bn]; // if so, record packet pointer
}
}
+
+ if(this.next_buffer != -1)
+ {
+ // Log which bank this packet was written to
+ unsigned new_read_bank_wr_ptr = increment_and_wrap_power_of_2(this.read_bank_wr_ptr, 32);
+
+ // If the pointers have overflowed the 32 slots then
+ // drop the packet.
+ if (this.read_bank_rd_ptr == new_read_bank_wr_ptr) {
+ this.next_buffer = -1;
+ this.refill_bank_number = bn;
+ return;
+ }
+
+ this.read_bank &= ~(1 << this.read_bank_wr_ptr);
+ this.read_bank |= bn << this.read_bank_wr_ptr;
+ this.read_bank_wr_ptr = new_read_bank_wr_ptr;
+ }
}
#pragma unsafe arrays
void mii_lite_free_in_buffer(struct mii_lite_data_t &this, char * unsafe base0) {
+// debug_printf("mii_lite_free_in_buffer(%x) [bank = %d]\n", base0, base0 < this.first_ptr[1] ? 0 : 1);
+// debug_printf(" Bank 0: %x - %x|%x\n", this.first_ptr[0], this.last_safe_ptr[0], this.first_ptr[1] - 4);
+// debug_printf(" Bank 1: %x - %x|%x\n", this.first_ptr[1], this.last_safe_ptr[1], this.last_safe_ptr[1] + MAXPACKET/4 - 4);
+ if(base0)
+ {
unsafe {
int base = (int) base0;
int bank_number = base < this.first_ptr[1] ? 0 : 1;
@@ -320,7 +361,9 @@ void mii_lite_free_in_buffer(struct mii_lite_data_t &this, char * unsafe base0)
base -= 4;
set(base-4, -get(base-4));
while (1) {
+// debug_printf(" free_ptr = %x\n", this.free_ptr[bank_number]);
int l = get(this.free_ptr[bank_number]);
+// debug_printf(" l = %d\n", l);
if (l > 0) {
break;
}
@@ -333,6 +376,8 @@ void mii_lite_free_in_buffer(struct mii_lite_data_t &this, char * unsafe base0)
}
// Note - wrptr may have been stuck
}
+ }
+
mii_lite_restart_buffer(this);
}