树莓派pico--PIO入门

PIO是什么?

(Programmable I/O)PIO是为RP2040设计的一个新硬件。它允许你在基于RP2040的设备上新创建或添加硬件接口。比如你可以“添加4个uart”,或“输出DPI视频”,甚至“打算与某个在某宝上买的串口设备通讯,但找不到其他支持这个硬件的设备”,这些都可以通过PIO解决。

背景

与其他数字硬件组件的接口是困难的。它经常发生在非常高的频率(由于需要传输的数据量),并且有非常精确的时间要求。

PIO硬件使用PIO

RP2040上的PIO子系统允许你为所谓的PIO状态机编写小型、简单的程序,RP2040在两个PIO实例中有八个分裂的状态机。状态机负责设置和读取一个或多个gpio,将数据缓冲到处理器或从处理器(或RP2040的超高速DMA子系统),并在需要数据或注意时通过IRQ或轮询通知处理器。
这些程序的运行周期精度最高可达系统时钟速度(或程序时钟可以划分给不活泼的协议去慢慢的运行)。
PIO状态机比RP2040上的通用Cortex-M0+处理器要紧凑得多。事实上,它们在尺寸(因此成本)上与标准SPI外设相似,例如RP2040上也发现了PL022 SPI,因为它们的大部分面积都花在了所有串行外设共同的组件上,如fifo、移位寄存器和时钟分频器。由于指令集小而规则,所以无需花费太多的硅来解码指令。没有必要因为将一个状态机仅用于一个I/O任务而感到内疚,因为有8个状态机!
尽管如此,当涉及到I/O时,PIO状态机在一个周期内比Cortex-M0+完成了更多的工作:例如,在一个周期内采样GPIO值,切换时钟信号并推入FIFO。缺点是PIO状态机不能远程运行通用软件。正如我们将看到的,编写PIO状态机对于以前编写过汇编代码的人来说是非常熟悉的,对于没有编写过汇编代码的人来说,小指令集应该很快就能上手。
对于简单的硬件协议-如PWM或双工SPI -一个单一的PIO状态机可以独自处理实现硬件接口的任务。对于更复杂的协议,如SDIO或DPI视频,你可能最终会使用两到三个。
不要试图在RP2040上“篡改”一个协议,而是使用PIO代替。对于重复从GPIOs读写数据的任何东西来说都是这样,但对于旨在传输数据的任何东西来说肯定都是这样。

开始使用PIO

可以在c++ SDK中或直接从MicroPython中编写PIO程序。

第一个PIO程序

在深入了解PIO汇编语言的所有细节之前,我们应该花点时间看看一个小而完整的应用程序:

  1. 将程序加载到PIO的指令存储器中
  2. 设置一个PIO状态机来运行程序
  3. 在状态机运行时与状态机进行交互

清单:

  • 一个PIO程序
  • 一些用C语言编写的软件,可以运行整个程序
  • 一个CMake文件,描述如何将这两者组合成一个程序映像,以便加载到基于rp2040的开发板上

下面是一个PIO程序列表。它是用PIO汇编语言编写的。

 .program hello
 
 ; Repeatedly get one word of data from the TX FIFO, stalling when the FIFO is
 ; empty. Write the least significant bit to the OUT pin group.

 loop:
     pull
 out pins, 1
 jmp loop

pull指令从发送FIFO缓冲区取一个数据项,并把它放在输出移位寄存器(OSR)中。数据每次从FIFO移动一个字(32位)到OSR。OSR能够使用out指令将数据一次移出一个或多个位,移到更远的目的地。(tip: fifo是在硬件上实现的数据队列。每个状态机有两个fifo,在状态机和系统总线之间,用于数据从(TX)发送到(RX)芯片。)

out指令从我们刚刚从FIFO拉出的数据中取一位,并将数据写入一些引脚。我们稍后将看到如何确定这些是哪些引脚。

jmp指令返回到loop: label,这样程序就会无限地重复。所以,总结一下这个程序的功能:重复地从FIFO中取一个数据项,从这个数据项中取一个位,并把它写入一个引脚。
.pio文件还包含了一个帮助函数,用于设置PIO状态机,以便正确执行这个程序:

