Доброго всем дня!
Столкнулся на уже действующем устройстве со следующей проблемой. Помимо возможности печати на внешнем USB-принтере встроил поддержку печати через JetDirect (порт 9100) на сетевом принтере, но проверить мог только на одном имеющемся в наличии, все работало. Сейчас заказали еще несколько принтеров, два из них работают так же хорошо, а один (Canon LBP6670dn) - не печатает. Начал изучать протокол коммуникации с ним при помощи Wireshark, выяснил, что никаких очевидных проблем нет:
Код
No. Time Source Destination Protocol Length Info
212 2015-10-07 08:25:32.945645000 192.168.120.130 192.168.120.20 TCP 60 12850→9100 [SYN] Seq=0 Win=4380 Len=0 MSS=1460
213 2015-10-07 08:25:32.945808000 192.168.120.20 192.168.120.130 TCP 60 9100→12850 [SYN, ACK] Seq=0 Ack=1 Win=384 Len=0 MSS=1460
214 2015-10-07 08:25:32.945838000 192.168.120.130 192.168.120.20 TCP 60 12850→9100 [ACK] Seq=1 Ack=1 Win=4380 Len=0
215 2015-10-07 08:25:32.956622000 192.168.120.130 192.168.120.20 TCP 63 12850→9100 [PSH, ACK] Seq=1 Ack=1 Win=4380 Len=9
216 2015-10-07 08:25:32.956792000 192.168.120.20 192.168.120.130 TCP 60 9100→12850 [ACK] Seq=1 Ack=10 Win=384 Len=0
--- таймаут 5 секунд, закрытие соединения ---
325 2015-10-07 08:25:37.726133000 192.168.120.130 192.168.120.20 TCP 60 12850→9100 [FIN, ACK] Seq=10 Ack=1 Win=4380 Len=0
326 2015-10-07 08:25:37.726449000 192.168.120.20 192.168.120.130 TCP 60 9100→12850 [FIN, ACK] Seq=1 Ack=11 Win=384 Len=0
327 2015-10-07 08:25:37.726496000 192.168.120.130 192.168.120.20 TCP 60 12850→9100 [ACK] Seq=11 Ack=2 Win=4380 Len=0
Но, судя по всему, устройство (LPC4088 с Keil RTX и стеком RL-TCPnet) не получает от принтера ACK в ответ на первый же пакет с данными (9 байт), хотя Wireshark показывает, что ACK был. Начал копаться в коде, ничего предосудительного не нашел, анализ драйвера Ethernet для LPC4088 показал, что проблема может быть только на уровне несрабатывания прерывания, нашел об этом несколько тем в сети. Пакет с ACK обнаружил в одном из буферов при остановке процессора в нужной точке. Перевел tcp-задачу в активацию по установке события в прерывании, а не по таймеру - стало лучше в плане отклика устройства на пинг, но не помогло с принтером. Увеличил число буферов с 4 до 6 - не помогло. Убрал из прерывания передачу данных для скорости, обработчика все равно не было - не помогло. Убрал прерывание вообще, заменив поллингом - стало все значительно медленнее, но не помогло. Очевидно, что пакет теряется где-то в самом стеке, но отладить его невозможно по причине закрытости. Причем в режиме длительного пинга устройство ведет себя хорошо, пакеты не теряются, максимальное время ответа - 2 мс, среднее - менее 1 мс.
Вот так выглядит обработчик прерывания:
Код
void ENET_IRQHandler (void)
{
// EMAC Ethernet Controller Interrupt function
OS_FRAME *frame;
U32 idx,int_stat,RxLen,info;
U32 *sp,*dp;
while ((int_stat = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable)) != 0) {
LPC_EMAC->IntClear = int_stat;
if (int_stat & INT_RX_DONE) {
// Packet received, check if packet is valid
idx = LPC_EMAC->RxConsumeIndex;
while (idx != LPC_EMAC->RxProduceIndex) {
info = Rx_Stat[idx].Info;
if (!(info & RINFO_LAST_FLAG)) {
goto rel;
}
RxLen = (info & RINFO_SIZE) - 3;
if (RxLen > ETH_MTU || (info & RINFO_ERR_MASK)) {
// Invalid frame, ignore it and free buffer
goto rel;
}
// Flag 0x80000000 to skip sys_error() call when out of memory
frame = alloc_mem (RxLen | 0x80000000);
// if 'alloc_mem()' has failed, ignore this packet
if (frame != NULL) {
dp = (U32 *)&frame->data[0];
sp = (U32 *)Rx_Desc[idx].Packet;
for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--) {
*dp++ = *sp++;
}
put_in_queue (frame);
isr_evt_set(0x0001, t_tcp);
}
rel: if (++idx == NUM_RX_FRAG) idx = 0;
// Release frame from EMAC buffer
LPC_EMAC->RxConsumeIndex = idx;
}
}
/*if (int_stat & INT_TX_DONE) {
// Frame transmit completed
}*/
}
}
Вот так выглядит печать на "нормальном" принтере:
Код
No. Time Source Destination Protocol Length Info
85 2015-10-07 08:09:39.427163000 192.168.120.130 192.168.120.86 TCP 60 12850→9100 [SYN] Seq=0 Win=4380 Len=0 MSS=1460
86 2015-10-07 08:09:39.429157000 192.168.120.86 192.168.120.130 TCP 60 9100→12850 [SYN, ACK] Seq=0 Ack=1 Win=4096 Len=0 MSS=1460
87 2015-10-07 08:09:39.429158000 192.168.120.130 192.168.120.86 TCP 60 12850→9100 [ACK] Seq=1 Ack=1 Win=4380 Len=0
89 2015-10-07 08:09:39.485000000 192.168.120.130 192.168.120.86 TCP 63 12850→9100 [PSH, ACK] Seq=1 Ack=1 Win=4380 Len=9
90 2015-10-07 08:09:39.485272000 192.168.120.86 192.168.120.130 TCP 60 9100→12850 [ACK] Seq=1 Ack=10 Win=16375 Len=0
--- продолжение печати ---
91 2015-10-07 08:09:39.700049000 192.168.120.130 192.168.120.86 TCP 150 12850→9100 [PSH, ACK] Seq=10 Ack=1 Win=4380 Len=96
92 2015-10-07 08:09:39.700325000 192.168.120.86 192.168.120.130 TCP 60 9100→12850 [ACK] Seq=1 Ack=106 Win=16288 Len=0
...
--- завершение печати ---
308 2015-10-07 08:09:44.942531000 192.168.120.130 192.168.120.86 TCP 60 12850→9100 [FIN, ACK] Seq=2012 Ack=1 Win=4380 Len=0
311 2015-10-07 08:09:44.944040000 192.168.120.86 192.168.120.130 TCP 60 9100→12850 [FIN, ACK] Seq=1 Ack=2013 Win=16384 Len=0
312 2015-10-07 08:09:44.944070000 192.168.120.130 192.168.120.86 TCP 60 12850→9100 [ACK] Seq=2013 Ack=2 Win=4380 Len=0
Есть ли у кого-то подобный опыт? Буду рад предположениям, потому что за неделю уже голову себе сломал, стало навязчивой идеей, есть страх, что не только этот Canon может себя так вести. Удивительно еще то, что более старое устройство на другой базе и с uIP в качестве стека на данном принтере печатает.
Только не предлагайте перейти на FreeRTOS, я уже пробовал это осуществить, но примеры lwIP под LPC4088 работают отвратительно, я так и не смог понять, сколько памяти там нужно, а сама FreeRTOS категорически на захотела запускаться в мультизадачном режиме с emWin, уже встроенной в проект, только в однозадачном, а меня это не устраивает, причем ничего изменить тут тоже не могу, потому что emWin прекомпилирована.