This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Can't use UART_2 when merged with sample azure_iot_hub, but can use it in standalone uart sample

Hello everyone, 

I have stuck in a problem with using UART_2 on my 9160 DK. I am trying to send some data with UART when a certain event occurs on the Azure server.

I have got successful working azure_iot_hub sample, which manages to turn on/off required LEDs on my DK upon a request from a cloud server.

I also have successful data transmitting from 9160 to Arduino with UART_2 but with another sample (found some outdated UART sample on the nordic github repo and modified it). This means my wiring is fine.

Now I am trying to merge these 2 samples. So when a request from server arrives - it initiates UART communication and makes 9160 to send data to Arduino. And here is where the error appears.

My project compiles with no errors and is capable of processing the server request. But it struggles to initiate UART communication. Whenever a UART communication tries to occur, the board resets and outputs the following to the terminal:

BFAR Address: 0x50008158

I have searched for this issue and have found some similar problems, but have not found a suitable solution. 

After this output, the 9160 boots up again and works as regular until there is no attempt to use UART again. 

My setup and code fragments:

//UART function
static void uart_send(struct k_work *work)
{
	if (!open) return; 
	dk_set_led(2,1); //turn on LED for test purpose (THIS WORKS)
	char buf[] = {'o','\0'};
	for (int i = 0; i < strlen(buf); i++) 
	{
		uart_poll_out(uart_dev, buf[i]); //this is the place where everything stucks
	}
}

//Have created a separate task for UART communication not to mess up with the Azure IoT Hub Direct Method handler
static void work_init(void)
{
	k_work_init(&method_data.work, direct_method_handler);
	k_work_init(&uart_data.work, uart_send); //UART communication thread
	k_work_init(&twin_report_work, twin_report_work_fn);
	k_work_init_delayable(&send_event_work, send_event);
	k_work_queue_start(&application_work_q, application_stack_area,
		       K_THREAD_STACK_SIZEOF(application_stack_area),
		       K_HIGHEST_APPLICATION_THREAD_PRIO, NULL);
}

void main(void)
{
	const struct device *uart_dev = device_get_binding("UART_2");
	if (!uart_dev)
	{
		printk("Not connected to UART_2");
		return;
	}
    
    ... azure_iot_hub related code ...
}

Device Tree Overlay file contents:

SPM config file fragment ( path -  azure_iot_hub\build\spm\zephyr\.config  )

prj.conf  file fragment:

...
CONFIG_UART_INTERRUPT_DRIVEN=y
...
CONFIG_SERIAL=y
CONFIG_TRUSTED_EXECUTION_NONSECURE=y
...

Does anyone have any idea of what can be wrong with my project? 

Max

  • Then I would assume the problem is related to the work thread, and not the UART.

    Maybe your program is not able to access the UART device from within the work thread, have you tried checking if the device struct is defined inside your work function?

    Have you tried using uart_tx instead of uart_poll_out to see if you get the same result?

    Have you tried calling uart_poll_out directly in the Azure event handler, instead of going through the workqueue, to see if you still get the crash?

    -Einar

  • Einar, it worked!

    Maybe your program is not able to access the UART device from within the work thread, have you tried checking if the device struct is defined inside your work function?

    This was the issue.  I have made device_get_binding("UART_2") inside of main() function, but it was not visible inside of work thread, although the compiler did not complain about that.

    I modified my code in the following way (compare it with the original code posted in the 1st message):

    //UART function
    static void uart_send(struct k_work *work)
    {
    	if (!open) return; 
    
        //THE FOLLOWING LINE SOLVED THE ISSUE
    	const struct device *dev = device_get_binding("UART_2");
    	
    	dk_set_led(2,1); //turn on LED for test purpose
    	char buf[] = "o\0";
    	for (uint8_t i = 0; i < strlen(buf); i++) 
    	{
    		uart_poll_out(dev, buf[i]);
    	}
    }
    
    

    So now my main() function does not contain UART device binding.

    As well as work_init() function turned out to be okay.

    Thank you for your help!

  • Glad to see that you found the cause of your issue!

    I think binding your device each time you call the uart send function seems like a pretty messy fix though.

    It should be possible to bind your device once at startup with a larger scope than the main function.

    You could try declaring your struct before the main function like this:

    static const struct device *dev;

    and then binding it to UART 2 in the main function:

    dev = device_get_binding("UART_2");

    I believe this could also solve your issue.

    -Einar

Related