NRF9160 Disable UART and RX pin into an interrupt pin

Hello everyone,

I'm working on a project with NRF9160 nRF Connect SDK v2.3.0.

In my project i use UART0 to exchange data and i disable the UART when is not use.

I need an interrupt to wake up my device when data come on the UART pin (TX/RX).

I have found different topic to disable and enable UART on runinng time. 

Now, when my uart is disable, i would like to convert RX pin into an interrupt pin which allow me to re-enable the UART to get data when interrupt occur.

Could you tell me if you have any advice about that ?

Best regards,

Lam

  • I found my error, lin 1, I define SWIN3_NODE and line 6 i use SWIN3. That wrong, i need to write on line 6 : "SWIN3_NODE"

    I have add in "configure_int_rx" function, 

    if (!device_is_ready(button.port)) {
    		printk("Error");
    		return;
    	}

    At the top of the function

    //gpio for UART interrupt definition
    void configure_int_rx(void){
    	int ret;
    
    	printk("configure interrupt\r\n");
    
    	if (!device_is_ready(button.port)) {
    		printk("Error");
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&button,GPIO_INPUT);
    	if (ret != 0) {
    		printk("Error");// %d: failed to configure %s pin %d\n",
    		      // ret, button.port->name, button.pin);
    		return;
    	}
    
    	printk("test1\r\n");
    
    	ret = gpio_pin_interrupt_configure_dt(&button,GPIO_INT_EDGE_TO_ACTIVE);		//GPIO_INT_EDGE_BOTH
    	if (ret != 0) {
    		printk("Error");// %d: failed to configure interrupt on %s pin %d\n",
    			//ret, button.port->name, button.pin);
    		return;
    	}
    
    	printk("test2\r\n");
    
    	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
    	gpio_add_callback(button.port, &button_cb_data);
    	printk("Set up button");// at %s pin %d\n", button.port->name, button.pin);
    }

    No I'm trying to disable, my interrupt to reenable the uart when my interrupt occur.

    When my interrupt occur, my callback function do that :

    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
    	const struct device * gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));
        gpio_pin_configure(gpio_dev,6, GPIO_DISCONNECTED);
    	printk("Button pressed\r\n");
    	restart_uart();
    
    }

    In my "restart_uart", i do that

    uint8_t restart_uart(void){
    
    
       const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
    
        if (!device_is_ready(uart)) {
            printk("error device ready\r\n");
            return;
        }
        initControlUart();
        printk("restart uart\r\n");
    }

    When my initControlUart is executed, i have an error in this code: 

     error = uart_rx_enable(uart_info.dev, buffer, RX_BUFF_LEN, RX_RCV_TIMEOUT);
        if(error != 0){
            printk("ERROR : Unable to init RX\n");
            return -1;
        }

    That works great at init but when i try to restart that's not work. It seems that RX gpio stay unable to be configure in RX

    Update below

    Best regards,

    lam

  • I have a better answer now,

    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
    	int ret;
    	ret = gpio_pin_interrupt_configure_dt(&button,GPIO_INT_DISABLE);		//GPIO_INT_EDGE_BOTH
    	if (ret != 0) {
    		printk("Error disable INT\r\n");
    		return;
    	}
    	printk("Button pressed\r\n");
    	restart_uart();
    
    }
    
    uint8_t restart_uart(void){
    
        NRF_UARTE0_NS->PSEL.RXD = 6;
        NRF_UARTE0_NS->PSEL.TXD = 7;
        NRF_UARTE0_NS->ENABLE = 8;
        NRF_UARTE0_NS->TASKS_STARTRX = 1;
        NRF_UARTE0_NS->TASKS_STARTTX = 1;
    
        send_uart_data_char("UART RESTARTED\r\n");
    
        //initControlUart();
    
        printk("restart uart\r\n");
    }

    I correctly have an answer from my UART, i correctly receive "UART RESTARTED".

    But 2 errors messages stay : 

    - ERROR : uart_rx_buf_rsp Failed

    - UART_TX_ABORTED

    The first one come from uart libray and the other one come from my uart callback function

    static void uart_callback(const struct device *dev, struct uart_event *evt, struct uart_info_struct *user_data){
        uint8_t *buffer, error;
    	switch(evt->type){
    		case UART_RX_RDY:
    		    //printk("RCV %d bytes\n", evt->data.rx.len);
                if(user_data->cmd_buffer_len < CMD_BUFF_LEN){
                    if((user_data->cmd_buffer_len + evt->data.rx.len) <= CMD_BUFF_LEN){
                        //case of new data less than remaining space in cmd_buffer
                        memcpy(user_data->cmd_buffer + user_data->cmd_buffer_len, evt->data.rx.buf + evt->data.rx.offset, evt->data.rx.len);
                        user_data->cmd_buffer_len += evt->data.rx.len;
                    }else{
                        //case of new data more than remaining space
                        memcpy(user_data->cmd_buffer + user_data->cmd_buffer_len, evt->data.rx.buf + evt->data.rx.offset, CMD_BUFF_LEN - user_data->cmd_buffer_len);
                        user_data->cmd_buffer_len += CMD_BUFF_LEN - user_data->cmd_buffer_len;
                    }
                }
                process_buffer(user_data);
    		break;
    		case UART_TX_ABORTED:
    		    printk("UART_TX_ABORTED\n");
    		break;
    		case UART_TX_DONE:
    		    //printk("UART_TX_DONE\n");
                //printk("+SEM=%d\n",k_sem_count_get(user_data->tx_semaphore));
                k_sem_give(user_data->tx_semaphore);
                //printk("+SEM=%d\n",k_sem_count_get(user_data->tx_semaphore));
    		break;
    		case UART_RX_BUF_REQUEST:
                //printk("UART_RX_BUF_REQUEST\n");
                buffer = k_malloc(RX_BUFF_LEN);
                if(buffer == NULL){
                    printk("ERROR : RX_BUF_REQUEST Failed to allocate buffer\n");
                    return;
                }
                error = uart_rx_buf_rsp(uart_info.dev, buffer, RX_BUFF_LEN);
                if(error != 0){
                    printk("ERROR : uart_rx_buf_rsp Failed\n");
                    return;
                }
    		break;
                case UART_RX_BUF_RELEASED:
                k_free(evt->data.rx_buf.buf);
                //printk("UART_RX_BUF_RELEASED\n");
    		break;
    		case UART_RX_DISABLED:
    		    printk("UART_RX_DISABLED\n");
    		break;
    		case UART_RX_STOPPED:
    		    printk("UART_RX_STOPPED\n");
    		break;
    	}
    }

    I think i'm on the right way,

    do you have advice about that ?

    Best regards,

    Lam

  • Hello,

    We think the problem lies where it is starting and stopping the UART. Can you check this (+) How can I enable and disable UART devices at run time on nRF9160? - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com) case? You may need to check the RXTO event. 

    Thanks.

    BR

    Kazi

  • Hello,

    Thanks for your help,

    I found a solution that was the following, if this can help someone.

    void button_pressed(const struct device *dev, struct gpio_callback *cb,
    		    uint32_t pins)
    {
    	int ret;
    
    	printk("Button pressed\r\n");
    
    	ret = gpio_pin_interrupt_configure(button.port,button.pin,GPIO_INT_DISABLE);		//GPIO_INT_EDGE_BOTH
    	if (ret != 0) {
    		printk("Error disable INT\r\n");
    		return;
    	}
    	
    	//restart_uart();
    	k_work_submit(&button_action_work);
    	//flag_interrupt = 1;
    }

    //gpio for UART interrupt definition
    void configure_int_rx(void){
    	int ret;
    
    	printk("configure interrupt\r\n");
    
    	if (!device_is_ready(button.port)) {
    		printk("Error config INT 1\r\n");
    		return;
    	}
    	
    	ret = gpio_pin_configure(button.port,button.pin,GPIO_INPUT);
    	if (ret != 0) {
    		printk("Error config INT 2\r\n");
    		return;
    	}
    
    	ret = gpio_pin_interrupt_configure(button.port,button.pin,GPIO_INT_EDGE_TO_ACTIVE);		//GPIO_INT_EDGE_BOTH
    	if (ret != 0) {
    		printk("Error config INT 3\r\n");
    		return;
    	}
    
    	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
    
    	ret = gpio_add_callback(button.port, &button_cb_data);
    	if (ret != 0) {
    		printk("Error config INT 4\r\n");
    		return;
    	}
    
    	printk("Config INT OK\r\n");
    }

    void timer_disable_uart_work_fn(struct k_work *work)
    {
    	disable_uart();
        configure_int_rx();
    }

    void process_work_timer_uart_disable(void){
    	//scehdule a time to disable uart
        //cancel last schedule
        if(k_work_delayable_busy_get(&timer_disable_uart_work) != 0 ){
            k_work_cancel_delayable(&timer_disable_uart_work);
    		while(k_work_delayable_busy_get(&timer_disable_uart_work) != 0 );	//wait until cancelation finnish
        }
        //enable new schedule
        k_work_schedule(&timer_disable_uart_work, K_SECONDS(WAIT_UART_DISABLE));
    }

    /* other code line to use to work */
    #define SWIN3_NODE	DT_ALIAS(swin3)
    #if !DT_NODE_HAS_STATUS(SWIN3_NODE, okay)
    #error "Unsupported board: SWIN3 devicetree alias is not defined"
    #endif
    
    
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SWIN3_NODE, gpios,0); 
    static struct gpio_callback button_cb_data;
    
    K_WORK_DEFINE(button_action_work, button_action_work_handler);
    void button_action_work_handler(struct k_work *work) {
        //do_something_because_a_button_was_pressed();
    	restart_uart();
    }
    
    static struct k_work_delayable timer_disable_uart_work;
    
    k_work_init_delayable(&timer_disable_uart_work,timer_disable_uart_work_fn);
    
    
    
    

  • Thanks for sharing the code. I am glad that you have fixed the issue. 

Related