Страницы

Страницы

суббота, 29 ноября 2014 г.

SysTick

Для обработчика системного исключения таймера SysTick заголовок функции-обработчика будет выглядеть так:

void SysTick_Handler(void)

Для обеспечения корректной работы обработчика необходимо , как минимум, назначить системному исключению приоритет и сбросить его в неактивное состояние после обработки (т.е., всё так же, как и у обычного прерывания). Но приоритеты системных исключений назначаются не в регистрах NVIC, а в регистрах системного блока управления (System control block), которые называются SHPR1 — SHPR3 (для разнообразия, они нумеруются, начиная с 1, а не с 0, т.е. регистра SHPR0 не существует). Приоритет системного исключения SysTick задаётся в регистре SHPR3, в битах [31:24]. Адрес регистра SHPR3 равен 0xE000ED20, и мы можем записать:

unsigned long  * pSHPR3 = (unsigned long *)0xE000ED20;
 
* pSHPR3 = SYS_TICK_PRIORITY << 24;

Сброс прерывания SysTick в неактивное состояние осуществляется с помощью регистра ICSR того же системного блока управления.

Обработчик системного исключения SysTick выглядит так:

void SysTick_Handler(void)
{
//тело обработчика
//сброс прерывания
ICSR_bit.PENDSTCLR = 1;
}

И, в заключение, ещё одна особенность, на этот раз связанная с обработкой прерывания Repetitive Interrupt Handler. У этого прерывания сброс в неактивное состояние нужно выполнять так:

RICTRL_bit.RITINT = 1;

Здесь RICTRL — регистр управления самого таймера RIT. Сброс прерывания в контроллере NVIC выполнится при этом автоматически.



В Cortex-M перечень (имен)функций обработчиков прерывания можно найти в startup.S. Эти функции имеют атрибут weak - "слабый", и вместо тел функций обработчиков проложены заглушки. Для задействования своего обработчика достаточно написать в любом *.c файле, включенном в проект, своей функции с тем же именем - компилятор зацепит её - она без атрибута weak. В Cortex-M завсегда есть в ядре SysTick таймер. Для его использования нужно выполнить SysTick_Config() и написать свой обработчик SysTick_Handler.


unsigned long SysTickCounter;
void SysTick_Handler(void){
  SysTickCounter++;
  // здесь, например, вставляем свои таймерные прибамбахи типо индикации
}
unsigned long clock(void){
  return SysTickCounter;
}
unsigned long clock_Elapsed(unsigned long start){
  return clock() - start; //вычитание беззнаковых - если clock() < start, результат в эквиваленте даст clock() + ~0UL -
start, т.е. start - clock()
}
int main(void){
    SystemCoreClockUpdate();//в STM32 при работе от кварца значение SystemCoreClock пересчитывается из константы HSE_Value
    SysTick_Config(SystemCoreClock/1000);//1 ms; для 100 мкс SystemCoreClock/10000, для 10 мс - SystemCoreClock/100

    ...
    unsigned long ts;
    do{
        ts = clock();
        LED_toggle();//тут придётся потрудиться:) написать мигалку
        while(clock_Elapsed(ts) < 100){//delay 100 ms
          ;//здесь тоже можно заняться чем-то полезным
        }
    }while(1);
   
}



1 комментарий: