Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как ПРАВИЛЬНО программировать на С++
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2, 3, 4
drvlas
Цитата(dxp @ Sep 11 2010, 14:49) *
Все эти трюки тов. Александреску - это высший пилотаж плюсового программирования, они требуют глубокого понимания концепций языка, а это приходит только с опытом его использования. Вот это и есть главная проблема для эмбеддеров - такого опыта у них, как правило, нет (по вполне объективным причинам). Поэтому этот код с шаблонами, списками типов и прочим для большинства - китайская грамота. Хотя при наличии отлаженной библиотеки можно использовать и не страдать. Необходимость вникать потребуется в случае портирования ее на другую платформу.


+1. Я как раз и есть тот, для которого сгенерить проект даже после прочтения этой великолепной статьи - невероятно сложно. Поэтому и хотелось бы видеть еще более конкретные вещи (уж не знаю, как это даже и назвать - библиотеки, шаблоны...), если это возможно.
Автору - успехов!

А то, что есть другие методы - дык! Флаг в руки! Покажите нам красиво smile.gif
DL36
Мне тоже понравилось, хотя на плюсах не пишу начал добавлять на вики сахары
Sergey_B
В функции UppendReadValue есть ошибка - portValue должно сдвигаться в противоположном направлении.

При использовании в IAR есть нюансы:
1. Для подавления довольно громоздких предупреждений компилятора подправить функции UppendValue и UppendReadValue подобным образом:
Код
    if (IsSerial<Typelist<Head, Tail> >::value)
    {
       #pragma diag_suppress = Pe062
        if ...
        else ...
        #pragma diag_default = Pe062
     }
     else
     {
         ...
         return value | ....
      }


2. Для получения заявленной автором эффективности, в макросе MAKE_PORT заменить вызовы функций data(), dir() и pin() непосредственно соответствующими параметрами макроса, т.к. IAR не оптимизирует ссылки на порты.

3. Конструкции типа #ifdef PORTA в IAR не работают, т. к. PORTA не является макроопределением. Тут уж по собственному усмотрению, ну и конечно не забыть про include guard.
neiver
Спасибо за отзыв и найденную ошибку.
1. Переделаю вскоре, чтоб не было предупреждений, я уже знаю как.
2. Впринципе, data(), dir() и pin() это просто артефакт. В них реальной необходимости нет.
3. Я с этим сталкивался, но пока не знаю, что с этим делать.
Include guard есть - #pragma once. Или IAR такую форму не понимает?
Sergey_B
В IAR используется "классическая" конструкция в заголовочных файлах:

#ifndef FILENAME_H
#define FILENAME_H
...
...
...
#endif


> 3. Я с этим сталкивался, но пока не знаю, что с этим делать.

Я заменил их макроопределениями типа USE_PORTA, которые объявляю в файле подобном avr/io.h для нужных мне контроллеров.
neiver
Цитата(Sergey_B @ Sep 17 2010, 17:36) *
Я заменил их макроопределениями типа USE_PORTA, которые объявляю в файле подобном avr/io.h для нужных мне контроллеров.


Да, ручками-то конечно можно определения писать, но не хочется.
neiver
Sergey_B, я пожалуй воспользуюсь вашей идеей с USE_PORTA. Для avr-gcc их можно определить автоматом, а для IAR - вручную
neiver
Добавил поддержку компилятора от IAR в свои списки линий. В общем работает.
Обновления в Git репозитории:
http://github.com/KonstantinChizhov/AvrPro.../master/avrcpp/

ЗЫ.
Что-то меня не впечатлил этот хвалёный компилятор от IAR Systems для AVR.
Я нашел тоько два вида оптимизации которые он делает лучше чем GCC:
- Common subexpression elimination,
- умеет работать с однобайтовыми указателями.
А в остальном как-то не впечатляет.
MrYuran
Цитата(neiver @ Sep 20 2010, 15:37) *
ЗЫ.
Что-то меня не впечатлил этот хвалёный компилятор от IAR Systems для AVR.
Я нашел тоько два вида оптимизации которые он делает лучше чем GCC:
- Common subexpression elimination,
- умеет работать с однобайтовыми указателями.
А в остальном как-то не впечатляет.

