一部の受信データが欠落しているという問題が発生しているカスタムLinuxシリアルドライバーをデバッグしようとしています。4つのシリアルポートに対して1つの割り込みがあり、ボーレートは115200です。最初に、割り込みハンドラーにかかる時間を測定する方法を確認したいと思います。私はperfを使用しましたが、秒単位ではなくパーセント単位です。第二に、物事をスピードアップするために改善できる以下のコードの問題を誰かが見ていますか?
void serial_interrupt(int irq, void *dev_id)
{
...
// Need to loop through each port to see which port caused the interrupt.
list_for_each(lpNode, &serial_ports)
{
struct serial_port_module *ser_dev = list_entry(lpNode, struct serial_port_module, port_list);
lnIsr = ioread8(ser_dev->membase + ser_dev->chan_num * PORT_OFFSET + SERIAL_ISR);
if (lnIsr & IPM512_RX_INT)
{
while (serialdata_is_data_available(ser_dev)) // equals a ioread8()
{
lcIn = ioread8(ser_dev->membase + ser_dev->chan_num * PORT_OFFSET + SERIAL_RBR);
kfifo_in(&ser_dev->rx_fifo, &lcIn, sizeof(lcIn));
// Notify if anyone is doing a blocking read.
wake_up_interruptible(&ser_dev->read_queue);
}
}
}
}
ftrace APIを使用して、レイテンシの問題を追跡してみてください。知る時間はもうありません:https://www.kernel.org/doc/Documentation/trace/ftrace.txt
これが重すぎる場合は、簡単なインストルメンテーションを自分で追加するのはどうですか?getnstimeofday(struct timespec *ts)
は比較的軽量です... sysfsデバッグファイルに出力できるコードが少ないと、最悪の場合の実行時間、この関数の呼び出しの待ち時間に関するいくつかの統計、割り込みごとに使用可能な最悪の場合のバイト数...この数がハードウェアFIFOサイズの近くで、問題が発生しています。
最適化の1つは、データが利用可能である限り、データをバッチでバッファーに読み取り、バッファー全体を入力してから、リーダーをウェイクアップすることです。
while(data_available(dev))
{
buf[cnt++] = ioread8();
}
kfifo_in(fifo, buf, cnt);
wake_up_interruptible();
しかし、この単純なコードの実行時間は問題になる可能性は低いです。おそらく、割り込みの見逃しや、割り込み処理の予期しない遅延に悩まされています。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加