Тоже были проблемы с отправкой UDP на W5100.
Смотри во вложении, "W3100A errata sheet v1.0"
На 5100 та же фигня оказалась...
Помогло использование функции отправки датаграммы на известный MAC адрес.
А при ошибке отправки датаграммы - переоткрытие сокета.
Но на практике получилось, что если отправлять по MAC адресу датаграммы, то сокет часто переоткрывать не приходится.
То есть такой принцип:
Своя ARP таблица.
При первой успешной отправке датаграммы добавляем MAC получателя в ARP таблицу, и в следующий раз используется функция отправки на известный MAC адрес.
if( arp_GetMac( p_dest_ip, dest_mac ) )
{
// отправка по MAC адресу (без ARP запроса)
u16 send_res = sendto_mac( wzn_id, sock_id, p_msg_data + p_msg_header->bytes_sent, bytes_to_send, p_dest_ip, p_msg_header->dest_port, dest_mac );
if( send_res == 0 )
{
// ошибка отправки датаграммы!
// переоткрываем сокет
close( wzn_id, sock_id );
socket( wzn_id, sock_id, Sn_MR_UDP, g_socket[ii].src_port, 0 );
}
else
{
// отправка с определением MAC адреса, в случае успеха обновляем ARP таблицу
if( sendto( wzn_id, sock_id, p_msg_data + p_msg_header->bytes_sent, bytes_to_send, p_dest_ip, p_msg_header->dest_port ) == bytes_to_send )
{
get_dst_mac( wzn_id, sock_id, dest_mac );
arp_Update( p_dest_ip, dest_mac );
}
else
{
// ошибка отправки датаграммы!
// переоткрываем сокет
close( wzn_id, sock_id );
socket( wzn_id, sock_id, Sn_MR_UDP, g_socket[ii].src_port, 0 );
}
}
ну и функция определения MAC адреса получателя (при успешной отправке датаграммы)
void get_dst_mac( u8 WZN_CS, SOCKET s, u8* mac )
{
mac[0] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 0));
mac[1] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 1));
mac[2] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 2));
mac[3] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 3));
mac[4] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 4));
mac[5] = IINCHIP_READ(WZN_CS, (Sn_DHAR0(s) + 5));
}
А вообще, если данные не часто отправляешь, я бы посоветовал перед каждой отправкой переоткрывать сокет. И всё будет гуд :-)
W3100A_20Errata_20Sheet_20v1.0.pdf