Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » Архив » STM32 Система тактирования


STM32 Система тактирования

Сообщений 1 страница 30 из 37

1

Система тактирования для F4 на примере F4 дискавери .

Сперва определимся с терминами и что, где искать в документации.

RM0090 Rev13. Ищем Clock tree.

http://s0.uploads.ru/Fn57B.png

Рассмотрим подробнее путь прохождения и трансформации тактовой частоты на примере варианта HSE+PLL.

http://s5.uploads.ru/dZs02.png

Читаем параграф 7.2 Clocks, а именно

All peripheral clocks are derived from the system clock (SYSCLK) except for:
• The USB OTG FS clock (48 MHz), the random analog generator (RNG) clock
(≤48 MHz) and the SDIO clock (≤ 48 MHz) which are coming from a specific output of
PLL (PLL48CLK)

Вся периферия тактируется от SYSCLK за исключением USB OTG FS,RNG,SDIO.
Источником тактовой для них служит PLL48CLK.

http://s0.uploads.ru/0iHFj.png

http://s3.uploads.ru/ki182.png

Читаем о PLL48 и о PLL вообще:

7.2.3 PLL configuration
The STM32F4xx devices feature two PLLs:
• A main PLL (PLL) clocked by the HSE or HSI oscillator and featuring two different
output clocks:
– The first output is used to generate the high speed system clock (up to 168 MHz)
– The second output is used to generate the clock for the USB OTG FS (48 MHz),
the random analog generator (≤48 MHz) and the SDIO (≤ 48 MHz).

Основной PLL тактируется от HSE или HSI и имеет два различных выхода тактовой:
- Первый для системной тактовой (вплоть до 168МГц)
-Второй , как выше и писано, для USB OTG FS,RNG,SDIO

Since the main-PLL configuration parameters cannot be changed once PLL is enabled, it is
recommended to configure PLL before enabling it (selection of the HSI or HSE oscillator as
PLL clock source, and configuration of division factors M, N, P, and Q).

Параметры PLL не могут быть изменены если PLL включена,
рекомендуется конфигурировать PLL до его включения( выбор HSI или HSE как источников
тактирование PLL и конфигурации делителей M, N, P, и Q)

Далее, идем в параграф 7.3.1 RCC clock control register (RCC_CR)

Здесь читаем о битах включения PLL и его готовности :

Bit 25 PLLRDY: Main PLL (PLL) clock ready flag
Set by hardware to indicate that PLL is locked.
0: PLL unlocked
1: PLL locked
Bit 24 PLLON: Main PLL (PLL) enable
Set and cleared by software to enable PLL.
Cleared by hardware when entering Stop or Standby mode. This bit cannot be reset if PLL
clock is used as the system clock.
0: PLL OFF
1: PLL ON

http://s1.uploads.ru/Tk8aJ.png
На рисунке /M соответствует PLLM, N- PLLN, VCO- VCO, P-PLLP,Q-PLLQ.

Идем в параграф 7.3.2 RCC PLL configuration register (RCC_PLLCFGR)

This register is used to configure the PLL clock outputs according to the formulas:
• f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
• f(PLL general clock output) = f(VCO clock) / PLLP
• f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ

Сей регистр служит для конфигурации выхлопа тактовой PLL исходя из формулы.

f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
Здесь определяется внутренняя тактовая PLL.
Где
VCO выход внутреннего делителя.
PLL clock input вход PLL
PLLN множитель VCO
PLLM делитель тактовой от HSI или HSE

http://sg.uploads.ru/K8TU0.png

Далее делитель для PLL48CK, для USB OTG FS, SDIO, RNG
• f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ

Ну и делитель для системной тактовой
• f(PLL general clock output) = f(VCO clock) / PLLP

Читаем о PLLQ

Bits 27:24 PLLQ: Main PLL (PLL) division factor for USB OTG FS, SDIO and random number generator
clocks
Set and cleared by software to control the frequency of USB OTG FS clock, the random
number generator clock and the SDIO clock. These bits should be written only if PLL is
disabled.
Caution: The USB OTG FS requires a 48 MHz clock to work correctly. The SDIO and the
random number generator need a frequency lower than or equal to 48 MHz to work
correctly.
USB OTG FS clock frequency = VCO frequency / PLLQ with 2 ≤PLLQ ≤15
0000: PLLQ = 0, wrong configuration
0001: PLLQ = 1, wrong configuration
0010: PLLQ = 2
0011: PLLQ = 3
0100: PLLQ = 4
...
1111: PLLQ = 15

