Skip to content

Commit

Permalink
Add PIO serial driver and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
KarlK90 authored and thpoll83 committed May 11, 2022
1 parent 62efd96 commit bab4567
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/serial_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ Where 'n' matches the peripheral number of your selected USART on the MCU.

### The `PIO` driver

<<<<<<< HEAD
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. Because of the flexible nature of the PIO peripherals, **any** GPIO pin can be used as a `TX` or `RX` pin. Half-duplex and Full-duplex operation is fully supported. The Half-duplex operation mode uses the built-in pull-ups and GPIO manipulation on the RP2040 to drive the line high by default. An external pull-up is therefore not necessary.
=======
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. Because of the flexible nature of the PIO peripherals, **any** GPIO pin can be used as a `TX` or `RX` pin. Half-duplex and Full-duplex operation is fully supported. The Half-duplex operation mode uses the built-in pull-ups of the RP2040 by default to drive the line high, therefore external pull-ups are not strictly necessary. But as these pull-ups are rather weak (~50kΩ) it is adviced to use external pull-ups on new designs.
>>>>>>> 951395777a (Add PIO serial driver and documentation)
Configure the hardware via your config.h:
```c
Expand Down
46 changes: 46 additions & 0 deletions platforms/chibios/drivers/serial_pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ void pio_serve_interrupt(void) {
}
}

<<<<<<< HEAD
#if !defined(SERIAL_USART_FULL_DUPLEX)
// The internal pull-ups of the RP2040 are rather weakish with a range of 50k to
// 80k, which in turn do not provide enough current to guarantee fast signal rise
Expand Down Expand Up @@ -179,6 +180,8 @@ static inline void enter_rx_state(void) {}
static inline void leave_rx_state(void) {}
#endif

=======
>>>>>>> 951395777a (Add PIO serial driver and documentation)
/**
* @brief Clear the RX and TX hardware FIFOs of the state machines.
*/
Expand Down Expand Up @@ -237,10 +240,37 @@ static inline bool send_impl(const uint8_t* source, const size_t size) {
* @return false Send failed.
*/
inline bool send(const uint8_t* source, const size_t size) {
<<<<<<< HEAD
leave_rx_state();
bool result = send_impl(source, size);
enter_rx_state();

=======
#if !defined(SERIAL_USART_FULL_DUPLEX)
// In Half-duplex operation the tx pin dual-functions as sender and
// receiver. To not receive the data we will send, we disable the receiving
// state machine.
pio_sm_set_enabled(pio, rx_state_machine, false);
#endif

bool result = send_impl(source, size);

#if !defined(SERIAL_USART_FULL_DUPLEX)
// Wait for the transmitting state machines fifo to run empty. At this point
// the last byte has been pulled from the transmitting state machines fifo
// into the output shift register. We have to wait a tiny bit more until
// this byte is transmitted, before we can turn on the receiving state
// machine again.
osalSysLock();
while (!pio_sm_is_tx_fifo_empty(pio, tx_state_machine)) {
}
// Wait for ~11 bits, 1 start bit + 8 data bits + 1 stop bit + 1 bit
// headroom.
chSysPolledDelayX(US2RTC(1 * MHZ, (1000000U * 11 / SERIAL_USART_SPEED)));
pio_sm_set_enabled(pio, rx_state_machine, true);
osalSysUnlock();
#endif
>>>>>>> 951395777a (Add PIO serial driver and documentation)
return result;
}

Expand Down Expand Up @@ -315,20 +345,33 @@ static inline void pio_tx_init(pin_t tx_pin) {
(pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
// clang-format on
pio_sm_set_pins_with_mask(pio, tx_state_machine, 1U << tx_pin, 1U << tx_pin);
<<<<<<< HEAD
pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1U, true);
=======
pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1, true);
>>>>>>> 951395777a (Add PIO serial driver and documentation)
#else
// clang-format off
iomode_t tx_pin_mode = PAL_RP_PAD_IE |
PAL_RP_GPIO_OE |
PAL_RP_PAD_SCHMITT |
PAL_RP_PAD_PUE |
PAL_RP_PAD_SLEWFAST |
<<<<<<< HEAD
PAL_RP_PAD_DRIVE12 |
PAL_RP_IOCTRL_OEOVER_DRVINVPERI |
(pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
// clang-format on
pio_sm_set_pins_with_mask(pio, tx_state_machine, 0U << tx_pin, 1U << tx_pin);
pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1U, true);
=======
PAL_RP_PAD_DRIVE4 |
PAL_RP_IOCTRL_OEOVER_DRVINVPERI |
(pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
// clang-format on
pio_sm_set_pins_with_mask(pio, tx_state_machine, 0U, 1U << tx_pin);
pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1, true);
>>>>>>> 951395777a (Add PIO serial driver and documentation)
#endif

palSetLineMode(tx_pin, tx_pin_mode);
Expand Down Expand Up @@ -417,8 +460,11 @@ static inline void pio_init(pin_t tx_pin, pin_t rx_pin) {
#else
nvicEnableVector(RP_PIO0_IRQ_0_NUMBER, RP_IRQ_UART0_PRIORITY);
#endif
<<<<<<< HEAD

enter_rx_state();
=======
>>>>>>> 951395777a (Add PIO serial driver and documentation)
}

/**
Expand Down

0 comments on commit bab4567

Please sign in to comment.