Считать циклы не совпадают на STM32F103C8? Буфер предварительной загрузки не работает, как я думаю?

Я боролся с этим предметом некоторое время. Я использую STM32F103C8 с ST-Link V2 на Atollic.

Я сделал несколько функций задержки на сборке. Я тестировал этот фрагмент кода с помощью осциллографа на ATSAM (84 МГц и работает отлично), а на STM32 я также использую регистр ЦП, чтобы увидеть точное количество циклов при отладке - DWT (Data Watchpoint and Trace).

Когда я настраиваю тактовую частоту процессора STM32 на 24 МГц, точное количество циклов, которое я спроектировал для временной задержки, является правильным. Это 1 цикл для инструкции по уменьшению ассемблера и 2 цикла для команды ветвления (в большинстве случаев). Итак, основной цикл проводят 3 цикла.

Когда я меняю тактовую частоту процессора на 72 МГц, каждая инструкция по сборке тратит вдвое больше времени!

Что ж, буфер префекта имеет размер 2x64 бита, и состояния ожидания не должны влиять на время процессора (не думая о предсказаниях или других остановках кода) на этом микроконтроллере? Должно ли это?

Что ж, на 24 МГц у флэш-памяти нет состояния ожидания, при более высокой тактовой частоте ЦП не должен ждать выполнения какого-либо кода. Должно ли это?

Я перепрошил с выпуском hex, чтобы увидеть разницу и не нашел.

Мое единственное объяснение будет о ST-LINK V2? Я прав?

Большое спасибо за ваше время и внимание.

Это часть кода, которая имеет значение:

asm (".equ fcpu, 72000000\n\t");    //72 MHz
asm (".equ const_ms, fcpu/3000  \n\t"); 
asm (".equ const_us, fcpu/3000000   \n\t"); 

void delay_us(uint32_t valor)   
{
  asm volatile ( "movw r1, #:lower16:const_us   \n\t"
  "movt r1, #:upper16:const_us  \n\t"   
  "mul r0, r0, r1   \n\t"   
  "r_us:    subs r0, r0, #1 \n\t" 
  "bne r_us \n\t");
}

void delay_ms(uint32_t valor)   
{
  asm volatile ("movw r1, #:lower16:const_ms    \n\t"
  "movt r1, #:upper16:const_ms  \n\t"   
  "mul r0, r0, r1   \n\t"   
  "r_ms:    subs r0, r0, #1 \n\t"
  "bne r_ms \n\t");
}

2 ответа

Это из-за состояний ожидания флэш-памяти, работающей на частоте 72 МГц. Хорошо читать документацию:).

Поместите код в SRAM, и вы получите то, что вы хотите.

Для получения хороших результатов от FLASH избегайте разветвлений, так как он очищает конвейер. Задержки такого рода хороши только для очень коротких. Все, что дольше, должно быть реализовано с использованием таймеров.

Я советую избегать задержек в коде.

PS St-Link не виноват:)

Я делал несколько тестов. Мой первый вывод заключается в том, что накладные расходы зависят от выравнивания инструкций по памяти (буфер предварительной выборки равен 2х64 бита). Во-вторых, из-за детерминированного поведения ветки, когда оно берется, оно очищает буфер предварительной выборки, а также конвейер.

Другие вопросы по тегам