Главное

Caution: The USB OTG FS requires a 48 MHz clock to work correctly.
Внимание: USB OTG FS требует 48МГц для корректной работы.

Читаем о выборе источника тактирования PLL
Цитата:

Bit 22 PLLSRC: Main PLL(PLL) and audio PLL (PLLI2S) entry clock source
Set and cleared by software to select PLL and PLLI2S clock source. This bit can be written
only when PLL and PLLI2S are disabled.
0: HSI clock selected as PLL and PLLI2S clock entry
1: HSE oscillator clock selected as PLL and PLLI2S clock entry

Теперь у нас есть все что необходимо для конфигурирации PLL.

1) Определяемся с чего бум тактировать - либо HSI (16МГц ) либо HSE( смотрим на кварц)

Вычисляем делители PLL исходя из выше озвученных частот, того что для USB нужно 48МГц
и желаемом системной частоты .
2) Кофигурируем PLL - делители и источник .
3) Ждем готовности PLL.















Система тактирования F4 на примере STM32F4 дискавери

Откроем  startup_stm32f407xx.s .
    При старте выполнение кода начинается  с вектора сброса  Reset_Handler.
    Найдем  эту секцию:

Код:
   ; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit      <=====  
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

Как видим до перехода на main вызывается функция SystemInit.
Находится она в system_stm32f4xx.c и содержит начальную инициализацию тактовой .

Исключим из компиляции файл  system_stm32f4xx.c и добавим свой clock_init.c
  который будет содержать ту же функцию SystemInit  но уже с нашим вариантом инициализации тактовой .

Итак при старте системы мы имеем следующее :

Система тактируется от HSI (16МГц)
Латентность флеш на минимуме

Основные  манипуляции, что нужно произвести для перехода на максимальную частоту тактирования  -168МГц от HSE (8МГц):

-Включить HSE и дождаться его готовности
-Настроить делители шин AHB,APB1и APB2
-Сконфигурировать PLL  включить PLL и дождаться готовности
-Настроить Flash prefetch, instruction cache, data cache и wait state
-Выбрать PLL источником тактирования системы и дождаться переключения

Напомню что частоты тактирования  модулей вычисляется исходя из формул

             PLL_VCO = ([HSE_VALUE or HSI_VALUE] / PLL_M) * PLL_N
             SYSCLK = PLL_VCO / PLL_P   
             USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ 

Читаем о
  PLL_M

Bits 5:0 PLLM: Division factor for the main PLL (PLL) and audio PLL (PLLI2S) input clock
Set and cleared by software to divide the PLL and PLLI2S input clock before the VCO.
These bits can be written only when the PLL and PLLI2S are disabled.
Caution: The software has to set these bits correctly to ensure that the VCO input frequency
ranges from 1 to 2 MHz. It is recommended to select a frequency of 2 MHz to limit
PLL jitter.

Основное — на вход VCO  можно подавать частоту в диапазоне 1-2МГц . Рекомендуется 2МГц для ограничения джиттера PLL.

PLL_N

Bits 14:6 PLLN: Main PLL (PLL) multiplication factor for VCO
Set and cleared by software to control the multiplication factor of the VCO. These bits can
be written only when PLL is disabled. Only half-word and word accesses are allowed to
write these bits.
Caution: The software has to set these bits correctly to ensure that the VCO output
frequency is between 100 and 432 MHz.
VCO output frequency = VCO input frequency × PLLN with 50 ≤ PLLN ≤ 432

  Частота на выходе VCO  может быть в диапазоне 100-432 МГц .
PLL_P

Bits 17:16 PLLP: Main PLL (PLL) division factor for main system clock
Set and cleared by software to control the frequency of the general PLL output clock. These
bits can be written only if PLL is disabled.
Caution: The software has to set these bits correctly not to exceed 168 MHz on this domain.
PLL output clock frequency = VCO frequency / PLLP with PLLP = 2, 4, 6, or 8
00: PLLP = 2
01: PLLP = 4
10: PLLP = 6
11: PLLP = 8

  Как видим минимальный делитель PLL_P может быть только 2.
   
И исходя из вышеозвученных ограничений определяем необходимые параметры
                       множителей/делителей

  Кварц F4 дискавери 8МГц  - соответственно  PLL_N  выбираем 4

SYSCLK = PLL_VCO / PLL_P
  Sysclk должна быть 168МГц , минимальное значение PLL_P 2 -соответсвенно частота на    выходеVCO будет 168МГц *2 = 336МГц и множитель PLL_N  равен 168 :
PLL_N = PLL_VCO / ([HSE_VALUE or HSI_VALUE] / PLL_M)
PLL_N = 336МГц / (8МГц / 4)

Ну и PLL_Q

PLLQ =  PLL_VCO /USB OTG FS, SDIO and RNG Clock
PLLQ = 336МГц/48МГц
PLLQ=7

http://sg.uploads.ru/tALCm.png

В итоге :

Код:
 #define PLL_M  4
 #define PLL_N  168

 #define PLL_P   2
 #define PLL_Q   7

Кофигурируем систему тактирование.

Включаем HSE и дожидаемся его готовности.

Код:
RCC->CR|= RCC_CR_HSEON;   
	  while (!(RCC->CR &RCC_CR_HSERDY)){};

Определяем делители шин.

Код:
RCC->CFGR |=RCC_CFGR_HPRE_DIV1|RCC_CFGR_PPRE2_DIV2|RCC_CFGR_PPRE1_DIV4;

на AHB 168МГц – предделитель 0;

Bits 15:13 PPRE2: APB high-speed prescaler (APB2)
Set and cleared by software to control APB high-speed clock division factor.
Caution: The software has to set these bits correctly not to exceed 84 MHz on this domain.
The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after
PPRE2 write.
0xx: AHB clock not divided
100: AHB clock divided by 2
101: AHB clock divided by 4
110: AHB clock divided by 8
111: AHB clock divided by 16
Bits 12:10 PPRE1: APB Low speed prescaler (APB1)
Set and cleared by software to control APB low-speed clock division factor.
Caution: The software has to set these bits correctly not to exceed 42 MHz on this domain.
The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after
PPRE1 write.
0xx: AHB clock not divided
100: AHB clock divided by 2
101: AHB clock divided by 4
110: AHB clock divided by 8
111: AHB clock divided by 16

  APB2=SYSCLK/2 = 168МГц/2 = 84МГц
APB1=SYSCLK/4 = 168МГц/4 = 42МГц

Заносим конфигурацию PLL.

Код:
RCC->PLLCFGR = PLL_M|(PLL_N<<6)|(((PLL_P>>1)-1)<<16)|RCC_PLLCFGR_PLLSRC_HSE|(PLL_Q<<24);

Включаем PLL и дожидаемся готовности PLL.

Код:
	RCC->CR |= RCC_CR_PLLON;
	while (!(RCC->CR &RCC_CR_PLLRDY)){};

Настраиваем Flash prefetch, instruction cache, data cache и wait state :
см таблицу на стр. 80 RM0090

http://sa.uploads.ru/YxnMF.png

Код:
FLASH->ACR|=FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS | FLASH_ACR_PRFTEN;

Переключаем системное татирование на PLL.

Код:
	RCC->CFGR &= ~RCC_CFGR_SW;
  RCC->CFGR |= RCC_CFGR_SW_PLL;

И дожидаемся этого переключения.

Код:
 while (!(RCC->CFGR & RCC_CFGR_SWS ) ){};

Для контроля выводим SYSCLK на MCO2 (PC9), частота на MCO2 =  SYSCLK/5:

Код:
	RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN;
	GPIOC->MODER&=~GPIO_MODER_MODE9;
	GPIOC->MODER|=GPIO_MODER_MODE9_1;
	GPIOC->OSPEEDR|=GPIO_OSPEEDER_OSPEEDR9;
	RCC->CFGR|=RCC_CFGR_MCO2PRE;

2

Код:
#define PLL_M  4
#define PLL_N  168
#define PLL_P   2
#define PLL_Q   7

