本文基于STM32F103RBT6微控制器,深入源码,详细分析了时钟中断处理程序Systick_isr
。
1. Systick_isr源代码
static volatile clock_time_t current_clock = 0;
static volatile unsigned long current_seconds = 0;
static unsigned int second_countdown = CLOCK_SECOND; //详情见2.1
/***时钟中断处理程序***/
void SysTick_Handler(void)
{
usart_puts("systick isr\n");
SCB->ICSR = SCB_ICSR_PENDSTCLR; //详情见2.2
current_clock++;
if (etimer_pending() && etimer_next_expiration_time() <= current_clock) //timerlist不为空且还没有etimer到期,则执行etimer_request_poll。详情见2.3
{
etimer_request_poll(); //详情见2.4
}
if (--second_countdown == 0)
{
current_seconds++;
second_countdown = CLOCK_SECOND; //重置second_countdown
}
}
注:时钟中断处理程序与硬件相关,我用的是STM32F103RBT6。
2. 源码分析
2.1 CLOCK_SECOND宏
CLOCK_SECOND
定义了1秒钟产生时钟中断的次数,默认情况是32次,可以通过宏CLOCK_CONF_SECOND
来配置。源代码如下:
/*CLOCK_SECOND宏定义*/
#ifdef CLOCK_CONF_SECOND
#define CLOCK_SECOND CLOCK_CONF_SECOND
#else
#define CLOCK_SECOND (clock_time_t)32
#endif
#define CLOCK_CONF_SECOND 10 /*define systick clock interrupt times per second*/
2.2 SCB & ICSR
该语句主要对寄存器进行设置,SCB指System Control Block,ICSR指Interrupt Control State Register,SCB_ICSR_PENDSTCLR是Clear pending SysTick bit。
#define SCB_ICSR_PENDSTCLR ((uint32_t)0x02000000) /*Clear pending SysTick bit */
2.3 etimer_pending函数和etimer_next_expiration_time函数
etimer_pending
函数检查timerlist
是否为空(若返回true表示不为空),etimer_next_expiration_time
函数返回next_expiration
(即到了next_expiration
才有etimer
到期。另,若timerlist
为空则返回0),并与系统当前时间current_clock
比较,若next_expiration
小于等于current_clock
,则表明还没有etimer
到期,于是把系统进程etimer_process
的needspoll
设为1,使其具有更快地再次获得执行。
2.3.1 etimer_pending函数
检查timerlist
是否为空,若不为空则返回true
,否则返回false
,源码如下:
/*Check if there are any non-expired event timers*/
int etimer_pending(void) //如果返回true则表明timerlist不为空
{
return timerlist != NULL;
}
2.3.2 etimer_next_expiration_time函数
next_expiration
是指timerlist
下一个到期的时间,即到了next_expiration
就会有etimer
到期,由update_time
计算,详情见博文《系统进程etimer_process》。
/*得到next_expiration,如果timerlist为空,则返回0*/
clock_time_t etimer_next_expiration_time(void)
{
return etimer_pending() ? next_expiration : 0;
}
2.4 etimer_request_poll函数
将系统进程etimer_process
的needspoll
设为1,使其获得更高优先级,即让etimer_process
更快地再次获得执行。详情见博文《系统进程etimer_process》。