Jump to content

    
DpInRock

stm32F030C8 и стирание страницы флэша

Recommended Posts

Может я велосипед изобрел, но вдруг кому надо.

Запись во флэш организована классически.

Стираем страницу и пишем в нее.

Вот все работает нормально до тех пор пока по USART1 (именно USART1) не пойдет символ во время стирания страницы.

В этом случае сабж просто останавливается.

Запреты прерываний не помогают.

Даже после выполнения записи во флэш, если разрешить прерывания - проц тоже останавливается.

При этом никакие другие активные прерывания (таймер 1 мс и USART2) на процесс не влияют никак.

Процедура обработчика USART1 ничего не делает. Просто принимает символ и никуда не отдает. Т.е. совсем просто.

 

В реальности помогает только после запрета прерывания от USART1 - выключить USART младшим битом, а перед разрешением прерываний -

включить и сделать flush через RQR.

Проц работает от внутреннего HSI на частоте 8 Мгц. 

==

Вот такое прямо наблюдение. 

 

 

Share this post


Link to post
Share on other sites
53 minutes ago, DpInRock said:

. . . Процедура обработчика USART1 ничего не делает. Просто принимает символ и никуда не отдает. . . . 

чтение из регистра данных - это не "ничего" :biggrin:

Share this post


Link to post
Share on other sites
1 час назад, DpInRock сказал:

Вот все работает нормально до тех пор пока по USART1 (именно USART1) не пойдет символ во время стирания страницы.

В этом случае сабж просто останавливается.

Так не бывает!

У вас, скорее всего, переполнение приемника случается, а в прерывании вы флаг переполнения не сбрасываете.

Вроде, соответствующая бага в стандартной библиотеке присутствовала...

Share this post


Link to post
Share on other sites
1 час назад, DpInRock сказал:

В этом случае сабж просто останавливается.

Запреты прерываний не помогают.

Даже после выполнения записи во флэш, если разрешить прерывания - проц тоже останавливается.

"Сабж" (МК) не умеет останавливаться. Разве что только все тактирование отключается. Посмотрите под отладчиком, где в это время процессор "крутится".

Share this post


Link to post
Share on other sites

Может останавливаться, если флэш блокируется стирателем.

FLASH->CR |= FLASH_CR_PER;
FLASH->AR = 0x0800FC00;
FLASH->CR |= FLASH_CR_STRT;
RED(1);

Вот после команды FLASH->CR |= FLASH_CR_STRT - все остальные команды не выполняются. (Даже при нахождении этого кода в RAM).
Т.е. проц мгновенно (плюс минус) останавливается. Т.е. исполнение кода останавливается. Где-бы этот код не находился.

Прерывание USART одно - по приему. 

Сам по себе USART все возложенные функции выполняет. Принимает и прочая (не самый простой протокол декодирует).

И работа с флэшем - сама по себе работает.

И что интересно - глобальный запрет прерываний не помогает. Только выключение USART.

А вот выключение NVIC - помогает. Запись во флэш проходит до конца, все хорошо, но при разрешении прерываний тем же NVIC - никакой код нигде не выполняется.

Никаких hard_fault не генерируется. Просто тихо как в морге.

==

И тот же самый код в USART2 - идентичный - никакого вляиния не оказывает.

 (Переделать USART1 в USART2 довольно просто. Циферки поменять практически).

 

 

Share this post


Link to post
Share on other sites

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

RED(1) - показано условно. Там просто прямая установка бита порта.

Байты по через порт идут слитно практически - промежуток между байтами - 2 бита.

Скорость очень маленькая 19200. 

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

Эту хрень побеждал сутки. 

Это единственное, что может говорить, что я где-то упал на совсем уж ровном месте. (Если долго мучаешься, почти всегда - это что-то очевидное и ровное).

Но вот непохоже. 

Share this post


Link to post
Share on other sites
13 минут назад, DpInRock сказал:

Эту хрень побеждал сутки.

Попробуйте вставить в обработчик USART1 такую строчку. 

  if(USART1->ISR & USART_ISR_ORE) USART1->ICR = USART_ISR_ORE;

 

Share this post


Link to post
Share on other sites

У меня особо специально запрещаются все прерывания, кроме нужного.

Провел эксперимент.

Могу посылать один символ, а могу - два подряд.

Оба вижу, все норм. Никаких иных битов в состоянии уарта нет.

Делаю так, что по приходу первого символа (конкретного, 0х55) запускается запись во флэш.

И пока даю один символ за раз (с частотой - мышкой кликаю) - все нормально. Запись происходит, ничего не висит.

А даю два подряд (другая кнопка) - привет.

В общем-то опубликовал исключительно для истории.

Может у кого будет что-то похожее - ну не с нуля начинать.

А я лично пока решил, что это просто баг в проце. 

Что-то типа такого, что прерывание во время именно уарта1 лезет во флэш для выборки адреса обработчика, но память занята.

И вот эта занятость остается навсегда. И никак не связана с разрешением прерывания ядра, но связан с какой-то прямой связью уарт1 с доступом к памяти.

Как будто разрешение прерывания самого уарта - единственное препятствие на пути к запросу к флэшу. И глобальное прерывание и NVIC не препятствуют этому...

Т.е. разрешение прерываний ядра и NVIC просто запрещают прерывания. А уарт все равно делает попытки доступа к памяти....

 

Темна вода в облацех..

Пока забил.

Чисто в догонку. 

Для справки следующим.

Операция стирания страницы выполняется. Т.е все виснет, но потом, уже программатором смотрю - страница таки стерта.

До записи данных, соответственно не доходит.

Share this post


Link to post
Share on other sites
29 минут назад, DpInRock сказал:

Что-то типа такого, что прерывание во время именно уарта1 лезет во флэш для выборки адреса обработчика, но память занята.

И вот эта занятость остается навсегда. И никак не связана с разрешением прерывания ядра, но связан с какой-то прямой связью уарт1 с доступом к памяти.

Когда знаний не хватает начинается мифотворчество... :biggrin: А ведь достаточно всего-лишь открыть мануал на ядро.  :unknw:

Если прерывание замаскировано в NVIC или есть глобальный запрет прерываний, то никакой UART во флешь не полезет. И UART-ы как правило не имеют доступа к флешь.

Если только у вас не запрограммирована работа DMA-канала для событий UART.

Да и вообще - всё это элементарно проверяется переносом таблицы векторов или всего кода во флешь (в M0 это возможно?).

А причина сбоев может быть например в питании - что-то просаживается при активности внешних цепей UART и это сбивает процедуру записи во флешь. Возможно параметры питания и так на пределе, а здесь последняя капля. Или ещё какая совсем неявная причина. Например - тупо где-то что-то разрушается (стек, содержимое регистров, ...), или срабатывает WDT или сбой источника тактирования или ...

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

 

Share this post


Link to post
Share on other sites
15 часов назад, Baser сказал:

"Сабж" (МК) не умеет останавливаться.

Можно попробовать устроить состояние блокировки (lockup state) - поможет только RESET (хотя в некоторых случаях можно еще шевельнуться в NMI).

Если обработчик HF находится во flash, а при стирании flash, например, выполняющийся из ОЗУ код, приведет к HF, то при обращении к обработчику HF скорее будет

не блокировка, а остановка ядра при чтении flash - когда последняя прокашляется - все вернется на место.

Код в студию! Я уверен, дело не в МК, а в ПО.

Share this post


Link to post
Share on other sites
1 час назад, adnega сказал:

не блокировка, а остановка ядра при чтении flash - когда последняя прокашляется - все вернется на место.

Таки наверное да. При проблемах с флеш памятью, может. Было у меня однажды - ошибся при отладке, программа начала стирать нулевую страницу флеш (как раз в STM32F051). Выглядело это забавно, но я не стал разбираться к чему это приводило, уже не помню - может и ядро останавливалось... Исправил ошибку и "попилил" дальше.

Share this post


Link to post
Share on other sites
20 hours ago, aaarrr said:

ORE запрещается только вместе с RXNE.

USART1->CR2 12 бит. OVR Disable.

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

Несброшенное прерывание ничем плохим не грозит.

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

(Ну совсем плохого). У меня стоит переключающий светодиод в прерывании. Каждое прерывание - переключается. Так что видно. 

(И частый вызов хорошо видно по снижению яркости).

 

И да - я сильно не хочу чтобы ауколось.

Точно такой же девайс делал на STM32L011- но там есть епром и на STM32F405 - там использую флэш по полной программе и три последовательных порта.

Ноль проблем.

И вот сделал типа бюджетной-миниатюрной версии - и вот получил такой результат.

 

Я перепроверю это дело на другой плате. На текущей просто очень трудно подпаиваться, она маленкая и она у меня одна. 

Но выясню, конечно.

===

И граждане, речь не идет о том, что я не читаю даташиты.

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

====

ARR

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

Т.е. железобетонно, что после старта стирания (запись в соотв. регистр) все останавливается и код не выполняется.

И даже делал смещение во времени для старта записи.

Типа сигнал пришел стереть, а я делаю разные задержки. И вот после старта стирания - конец фильма точно.

При этом запись сама завершается удачно (как становится известно потом).

Edited by DpInRock

Share this post


Link to post
Share on other sites

Киньте пробный проект, на котором тестируете.

Условия эксперимента, приводящие к багу, как я понял, достаточны при соблюдении следующей последовательности:

  1. Со сторонней платы заслать по UART 19200-N-1 на UART1 МК STM32F030 2 символа.
  2. В прерывании по приему первого символа начать стирать Flash.
  3. Тут должны застрять.

У меня вот свежекупленная плата на F072, там все с F030 в этом плане должно быть одинаково.

Больно любопытно посмотреть, что там происходит. Но это ближе к выходным, если не забуду:smile:

Share this post


Link to post
Share on other sites

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

Условия таковы.

USART1 (именно 1), 19200, четность EVEN, 1 stop.

Прерывания по приему.

Внутри прерывания - считывание символа в волатильную переменную. 

Есть еще таймер3, который прерывается раз в 1ms для всяких задержек и прочего.

Главный цикл - раз, например в секунду стираем страницу. Я стираю последнюю (0х0800FC00).

Смотрим, что стирание выполняется, и цикл не виснет (я светодиодом моргаю по входу выходу из функции).

И начинаем гнать в порт какой-нибудь поток. 

Вот тут цикл виснет. Все виснет. Ничто не живет. Состояния портов ввода-вывода сохраняются.

=

Если сделать стирание пореже и гнать-останавливать поток на последовательный порт в промежутках - все работает нормально.

Чисто возможно, что в момент стирания действительно происходит оверран (ну, логично, память занята).

Но по завершении стирания должно вроде как все поехать снова. А оно не едет.

Причем - ПРЕРЫВАНИЯ от таймера - идут еще чаще.  И несмотря на занятость флэша - ничего плохого не происходит.

Только USART1.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.