The reason for this is on the rgmii_10_100_master_tx_pins task:
Code: Select all
int word_count = byte_count >> 2;
tail_byte_count = byte_count & 3;
// Ensure that the interframe gap is respected
tmr when timerafter(ifg_time) :> ifg_time;
// Send the preamble
{tmp1, tmp2} = zip2(0x55555555, 0x55555555);
If there is a idle time between buffers for more than 21 seconds, the timerafter(ifg_time) adds another (up to 21 seconds) delay before handling the buffer!
tmr is a 2^32 bit 100MHz counter but timerafter() can only handle delays up to 2^31 ticks. Longer delays are handelt after a "rollover" after 42 seconds.
As a work around, I restricted the max idle time to 20 seconds with this hack:
Code: Select all
unsafe void rgmii_10_100_master_tx_pins(streaming chanend c,
out buffered port:32 p_txd,
streaming chanend c_speed_change)
{
unsigned tmp1, tmp2;
timer tmr;
unsigned ifg_time;
unsigned TimerWorkaround;
tmr :> ifg_time;
while (1)
{
uintptr_t buffer;
unsigned timestamp;
TimerWorkaround = 0;
select
{
case c_speed_change :> buffer:
return;
case c :> buffer:
break;
case tmr when timerafter(ifg_time + 2000000000) :> ifg_time:
TimerWorkaround = 1;
break;
}
unsigned int eof_time;
int tail_byte_count;
mii_packet_t * unsafe buf = (mii_packet_t * unsafe)buffer;
if (TimerWorkaround == 0)
{
unsafe {
register const unsigned poly = 0xEDB88320;
// Pre-load CRC with value making equivalent of doing crc of ~first_word
....
...
Best regards
Armin