суббота, 17 марта 2012 г.

I & STM32-discovery part13 - clocking

Второй частью блока сброса и генерации тактового сигнала, является собственно блок генерации тактового сигнала. Свойственное армам и семейству stm32 богатство периферии, распространяется и на этот блок. Большое количество настроек позволяет максимально удобно настроить тактовую частоту основных блоков.



3 источника тактового сигнала для системного тактирования (SYSCLK):
  • HSI - высокоскоростной встроенный осциллятор тактового сигнала
  • HSE - высокоскоростной внешний осциллятор тактового сигнала
  • PLL - ФАПЧ для гибкой настройки тактового сигнала
2 источника тактового сигнала для вторичных системных нужд:
  • LSI - низкоскоростной 40 кГц встроенный осциллятор для сервисных устройств: ватчдоги, часы реального времени и системы авто-старта для режимов ожидания/останова.
  • LSE - низкоскоростной 32768 Гц внешний осциллятор для опционального источника тактового сигнала часов реального времени
Источники и блоки могут быть подключены и отключены, когда не использованы для оптимизации энергопотребления
Как видно из блок-схемы, источники через делители и предделители, множители в ФАПЧ поставляют тактовый сигнал до потребителей - блоков периферии. Когда нет проблем по потреблению то предпочтительнее использование внешних источников тактового сигнала т.к. они стабильнее внутренних. Однако внутренние предпочтительнее по потреблению и безопасности.

Основной тактовый сигнал разделен и пропущен через блоки предделителей для того чтобы соответствовать требованиям периферии. Для основной линии используется сигнал с AHB источника, который используется для генерации тактового сигнала арм ядра, ПДП, системного таймера, AHB шины.

Далее через предделители APB1(низкоскоростная линия) и APB2(высокоскоростная линия) сигнал подается на таймеры через предделители или напрямую на различные блоки периферии. Отдельно с APB2 сигнал через собственный предделитель идет на АЦП.

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

Также присутствует вывод для тактового сигнала - можно потключить внешние потребители тактового сигнала. Источником для этого вывода могут быть:
  • SYSCLK
  • HSI
  • HSE
  • PLL тактовый сигнал деленный на 2
Система защиты тактового сигнала (CSS). Данный блок следит за тактовым сигналом HSE и автоматически при его сбое совершает группу действий направленную на стабилизацию системы при сбое. Останавливается осциллятор HSE, генерируется немаскируемое прерывание CSSI. После происходит переключение на внутренний источник тактового сигнала HSI, если было использование PLL он также будет выключен.

Тактирование часов реального времени осуществляется от нескольких источников - HSE/128, LSE или LSI. Это программируется из регистра резервного домена RCC_BDCR и не может быть изменено без сброса самого домена.

Более подробно о всех подробностях тактовой системы можно прочитать в соответствующем разделе дш, а мы переходим к практическому примеру. В качестве примера возьмем следующий алгоритм - в пример с использованием в таймере ШИМ добавим в качестве основного тактового сигнала ФАПЧ ( с использованием HSE), частоту которого будем увеличивать с каждым внешним прерыванием. А заодно поставим прерывание на сбой внешнего тактового сигнала, активацию которого будет индицировать другой один светодиод, другой оставим для индикации основного тактового сигнала.

Как обычно начинаем с создания проекта:

nis@jane ~/stm32/examples $ cp -a 06-tim3-pwm/ 08-clocking
nis@jane ~/stm32/examples $ cd 08-clocking/

В код функции main добавим защиту от сбоя внешнего осциллятора тактового сигнала. После этого добавим код инициализации внешнего осциллятора, настройку ФАПЧ и переключение его на внешний осциллятор, переключение системы генерации тактового сигнала на ФАПЧ:

        /* enable security HSE - CSS */
        RCC->CR |= RCC_CR_CSSON;
        /* setup PLL from HSE */
        /** enable HSE and wait to ready */
        RCC->CR |= RCC_CR_HSEON;
        while ((RCC->CR & RCC_CR_HSERDY) == 0);
        /** setup PLL, enable and wait to ready */
        RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
        RCC->CFGR |= (RCC_CFGR_PLLSRC_PREDIV1);
        RCC->CR |= RCC_CR_PLLON;
        while ((RCC->CR & RCC_CR_PLLRDY) == 0);
        /** select PLL for system clock and wait to select */
        RCC->CFGR &= ~RCC_CFGR_SW;
        RCC->CFGR |= RCC_CFGR_SW_PLL;
        while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0);

Также перестроим блоки сравнения/захвата:

/** setup value to compare registers 3..4 */
        TIM3->CCR3 = 0;
        TIM3->CCR4 = 500;

В файле системной инициализации, векторов и обработчиков прерываний - startup.c добавим функцию обработки на немаскируемое прерывание - именно его вызывает ядро мк по событию системы защиты тактового сигнала:

 /* NMI interrupt */
void NMI_Handler(void) {
    if (RCC->CIR & RCC_CIR_CSSF) {
        /* fail led blink enabled */
        TIM3->CCR3 = 100;
        /* reset CSSC flag */
        RCC->CIR |= RCC_CIR_CSSC;
    }
}

А также изменим прерывание по внешенему событию чтобы оно переключало множитель ФАПЧ:

/* EXTI line0 interrupt */
void EXTI_L0_Handler(void) {
    if (EXTI->PR & (1 << 0)) {
        volatile static int pll_mul = 0;
        /* change multiply for PLL */
        if (pll_mul > (4 << 18))
            pll_mul = 0;
        else
            pll_mul += (1 << 18);
        /* if enable HSI CSS enabled, return */
        if ((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_HSI)
            return;
        /* switch to HSI and wait for stable*/
        RCC->CFGR &= ~RCC_CFGR_SW;
        while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);
        /* disable PLL and wait for off */
        RCC->CR &= ~RCC_CR_PLLON;
        while ((RCC->CR & RCC_CR_PLLRDY) == 1);
        /* setup PLL, enable and wait to ready */
        RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
        RCC->CFGR |= (RCC_CFGR_PLLSRC_PREDIV1 | pll_mul);
        RCC->CR |= RCC_CR_PLLON;
        while ((RCC->CR & RCC_CR_PLLRDY) == 0);
        /* select PLL for system clock and wait to select */
        RCC->CFGR &= ~RCC_CFGR_SW;
        RCC->CFGR |= RCC_CFGR_SW_PLL;
        while ((RCC->CFGR & RCC_CFGR_SWS_PLL) == 0);
        /* reset EXTI flag */
        EXTI->PR |= (1 << 0);
    }
   
}


Полный исходный код проекта. main.c:


startup.c:

Cоберем проект и зальем прошивку в мк:

nis@jane ~/stm32/examples/08-clocking $ make all write
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F10X_MD_VL -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f100xb_flash.ld   -c -o startup.o startup.c
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F10X_MD_VL -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f100xb_flash.ld -o firmware.elf main.o sys_init.o startup.o -L.
arm-softfloat-linux-gnueabi-objcopy -O binary firmware.elf firmware.bin
st-flash write v1 firmware.bin 0x8000000
2012-03-16T23:51:36 INFO src/stlink-sg.c: Current mode unusable, trying to get back to a useful state...
2012-03-16T23:51:36 WARN src/stlink-sg.c: received tag 0 but expected 3
2012-03-16T23:51:36 INFO src/stlink-common.c: Loading device parameters....
2012-03-16T23:51:36 INFO src/stlink-common.c: Device connected is: F1 Medium-density Value Line device
2012-03-16T23:51:36 INFO src/stlink-common.c: SRAM size: 0x2000 bytes (8 KiB), Flash: 0x20000 bytes (128 KiB) in pages of 1024 bytes
2012-03-16T23:51:36 INFO src/stlink-sg.c: Successfully opened a stlink v1 debugger
2012-03-16T23:51:36 INFO src/stlink-common.c: Successfully unlocked flash
Erasing chip entirely... Done
2012-03-16T23:51:36 INFO src/stlink-common.c: Attempting to write 884 (0x374) bytes to stm32 address: 134217728 (0x8000000)
2012-03-16T23:51:36 INFO src/stlink-common.c: Erasing flash page at addr: 0x8000000
2012-03-16T23:51:36 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-16T23:51:36 INFO src/stlink-common.c: Finished erasing 1 pages of 1024 (0x400) bytes
2012-03-16T23:51:36 INFO src/stlink-common.c: Starting Flash write for VL core id
2012-03-16T23:51:36 INFO src/stlink-common.c: Successfully loaded flash loader in sram
2012-03-16T23:51:36 INFO src/stlink-common.c: Writing flash block 0 of size 64 (0x40)
...
2012-03-16T23:51:37 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-16T23:51:37 INFO src/stlink-common.c: Writing flash block 13 of size 64 (0x40)
2012-03-16T23:51:37 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-16T23:51:37 INFO src/stlink-common.c: Starting verification of write complete
2012-03-16T23:51:37 INFO src/stlink-common.c: Flash written and verified! jolly good!


И наконец видео:
На этом все.