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

 
 
26 страниц V  « < 18 19 20 21 22 > »   
Reply to this topicStart new topic
> Библиотеки для STM32
Forger
сообщение Apr 20 2017, 07:37
Сообщение #286


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(juvf @ Apr 20 2017, 10:32) *
тогел потоко не защищённый. Осторожно, тут мины!! ))

Я же говорил, что к одному и тому же пину у меня в коде НИКОГДА нет обращения их РАЗНЫХ потоков.
Это исключено еще на этапе построения проекта.
Поэтому не будет ничего страшного, если кто-то прервет эту строчку с ODR.
В крайнем случае могу использовать CriticalSection, если нужно сохранить строгую последовательность некого пинодрыга, но пока еще с таким я не сталкивался.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 20 2017, 07:37
Сообщение #287


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



ЕМНИП, в компиляторе Hi-Tech для PIC тип char был беззнаковый по умолчанию, но можно было задать знаковый. К спору об int не относится, с ним ясно всем, кроме одного. rolleyes.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 20 2017, 07:42
Сообщение #288


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Forger @ Apr 20 2017, 12:28) *
Цитата(juvf @ Apr 20 2017, 12:21) *

вы в одном потоке дергаете cs? который есть PA13, а в другом потомке маргаете диодом который сидит на PA5.

Ага, я понял к чему вы - я имел ввиду не порт, а пин.
Но и в данном случае проблем тоже не будет - в MODER пишется маска, меняющая всего лишь ОДИН соотв. бит, а не группу битов.

Ничего вы не поняли.
В вашем коде две проблемы:
1. Проблема с двухэтапной записью в MODER. Выше уже очень хорошо объяснили, что это нехорошо. Потому что ножка переводится в промежуточное состояние, которое может быть нежелательным. И при возникновении прерывания между двумя записями ножка может остаться в этом состоянии достаточно продолжительное время. Этого может быть достаточно, чтобы что-нибудь сжечь. Это реальная мина, потому что на столе может всё работать, а в продакшене может рвануть.

2. Проблема с неатомарностью операции GPIOA->ODR ^= bit. (Об этом вам пишет juvf). Дело в том, что если такие операции выполняются одновременно из разных потоков (к разным битам одного порта), то возможны сбои. Разжёвывать не буду, гуглите.

ЗЫ. Рано вы взялись за "Чистый код". Надо было сначала основы подтянуть.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Forger
сообщение Apr 20 2017, 07:49
Сообщение #289


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(AHTOXA @ Apr 20 2017, 10:42) *
1. Проблема с двухэтапной записью в MODER. Выше уже очень хорошо объяснили, что это нехорошо. Потому что ножка переводится в промежуточное состояние, которое может быть нежелательным. И при возникновении прерывания между двумя записями ножка может остаться в этом состоянии достаточно продолжительное время. Этого может быть достаточно, чтобы что-нибудь сжечь. Это реальная мина, потому что на столе может всё работать, а в продакшене может рвануть.
В моих схемах ни одна ножка не висит в воздухе, всегда есть внешняя подтяжка, это связано с непредсказуемым поведение схемы, пока проц в состоянии сброса или прошивается.
Поэтому в моих проектах это не создает никаких проблем ))
Внутренние пуллапы может быть и полезны разве что для входных пинов, т.е. те, которые всегда настроены на вход.

Цитата
2. Проблема с неатомарностью операции GPIOA->ODR ^= bit. (Об этом вам пишет juvf). Дело в том, что если такие операции выполняются одновременно из разных потоков (к разным битам одного порта), то возможны сбои. Разжёвывать не буду, гуглите.
Вы хотите сказать, что операция обращения к ODR неатомарнае, например, копирование из регистра R2 -> [R3], где R3 хранит адрес ODR-регистра?
Вы точно ничего не путаете?


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
juvf
сообщение Apr 20 2017, 07:51
Сообщение #290


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(Forger @ Apr 20 2017, 12:37) *
Я же говорил, что к одному и тому же пину у меня в коде НИКОГДА нет обращения их РАЗНЫХ потоков.
Это исключено еще на этапе построения проекта.
Поэтому не будет ничего страшного, если кто-то прервет эту строчку с ODR.
В крайнем случае могу использовать CriticalSection, если нужно сохранить строгую последовательность некого пинодрыга, но пока еще с таким я не сталкивался.

просто ужос!!!! такие элементарные вещи... вроде разживал все... выделил жирным шрифтом, что при изменении РАЗНЫХ ПИНОВ РАЗНЫХ!!!
ну не видите вы сами... я же вам привел пример... РА15 и РА5

пошагам.... пусть cs будет РА1, а led будет PA4. воспользуемся литералом b. для кратности пусть порт будет 8 бит. изночально в ODR 0b0000'0000
вы в одном поторке выитали ODR, он равен нулю. второй поток прервал первый. второй поток вычитал ODR и добавил туда cs, стало 0b0000'0010. теперь записал это в ODR. Сs стал "1". Вернулись в первый поток... 0b0000'0000 добавили бит светодиода, получили 0b0001'0000 - записали в ODR - всё!!! CS сбросился! Упс!!!

раз вы пишете на RTOS, должны знать про неатомарные операции

Цитата
Вы хотите сказать, что операция обращения к ODR неатомарная, например, копирование из регистра R2 -> [R3], где R3 хранит адрес ODR-регистра?
БИНГО!!!!
Go to the top of the page
 
+Quote Post
Reflector
сообщение Apr 20 2017, 07:56
Сообщение #291


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836



Цитата(juvf @ Apr 20 2017, 06:50) *
естественно.... так же как и в шаблонах/классах

Для класса ты пишешь всякие on/off один раз и они точно будут рабочие. На макросах ты пишешь намного больше и можешь случайно ошибиться:
Код
#define csOn() (GPIOA->BSRR = GPIOA_BSRR_BR4)
#define csOff() (GPIOA->BSRR = GPIOA_BSRR_BS4)

#define led1On() (GPIOA->BSRR = GPIOA_BSRR_BR5)
#define led1Off() (GPIOA->BSRR = GPIOA_BSRR_BS5)
...


Цитата
чего?

На радиокоте недавно спрашивали как записать 7 бит заданного байта в PD9, 5 бит в РВ4 и т.д.... Дали парочку ответов, лучший из которых выглядит так:
Код
GPIOD->BSRR = b & 0x80 ? GPIO_BSRR_BS9 : GPIO_BSRR_BR9;
GPIOB->BSRR = b & 0x20 ? GPIO_BSRR_BS4 : GPIO_BSRR_BR4;

Шаблонный код мог бы быть таким:
Код
GpioD<9>::write(b & 0x80);
GpioB<4>::write(b & 0x20);

Он понятнее и эффективнее, т.к. никаких проверок в нем нет.

Цитата
я затронул только переключение бита. инит нужен. его можно и функцией, и макросом, можно классом...можно сразу хором весь порт GPIOA проинитить.... это как вам угодно.

Речь про инит, который уже написан, отлажен и привязан к конкретному пину. Возьмем, для примера, USART. У некоторых популярных мк их по 6 штук, каждому нужно инитить ноги, большинству нужно 3 параметра для каждого пина, у STM32F1 их 2, но там инициализация немного другая... Какая сущность должна всем этим заниматься? Должен ли я для каждого USARTа закопать инициализацию пинов в какой-то общей функции инициализации? Считаю, что не должен, потому делаю так:
Код
Usart1<> usart1;
Usart6<> usart6;

usart1.init<PinA<9, 7>, PinA<10, 7>>(2457600);
usart6.init<PinC<6, 8>, PinC<7, 8>>(115200);

Не нравится прописывать пины прямо тут, выносим их куда угодно
Код
using USART1_TX = PinA<9, 7>;
using USART1_RX = PinA<10, 7>;

usart1.init<USART1_TX, USART1_RX>>(2457600);


Цитата
Я просто хочу сказать, что не нужно думать бинарно.... у вас либо 0, либо 1. Либо С++ с ООП в полный рост безоговорочно.... с оверинженерингом, либо если один макрос или литерал воткнут - то это непрофессионализм. Использование стандартного литерала х и b - это фу фу фу, магическая цифра.... зато SIGNED32 (при чем с миной) - это круть!!!!

Здорово, особенно учитывая, что про бинарные литералы в С++ тебе рассказал именно я sm.gif
Go to the top of the page
 
+Quote Post
juvf
сообщение Apr 20 2017, 08:21
Сообщение #292


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(Reflector @ Apr 20 2017, 12:56) *
....
Даже коментировать тут нечего.... Полемика. Ну я же говорю, бинарно мыслите... при чем тут уарт? я вам сказал что макросы ВЕЗДЕ лучше классов/шаблонов?


Цитата(Reflector @ Apr 20 2017, 12:56) *
На радиокоте недавно спрашивали как записать 7 бит заданного байта в PD9, 5 бит в РВ4 и т.д.... Дали парочку ответов, лучший из которых выглядит так:
Код
GPIOD->BSRR = b & 0x80 ? GPIO_BSRR_BS9 : GPIO_BSRR_BR9;
GPIOB->BSRR = b & 0x20 ? GPIO_BSRR_BS4 : GPIO_BSRR_BR4;

Шаблонный код мог бы быть таким:
Код
GpioD<9>::write(b & 0x80);
GpioB<4>::write(b & 0x20);

Он понятнее и эффективнее, т.к. никаких проверок в нем нет.
я бы не так сделал. была подобная задача.
Go to the top of the page
 
+Quote Post
Forger
сообщение Apr 20 2017, 08:28
Сообщение #293


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(juvf @ Apr 20 2017, 10:51) *
...

Так глубоко в компилятор я не влезал, щас влез в asm код, который нагенерил компилятор для toggle() ...
Действительно, возможны глюки, надо переписывать!
Вот и баги нашлись smile3046.gif
Хотя до сих пор, проблем не было, но это - вопрос времени, нужно обязательно переделать!

Есть идеи, как переделать void toggle() { port->ODR ^= pinMask; }, избежав критических секций?

