在mm32f3270上为MicroPython启用Timer模块
昨天阅读micropython的材料时,特别注意了这个名字的写法,官方正式使用的是“MicroPython",确实有两个字母是大写的。我在这个项目的开发过程中一直秉承继承原汁原味的原生风格,自然也要使用“正确”的名字。后面的笔记中,均使用“MicroPython”这个名字。
Requirements
MicroPython的开发者官网文档中描述了对Timer模块的规范定义:https://docs.micropython.org/en/latest/library/machine.Timer.html
Timer的实例化传参直接用的id号,并且支持一个“-1”的id号表示创建虚拟定时器。“-1”的id号是可选项。我打算仅实现硬件对应的id。软件定时器意思不大。
Timer暴露给用户的全部是通过callback实现的,我看到esp的实现里有value函数,但标准实现中没有,我认为这个意思不大,也就不实现了。
Timer就是基本定时器,周期计数而已,用户在初始化实例的时候,指定唤醒频率即可直接启动,连start函数都没有。但有两种唤醒模式,分别对应两个累成员变量:Timer.ONE_SHOT和Timer_PERIODIC。
Timer相对于别的模块,一个实现难点是,增加的 callback 的机制。但 callback 函数是在 python 代码中传入的,怎么能在 C 语言层面上硬件中断服务程序中被调用呢。通过阅读stm32、mimxrt 和 esp 的移植,发现了一个关键的函数 mp_sched_schedule()函数,用于在定时器中断到来之时,实现在C语言层面上将python的程序注入到python内核的主线程参与调度的做法。目前只找到了一篇文章对 mp_sched_schedule() 函数的机制简要说明,见《MicroPython中Python与C代码是如何交互的》
mimxrt 的 Timer 基于 PIT 实现,固定使用一个 PIT,但是使用了其中的多通道。在 MM32 的实现上,具有的多通道的定时器(tim_16b、tim_32b、tim_adv)都用来作为PWM输出和编码器输入了,我最终选择使用仅具有计数功能的 tim_basic,但需要使用两个Instance。这里少不了还要实现一个 find_timer() 的函数以及一组预先分配好的conf结构体。
Implementation
使用 ports/mimxrt/machine_timer.c作为模板,完成mm32的Timer模块的实现。
STATIC mp_obj_t machine_timer_obj_init_helper () 函数中的实例化参数清单
static const mp_arg_t allowed_args[] =
{
{
MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {
.u_int = TIMER_MODE_PERIODIC} },
{
MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {
.u_rom_obj = MP_ROM_NONE} },
{
MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {
.u_int = 0xffffffff} },
{
MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {
.u_int = 1000} },
{
MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {
.u_rom_obj = MP_ROM_NONE} },
};
Timer 对象的类型定义,要存放好硬件相关信息,同时能保存这些动态配置信息
typedef struct
{
void * callback;
uint32_t period;
uint32_t tick_hz;
uint32_t freq;
uint32_t mode;
}
启用MicroPython在MM32F3270上的Timer模块实现与应用

最低0.47元/天 解锁文章
2214

被折叠的 条评论
为什么被折叠?



