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

Parents
  • Hello!

    Since you have the parts working separately, I believe the best approach here would be to compare the configurations of your two projects very thoroughly, to see if you can figure out what is causing the different behavior. Maybe there is something missing in the prj.conf file, or maybe you've missed a part of the uart initialization?

    In your uart application, do you also build for nrf9169_ns?

    Best regards,

    Einar

  • Hello Einar,

    Thank you for your response! Yes, I build it for nrf9160dk_nrf9160_ns. 

    I have checked both project configurations and have concluded that the problem might be somewhere else. I then tried a different approach: I have called  the UART TX function inside of main() function, so now it successfully sends data through UART upon system startup.

    This means that the issue is Zephyr  specific and I should find the way to manage multitasking to work without conflicts.

  • oh, so uart_poll_out() works when you call it from main, but not when you call it from your workqueue thread?

  • 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

Reply
  • 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

Children
No Data
Related