62 lines
2.0 KiB
Plaintext
62 lines
2.0 KiB
Plaintext
|
;
|
||
|
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||
|
;
|
||
|
; SPDX-License-Identifier: BSD-3-Clause
|
||
|
;
|
||
|
|
||
|
.program uart_tx
|
||
|
.side_set 1 opt
|
||
|
|
||
|
; An 8n1 UART transmit program.
|
||
|
; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin.
|
||
|
|
||
|
pull side 1 [7] ; Assert stop bit, or stall with line in idle state
|
||
|
set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks
|
||
|
bitloop: ; This loop will run 8 times (8n1 UART)
|
||
|
out pins, 1 ; Shift 1 bit from OSR to the first OUT pin
|
||
|
jmp x-- bitloop [6] ; Each loop iteration is 8 cycles.
|
||
|
|
||
|
|
||
|
% c-sdk {
|
||
|
#include "hardware/clocks.h"
|
||
|
|
||
|
static inline void uart_tx_program_init(PIO pio, uint sm, uint offset, uint pin_tx, uint baud) {
|
||
|
// Tell PIO to initially drive output-high on the selected pin, then map PIO
|
||
|
// onto that pin with the IO muxes.
|
||
|
pio_sm_set_pins_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||
|
pio_sm_set_pindirs_with_mask(pio, sm, 1u << pin_tx, 1u << pin_tx);
|
||
|
pio_gpio_init(pio, pin_tx);
|
||
|
|
||
|
pio_sm_config c = uart_tx_program_get_default_config(offset);
|
||
|
|
||
|
// OUT shifts to right, no autopull
|
||
|
sm_config_set_out_shift(&c, true, false, 32);
|
||
|
|
||
|
// We are mapping both OUT and side-set to the same pin, because sometimes
|
||
|
// we need to assert user data onto the pin (with OUT) and sometimes
|
||
|
// assert constant values (start/stop bit)
|
||
|
sm_config_set_out_pins(&c, pin_tx, 1);
|
||
|
sm_config_set_sideset_pins(&c, pin_tx);
|
||
|
|
||
|
// We only need TX, so get an 8-deep FIFO!
|
||
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||
|
|
||
|
// 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 void uart_tx_program_putc(PIO pio, uint sm, char c) {
|
||
|
pio_sm_put_blocking(pio, sm, (uint32_t)c);
|
||
|
}
|
||
|
|
||
|
static inline void uart_tx_program_puts(PIO pio, uint sm, const char *s) {
|
||
|
while (*s)
|
||
|
uart_tx_program_putc(pio, sm, *s++);
|
||
|
}
|
||
|
|
||
|
%}
|