Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_subdirectory(otpset)
add_subdirectory(overlaycheck)
add_subdirectory(ovmerge)
add_subdirectory(pinctrl)
add_subdirectory(piolib)
add_subdirectory(raspinfo)
add_subdirectory(vcgencmd)
add_subdirectory(vclog)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A collection of scripts and simple applications
* [pinctrl](pinctrl/) - A more powerful replacement for raspi-gpio, a tool for
displaying and modifying the GPIO and pin muxing state of a system, bypassing
the kernel.
* [piolib](piolib/) - A library for accessing the Pi 5's PIO hardware.
* [raspinfo](raspinfo/) - A short script to dump information about the Pi. Intended for
the submission of bug reports.
* [vclog](vclog/) - A tool to get VideoCore 'assert' or 'msg' logs
Expand Down
41 changes: 41 additions & 0 deletions piolib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.10...3.27)

include(GNUInstallDirs)

#set project name
project(piolib)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")

if (CMAKE_COMPILER_IS_GNUCC)
add_definitions (-ffunction-sections)
endif ()

add_library (pio OBJECT piolib.c pio_rp1.c)
target_include_directories(pio PRIVATE .)
target_link_libraries(pio)

add_executable(piotest piotest.c)
target_include_directories(piotest PRIVATE .)
target_link_libraries(piotest pio)
install(TARGETS piotest RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_executable(piopwm pwm.c)
target_include_directories(piopwm PRIVATE .)
target_link_libraries(piopwm pio)
install(TARGETS piopwm RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_executable(pioseq genseq.c)
target_include_directories(pioseq PRIVATE .)
target_link_libraries(pioseq pio)
install(TARGETS pioseq RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_executable(piows2812 ws2812.c)
target_include_directories(piows2812 PRIVATE .)
target_link_libraries(piows2812 pio)
install(TARGETS piows2812 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_executable(rp1sm rp1sm.c)
target_include_directories(rp1sm PRIVATE .)
target_link_libraries(rp1sm pio)
install(TARGETS rp1sm RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
27 changes: 27 additions & 0 deletions piolib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# piolib

PIOlib/libPIO is a user-space API to the rp1-pio driver, which gives access to the PIO hardware of RP1. It takes the form of a clone of the PICO SDK PIO API, where most of the methods are implemented as RPC calls to RP1. This allows existing PIO code to be run without (much) alteration, but runs into problems when it relies on the PIO state machine and the support code being closely coupled.

To build piolib:
1. cmake . (or create a build subdirectory and cmake ..)
2. make

If `ls -l /dev/pio0` reports that the file is not found, you may need to update your Pi 5 firmware to one with PIO support and make sure that you are running a suitably recent kernel.
If `ls -l /dev/pio0` reports that the file is owned by `root` and group `root`, you should add the following to /etc/udev/rules/99-com.rules:
```
SUBSYSTEM=="*-pio", GROUP="gpio", MODE="0660"
```

Examples:

* piotest:
This is the normal WS2812 example LED PIO code, but using DMA to send the data. The optional parameter is the GPIO number to drive; the defailt is 2.
* piopwm:
The PWM example, unmodified except for dynamic SM allocation and a command line parameter to choose the GPIO. The optional parameter is the GPIO number to drive; the default is 4.
* piows2812:
The ws2812 example, unmodified except for dynamic SM allocation and a command line parameter to choose the GPIO. The optional parameter is the GPIO number to drive; the defailt is 2.
* rp1sm:
Show the state of the hardware for a particular SM. The parameter is the number of the state machine to inspect.

Known issues:
* Blocking operations block the whole RP1 firmware interface until they complete.
9 changes: 9 additions & 0 deletions piolib/ds18b20.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Function commands for d218b20 1-Wire temperature sensor
// https://www.analog.com/en/products/ds18b20.html
//
#define DS18B20_CONVERT_T 0x44
#define DS18B20_WRITE_SCRATCHPAD 0x4e
#define DS18B20_READ_SCRATCHPAD 0xbe
#define DS18B20_COPY_SCRATCHPAD 0x48
#define DS18B20_RECALL_EE 0xb8
#define DS18B20_READ_POWER_SUPPLY 0xb4
68 changes: 68 additions & 0 deletions piolib/genseq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include <stdlib.h>

#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "genseq.pio.h"

#define DATA_WORDS 1024

int main(int argc, const char **argv) {
uint32_t databuf[DATA_WORDS];
bool use_dma = true;
int ret = 0;
int i, j;
stdio_init_all();

PIO pio = pio0;
int sm = pio_claim_unused_sm(pio, true);
uint offset = pio_add_program(pio, &genseq_program);
uint gpio = 4;
if (argc == 2)
gpio = (uint)strtoul(argv[1], NULL, 0);
printf("Loaded program at %d, using sm %d, gpio %d\n", offset, sm, gpio);

pio_sm_config_xfer(pio, sm, PIO_DIR_FROM_SM, 256, 1);

pio_gpio_init(pio, gpio);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 1, true);
pio_sm_config c = genseq_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, gpio);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);

for (i = 0; i < DATA_WORDS; i++) {
printf("Iter %d:\n", i);
pio_sm_put_blocking(pio, sm, i);
if (use_dma) {
ret = pio_sm_xfer_data(pio, sm, PIO_DIR_FROM_SM, (i + 1) * sizeof(databuf[0]), databuf);
if (ret)
break;

for (j = i; j >= 0; j--)
{
int v = databuf[i - j];
if (v != j)
printf(" %d: %d\n", j, v);
}
} else {
for (j = i; j >= 0; j--)
{
int v = pio_sm_get_blocking(pio, sm);
if (v != j)
printf(" %d: %d\n", j, v);
}
}
sleep_ms(10);
}

if (ret)
printf("* error %d\n", ret);
return ret;
}
42 changes: 42 additions & 0 deletions piolib/genseq.pio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //

#pragma once

#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif

// ------ //
// genseq //
// ------ //

#define genseq_wrap_target 0
#define genseq_wrap 4

static const uint16_t genseq_program_instructions[] = {
// .wrap_target
0x80a0, // 0: pull block side 0
0xa027, // 1: mov x, osr side 0
0xa0c1, // 2: mov isr, x side 0
0x9020, // 3: push block side 1
0x0042, // 4: jmp x--, 2 side 0
// .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program genseq_program = {
.instructions = genseq_program_instructions,
.length = 5,
.origin = -1,
};

static inline pio_sm_config genseq_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + genseq_wrap_target, offset + genseq_wrap);
sm_config_set_sideset(&c, 1, false, false);
return c;
}
#endif