static inline void hello_program_init(PIO pio, uint sm, uint offset, uint pin) {
    pio_sm_config c = hello_program_get_default_config(offset);

    // Map the state machine's OUT pin group to one pin, namely the `pin`
    // parameter to this function.
    sm_config_set_out_pins(&c, pin, 1);
    // Set this pin's GPIO function (connect PIO to the pad)
    pio_gpio_init(pio, pin);
    // Set the pin direction to output at the PIO
    pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);

    // Load our configuration, and jump to the start of the program
    pio_sm_init(pio, sm, offset, &c);
    // Set the state machine running
    pio_sm_set_enabled(pio, sm, true);
}

这里要设置的主要内容是我们打算将数据输出到的GPIO。这里有三件事需要考虑:

  1. 需要告诉状态机要向哪个或哪个GPIO输出。有四个不同的引脚组,它们被不同的指令在不同的情况下使用;这里我们用的是out引脚组,因为我们用的是out指令。
  2. GPIO还需要被告知PIO正在控制它(GPIO function select)
  3. 如果我们只使用输出引脚,我们需要确保PIO驱动输出使能行高。PIO可以通过编程的方式来驱动这一行,例如使用out pindirs指令,但是在这里我们是在启动程序之前进行设置的。

PIO在被正确配置之前不会做任何事情,所以我们需要一些软件来做这些。我们刚刚看到的hello.pio将自动转换(稍后我们将看到如何转换)为一个头文件,其中包含汇编好的pio程序二进制文件、文件中包含的任何辅助函数以及有关该程序的一些有用信息。在c程序中我们引用的头文件叫hello.pio.h。

/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd. 3*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "pico/stdlib.h"
#include "hardware/pio.h"
// Our assembled program:
#include "hello.pio.h"

int main() {
	// Choose which PIO instance to use (there are two instances)
    PIO pio = pio0;

	// Our assembled program needs to be loaded into this PIO's instruction
	// memory. This SDK function will find a location (offset) in the
	// instruction memory where there is enough space for our program. We need
	// to remember this location!
    uint offset = pio_add_program(pio, &hello_program);

	// Find a free state machine on our chosen PIO (erroring if there are
	// none). Configure it to run our program, and start it, using the
	// helper function we included in our .pio file.
    uint sm = pio_claim_unused_sm(pio, true);
    hello_program_init(pio, sm, offset, PICO_DEFAULT_LED_PIN);

	// The state machine is now running. Any value we push to its TX FIFO will
	// appear on the LED pin.
    while (true) {
		// Blink
		pio_sm_put_blocking(pio, sm, 1);
		sleep_ms(500);
		// Blonk
		pio_sm_put_blocking(pio, sm, 0);
		sleep_ms(500);
    }
}  

上面说到,RP2040有两个PIO块,每个PIO块有四个状态机。每个PIO块都有一个32槽的指令内存,这对块中的4个状态机都是可见的。在任何状态机运行程序之前,我们需要将程序加载到这个指令内存中。函数pio_add_program()在给定的PIO指令内存中为我们的程序找到空闲空间,并加载它。
指令有32条,这听起来可能不是很多,但是一旦充分了解了PIO指令集的特性,它就会变得非常密集。一个完全可用的UART传输程序可以用4条指令实现,如pico-examples中的pio/uart_tx示例所示。状态机也有两种方式来执行来自其他来源的指令——比如直接来自FIFOs——在RP2040Datasheet中可以阅读到有关这些指令的所有信息。
一旦程序被加载,我们就找到一个空闲的状态机并告诉它运行我们的程序。我们可以命令多个状态机来运行同一个程序。同样,我们可以指示每个状态机运行不同的程序,只要它们都能同时放入指令内存。
上面的构建的状态机输出数据到PICO上的LED上,可以很明显的看到。
此时,状态机是自动运行的。状态机将立即停止,因为它正在等待TX FIFO中的数据,而我们还没有提供任何数据。处理器可以使用pio_sm_put_blocking()函数将数据直接推入状态机的TX FIFO。(_blocking,因为当TX FIFO满的时候,这个函数会让处理器停止。)写入1会打开LED,写入0会关闭LED
下面写cmake文件
现在有两个文本文件,名称以,pio和.c结尾,但它们并没有给我们带来太多好处。一个CMake文件描述了这些是如何构建到一个二进制文件,适合加载到你的Raspberry Pi Pico或其他基于rp2040的板。