Не совсем в тему, но всё-таки местами он (ИАР) гораздо лучше работает.
В mspgcc при всех моих потугах мне так и не удалось достичь иаровского размера бинарника.
Разница как минимум 20%.
Существенно, когда балансируешь на грани невпихуемости.
Хотя, глючки иногда подкидывает специфические и трудноуловимые. Например, коллега целый день бился, пока не поменял bool на char. И это при нулевой оптимизации.
Преимущество ИАРа в том, что его лучше затачивают под конкретную платформу (под каждую из).
Недостаток - при этом он код теряет переносимость, вследствие специфических приёмов.
Quasy
Вопрос автору этого инструмента: как будет выглядеть после трансляции асм-код для ATmega128 при записи в группу из 4-х бит число 0x0A. Группа такая (начиная с младшего в группе): PA.0, PB.0, PD.3, PD.4? Хотелось бы посмотреть именно "боевой", (не учебный) код, который будет сгенерирован в этом случае. Спасибо.
neiver
to Quasy.
Исходный код:
Код
#include <avr/io.h>
#include "iopins.h"
#include "pinlist.h"
#include "util.h"

using namespace IO;

typedef PinList<Pa0, Pb0, Pd3, Pd4>  Pins;

int main()
{
    Pins::Write(0x0A);
}


Асм листинг для атмега128:

Код
000000be <main>:
    
  be:    d8 98           cbi    0x1b, 0; 27

  c0:    c0 98           cbi    0x18, 0; 24

  c2:    82 b3           in    r24, 0x12; 18
  c4:    87 7e           andi    r24, 0xE7; 231
  c6:    80 61           ori    r24, 0x10; 16
  c8:    82 bb           out    0x12, r24; 18


  ca:    80 e0           ldi    r24, 0x00; 0
  cc:    90 e0           ldi    r25, 0x00; 0
  ce:    08 95           ret


Как-то так. Писать в виртуальные порты константы не интересно - запись любого набора бит в один порт будет соптимизирована не более чем до:
Код
in    r24, PORTx
andi    r24, Mask;
ori    r24, Value
out    PORTx, r24

Интереснее запись занчеия неизвестного во время компиляции - там будет перетасовка бит из входного значения в резистры.

ЗЫ.
Интересно, что вам мешает взять исходный код и поэкспериментировать самостоятельно.
Quasy
Как, это уже и есть боевой код? Но согласитесь, в таком виде его применять просто нельзя. Где в вашем варианте элементарные мероприятия по защите от неатомарности портовой операции "чтение-модификация-запись"?
neiver
Атомарность доступа далеко не всегда нужна. Обеспечивать ее всегда слишком расточительно. Если она всё-таки необходима используйте ATOMIC_BLOCK и иже сним, например:

ATOMIC_RESTORESTATE
{
Pins::Write(0x0A);
}

В чём проблема-то?
Quasy
А проблема в том, что, в предлагаемом виде генерируемый код фигурально выражаясь, подпадает под статью "Вредительство". По крайней мере в стране эмбедеров smile.gif) Применять его пока нельзя. И мне очень бы хотелось посмотреть генерируемый вашим инструментом вариант боевого код с учетом неатомарности. Или вы предлагаете программисту, применяющему ваш код, надеяться что не будет прерываний? Или вы предлагаете самому программисту позаботиться об атомарности? Очень хочется посмотреть вариант Безопасного кода записи в группу. Спасибо.

Дилемма. Без организации критической секции код применять нельзя. С организацией критической секции ваш код займет 11 тактов, что недопустимо. А все потому, что ваш код не научился делать четыре операции SBI/CBI.
Сергей Борщ
Цитата(Quasy @ Sep 27 2010, 09:57) *
Или вы предлагаете программисту,
Ключевое слово "программисту". Которому голова дана не только чтобы в нее есть.
Цитата(Quasy @ Sep 27 2010, 09:57) *
Или вы предлагаете программисту, применяющему ваш код, надеяться что не будет прерываний?
У меня нет махания ногами в прерываниях. Нафига мне лишний оверхед с вашей атомарностью?
Цитата(Quasy @ Sep 27 2010, 09:57) *
А все потому, что ваш код не научился делать четыре операции SBI/CBI.
Зал притих - покажите, на примере порта E.
neiver
Заботиться об атомарности всё равно прийдётся программисту. Даже операция вида int c = a + b; И всегда есть шанс, что прерывание случится в момент когда первый байт в переменную "с" уже записан, а второй нет. И если в этом перерывании используется эта переменная "с"...
Вы предлагаете использовать везде операции SBI/CBI и выводить значение побитно? А что, если мы будем записывать значение неизвестное во время компиляции побитно? Попробуйте сами написать, хоть на Си, хоть на ассемблере. Покажите как должно быть правильно.
Quasy
Цитата(Сергей Борщ @ Sep 27 2010, 11:33) *
Ключевое слово "программисту". Которому голова дана не только чтобы в нее есть.
У меня нет махания ногами в прерываниях. Нафига мне лишний оверхед с вашей атомарностью?
Зал притих - покажите, на примере порта E.

