0

Raspberry Pi Pico RP2040

When transmitting the UART produce endless interrupts. I edited the example "uart_advanced" to show the problem, it occurs with or without fifos enabled.

to show the problem on the oscilloscope I toggled gpio in the interrupt handler. in the attached image:

  • channel 1 is the uart tx line gpio (8)
  • channel 2 is the interrupt handler gpio (16)

the code is attached also

How do I acknowlage the interrupt? What I'm missing here?

#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "hardware/gpio.h"


#define UART_ID         uart1
#define BAUD_RATE       115200
#define DATA_BITS       8
#define STOP_BITS       1
#define PARITY          UART_PARITY_NONE

#define UART_TX_PIN     8
#define UART_RX_PIN     9

#define D_GPIO_TEST     16


// interrupt handler
void on_uart_interrupt() {
    for( int i = 0; i < 8; ++i ) {
        gpio_put( D_GPIO_TEST, true ) ;
    }
    gpio_put( D_GPIO_TEST, false ) ;
}


int main() {
gpio_init( D_GPIO_TEST ) ;
gpio_set_dir( D_GPIO_TEST, GPIO_OUT ) ;
gpio_pull_up( D_GPIO_TEST ) ;
gpio_put( D_GPIO_TEST, false ) ;

   // Set up our UART with a basic baud rate.
    uart_init(UART_ID, 2400);

    // Set the TX and RX pins by using the function select on the GPIO
    // Set datasheet for more information on function select
    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
    gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);

    // Actually, we want a different speed
    // The call will return the actual baud rate selected, which will be as close as
    // possible to that requested
    int __unused actual = uart_set_baudrate(UART_ID, BAUD_RATE);

    // Set UART flow control CTS/RTS, we don't want these, so turn them off
    uart_set_hw_flow(UART_ID, false, false);

    // Set our data format
    uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);

    // Turn on FIFO's 
    //uart_set_fifo_enabled(UART_ID, true);

    // Set up a interrupt
    // We need to set up the handler first
    // Select correct interrupt for the UART we are using
    int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ;

    // And set up and enable the interrupt handlers
    irq_set_exclusive_handler(UART_IRQ, on_uart_interrupt);
    irq_set_enabled(UART_IRQ, true);

    // Now enable the UART interrupts
    uart_set_irq_enables(UART_ID, false, true);

    sleep_ms( 10 ) ;

    uart_puts(UART_ID, "Hello uart\n");

    while (1)
        tight_loop_contents();
}

enter image description here

teach me
  • 453
  • 5
  • 20
  • Reading the RP2040 Datasheet, it sounds like the interrupt routine has to clear the TX interrupt bit. Or feed the FIFO. *The transmit interrupt is cleared by writing data to the transmit FIFO until it becomes greater than the trigger level, or by clearing the interrupt.* Other UART interrupts also say: *It is cleared by writing a 1 to the corresponding bit(s) in the Interrupt Clear Register, UARTICR,* – aMike Jun 01 '23 at 02:24

2 Answers2

0

Thanks @aMike, I found the info at RP2040 Datasheet.

As @aMike mention, feed the FIFO if you have additional data to transmit otherwise clear the tx interrupt. see below how to clear the tx interrupt.

// interrupt handler
void on_uart_interrupt() {

    // The missing line to clear the TX interrupt
    uart_get_hw(UART_ID)->icr = UART_UARTICR_TXIC_BITS ;

    for( int i = 0; i < 8; ++i ) {
        gpio_put( D_GPIO_TEST, true ) ;
    }
    gpio_put( D_GPIO_TEST, false ) ;
}
teach me
  • 453
  • 5
  • 20
  • Why are you not using a pattern like `while (uart_is_readable (UART_ID)) { uint8_t ch = uart_getc (UART_ID); ... /* do your stuff */ }`? – David C. Rankin Jun 23 '23 at 07:57
  • @DavidC.Rankin thats exactly what I'm doing to receive data. The question talks about transmitting. When you transmit the UART generates endless interrupts if you don't clear the TX interrupt as in the example above. Best regards – teach me Jun 26 '23 at 06:38
  • Sorry for the confusion. The general patter is to read while data is pending and transmit as needed. I skimmed past your point that it was the TX interrupts being generated that were your problem -- glad you found the solution. I guess you have a separate part of your code responding to the TX interrupts that is where the issue arises. – David C. Rankin Jun 26 '23 at 07:14
0

you shoud clear UART recieve buffer.

void on_uart_interrupt() {
unsigned char ch;

ch = uart_get_hw(UART_ID)->dr; //receive

for( int i = 0; i < 8; ++i ) {
    gpio_put( D_GPIO_TEST, true ) ;
}
gpio_put( D_GPIO_TEST, false ) ;
}
ej3989
  • 1