#kernel #driver #wait #interrupt #uart
#ядро #драйвер #подождите #прерывание #uart
Вопрос:
Я программирую драйвер для устройства последовательной связи, которое работает следующим образом:
1 — Я вызываю функцию чтения из пользовательского пространства.
2 — Система переходит в режим ожидания, пока в FIFO не появится первый символ.
3 — Появляется символ, и система его считывает.
4 — Теперь система должна ждать (в состоянии ожидания без занятости), пока не появится следующий символ, таким образом, используется очередь ожидания.
5 — При поступлении символа аппаратное обеспечение вызывает прерывание. Затем обработчик этого прерывания запускает процесс чтения, который продолжается.
Изначально у меня была следующая схема для кода:
read_function(int number) {
busy_wait(!fifo_empty)
for(i = 0, i < number) {
char_read = global_buffer;
wait_event_interruptible(queue,!fifo_empty);
}
irq_handler() {
wake_up(queue);
global_buffer = read_fifo();
return IRQ_HANDLED;
}
Однако у этого была следующая проблема: после того, как я прочитал fifo в обработчике, условие «fifo_empty» становится истинным. Это означает, что, хотя я разбудил процесс в тот момент, когда он был ложным, перед тем, как я выйду из обработчика, условие вернется к true, и тогда процесс чтения не будет продолжен.
Затем я решил удалить буфер и поместить вызов read_fifo() в функцию чтения. Однако это вызывает некоторые проблемы, а именно:
а) Флаг, вызывающий прерывание, не опускается до того, как я выполню read_fifo. Я вижу, что прерывание вызывается много раз в сообщениях ядра, и то, как функция ведет себя с точки зрения того, что идет первым, довольно случайно.
б) Если символ поступает, когда функция чтения не была вызвана, ядро завершает работу, потому что прерывание входит в цикл.
c) По какой-то причине, даже после ввода number
символов, система не выйдет из цикла.
Затем я хотел бы знать, должен ли я помещать вызов fifo_read в обработчик или read. Я твердо верю (основываясь на других ответах на этом сайте), что его следует поместить в обработчик. Но тогда как я могу разбудить процесс? Очевидно, что использование некоторых глобальных переменных помогло бы, но мне интересно, есть ли лучший способ сделать это.
Комментарии:
1. Обычно следует вызывать wake_up только после внесения изменений, которые могут повлиять на условие. Похоже, что ваш код делает прямо противоположное тому, что в обработчике. Это может быть причиной предполагаемого случайного поведения.
2. @embedded_dev проблема случайных событий была, как объяснялось, не в случае псевдокода.