Залу не надо притихать! Он и так 8 страниц переливал из пустого в порожнее и не обсуждал самое главное - безопасность применения. Про PORTE? Ну, вам-то я скажу по секрету: у Atmega 128 (про который речь) его адрес 03 smile.gif SBI & CBI. У меги128 90% портов в битовом пространстве.



Цитата(neiver @ Sep 27 2010, 11:34) *
Вы предлагаете использовать везде операции SBI/CBI и выводить значение побитно? А что, если мы будем записывать значение неизвестное во время компиляции побитно? Попробуйте сами написать, хоть на Си, хоть на ассемблере. Покажите как должно быть правильно.

Мы пока говорим про константы. Если настало время - я скажу и про переменные. Там для предложенной группы нет альтернативы варианту с побитовым анализом переменной и операциям SBI/CBI.
Dima_G
Цитата(Quasy @ Sep 27 2010, 13:15) *
Как, это уже и есть боевой код? Но согласитесь, в таком виде его применять просто нельзя. Где в вашем варианте элементарные мероприятия по защите от неатомарности портовой операции "чтение-модификация-запись"?

А вы все операции с портами ввода-вывода оборачиваете в критические секции? Даже те, которые абсолютно не зависят от прерываний? Надеюсь, что нет.
Тогда какой смысл оборачивать в критические секции операции в "библиотечном" классе? Разумно это отдавать на откуп пользователю

у меня это например реализовано так:
Код
template <class ELEMENT, class SYNC_OBJ>
class TClQueue;
Quasy
Цитата(Dima_G @ Sep 27 2010, 12:02) *
А вы все операции с портами ввода-вывода оборачиваете в критические секции? Даже те, которые абсолютно не зависят от прерываний? Надеюсь, что нет.
Тогда какой смысл оборачивать в критические секции операции в "библиотечном" классе? Разумно это отдавать на откуп пользователю

у меня это например реализовано так:
Код
template <class ELEMENT, class SYNC_OBJ>
class TClQueue;

Кто сказал про "класс"? Я просил результирующий асм-код и критикую его. Где будет решаться проблема неатомарности - это я и хотел понять. Причем критика не понедельничного злого бодуна, а вполне конструктивная: я предлагаю путь.
MrYuran
Тут пришёл поручик Ржевский и всё опошлил.

Скажите, Quasy, а нафига козе боян зачем вообще нужна ваша атомарность?
Я пока не вижу особых критических моментов.
Выставили байт - подали отдельно строб.
Тем более что при вашем битовом анализе всё равно вручную всё обеспечивать.
Quasy
Цитата(MrYuran @ Sep 27 2010, 12:06) *
Тут пришёл поручик Ржевский и всё опошлил.

Скажите, Quasy, а нафига козе боян зачем вообще нужна ваша атомарность?
Я пока не вижу особых критических моментов.
Выставили байт - подали отдельно строб.
Тем более что при вашем битовом анализе всё равно вручную всё обеспечивать.

Какой строб, господи? Я просил пример реализации записи числа в определенную группу...
Dima_G
Цитата(Quasy @ Sep 27 2010, 15:06) *
Кто сказал про "класс"? Я просил результирующий асм-код и критикую его. Где будет решаться проблема неатомарности - это я и хотел понять. Причем критика не понедельничного злого бодуна, а вполне конструктивная: я предлагаю путь.

