Jump to content

    
Sign in to follow this  
Firer

STM32F103

Recommended Posts

Компилятор Keil.

Код в вечном цикле меняет состояние выходного бита порта.

Кварц 8МГц. SYSCLK=8*9=72МГц

APB1=72/2, APB2=72

порт настроен на макс.частоту 50МГц.

прерывания все запрещены.

Ядро работает на 72МГц - MCO включал убедился осциллографом вижу 72МГц.

 

Реально порт дергается с частотой около 3МГц. В чем дело?

Как минимум должно быть около 36МГц меандр.

 

Share this post


Link to post
Share on other sites

Для начала не плохо было бы посмотреть во что скомпилировался Ваш вечный цикл (посмотреть что там в асме). А вообще такие вещи нужно писать на асме или делать асмовские вставки. Думаю после этого часть вопросов отпадет сама по себе.

Share this post


Link to post
Share on other sites
Как минимум должно быть около 36МГц меандр.

Ну-ну, мечтайте дальше.

Как сказано выше, код цикла может скомпилироваться неоптимально.

Кроме того, скорость GPIO в серии STM32F1xx точно меньше скорости процессора. На сколько именно - в документации не написано, надо экспериментировать. Встречал упоминания о том, что мост AHB-APB добавляет 2 цикла задержки. И вот эти "50 МГц" - это всего лишь крутизна фронтов, то есть на частоту переключения не влияет.

Кстати, в серии STM32F2xx совсем другая история.

Share this post


Link to post
Share on other sites

Коллеги спасибо за подсказки!

Код я посмотрел ассемблерный. Так что имею права на мечту, ну не 36МГц, ну 10 хотя бы. А то выходит 3.

 

while (1)

XLED0_TGL;

 

На асме это:

metka: ldr r1,[r0,0x80c]

eor r1,r1,#0x200

str r1,[r0,#0x80c]

b metka

 

т.е. 4 такта? Или я не прав?

Ну если еще мост добавит 2 раза по 2 цикла задержки, то выходит около 10 тактов?

А это 7.2МГц а не 3.6.

 

Share this post


Link to post
Share on other sites
т.е. 4 такта? Или я не прав?

Очень часто инструкция выполняется не за 1 такт. В документе "Cortex-M3 Technical Reference Manual" описывается время выполнения инструкций. Дополнительные задержки могут возникать при обращении процессора к внешним шинам (APB, флэш и прочее).

Кроме того, более оптимальный код такой:

int pdata1 = 0x0000, pdata2 = 0x0200;
while (1)
{
    PORT = pdata1;
    PORT = pdata2;
}

Ну и компилировать с максимальной оптимизацией по скорости.

А на ассемблере можно сделать оптимально без оглядки на компилятор.

 

Update:

Да, забыл.

Ну если еще мост добавит 2 раза по 2 цикла задержки, то выходит около 10 тактов?

А это 7.2МГц а не 3.6.

Нет, это не 10, а 20 тактов. Одна итерация цикла в таком виде - это половина периода ("0" - 10 циклов, "1" - 10 циклов, ...).

Share this post


Link to post
Share on other sites

Разбирался когда-то с этим.

 

STR в порт на STM32 действительно занимает 2 такта (ну не совсем так, но упростим для вашего случая), но вы не забывайте еще и про переход. А вот его влияние на время исполнение приведенного кода уже замысловатее из-за тактов ожидания флеши и буфера предвыборки. Там будет зависимость от того на какой адрес идет переход, и от размера и времени выполнения команд, на которые идет переход.

Попробуйте, не будет ли приведенный вами код по времени исполнения зависеть от адреса метки :rolleyes:

 

Линейный код, состоящий из STR, будет как и должно выполняться за 2 такта на каждое обращение, и обеспечивать обещанную частоту переключения 18МГц.

 

 

 

Share this post


Link to post
Share on other sites

Переход тоже гдето в 2 така выливается. Тоесть цикл записи в порт самый оптимизированный(а не тот что приведен выше) занимает около 6 тактов,соответственно 12 тактов запись патерна. Тоесть теоретически 6-7 мгц это максимум что можно получить при генерации меандра.

Share this post


Link to post
Share on other sites
Переход тоже гдето в 2 така выливается. Тоесть цикл записи в порт самый оптимизированный(а не тот что приведен выше) занимает около 6 тактов,соответственно 12 тактов запись патерна. Тоесть теоретически 6-7 мгц это максимум что можно получить при генерации меандра.

Это вы оптимист насчет перехода, 2 в идеальном случае.

Branches take one cycle for instruction and then pipeline reload for target instruction. Non-taken branches are 1 cycle total.

Taken branches with an immediate are normally 1 cycle of pipeline reload (2 cycles total). Taken branches with register

operand are normally 2 cycles of pipeline reload (3 cycles total). Pipeline reload is longer when branching to unaligned 32-bit

instructions in addition to accesses to slower memory. A branch hint is emitted to the code bus that permits a slower system

to pre-load. This can reduce the branch target penalty for slower memory, but never less than shown here.

А если вспомнить про 2 такта ожидания при обращении к флеш на 72МГц для STM32F103, и небольшую глубину буфера предвыборки, то если память мне не изменяет, то и 5 тактов можно получить.

С оптимизацией тож не все так очевидно, какой код там самый оптимизированный. Из-за нюансов внутренней архитектуры легко получаются чудеса.

 

Цикл из двух записей в порт и перехода на 72МГц действительно по минимуму 6 тактов, т.е. генерация меандра 12МГц. Но можно получить и в 1.5 раза медленее на том же исходном коде.

 

Share this post


Link to post
Share on other sites
Встречал упоминания

Вот там посмотрите http://caxapa.ru/182481.html

Реально 2-3 такта на каждую команду, если в коротком цикле только две записи в порт

Share this post


Link to post
Share on other sites
Компилятор Keil.

Код в вечном цикле меняет состояние выходного бита порта.

Кварц 8МГц. SYSCLK=8*9=72МГц

APB1=72/2, APB2=72

порт настроен на макс.частоту 50МГц.

прерывания все запрещены.

Ядро работает на 72МГц - MCO включал убедился осциллографом вижу 72МГц.

 

Реально порт дергается с частотой около 3МГц. В чем дело?

Как минимум должно быть около 36МГц меандр.

 

Когда с STM32F4 игрался то дергал ногу с частотой проца. те 2 раза ниже.

А параметры отвечающие за частоту работы порта отвечали за фронт сигнала на пине (т.е. управляли током работы PIO).

Share this post


Link to post
Share on other sites

В Keil есть симулятор, в котором прекрасно видно, за сколько тактов выполняется команда, а также можно запустить "секундомер" - в строке состояния Keil.

Share this post


Link to post
Share on other sites
В Keil есть симулятор, в котором прекрасно видно, за сколько тактов выполняется команда, а также можно запустить "секундомер" - в строке состояния Keil.

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

Share this post


Link to post
Share on other sites
Вопрос в том, насколько точен этот симулятор. Насколько я понимаю, они стараются делать его приближенным к реальному кремнию, но гарантий не дают.

Я не уверен, что симулятор учитывает чтение и использование команд в буфере. Но в остальном, понять, сколько тактов занимает последовательность команд, можно. Keil показывает количество тактов и время, а мы гордо пройдем мимо? Давайте сначала посмотрим на числа, что он показывает, а потом будем отвергать. Уж 36 MHz меандр он точно не покажет. :)

Share this post


Link to post
Share on other sites

Для быстрого дрыга пинами очень актуальным будет использование BitBand-a. Что за зверь и как юзать может доступно поведать Insider's Guide на русском даже языке.

Однако ж даже с ним 32Мгц не ждите.

PS прошу прощения за "вражий сайт", но файл больше чем 2мб и посему не прикреплябелен(

Edited by Lukdut

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.

Sign in to follow this