|
Конфликт RAM и SPI |
|
|
|
Jan 19 2017, 06:43
|
Гуру
     
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 19 2017, 06:51
|
Гуру
     
Группа: Свой
Сообщений: 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 маленькую ёмкость (десятки пФ) на землю.
|
|
|
|
|
Jan 19 2017, 08:05
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Цитата Кстати, с тактированием всё нормально? Может быть, вы дико разогнали МК, не заметив этого, и он странно глючит? Или шум в цепи Vdda? Работаю с макеткой, которая хоть и китайская, но за 5 лет меня подобным образом ни разу не подводила. У меня ничего не разогнано. Вы понимаете, в чем парадокс? За то, что это глюк отладчика говорит тот факт, что сам контроллер, его код, науськанный на непрерывное отслеживание изменений в буфере, не обнаруживает таковых. За то, что проблема в контроллере и программе говорит тот факт, что отключение записи в SPI сохраняет данные в буфере в целостности. Еще одна особенность, которую я не могу трактовать в пользу чего либо - если в буфере 0x00, то пишется FF или AA. А если какие-то данные есть, то там оказывается другое число. Понимаете, если бы туда шла запись, то писалось бы конкретное число, а тут идет порча битов. Самое интересное, что, как я уже писал, в работе программа не ощутила изменений в буфере за 3 миллиона его проверок. То есть либо изменение кратковременное, либо это брехня. Ну а если бы и ощутила, протокол, который я собираюсь использовать, предполагает проверку контрольной суммы и данные были бы запрошены повторно. То есть можно смело выпускать устройство. Но все равно меня этот глюк гложет... Скажите, а можно ли как то при объявлении переменной приказать ей разместиться в строго определенном адресе? Ну или... если я чисто по тексту программы размещу ее в самом начале, она окажется по другому адресу? Если это глюк и что-то в программе лезет по определенному адресу, где у меня случайным образом оказался rx_buffer, то проблема именно с этой переменной должна исчезнуть. Это будет свидетельствовать в пользу глюка отладчика.
Сообщение отредактировал zheka - Jan 19 2017, 07:37
|
|
|
|
|
Jan 19 2017, 08:32
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(zheka @ Jan 19 2017, 08:43)  Господа, я понимаю, что причину моей проблемы вы не найдете, но может быть подскажете, как искать ошибку. А может быть и констатируете, что это не ошибка, а глюк отладчика... Я бы посмотрел (по карте памяти), какие переменные размещены до и после исследуемого буфера ("обрамляют" его) . Причина: не исключено, что в процедурах, работающих c "обрамляющими" переменными, нарушается некий указатель. Вторая тема: размер и размещение стэка. Третья тема: наличие, размер и размещение кучи (HEAP). Явно кто-то влазит на исследуемый буфер. Я также работаю с KEIL. Он может показывать чушь содержимого переменной, если смотреть переменную через watch (особенно при включенной оптимизации кода), но до сих пор KEIL мне всегда показывал правду, если смотреть память по адресу.
|
|
|
|
|
Jan 19 2017, 09:44
|
Гуру
     
Группа: Свой
Сообщений: 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-битных слова.
|
|
|
|
|
Jan 19 2017, 09:56
|
Гуру
     
Группа: Свой
Сообщений: 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 - вот он и был задействован, очевидно.
|
|
|
|
|
Jan 19 2017, 11:05
|

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

|
"Кутузов был без глаза. Нет! У Кутузова не было глаза!" Цитата(jcxz @ Jan 19 2017, 14:36)  Не надо использовать такие МК.  STM чумовая контора: с rev3 (PM0056) руководства по программированию в CM3 - есть MPU! Что меня и смутило: как так в L152 - есть, а в F103 вдруг нет?!
--------------------
Пролетарий умственного труда.
|
|
|
|
|
Jan 19 2017, 18:22
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
/////
Господа, в общем вывод такой - это глюк даже не отладчика, а самого кейла.
Никто мне в переменную ничего не пишет. Об этом свидетельсвтует следующее 1.Несмотря на то, что по сообщениям окна watсh, переменную rx_buffer кто-то упорно насилует, брейкпоинты на запись не срабатывают. При этом они срабатывают когда туда на самом деле осуществляется запись. 2. Как я заметил, байт, который оказывается в буфере, зависит от того, что там было раньше. Если бы шла запись в переменную, то ее содержимое просто затиралось бы конкретным числом, а тут мусор есть производное от первоначального значения. Мне сложно представить себе такой глюк или конфликт с памятью, при котором из буфера что-то будет читаться, затем с полученным результатом что-то делается и результат записывается в ячейку.... А вот на порчу отдельных бит это похоже. Более того, как я писал, появление левых данных всегда кратковременное, через долю секунды данные возвращаются к исходному виду. Опять таки, мне сложно представить глюк, который считывает данные, гадит, а потом восстанавливает.
Зато это очень похоже на периодическое искажение выведения результата кейлом - то есть данные в буфере постоянны, иногда KEIL считав их, теряет их правильность и выводит на экран бред, но при следующем чтении тех же самых правильных данных все нормально.
Сообщение отредактировал zheka - Jan 19 2017, 18:04
|
|
|
|
|
Jan 20 2017, 10:15
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zheka @ Jan 19 2017, 21:22)  Зато это очень похоже на периодическое искажение выведения результата кейлом - то есть данные в буфере постоянны, иногда KEIL считав их, теряет их правильность и выводит на экран бред, но при следующем чтении тех же самых правильных данных все нормально. В чём проблема проверить это? Когда появились странные данные, нажать кнопочку "Refresh" чтобы обновить данные в окне "watch". Или в кейле нет такой кнопочки? Цитата(zheka @ Jan 19 2017, 21:22)  Мне сложно представить себе такой глюк или конфликт с памятью, при котором из буфера что-то будет читаться, затем с полученным результатом что-то делается и результат записывается в ячейку.... А вот на порчу отдельных бит это похоже. Например - при доступах через bitband. Хотя в Вашем МК и его похоже тоже нету...
|
|
|
|
|
Jan 20 2017, 10:33
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(zheka @ Jan 19 2017, 21:22)  Господа, в общем вывод такой - это глюк даже не отладчика, а самого кейла.
Зато это очень похоже на периодическое искажение выведения результата кейлом - то есть данные в буфере постоянны, иногда KEIL считав их, теряет их правильность и выводит на экран бред, но при следующем чтении тех же самых правильных данных все нормально. Я бы не спешил ругать Кейл. Всё-таки он полагается на дрова для отладочного адаптера, которые написаны другими товарищами, и в них возможны глюки. Кроме того, весьма вероятно, что в протоколе SWD нет средств контроля целостности данных, поэтому в случае порчи сигналов SWD получите то, что получили. А тут уже вы виноваты - не надо портить сигналы
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|