Тут по-моему уже се запутались в вопросе - что вы собственно предлагаете то?
Топикстартер показал решение предложенной вами задачи, используя его инструментарий. Показал на тестовом примере + ассемблерный листинг.
Продемонстрируйте свой вариант и асм листинг. Тогда можно будет предметно говорить.
Andy Mozzhevilov
Цитата(Quasy @ Sep 27 2010, 12:06) *
Кто сказал про "класс"? Я просил результирующий асм-код и критикую его. Где будет решаться проблема неатомарности - это я и хотел понять. Причем критика не понедельничного злого бодуна, а вполне конструктивная: я предлагаю путь.

На самом деле вы ничего не предлагается. Вы ведете себя как Гуру, который достиг просветления и ему стали понятны какие-то более высокие материи, чем всем остальным. И куда уж нам тут всем, до Вас - небожителей.
Вместо того, чтобы привести четкий и понятный код, хоть на Си, хоть на ассемблере - и сказать: "Я считаю, что так правильно потому-то и потому-то" (ведь каждый может иметь мнение и опыт, на котором оно основано), вы пишите какими-то намеками, недомолвками и т.п.
Из чего напрашивается вывод - либо вы сами не знаете, как... Либо вы боитесь показать тот код, который считаете правильным, поскольку он может быть подвергнут критике.
Quasy
Цитата(Dima_G @ Sep 27 2010, 12:12) *
Тут по-моему уже се запутались в вопросе - что вы собственно предлагаете то?
Топикстартер показал решение предложенной вами задачи, используя его инструментарий. Показал на тестовом примере + ассемблерный листинг.
Продемонстрируйте свой вариант и асм листинг. Тогда можно будет предметно говорить.

Как, опять непонятно? Как, это я со стропами-стробами запутался? smile.gif Еще раз: я показал автору слабые места и вариант куда грести. Могу и больше подсказать, если надо. И предлагаю уважаемому (без всяких колкостей - уважаемому за свой труд) автору в хорошем смысле слова разозлиться(вот сверхзадача моих постов) и отшлифовать свою библиотечку, чтобы она стала бриллиантом. Для XMEGA уже хорошо. Вот для просто меги - пусть разозлится.

Цитата(Andy Mozzhevilov @ Sep 27 2010, 12:19) *
На самом деле вы ничего не предлагается. Вы ведете себя как Гуру, который достиг просветления и ему стали понятны какие-то более высокие материи, чем всем остальным. И куда уж нам тут всем, до Вас - небожителей.
Вместо того, чтобы привести четкий и понятный код, хоть на Си, хоть на ассемблере - и сказать: "Я считаю, что так правильно потому-то и потому-то" (ведь каждый может иметь мнение и опыт, на котором оно основано), вы пишите какими-то намеками, недомолвками и т.п.
Из чего напрашивается вывод - либо вы сами не знаете, как... Либо вы боитесь показать тот код, который считаете правильным, поскольку он может быть подвергнут критике.

Что ж, мне жаль вас, не видящим предложений хотя бы по замене RMW-записи в порт операциями SBI & CBI. Повторюсь, если автору потребуется - помогу более детально. По крайней мере как я вижу возможности различить варианты RMW порта и побитовые операции.
MrYuran
Цитата(Quasy @ Sep 27 2010, 12:09) *
Какой строб, господи? Я просил пример реализации записи числа в определенную группу...

Ну, записали число в группу...
Дальше что?
И для чего атомарность?
И что такое CBI/SBI?
Или по-вашему, кроме AVR, других контроллеров не существует?
Осмелюсь доложить, что в msp430 нет битовых команд.
Кроме того, компилятор, как правило, сам выбирает оптимальную реализацию - с помощью маски или битовых манипуляций.
Dima_G
Цитата(Quasy @ Sep 27 2010, 15:24) *
Еще раз: я показал автору слабые места и вариант куда грести.

Вы про атомарность? Не нужна она здесь в явном виде! Более того - вредна. Посмотрите пример STL - там об атомарности ничего не говорится, а писали ее далеко не дураки.
Единственно, для себя я бы возможно добавил флаг атомарности в шаблон класса

Цитата(Quasy @ Sep 27 2010, 15:24) *
Могу и больше подсказать, если надо.

Покажите, это многим будет интересно. Как говорится - с миру по нитке..

Цитата(Quasy @ Sep 27 2010, 15:24) *
И предлагаю уважаемому (без всяких колкостей - уважаемому за свой труд) автору в хорошем смысле слова разозлиться(вот сверхзадача моих постов) и отшлифовать свою библиотечку, чтобы она стала бриллиантом. Для XMEGA уже хорошо. Вот для просто меги - пусть разозлится.

Так вы конкретно напишите: на Си (не обязательно круто - главное чтоб идею понять), просто словами (внятно). Что по-вашему необходимо добавить / исправить в библиотеке?
Andy Mozzhevilov
Цитата(Quasy @ Sep 27 2010, 12:29) *
Что ж, мне жаль вас, не видящим предложений хотя бы по замене RMW-записи в порт операциями SBI & CBI. Повторюсь, если автору потребуется - помогу более детально. По крайней мере как я вижу возможности различить варианты RMW порта и побитовые операции.

Меня жалеть не нужно.
Научитесть на форуме общаться конструктивно. Телепатов тут нет. Есть мысль, предложение, обоснование - дайте код, который можно будет обсуждать. Предыдущее сообщение я написал, чтобы подчеркнуть только этот аспект.
Quasy
Цитата(Dima_G @ Sep 27 2010, 12:31) *
Вы про атомарность? Не нужна она здесь в явном виде! Более того - вредна. Посмотрите пример STL - там об атомарности ничего не говорится, а писали ее далеко не дураки.
Единственно, для себя я бы возможно добавил флаг атомарности в шаблон класса


Покажите, это многим будет интересно. Как говорится - с миру по нитке..


Так вы конкретно напишите: на Си (не обязательно круто - главное чтоб идею понять), просто словами (внятно). Что по-вашему необходимо добавить / исправить в библиотеке?

Весной накропал подобную библиотека для ATXMEGA. Но она на простом Си и активно использует макросы. Если подождать несколько дней - я приведу ее в удобоваримый вид и выложу для критики. Если от нее что-то останется, то, после того, как меня высушат после помоев, можно вместе ее портировать для ATmegи.
Andy Mozzhevilov
Цитата(Quasy @ Sep 27 2010, 12:44) *
Весной накропал подобную библиотека для ATXMEGA. Но она на простом Си и активно использует макросы. Если подождать несколько дней - я приведу ее в удобоваримый вид и выложу для критики.

Я думаю, будет достаточно, если вы выложите результат работы компилятора в виде листинга и поясните, что вы считаете в вашем случае лучше (если это не будет очевидным).
Quasy
Цитата(Andy Mozzhevilov @ Sep 27 2010, 12:40) *
Меня жалеть не нужно.
Научитесть на форуме общаться конструктивно. Телепатов тут нет. Есть мысль, предложение, обоснование - дайте код, который можно будет обсуждать. Предыдущее сообщение я написал, чтобы подчеркнуть только этот аспект.

А телепатия и не нужна. Задача: Есть например, группа бит на портах: A.0, B.0, C.3, С.4. Надо записать в нее число 0x0A. То есть GROUP(0х0А); Вот вариант-образец как напишем без всяких инструментов: cbi PortA, 0; sbi PortB, 0; cbi PortC, 3; sbi PortC, 4; Хотелось бы знать, не может ли эта библиотека сделать подобный код? Все!
neiver
Я прекрасно понимаю, о каких проблемах говорит Quasy.
Он имеет ввиду ситуацию когда прерывание происходит между in и out и в этом прерывании происходит запись в тот-же порт.
При этом значение записанное в прерывании потеряется.
В этом случае атомарность записи действительно нужна, но ее легко добится использованием того-же ATOMIC_BLOCK.
В остальных случаях она лишняя.


Код
  c2:    82 b3           in    r24, 0x12; 18
  c4:    87 7e           andi    r24, 0xE7; 231
  c6:    80 61           ori    r24, 0x10; 16
  c8:    82 bb           out    0x12, r24; 18


Кстати комманды SBI & CBI выполняются за 2 такта. In/Out/andi/Ori - каждая за один такт. По тактам одинаково выходит даже в этом примере.


Да, для MSP430 я этот подход уже адаптировал. Компилируется под mspgcc и под IAR.
MrYuran
Цитата(Quasy @ Sep 27 2010, 12:54) *
А телепатия и не нужна. Задача: Есть например, группа бит на портах: A.0, B.0, C.3, С.4. Надо записать в нее число 0x0A. То есть GROUP(0х0А); Вот вариант-образец как напишем без всяких инструментов: cbi PortA, 0; sbi PortB, 0; cbi PortC, 3; sbi PortC, 4; Хотелось бы знать, не может ли эта библиотека сделать подобный код? Все!