add_executable(hello_pio)

pico_generate_pio_header(hello_pio ${CMAKE_CURRENT_LIST_DIR}/hello.pio)

target_sources(hello_pio PRIVATE hello.c)

target_link_libraries(hello_pio PRIVATE
        pico_stdlib
        hardware_pio
        )

pico_add_extra_outputs(hello_pio)

# add url via pico_set_program_url
example_auto_set_url(hello_pio)
  • add_executable(): 声明我们正在构建一个名为hello_pio的程序
  • pico_generate_pio_header(): 声明我们有一个PIO程序,hello.pio,我们希望将其构建到C头文件中 与我们的程序一起使用
  • target_sources():列出hello_pio程序的源代码文件。在本例中,只有一个C文件。
  • target_link_libraries():确保我们的程序是使用PIO硬件API构建的,这样我们就可以调用类似的函数 在C文件中的pio_add_program()。
  • pico_add_extra_outputs():默认情况下,我们只获得一个.elf文件作为我们的应用程序的构建输出。在这里,我们声明我们也想要额外的构建格式,比如一个.uf2文件,可以直接拖放到USB连接的树莓派Pico上。

然后通过以下命令来构建程序

mkdir build
cd build
cmake ..
make
  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 树莓派Pico是树莓派推出的一款微型电脑,Pico中文版是针对中国市场推出的版本。Pico-Python-SDK是树莓派官方提供的软件开发工具包,用于编写和运行Python程序。Pico-Python-SDK中文版是根据中国用户的需求进行本土化开发的版本。 树莓派Pico是一款体积小巧但功能强大的微型电脑,搭载了ARM Cortex-M0+处理器和26个GPIO口,可用于连接各种传感器、执行各种控制任务。同时,Pico支持MicroPython和C/C++两种编程语言,非常适合初学者和嵌入式系统开发人员。 Pico-Python-SDK中文版是官方提供的软件开发工具包,它提供了一系列的API和库函数,可以帮助开发者更方便地编写和调试Python程序。无论是控制外部硬件设备还是实现各种功能,Pico-Python-SDK都提供了丰富的功能和示例代码,使开发工作更加便捷。 Pico-Python-SDK中文版还提供了中文文档和教程,有助于开发者更快速地上手。通过学习这些文档和教程,开发者可以了解Pico的基本原理、功能特性以及编程方法,从而高效地开发出各种应用。 总的来说,树莓派Pico-Python-SDK中文版为中国用户提供了一个方便、易用的软件开发平台,帮助开发者快速上手并实现各种创意和项目。无论是学习编程还是进行嵌入式系统开发,Pico-Python-SDK中文版都是一个不错的选择。 ### 回答2: 树莓派pico-python-sdk-中文版是为了方便中国开发者使用而推出的一款软件开发工具包。它是基于树莓派pico微控制器设计的,通过使用Python语言进行开发。该SDK提供了丰富的功能和接口,使得使用者能够轻松地进行树莓派pico的开发工作。 树莓派pico-python-sdk-中文版包含了各种模块和库,如GPIO库、PWM库、I2C库、SPI库等,这些库可以帮助开发者通过编写Python代码来操控各种外设和传感器。例如,使用GPIO库可以控制LED灯的开关,使用PWM库可以控制舵机的转动,使用I2C库可以与其他设备进行通信,使用SPI库可以实现高速数据传输等等。 此外,树莓派pico-python-sdk-中文版还提供了丰富的示例代码和文档,帮助开发者快速上手。开发者可以参考这些示例代码和文档,了解如何使用SDK中的功能和接口,从而加速自己的开发进程。 总之,树莓派pico-python-sdk-中文版是一款功能强大、易于学习和使用的软件开发工具包。它不仅方便中国开发者使用树莓派pico进行开发工作,还提供了丰富的功能和接口,使得开发者能够更加便捷地实现各种应用和项目。无论是初学者还是有经验的开发者,都可以通过使用这个SDK来实现自己的创意和想法。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值