[Diao Ye Learns Programming] MicroPython Manual ESP32 Specific Port Library esp32.ULP.load_binary()

Insert image description here

MicroPython is a lightweight version of the interpreter designed for running the Python 3 programming language in embedded systems. Compared with regular Python, the MicroPython interpreter is small (only about 100KB) and is compiled into a binary Executable file to run, resulting in higher execution efficiency. It uses a lightweight garbage collection mechanism and removes most of the Python standard library to accommodate resource-constrained microcontrollers.

The main features of MicroPython include:
1. The syntax and functions are compatible with standard Python, making it easy to learn and use. Supports most core syntax of Python.
2. Directly access and control hardware, control GPIO, I2C, SPI, etc. like Arduino.
3. Powerful module system, providing file system, network, graphical interface and other functions.
4. Support cross-compilation to generate efficient native code, which is 10-100 times faster than the interpreter.
5. The amount of code is small and the memory usage is small. It is suitable for running on MCU and development boards with small memory.
6. Open source license, free to use. The Shell interactive environment provides convenience for development and testing.
7. The built-in I/O driver supports a large number of microcontroller platforms, such as ESP8266, ESP32, STM32, micro:bit, control board and PyBoard, etc. There is an active community.

MicroPython application scenarios include:
1. Rapidly build prototypes and user interactions for embedded products.
2. Make some small programmable hardware projects.
3. As an educational tool, it helps beginners learn Python and IoT programming.
4. Build smart device firmware to achieve advanced control and cloud connectivity.
5. Various microcontroller applications such as Internet of Things, embedded intelligence, robots, etc.

Things to note when using MicroPython:
1. Memory and Flash space are limited.
2. The explanation and execution efficiency is not as good as C language.
3. Some library functions are different from the standard version.
4. Optimize the syntax for the platform and correct the differences with standard Python.
5. Use memory resources rationally and avoid frequently allocating large memory blocks.
6. Use native code to improve the performance of speed-critical parts.
7. Use abstraction appropriately to encapsulate underlying hardware operations.

Generally speaking, MicroPython brings Python into the field of microcontrollers, which is an important innovation that not only lowers the programming threshold but also provides good hardware control capabilities. It is very suitable for the development of various types of Internet of Things and intelligent hardware.
Insert image description here

MicroPython's esp refers to the MicroPython firmware and related software libraries for ESP8266 and ESP32 chips. ESP8266 and ESP32 are a class of low-cost, low-power Wi-Fi and Bluetooth modules widely used in IoT and embedded systems. MicroPython's esp provides an advanced scripting environment for both chips, allowing developers to use the Python language for rapid prototyping and development.

ESP8266: It is a low-cost, low-power Wi-Fi module/chip developed by Espressif Systems. It has a built-in TCP/IP protocol stack, can be used to connect to the Internet, and has strong processing capabilities. MicroPython's esp provides firmware and related software libraries for ESP8266, allowing developers to use MicroPython language to develop ESP8266 applications.

ESP32: It is a highly integrated Wi-Fi and Bluetooth module/chip launched by Espressif Systems. Compared with ESP8266, it has more powerful processing power, more peripheral interfaces and more memory. MicroPython's esp also provides firmware and related software libraries for ESP32, allowing developers to use MicroPython language to develop ESP32 applications.

MicroPython's esp firmware: It is a MicroPython firmware version specifically for ESP8266 and ESP32 chips. These firmwares have been specifically optimized to run on ESP8266 and ESP32, and provide APIs for hardware interaction, network communication, and peripheral control.

Software libraries: MicroPython's esp also provides a series of software libraries related to ESP8266 and ESP32 hardware to simplify and accelerate the development process. These software libraries provide a rich set of functional interfaces, covering commonly used hardware and communication protocols such as Wi-Fi, Bluetooth, GPIO (General Purpose Input and Output), I2C, SPI, and PWM, allowing developers to easily access and control hardware resources.
Insert image description here
MicroPython's esp32.ULP.load_binary() is a method used to load binary files into the memory of the ULP (Ultra Low-Power) coprocessor. It has the following main features, application scenarios and precautions:

main feature:

