S32K3 Timer(PIT & STM)使用介绍 ——基于LLD


本文基于 S32K3xx系列芯片和S32 Design Studio for S32 Platform开发平台,介绍timer(STM 和 PIT) LLD(Low Level Driver)层的开发。
基于MCAL的开发,请参考
timer: https://editor.csdn.net/md/?articleId=124290730

GPIO:https://editor.csdn.net/md/?articleId=123682340
电源及低功耗:https://editor.csdn.net/md/?articleId=123681206

1. 缩写说明:

STM System Timer Module
AIPS peripheral bridges
FXOSC Fast External Crystal oscillator
FIRC Fast Internal RC Oscillator
CGM Clock Generation Module
PIT Periodic Interrupt Timer
RTI Real Timer Interrupt

2. PIT

2.1 PIT简介

  • PIT时钟源为AIPS,其中RTI时钟为SIRC_CLK,用于在standby模式下唤醒CPU。
  • PIT共有3个instance,每个instance又有4个channel。其中PIT_0可以被链接成为一个64bit的定时器(正常为32bit的定时器)
  • PIT的定时器为向下计数器,counter值写在LDVAL registers中。

2.2 在diver中添加模块

在这里插入图片描述

核心模块为Pit_1和IntCtrl_Ip_1,Siul2模块主要用于定时器中断中点个LED方便查看现象。因此GPIO的操作请参考之前的文章。

2.3 PIT driver配置

2.3.1 使能PIT和对应的channel

在这里插入图片描述

如图所示,使能需要使用的PIT instance和对应的channel。

2.3.2 配置instance和channel

在这里插入图片描述

注意选择对应的instance和channel即可。
PitFreezeEnable 打开后可以让我们调试打了断点后定时器也相应的停止,建议打开,方便调试。
Pit Channel 的选择要与物理通道相对应。
ChainMode 是将PIT0链接为64bit的通道,可以进行整个CPU生命周期的超长定时。
PitNotification 是用户自定义的回调函数,在用户函数中需保持一致。

2.3.3 中断配置的两种方式

方式一:
在这里插入图片描述

此模块保持默认配置,在代码中单独使能。此方式与后续的代码配置中中断配置的方式一相对应。

方式二:
在IntCtrl_Ip_1模块中使能pit
在这里插入图片描述

在这里插入图片描述

0表示中断优先级,优先级的value越小,优先级越高。如果设置的优先级value相同,则表格中顺序靠前的先执行。最大可设置16级优先级(4bit)。
在这里插入图片描述

在这里插入图片描述

配置中断回调函数,此函数指针要与pit_ip.c中的一致。

2.3.4 配置GPIO

根据自己的需求,配置相应的GPIO,用来在定时器中翻转显示。具体操作见GPIO的文档

2.4 PIT软件配置

2.4.1 加入头文件

在应用代码中加入相应的头文件

#include "Clock_Ip.h"
#include "IntCtrl_Ip.h"
#include "Pit_Ip.h"
#include "Siul2_Dio_Ip.h"
#include "Siul2_Port_Ip.h"

2.4.2 初始化时钟

调用如下函数:

Clock_Ip_StatusType Clock_Ip_Init(Clock_Ip_ClockConfigType const * Config)

函数参数:
Board文件中的Clock_Ip_PBcfg.c中的Mcu_aClockConfigPB参数
注意:
不要调用Clock_Ip_InitClock();函数来初始化时钟,此函数被Clock_Ip_Init()调用。否则在clock模块中的配置,比如PLL将不会生效。

2.4.3 初始化中断

根据前文中的配置不同,中断也有两种初始化方式。
方式一:
调用中断模块中的如下函数,单独使能pit0的中断:

IntCtrl_Ip_InstallHandler( PIT0_IRQn, PIT_0_ISR , NULL_PTR);

参数一:PIT0的中断号
参数二:PIT0的中断回调函数入口
参数三:旧有PIT0的中断回调函数

IntCtrl_Ip_EnableIrq(PIT0_IRQn);

参数一:PIT0的中断号

以上两个函数其实就是在向内核注册并使能pit0的中断

方式二:

IntCtrl_Ip_Init(&IntCtrlConfig_0);

参数一:中断控制器的配置,与前文中IntCtrl_Ip模块配置一致,包括中断号,是否使能该中断,以及中断对应的优先级。

IntCtrl_Ip_ConfigIrqRouting(&intRouteConfig);

参数一:中断路由配置,与前文中IntCtrl_Ip模块配置一致,包括中断号,中断的Target Core(双核情况下才配置,默认为核1),以及对应的中断回调函数。

以上两个函数会将我们所有配置了的中断统一初始化,比较方便。

2.4.4 编写中断回调函数

在应用程序中编写中断回调函数,此函数与前文driver配置中的回调函数应保持一致。
在这里插入图片描述

2.4.5 配置Pit

2.4.5.1 初始化pit instance
Pit_Ip_Init(PIT_INST_0, &PIT_0_InitConfig_PB);

参数一:instance value,0,1,2等
参数二:pit instance的相关配置,此配置在generate/src文件夹中的Pit_Ip_BOARD_InitPeripherals_PBcfg.c文件中。包含了是否打开标准定时器,是否打开RTI定时器,是否使能pit调试模式(前文中我们配置的PitFreezeEnable)等信息

2.4.5.2 初始化相应的channel
Pit_Ip_InitChannel(PIT_INST_0, &PIT_0_ChannelConfig_PB);

参数一:instance value,0,1,2等
参数二:pit channel相关配置,此配置在generate/src文件夹中的Pit_Ip_BOARD_InitPeripherals_PBcfg.c文件中。包括了通道号、是否使能中断,以及中断回调函数,中断回调函数的参数等信息。

2.4.5.3 使能相应通道的中断
Pit_Ip_EnableChannelInterrupt(PIT_INST_0, CH_0);

参数一:instance value,0,1,2等
参数二:channel value,0,1,2等

2.4.5.4 开启定时器
Pit_Ip_StartChannel(PIT_INST_0, CH_0, PIT_PERIOD);

参数一:instance value,0,1,2等
参数二:channel value,0,1,2等
参数三:counter value
计数器值与时钟有关,计算方法如下:
User time / Clock period - 1 = counter value
User time: 用户想要定时的时间。
Clock period:定时器的时钟周期。比如pit的时钟选择如下图所示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
若我们想要定时1s,根据公式可以算出counter value的值为:39999999.
由公式可知,我们改变定时周期有两种方法:一是改变pit的时钟,二是改变counter value。一般来说工程搭建起来后就不会再去改变系统clock,因此,一般我们都去设置counter value。
PS:
Pit的时钟来源于AIPS,而AIPS可以配置为FXOSC或者FIRC

2.4.6 初始化LED引脚

Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0,g_pin_mux_InitConfigArr0);

在中断回调函数点亮LED,详细内容参考GPIO的文章

经过上述配置,pit即可正常使用。

2.5 常用API说明

  • Instance的初始化与反初始化
Void  Pit_Ip_Init(uint8 instance,  const Pit_Ip_InstanceConfigType *config);
void  Pit_Ip_Deinit(uint8 instance);
  • Channel的初始化
void  Pit_Ip_InitChannel(uint8 instance, const Pit_Ip_ChannelConfigType *chnlConfig);
  • Channel计数的开始与停止
Pit_Ip_StatusType  Pit_Ip_StartChannel(uint8 instance, uint8 channel, uint32 countValue);
void Pit_Ip_StopChannel(uint8 instance, uint8 channel);
  • Channel中断的使能与禁止
void  Pit_Ip_EnableChannelInterrupt(uint8 instance, uint8 channel);
void  Pit_Ip_DisableChannelInterrupt(uint8 instance, uint8 channel);
  • 获取count value的值
uint64  Pit_Ip_GetCurrentTimer(uint8 instance, uint8 channel);

