Initial Release

This commit is contained in:
graham sanderson
2021-01-20 10:49:34 -06:00
commit 46078742c7
245 changed files with 21157 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
add_executable(pio_uart_rx)
pico_generate_pio_header(pio_uart_rx ${CMAKE_CURRENT_LIST_DIR}/uart_rx.pio)
target_sources(pio_uart_rx PRIVATE uart_rx.c)
target_link_libraries(pio_uart_rx PRIVATE
pico_stdlib
pico_multicore
hardware_pio
)
pico_add_extra_outputs(pio_uart_rx)
# add url via pico_set_program_url
example_auto_set_url(pio_uart_rx)

60
pio/uart_rx/uart_rx.c Normal file
View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "hardware/pio.h"
#include "hardware/uart.h"
#include "uart_rx.pio.h"
// This program
// - Uses UART1 (the spare UART, by default) to transmit some text
// - Uses a PIO state machine to receive that text
// - Prints out the received text to the default console (UART0)
// This might require some reconfiguration on boards where UART1 is the
// default UART.
#define SERIAL_BAUD PICO_DEFAULT_UART_BAUD_RATE
#define HARD_UART_INST uart1
// You'll need a wire from GPIO4 -> GPIO3
#define HARD_UART_TX_PIN 4
#define PIO_RX_PIN 3
// Ask core 1 to print a string, to make things easier on core 0
void core1_main() {
const char *s = (const char *) multicore_fifo_pop_blocking();
uart_puts(HARD_UART_INST, s);
}
int main() {
// Console output (also a UART, yes it's confusing)
setup_default_uart();
printf("Starting PIO UART RX example\n");
// Set up the hard UART we're going to use to print characters
uart_init(HARD_UART_INST, SERIAL_BAUD);
gpio_set_function(HARD_UART_TX_PIN, GPIO_FUNC_UART);
// Set up the state machine we're going to use to receive them.
PIO pio = pio0;
uint sm = 0;
uint offset = pio_add_program(pio, &uart_rx_program);
uart_rx_program_init(pio, sm, offset, PIO_RX_PIN, SERIAL_BAUD);
// Tell core 1 to print some text to uart1 as fast as it can
multicore_launch_core1(core1_main);
const char *text = "Hello, world from PIO! (Plus 2 UARTs and 2 cores, for complex reasons)\n";
multicore_fifo_push_blocking((uint32_t) text);
// Echo characters received from PIO to the console
while (true) {
char c = uart_rx_program_getc(pio, sm);
putchar(c);
}
}

94
pio/uart_rx/uart_rx.pio Normal file
View File

@@ -0,0 +1,94 @@
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;
.program uart_rx_mini
; Minimum viable 8n1 UART receiver. Wait for the start bit, then sample 8 bits
; with the correct timing.
; IN pin 0 is mapped to the GPIO used as UART RX.
; Autopush must be enabled, with a threshold of 8.
wait 0 pin 0 ; Wait for start bit
set x, 7 [10] ; Preload bit counter, delay until eye of first data bit
bitloop: ; Loop 8 times
in pins, 1 ; Sample data
jmp x-- bitloop [6] ; Each iteration is 8 cycles
% c-sdk {
#include "hardware/clocks.h"
#include "hardware/gpio.h"
static inline void uart_rx_mini_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) {
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
pio_gpio_init(pio, pin);
gpio_pull_up(pin);
pio_sm_config c = uart_rx_mini_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin); // for WAIT, IN
// Shift to right, autopush enabled
sm_config_set_in_shift(&c, true, true, 8);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
// SM transmits 1 bit per 8 execution cycles.
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}
.program uart_rx
; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and
; break conditions more gracefully.
; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX.
start:
wait 0 pin 0 ; Stall until start bit is asserted
set x, 7 [10] ; Preload bit counter, then delay until halfway through
bitloop: ; the first data bit (12 cycles incl wait, set).
in pins, 1 ; Shift data bit into ISR
jmp x-- bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles
jmp pin good_stop ; Check stop bit (should be high)
irq 4 rel ; Either a framing error or a break. Set a sticky flag,
wait 1 pin 0 ; and wait for line to return to idle state.
jmp start ; Don't push data if we didn't see good framing.
good_stop: ; No delay before returning to start; a little slack is
push ; important in case the TX clock is slightly too fast.
% c-sdk {
static inline void uart_rx_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) {
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
pio_gpio_init(pio, pin);
gpio_pull_up(pin);
pio_sm_config c = uart_rx_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin); // for WAIT, IN
sm_config_set_jmp_pin(&c, pin); // for JMP
// Shift to right, autopull disabled
sm_config_set_in_shift(&c, true, false, 32);
// Deeper FIFO as we're not doing any TX
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
// SM transmits 1 bit per 8 execution cycles.
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
static inline char uart_rx_program_getc(PIO pio, uint sm) {
// 8-bit read from the uppermost byte of the FIFO, as data is left-justified
io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm] + 3;
while (pio_sm_is_rx_fifo_empty(pio, sm))
tight_loop_contents();
return (char)*rxfifo_shift;
}
%}