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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Конфликт RAM и SPI
zheka
сообщение Jan 19 2017, 06:43
Сообщение #1


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



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

Суть такова. Контроллер STM32F103, в нем включен USART. В обработчике прерывания по приему заполняется буфер, объявленный как uint8_t rx_buffer[50]; Буфер кольцевой.
Работаю с KEIL. Отлаживаю по SWD, в окно watch я добавил rx_buffer. Проблема в чем - в эту переменную, согласно уведомлениям отладчика, периодически в случайные позиции на мгновение вместо 0x00 записывается 0xFF или 0xAA. При этом единственное место в программе, где в эту переменную что-то пишется - это обработка прерывания по приему, я ставил брейкпоинт на эту единственную строку - не срабатывает. Потому как я для чистоты эксперимента вообще отключил источник данных.

Я закомментировал практически всю программу
Код
main()
{
while(1)
  {
    LCD_DrawFill(0,0,30,30,BLACK);
  }

}

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

Я бы обозначил эту проблему, как конфликт SPI и RAM если бы не два "но".

1. В SPI ведется запись еще несколькими функциями, но проблема возникает только в одной из них.
2. Я написал кусок кода, который в цикле проверяет каждый элемент rx_buffer на предмет отличия его от изначального 0x00 и поставил на нем брейкпоинт. Понимая, что проверка и кратковременное изменение буфера могут не совпасть по времени, я запустил программу на ночь, по моим прикидкам буфер должен был быть проверен около 3 миллионов раз. Ни разу програма не засекла вмешательство в буфер.


Похожие глюки, с записыванием данных не в те переменные у меня была как-то, когда я объявил безразмерный массив ( uint8_t XXX[]; ) Но в данном случае ничего такого у меня нет.

Скажите, возможно ли что отладчик брешет?
Как используя средства отдладки KEIL подловить момент записи в переменную и определить кто на нее посягает?

Сообщение отредактировал zheka - Jan 19 2017, 09:59
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 19 2017, 06:51
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zheka @ Jan 19 2017, 09:43) *
Скажите, возможно ли что отладчик брешет?

Наверное. Тут нужно в деталях разбираться, как работает отладчик.

Цитата(zheka @ Jan 19 2017, 09:43) *
Как используя средства отдладки KEIL подловить момент записи в переменную и определить кто на нее посягает?

Обычно это называют watchpoint, вроде бы. У Кейла это называется data breakpoint. Если настроить всё как надо, отладчик остановится в тот момент, когда процессор попробует записать что-то в указанный диапазон адресов. Он не остановится, если туда полезет DMA, но это не ваш случай, насколько я понял.

Кстати, с тактированием всё нормально? Может быть, вы дико разогнали МК, не заметив этого, и он странно глючит? Или шум в цепи Vdda?
Ещё можно поварьировать частоту SWCLK. Если наблюдается неустойчивое соединение, можно повесить на цепь SWCLK маленькую ёмкость (десятки пФ) на землю.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 19 2017, 08:05
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
Кстати, с тактированием всё нормально? Может быть, вы дико разогнали МК, не заметив этого, и он странно глючит? Или шум в цепи Vdda?

Работаю с макеткой, которая хоть и китайская, но за 5 лет меня подобным образом ни разу не подводила.
У меня ничего не разогнано.
Вы понимаете, в чем парадокс?
За то, что это глюк отладчика говорит тот факт, что сам контроллер, его код, науськанный на непрерывное отслеживание изменений в буфере, не обнаруживает таковых.
За то, что проблема в контроллере и программе говорит тот факт, что отключение записи в SPI сохраняет данные в буфере в целостности.

Еще одна особенность, которую я не могу трактовать в пользу чего либо - если в буфере 0x00, то пишется FF или AA. А если какие-то данные есть, то там оказывается другое число. Понимаете, если бы туда шла запись, то писалось бы конкретное число, а тут идет порча битов.


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

Скажите, а можно ли как то при объявлении переменной приказать ей разместиться в строго определенном адресе?
Ну или... если я чисто по тексту программы размещу ее в самом начале, она окажется по другому адресу?
Если это глюк и что-то в программе лезет по определенному адресу, где у меня случайным образом оказался rx_buffer, то проблема именно с этой переменной должна исчезнуть. Это будет свидетельствовать в пользу глюка отладчика.

Сообщение отредактировал zheka - Jan 19 2017, 07:37
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jan 19 2017, 08:32
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(zheka @ Jan 19 2017, 08:43) *
Господа, я понимаю, что причину моей проблемы вы не найдете, но может быть подскажете, как искать ошибку.
А может быть и констатируете, что это не ошибка, а глюк отладчика...

Я бы посмотрел (по карте памяти), какие переменные размещены до и после исследуемого буфера ("обрамляют" его) . Причина: не исключено, что в процедурах, работающих c "обрамляющими" переменными, нарушается некий указатель. Вторая тема: размер и размещение стэка. Третья тема: наличие, размер и размещение кучи (HEAP). Явно кто-то влазит на исследуемый буфер.

Я также работаю с KEIL. Он может показывать чушь содержимого переменной, если смотреть переменную через watch (особенно при включенной оптимизации кода), но до сих пор KEIL мне всегда показывал правду, если смотреть память по адресу.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 19 2017, 08:59
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
Я бы посмотрел (по карте памяти),

Это где примерно?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 19 2017, 09:44
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(zheka @ Jan 19 2017, 09:43) *
Как используя средства отдладки KEIL подловить момент записи в переменную и определить кто на нее посягает?

Насчёт Кейла не скажу, но у Вас же Cortex-M3? В нём есть MPU. Выносите rx_buffer в отдельную секцию памяти, выравниваете ещё положение и размер на 64 байта (например), закрываете к ней доступ по записи через MPU, приоткрывая его временно только в точке записи (в ISR) (на всякий случай запретив прерывания на это время (или назначив прерыванию rx_buffer наивысший приоритет из всех)).
Если в каком-то другом месте будет попытка записи в эту область - сразу получите исключение, проанализируете его источник - найдёте виновника.
Я таким образом не раз решал проблемы со случайными записями в переменные.

Цитата(scifi @ Jan 19 2017, 09:51) *
Обычно это называют watchpoint, вроде бы. У Кейла это называется data breakpoint. Если настроить всё как надо, отладчик остановится в тот момент, когда процессор попробует записать что-то в указанный диапазон адресов. Он не остановится, если туда полезет DMA, но это не ваш случай, насколько я понял.

Плохой метод. Наличие watchpoint-ов вызывает изменение временной диаграммы работы программы (вызывает резкое её замедление).
Видимо потому, что анализ условия watchpoint выполняется программно в ПО эмулятора (или отладчика?).
Изменение времянки может привести к исчезновению проблемы.
Применение MPU - менее инвазивный метод.

Ещё другой способ:
Запускаете высокочастотное прерывание от любого таймера. Частотой 500-1000кГц (зависит от производительности процессора). Так чтобы оно грузило процессор процентов на 50% или больше.
В ISR сравниваете какие-то части rx_buffer с копией (Ваш ISR, который пишет в rx_buffer, должен дублировать запись и в его копию).
Назначаете приоритет прерывания записи rx_buffer самым высоким, прерывания от таймера - выше других, но ниже прерывания пишущего rx_buffer.
Если при очередной проверке данные не совпали - читаете из стека в какой точке идёт выполнение фоновой программы.
Если обработчик таймера будет коротким (лучше на асм), то сможете обнаружить точку модификации с точностью до примерно десятка команд или меньше.
Но конечно этот метод сильнее влияет на выполнение самой исследуемой программы чем метод с MPU. Да и весь rx_buffer сразу в одном прерывании не проконтролируешь, только 1-2 32-битных слова.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 19 2017, 09:56
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ Jan 19 2017, 12:44) *
Насчёт Кейла не скажу, но у Вас же Cortex-M3? В нём есть MPU.

Указано же, что это STM32F103. Нету там никакого MPU.

Цитата(jcxz @ Jan 19 2017, 12:44) *
Плохой метод. Наличие watchpoint-ов вызывает изменение временной диаграммы работы программы (вызывает резкое её замедление).
Видимо потому, что анализ условия watchpoint выполняется программно в ПО эмулятора (или отладчика?).

Когда я пользовался этой штукой, у меня ничто не замедлялось. Там же есть аппаратный watchpoint - вот он и был задействован, очевидно.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 19 2017, 09:59
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(scifi @ Jan 19 2017, 12:56) *
Когда я пользовался этой штукой, у меня ничто не замедлялось. Там же есть аппаратный watchpoint - вот он и был задействован, очевидно.

Как раз я (под IAR) когда его пробовал - было резкое замедление, во много раз.
Поэтому тогда и реализовал метод с высокочастотным таймером.
Go to the top of the page
 
+Quote Post
Obam
сообщение Jan 19 2017, 10:07
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



Опередили про MPU…

PM0056 STM32F10xxx Cortex-M3 programming manual:
About the STM32 core peripherals
0xE000ED90-0xE000ED93 MPU type register Reads as zero, indicating no MPU is implemented(1)

Сообщение отредактировал Obam - Jan 19 2017, 10:08


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 19 2017, 10:36
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Obam @ Jan 19 2017, 13:07) *
0xE000ED90-0xE000ED93 MPU type register Reads as zero, indicating no MPU is implemented(1)

Не надо использовать такие МК. wink.gif
Go to the top of the page
 
+Quote Post
Obam
сообщение Jan 19 2017, 11:05
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



"Кутузов был без глаза. Нет! У Кутузова не было глаза!"
Цитата(jcxz @ Jan 19 2017, 14:36) *
Не надо использовать такие МК. wink.gif


STM чумовая контора: с rev3 (PM0056) руководства по программированию в CM3 - есть MPU!
Что меня и смутило: как так в L152 - есть, а в F103 вдруг нет?!


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 19 2017, 11:18
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Obam @ Jan 19 2017, 14:05) *
STM чумовая контора: с rev3 (PM0056) руководства по программированию в CM3 - есть MPU!

Не надо наговаривать:
Цитата
This section describes the Memory protection unit (MPU) which is implemented in some STM32 microcontrollers. Refer to the corresponding device datasheet to see if the MPU is present in the STM32 type you are using.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 19 2017, 18:22
Сообщение #13


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



/////

Господа, в общем вывод такой - это глюк даже не отладчика, а самого кейла.

Никто мне в переменную ничего не пишет. Об этом свидетельсвтует следующее
1.Несмотря на то, что по сообщениям окна watсh, переменную rx_buffer кто-то упорно насилует, брейкпоинты на запись не срабатывают. При этом они срабатывают когда туда на самом деле осуществляется запись.
2. Как я заметил, байт, который оказывается в буфере, зависит от того, что там было раньше. Если бы шла запись в переменную, то ее содержимое просто затиралось бы конкретным числом, а тут мусор есть производное от первоначального значения. Мне сложно представить себе такой глюк или конфликт с памятью, при котором из буфера что-то будет читаться, затем с полученным результатом что-то делается и результат записывается в ячейку.... А вот на порчу отдельных бит это похоже.
Более того, как я писал, появление левых данных всегда кратковременное, через долю секунды данные возвращаются к исходному виду. Опять таки, мне сложно представить глюк, который считывает данные, гадит, а потом восстанавливает.

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

Сообщение отредактировал zheka - Jan 19 2017, 18:04
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 20 2017, 10:15
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(zheka @ Jan 19 2017, 21:22) *
Зато это очень похоже на периодическое искажение выведения результата кейлом - то есть данные в буфере постоянны, иногда KEIL считав их, теряет их правильность и выводит на экран бред, но при следующем чтении тех же самых правильных данных все нормально.

В чём проблема проверить это?
Когда появились странные данные, нажать кнопочку "Refresh" чтобы обновить данные в окне "watch".
Или в кейле нет такой кнопочки?

Цитата(zheka @ Jan 19 2017, 21:22) *
Мне сложно представить себе такой глюк или конфликт с памятью, при котором из буфера что-то будет читаться, затем с полученным результатом что-то делается и результат записывается в ячейку.... А вот на порчу отдельных бит это похоже.

Например - при доступах через bitband. Хотя в Вашем МК и его похоже тоже нету...
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 20 2017, 10:33
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zheka @ Jan 19 2017, 21:22) *
Господа, в общем вывод такой - это глюк даже не отладчика, а самого кейла.

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

Я бы не спешил ругать Кейл. Всё-таки он полагается на дрова для отладочного адаптера, которые написаны другими товарищами, и в них возможны глюки. Кроме того, весьма вероятно, что в протоколе SWD нет средств контроля целостности данных, поэтому в случае порчи сигналов SWD получите то, что получили. А тут уже вы виноваты - не надо портить сигналы laughing.gif
Go to the top of the page
 
+Quote Post

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

 


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


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