Важная информация

User Tag List

Страница 4 из 17 ПерваяПервая 12345678 ... ПоследняяПоследняя
Показано с 31 по 40 из 163

Тема: ROM-плеер на ардуино

  1. #31
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,653
    Спасибо Благодарностей отдано 
    214
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Кстати, если в программе только одно прерывание и оно используется для формирования выходного WAV, то должно быть глубоко фиолетово, сколько буферов и какие они... главное, чтобы были не пустыми. Поскольку прерывание на вывод очередного фронта прервёт общение с SD-картой (оно ведь не на прерываниях)...

  2. #31
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #32
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    970
    Спасибо Благодарностей отдано 
    417
    Спасибо Благодарностей получено 
    392
    Поблагодарили
    217 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от svofski Посмотреть сообщение
    Маленькое замечание — delay() для ожидания изменения бита не имеет смысла, потому что внутри его такой же цикл.
    Там немного сокровенный смысл: во время отработки цикла в delay(Tpp) не трогается переменная CRB, которая может неожиданно измениться в подпрограмме обработки прерывания, просто ждём 1000 циклов таймера, и за это время чтение догонит запись на 125 байт (почти половину буфера). :-)

  4. #33
    Guru Аватар для svofski
    Регистрация
    20.06.2007
    Адрес
    С.-Петербург
    Сообщений
    4,105
    Спасибо Благодарностей отдано 
    772
    Спасибо Благодарностей получено 
    643
    Поблагодарили
    398 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Когда что-то поменяется, что-то добавится, или просто пройдет достаточное время, это навернется и поймать проблему будет очень трудно.

    Для while() { delay(); } я бы завел булевый флажок, который устанавливается по такому же условию, но из прерывания.

    Операция BUFF[lowByte(CWB++)] = SBb должна быть атомарной, то есть в скобке из noInterrupts() - interrupts().

    Таким образом уйдет сокровенность и не останется мест, где зависимая переменная может измениться во время проверки условия. Останется бездушный автомат =)
    Больше игр нет

  5. #34
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    970
    Спасибо Благодарностей отдано 
    417
    Спасибо Благодарностей получено 
    392
    Поблагодарили
    217 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от svofski Посмотреть сообщение
    Для while() { delay(); } я бы завел булевый флажок, который устанавливается по такому же условию, но из прерывания.
    Не вижу смысла, т.к.:
    1. Это увеличит код подпрограммы прерывания, что не есть гуд.
    2. Обращение к этой булевой переменной в основной программе также должно быть внутри noInterrupts / interrupts.
    Лучше сделать нечто такое:
    Код:
    noInterrupts();
    CRB_temp = CRB;
    interrupts();
    и далее в программе используем CRB_temp, как, собственно рекомендуют по ссылкам выше... И хотя вероятность одновременного чтения и записи переменной CRB крайне низка, это защитит нас от глюка на 100%.

    Операция BUFF[lowByte(CWB++)] = SBb должна быть атомарной, то есть в скобке из noInterrupts() - interrupts().
    Ну может оно и так, но если принять за аксиому то, что разработчики компиляторов для ардуин -- разумные люди, то запись одного элемента массива ни в коем разе не должна затрагивать как-то другие элементы. А попадание чтения и записи в одну ячейку исключено программно задержкой, поэтому особого смысла выделять эту команду я не вижу.

  6. #35
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,653
    Спасибо Благодарностей отдано 
    214
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    А запрет прерывания не приведёт к потере прерывания и соответственно удлинениям импульсов ?

  7. #36
    Guru Аватар для svofski
    Регистрация
    20.06.2007
    Адрес
    С.-Петербург
    Сообщений
    4,105
    Спасибо Благодарностей отдано 
    772
    Спасибо Благодарностей получено 
    643
    Поблагодарили
    398 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Improver Посмотреть сообщение
    1. Это увеличит код подпрограммы прерывания, что не есть гуд.
    2. Обращение к этой булевой переменной в основной программе также должно быть внутри noInterrupts / interrupts.
    Увеличит на то же количество инструкций, которое эта же операция займет внутри секции с запрещенными прерываниями в основном цикле. И это пренебрежимо малое время в любом случае.

    Опрос такого флага в основной программе не нужно прятать в критическую секцию, потому что она только читается, это флажок - один байт, суть чтение атомарное, и никаких попыток одновременной модификации не делается. Запрет прерывания вокруг проверки просто ничего не изменит.

    Вариант с копированием переменной в критической секции тоже будет работать, но он не лучше. Это просто другой способ сделать то же самое.

    Цитата Сообщение от Improver Посмотреть сообщение
    разработчики компиляторов для ардуин -- разумные люди
    Дело не в компиляторе, а в том, что эта простая строчка на C++ прячет в себе много операций, каждая из которых может быть прервана:
    - вычисление смещения
    - запись
    - инкремент
    - запись
    каждая из этих операций тоже не атомарна, 16-битные инкременты, например, и тоже может быть разбита прерыванием.

    Если вычисление флажка делать в прерывании, то операция записи должна быть в критической секции, чтобы флажок не вычислился с непонятным значением CWB. Если проверка условия c копированием итд в основном цикле, то операция копирования должна быть в критической секции. В принципе это дело вкуса.

    Но все это из совершенно другой категории, чем подгонка буферов через delay(). delay() просто старается обойти проблему стороной, а правильная реализация взаимодействия между потоками исключает конфликтную ситуацию в принципе. То есть, если есть желание разбираться, то начинать надо с убирания delay().

    Цитата Сообщение от KTSerg Посмотреть сообщение
    А запрет прерывания не приведёт к потере прерывания и соответственно удлинениям импульсов ?
    Флаг запроса прерывания висит, пока его не сбросят вручную, или автоматом при вызове обработчика (лучше мне не верить, а почитать даташыт, страница 112, Timer/Counter Interrupt Flag Register – TIFR).
    Больше игр нет

  8. #37
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    970
    Спасибо Благодарностей отдано 
    417
    Спасибо Благодарностей получено 
    392
    Поблагодарили
    217 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от svofski Посмотреть сообщение
    Увеличит на то же количество инструкций, которое эта же операция займет внутри секции с запрещенными прерываниями в основном цикле. И это пренебрежимо малое время в любом случае.
    Не совсем на то же -- в основной программе можно вычисление этой булевой переменной вынести за секцию с запрещением прерывания. Я приводил пример выше, и по ссылке тоже так рекомендуют... Плюс к тому же не требуется выносить в критические секции все обращения к переменной CWB. Да, это будет всего несколько десятков циклов процессора, но всё же...

    Цитата Сообщение от svofski Посмотреть сообщение
    Если вычисление флажка делать в прерывании, то операция записи должна быть в критической секции, чтобы флажок не вычислился с непонятным значением CWB. Если проверка условия c копированием итд в основном цикле, то операция копирования должна быть в критической секции. В принципе это дело вкуса.
    Ещё, если вычисление флажка делать в подпрограмме прерывания, то он будет вычисляться каждый полуцикл, а если в основной программе -- то только перед записью в буфер, и в случае "паузы" он вычисляться не будет... А в остальном -- да, различия минимальны и это дело вкуса, но мне почему-то больше нравится второй вариант.

    Цитата Сообщение от svofski Посмотреть сообщение
    То есть, если есть желание разбираться, то начинать надо с убирания delay().
    Как? Заменить на millis()/micros() -- в данном случае это неимоверно усложнит программу... Честно -- я не представляю, как это сделать. Можно пример кода, или ссылку на то, как можно замедлить (синхронизировать) поток записи без применения delay() или другого подобного цикла ожидания?

    - - - Добавлено - - -

    Цитата Сообщение от KTSerg Посмотреть сообщение
    А запрет прерывания не приведёт к потере прерывания и соответственно удлинениям импульсов ?
    Безусловно да, и в худшем случае импульс будет удлинён на время исполнения кода внутри секции с запретом прерывания, но при частоте процессора в 16Мгц, задержка на десяток циклов будет пренебрежительно мала. Хотя, это не избавляет от необходимости сокращения до минимума кода, исполняемого с запретом прерываний.

  9. #38
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,653
    Спасибо Благодарностей отдано 
    214
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Можно ещё одно "извращение" сделать...
    В прерывании, при изменении индекса CRB (или просто в конце прерывания), устанавливать флаг, а в программе ждать установки этого флага и только тогда переходить к проверке (сравнению индексов).
    Контроль такого флага даст уверенность, что сравнение индексов происходит сразу по окончании прерывания и не будет "прервано"...
    Непосредственно перед циклом ожидания флага, обязательно его (флаг) сбросить.
    Последний раз редактировалось KTSerg; 20.02.2018 в 10:38.

  10. #39
    Guru Аватар для svofski
    Регистрация
    20.06.2007
    Адрес
    С.-Петербург
    Сообщений
    4,105
    Спасибо Благодарностей отдано 
    772
    Спасибо Благодарностей получено 
    643
    Поблагодарили
    398 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Improver Посмотреть сообщение
    Как? Заменить на millis()/micros() -- в данном случае это неимоверно усложнит программу... Честно -- я не представляю, как это сделать. Можно пример кода, или ссылку на то, как можно замедлить (синхронизировать) поток записи без применения delay() или другого подобного цикла ожидания?
    Задержка — это просто пустой цикл, который ничем не отличается от цикла, который эту задержку вызывает. Сейчас структура основного цикла условно говоря такая:

    Код:
    while (в буфере нет места) {
       задержка(); /* на самом деле просто вложенный пустой цикл */
    }
    записать_в_буфер;

    Задержка тут не является никакой частью механизма синхронизации. В последней версии скетча она выполняла "сокровенную функцию", то есть оттягивала фиаско. Синхронизация же обеспечивается любым из рассмотренных раньше способов, суть которых сводится к атомарной установке флага в одном месте и проверке его в другом. Если она сделана и исправно работает, то никаких ухищрений в виде задержек больше не потребуется:

    Код:
    while(в буфере нет места) { /* ничего */ };
    записать_в_буфер;
    Вместо двух вложенных циклов будет просто цикл.

    Цитата Сообщение от KTSerg
    В прерывании, при изменении индекса CRB (или просто в конце прерывания), устанавливать флаг, а в программе ждать установки этого флага и только тогда переходить к проверке (сравнению индексов).
    Контроль такого флага даст уверенность, что сравнение индексов происходит сразу по окончании прерывания и не будет "прервано"...
    Непосредственно перед циклом ожидания флага, обязательно его (флаг) сбросить.
    Если будет чтение сектора, потом копирование большого числа байтов, прерывание несколько раз случится за это время.

    Еще можно сразу после заполнения буфера загонять ардуину в сон (тут надо долго читать, какой именно из режимов сна правильно будет работать). Она будет просыпаться только на прерывание и забивание буфера, остальное время потреблять какой-то там наноампер.
    Больше игр нет

  11. #40
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,653
    Спасибо Благодарностей отдано 
    214
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Я вот чет притормозил... А зачем вообще необходима атомарность в BUFF[lowByte(CWB)] = SBb; ?
    В прерывании вообще нет обращения к CWB, его модификация не происходит (где-то в другом месте кода), ну разорвётся эта запись на прерывание, и чем это грозит? (если не считать, случай когда CRB догнал CWB...), Но опять-же, индекс CWB ведь не изменяется до окончания записи в буфер, значит и проблемы не должно быть...

Страница 4 из 17 ПерваяПервая 12345678 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Портативный AY плеер.
    от Руслан в разделе Звук
    Ответов: 1
    Последнее: 16.04.2014, 08:46
  2. Service rom + 128 basic rom
    от VELESOFT в разделе Оси
    Ответов: 1
    Последнее: 24.03.2013, 04:48
  3. Плеер для pt 3
    от Руслан в разделе Музыка
    Ответов: 25
    Последнее: 14.08.2012, 19:25
  4. Advanced ROM Manager (ROM Switvcher + Prof. ROM)
    от Alex_NEMO в разделе Память
    Ответов: 4
    Последнее: 04.10.2010, 11:43
  5. AY плеер
    от newart в разделе Звук
    Ответов: 19
    Последнее: 20.07.2006, 00:03

Метки этой темы

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •