Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Самопроизвольное изменение значения переменной

Чт мар 23, 2023 19:47:46

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

Дано: STM32G041J6M6, для управления WS2812B.
Проблема: в функции WS2812B_fill_buf при наступлении условия k=1, при заполнении G-составляющей, при i=1 происходит самопроизвольное присвоение переменной tim_stat значением 0x19. И естественно ничего не работает. В коде в данном месте, явно нет такого присвоения, как такое может быть?

ws2812.h




ws2812.c



Добавлено after 2 minutes 5 seconds:
Прошу прощения за дубликат, что-то пошло не так

Re: Самопроизвольное изменение значения переменной

Чт мар 23, 2023 20:17:35

Разаер uint8_t led_buf[BUF_LEN] равен 25 элементов(байт). Что будет тут buf[k*24+i] = WS2812_0; при k=1 и i=1?

Счётчики циклов не надо делать __IO. Да и вообще, грязненько написано ещё много где.

Добавлено after 4 minutes 18 seconds:
TIM17->SR &= ~TIM_SR_UIF; - анафема.
GPIOB->BSRR |= GPIO_BSRR_BR0; - вечное проклятие.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 00:42:43

Разаер uint8_t led_buf[BUF_LEN] равен 25 элементов(байт). Что...


спасибо за ответ, но так как я не профи(не занимаюсь коммерческой деятельностью в области микроконтроллеров, это мое хобби) возникло еще большее недопонимание:TIM17->SR &= ~TIM_SR_UIF; - анафема за что? в данной строчке я подразумевал простое снятие флага (было прерывание, выставлен флаг, его надо снять) разве не так? если можете поясните в чем не прав.
GPIOB->BSRR |= GPIO_BSRR_BR0; и за что ту вечное проклятие, подскажите более интересный способ сбросить бит.

"Разаер uint8_t led_buf[BUF_LEN] равен 25 элементов(байт). Что будет тут buf[k*24+i] = WS2812_0; при k=1 и i=1?" ага... переполнение (надеюсь правильно понял) тут пошел думать. А почему счетчик циклов не надо делать __IO ?
Ну если есть возможность обЪяснить эту конструкцию __IO, я то так понял шо это команда компилятору, мол компилируй и не оптимизируй эту штуку, ну как-то так.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 01:53:13

- анафема за что?
и за что ту вечное проклятие
За непрочтение RM на предмет того как работать с битами регистров TIMx->SR и GPIOx->BSRR и соответственно неправильное применения операторов &= и |= к ним. В первом регистре флаги сбрасываются записью ноля, а втрой вообще только для записи.
А почему счетчик циклов не надо делать __IO ?
Ну если есть возможность обЪяснить эту конструкцию __IO, я то так понял шо это команда компилятору, мол компилируй и не оптимизируй эту штуку, ну как-то так.
Ну и откуда взялось желание сказать компилятору "не оптимизируй счётчик циклов"? Бывают случаи, когда это действительно нужно, но тут то зачем? Хотелось бы услышать ваши рассуждения по этому поводу.

Добавлено after 28 minutes 32 seconds:
Ещё интересно было бы узнать, что по вашему замыслу делает команда (void)tmp; ? Почему она где-то __IO, а где-то нет? И кто вам рассказал, что нужно делать /* Delay after an RCC peripheral clock enabling */?

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 06:07:45

VladislavS писал(а):Ну если есть возможность обЪяснить эту конструкцию __IO, я то так понял шо это команда компилятору, мол компилируй и не оптимизируй эту штуку, ну как-то так.

Компилятор в праве удалить любые переменные и операции с ними - если они ограничиваются областью видимости функции.
Область видимости функции ограничена скобками самой функции, буквально. По этому любая запись во внешнюю переменную будет безусловной, и на неё необязательно вешать __IO.
По поводу кода.
Постарайся раскидать функции по уровням и типу действия. Например RCC_Cfg() и GPIO_test_cfg() относятся к предварительным настройкам МК, этим функциям самое место в SystemInit() или что-то подобное - то вызывается до main.c. WS2812_init() и всё связанное с WS2812 - должно иметь свой файл, без лишних торчащих ушей. Делать буфер для WS2812 глобальным - очень плохая идея, он должен быть виден там где используется, и больше нигде. Тогда станет доступной возможность оперативно менять количество светодиодов, без смены алгоритма и переписывания части кода.

И кстати, WS2812 длинная пауза в единице - автоматически применяет полученные данные, даже если они были неполные.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 06:30:42

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

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 07:14:20

Компилятор в праве удалить...
Постарайся раскидать функции...
И кстати, WS2812 длинная пауза в единице...


Спасибо, этого я не знал,
Раскидать по разным модулям это для меня еще сложно, есть непонимание в обмене данными между этими модулями(static, extern) где как обьявлять переменные, с этим буду позже разбираться, да и програмки у меня пока не большие.
WS2812 в DS написано RET Code 0 более 50us, а про единичку не знал, попробую.

Добавлено after 26 minutes 12 seconds:
- анафема за что?
и за что ту вечное проклятие
За непрочтение RM на предмет того как работать с битами регистров TIMx->SR и GPIOx->BSRR и соответственно неправильное применения операторов &= и |= к ним. В первом регистре флаги сбрасываются записью ноля, а втрой вообще только для записи.
А почему счетчик циклов не надо делать __IO ?
Ну если есть возможность обЪяснить эту конструкцию __IO, я то так понял шо это команда компилятору, мол компилируй и не оптимизируй эту штуку, ну как-то так.
Ну и откуда взялось желание сказать компилятору "не оптимизируй счётчик циклов"? Бывают случаи, когда это действительно нужно, но тут то зачем? Хотелось бы услышать ваши рассуждения по этому поводу.

Добавлено after 28 minutes 32 seconds:
Ещё интересно было бы узнать, что по вашему замыслу делает команда (void)tmp; ? Почему она где-то __IO, а где-то нет? И кто вам рассказал, что нужно делать /* Delay after an RCC peripheral clock enabling */?


Про BSRR я знаю, что только для записи 1 (биты 0-15 для установки, а 16-31 для сброса) , так и в коде у меня только запись единички в этот регистр или про BSRR я опять не правильно понимаю?
По поводу SR записью 0, а логическое & инвертированного TIM_SR_UIF разве не есть запись нолика?
Про счетчик циклов, как-то столкнулся с проблемкой, по поводу переменной счетчика. Пока не нарисовал ей __IO не работало, ну с тех пор так и привык. Сейчас проверил конкретно в данной программе , убрал __IO работает. Спасибо, записал на память, при случае буду изучать этот вопрос до полного понимания

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 07:23:31

Компилятор в праве удалить любые переменные и операции с ними - если они ограничиваются областью видимости функции.
Область видимости функции ограничена скобками самой функции, буквально. По этому любая запись во внешнюю переменную будет безусловной, и на неё необязательно вешать __IO.
Я немного понимаю в программировании. Но из этого вообще ничего не понял.

Постарайся раскидать функции по уровням и типу действия. Например RCC_Cfg() и GPIO_test_cfg() относятся к предварительным настройкам МК, этим функциям самое место в SystemInit() или что-то подобное - то вызывается до main.c.
Тут, пожалуй, соглашучь. Но для любителя это не обязательно. Считать что "жизнь начинается с main" для С-программиста вполне нормальная практика. Качество кода это как-то заметно не ухудшает.

WS2812_init() и всё связанное с WS2812 - должно иметь свой файл, без лишних торчащих ушей.
Иметь файл, торчащие уши... Вы о чём вообще? Человек и так не профи, да ещё жаргон какой-то понять надо.

Делать буфер для WS2812 глобальным - очень плохая идея, он должен быть виден там где используется, и больше нигде.
А каки же как не глобальным он должен быть? Вы, наверное, глобальность с областью видимости путаете? Так тут одна единица трансляции, куда что прятать?

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

По мне, так только запутали бедного ТС. Дайте ему с алгоритмом для начала разобраться.

Добавлено after 4 minutes 29 seconds:
Про BSRR я знаю, что только для записи 1 (биты 0-15 для установки, а 16-31 для сброса) , так и в коде у меня только запись единички в этот регистр или про BSRR я опять не правильно понимаю?
По поводу SR записью 0, а логическое & инвертированного TIM_SR_UIF разве не есть запись нолика?
Ну тогда всё ещё хуже. Стоит открыть учебник по С раздел про операторы |= и &= - удивитесь.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 07:55:53

Ой... ваще поплыл.
Для начала:
запись GPIOC->BSRR |= GPIO_BSRR_BR0 сбросит нулевой бит в регистре, а GPIOC->BSRR |= GPIO_BSRR_BS0 установит нулевой бит в регистре. Это я правильно понимаю?

Добавлено after 5 minutes 10 seconds:
Ида по поводу (void)tmp это когда я переписывал инициализацию с автоматически сгенерированного CubeMX файла там используется библиотека LL, а мне нравится CMSIS. Так там и была эта конструкция, задержка после включения.

Добавлено after 9 minutes 35 seconds:
Разаер uint8_t led_buf[BUF_LEN] равен 25 элементов(байт). Что будет тут buf[k*24+i] = WS2812_0; при k=1 и i=1?


Разобрался, заработало!
Осталось избавиться от анафемы и снять вечное проклятие.

Огромное спасибо!

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 08:25:44

Ой... ваще поплыл.
Для начала:
запись GPIOC->BSRR |= GPIO_BSRR_BR0 сбросит нулевой бит в регистре, а GPIOC->BSRR |= GPIO_BSRR_BS0 установит нулевой бит в регистре. Это я правильно понимаю?

