В настоящее время я пишу код для беспроводного клиента на аппаратном уровне (в сборке 8051), в котором данные передаются обратно на сервер, только когда данные отправляются клиенту с того же сервера. Радиомодули, подключенные к клиенту и серверу, работают только в полудуплексном режиме.
Проблема в том, что я пытаюсь сделать данные атомарными.
В моем коде у меня есть таймер, который срабатывает на регулярной основе (чтобы помочь обнаружить тайм-ауты последовательных данных). У меня также есть последовательное прерывание, которое имеет приоритет над таймером, поэтому при поступлении символа последовательное прерывание добавляет новый символ. в приемный буфер и вызывает таймер для запуска сразу после.
Когда приемный буфер заполнен, входящая строка считывается, и данные из локального передающего буфера копируются в буфер передачи, и оттуда она сразу же отправляется по одному байту за раз. Все это делается в пределах прерывания по таймеру.
Теперь вот часть, которая меня беспокоит.
У меня есть функция магистрали (вне прерывания таймера и последовательного прерывания), которая устанавливает различные значения в локальном буфере передачи.
Проблема в том, что частично через функцию вызывается прерывание, которое может копировать неверные данные. Я постараюсь объяснить в упрощенном коде:
Вот серийное прерывание. Если данные получены, они помещаются в приемный буфер. Аналогично, если данные передаются, они загружаются из буфера передачи:
Serial_interrupt:
If byte is transmitted then
If transmit buffer pointer is at end then
Set transmit complete flag and end
else
Read next byte in buffer
End If
If byte is received then
Set byte received flag
Set Timer Overflow flag
If received buffer pointer is at end then
Set receive complete flag and end
else
set value in buffer to byte and advance pointer
End If
end_interrupt
Timer_interrupt:
If byte received flag is set then
clear byte received flag
else
reset receive pointer (void old data)
end if
If receive complete flag is set then
clear receive complete flag
copy data from userspace buffer to data transmit buffer **
end if
end_timer_interrupt
Mainline:
Set a value of a byte in userspace buffer **
Set a value of a byte in userspace buffer **
Set a value of a byte in userspace buffer **
Do some other irrelevant action
restart_mainline
Я надеюсь, что мой псевдокод облегчит мой вопрос. Меня интересуют предложения со звездами, потому что в основной процедуре я хочу установить три байта одновременно и отправить их все.
Вероятно, что до того, как данные пользовательского пространства будут скопированы в локальный буфер передачи из-за временной привязки, будет правильно установлено менее трех байтов, и, следовательно, будут переданы неправильные данные.
Например, вполне вероятно, что это произойдет, чего я не хочу:
Mainline:
Set a value of a byte in userspace buffer **
Set a value of a byte in userspace buffer **
--system detects byte and calls serial_interrupt function
--timer function executes and userspace data is copied to transmit buffer
Set a value of a byte in userspace buffer ****
Do some other irrelevant action
restart_mainline
в точке, где вы видите 4 звезды, первые два байта были успешно отправлены в первом пакете по сети, но третий байт не был обработан вовремя, поэтому он был отправлен в следующем пакете.
Есть ли способ, которым я могу настроить полный большой объем данных во времени, не отправляя какую-либо их часть из-за времени?
Пока что единственное, о чем я могу думать, это отключить прерывания во время установки значений и включить их снова после (я думаю, они называют этот критический раздел?), Но могу ли я что-нибудь еще сделать, чтобы решить эту проблему?
Аппаратное обеспечение, которое я использую, - AT89S52 с кристаллом 22.1184 МГц. Для выполнения каждой инструкции требуется не более 1 мкс, а размер фрагмента данных, который я заинтересован в отправке со скоростью 56 Кбит / с, составляет 10 байт.