简 介: 通过mem32,mem16,mem8可以使得MicroPython向访问数字一样访问MCU中的任意内存。在ARM模型下,所有的寄存器都是基于RAM地址访问,所以原则上,可以通过memxx编程,在MicroPython层完成对于MCU中所有的模块的使用。这在内核功能还没有支持的一些特殊的MCU功能的实现,是非常重要的。
关键词
: mem32,mem16,mem8,MM32,MicroPython
§01 mem内存访问
一、mem函数
在(2021-11-30)有 MindMotion 的SuYong提供的MicroPython以及之前的版本中,都带有mem函数。在 MicroPython 官网上也介绍了如果使用mem函数能够直接对于特定的MCU中的寄存器进行访问,从而加快程序的の执行。
MicroPython v1.16 on 2021-11-29; MB_F3270 with MM32F3277G7P
>>>
>>> import machine
>>> dir(machine)
['__name__', 'ADC', 'DAC', 'PWM', 'Pin', 'SDCard', 'SPI', 'Signal', 'SoftI2C', 'SoftSPI', 'Timer', 'UART', 'freq', 'mem16', 'mem32', 'mem8']
>>>
比如在下面的代码中,使用mem16完成对于STM32GPIOA中的Pin数据寄存器直接方法,可以大大加快运行的速度。
import machine
import stm
BIT14 = const(1 << 14)
machine.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14
下面是常用到的python对Pin的操作。其中隐含了一些额外的函数调用支出。
mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin
二、初步测试mem
根据MM32F3277数据手册对于其中内存的分布定义,下表格给出了各个内部资源位置的定义。
▲ 图1.2.2 MM32F3277 内存位置定义
1、访问FLASH区域
(1)使用mem32访问
使用mem32访问的时候,地址需要为4的整数倍数,否则会出定义错误。
访问程序代码:
from machine import Pin,mem8,mem32,mem16
import utime
for i in range(10):
print("%04x"%mem32[i<<2])
输出代码:
>> Download MicroPython : 22 lines/526 characters.
>> -------------------------------------------------------------------------
20010000
800042d
8000491
8000495
800048d
800048d
800048d
0000
0000
0000
>>>
(2)使用mem8访问
使用mem8可以按照字节访问内部的FLASH。
from machine import Pin,mem8,mem32,mem16
import utime
for i in range(10):
str = ''
for j in range(16):
str = str + "%02x "%mem8[i*16+j]
print(str)
输出的结果为:
>> Download MicroPython : 25 lines/589 characters.
>> -------------------------------------------------------------------------
00 00 01 20 2d 04 00 08 91 04 00 08 95 04 00 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 99 04 00 08
8d 04 00 08 00 00 00 00 9d 04 00 08 9d 57 01 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 8d 04 00 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 8d 04 00 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 8d 04 00 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 8d 04 00 08
8d 04 00 08 8d 04 00 08 8d 04 00 08 8d 04 00 08
00 00 00 00 8d 04 00 08 00 00 00 00 8d 04 00 08
>>>
对比下载的MicroPython程序,可以看到输出的数据与下载的Flash在0x800000,映射到0x0处的Flash的结果一样的。
上面的结果使用下面的代码访问是一样的:
for i in range(10):
str = ''
for j in range(16):
str = str + "%02x "%mem8[i*16+j+0x8000000]
print(str)
▲ 图1.2.1 MicroPython烧入程序
2、访问RAM
from machine import Pin,mem8,mem32,mem16
import utime
for i in range(10):
str = ''
for j in range(16):
str = str + "%02x "%mem8[i*16+j+0x20004000]
print(str)
(1)读取RAM
这是0x2000000前面RAM中的内容。
>> Download MicroPython : 25 lines/600 characters.
>> -------------------------------------------------------------------------
40 35 02 08 54 35 02 08 03 00 00 00 94 36 02 08
a4 36 02 08 14 37 02 08 24 37 02 08 34 37 02 08
44 37 02 08 54 37 02 08 64 37 02 08 74 37 02 08
84 37 02 08 b4 36 02 08 c4 36 02 08 d4 36 02 08
e4 36 02 08 f4 36 02 08 04 37 02 08 94 37 02 08
a8 37 02 08 bc 37 02 08 e8 37 02 08 14 38 02 08
90 40 02 08 a0 40 02 08 b0 40 02 08 c0 40 02 08
d0 40 02 08 00 00 00 00 60 3e 02 08 70 3e 02 08
80 3e 02 08 10 41 02 08 20 41 02 08 90 41 02 08
a0 41 02 08 b0 41 02 08 c0 41 02 08 00 00 00 00
>>>
下面是0x20004000 RAM处的内容:
>> Download MicroPython : 25 lines/600 characters.
>> -------------------------------------------------------------------------
aa 78 90 01 b3 70 9b eb ef ea 88 4c 58 d3 fc b4
1e 7e ba c8 07 62 a9 cb df 67 c0 80 3f 24 f0 14
c7 fa c6 10 d0 36 b7 bd d9 3b 70 a1 5c 0e aa 75
91 ec 83 36 c1 19 da bc ac f6 92 4c 00 14 2b ae
a6 0a c8 44 dc a6 b4 1e e6 f1 a7 81 44 92 ff eb
05 9d 35 bb 61 91 7f 7f fc a6 d3 34 c5 f9 dd 56
63 bd 00 21 28 4e 97 e3 e3 f5 09 03 50 51 33 8c
0f f7 95 65 48 df 73 e5 99 9e 13 20 ea 50 4d 6b
c6 07 a8 f1 b1 82 c8 e9 a7 a7 ec a7 58 91 51 39
6f 5b c5 b2 ee 1f 4f 5f bc f7 19 65 81 50 f8 20
>>>
(2)对于RAM进行写入
from machine import Pin,mem8,mem32,mem16
import utime
for i in range(10):
str = ''
for j in range(16):
mem8[i*16+j+0x20004000] = i*16+j
for i in range(10):
str = ''
for j in range(16):
str = str + "%02x "%mem8[i*16+j+0x20004000]
print(str)
允许结果如下,可以看到读出的内容是写入的。
>> Download MicroPython : 30 lines/699 characters.
>> -------------------------------------------------------------------------
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
>>>
§02 访问MM32F3277
一、访问Chip ID
1、一些特殊常量
根据MM32F3277的数据手册,芯片的MCU,DEBUG_CR,JEDEC_ID的地址,下面访问他们的内容:
from machine import Pin,mem8,mem32,mem16
from micropython import const
import utime
mcu_id = const(0x40007080)
debug_cr = const(0x40007084)
jedec_id = const(0xe00ff000)
print('DEV ID:%04x'%mem32[mcu_id])
print('DEBUG_CR:%04x'%mem32[debug_cr])
print('JEDECID:%04x'%mem32[jedec_id])
运行结果:
DEV ID:-33655f19
DEBUG_CR:0000
JEDECID:-f0ffd
可以看到,输出的结果与手册中给定的の结果很不一致。
2、UID
读取 DEVICE ID 数值。
(1)代码
from machine import Pin,mem32,mem16,mem8
import utime
from micropython import const
uid_base = const(0x1ffff7e8)
for i in range(12):
print('%02x'%mem8[uid_base+i])
(2)输出结果
00
32
4d
4d
48
ff
ff
ff
88
fe
fc
ff
二、访问IO
下面代码反映对于PB2,通过地址直接进行方案,改变他的输出状态。
from machine import Pin,mem8,mem32,mem16
from micropython import const
import utime
led = Pin('PB2', Pin.OUT_PUSHPULL)
GPIOA_BASE = const(0x40040400)
BIT0 = const(1<<2)
while True:
mem32[GPIOA_BASE+3*4] ^= BIT0
utime.sleep_ms(100)
▲ 图2.2.1 通过mem改变LED状态
三、访问Timer
下面代码是使用mem直接访问Timer的寄存器,来修改PWM输出的频率。
from machine import PWM,Pin,mem8,mem16,mem32
import utime
import machine
from micropython import const
led = Pin('PB2', Pin.OUT_PUSHPULL)
pwm0 = PWM(0, freq=10000, duty=500)
APB2PERIPH_BASE = const(0x40010000)
APB1PERIPH_BASE = const(0x40000000)
TIM1_BASE = const(APB2PERIPH_BASE + 0x2C00)
TIM2_BASE = const(APB1PERIPH_BASE + 0x0000)
TIM3_BASE = const(APB1PERIPH_BASE + 0x0400)
TIM4_BASE = const(APB1PERIPH_BASE + 0x0800)
TIM5_BASE = const(APB1PERIPH_BASE + 0x0C00)
TIM6_BASE = const(APB1PERIPH_BASE + 0x1000)
TIM7_BASE = const(APB1PERIPH_BASE + 0x1400)
TIM8_BASE = const(APB2PERIPH_BASE + 0x3400)
print("Test PWM0.")
for i in range(29):
print('%d,%04x'%(i, mem32[TIM3_BASE+i*4]))
mem32[TIM3_BASE+11*4] = 0x300
while True:
led(led()^1)
utime.sleep_ms(100)
print("%04x"%mem32[TIM3_BASE+9*4])
break
※ 总 结 ※
通过mem32,mem16,mem8可以使得MicroPython向访问数字一样访问MCU中的任意内存。在ARM模型下,所有的寄存器都是基于RAM地址访问,所以原则上,可以通过memxx编程,在MicroPython层完成对于MCU中所有的模块的使用。这在内核功能还没有支持的一些特殊的MCU功能的实现,是非常重要的。
■ 相关文献链接:
● 相关图表链接: