Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: дерганье ножками lpc2xxx
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
HEX
Казалось бы такая простая вещь дергать ножкой...

В Примерах к китам, повсеместно для установка пинов вызывается что типа:
Код
IO1SET |= 0x00000001;

Как то раньше не задумывалься, пока глюку не словил, ножка "сама" прыгала в "1",
хорошо это было направления 485 и контроллер просто переставал отвечать оставаясь в передаче, тяжело было не заметить.
Проблема в том что операция не атомарная, и при наличии нескольких потоков, одновременно работающих с портом, в порт может быть выведена ерунда:
если после загрузки значения IOSET в регистр произойдет переключение потоков, в другом потоке будут сброшены битики, потом управление будет возвращено первому потоку, он установить сброшеные биты обратно в "1" (аналогично для IOCLR).

Решается проблема просто использованием
Код
IO1SET = 0x00000001
IO1CLR = 0x00000001

или помещением в критическую секцию. Тем более что
Код
IO1SET |= ..
бесмысленно, т.к. запись нуля ничего не меняет.

вот как выглядет на асме:
Код
//IO1SET |= 0x1;
LDR      R0, [PC, #+156]
LDR      R1, [PC, #+152]
LDR      R1, [R1, #+0]
ORRS    R1, R1, #0x1
STR      R1, [R0,  #+0]

//IO1SET_bit.P0_1 = 1;
LDR      R0,  [PC, #+136]
LDR      R1, [PC,  #+132]
LDR      R1, [R1, #+0]
ORRS    R1, R1, #0x2
STR      R1, [R0, #+0]

//IO1SET = 0x1;
LDR      R0, [PC, #+116]
MOV     R1, #+1
STR       R1, [R0, #+0]
zltigo
Цитата(HEX @ Jun 26 2008, 14:08) *
Казалось бы такая простая вещь дергать ножкой...

Тем не менее, извините, Вам удалось облажаться и эту лажу вынести на всеобщее обозрение.
Цитата
В Примерах к китам, повсеместно для установка пинов вызывается что типа:
Код
IO1SET |= 0x00000001;

Нет. Для тех, кто читал документацию, это выглядит так.
Код
IO1SET = 0x00000001;

Цитата
Проблема в том что операция не атомарная

Операция атомарная smile.gif, а IOSET, IOCLR и IOPIN это совсем разные регистры.
HEX
Цитата(zltigo @ Jun 26 2008, 16:26) *
Тем не менее, извините, Вам удалось облажаться и эту лажу вынести на всеобщее обозрение.

Поясните пожалуйста, чем вызвано оскарбление в мой адрес, и как это относится к теме сообщений?
zltigo
Цитата(HEX @ Jun 26 2008, 14:47) *
Поясните пожалуйста,...

Погорячился sad.gif изрядно. Извините.
Цитата
это относится к теме сообщений?

К теме сообщения это относится так - Вы совершенно неправильно работаете с регистами установки и очистки битов, посему Ваше прeдупреждение ложно.
defunct
Цитата(zltigo @ Jun 26 2008, 16:19) *
К теме сообщения это относится так - Вы совершенно неправильно работаете с регистами установки и очистки битов, посему Ваше прeдупреждение ложно.

Предупреждение не ложно.
Возможно ложен "наезд" на примеры к КИТам, но не само предупреждение.

Надо бы просто перефразировать:

IOSET/CLR - WriteOnly регистры и читать их бессмыслено.

операции |= и &= и любые другие "чтение-мод-запись" к WriteOnly регистрам неприменимы ни при каких условиях - будь-то один поток или несколько.
zltigo
Цитата(defunct @ Jun 26 2008, 17:16) *
Возможно ложен "наезд" на примеры к КИТам, но не само предупреждение.

Ну чего только в "примерах" не выкладывают sad.gif лучше просто не смотреть, если не достигли приличного уровня владения вопросом sad.gif.
Цитата
Надо бы просто перефразировать:

Или более общая формулировка - смотреть только документацию (за нее хоть кто-то в ответе), к примерам от производителя (их уже пишут и студенты, и индийцы...) относиться скептически, ко всем прочим (хорошее "просто так" очень редко встречается) - очень насторожено и не использовать до тех пор, пока четко не поймете и не пропустите через себя то, что там кто-то написал.
Цитата(defunct @ Jun 26 2008, 17:16) *
IOSET/CLR - WriteOnly регистры и читать их бессмыслено.

IOSET можно (и бывает нужно!) читать, только вот почему-то рассчитывать на атомарность нескольких подряд операций c GPIO совершенно наивно.
defunct
Цитата(zltigo @ Jun 26 2008, 18:50) *
IOSET можно (и бывает нужно!) читать, только вот почему-то рассчитывать на атомарность нескольких подряд операций c GPIO совершенно наивно.

И правда можно 07.gif , возвращает значение защелок порта. Не знал, а может знал да забыл. Не суть важно. Как для себя причислил сей регистр к WriteOnly и горя не знаю.
Сергей Борщ
Цитата(defunct @ Jun 27 2008, 01:45) *
Как для себя причислил сей регистр к WriteOnly и горя не знаю.
А напрасно. GetSmart показывал интересный пример, когда это может быть чревато неприятностями. Не буду настаивать, что вам надо менять привычки, но взять на заметку, скорее всего, не помешает.
defunct
Цитата(Сергей Борщ @ Jun 27 2008, 22:50) *
но взять на заметку, скорее всего, не помешает.

Спасибо, как на заметку пригодится.
Хотя задач, где бы понадобилась слепая инверсия порта, не могу даже представить.

Цитата
когда это может быть чревато неприятностями.

Ну почему же сразу неприятностями?
Есть выход без неприятностей - просто использовать переменную, сработает для любой архитектуры.
На некоторых архитектурах в частности на ARM такое решение будет более эффективным, за счет сокращения обращений к APB.
GetSmart
Цитата(defunct)
Спасибо, как на заметку пригодится.
Хотя задач, где бы понадобилась слепая инверсия порта, не могу даже представить.
Почему слепая? Простая нормальная инверсия. В отличие от "слепой", а точнее кривой инверсии через IOPIN.
Цитата(defunct)
На некоторых архитектурах в частности на ARM такое решение будет более эффективным, за счет сокращения обращений к APB.
Обращение к порту - 7 тактов максимум. Чтение и запись в дополнительную переменную в раме - 5 тактов, плюс ещё загрузка адресных регистров - тактов 10. Так что не будет эффективнее. По крайней мере в большинстве случаев.
defunct
Цитата(GetSmart @ Jun 29 2008, 13:33) *
Почему слепая? Простая нормальная инверсия.

Потому что процессору все равно что выведено в порт, цель проинвертировать.
В задачах с которыми я сталкиваюсь инвертировать (слепо - переворачивать значение порта) не нужно, нужно выводить конкетные значения.

Цитата
Обращение к порту - 7 тактов максимум. Чтение и запись в дополнительную переменную в раме - 5 тактов, плюс ещё загрузка адресных регистров - тактов 10. Так что не будет эффективнее.

Загрузка адресных регистров есть и там и там. Или есть способ обратиться к APB без загрузки адреса?
Забыли учесть возможное наличие кеш памяти, и то, что такты APB и такты процессора могут быть разной длительности.
GetSmart
Цитата(defunct)
Загрузка адресных регистров есть и там и там. Или есть способ обратиться к APB без загрузки адреса?
Изменение пина (через любой из IOPIN, IOSET, IOCLR) уже загружает адресный регистр, поэтому дополнительное чтение IOSET ничего не требует, в отличие от переменной в раме.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.