24 changes: 24 additions & 0 deletions piolib/hardware/clocks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Raspberry Pi Ltd.
* All rights reserved.
*/

#ifndef _HARDWARE_CLOCKS_H
#define _HARDWARE_CLOCKS_H

enum clock_index {
clk_gpout0 = 0, ///< GPIO Muxing 0
clk_gpout1, ///< GPIO Muxing 1
clk_gpout2, ///< GPIO Muxing 2
clk_gpout3, ///< GPIO Muxing 3
clk_ref, ///< Watchdog and timers reference clock
clk_sys, ///< Processors, bus fabric, memory, memory mapped registers
clk_peri, ///< Peripheral clock for UART and SPI
clk_usb, ///< USB clock
clk_adc, ///< ADC clock
clk_rtc, ///< Real time clock
CLK_COUNT
};

#endif
63 changes: 63 additions & 0 deletions piolib/hardware/gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Raspberry Pi Ltd.
* All rights reserved.
*/
#ifndef _HARDWARE_GPIO_H
#define _HARDWARE_GPIO_H

#include "pio_platform.h"

#ifndef PARAM_ASSERTIONS_ENABLED_GPIO
#define PARAM_ASSERTIONS_ENABLED_GPIO 0
#endif

#define NUM_BANK0_GPIOS 32

enum gpio_function {
GPIO_FUNC_XIP = 0,
GPIO_FUNC_SPI = 1,
GPIO_FUNC_UART = 2,
GPIO_FUNC_I2C = 3,
GPIO_FUNC_PWM = 4,
GPIO_FUNC_SIO = 5,
GPIO_FUNC_PIO0 = 6,
GPIO_FUNC_PIO1 = 7,
GPIO_FUNC_GPCK = 8,
GPIO_FUNC_USB = 9,
GPIO_FUNC_NULL = 0x1f,
};

#define GPIO_OUT 1
#define GPIO_IN 0

enum gpio_irq_level {
GPIO_IRQ_LEVEL_LOW = 0x1u,
GPIO_IRQ_LEVEL_HIGH = 0x2u,
GPIO_IRQ_EDGE_FALL = 0x4u,
GPIO_IRQ_EDGE_RISE = 0x8u,
};

enum gpio_override {
GPIO_OVERRIDE_NORMAL = 0, ///< peripheral signal selected via \ref gpio_set_function
GPIO_OVERRIDE_INVERT = 1, ///< invert peripheral signal selected via \ref gpio_set_function
GPIO_OVERRIDE_LOW = 2, ///< drive low/disable output
GPIO_OVERRIDE_HIGH = 3, ///< drive high/enable output
};
enum gpio_slew_rate {
GPIO_SLEW_RATE_SLOW = 0, ///< Slew rate limiting enabled
GPIO_SLEW_RATE_FAST = 1 ///< Slew rate limiting disabled
};

enum gpio_drive_strength {
GPIO_DRIVE_STRENGTH_2MA = 0, ///< 2 mA nominal drive strength
GPIO_DRIVE_STRENGTH_4MA = 1, ///< 4 mA nominal drive strength
GPIO_DRIVE_STRENGTH_8MA = 2, ///< 8 mA nominal drive strength
GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
};

static inline void check_gpio_param(__unused uint gpio) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
}

#endif
11 changes: 11 additions & 0 deletions piolib/hardware/pio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Raspberry Pi Ltd.
* All rights reserved.
*/
#ifndef _HARDWARE_PIO_H
#define _HARDWARE_PIO_H

#include "piolib.h"

#endif
Loading