-
- классика с нереентерабельностью функции? - jaga-jaga(03.05.2024 18:27)
- Попробуйте использовать инструкции LDREX/STREX или их обертки
__LDREX/__STREX из CMSIS. На Cortex-M4 должно проканать. Немного
творчи надо только проявить в применении к uint64_t. - LightElf(24.04.2024 17:26 - 17:33)
- Спасибо. - Nikolay_Po(03.05.2024 18:21)
- +1 - Oman(24.04.2024 22:37)
- Да, действительно любопытная тема. Поизучаю, спасибо! - ar-elec(24.04.2024 19:47)
- Ха, прикольное POV(1 знак., 24.04.2024 17:27, ссылка)
- Статья по ссылке оставила вопросы. Почитал руководство по
программированию ядра. Вот что выяснил: Nikolay_Po(937 знак., 03.05.2024 18:26)
- Оная функциональность на мелких кортексах (как и на SuperH, с
которого слизана) реализована примитивнее некуда. Там один триггер
на всю красоту, адрес вообще игнорится. LDREX взводит триггер,
STREX проверяет, взведён ли он, выполняет запись и сбрасывает
триггер. Любое прерывание триггер сбрасывает. Все. - LightElf(04.05.2024 02:19)
- Откуда информация про то, что адрес игнорируется? А если обращение
к памяти было от контроллера ПДП, без прерывания? Что, тоже адрес
игнорируется? - Nikolay_Po(04.05.2024 04:28)
- Адрес игнорируется, это описано в армовских доках на Cortex-M.
Вложенные ldrex/strex работать не будут (сработает только самая
глубокая пара). На STM32F4 отслеживания активности DMA я не
обнаружил, да и затруднительно оно в реализации, с учётом крайне
развесистого шинного хозяйства. На толстых многоядерных кортексах
может и есть что. - LightElf(12.05.2024 18:49)
- Насчёт вложений LDREX/STREX, разумеется, сработает лишь самая
глубокая пара. Остальные получат отказ (фиксацию вмешательства в
память). И это будет безопасно. В этом смысле оно "работает",
использование вложенных LDREX/STREX - не приведёт к
непредсказуемому поведению и не разрушит атомарность доступа,
предусмотренную циклом с LDREX/STREX. - Nikolay_Po(13.05.2024 10:22)
- Ну если "зациклится" == "сработает", то да ;-) - LightElf(13.05.2024 14:01)
- Когда самое глубоко вложенное сделает свои дела и перестанет
вызывать STREX, цикл у чуть менее глубокого успешно завершится. И
так до самого верхнего уровня. - Nikolay_Po(13.05.2024 15:27)
- У нас, похоже, разное понимание слова "вложенный". LightElf(314 знак., 13.05.2024 15:44 - 18:40)
- Да. Разное. Я имел ввиду вложение этой пары инструкции внутри прерывания уже исполняемой пары. Nikolay_Po(129 знак., 13.05.2024 15:49)
- Но зачем, Холмс? :-) - SciFi(13.05.2024 15:48)
- Да фиг его знает. Просто иллюстрация к термину "вложенный". - LightElf(13.05.2024 18:41)
- Предложите, как сделать обновление двух переменных, без
использования отдельного флага "занято". Там вложенность так и
просится AlexBi(264 знак., 13.05.2024 18:22)
- Никак, что логично. Сделай на две переменные - завтра попросят десять переменных атомарно обновить ;-) - LightElf(13.05.2024 21:48)
- Увы, так не заработает. Я прикидывал и не нашёл способа атомарно
обновить, при помощи этой пары инструкций, что-либо больше 32 бит.
Если у STM32F адрес не проверяется, то для обоих переменных
достаточно одной обёртки. Но это будет противоречить документации,
где явно указано, что нужно проверять сохранность эксклюзивности
доступа именно по указанному адресу и именно указанной ширины. А
это лишь один адрес с шириной данных до 32 бит. - Nikolay_Po(13.05.2024 19:54)
- Это не у STM32, это у Cortex-M3/4 вообще. LightElf(346 знак., 13.05.2024 20:46, ссылка)
- Именно. Не нужно доводить до абсурда. Жаль, иногда само получается. - Nikolay_Po(13.05.2024 15:50)
- У нас, похоже, разное понимание слова "вложенный". LightElf(314 знак., 13.05.2024 15:44 - 18:40)
- Когда самое глубоко вложенное сделает свои дела и перестанет
вызывать STREX, цикл у чуть менее глубокого успешно завершится. И
так до самого верхнего уровня. - Nikolay_Po(13.05.2024 15:27)
- Ну если "зациклится" == "сработает", то да ;-) - LightElf(13.05.2024 14:01)
- Насчёт вложений LDREX/STREX, разумеется, сработает лишь самая
глубокая пара. Остальные получат отказ (фиксацию вмешательства в
память). И это будет безопасно. В этом смысле оно "работает",
использование вложенных LDREX/STREX - не приведёт к
непредсказуемому поведению и не разрушит атомарность доступа,
предусмотренную циклом с LDREX/STREX. - Nikolay_Po(13.05.2024 10:22)
- Адрес игнорируется, это описано в армовских доках на Cortex-M.
Вложенные ldrex/strex работать не будут (сработает только самая
глубокая пара). На STM32F4 отслеживания активности DMA я не
обнаружил, да и затруднительно оно в реализации, с учётом крайне
развесистого шинного хозяйства. На толстых многоядерных кортексах
может и есть что. - LightElf(12.05.2024 18:49)
- Откуда информация про то, что адрес игнорируется? А если обращение
к памяти было от контроллера ПДП, без прерывания? Что, тоже адрес
игнорируется? - Nikolay_Po(04.05.2024 04:28)
- Оная функциональность на мелких кортексах (как и на SuperH, с
которого слизана) реализована примитивнее некуда. Там один триггер
на всю красоту, адрес вообще игнорится. LDREX взводит триггер,
STREX проверяет, взведён ли он, выполняет запись и сбрасывает
триггер. Любое прерывание триггер сбрасывает. Все. - LightElf(04.05.2024 02:19)
- Статья по ссылке оставила вопросы. Почитал руководство по
программированию ядра. Вот что выяснил: Nikolay_Po(937 знак., 03.05.2024 18:26)
- Похоже, проще всего сделать раздельные функции для фона и для
прерывания. Кстати, забавный факт (uint32_t)timer64 и cnt_old - это
одно и то же. - SciFi(24.04.2024 16:57)
- Согласен, проще. Только эстетическое чуйство страдает. Ну, может я
и зря так на этот вариант косо смотрю... Спасибо всем ответившим!
Три варианта, это прям хорошо. Дёшево/быстро/качественно. - ar-elec(24.04.2024 17:03)
- Вот финт ушами для эстетики: SciFi(167 знак., 24.04.2024 17:08)
- Спасибо - ar-elec(24.04.2024 19:52)
- Вот финт ушами для эстетики: SciFi(167 знак., 24.04.2024 17:08)
- Согласен, проще. Только эстетическое чуйство страдает. Ну, может я
и зря так на этот вариант косо смотрю... Спасибо всем ответившим!
Три варианта, это прям хорошо. Дёшево/быстро/качественно. - ar-elec(24.04.2024 17:03)
- Решения есть. Но задача неясна. - SciFi(24.04.2024 16:18)
- Есть аппаратный таймер, считающий в пределах uint32. Хочется, чтобы
считал до uint64. Я использую функцию, которая видит, насколько
изменилось значение таймера между вызовами и добавляет эту разницу
в переменную uint64 - ar-elec(24.04.2024 16:25)
- 1) "заворот кишок" не анализируется (переход с 99 на 3) Zoro(142 знак., 24.04.2024 16:34)
- Если я правильно понял, речь в 1 про то, что cnt_old, допустим, уже
близко к максимуму, а cnt уже перебежало через него и стало опять
маленьким? ar-elec(391 знак., 24.04.2024 16:45)
- нафиг int32_t. использование uint32_t сильно упрощает. - Vit(04.05.2024 17:04)
- Возможно, сама хотелка хотелка перейти на 64 бита неуместна. Оно
таки нужно? Намного проще и безопаснее определить переполнение,
если чтение счетчика происходит не реже 4Г тактов. - POV(24.04.2024 16:50)
- ...А 64 бита - да, нужно. - ar-elec(24.04.2024 16:52)
- Да, возможно, я тоже в эту сторону смотрю. Но это не приведёт к тем же проблемам? Только они будут ещё реже возникать, и если там будет косяк, то его вообще хрен отловишь. - ar-elec(24.04.2024 16:51)
- Если я правильно понял, речь в 1 про то, что cnt_old, допустим, уже
близко к максимуму, а cnt уже перебежало через него и стало опять
маленьким? ar-elec(391 знак., 24.04.2024 16:45)
- Как-то так, наверное: SciFi(434 знак., 24.04.2024 16:34)
- А зачем это в разных местах вызывать? Всё рано ж дельта плюсуется. - POV(24.04.2024 16:26)
- Ну ок, неправ я. Не написал явно, что результат этого func'а
возвращается и используется там, откуда его вызвали. Т.е. на самом
деле ar-elec(300 знак., 24.04.2024 16:40)
- Ну вот, уже что-то осмысленное. У задачи повышения разрядности
таймера, и получения правильного значения есть классическое
решение, без запрета прерываний вообще. il-2(489 знак., 24.04.2024 16:54)
- Да, согласен. Единственно, по переполнению таймера тоже прерывание.
Хотя, ему можно поставить приоритет ниже, чем у всех остальных,
чтобы они не блокировались, тогда, действительно, должно идеально
сработать. Спасибо! В эту сторону тоже смотрел, но до конца не
продумал. - ar-elec(24.04.2024 16:59)
- Наоборот - приоритет самый высокий... POV(44 знак., 24.04.2024 17:00)
- 3. Повторить чтение - убедиться, что прочитали оно и то же (что не было в момент чтения переполнения счетчика). - POV(24.04.2024 16:58)
- Да, согласен. Единственно, по переполнению таймера тоже прерывание.
Хотя, ему можно поставить приоритет ниже, чем у всех остальных,
чтобы они не блокировались, тогда, действительно, должно идеально
сработать. Спасибо! В эту сторону тоже смотрел, но до конца не
продумал. - ar-elec(24.04.2024 16:59)
- И в гиперлупе и в прерываниях это нужно? Ну запрети прерывание синк
на пару тактов - чему это может повредить? - POV(24.04.2024 16:44)
- Ну, там не пара тактов, конечно, а пара десятков. Может, и ничего.
Критическое время порядка 10 мкс, частота процессора порядка 30-40
МГц. По идее, да, вроде, можно и запретить. Если ничего не
придумается, так и сделаю, но вдруг чудо? - ar-elec(24.04.2024 16:49)
- У тебя несколько команд. В любой момент исполнение функции
чтения-коррекции счетчика может быть прервано прерыванием с вызовом
той же самой функции. И все вычисления идут лесом. Особенно со
статик переменными, которые уж точно в единственно экземпляре (см.
недавнее обсуждение вопроса mse). - POV(24.04.2024 16:52)
- Вычисления лесом можно, теоретически, продублировать и сравнить, ну, и выполнять до тех пор, пока не совпадут, это будет критерием, что их никто не прерывал. В другом месте программы я так и делаю, только там прерывания не меняют этих переменных, так что прекрасно всё работает. А здесь вот - другая ситуасьён. - ar-elec(24.04.2024 16:55)
- У тебя несколько команд. В любой момент исполнение функции
чтения-коррекции счетчика может быть прервано прерыванием с вызовом
той же самой функции. И все вычисления идут лесом. Особенно со
статик переменными, которые уж точно в единственно экземпляре (см.
недавнее обсуждение вопроса mse). - POV(24.04.2024 16:52)
- Ну, там не пара тактов, конечно, а пара десятков. Может, и ничего.
Критическое время порядка 10 мкс, частота процессора порядка 30-40
МГц. По идее, да, вроде, можно и запретить. Если ничего не
придумается, так и сделаю, но вдруг чудо? - ar-elec(24.04.2024 16:49)
- Ну вот, уже что-то осмысленное. У задачи повышения разрядности
таймера, и получения правильного значения есть классическое
решение, без запрета прерываний вообще. il-2(489 знак., 24.04.2024 16:54)
- Ну ок, неправ я. Не написал явно, что результат этого func'а
возвращается и используется там, откуда его вызвали. Т.е. на самом
деле ar-elec(300 знак., 24.04.2024 16:40)
- 1) "заворот кишок" не анализируется (переход с 99 на 3) Zoro(142 знак., 24.04.2024 16:34)
- Есть аппаратный таймер, считающий в пределах uint32. Хочется, чтобы
считал до uint64. Я использую функцию, которая видит, насколько
изменилось значение таймера между вызовами и добавляет эту разницу
в переменную uint64 - ar-elec(24.04.2024 16:25)