在mm32f3270为micropython创建Pin模块(1)

Requirements

最终期望实现的效果是,在REPL界面能运行如下脚本:

from machine import Pin

pin0 = Pin(22)
UART0 = Pin(pin0, af=PIN_AF_1)

pin1 = Pin(23, mode=PIN_MODE_1, drive=PIN_DRIVE_1)

pin1.high()
pin1.low()
pin1.value([0])

print("pin1 value:" + pin1.value())

类对象方法实例化,类方法定义,位置参数和关键字参数的传参等问题,都可以参考之前的文章,套用workflow予以解决。但是对于引脚的编号,需要在编写相应代码(引脚映射表格)时考虑一下。另外,编写Pin基本功能的同时,也尽量考虑一下在分析代码过程中暂时放过的AF类和IRQ类。

一点长远的考虑,timer的类原本是在minimal中的,它对硬件的依赖并不复杂,短时间也考虑实现出来。这样,最后闪小灯的脚本就应该是:
 

from machine import Pin
from machine import Timer

pin0 = Pin(22)
timer0 = Timer(0)

while True:
	pin0.high()
	timer0.sleep(10)
	pin0.low()
	timer0.sleep(10)

涉及到mimxrt的源文件有:

machine_pin.c
pin.h
pin.c
代码框架
在“ports/mm32”目录下创建“machine_pin.c”,此文件专用于存放pin类的实现,是“modmachine.c”总类的下属。之后尽量把所有Pin模块实现相关的代码都放在这一个源文件中。

在“machine_pin.c”文件中编写与底层无关的框架代码,见附件。

把“machine_pin.c”文件加到Makefile文件中:
 

 - 在“SRC_C”中添加“machine_pin.c \\”
 - 在“SRC_QSTR”中添加“machine_pin.c \\”。

在“modmachine.c”中,登记Pin模块为machine模块的下属:

 - 在文件接近开始的地方引用已经定义好的Pin类对象:
extern const mp_obj_type_t machine_pin_type;

这句话原来是定义在“modmachine.h”文件中的,但是在我移植中,我不想创建这个文件了。反正使用命令行编译工具,让源文件尽量少一点,相关代码都放在“machine_pin.c”中。

	- 在“machine_module_globals_table[]”中登记Pin类:
    { MP_ROM_QSTR(MP_QSTR_Pin),                 MP_ROM_PTR(&machine_pin_type) },

工程里,试着编一下,OK。再下载运行。。。

HARDFAULT !!! HARDFAULT !!! HARDFAULT !!!

复位后可以正常打印输出log,但是一运行python语句就完蛋。试过了降主频(之前有一次在MM32F3270上运行micropython碰到Hardfault就是这么解决的)但仍不起作用。

在ozone里逐行跟踪汇编语句,一点点看,终于找到案发现场了,是在一个strcmp()函数中挂掉。但这是个标准库函数,又不涉及操作硬件,估计是编译器选项、链接库或者芯片内核的bug。再次试过了给3270降主频、给内核加电压、调整预读取缓存都不起作用。那就看能不能跳过这些语句,看call_stack,最后定位的点在“lib/mp-readline/readline.c”文件中的“readline_process_char()”函数中,处理回车那块,将已收到的命令压入历史记录里:
 

int readline_process_char(int c) {
    size_t last_line_len = rl.line->len;
    int redraw_step_back = 0;
    bool redraw_from_cursor = false;
    int redraw_step_forward = 0;
    if (rl.escape_seq == ESEQ_NONE) {
        if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_E && vstr_len(rl.line) == rl.orig_line_len) {
            // control character with empty line
            return c;
        } else if (c == CHAR_CTRL_A) {
            // CTRL-A with non-empty line is go-to-start-of-line
            goto home_key;
        #if MICROPY_REPL_EMACS_KEYS
        } else if (c == CHAR_CTRL_B) {
            // CTRL-B with non-empty line is go-back-one-char
            goto left_arrow_key;
        #endif
...

        } else if (c == '\r') {
            // newline
            mp_hal_stdout_tx_str("\r\n");
            /* Andrew to get rid of hardfault on mm32. */
            //readline_push_history(vstr_null_terminated_str(rl.line) + rl.orig_line_len);
            return 0;
        }
...
}

我把“readline_push_history()”那句mask掉之后,重新编译,下载,运行,正常。

但是按“up”键调用history的时候还是跳Hardfault。

此处猜测可能是保存history的内存的分配情况还是有问题。考虑到history可能涉及到的地方比较多,我试着找了找能不能通过某个用户选项把history相关的功能都关掉,未果,只好人工mask掉这一句,并且祈祷尽量别碰到使用history的场景。现在重点在于把底层调通,软件的部分后面再专门抽出时间追一下。

在micropython的REPL里,已经可以看到Pin模块被注册到machine模块下面了:
 


MicroPython v1.16 on 2021-08-22; MB_F3270 with MM32F3277G7P
>>> dir(machine)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name not defined
>>> import machine
>>> dir(machine)
['__name__', 'Pin', 'freq', 'mem16', 'mem32', 'mem8']
>>> import machine.Pin
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: module not found
>>> from machine import Pin
>>> pin0 = Pin()
>>> print(pin0)
None
>>>

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值