Я отслеживаю основную причину задержки деактивации выбора микросхемы после передачи по шине Spi Bus в ядре Linux.
Я использую freescale imx6ull, работающий на частоте 400 МГц, в настоящее время актуальный наветка ядра 4.14.2-imx здесь:
https://github.com/Freescale/linux-fslc/tree/4.14-2.0.x-imx
То, что мы наблюдаем сейчас:
- Задержка между включением выбора микросхемы (опускание вниз)и начало передачи менее 10 мкс
- SPI передача занимает от 5 до 6 мс
- Задержка между отключением выбора микросхемы (подтягиванием) варьируется в пределах 10 мс и 7 мс
Я добавил следующие блоки кода для отслеживания обратного вызова dma для уменьшения задержки в drivers / spi / spi-imx.c
static void spi_imx_dma_tx_callback(void *cookie)
{
struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie;
struct timespec now;
complete(&spi_imx->dma_tx_completion);
getnstimeofday(&now);
if(now.tv_sec == spi_imx->transfer_start_time.tv_sec)
{
int delta_ns;
// Calculate some callback stats
delta_ns = now.tv_nsec - spi_imx->transfer_start_time.tv_nsec;
if(delta_ns > 7000000) {
spi_imx->transfer_nb_cnt++;
printk(KERN_ALERT "%s %d - dma_tx_callback took :%i, cnt: %i \n", __FUNCTION__,__LINE__, delta_ns, spi_imx->transfer_nb_cnt);
}
if(delta_ns > spi_imx->max_completion_time_ns) {
spi_imx->max_completion_time_ns = delta_ns;
printk(KERN_ALERT "%s %d - delta_ns greater max_completion_time: %i \n", __FUNCTION__,__LINE__, spi_imx->max_completion_time_ns);
}
}
}
Я вижу здесь, в обратном вызове, что время передачи является постоянным, поэтомузадержка, кажется, происходит после обратного вызова.Однако все, что есть после обратного вызова, - это цепочка вызовов wait_for_completion, таких как:
timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
transfer_timeout);
Я добавил подобные блоки кода вокруг wait_for_completion_call, чтобы посмотреть, сколько времени они потребляют, увидеть следующие трассировки:
spi_imx_dma_tx_callback 1288 - delta_ns больший max_completion_time: 5285666 spi_imx_dma_transfer 1401 - wait_for_completion_tx потребовалось: 12413333
Подводя итоги, между 235 начала и начала обратного вызова: между суммой возврата к началу и окончанием пересылки было получено 525666.Между началом передачи и моментом пробуждения первого wait_for_completion после обратного вызова потребовалось 12413333 наносекунды.Разница в 7мс, что, конечно, мешает следующей передаче.
Я посылаю 100 шин в секунду, и эти пики задержки происходят в среднем один раз каждые 10 секунд.Среднее использование процессора составляет около 10%.
Что может быть основной причиной этого?