реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> дерганье ножками lpc2xxx, не наступайте на грабли!
HEX
сообщение Jun 26 2008, 12:08
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228



Казалось бы такая простая вещь дергать ножкой...

В Примерах к китам, повсеместно для установка пинов вызывается что типа:
Код
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]
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2008, 12:26
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(HEX @ Jun 26 2008, 14:08) *
Казалось бы такая простая вещь дергать ножкой...

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

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

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

Операция атомарная smile.gif, а IOSET, IOCLR и IOPIN это совсем разные регистры.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
HEX
сообщение Jun 26 2008, 12:47
Сообщение #3


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 25-11-04
Из: Тула
Пользователь №: 1 228



Цитата(zltigo @ Jun 26 2008, 16:26) *
Тем не менее, извините, Вам удалось облажаться и эту лажу вынести на всеобщее обозрение.

Поясните пожалуйста, чем вызвано оскарбление в мой адрес, и как это относится к теме сообщений?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2008, 13:19
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(HEX @ Jun 26 2008, 14:47) *
Поясните пожалуйста,...

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

К теме сообщения это относится так - Вы совершенно неправильно работаете с регистами установки и очистки битов, посему Ваше прeдупреждение ложно.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 26 2008, 15:16
Сообщение #5


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



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

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

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

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

операции |= и &= и любые другие "чтение-мод-запись" к WriteOnly регистрам неприменимы ни при каких условиях - будь-то один поток или несколько.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2008, 15:50
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(defunct @ Jun 26 2008, 17:16) *
Возможно ложен "наезд" на примеры к КИТам, но не само предупреждение.

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

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

IOSET можно (и бывает нужно!) читать, только вот почему-то рассчитывать на атомарность нескольких подряд операций c GPIO совершенно наивно.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 26 2008, 22:45
Сообщение #7


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



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

И правда можно 07.gif , возвращает значение защелок порта. Не знал, а может знал да забыл. Не суть важно. Как для себя причислил сей регистр к WriteOnly и горя не знаю.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 27 2008, 19:50
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 28 2008, 23:54
Сообщение #9


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Сергей Борщ @ Jun 27 2008, 22:50) *
но взять на заметку, скорее всего, не помешает.

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

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

Ну почему же сразу неприятностями?
Есть выход без неприятностей - просто использовать переменную, сработает для любой архитектуры.
На некоторых архитектурах в частности на ARM такое решение будет более эффективным, за счет сокращения обращений к APB.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 29 2008, 10:33
Сообщение #10


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 29 2008, 19:03
Сообщение #11


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(GetSmart @ Jun 29 2008, 13:33) *
Почему слепая? Простая нормальная инверсия.

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

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

Загрузка адресных регистров есть и там и там. Или есть способ обратиться к APB без загрузки адреса?
Забыли учесть возможное наличие кеш памяти, и то, что такты APB и такты процессора могут быть разной длительности.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 29 2008, 19:32
Сообщение #12


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(defunct)
Загрузка адресных регистров есть и там и там. Или есть способ обратиться к APB без загрузки адреса?
Изменение пина (через любой из IOPIN, IOSET, IOCLR) уже загружает адресный регистр, поэтому дополнительное чтение IOSET ничего не требует, в отличие от переменной в раме.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 23:33
Рейтинг@Mail.ru


Страница сгенерированна за 0.01445 секунд с 7
ELECTRONIX ©2004-2016