Я вам более реальный пример приведу.
Прибегает снабженец и говорит такую речь:
У атмеля проблемы с поставками, поэтому вместо ATMega128 я закупил ящик msp430f149.
У вас неделя, чтобы привести в порядок документацию.

Вопрос: что будет делать ваша библиотека?
Quasy
Не, ну это хоть сейчас... Вот группа : PORTA.0, PORTB.0, PORTR.1 и PORTR.5. Даю макрос: Записать в нее (а именно в регистр DIR порта) число 09. Листинг вот он:
203 PUT_CONST_GROUP( 0, _DIR, 0x09 );
\ 000000D8 9A80 SBI 0x10, 0x00
\ 000000DA 9881 CBI 0x10, 0x01
\ 000000DC E200 LDI R16, 32
\ 000000DE 930007E1 STS 2017, R16
\ 000000E2 E002 LDI R16, 2
\ 000000E4 930007E2 STS 2018, R16
neiver
Цитата(Quasy @ Sep 27 2010, 12:54) *
А телепатия и не нужна. Задача: Есть например, группа бит на портах: A.0, B.0, C.3, С.4. Надо записать в нее число 0x0A. То есть GROUP(0х0А); Вот вариант-образец как напишем без всяких инструментов: cbi PortA, 0; sbi PortB, 0; cbi PortC, 3; sbi PortC, 4; Хотелось бы знать, не может ли эта библиотека сделать подобный код? Все!


Это можно реализовать. Но я не уверен, что нужно. Это оптимизация под один частный случай использования под определенной семейство МК. В этой библиотеке есть более важные варианты использования, которые надо оптимизировать.
MrYuran
Цитата(neiver @ Sep 27 2010, 12:56) *
Я прекрасно понимаю, о каких проблемах говорит Quasy.
Он имеет ввиду ситуацию когда прерывание происходит между in и out и в этом прерывании происходит запись в тот-же порт.

А, ну вот, единственный случай.
"-Доктор, когда я так делаю...
- А вы так не делайте!"
Ну и, писали уже - атомик блок. Без вариантов.
Andy Mozzhevilov
Цитата(MrYuran @ Sep 27 2010, 12:58) *
Я вам более реальный пример приведу.
Прибегает снабженец и говорит такую речь:
У атмеля проблемы с поставками, поэтому вместо ATMega128 я закупил ящик msp430f149.
У вас неделя, чтобы привести в порядок документацию.

Вопрос: что будет делать ваша библиотека?

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

Quasy
Пардон, PORTB.1 а не 0...

Цитата(Quasy @ Sep 27 2010, 13:03) *
Пардон, PORTB.1 а не 0...

Гы... Короче, A.0, A.1, R.1, R.5

Предлагаю посоревноваться с автором листингами записи групп на ХМЕГА. Будем туда писать постоянные, переменные... Например, исходно имеем группу из 4...6 бит. Часть из них на виртуальном порту, часть - нет. Предлагайте варианты как расположить битовые группы и что туда загнать. Если интересно, конечно...
MrYuran
Цитата(Andy Mozzhevilov @ Sep 27 2010, 13:03) *
Если бы случилась такая фигня, то лично моя библиотека бы ничего не стала делать.
Снабженец был бы просто уволен.

Да, согласен, утрировал немного (самую малость).
Но и товарищ был не прав, выдавая частный случай и свою узкозаточенную реализацию (без исходников, кстати) за истину в последней инстанции.
Quasy
Цитата(MrYuran @ Sep 27 2010, 13:22) *
Да, согласен, утрировал немного (самую малость).
Но и товарищ был не прав, выдавая частный случай и свою узкозаточенную реализацию (без исходников, кстати) за истину в последней инстанции.

Исходники для XMEGA обещаны. Если посоревнуемся и они окажутся достойными авторских, конечно... А если они окажутся плохими, то зачем миру мои нелепые исходники? smile.gif
DL36
Есть хорошая статья, Атомарный доступ к структурам по поводу атомарности.
Цитата
О "волшебном" свойстве XOR я знал давно, но формализованный подход увидел первый раз на форуме microchip.com. Автор замечательной коммерческой RTOS AVIX-RT выложил макрос, который использует inline ассемблер для реализации xor доступа. Затем в состав AVIX вошел заголовочный файл, в котором реализованы расширенные варианты подобного макроса для архитектур PIC24/dsPIC (компилятор C30) и PIC32 (MIPS32 M4K, компилятор C32).