void SystemInit(void)
{
  /* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif
  
	RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN;
	GPIOC->MODER&=~GPIO_MODER_MODE9;
	GPIOC->MODER|=GPIO_MODER_MODE9_1;
	GPIOC->OSPEEDR|=GPIO_OSPEEDER_OSPEEDR9;
	RCC->CFGR|=RCC_CFGR_MCO2PRE;
	
	
	RCC->CR|= RCC_CR_HSEON;
	while (!(RCC->CR &RCC_CR_HSERDY)){};
	
    
	RCC->CFGR |=	RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 |RCC_CFGR_PPRE1_DIV4;
	RCC->PLLCFGR = PLL_M|(PLL_N<<6)|(((PLL_P>>1)-1)<<16)|RCC_PLLCFGR_PLLSRC_HSE|(PLL_Q<<24);
	
	RCC->CR |= RCC_CR_PLLON;
	while (!(RCC->CR &RCC_CR_PLLRDY)){};
	
  FLASH->ACR|=FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS | FLASH_ACR_PRFTEN;
    
	RCC->CFGR &= ~RCC_CFGR_SW;
  RCC->CFGR |= RCC_CFGR_SW_PLL;

   
  while (!(RCC->CFGR & RCC_CFGR_SWS ) ){};
   

  
}

3

Система тактирования для F0 , на примере  F042x, F072x

Открываем даташиты на чипы и RM0091

Так же находим Clock tree .

http://se.uploads.ru/q4hGo.png

http://s4.uploads.ru/fbkhH.png

http://s4.uploads.ru/lkQBO.png

Обратите внимание, в свежих даташитах наконец-то корректно обозначены сущности .
На сером фоне, белым текстом.

http://s45.radikal.ru/i108/1703/95/d3ca17bc39b8.png

http://i026.radikal.ru/1703/60/08f18dee7fc9.png

4

Для F072 и F042  тактирование системы от PLL , PLL от HSI.
  Sysclk 48MHz .

Код:
  void SystemInit (void)
    	{     
    	if ((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL)  
    	{ 
    	 RCC->CFGR &= (uint32_t) (~RCC_CFGR_SW);
    	 while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) 
    	 {
    	
    	 }
    	}
    	
    	RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
    	while((RCC->CR & RCC_CR_PLLRDY) != 0) {};
    	FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
    	RCC->CFGR|=RCC_CFGR_PLLSRC_0;
    	RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_PLLMUL)) | (RCC_CFGR_PLLMUL6); 
    	
    	RCC->CR |= RCC_CR_PLLON; 
    	while((RCC->CR & RCC_CR_PLLRDY) == 0){};
    	
    	RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
    	while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {};
    	
    	}
    	

  Здесь собственно и разбирать-то нечего.
Вначале выясняем -если система тактируется от PLL , переключаемся на тактирование от HSI и дожидаемся этого переключения(зачем?)
Выключаем PLL, ждем разлочки PLL.
Настраиваем PLL, латентность flash.
Включаем PLL, дожидаемся готовности PLL.
Переключаем тактирование системы на PLL и дожидаемся этого переключения.

5

Для F072 и F042  тактирование системы от PLL , PLL от HSE.
  Sysclk 48MHz

Код:
void SystemInit (void)
    	{     
    	if ((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL)  
    	{ 
    	 RCC->CFGR &= (uint32_t) (~RCC_CFGR_SW);
    	 while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) 
    	 {
    	
    	 }
    	}
    	RCC->CR |= ((uint32_t)RCC_CR_HSEON);
          while((RCC->CR & RCC_CR_HSERDY) == 0)    
          {          
          }
        

    	RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
    	while((RCC->CR & RCC_CR_PLLRDY) != 0) {};
    	FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
    	RCC->CFGR|=RCC_CFGR_PLLSRC_1;
    	RCC->CFGR = (RCC->CFGR & (~RCC_CFGR_PLLMUL)) | (RCC_CFGR_PLLMUL6); 
    	
    	RCC->CR |= RCC_CR_PLLON; 
    	while((RCC->CR & RCC_CR_PLLRDY) == 0){};
    	
    	RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
    	while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {};
    	
    	}
    	

6

Разъясните,пожалуйста.
По умолчанию,регистр CFGR сброшен.
http://s3.uploads.ru/t/1UmzY.jpg
Но Вы(и не только,это встречается и в примерах от СТМ) некоторые биты сбрасываете:
RCC->CFGR &= ~RCC_CFGR_SW;
В чём причина таких действий?

7

Например потому, что  инит тактовой не только при сбросе может быть, а и на лету ...

8

Перестраховка?

9

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

10

Спасибо.

11

Подскажите, есть ли какое то красивое решение определения sysclock? В смысле измерить надо, исходя из того что мы не знаем ничего о источнике тактового сигнала. Вывести на MCO sysclock, подключить к входу счетчика(таймера). Но это требует внешних цепей :) провод, но он нужен. а можно ли как то по "SISTEMTIMER" определить? его делитель известен. тогда не надо внешних цепей, но как? алгоритм какой?

12

домовой Зачем тебе это надо, чтобы устройство работало от любого кварцевого резонатора?

13

MasterElectric написал(а):

домовой Зачем тебе это надо, чтобы устройство работало от любого кварцевого резонатора?

Ну что то в этом духе. Не моя "тайна" зачем это надо. Предположим что HSI поплыл у меня, и надо точно (насколько это возможно) подправить калибровочную часть. Может получится так, что доступа к плате нет, а SWD выведен. :) ну где то так или около того.

14

возможно.
  \brief  Structure type to access the System Timer (SysTick).
*/
typedef struct
{
  __IOM uint32_t CTRL;                   /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
  __IOM uint32_t LOAD;                   /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register */
  __IOM uint32_t VAL;                    /*!< Offset: 0x008 (R/W)  SysTick Current Value Register */
  __IM  uint32_t CALIB;                  /*!< Offset: 0x00C (R/ )  SysTick Calibration Register */
} SysTick_Type;

http://infocenter.arm.com/help/index.js … ieigh.html

Отредактировано домовой (2017-09-06 20:56:35)

15

Что-то у меня вообще лыжи не едут: взял инициализацию таймера по 8МГц HSI → 72МГц из SPL'ного CMSIS'а. Пытаюсь зажечь светодиоды на девборде с STM32F103:

Код:
int main(void){
    sysreset();
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
    GPIOB->CRH = 0x00000066; // PB8/9 - 2MHz opendrain 
    GPIOB->ODR = 0;
    while(1){}
    return 0;
}

Вообще ноль реакции!!! Без sysreset() оно тоже не работает, хотя должно! То ли я где-то намудрил, пока из заголовочных файлов opencm3 и SPL сооружал НĒХ, то ли где-то что-то упустил. Но что можно упустить, что МК даже в main() не заходит (хотя main явно вызывается из reset_handler)?

16

Код:
void Sys_ClockInit(void)
{// HSE = 8000000; SYSCLK = 72000000; APB1 = 36000000; APB2 = 72000000
  FLASH->ACR = 0x30 | FLASH_ACR_LATENCY_2;  //

  RCC->CR |= RCC_CR_HSEON;                                                        //включаем генератор HSE
  while(!(RCC->CR & RCC_CR_HSERDY));                                           //ожидание готовности HSE
  RCC->CFGR = RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9 | RCC_CFGR_PPRE1_2;          //источник тактовых сигналов дл¤ PLL выбираем HSE
  RCC->CR |= RCC_CR_PLLON;                                                     //включаем PLL
  while(!(RCC->CR & RCC_CR_PLLRDY));                                        //ожидание готовности PLL
  RCC->CFGR |= RCC_CFGR_SW_PLL;                                            //выбираем PLL для тактирования
}

попробуй этот, только нужно запускать код в состоянии после сброса.

17

Не работает, зараза!
Чип точно рабочий: попробовал прошивку старую прошить - работает.
Чертовщина какая-то!!

18

Попробовал минимальный пример запустить отсюда, запустилось, мыргает.
ЧЕрт! Это получается, я где-то накосячил на развалах бешеных толп заголовочных файлов. Как только подключаю свой стартам, сразу все не работает! Т.е. reset_handler либо вообще не вызывается, либо почему-то из себя не вызывает main. Но как-то нужно чертовы таблицы прерываний инициировать, да и я хотел сделать общую базу для всей линейки STM32, чтобы директория с инклюдами была одной для всех.
Буду рукожопить дальше.

19

Вот какую странную штуку обнаружил. Если все закомментировать, т.е. сделать вот так:

Код:
void WEAK __attribute__ ((naked)) reset_handler(void)
{
/*
    volatile unsigned *src, *dest;
    funcp_t *fp;

    for (src = &_data_loadaddr, dest = &_data;
        dest < &_edata;
        src++, dest++) {
        *dest = *src;
    }

    while (dest < &_ebss) {
        *dest++ = 0;
    }

    /* Constructors. 
    for (fp = &__preinit_array_start; fp < &__preinit_array_end; fp++) {
        (*fp)();
    }
    for (fp = &__init_array_start; fp < &__init_array_end; fp++) {
        (*fp)();
    }
    */

    /* Call the application's entry point. */
    main();

    /* Destructors. 
    for (fp = &__fini_array_start; fp < &__fini_array_end; fp++) {
        (*fp)();
    }*/
}

то работает, иначе - хрен!
Ну и ядрен батон! А данные как копировать?

20

Настало время поговорить о пользе дебуггера?

21

А зачем тебе стартап на си. Если это ресет хендлер, то тогда вроде как не инициализируеться регистр MSP ядра. А т.к. локальные переиенные храняться в стеке вот вам и хардфаулт.

22

Выяснил, что если у меня только константы, reset_handler зависает, если добавить переменную - инициализированный массив, то все ОК. Как это работало в opencm3, я не понимаю. Абсолютно этот же код прекрасно работает под STM32F0. В общем, психика моя истощена, и я решил послать нахер эти 103, пока не понадобятся (надеюсь, этого не будет никогда), буду спокойно с F0 продолжать работать, не портя своего здоровья.

Настало время поговорить о пользе дебуггера?

Да насрать мне на дебаггер: я им не умею пользоваться и не собираюсь учиться! Да и в данной ситуации он абсолютно ничем не поможет. Особенно прикольно, когда gcc генерит неправильные файлы (в первом слове почему-то неправильный объем памяти указан).

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

23

А не чет я перепутал, адрес стека инициализируеться автоматически. Но в стартапах от атоллика они еще раз инициализируют SP вот я и подумал...

24

MasterElectric написал(а):

А не чет я перепутал, адрес стека инициализируеться автоматически. Но в стартапах от атоллика они еще раз инициализируют SP вот я и подумал...

Если запускать из RAM при очищенном флеше, то нужно SP вручную инитить.

Отредактировано Reflector (2018-11-04 16:46:50)

25

Там подкрутил, сям подкрутил, работает. Но что-то у меня systick выдает 50 импульсов за 10 секунд (вместо 10 импульсов), когда я его настраиваю на период в 0.5с (9000*500) - а по схеме у него частота в 8 раз ниже системной, т.е. 9МГц... Ковыряюсь дальше...

26

Источник для тактирования можно выбирать (SysTick_CTRL_CLKSOURCE_Msk ). Вот рабочий код (без делителя):

Код:
  /* запускаем системный таймер */
  SysTick->LOAD = SYS_CLK/10000 - 1; // Загрузка значения в 0.1 ms
  SysTick->VAL = SYS_CLK/10000 - 1; // Устанавливаем текущее значение
  SysTick->CTRL= SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;

27

Eddy_Em написал(а):

Хреново, что этим микроконтроллерам уже столько лет, а нигде в сети нет вменяемого набора файлов "бери и пользуйся".

Вообще-то, лично для меня это и была превоначальная цель этого форума, но... что-то пошло не так )

