jcxz 242 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Вы хоть смотрели, как работают биты в регистре BSRR? Вся ваша галиматья не к месту. Ага, вижу, посмотрели таки! Гуд! Теперь согласны насчет галиматьи? Всё равно если есть возможность - это лучше чем если её нет. А применение найдётся. Атомарность внутри процессора. Ну почему-же. Если нет функции инверсии бита, а нужна именно инверсия, то как быть? Напишем что-то типа: if (PinOutputState()) PinReset(); else PinSet(); Если это не сделать атомарным (не завернуть в критическую секцию), а в программе данный пин управляется в разных задачах/ISR, то возможны коллизии. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 21 апреля, 2017 Опубликовано 21 апреля, 2017 (изменено) · Жалоба Если это не сделать атомарным (не завернуть в критическую секцию), а в программе данный пин управляется в разных задачах/ISR, то возможны коллизии. Это понятно, но я смотрю немного на более высокий уровень - какой смысл управлять одним и тем же пином из разных задач без какой-либо синхронизации? Как по мне, то никакого, а если делается синхронизация, то и проблемы нет. Вот когда речь идет про порт и управление разными пинами, то это очень реальный вариант, а с одним пином... Изменено 21 апреля, 2017 пользователем Шаманъ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Этот пример мимо, ибо в данном случае идет речь о регистре BSRR и операциях с одним пином. Если изменение состояния пинов сделано через BSRR, то все будет прекрасно работать в двух потоках :) Проблема может быть только если оба потока пытаются управлять одним и тем же пином, но это без какой-либо синхронизации не правильно по своей сути.Если у бабки были бы яйца... Только я в своем примере указал GPIO_ToggleBits() от стм, а они пользуют ODR, а не BSRR. а так согласен, запись в BSRR не создаст колизии, и тем не мение, осутствие аппаратного тогла требует лишней проверки выхода. какой смысл управлять одним и тем же пином из разных задач без какой-либо синхронизации?я не имел в виду одним пином. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Это понятно, но я смотрю немного на более высокий уровень - какой смысл управлять одним и тем же пином из разных задач без какой-либо синхронизации? Как по мне, то никакого, а если делается синхронизация, то и проблемы нет. Вот когда речь идет про порт и управление разными пинами, то это очень реальный вариант, а с одним пином... Ну вот например: У Вас параллельная шина от Вашего МК к другому устройству, работает через GPIO, несколько сигналов данных и один - квитирования. Работает как шина DDR - т.е. обновление данных на шине фиксируется не по фронту или спаду, а по перепаду сигнала квитирования. Так получается можно быстрее данные передавать. А теперь представим, что для быстрого вывода на эту шину мы и линии данных и сигнал квитирования расположили в одном порту. Тогда чтобы вывести данные на эту шину достаточно одной операции записи. И никакие дополнительные средства обеспечения атомарности не нужны (типа запретов прерываний). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба А у тебя как это сделано? Я сначала тоже пробовал bitband, но без структуры, как у тебя, потому выигрыш был, но не такой заметный чтобы инлайнить полную инициализацию, а в дебаге размер вырос весьма значительно, плюс потеря поддержки F0. Потому в итоге остановился на отдельно функции инита, а встраивается только ее вызов. Внутри типичный код, который используется практически везде: читаем из MODER и пишем обратно(для F0 по-другому и не получится). Но проблема никуда не делась, хотя промежуточных состояний больше нет, в прерывании или другом потоке может быть изменен сам MODER и тогда будет записано старое, не измененное значение. Если это актуально, то можно написать потокобезопасные версии функций, которые будут запрещать прерывания на время модификаций всех 4-х регистров(и ODR), лично мне они пока не были нужны, т.к. до сих пор обходился прерываниями и регистры задающие режимы gpio в них не менял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 21 апреля, 2017 Опубликовано 21 апреля, 2017 (изменено) · Жалоба Если у бабки были бы яйца... Только я в своем примере указал GPIO_ToggleBits() от стм, а они пользуют ODR, а не BSRR. а так согласен, запись в BSRR не создаст колизии, и тем не мение, осутствие аппаратного тогла требует лишней проверки выхода. Что у стм не знаю, извиняюсь, но не пользовался никогда. Проверка (если Вы про ? или if) не обязательна, я уже приводил пример: Для внешнего устройства по идее достаточно (скажем для битов 0 и 7): GPIOx->BSRR = (~GPIOx->IDR & 0x81) | 0x00810000; Если же Вы про чтение порта, то я уже писал, что это плюс для аппаратного тоггла. Ну вот например: У Вас параллельная шина от Вашего МК к другому устройству, работает через GPIO, несколько сигналов данных и один - квитирования. Работает как шина DDR - т.е. обновление данных на шине фиксируется не по фронту или спаду, а по перепаду сигнала квитирования. Так получается можно быстрее данные передавать. А теперь представим, что для быстрого вывода на эту шину мы и линии данных и сигнал квитирования расположили в одном порту. Тогда чтобы вывести данные на эту шину достаточно одной операции записи. И никакие дополнительные средства обеспечения атомарности не нужны (типа запретов прерываний). Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример". Изменено 21 апреля, 2017 пользователем Шаманъ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример". Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь. Не, я не про то, подредактировал свой вопрос и уточнил про какой "порт" я говорил: Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Что у стм не знаю, извиняюсь, но не пользовался никогда. Проверка (если Вы про ? или 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;//одна операция!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Если запись любого числа битов в порт через BSRR атомарна, а она именно такова, то в принципе не нужно задумываться с каким портом в данный момент работаешь. Запись атомарна, но в условии задачи указано "сигнал квитирования надо инвертировать". А значит на STM одной операцией записи не обойтись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Запись атомарна, но в условии задачи указано "сигнал квитирования надо инвертировать". А значит на STM одной операцией записи не обойтись. Это да, но атомарную запись можно получить именно благодаря тому, что при одновременных установке и сбросе бита никакой инверсии нет. Если бы она была пришлось бы добавлять еще один регистр, так что при условии, что подобный регистр всего один была выбрана более полезная его функциональность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Пример несколько футуристический и вызывает много вопросов "зачем?", самый главный - зачем писать данные из двух потоков в один порт без синхронизации (порт в данном случае не GPIO порт, а Ваш "виртуальный" а-ля DDR канал)? Мне кажется такое построение это некоторая ошибка в построении всей архитектуры системы или "синтетический пример". Понятно, что пример синтетический. В реальной практике у меня такой задачи не было. Но вот например у Вас есть внешняя память (SDRAM) скажем на нормальной шине. Вы же пишете в неё из разных задач/ISR не задумываясь об атомарности - это всё сделано на аппаратном уровне. Полезность такой записи из разных задач очевидна? А теперь представьте, что в МК нет внешней шины, или что эта шина не поддерживает устройство в которое надо писать. А это устройство имеет интерфейс, подобный DDR. И пакетные записи не нужны - каждая запись имеет значение (собственно этой записью передаётся некая команда в устройство). Все возможные схемы представить сложно, но имхо это - вполне жизненный вариант. У меня когда-то давно была практическая задача подобная этой, но там правда не надо было обращаться к шине из разных задач, но нужно было как можно быстрее передавать по такой шине. И при этом - на данном порту были ещё другие пины, которые трогать было нельзя. И в таком случае с регистром BSRR STM32 можно конечно реализовать такую передачу, но реализация получается более громоздкой чем на Infineon или LPC. Это да, но атомарную запись можно получить именно благодаря тому, что при одновременных установке и сбросе бита никакой инверсии нет. Если бы она была пришлось бы добавлять еще один регистр, так что при условии, что подобный регистр всего один была выбрана более полезная его функциональность. Зачем добавлять??? На Infineon я прекрасно и устанавливаю и сбрасываю и инвертирую пины одной операцией записи. BSRR = 1 << pin; //установка BSRR = 1 << pin + 16; //сброс BSRR = 0x10001 << pin; //инверсия Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Reflector 0 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Зачем добавлять??? На Infineon я прекрасно и устанавливаю и сбрасываю и инвертирую пины одной операцией записи. Речь про STM32, у него только BSRR который дает возможность атомарно записать группу битов не затрагивая остальные пины. Если эту его способность заменить атомарной инверсией, то пользы будет меньше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба то пользы будет меньше. Почему? Не понимаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Все возможные схемы представить сложно, но имхо это - вполне жизненный вариант. Да, если пакет помещается в одну операцию, то возможно, хотя и несколько "притянуто". В этом варианте аппаратный тоггл рулит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться