通过mem函数在MicroPython中访问模块寄存器
简 介: 通过mem函数直接访问MCU内部的寄存器,可以完成一些在原来的MicroPython中内核没有实现的模块。通过测试可以看到,通过mem访问GPIO并没有明显增加访问的速度。使用mem访问CRC,验证了它的工作机制,但对比Online CRC计算结果发现他们之间存在差异。对于UART的访问,可以获得UART1,作为REPL接收可以直接读取来自于RDR中的内容。
关键词
: mem,MM32,CRC,UART
§01 mem操作模块
一、为什么使用mem函数?
在博文 MM32F3277 MicroPython的 mem 函数对于MCU内存访问 测试了利用MicroPython中的mem函数直接访问MCU的 Flash, RAM, 内部特殊寄存器等。最初使用mem来直接访问和操作MCU的寄存器的目的是希望能够加快运行。下面将会通过一些特定的实验来检查这方面的差异。
二、操作GPIO
1、使用Pin操作
(1)测试代码
from machine import Pin,mem32,mem16
import utime
print("Test IO operating.")
pin0 = Pin('PA0', Pin.OUT_PUSHPULL)
led = Pin('PB2', Pin.OUT_PUSHPULL)
while True:
pin0(1)
pin0(0)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
(2)测试结果
测量PA0的波形如下图所示。 对应的频率为24.31kHz。
▲ 图1.2.1 测量PA0的波形与频率
(3)使用函数high,low
使用high(), low() 函数改变GPIO。
while True:
pin0.high()
pin0.low()
- 1
- 2
- 3
- 4
PA0的波形如下图所示。对应的频率为:20.78kHz。
▲ 图1.2.2 测量PA0的波形和频率
2、使用mem操作
(1)测试代码
from machine import Pin,mem32,mem16
import utime
from micropython import const
print("Test IO operating.")
pin0 = Pin('PA0', Pin.OUT_PUSHPULL)
led = Pin('PB2', Pin.OUT_PUSHPULL)
AHBPERIPH_BASE = const(0x40020000)
GPIOA_BASE = const(AHBPERIPH_BASE + 0x0020000)
GPIOB_BASE = const(AHBPERIPH_BASE + 0x0020400)
GPIOC_BASE = const(AHBPERIPH_BASE + 0x0020800)
GPIOD_BASE = const(AHBPERIPH_BASE + 0x0020C00)
GPIOE_BASE = const(AHBPERIPH_BASE + 0x0021000)
GPIOF_BASE = const(AHBPERIPH_BASE + 0x0021400)
GPIOG_BASE = const(AHBPERIPH_BASE + 0x0021800)
GPIOH_BASE = const(AHBPERIPH_BASE + 0x0021C00)
ODR = const(GPIOA_BASE+3*4)
while True:
mem32[ODR] ^= 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
(2)测试结果
测试上述操作对应的PA0的输出方波频率:23.54kHz。
▲ 图1.2.3 PA0信号波形与频率
(3)使用幅值操作GPIO
while True:
mem32[ODR] = 0
mem32[ODR] = 1
- 1
- 2
- 3
PA0的输出波形与频率如下图所示。
▲ 图1.2.4 PA0的波形与频率
■ 测试结论
通过上面测试,可以看到使用mem访问GPIO进行操作,实际上比起直接使用Pin的函数并没有快多少。
§02 CRC计算
一、基本测试
1、测试程序
from machine import mem32
import utime
from micropython import const
AHBPERIPH_BASE = const(0x40020000)
CRC_BASE = const(AHBPERIPH_BASE + 0x3000)
CRC_DR = const(CRC_BASE + 0) # CRC data register
CRC_IDR = const(CRC_BASE + 4) # CRC independent data register
CRC_CR = const(CRC_BASE + 8) # CRC control register
CRC_MIR = const(CRC_BASE + 12) # Middle data register
RCC_BASE = const(AHBPERIPH_BASE + 0x1000)
RCC_AHB1 = const(RCC_BASE+10*4)
mem32[RCC_AHB1] |= 0x1000 # Enable CRC clock
mem32[CRC_CR] = 0x1 # Reset CRC
print('CRC CR: %08x'%mem32[CRC_CR])
print('CRC DR: %08x'%mem32[CRC_DR])
mem32[CRC_DR] = 1
mem32[CRC_DR] = 2
print('CRC DR: %08x'%mem32[CRC_DR]) # Caculate the CRC
mem32[CRC_DR] = mem32[CRC_DR] # Check CRC
print('CRC DR: %08x'%mem32[CRC_DR])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2、测试结果
CRC CR: 00000000
CRC DR: -0000001
CRC DR: 298be7ba
CRC DR: 00000000
- 1
- 2
- 3
- 4
可以看到对于1,2 进行CRC计算之后,如果重新将CRC结果输入到DR,最终可以得到输出的DR为0。
▲ 图2.1.1 CRC 控制寄存器的定义
通过测试,发现CRC_BITSEL只能选择00,对应32位,最终的CRC校验才能够归零。至于为什么,现在不清楚。
3、Online CRC计算
在 CRCCALC 中给出了在线的CRC计算。通过它的计算对比MM32的计算结果。
▲ 图2.1.2 在线Online CRC 计算
通过测试,发现通过Online的计算结果与MM32计算的结果没有能够对应上。
x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
§03 UART访问
由于现在MicroPython不提供对于UART1的接受访问,这个端口用于REPL。 那么是否可以通过mem直接访问呢?
一、读取UART1接收数据寄存器
1、读取数据寄存器
from machine import Pin,mem32
import utime
from micropython import const
APB2PERIPH_BASE = const(0x40010000)
APB1PERIPH_BASE = const(0x40000000)
UART1_BASE = const(APB2PERIPH_BASE + 0x3800)
UART2_BASE = const(APB1PERIPH_BASE + 0x4400)
UART3_BASE = const(APB1PERIPH_BASE + 0x4800)
UART4_BASE = const(APB1PERIPH_BASE + 0x4C00)
UART5_BASE = const(APB1PERIPH_BASE + 0x5000)
UART6_BASE = const(APB2PERIPH_BASE + 0x3C00)
UART7_BASE = const(APB1PERIPH_BASE + 0x7800)
UART8_BASE = const(APB1PERIPH_BASE + 0x7C00)
UART1_RDR = const(UART1_BASE + 1*4)
print("Test UART.")
while True:
print("%08x"%mem32[UART1_RDR])
utime.sleep_ms(250)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
输出的结果为:就是刚刚输入的字符结果。
2、使用UART1
print("Test UART.")
uart1 = UART(0,115200)
print(dir(uart1))
oldany = uart1.any()
while True:
if uart1.any() != oldany:
oldany = uart1.any()
print("%c"%mem32[UART1_RDR])
utime.sleep_ms(20)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
通过测试,发现:
- UART1 无法使用 uart.read() : 这个函数应该放开;
- UART1只能够接收到有限个字符,希望能够扩展到128个字符。
※ 测试总结 ※
通过mem函数直接访问MCU内部的寄存器,可以完成一些在原来的MicroPython中内核没有实现的模块。通过测试可以看到,通过mem访问GPIO并没有明显增加访问的速度。使用mem访问CRC,验证了它的工作机制,但对比Online CRC计算结果发现他们之间存在差异。
对于UART的访问,可以获得UART1,作为REPL接收可以直接读取来自于RDR中的内容。
■ 相关文献链接:
● 相关图表链接:
- 图1.2.1 测量PA0的波形与频率
- 图1.2.2 测量PA0的波形和频率
- 图1.2.3 PA0信号波形与频率
- 图1.2.4 PA0的波形与频率
- 图2.1.1 CRC 控制寄存器的定义
- 图2.1.2 在线Online CRC 计算
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/121704275
- 点赞
- 收藏
- 关注作者
评论(0)