28

MasterElectric, в core_cm3.h все уже есть:

Код:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)  return (1);      /* Reload value impossible */

  SysTick->LOAD  = ticks - 1;                                  /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

В картинке из даташита на 103 нарисовано, что Cortex System timer идет после деления AHB (она у меня как и системная шина - 72МГц) на восемь. А вот фиг там!!! Почему-то этого деления не происходит, и чтобы выставлять SysTick на нужное количество миллисекунд, мне приходится делать так:

Код:
static void systick_setup(uint32_t xms){
    static uint32_t curms = 0;
    if(curms == xms) return;
    // this function also clears counter so it starts right away
    SysTick_Config(72000 * xms);
    curms = xms;
}

29

А я вам писал что источник можно выбирать деленный или нет. За это отвечает бит SysTick_CTRL_CLKSOURCE_Msk регистра CTRL. Хорошо что в CMSIS есть, но я особо там не рылся.

30

И действительно, спасибо! Таперча я совершенно спокоен.
Надо бы поискать еще RM на ARM (сайт, собака, в html документацию не показывает - говорит, мол, зарегистритуйся сначала).
Непонятно, какого хрена во всех RM на STM32 тактирование SysTick неправильно нарисовано: /8 там напрямую от системной шины идет безо всякого условного обхода!


Вы здесь » Микроконтроллеры » Архив » STM32 Система тактирования