Search code examples
raspberry-pi-picorp2040

UART TX produce endless interrupts. How to acknowlage the interrupt?


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


Solution

  • 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 ) ;
    }