Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 6.

Настройка системы тактирования.

Часть 1. Установка MDK, создание проекта, основы Keil uVision

Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32.

Часть 3. Карта памяти контроллеров STM32, методы работы с памятью.

Часть 4. Регистры, старт и режимы работы контроллеров STM32.

Часть 5. Как залить прошивку в контроллер.

Часть 6. Настройка системы тактирования.

Часть 7. Работа с портами ввода-вывода.

Контроллеры STM32 обладают достаточно развитой системой тактирования, включающей кучу различных делителей, умножителей и селекторов, которые позволяют "разогнать" до 72 МГц частоту ядра и системной шины, а также организовать тактирование на различных частотах всех входящих в состав контроллера модулей (USB, I/O, I2C, SPI...).

При этом стартует контроллер всегда от внутреннего генератора на 8 МГц, а дальнейший "разгон" и настройка тактирования различных модулей выполняется программно.

Все регистры, отвечающие за настройку системы тактирования сгруппированы в так называемый блок RCC (reset and clock control). Это десять 32-х битных регистров, доступных в памяти начиная с адреса 0x40021000, названия которых начинаются с "RCC_".

Настройку системы тактирования можно разделить на два этапа. На первом этапе настраивается системная тактовая частота. На втором этапе - частота системной шины AHB и подключенные к шине AHB модули. Отдельно от этих двух этапов можно настроить низкоскоростные генераторы для часов реального времени и независимого "собачьего таймера".

Тут важно запомнить и понять вот что: 1) все модули контроллера "сидят" на каких-нибудь шинах, 2) после включения контроллера тактирование большинства модулей, а также тактирование периферийных шин - выключены. Соответственно, до тех пор, пока вы не затактируете выключенные шины и модули - вам не будут доступны регистры настройки модулей. Из этих регистров будут читаться одни нули, а запись в них не будет иметь никакого эффекта.

Структурной схему, показывающую какие в контроллере есть шины и модули, какие модули к какой шине подключены и какие регистры используются для настройки всей этой системы, можно найти в документации. Тут самый главный документ - это Reference Manual RM0008 (CD00171190.pdf).

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

Настройка системной частоты, часов реального времени и независимого собачьего таймера

Серыми прямоугольниками в левом ряду обозначены 4 первичных источника тактовых сигналов: HSI - высокоскоростной встроенный RC-генератор, HSE - усилитель внешнего высокоскоростного кварцевого резонатора, LSE OSC - усилитель часового кваца (внешний низкоскоростной резонатор), LSI RC - низкоскоростной RC-генератор.

Настройка приведённого на рисунке выше "дерева" происходит слева-направо, начиная с выбора первичных источников тактового сигнала. При этом общая методика такая: настраиваем модуль, включаем модуль, ждём сигнала готовности. После получения сигнала готовности переходим к настройке компонента, находящегося правее.

Сигнал готовности означает, что выходная частота соответствующего компонента стабилизировалась и её можно использовать дальше. В качестве сигнала готовности используются специальные биты в специальных регистрах (индивидуальные для каждого модуля). На схеме эти регистры и биты не отражены, но их можно найти в документации. Например, о готовности PLL сигнализируется установкой бита PLLRDY в регистре RCC_CR, о готовности усилителя внешнего кварца - установкой бита HSERDY в регистре RCC_CR и так далее.

Интересной фишкой является наличие в процессоре Cortex-M3 модуля CSS (clock security system). Этот модуль включается программно и после включения начинает анализировать работу внешнего кварца (HSE). При обнаружении ошибки, он автоматически отключает внешний кварц и переключает селектор выбора системной частоты на внутренний высокоскоростной генератор (HSI). Если HSE использовался не напрямую, а через PLL, то PLL тоже выключается. Кроме того, при срабатывании модуля CSS генерируется прерывание NMI И посылаются сигналы ошибки таймерам TIM1, TIM8.

После того, как первый этап закончен - можно приступать ко второму. Настраиваемые на этом этапе компоненты и последовательность их настройки также изображены в виде древовидной структуры (рисунок ниже).

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

Если мы работаем с flash-памятью, а не перегружаем программу в оперативку, то для оптимальной работы нашего камня должны быть настроены ещё кое-какие опции.

Во-первых, нужно задать параметр, называемый Latency. Это количество циклов задержки для операций чтения из flash. Оно задаётся исходя из следующих правил:

=0, если 0 ≤ SYSCLK ≤ 24 MHz;

=1, если 24 MHz ≤ SYSCLK ≤ 48 MHz;

=2, если 48 MHz ≤ SYSCLK ≤ 72 MHz.

Во-вторых, для ускорения работы процессора, должен быть включен буфер предварительной выборки (prefetch buffer), который позволяет вычитывать инструкции из flash двумя 64-х битными блоками. Включить или выключить этот буфер можно только когда SYSCLK < 24 MHz и делитель шины AHB=1. После сброса он автоматически включается, поэтому нам ничего делать не нужно. Но обычно если его хотят выключить, то делают это в самом начале программы, при инициализации, когда контроллер ещё работает от внутреннего генератора 8 MHz.

Обе перечисленные выше настройки flash-памяти доступны в регистре FLASH_ACR.

Для контроля полученных в итоге частот можно использовать специальную ногу (PA8), одна из функций которой - работа в качестве MCO (microcontroller clock output). На эту ногу можно настроить вывод одной из следующих частот: SYSCLK, HSI, HSE, PLL/2. Выбор осуществляется программированием битов MCO[2:0] в регистре RCC_CFGR. Кроме программирования этих битов нужно затактировать шину APB2 (на которой находится GPIO) и настроить ногу PA8 на функционирование в качестве MCO. Кроме того, при использовании PA8 в качестве MCO необходимо учитывать, что частота GPIO не должна превышать 50 МГц (а SYSCLK как мы помним можно разогнать до 72-х).

Ну вот пожалуй и всё. А в заключении давайте напишем небольшой пример - разгоним наш камень до заветных 72-х МГц и выведем частоту PLL/2 через MCO:

;---------------------------------------------------------
; blocks addresses
SAR         EQU 0x42000000 ; Start Alias Region
FLASH       EQU 0x40022000
RCC         EQU 0x40021000
PORTA       EQU 0x40010800
; registers addresses
FLASH_ACR   EQU FLASH+0x0
RCC_CR      EQU RCC+0x0
RCC_CFGR    EQU RCC+0x4
RCC_APB2ENR EQU RCC+0x18
GPIOA_CRH   EQU PORTA+0x4
; bits numbers
LAT1        EQU 1
HSEON       EQU 16
HSERDY      EQU 17
PLLSRC      EQU 16
PLLMUL      EQU 18
PPRE2       EQU 11
PLLON       EQU 24
PLLRDY      EQU 25
SW1         EQU 1
AFIOEN      EQU 0
IOPAEN      EQU 2
MCO         EQU 24
MODE8       EQU 0
CNF8        EQU 2

	AREA STACK, NOINIT, READWRITE
	SPACE 0x400
Stack_top

	AREA RESET, DATA, READONLY
	dcd Stack_top
	dcd Program_start
	
	AREA PROGRAM, CODE, READONLY
	ENTRY
Program_start
InitClock
	mov r9, #1
   ; устанавливаем Latency = 2
	ldr r0, =SAR+(FLASH_ACR&0x00FFFFFF)*0x20+LAT1*4
	str r9,[r0]
   ; включаем HSE
	ldr r0, =SAR+(RCC_CR&0x00FFFFFF)*0x20+HSEON*4
	str r9,[r0]
   ; ждём появления флага HSERDY
	ldr r0, =RCC_CR      ; загружаем в r0 адрес регистра RCC_CR
wait_hserdy
	ldr r10,[r0]         ; читаем регистр RCC_CR
   ; проверяем, равен ли бит HSERDY единице (&0x20000)
	tst r10,#(1<<HSERDY)
	beq wait_hserdy
   ; выбираем HSE источником для PLL, устанавливаем множитель=9,
   ; предделитель для APB2 (/2), выбираем источник для MCO
	ldr r0,=RCC_CFGR     ; загружаем адрес регистра RCC_CFGR
	ldr r10,=(1<<PLLSRC)+(7<<PLLMUL)+(4<<PPRE2)+(7<<MCO)
	str r10,[r0]
   ; включаем PLL
	ldr r0,=SAR+(RCC_CR&0x00FFFFFF)*0x20+PLLON*4
	str r9,[r0]
   ; ждём появления флага PLLRDY
	ldr r0, =RCC_CR      ; загружаем адрес регистра RCC_CR
wait_pllrdy
	ldr r10,[r0]         ; читаем RCC_CR
   ; проверяем, равен ли бит PLLRDY единице (&0x2000000)
	tst r10, #(1<<PLLRDY)
	beq wait_pllrdy
   ; выбираем PLL в качестве SYSCLK
	ldr r0,=SAR+(RCC_CFGR&0x00FFFFFF)*0x20+SW1*4
	str r9,[r0]
   ; включаем тактирование PORTA
	ldr r0,=SAR+(RCC_APB2ENR&0x00FFFFFF)*0x20+IOPAEN*4
	str r9,[r0]
   ; конфигурим PORTA для MCO
	ldr r0,=GPIOA_CRH
	ldr r10,[r0]         ; читаем регистр GPIOA_CRH
   ; устанавливаем для PA8 MODE=11 (output max speed 50MHz),
   ; CNF=10  (alternate function output push-pull)
	ldr r11,=(3<<MODE8)+(2<<CNF8)
	bfi r10, r11, #0, #4 ; копируем 4 младших бита r11 в r10
	str r10,[r0]         ; записываем r10 в GPIOA_CRH
;------------------
   ; ничего не делаем
Work
	b Work
	END
;---------------------------------------------------------

Естественно, в реальности никто в заголовке имена и адреса регистров и битов не описывает, вместо этого берут готовый файл, в котором все эти имена описаны и добавляют его в свой код директивой GET. В примере я их специально описал, чтобы было понятно, откуда что берётся (сопоставьте их с картой памяти, которую мы рассматривали в третьей части).

Ну да ладно, пусть этот код и не самый оптимальный, зато, надеюсь, предельно понятный. Для установки отдельных битов в примере используется метод bit-banding, если требуется изменить сразу кучу битов - классические "чтение-модификация-запись".

Если есть вопросы - как обычно, задаём на форуме.

Часть 1. Установка MDK, создание проекта, основы Keil uVision.

Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32.

Часть 3. Карта памяти контроллеров STM32, методы работы с памятью.

Часть 4. Регистры, старт и режимы работы контроллеров STM32.

Часть 5. Как залить прошивку в контроллер.

Часть 6. Настройка системы тактирования.

Часть 7. Работа с портами ввода-вывода.

radiohlam.ruтеорияконтроллеры и программирование

Понравилась статья? Поделись с друзьями!

Обсудить эту статью на форуме

 
Rambler's Top100 © 2009 - Материалы сайта охраняются законом об авторском праве