Перейти к содержанию
    

Вы хоть смотрели, как работают биты в регистре BSRR? Вся ваша галиматья не к месту.

Ага, вижу, посмотрели таки! Гуд! Теперь согласны насчет галиматьи?

Всё равно если есть возможность - это лучше чем если её нет. А применение найдётся.

 

Атомарность внутри процессора.

Ну почему-же.

Если нет функции инверсии бита, а нужна именно инверсия, то как быть?

Напишем что-то типа:

if (PinOutputState()) PinReset();

else PinSet();

Если это не сделать атомарным (не завернуть в критическую секцию), а в программе данный пин управляется в разных задачах/ISR, то возможны коллизии.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если это не сделать атомарным (не завернуть в критическую секцию), а в программе данный пин управляется в разных задачах/ISR, то возможны коллизии.

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

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Этот пример мимо, ибо в данном случае идет речь о регистре BSRR и операциях с одним пином. Если изменение состояния пинов сделано через BSRR, то все будет прекрасно работать в двух потоках :) Проблема может быть только если оба потока пытаются управлять одним и тем же пином, но это без какой-либо синхронизации не правильно по своей сути.
Если у бабки были бы яйца... Только я в своем примере указал GPIO_ToggleBits() от стм, а они пользуют ODR, а не BSRR. а так согласен, запись в BSRR не создаст колизии, и тем не мение, осутствие аппаратного тогла требует лишней проверки выхода.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Ну вот например:

У Вас параллельная шина от Вашего МК к другому устройству, работает через GPIO, несколько сигналов данных и один - квитирования.

Работает как шина DDR - т.е. обновление данных на шине фиксируется не по фронту или спаду, а по перепаду сигнала квитирования. Так получается можно быстрее данные передавать.

А теперь представим, что для быстрого вывода на эту шину мы и линии данных и сигнал квитирования расположили в одном порту.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у тебя как это сделано?

Я сначала тоже пробовал bitband, но без структуры, как у тебя, потому выигрыш был, но не такой заметный чтобы инлайнить полную инициализацию, а в дебаге размер вырос весьма значительно, плюс потеря поддержки F0. Потому в итоге остановился на отдельно функции инита, а встраивается только ее вызов. Внутри типичный код, который используется практически везде: читаем из MODER и пишем обратно(для F0 по-другому и не получится). Но проблема никуда не делась, хотя промежуточных состояний больше нет, в прерывании или другом потоке может быть изменен сам MODER и тогда будет записано старое, не измененное значение. Если это актуально, то можно написать потокобезопасные версии функций, которые будут запрещать прерывания на время модификаций всех 4-х регистров(и ODR), лично мне они пока не были нужны, т.к. до сих пор обходился прерываниями и регистры задающие режимы gpio в них не менял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если у бабки были бы яйца... Только я в своем примере указал GPIO_ToggleBits() от стм, а они пользуют ODR, а не BSRR. а так согласен, запись в BSRR не создаст колизии, и тем не мение, осутствие аппаратного тогла требует лишней проверки выхода.

Что у стм не знаю, извиняюсь, но не пользовался никогда. Проверка (если Вы про ? или if) не обязательна, я уже приводил пример:

Для внешнего устройства по идее достаточно (скажем для битов 0 и 7):

GPIOx->BSRR = (~GPIOx->IDR & 0x81) | 0x00810000;

 

Если же Вы про чтение порта, то я уже писал, что это плюс для аппаратного тоггла.

 

Ну вот например:

У Вас параллельная шина от Вашего МК к другому устройству, работает через GPIO, несколько сигналов данных и один - квитирования.

Работает как шина DDR - т.е. обновление данных на шине фиксируется не по фронту или спаду, а по перепаду сигнала квитирования. Так получается можно быстрее данные передавать.

А теперь представим, что для быстрого вывода на эту шину мы и линии данных и сигнал квитирования расположили в одном порту.

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

Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример".

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример".

Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь.

Не, я не про то, подредактировал свой вопрос и уточнил про какой "порт" я говорил:

Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что у стм не знаю, извиняюсь, но не пользовался никогда. Проверка (если Вы про ? или if) не обязательна, я уже приводил пример:

Для внешнего устройства по идее достаточно (скажем для битов 0 и 7):

GPIOx->BSRR = (~GPIOx->IDR & 0x81) | 0x00810000;

а это разве не проверка?

1)читаем GPIOx->IDR (только правильнее будет ODR)

2)инвертируем ~GPIOx->IDR

3)& 0x81

4)| 0x00810000

5)записываем BSRR

хотя согласен, для более одного пина, ваш вариант лучше, чем явные ? и if

 

 

с аппаратным тогл, как в XMC4700/4800

1)GPIOx->BSRR = 0x0081'0081;//одна операция!!!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь.

Запись атомарна, но в условии задачи указано "сигнал квитирования надо инвертировать". А значит на STM одной операцией записи не обойтись.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Запись атомарна, но в условии задачи указано "сигнал квитирования надо инвертировать". А значит на STM одной операцией записи не обойтись.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример".

Понятно, что пример синтетический. В реальной практике у меня такой задачи не было.

Но вот например у Вас есть внешняя память (SDRAM) скажем на нормальной шине. Вы же пишете в неё из разных задач/ISR не задумываясь об атомарности - это всё сделано на аппаратном уровне. Полезность такой записи из разных задач очевидна?

А теперь представьте, что в МК нет внешней шины, или что эта шина не поддерживает устройство в которое надо писать. А это устройство имеет интерфейс, подобный DDR.

И пакетные записи не нужны - каждая запись имеет значение (собственно этой записью передаётся некая команда в устройство).

Все возможные схемы представить сложно, но имхо это - вполне жизненный вариант.

 

У меня когда-то давно была практическая задача подобная этой, но там правда не надо было обращаться к шине из разных задач, но нужно было как можно быстрее передавать по такой шине. И при этом - на данном порту были ещё другие пины, которые трогать было нельзя.

И в таком случае с регистром BSRR STM32 можно конечно реализовать такую передачу, но реализация получается более громоздкой чем на Infineon или LPC.

 

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

Зачем добавлять??? На Infineon я прекрасно и устанавливаю и сбрасываю и инвертирую пины одной операцией записи.

BSRR = 1 << pin; //установка

BSRR = 1 << pin + 16; //сброс

BSRR = 0x10001 << pin; //инверсия

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем добавлять??? На Infineon я прекрасно и устанавливаю и сбрасываю и инвертирую пины одной операцией записи.

Речь про STM32, у него только BSRR который дает возможность атомарно записать группу битов не затрагивая остальные пины. Если эту его способность заменить атомарной инверсией, то пользы будет меньше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все возможные схемы представить сложно, но имхо это - вполне жизненный вариант.

Да, если пакет помещается в одну операцию, то возможно, хотя и несколько "притянуто". В этом варианте аппаратный тоггл рулит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...