这个函数从CVAL Register寄存器中读取counter value,实时更新的,即返回当前timer的实际计数值。

2.6 进一步的使用

2.6.1 使用两路或多路channel

如果使用用一个pit的多路channel,配置过程与上述一致,只是需要注意初始化通道时要初始化多次(有几个通道就要初始化几次),而不是一次,如下图所示:
在这里插入图片描述

原因如下:
Pit_Ip_InitChannel();此函数并没有在内部循环遍历,也就是说此函数一次只能初始化一个通道。因此,我们有多少通道就要调用多少此这个函数来完成初始化。如下图所示:
在这里插入图片描述
在这里插入图片描述

同一个instance不同的channel进的是同一个中断处理函数,Pit_Ip_ProcessCommonInterrupt(uint8 instance, uint8 channel); 这个函数里面再去读是哪个channel发生了中断,调用不同的callback。如图所示:

因此,当我们使用单独打开中断的方式:

IntCtrl_Ip_InstallHandler( PIT0_IRQn, PIT_0_ISR , NULL_PTR);
IntCtrl_Ip_EnableIrq(PIT0_IRQn);

不同通道只需要是调用一次即可。

2.6.2 使用Chained Timer

假设如下需求:
进行一个2分钟的定时,且此时系统给到pit的时钟为40MHz。
分析:
通过公式我们可以算出写入的counter value为:4800million
但一个32bit寄存器最大能写入:4 294 967 295,显然不能容纳4800million这个值。
因此我们需要使用chained timer来实现这个需求。
使用两个timer,timer1定时6s(counter value: 600 000 000 - 1),timer2定时20次(counter value:20 - 1),共计120s。
S32DS这个平台还没有实现这个功能,具体实现是需要操作寄存器。详见手册。

3. STM

3.1 STM简介

  • 时钟来源于AIPS_PLAT_CLK or FXOSC or FIRC,可以在CGM中选择
  • 3个stm instance,每个instance有4个32bit的compare channel,每个channel都有独立的中断。
  • 1个32-bit的向上计数器,具有8位的预分频器,可进行0–256级分频。

3.2 在driver中添加模块

在这里插入图片描述

3.3 STM driver配置

在这里插入图片描述

在这里插入图片描述

Stm的diver配置项与pit的diver配置项几乎一模一样,在此不赘述了。

3.4 STM软件配置

配置方式基本类似PIT,在此不赘述了,主要介绍使用到的API。

Stm_Ip_Init( 0, &STM_0_InitConfig_PB);

参数一:instance号
参数二:instance相关配置,此配置在generate/src文件夹中的Stm_Ip_BOARD_InitPeripherals_PBcfg.c文件中。包含了是否打开预分频器,预分频器设置多少分频,是否使能stm调试模式(前文中我们配置的PitFreezeEnable)等信息

Stm_Ip_InitChannel(0, STM_0_ChannelConfig_PB);

参数一:instance号
参数二:channel配置,此配置在generate/src文件夹中的Stm_Ip_BOARD_InitPeripherals_PBcfg.c文件中。包括了通道号,中断回调函数,中断回调函数的参数等信息。

Stm_Ip_StartCounting(0, 0 , 48000000);

参数一:instance号
参数二:channel号
参数三:比较值,设置方法参考PIT。

另外两个重要函数:

Stm_Ip_GetCompareValue(uint8 instance,  uint8 channel)

此函数返回的counter是CPU用来被比较的counter,即我们设置的counter,比如一开始我们设置为48M,则第一个周期此函数返回值为48M,但在第二个周期这个值就会变为:48 * 2M,以此类推,知道满32bit后,从0重新开始

Stm_Ip_GetCounterValue(uint8 instance)

此函数返回的是timer定时器计数的实时值,比如第一个周期内counter具体值是多少了,用这个值可以判断我在一个周期内的时间是多少。

4. 相关文章

4.1 S32K3系列GPIO及其中断使用介绍

  • 11
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值