【简介】
瑞萨的R2/N2L芯片采用的ARM R52 的内核,芯片的整体框图如下。

R52 的MCU 相对我们常用的M核的MCU在内核上是有很大差异的,通常在M核的 MCU 内部是集成了systick 的timer用来实现操作系统的调度时基。在R核的CPU 内部也是有个通用的Generic Timer 可以 实现类似的功能,我们可以先看下R52核 内部的通用timer 的描述。

从上述描述可以看出通用的定时器有EL1/EL2/和一个虚拟的timer,从ARM 的手册中可以看出不同的程序是运行在不同的等级下。

G timer 涉及的寄存器内容也不多,基本的定时器控制及定时器比较参数配置。


从上述的描述可以知道Generic Timer 的寄存器是通过CP15 的协处理器进行访问控制的。
以下是CP15 寄存器访问timer 寄存器的的代码实现
/* ACLE: Reads a system register */
#define __arm_rsr __iar_builtin_rsr
#define __get_CP(cp, op1, RT, CRn, CRm, op2) \
((RT) = __arm_rsr("p" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2))
/** \brief Get CNTV_CTL register
\return CNTV_CTL Register value
*/
__STATIC_FORCEINLINE uint32_t __get_CNTV_CTL(void)
{
uint32_t result;
__get_CP(15, 0, result, 14, 3, 1);
return result;
}上述代码对宏定义中的成员和寄存器的配置是一致的,对应关系如下

对应的定时器的使用还是很简单的,CNPCT寄存器记录着当前系统时间

CNTP_CVAL 记录着当前cmopare 的寄存器,一旦超过该值就会触发中断。

CNTP_CTL 寄存器可以用来开启关闭对应的定时器及中断使能配置。

有了上述的了解我们查看下RT-thread 系统适配R2/N2L 芯片时对定时器的使用代码如下。
#ifdef SOC_SERIES_R9A07G0
static void SysTimerInterrupt(void)
{
uint64_t tempCNTPCT = __get_CNTPCT();
/* Wait for counter supply */
while (__get_CNTPCT() == tempCNTPCT)
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS);
}
/* generic timer initialize */
/* set interrupt handler */
g_sgi_ppi_vector_table[(int32_t) BSP_VECTOR_NUM_OFFSET +
NonSecurePhysicalTimerInt] = SysTick_Handler;
rtt_timer_delay = R_GSC->CNTFID0 / RT_TICK_PER_SECOND;
/* set timer expiration from current counter value */
__set_CNTP_CVAL(__get_CNTPCT() + rtt_timer_delay);
/* configure CNTP_CTL to enable timer interrupts */
__set_CNTP_CTL(1);
R_BSP_IrqCfgEnable(NonSecurePhysicalTimerInt, (int32_t) BSP_VECTOR_NUM_OFFSET +
NonSecurePhysicalTimerInt, RT_NULL);
}
#endif上述代码根据给generic timer 当前系统时间设置比较寄存器的数值来触发中断。在以下的中断处理函数中再次更新比较寄存器的数值来触发下一次中断。
/**
* This is the timer interrupt service routine.
*
*/
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
#ifdef SOC_SERIES_R9A07G0
__set_CNTP_CVAL(__get_CNTP_CVAL() + rtt_timer_delay);
#endif
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
我要赚赏金
