Я працюю з набором для виявлення STM32F303VC, і я трохи спантеличений його роботою. Для ознайомлення з системою я написав дуже просту програму, щоб просто перевірити швидкість удару бітів цього MCU. Код можна розділити наступним чином:
- Увімкнено тактовий годинник HSI (8 МГц);
- PLL ініціюється за допомогою прекалера 16 для досягнення HSI / 2 * 16 = 64 МГц;
- PLL позначається як SYSCLK;
- SYSCLK контролюється на штифті MCO (PA8), і один із штифтів (PE10) постійно перемикається у нескінченну петлю.
Нижче подано вихідний код цієї програми:
#include "stm32f3xx.h"
int main(void)
{
// Initialize the HSI:
RCC->CR |= RCC_CR_HSION;
while(!(RCC->CR&RCC_CR_HSIRDY));
// Initialize the LSI:
// RCC->CSR |= RCC_CSR_LSION;
// while(!(RCC->CSR & RCC_CSR_LSIRDY));
// PLL configuration:
RCC->CFGR &= ~RCC_CFGR_PLLSRC; // HSI / 2 selected as the PLL input clock.
RCC->CFGR |= RCC_CFGR_PLLMUL16; // HSI / 2 * 16 = 64 MHz
RCC->CR |= RCC_CR_PLLON; // Enable PLL
while(!(RCC->CR&RCC_CR_PLLRDY)); // Wait until PLL is ready
// Flash configuration:
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR |= FLASH_ACR_LATENCY_1;
// Main clock output (MCO):
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->MODER |= GPIO_MODER_MODER8_1;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_8;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR8;
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;
GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL0;
// Output on the MCO pin:
//RCC->CFGR |= RCC_CFGR_MCO_HSI;
//RCC->CFGR |= RCC_CFGR_MCO_LSI;
//RCC->CFGR |= RCC_CFGR_MCO_PLL;
RCC->CFGR |= RCC_CFGR_MCO_SYSCLK;
// PLL as the system clock
RCC->CFGR &= ~RCC_CFGR_SW; // Clear the SW bits
RCC->CFGR |= RCC_CFGR_SW_PLL; //Select PLL as the system clock
while ((RCC->CFGR & RCC_CFGR_SWS_PLL) != RCC_CFGR_SWS_PLL); //Wait until PLL is used
// Bit-bang monitoring:
RCC->AHBENR |= RCC_AHBENR_GPIOEEN;
GPIOE->MODER |= GPIO_MODER_MODER10_0;
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_10;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR10;
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10;
while(1)
{
GPIOE->BSRRL |= GPIO_BSRR_BS_10;
GPIOE->BRR |= GPIO_BRR_BR_10;
}
}
Код був складений разом з CoIDE V2 за допомогою вбудованої інструментальної мережі GNU ARM з використанням оптимізації -O1. Сигнали на штифтах PA8 (MCO) та PE10, досліджені осцилографом, виглядають так:
Здається, SYSCLK налаштований правильно, оскільки МКО (помаранчева крива) має коливання майже 64 МГц (з огляду на похибку внутрішнього тактового сигналу). Дивна для мене частина - поведінка на PE10 (синя крива). У нескінченному циклі (1) потрібно 4 + 4 + 5 = 13 тактових циклів для виконання елементарної 3-ступінкової операції (тобто біт-набір / біт-скидання / повернення). Це стає ще гіршим на інших рівнях оптимізації (наприклад, -O2, -O3, ar -Os): кілька додаткових тактових циклів додаються до низької частини сигналу, тобто між падаючими та піднімаючими краями PE10 (що дозволяє LSI якось здається виправити цю ситуацію).
Чи очікується така поведінка від цього MCU? Я б уявив, що завдання таке просте, як встановлення та скидання трохи повинно бути в 2-4 рази швидше. Чи є спосіб пришвидшити справи?