genyasugen
@genyasugen (YASUNARI GEN)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

PICOでUART2個増設

Q&A

Closed

解決したいこと

PICO でUART増設したい(追加2個)

  PIO0とPIO1で同じコード動かしたい同じ機能の(FORMAT)のUART増設したい

例)
使用ツールは SDK。
解決方法を教えて下さい。

発生している問題・エラー

下記コードで PIO0は動作します
PIIO1でうまく動作しません

該当するソースコード


int main()
{
    stdio_init_all();
//Uart 2
    PIO pio = pio0;        // values: pio0, pio1 正しく動く
   // PIO pio = pio1;        // values: pio0, pio1 動かない

    uint pin = 20;          //20= No.26Pin  rx pin. Any gpio is valid
    uint irq = PIO0_IRQ_0; // values for pio0: PIO0_IRQ_0, PIO0_IRQ_1. values for pio1:O1_IRQ_0, PIO1_IRQ_1
    
    uint baudrate = 9600;

    uart_rx_init(pio, pin, baudrate);
    uart_rx_set_handler(rx_handler, irq);
  
//Uart 3
//

   PIO pio2 = pio0;        // values: pio0, pio1
    uint pin2 = 21;          //21= No.27Pin  rx pin. Any gpio is valid
    uint irq2 = PIO0_IRQ_0; // values for pio0: PIO0_IRQ_0, PIO0_IRQ_1. values for pio1: PIO1_IRQ_0, PIO1_IRQ_1
    uint baudrate2 = 9600;

 //   uart_rx_init(pio2, pin2, baudrate2);
 //   uart_rx_set_handler(rx_handler2, irq2);

### 自分で試したこと
pio1:O1_IRQ_0, PIO1_IRQ_1 色々変えてみたが駄目です

-----
#include "uart_rx.h"

#define BUFFER_SIZE (1 << UART_RX_BUFFER_RING_BITS)

static const uint reload_counter_ = 0xffffffff;
static uint sm_, offset_, buffer_pos_, irq_, dma_channel_, dma_channel_reload_counter_;
static PIO pio_;
static void (*handler_)() = NULL;
static uint8_t buffer_[BUFFER_SIZE] __attribute__((aligned(BUFFER_SIZE * sizeof(uint8_t))));

static inline void handler_pio(void);

void uart_rx_init(PIO pio, uint pin, uint baudrate)
{
    // init pio
    pio_ = pio;
    sm_ = pio_claim_unused_sm(pio_, true);
    pio_sm_set_consecutive_pindirs(pio_, sm_, pin, 1, false);
   // pio_sm_set_consecutive_pindirs(pio_, sm_, pin, 1, false);
    pio_gpio_init(pio_, pin);
    gpio_pull_up(pin);
    offset_ = pio_add_program(pio_, &uart_rx_program);
    pio_sm_config pio_config = uart_rx_program_get_default_config(offset_);
    sm_config_set_in_pins(&pio_config, pin);
    sm_config_set_jmp_pin(&pio_config, pin);
    sm_config_set_in_shift(&pio_config, true, false, 32);
    sm_config_set_fifo_join(&pio_config, PIO_FIFO_JOIN_RX);
    float div = (float)clock_get_hz(clk_sys) / (8 * baudrate);
    sm_config_set_clkdiv(&pio_config, div);
    pio_sm_init(pio_, sm_, offset_, &pio_config);

    // init dma reload counter
    dma_channel_reload_counter_ = dma_claim_unused_channel(true);
    dma_channel_ = dma_claim_unused_channel(true);
    dma_channel_config config_dma_channel_reload_counter = dma_channel_get_default_config(dma_channel_reload_counter_);
    channel_config_set_transfer_data_size(&config_dma_channel_reload_counter, DMA_SIZE_32);
    channel_config_set_write_increment(&config_dma_channel_reload_counter, false);
    channel_config_set_read_increment(&config_dma_channel_reload_counter, false);
    dma_channel_configure(
        dma_channel_reload_counter_,
        &config_dma_channel_reload_counter,
        &dma_hw->ch[dma_channel_].al1_transfer_count_trig, // write address
        &reload_counter_,                                  // read address
        1,
        false);

    // init dma buffer
    dma_channel_config config_dma = dma_channel_get_default_config(dma_channel_);
    channel_config_set_transfer_data_size(&config_dma, DMA_SIZE_8);
    channel_config_set_ring(&config_dma, true, UART_RX_BUFFER_RING_BITS);
    channel_config_set_write_increment(&config_dma, true);
    channel_config_set_read_increment(&config_dma, false);
    channel_config_set_dreq(&config_dma, pio_get_dreq(pio_, sm_, false));
    channel_config_set_chain_to(&config_dma, dma_channel_reload_counter_);
    dma_channel_configure(
        dma_channel_,
        &config_dma,
        &buffer_,                     // write address
        (uint8_t *)&pio0->rxf[0] + 3, // read address
        0xffffffff,
        false);

    dma_channel_start(dma_channel_);
    pio_sm_set_enabled(pio_, sm_, true);
}

void uart_rx_set_handler(uart_rx_handler_t handler, uint irq)
{
    handler_ = handler;
    if (irq == PIO0_IRQ_0 || irq == PIO1_IRQ_0)
        pio_set_irq0_source_enabled(pio_, (enum pio_interrupt_source)(pis_interrupt0 + UART_RX_IRQ_NUM), true);
    else
        pio_set_irq1_source_enabled(pio_, (enum pio_interrupt_source)(pis_interrupt0 + UART_RX_IRQ_NUM), true);
    pio_interrupt_clear(pio_, UART_RX_IRQ_NUM);
    irq_set_exclusive_handler(irq, handler_pio);
    irq_set_enabled(irq, true);
}

char uart_rx_read(void)
{
    uint transfer_count = 0xffffffff - dma_hw->ch[dma_channel_].transfer_count;
    if (uart_rx_overflow())
        buffer_pos_ = transfer_count - BUFFER_SIZE;
    char value = buffer_[buffer_pos_ % BUFFER_SIZE];
    if (buffer_pos_ < transfer_count)
        buffer_pos_++;
    return value;
}

char uart_rx_peek(void)
{
    uint transfer_count = 0xffffffff - dma_hw->ch[dma_channel_].transfer_count;
    if (uart_rx_overflow())
        buffer_pos_ = transfer_count - BUFFER_SIZE;
    return buffer_[buffer_pos_ % BUFFER_SIZE];
}

uint uart_rx_available(void)
{
    uint available = 0xffffffff - dma_hw->ch[dma_channel_].transfer_count - buffer_pos_;
    if (available > BUFFER_SIZE)
        available = BUFFER_SIZE;
    return available;
}

bool uart_rx_overflow(void)
{
    uint transfer_count = 0xffffffff - dma_hw->ch[dma_channel_].transfer_count;
    if (transfer_count - buffer_pos_ > BUFFER_SIZE)
        return true;
    return false;
}

void uart_rx_remove(void)
{
    handler_ = NULL;
    pio_remove_program(pio_, &uart_rx_program, offset_);
    pio_sm_unclaim(pio_, sm_);
    dma_channel_abort(dma_channel_);
    dma_channel_unclaim(dma_channel_);
}

static inline void handler_pio(void)
{
    if (handler_)
        handler_();
    pio_interrupt_clear(pio_, UART_RX_IRQ_NUM);
}
0

1Answer

Comments

  1. @genyasugen

    Questioner

    情報ありがとうございました私の質問が間違っていましたUARTを追加で2本増設したいのです

  2. Picoはハードウェアシリアルは2本までです。
    それ以上はソフトウェアシリアルを使うことになると思います。

    シリアル通信名 送信用端子 受信用端子
    UART0 UART0 TX UATR0 RX
    UART1 UART1 TX UART1 RX
    ソフトウェアシリアル GP0〜GP22
    GP26〜GP28
    GP0〜GP22
    GP26〜GP28

    ソフトウェアシリアルの使い方、↓これが参考になるかな?

  3. @genyasugen

    Questioner

    PIOで実装する方法探しています。1個追加(Total3個)はできたのですが、あと1個どうしても」実現できてなくて、困っています

  4. 「ソフトウェアシリアル」は、PIOベースです。

    Pico SDK でも使えるのでは?

  5. @genyasugen

    Questioner

    Arduino のソフトシリアルでUART2CH追加できました、ありがとうございました
    C-SDKはまだです。もしよければ PICO 用のArduino のソフトシリアルのソース(CPP)の保存場所わかりませんでしょうか?C-SDKの参考にします

  6. 'SoftwareSerial.h''SerialPIO.h'をincludeしていて、'SerialPIO.cpp'も同じフォルダですね。自分の環境だと
    "C:\Users\USERNAME\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\3.7.2\cores\rp2040"
    でした。

  7. @genyasugen

    Questioner

    本当に助かりました。試してみます

  8. 解決でよろしければ、当Q&Aをクローズしてください。

Your answer might help someone💌