Нет, не правильно понимаете.
Написанное вами выражение означает не запись единицы, а последовательное выполнение: ЧТЕНИЕ РЕГИСТРА (который возвращает только нули, ибо не подлежит чтению,), логическая функция результата чтения с маской и запись обратно в регистр.
НАМЕКАЮ. Запись в такие регистры должна иметь ТОЛЬКО ПРИСВОЕНИЕ ЗНАЧЕНИЯ. Без какой либо математики с содержимым этого регистра.
Последний раз редактировалось КРАМ Пт мар 24, 2023 08:44:05, всего редактировалось 2 раз(а).

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 08:37:28

(который возвращает только нули, ибо не подлежит чтению,)
Это где-то написано/гарантировано? Я бы на месте разработчиков контроллера возвращал рандомное значение. Чисто поприкалываться над "любителями CMSIS".

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 08:39:16

Чисто поприкалываться над "любителями CMSIS".

Согласен. Не гарантировано. Но возвращает. Итальянцы с французами не понимают таких приколов.
Однако, я один из "любителей CMSIS". Это никак не мешает читать RM и не делать таких ошибок.
А если точнее, то мне, как радиоинженеру, не близки ваши предпочтения как программиста. И это тоже не мешает мне успешно делать проекты.
ЗЫ. В догон. Я нынче предпочитаю Artery европейским МК. По известным причинам.
А там регистры объявлены как битовые структуры. То есть не надо писать с масками.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 08:53:05

То есть правильно будет GPIOB->BSRR = GPIO_BSRR_BS0 для установки, а для сброса GPIOB->BSRR = GPIO_BSRR_BR0. Ну и по SR TIM17->SR = ~TIM_SR_UIF.
Мне кажется я смог избавиться от анафемы и вечного проклятия. Спасибо.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 08:58:21

То есть правильно будет GPIOB->BSRR = GPIO_BSRR_BS0 для установки, а для сброса GPIOB->BSRR = GPIO_BSRR_BR0.
Конечно. Для закрепления результата посмотрите ассемблерный листинг с |= и с =.

Ну и по SR TIM17->SR = ~TIM_SR_UIF.
Так можно, но так ведь проще SR TIM17->SR = 0; Опять же, загляните в листинг.

Мне кажется я смог избавиться от анафемы и вечного проклятия.
Тут только трёхкратное прочтение K&R спасёт.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 09:21:31

Что? Опять? Как так-то?
SR TIM17->SR = 0 я понимаю это обнулит весь регистр (сбросит все флаги), а если мне надо обнулить определенный флаг?
SR TIM17->SR = ~TIM_SR_UIF Это не сработает?

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 09:37:10

зачем хранить прошлогодние флаги?

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 10:01:35

Маска на сброс флага это нормально. Не путайте человека.
Учитывая, что вектора прерываний таймеров не избирательны на флаги, на входе в обработчик ставят семафор, который эти флаги и проверяет.
Немаскируемый сброс флагов приведет к потере событий.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 10:30:11

дык, обычно то, берешь SR проверяешь нужный флаг, проверяешь дополнительный (типа "не произошло ли еще что-то", что нужно учитывать). и зачем оставлять SR у таймера?

у более сложной периферии, вероятно, так огульно не следует, но (честно говоря) я о ней сразу не подумал - перед глазами был TIM.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 11:22:33

дык, обычно то, берешь SR проверяешь нужный флаг, проверяешь дополнительный

А не проще и удобнее в начале каждой секции семафора проверять и сбрасывать единственный флаг?
В чем проблема? Что малочитабельного в маске? Дело ведь не в маске, а в месте ее применения. Не стоит же всех считать идиотами не способными сообразить, что в семафоре проверяется и сбрасывается флаг сгенерировавший прерывание. Тем более, что маска при проверке флага и при его сбросе идентична.
Ну и немаловажна латентность между проверкой флага и его сбросом, если сброс выполняется "оптом". Так и пропустить событие несложно.

Re: Самопроизвольное изменение значения переменной

Пт мар 24, 2023 13:02:04

VladislavS писал(а):Я немного понимаю в программировании. Но из этого вообще ничего не понял.

Не ожидал :shock: .
Функцию придумали для выполнения полезной работы над внешними данными. Любая бурная псевдо-деятельность без полезного выхлопа - полностью удаляется компилятором, потому как не влияет на внешнюю память.

Добавлено after 7 minutes 51 second:
Маска на сброс флага это нормально. Не путайте человека.
Учитывая, что вектора прерываний таймеров не избирательны на флаги, на входе в обработчик ставят семафор, который эти флаги и проверяет.
Немаскируемый сброс флагов приведет к потере событий.

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