зы. Пока писал, нашел простое на мой взгляд решение - некий более старший в иерархии класс Port, который уже будет предоставлять функционал Pin более потоко-безопасно.
К тому же этот Port сможет предоставить возможность массовой настройки пинов (например, подключена внешняя память на параллельной шине).


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Reflector
сообщение Apr 20 2017, 08:36
Сообщение #294


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836



Цитата(juvf @ Apr 20 2017, 11:11) *
Даже коментировать тут нечего.... Полемика. Ну я же говорю, бинарно мыслите... при чем тут уарт? я вам сказал что макросы ВЕЗДЕ лучше классов/шаблонов?

Был тут уже один товарищ с критикой, я ему предложил написать аналог инициализации портов FSMC двумя строками, ты видел ответ? Так и тут... Начинается с того, что задефайнить csOn()/csOff() и прочие максросы проще простого, как и проинитить, а ты покажи полную инициализацию пинов хотя бы пары усартов, тогда будет с чем сравнивать. Имеется в виду количество кода который придется написать для каждого нового усарта в проекте.

Цитата
я бы не так сделал. была подобная задача.

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

Сообщение отредактировал Reflector - Apr 20 2017, 08:37
Go to the top of the page
 
+Quote Post
juvf
сообщение Apr 20 2017, 08:55
Сообщение #295


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(Forger @ Apr 20 2017, 13:28) *
Есть идеи, как переделать void toggle() { port->ODR ^= pinMask; }, избежав критических секций?

Навскидку...

Код
void toggle() { port->BSRR = (port->ODR & pinMask) == 0 ? pinMask : pinMask << 16; }




Цитата
зы. Пока писал, нашел простое на мой взгляд решение - некий более старший в иерархии класс Port, который уже будет предоставлять функционал Pin более потоко-безопасно.
К тому же этот Port сможет предоставить возможность массовой настройки пинов (например, подключена внешняя память на параллельной шине).
!!! Извини.... но блин.... это всего лишь ногой дёрнуть!!! ))))))))))))
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 20 2017, 08:56
Сообщение #296


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Forger @ Apr 20 2017, 13:28) *
Есть идеи, как переделать void toggle() { port->ODR ^= pinMask; }, избежав критических секций?

Можно использовать bit-band для реализации cpl(). У меня так.
(К сожалению, для stm32L0x - не сработает, там нет bin-band для GPIO).

Да и ерунда всё это, на самом деле. Я лично не помню, чтобы где-то использовал cpl(), кроме тестов. Всегда нужно переводить ножку в какое-то определённое состояние.



--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
juvf
сообщение Apr 20 2017, 09:08
Сообщение #297


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(AHTOXA @ Apr 20 2017, 13:56) *
Да и ерунда всё это, на самом деле. Я лично не помню, чтобы где-то использовал cpl(), кроме тестов.

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

ps ещё програмный меандр выдавать.... можно найти применение cpl-ю
Go to the top of the page
 
+Quote Post
Reflector
сообщение Apr 20 2017, 09:09
Сообщение #298


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 15-07-06
Пользователь №: 18 836



Цитата(juvf @ Apr 20 2017, 11:55) *
Навскидку...

Код
void toggle() { port->BSRR = (port->ODR & pinMask) == 0 ? pinMask : pinMask << 16; }

Ага, но только что я приводил пример практически такого-же кода, как не самого эффективного, т.к. там будет проверка.
Код
redLed.write(!redLed.read());

То же самое, но без лишней инструкции ITE.
ps. Упс, сорри, это совсем не тоже самое, т.к. читает с IDR sm.gif Но сути это не меняет, меняем IDR на ODR, но код прячем внутри класса.

Код
gpio->BSRR = (0x10000 << pin) | (!(gpio->ODR & (1 << pin)) << pin);

У F0 ITE нет, там проверки еще более тяжелые.

Сообщение отредактировал Reflector - Apr 20 2017, 09:34
Go to the top of the page
 
+Quote Post
Forger
сообщение Apr 20 2017, 09:15
Сообщение #299


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(juvf @ Apr 20 2017, 11:55) *
Код
void toggle() { port->BSRR = (port->ODR & pinMask) == 0 ? pinMask : pinMask << 16; }

Как вариант ))

Но я предпочитаю более читаемо:
Код
void toggle() { if (isLow()) setToHigh(); else setToLow(); }


Впрочем, этот toggle (добавил совсем недавно) у меня пока что использовался лишь для моргания лампочкой, поэтому багов не было.
Но исправить все же нужно, дабы больше не возвращаться к этому вопросу.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 20 2017, 09:18
Сообщение #300


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(juvf @ Apr 20 2017, 14:08) *
есть проект, где светодиод мигает, показывая живучесть системы. не было cpl, использовал с дополнительным флагом сет/ресет. А так бы было бы удобно cpl.

ps ещё програмный меандр выдавать.... можно найти применение cpl-ю


Ну тогда bit-band. Есть везде, кроме L0.

ЗЫ. Я там вам ответил про варианты pin.h, возможно вы проглядели (тема растёт очень быстро).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

26 страниц V  « < 18 19 20 21 22 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 17th August 2025 - 20:08
Рейтинг@Mail.ru


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