Author |
Message |
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Как правильно реализовать mutex или хотя бы spinlock на ассемблере avr? Не нагуглил ничего подходящего. Типовая реализация spinlock требует команды типа xchg, которой тут нет. Задача - взаимодействия кода из прерываний и "основного цикла" через общую память (флаги, счётчики). Хочется счётчик 16 бит, устанавливаемый флаг и возможно буфер. Прерывания запрещать нельзя
|
19 Jun 2023 18:54 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22702 Location: Silicon Valley
|
А зачем мьютексы то? Мультитредности то нету Есть обработчик прерывания и основная программа - они обе могут использовать одни и те же переменные Всё просто
|
20 Jun 2023 00:22 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Нормальной может и нету, но параллельные "потоки" выполнения вполне есть.
Пример: основной цикл дрючит какой-то медленный процесс, например читает UART, прерывания быстро выводят данные куда-то наружу, пусть на VGA :trollface:
Взаимодействие этих "потоков" на примере счётчика - пусть он увеличивается при чтении с UART и иногда уменьшается при выводе.
1. цикл - читает в регистр значения ячейки счётчика (дальше хочет сравнивать) 2. тут "врывается" прерывание, меняет значение счётчика, оканчивается 3. цикл продолжает работу с уже неверным значением.
Логично, что прерыванию хорошо бы "знать" что тут счётчик занят и не трогать его, нужен какой-то флаг, который атомарен и с ним самим не случиться той же неприятности, что случилась с ячейкой счётчика.
|
20 Jun 2023 01:00 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22702 Location: Silicon Valley
|
Ну UART это не такая уж медленная штука, если нормальные скорости делать... Есть же команды запрещения-разрешения прерываний - надо тебе из основной программки поюзать общий счётчик - запрещаешь прерывания и юзаешь А обработчик прерывания может трогать счётчик когда захочет т.к. он сам отдаёт управление, когда всё сделал И никаких мьютексов
|
20 Jun 2023 01:18 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Тут вопрос не про медленная или нет, важно, что прерывания посреди него не мешают. Прерывания запрещать нельзя по условиям задачи (в случае вывода на VGA на экране будут помехи).
Костыльно можно сделать так:
1. цикл устанавливает флажок (хоть в памяти, хоть в регистре) 2. цикл обрабатывает конфликтный ресурс 3. цикл сбрасывает флажок 4. цикл делает все остальные дела
А прерывание никогда не меняет флажок, но может проверить, что он установлен и в этот раз не трогать конфликтный ресурс (так как он точно не освободится до завершения прерывания и передачи управления основному циклу), иначе с конфликтным ресурсом можно делать всё, что угодно.
---
Вопрос - можно ли как-то реализовать не так костыльно и более общим случаем?
|
20 Jun 2023 01:31 |
|
|
Mixa64
Doomed
Joined: 25 Aug 2009 07:02 Posts: 461 Location: Москва
|
"Костыль" ПМСМ начинается уже тут , а не тут : , которое, вообще-то, уже не костыль сам по себе, а вполне разумный подход в сложившихся обстоятельствах. Более общий случай - это как раз что-то типа enterCritical() и exitCritical() , внутри этих скобок обрамление из запрета и разрешения прерываний. То есть, вы, вероятно, считаете костылем то, что при таком вынужденном подходе прерывание будет иногда отрабатываться вхолостую, если случается, что ресурс трогать нельзя. Согласен, это нужно учитывать и принимать не всегда изящные меры. Заперт прерывания как раз для таких случаев, запрос никогда не отрабатывается вхолостую (и нету каких-то ветвлений в зависимости от чего-то), просто обработка может быть чуть задержана, если попали на момент апдейта атомарного. А так, DMA еще бывает, если что.
|
20 Jun 2023 03:58 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Во многих архитектурах можно без прерывания, может и у AVR можно (но я не знаю как)? Скорее из сохранения состояния прерываний и восстановления - кто сказал, что они запрещены? Да, там кроме прерываний ещё и сам макрос быть должен какой-то. Не, тем, что этот подход только для данного примера пригоден. А вот если вообразить какой-нибудь "диспетчер", получающий управление по прерыванию от одного кода, а возвращающий в другой (примитивная такая многозадачность), то так уже не выйдет, там при попытке получить семафор управление должно передаваться другим "потокам" до освобождения. Xmega?
|
20 Jun 2023 08:39 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
|
20 Jun 2023 08:51 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Хотя по аналогии с реализацией spinlock на обмене регистра с памятью можно сделать на инкременте / декременте регистра (регистр будет занят всегда, увы): (псевдокод для варианта - попытаться или обломаться без ожидания; в регистре единица) if(! --reg){ do_crytical() } reg++
при попытке кучи "потоков" уменьшить регистр только один получит 0, а остальные - FF или чуть меньше, но быстро вернут назад.
|
20 Jun 2023 09:50 |
|
|
Mixa64
Doomed
Joined: 25 Aug 2009 07:02 Posts: 461 Location: Москва
|
Я всего лишь хотел сказать, что запреты и разрешения прерываний это обычная практика, а если запретить запреты прерываний, то тут уж хозяин барин.
|
21 Jun 2023 10:15 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Вопрос был и теоретический тоже - поинтересовавшись, как на разных платформах реализуют тот же spinlock (как правило без запрета прерываний), я не придумал, как сделать на AVR, потому и спросил. P.S. В моём практическом примере классический (ожидающий) семафор приведёт как раз к зависанию
|
21 Jun 2023 21:21 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22702 Location: Silicon Valley
|
Если очень хочется "запретить запреты прерываний", то надо заводить атомарный флаг доступа (семафор?) где неделимы были бы инкремент/декремент и сравнение (иначе прерывание может между ними проскочить) - в авре вроде есть косвенный доступ к регистрам с постинкрементом (или предекрементом) индексного регистра одной инструкцией - возможно это как-то удастся задействовать?...
|
22 Jun 2023 22:38 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
Про то и речь и ничего кроме физического регистра (который на 100% занят этим и только этим) в голову не пришло. Типа "LD rx, Z+"? Тут 100% не выйдет, значение памяти не меняется, если параллельно (в прерывании) другой код сделает тоже самое, друг на друга они не повлияют - ну только если не глобально запретить использовать Z для чего-то ещё другого и тогда получится ровно то же, что я писал про регистр, только чуть сложнее (потребуется кусок памяти с одной единичкой и каким-то списком нулей после).
|
24 Jun 2023 07:13 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22702 Location: Silicon Valley
|
А вообще AVR это не та платформа, на которой следует экспериментировать с многозадачностью...
|
24 Jun 2023 22:17 |
|
|
masterspammer
Fanat
Joined: 13 Dec 2020 21:11 Posts: 86
|
А вы отдаёте себе отчёт, что на этом форуме такие слова звучат как вызов? С многозадачностью, правда, хочу поиграть на Z80 (который пошустрее из новых), но чем AVR не то?
|
04 Jul 2023 06:58 |
|
|