Если добавить предложенный подход к предложенному методу будет вообще ...
MrYuran
Цитата(DL36 @ Sep 27 2010, 13:58) *
Есть хорошая статья, Атомарный доступ к структурам по поводу атомарности.

Вот ведь, никогда не задумывался над подобной проблемой.
А ведь действительно...
В последнее время всё чаще приходится воевать с "чудесами" в структурах.
Надо будет тщательнее рассмотреть...
neiver
Цитата(DL36 @ Sep 27 2010, 13:58) *
Есть хорошая статья, Атомарный доступ к структурам по поводу атомарности.


Если добавить предложенный подход к предложенному методу будет вообще ...

Боюсь для tiny/maga AVR этот матод не реализуем - нету в них атомарного xor. Для XMaga он не нужен - есть специальные регистры для атомарного И/ИЛИ. А для MSP430 не знаю, надо разбираться, может и сработает.

Строго говоря, приведённый код не является атомарным. Прерывание так-же может произойти между чтением регистра и его модификацией/записью с помощью xor. Однако побочные эффекты при этом будут другие: если в прерывании изменятся биты, которые должны быть изменены с помощью последнего xor, то их значение будет ошибочно инвертировано.
Лучше это или хуже чем терять значение записанное в прерывании не знаю, ни то не другое не есть хорошо и прерывания всё равно прийдётся запрещать.

Код
002FA  801630     mov.w TRISB, W0
002FC  68006A     xor.w W0, #0x000A, W0
002FE  60006F     and.w W0, #0x000F, W0
00300  B6A2C6     xor.w TRISB
Quasy
Цитата(neiver @ Sep 27 2010, 14:38) *
Боюсь для tiny/maga AVR этот матод не реализуем - нету в них атомарного xor. Для XMaga он не нужен - есть специальные регистры для атомарного И/ИЛИ. А для MSP430 не знаю, надо разбираться, может и сработает.

Для Хмега тоже есть изюминки. Там SBI за 1 такт выполняется, поэтому, если порт отображен на виртуальный, && количество бит, принадлежащих этому порту порту, 1 или 2, то выгоднее по тактам обращаться побитно через SBI/CBI VPORTn_OUT, а иначе - через OUTSET/OUTCLR физического порта.
MrYuran
Цитата(neiver @ Sep 27 2010, 14:52) *
Строго говоря, приведённый код не является атомарным. Прерывание так-же может произойти между чтением регистра и его модификацией/записью с помощью xor. Однако побочные эффекты при этом будут другие: если в прерывании изменятся биты, которые должны быть изменены с помощью последнего xor, то их значение будет ошибочно инвертировано.
Лучше это или хуже чем терять значение записанное в прерывании не знаю, ни то не другое не есть хорошо и прерывания всё равно прийдётся запрещать.

Как раз-таки нет.
Насколько я понял, на биты, которые мы отгородили для XOR-енья, оставшиеся никак влиять не будут, при условии, естественно, что они модифицируются аналогичным образом.
Всё потому, что мы накладываем на XOR-ную маску ещё маску пинов, то есть на "чужие" пины она никакого влияния не окажет.
_______
Вот какая полезная тема оказалась, я бы до такого сам бы не дошёл!
Причём совершенно параллельно, на си это написано или на плюсах...
Quasy
А с проблемой атомарности там на хмеге действительно легче. Кроме одного случая: групповая конфигурация режимов пина. Там тоже надо ставить критическую секцию. Но тут еще проблема - ГДЕ ставить начало критической секции. Если в группе несколько портов с битовым доступом и всего для одной пары бит нужна критическая секция - зачем же запрещать прерывания в самом начале? Это ж на сколько лишних татктов МК "оглохнет"! Надо запрещать прерывания только перед той операцией, где это действительно требуется.

Цитата(MrYuran @ Sep 27 2010, 15:06) *
Вот какая полезная тема оказалась, я бы до такого сам бы не дошёл!
Причём совершенно параллельно, на си это написано или на плюсах...

Вот видите, самипоняли важность, а то недоумевали - зачем этот пришлый выскочка поднял такую узкую тему. Атомарность это ого-го. PS.На Телесистемах перестройка - я с вашего разрешения тут пережду. Заодно поколыхаю немножко вашу тихую заводь smile.gif
neiver
Цитата(MrYuran @ Sep 27 2010, 15:06) *
Как раз-таки нет.
Насколько я понял, на биты, которые мы отгородили для XOR-енья, оставшиеся никак влиять не будут, при условии, естественно, что они модифицируются аналогичным образом.
Всё потому, что мы накладываем на XOR-ную маску ещё маску пинов, то есть на "чужие" пины она никакого влияния не окажет.
_______
Вот какая полезная тема оказалась, я бы до такого сам бы не дошёл!
Причём совершенно параллельно, на си это написано или на плюсах...


mov.w TRISB, W0 //TRISB == 0x0000
xor.w W0, #0x000A, W0 //W == 0x000A
and.w W0, #0x000F, W0 //W == 0x000A

//прерыване
//сохраняем W и т.д.
mov.w TRISB, W0 //TRISB == 0x0000
xor.w W0, #0x0028, W0 //W == 0x0028
and.w W0, #0x003C, W0 //W == 0x003C
xor.w TRISB //TRISB == 0x0028
//восстанавливаем W и т.д.
//конец прерывания
//W == 0x000A, TRISB == 0x0028
xor.w TRISB // TRISB = 0x0022 --> один бит потеряли, должно быть 0x002A

Так, что и тут есть подводные камни. Но только в случае, если модифицируется пересекающееся множество бит.
Если модифицируемые биты различны, то проблем нет.
MrYuran
Цитата(neiver @ Sep 27 2010, 15:29) *
xor.w TRISB // TRISB = 0x0022 --> один бит потеряли, должно быть 0x002A

У вас маски перекрываются, так не договаривались rolleyes.gif
segment
Если правильно спроектировать код - то не будет такого бреда, как запись в порт в прерывании и в основном потоке.
neiver
Цитата(Сега @ Sep 27 2010, 16:32) *
Если правильно спроектировать код - то не будет такого бреда, как запись в порт в прерывании и в основном потоке.

Согласен, в большинстве случаев этого можно и нужно избегать, но иногда это бывает оправдано.
Andy Mozzhevilov
Цитата(Сега @ Sep 27 2010, 16:32) *
Если правильно спроектировать код - то не будет такого бреда, как запись в порт в прерывании и в основном потоке.


Это никакой не бред. Gpio - они на то и Gpio, чтобы ими можно было программно махать.
При проектировании аппаратной части устройства те сигналы, которые управляются через gpio могут использоваться много для каких целей, от простейшего управления светодиодами, до каких-то сигналов стробирования периферийных устройств(работающих по прерываниям), генерации последовательностей импульсов, напрмер управления шаговиками (это то что пришло на ум сразу из того, что я реально делал). Часть этих портов могут управляться из фоновой программы, частью - целесообразно управлять из прерываний. Если используется RTOS - то управление может производится в том числе из разных задач. И только не говорите, что это неправильно спроектированный софт и бред. Бред как раз - это обеспечивать управление всеми gpio из одной задачи в случае RTOS, или только из background при ее отсутствии.
При разводке схемы разработчик скорее руководствуются оптимальностью разводки, чем задумываются об атомарности доступа и прочих удобствах для программиста (как то, группировка gpio на соседних линиях портов). Такой подход понятен и вполне оправдан.
Поэтому при управлении gpio портами нужно либо иметь эти эффекты ввиду и организационно обеспечивать атомарное обращение к портам, либо код обращения к портам обертывать в критические секции, либо использовать атомарные команды при изменении битов портов.
Я с АВР давно уже не работаю и не отслеживаю, что там у них и как со свойствами периферии и/или системой команд.
Но, работаю с ARM7 NXP, в коих разработчики позаботились об этой проблеме, разделив регистры по установке и сбросу битов в gpio портах, таким образом обеспечив атомарность этих операций. Однако, если обращение идет к регистрам конфигурирования (направления, подтяжки), эти операции уже не являются атомарными, поскольку используют RMW. Поэтому приходится настройку портов оборачивать в критические секции. Но поскольку порты обычно настраиваются при старте системы и обычно - сразу кучей, то обертывание в критическую секцию этих операций - не такая и большая плата).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.