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

 
 
 
Reply to this topicStart new topic
> STM32F103ZE - время исполнения кода?, Странности.
pr0m
сообщение Jan 22 2011, 20:12
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Всем привет.
Делаю первые шаги в освоении АРМ-ов. Стоит задача сделать DDS (синтезатор сигналов, до 400кГц, тональные, ЛЧМ). Решил реализовать на этом камне. Всё работает, но! Тот участок кода, к-й и реализует алгоритм DDS (инкремент аккумулятора фазы, выборка значения из таблицы формы сигнала, запись в регистр ЦАП-а) в симуляторе исполняется с абсолютно детерминированным количеством тактов (13), а в реальной железке меняется от 13 до 16 от прошивки к прошивке, причём эти прошивки отличаются в участках кода, не имеющих никакого отношения к основному алгоритму..... wacko.gif Это происходит даже после единственного изменения в исходном коде - изменения начального значения некой переменной в некой процедуре инициализации с одной цифры на другую. Обратил внимание, что при этом ничтожном изменении, содержимое выходного файла прошивки меняется радикально.
DMA, прерывания не использую.
Оптимизации кода выключены, код DDS написан на ассемблере, отдельным модулем! Весь алгоритм основан на точном значении количества тактов кода DDS, а у меня он живёт своей жизнью... Keil 4.14.


Прошу поделиться советами и прочими соображениями!


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
vptr
сообщение Jan 22 2011, 20:47
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 26
Регистрация: 15-11-07
Пользователь №: 32 363



есть мнение что в АРМах (Кортексах) время выпонения команд не детерминировано.

вот цитата:
Архитектура микроконтроллера с ARM-ядром значительно отличается от архитектур традиционных 8-и и 16-и разрядных микроконтроллеров, и прежде всего тем что в ней используется иерархия внутренних шин соединенных межшинными интерфейсами. Шины могут работать на разных частотах, за доступ к шинам могут конкурировать много внутренних модулей микроконтроллера, обмены данными по шинам могут заканчиваться ошибками за которыми следует следить программными средствами. Это приводит к тому, что отсутствует строгий детерминизм времени выполнения инструкций как это присуще простейшим микроконтроллерам. Во многом такое положение связано с высокими частотами на которых работает ARM ядро, на таких частотах уже не способна работать FLASH...

полный текст http://www.indemsys.ru/knowledge-base-mate...x-overview.html
это про STR91x. но тенденция понятна.

Сообщение отредактировал IgorKossak - Jan 22 2011, 20:49
Причина редактирования: Бездумное цитирование
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jan 22 2011, 20:56
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



попробуйте сначала писать в ЦАП, потом считать следующий семпл.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jan 23 2011, 09:25
Сообщение #4


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



У ARM-ов работающих в турбированном режиме с Flash (это частоты где-то больше 50 МГц) всегда есть модуль предвыборки, его еще акселератором называют. Идет эта предвыборка по границе выровненной 128 бит обычно (16-ть байт).
Все короткие циклы надо делать в пределах этих выровненных 16-и байт. Иначе будет вмешиваться механизм предвыборки.
Либо переносить код в RAM.
Go to the top of the page
 
+Quote Post
pr0m
сообщение Jan 23 2011, 11:13
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Цитата(AlexandrY @ Jan 23 2011, 12:25) *
У ARM-ов работающих в турбированном режиме с Flash (это частоты где-то больше 50 МГц) всегда есть модуль предвыборки, его еще акселератором называют. Идет эта предвыборка по границе выровненной 128 бит обычно (16-ть байт).
Все короткие циклы надо делать в пределах этих выровненных 16-и байт. Иначе будет вмешиваться механизм предвыборки.
Либо переносить код в RAM.


Похоже, Вы правы. Но отчасти, по части нижней частоты, при которой перестаёт вмешиваться предвыборка. Вчера экспериментировал:
1. снизил частоту до 36 Мгц, но там всё ещё нужен 1 waitstate для флэшки, и проблема оставалась - время выполнения куска кода DDS менялось. На 24МГц уже не нужны waitstate-ы, но такая тактовая частота уже маловата, теряется смысл использования АРМ-а и стал подумывать не использовать ли замечательный 8051-й от Silabs - они до 50 MIPS выдают.... Глянул бегло в их даташит - у них тоже выше 25МГц вставляются waitstates, и если склероз не изменяет, тоже есть предвыборка, и это насторожило.
2. Перенёс код DDS в RAM - и о чудо - пока работает стабильно - исполняется за детерминированное кол-во тактов. Правда, упала скорость, примерно в 1.3 раза. Насколько я понял, из-за того, что теперь данные и код читаются по одной шине. В связи с этим в по этому пункту 2 вопроса возникли 1) не начнёт ли происходить то же самое со скоростью, если вдруг захочу использовать DMA, к-й пользует ту же шину. 2) Вырастет ли скорость, если при исполнении кода из RAM на частоте 72МГц убрать те 2 waitstate-а, или они используются только при чтении кода из флэш по шине IBUS?

