Перейти к содержанию
    

Конфликт RAM и SPI на STM32F103

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

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

 

Суть такова. Контроллер 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 подловить момент записи в переменную и определить кто на нее посягает?

Изменено пользователем haker_fox
Уточнил название темы, добавил теги, переместил в нужный раздел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скажите, возможно ли что отладчик брешет?

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

 

Как используя средства отдладки KEIL подловить момент записи в переменную и определить кто на нее посягает?

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

 

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

Ещё можно поварьировать частоту SWCLK. Если наблюдается неустойчивое соединение, можно повесить на цепь SWCLK маленькую ёмкость (десятки пФ) на землю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

У меня ничего не разогнано.

Вы понимаете, в чем парадокс?

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

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

 

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

 

 

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

 

Скажите, а можно ли как то при объявлении переменной приказать ей разместиться в строго определенном адресе?

Ну или... если я чисто по тексту программы размещу ее в самом начале, она окажется по другому адресу?

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

Изменено пользователем zheka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

Я также работаю с KEIL. Он может показывать чушь содержимого переменной, если смотреть переменную через watch (особенно при включенной оптимизации кода), но до сих пор KEIL мне всегда показывал правду, если смотреть память по адресу.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как используя средства отдладки KEIL подловить момент записи в переменную и определить кто на нее посягает?

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

Если в каком-то другом месте будет попытка записи в эту область - сразу получите исключение, проанализируете его источник - найдёте виновника.

Я таким образом не раз решал проблемы со случайными записями в переменные.

 

Обычно это называют 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-битных слова.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насчёт Кейла не скажу, но у Вас же Cortex-M3? В нём есть MPU.

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

 

Плохой метод. Наличие watchpoint-ов вызывает изменение временной диаграммы работы программы (вызывает резкое её замедление).

Видимо потому, что анализ условия watchpoint выполняется программно в ПО эмулятора (или отладчика?).

Когда я пользовался этой штукой, у меня ничто не замедлялось. Там же есть аппаратный watchpoint - вот он и был задействован, очевидно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда я пользовался этой штукой, у меня ничто не замедлялось. Там же есть аппаратный watchpoint - вот он и был задействован, очевидно.

Как раз я (под IAR) когда его пробовал - было резкое замедление, во много раз.

Поэтому тогда и реализовал метод с высокочастотным таймером.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Опередили про 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

0xE000ED90-0xE000ED93 MPU type register Reads as zero, indicating no MPU is implemented(1)

Не надо использовать такие МК. ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"Кутузов был без глаза. Нет! У Кутузова не было глаза!"

Не надо использовать такие МК. ;)

 

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

Что меня и смутило: как так в L152 - есть, а в F103 вдруг нет?!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

/////

 

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

 

Никто мне в переменную ничего не пишет. Об этом свидетельсвтует следующее

1.Несмотря на то, что по сообщениям окна watсh, переменную rx_buffer кто-то упорно насилует, брейкпоинты на запись не срабатывают. При этом они срабатывают когда туда на самом деле осуществляется запись.

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

Более того, как я писал, появление левых данных всегда кратковременное, через долю секунды данные возвращаются к исходному виду. Опять таки, мне сложно представить глюк, который считывает данные, гадит, а потом восстанавливает.

 

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

Изменено пользователем zheka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

В чём проблема проверить это?

Когда появились странные данные, нажать кнопочку "Refresh" чтобы обновить данные в окне "watch".

Или в кейле нет такой кнопочки?

 

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

Например - при доступах через bitband. Хотя в Вашем МК и его похоже тоже нету...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Я бы не спешил ругать Кейл. Всё-таки он полагается на дрова для отладочного адаптера, которые написаны другими товарищами, и в них возможны глюки. Кроме того, весьма вероятно, что в протоколе SWD нет средств контроля целостности данных, поэтому в случае порчи сигналов SWD получите то, что получили. А тут уже вы виноваты - не надо портить сигналы :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...