esp32.ULP.load_binary() is a method of the esp32.ULP class, which can act on any ULP coprocessor object.
The function of esp32.ULP.load_binary() is to load a byte object, that is, a binary file containing ULP machine code, into the specified address in the ULP coprocessor memory.
The return value of esp32.ULP.load_binary() is None, indicating that the loading is successful.
There are two parameters for esp32.ULP.load_binary(). The first one is an integer, indicating the load address, ranging from 0-409512. The second is a bytes object representing the binary file to be loaded.
The default parameters of esp32.ULP.load_binary() are 0 and a null byte object, which means nothing is loaded.

Application scenarios:

The esp32.ULP.load_binary() function can be used to compile or download the ULP assembler directly on the ESP32 and load it into the ULP coprocessor memory, ready to run.
The function of esp32.ULP.load_binary() can be used to dynamically modify or replace the program in the ULP coprocessor memory on ESP32 to implement different functions or logic.
The esp32.ULP.load_binary() function can also be used to save or restore programs in the ULP coprocessor memory on ESP32 to achieve persistence or backup.

Precautions:

The function of esp32.ULP.load_binary() needs to pay attention to conflicts with other functions that occupy ULP coprocessors or pins, such as SPI, I2C, UART, etc.
The function of esp32.ULP.load_binary() needs to pay attention to the impact of other functions that occupy shared memory or interrupt signals, such as network communication, file system, garbage collection, etc.
The function of esp32.ULP.load_binary() needs to be coordinated with other functions that require interrupt services or timer services, such as machine timers, machine interrupts, etc.

The following are several practical application examples using MicroPython's esp32.ULP.load_binary() method:

Case 1: Use esp32.ULP.load_binary() to load a binary file compiled by py-esp32-ulp. This file implements a simple counter function and stores the result in shared memory.

# 导入必要的模块
import esp32
import machine
import py_esp32_ulp

# 定义一个计数器程序的源代码,使用py-esp32-ulp提供的汇编语法
counter_src = """
data: .long 0
entry: move r3, data
loop:  add r3, r3, 1
       move r0, r3
       store r0, r3, 0
       wait 1000
       jump loop
"""

# 使用py_esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
counter_bin = py_esp32_ulp.assemble(counter_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为0,表示不唤醒主CPU
esp32.ULP.set_wakeup_period(0)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, counter_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 使用machine.deepsleep()函数来让主CPU进入深度睡眠模式,ULP协处理器继续运行
machine.deepsleep()

# 使用esp32.ULP.mem_read()函数来读取共享内存中的数据,地址为0,返回一个整数
counter = esp32.ULP.mem_read(0)

# 打印出计数器的值
print(counter)

Case 2: Use esp32.ULP.load_binary() to load a binary file compiled by micropython-esp32-ulp. This file implements a simple temperature sensor function and stores the result in shared memory.

# 导入必要的模块
import esp32
import machine
import esp32_ulp

# 定义一个温度传感器程序的源代码,使用esp32_ulp提供的汇编语法
temp_src = """
data: .long 0
entry: tsens r0, 850 # 读取温度传感器的值,延迟850个周期
       move r3, data # 将数据地址存入r3寄存器
       store r0, r3, 0 # 将温度值存入数据地址
       halt # 停止执行
"""

# 使用esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
temp_bin = esp32_ulp.assemble(temp_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为1000000,表示每隔1秒唤醒一次主CPU
esp32.ULP.set_wakeup_period(0, 1000000)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, temp_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 定义一个循环,每隔1秒打印出温度值,并让主CPU重新进入睡眠模式
while True:
    # 使用esp32.ULP.mem_read()函数来读取共享内存中的数据,地址为0,返回一个整数
    temp = esp32.ULP.mem_read(0)
    # 打印出温度值,单位为摄氏度
    print(temp / 2 - 40)
    # 使用machine.lightsleep()函数来让主CPU进入轻度睡眠模式,等待下一次唤醒
    machine.lightsleep()

Case 3: Use esp32.ULP.load_binary() to load a binary file compiled by binutils-esp32ulp. This file implements a simple PWM (pulse width modulation) function and outputs the result to the pin.

# 导入必要的模块
import esp32
import machine
import py_esp32_ulp

# 定义一个LED灯闪烁程序的源代码,使用py-esp32-ulp提供的汇编语法
led_src = """
data: .long 0
entry: move r3, data # 将数据地址存入r3寄存器
       load r0, r3, 0 # 将数据值加载到r0寄存器
       move r1, 18 # 将引脚号18存入r1寄存器
       i2c_rd r2, r1, 28, 1 # 读取GPIO_OUT寄存器的值,存入r2寄存器
       xor r2, r2, r0 # 将r2和r0做异或运算,得到反转后的值,存入r2寄存器
       i2c_wr r2, r1, 28, 1 # 将r2的值写入GPIO_OUT寄存器,控制LED灯的状态
       store r2, r3, 0 # 将r2的值存回数据地址,更新数据值
       wait 1000000 # 等待1000000个周期(约为1秒)
       jump entry # 跳转到entry标签,重复执行
"""

# 使用py_esp32_ulp.assemble()函数来编译源代码,并返回一个字节对象
led_bin = py_esp32_ulp.assemble(led_src)

# 使用esp32.ULP.set_wakeup_period()函数来设置ULP协处理器唤醒周期为0,表示不唤醒主CPU
esp32.ULP.set_wakeup_period(0)

# 使用esp32.ULP.load_binary()函数来加载二进制文件到ULP协处理器内存中,起始地址为0
esp32.ULP.load_binary(0, led_bin)

# 使用esp32.ULP.run()函数来运行二进制文件,起始地址为0
esp32.ULP.run(0)

# 此时,ESP32的第18号引脚会每隔1秒反转一次电平,从而控制LED灯的闪烁

Case 4: Load ULP program binary code:

import esp32
with open('ulp_code.bin', 'rb') as f:
bin_data = f.read()
esp32.ULP.load_binary(bin_data)

Case 5: Reading ULP code from Flash and loading:

import esp32
buf = esp32.flash_read(addr, size)
esp32.ULP.load_binary(buf)

Case 6: Delete the loaded ULP program:

import esp32
esp32.ULP.load_binary(b'')

The first example reads binary data from a file and loads it into a ULP. The second example loads ULP code from Flash. The third example clears a previously loaded ULP program. This function is used to load precompiled ULP binary code. Through it, dynamic loading of ULP programs can be achieved, which is often used in firmware upgrade scenarios. Cooperating with Flash reading and writing, flexible management of ULP programs can be achieved.

Case 7: Load the binary code of the ULP program:

import esp32

# 定义 ULP 程序的二进制代码
ulp_binary_code = b'\x00\x00\x00\x00\x00\x00\x00\x00'  # 请替换为实际的二进制代码

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

This sample program shows how to use the load_binary() method to load the binary code of a ULP program into the ULP coprocessor.

Case 8: Load the binary code of the ULP program from a file:

import esp32

# 从文件中读取 ULP 程序的二进制代码
with open('ulp_program.bin', 'rb') as file:
    ulp_binary_code = file.read()

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

This sample program shows how to read the binary code of a ULP program from a file and load it into the ULP coprocessor using the load_binary() method. Please make sure to replace the actual binary code file path with "ulp_program.bin".

Case 9: Use the ULP program generation tool to load the binary code of the ULP program:

import esp32
import ulptool

# 使用 ULP 程序生成工具生成 ULP 程序的二进制代码
ulp_source_code = """
    .section .ulp_text
    .global function_entry
    function_entry:
        # ULP 程序代码,请根据实际需求编写
"""

ulp_binary_code = ulptool.assemble(ulp_source_code)

# 加载 ULP 程序的二进制代码到 ULP 协处理器
esp32.ULP.load_binary(ulp_binary_code)

This sample program shows how to use the ULP program generation tool in the ulptool module by writing the source code of the ULP program and using the assemble() method to generate binary code, and then using the load_binary() method to load it into the ULP coprocessor. Please write ULP program code according to actual needs.

These sample programs demonstrate how to load binary code on the ESP32's ULP coprocessor using the esp32.ULP.load_binary() method. You can provide binary code directly to the method, read the code from a file, or use the ULP program generation tool to generate the code. Please ensure that the binary code provided meets the requirements of the ULP coprocessor and is loaded into the ULP coprocessor correctly.

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_41659040/article/details/132944049