Цитата(ukpyr @ Jan 22 2011, 23:56) *
попробуйте сначала писать в ЦАП, потом считать следующий семпл.


Не знаю, на что это может повлиять. ЦАП тактируется 36МГц, при частоте ядра 72МГц, на самом деле использую оба ЦАПа, второй выдаёт инверсный сигнал - потом проще сделать меандр с минимальным джиттером ч-з компаратор, но пишу в теневой регистр данные сразу для обоих, причём в даташите написано, что в этом режиме данные из этого регистра попадают в выходные регистры точно на следующий такт. В моём случае, имхо, не имеет значения, это ведь приведёт лишь к сдвигу фиксированному во времени всех значений на выходе.

Цитата(vptr @ Jan 22 2011, 23:47) *
есть мнение что в АРМах (Кортексах) время выпонения команд не детерминировано.

вот цитата:
Архитектура микроконтроллера с ARM-ядром значительно отличается от архитектур традиционных 8-и и 16-и разрядных микроконтроллеров, и прежде всего тем что в ней используется иерархия внутренних шин соединенных межшинными интерфейсами. Шины могут работать на разных частотах, за доступ к шинам могут конкурировать много внутренних модулей микроконтроллера, обмены данными по шинам могут заканчиваться ошибками за которыми следует следить программными средствами. Это приводит к тому, что отсутствует строгий детерминизм времени выполнения инструкций как это присуще простейшим микроконтроллерам. Во многом такое положение связано с высокими частотами на которых работает ARM ядро, на таких частотах уже не способна работать FLASH...

полный текст http://www.indemsys.ru/knowledge-base-mate...x-overview.html
это про STR91x. но тенденция понятна.

Да, очень на то похоже - про недерминированность. Но у меня заворот мозгов от попытки понять, что происходит, когда сначала работает одна прошивка и выполняет мой кусочек кода за 13 тактов, а затем я меняю !! одну цифру в коде инициализации, заливаю новую прошивку, и она работает уже, как повезёт, 13-16 тактов.
Что-то вроде:
u32 f1,f2,tau;
f1 = 380000;
f2 = 420000;
tau = 100; // меняю на 10, или 1000 - и меняется время исполнения. Этот параметр ессно не счётчик цикла, и лишь для инкремента аккумулятора
на это значение
DDS_Proc(f1,f2,tau); // в другом модуле на асм-е, 9 инструкций


Сообщение отредактировал IgorKossak - Jan 23 2011, 18:05
Причина редактирования: Бездумнейшее самоцитирование


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 23 2011, 11:34
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(pr0m @ Jan 23 2011, 14:13) *
1) не начнёт ли происходить то же самое со скоростью, если вдруг захочу использовать DMA, к-й пользует ту же шину.

Конечно начнет.

Цитата(pr0m @ Jan 23 2011, 14:13) *
2) Вырастет ли скорость, если при исполнении кода из RAM на частоте 72МГц убрать те 2 waitstate-а, или они используются только при чтении кода из флэш по шине IBUS?

Нет, флеш ведь не задействована.
Go to the top of the page
 
+Quote Post
pr0m
сообщение Jan 23 2011, 12:17
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Ещё вопрос знающим - как работает механизм переключения на исполнение из ОЗУ? Вчера ночью не оставалось сил разобраться. Я следовал советам на сайте ARM-овцев - в свойствах проекта вырезал кусок ОЗУ и поместил в ROM, туда же направил в свойствах модуля DDS его код, собрал, прошил. Код в область ОЗУ пишет программатор? Тогда после выключения питания его уже там не будет? Или существует какая-то тайная сила в виде подпрограммы, переписывающей указанный кусок кода из флэш в ОЗУ?
Бегло прошёлся симулятором - в момент входа в main нужный код уже лежит в ОЗУ, а непосредственно перед вызовом моей процедуры в ОЗУ идёт вызов какой-то библиотечной процедуры из 2 инструкций - грузит регистр адресом входа в мою процедуру в ОЗУ и собсно переход.


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 23 2011, 13:17
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(pr0m @ Jan 23 2011, 15:17) *
Или существует какая-то тайная сила в виде подпрограммы, переписывающей указанный кусок кода из флэш в ОЗУ?

Существует. Почитайте в хелпе про __main.
Go to the top of the page
 
+Quote Post
pr0m
сообщение Jan 23 2011, 14:21
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Цитата(aaarrr @ Jan 23 2011, 16:17) *
Существует. Почитайте в хелпе про __main.

Неа. Добрался до железки, дёрнул питание - перестала работать.
Делаю вывод - нужно в начале программы самому копировать код в ОЗУ.
По поводу main вроде всё понятно - в стартапе вызывается из обработчика RESET-а, после SystemInit.
RESET_HANDLER
LDR R0,=SYSTEMINIT
BLX R0
LDR R0,=__main
BX R0
ENDP


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 23 2011, 15:06
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(pr0m @ Jan 23 2011, 17:21) *
Неа. Добрался до железки, дёрнул питание - перестала работать.

Значит что-то не так сделали. Скрипт линкера и map-файл покажите.

Цитата(pr0m @ Jan 23 2011, 17:21) *
По поводу main вроде всё понятно - в стартапе вызывается из обработчика RESET-а, после SystemInit.

main и __main совсем не одно и то же.
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jan 23 2011, 15:17
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



синхронзировать запись в DAC с таймером не получается ?
Go to the top of the page
 
+Quote Post
pr0m
сообщение Jan 23 2011, 15:37
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Цитата(ukpyr @ Jan 23 2011, 18:17) *
синхронзировать запись в DAC с таймером не получается ?

Не вижу смысла, тем более что в даташите написано, что при записи с использованием триггера по таймеру задержка записи - до 3 тактов, а напрямую - 1. Если Вы имеете ввиду - в обработчике прерывания от таймера - не годится, т.к. это очень медленно - у меня желательно период обновления значения DAC уложить в 20 тактов максимум, чтоб сохранить достаточно высокую частоту дискретизации и макс. частоты генерируемого сигнала соответсно.


Цитата(aaarrr @ Jan 23 2011, 18:06) *
Значит что-то не так сделали. Скрипт линкера и map-файл покажите.


main и __main совсем не одно и то же.

ага, зашёл в __main. Там уже что-то интетесное происходит до вызова main. Сбрасываю скаттер-файл и map.

А вот содержимое файла .lnp
--cpu Cortex-M3 ".\debug\main.o" ".\debug\dss.o" ".\debug\stm32f10x_it.o" ".\debug\system_stm32f10x.o" ".\debug\startup_stm32f10x_hd.o" ".\debug\stm32f10x_tim.o" ".\debug\stm32f10x_gpio.o" ".\debug\stm32f10x_rcc.o" ".\debug\misc.o" ".\debug\stm32f10x_dac.o" ".\debug\stm32f10x_exti.o" --library_type=microlib --strict --scatter ".\Debug\NAU.sct"
--autoat --summary_stderr --info summarysizes --map --xref --callgraph --symbols
--info sizes --info totals --info unused --info veneers
--list ".\LST\NAU.map" -o ".\Debug\NAU.axf"

Сообщение отредактировал pr0m - Jan 23 2011, 15:46
Прикрепленные файлы
Прикрепленный файл  NAU.rar ( 7.17 килобайт ) Кол-во скачиваний: 20
 


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 23 2011, 15:57
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(pr0m @ Jan 23 2011, 18:37) *
ага, зашёл в __main. Там уже что-то интетесное происходит до вызова main. Сбрасываю скаттер-файл и map.

На вид все правильно, DSS_Proc живет в RAM.
Стоп. Зачем в скаттере два загрузочных региона?

Должно быть так:
Код
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00080000
{  ; load region size_region
    ER_IROM1 0x08000000 0x00080000
    {; load address = execution address
        *.o (RESET, +First)
        *(InRoot$$Sections)
        .ANY (+RO)
    }
    RW_IRAM1 0x20000000 0x0000FC00
    {; RW data
        .ANY (+RW +ZI)
    }
    ER_IRAM1 0x2000FC00 0x00000400
    {
        dss.o (+RO)
    }
}
Go to the top of the page
 
+Quote Post
pr0m
сообщение Jan 23 2011, 17:31
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 183
Регистрация: 22-06-05
Из: Таганрог
Пользователь №: 6 233



Цитата(aaarrr @ Jan 23 2011, 18:57) *

Затрудняюсь ответить, ибо размечал регионы как рекомендуют на сайте ARM для исполнения кода в ОЗУ, файл лежал в директории проекта. Спасибо, сейчас попробую по Вашим рекомендациям. И если несложно, поясните вкратце каким образом мой код оказывается в ОЗУ после снятия питания. Должна же быть для его копия во флэш?

Работает! Но что же происходит в __main??

Сообщение отредактировал IgorKossak - Jan 23 2011, 18:06
Причина редактирования: Бездумное цитирование


--------------------
Правильно поставленный вопрос - половина ответа...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 23 2011, 17:42
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(pr0m @ Jan 23 2011, 20:31) *
Должна же быть для его копия во флэш?

Разумеется. Код копируется из флеш перед вызовом main.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 19:40
Рейтинг@Mail.ru


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