This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

main thread no longer running

Hi,Nordic and all great guys,

I am a new developer for NRF51822, and quite unfortunately ,we have a complex application to develop. We need to run code in the main thread ,and we don`t even find examples about it in the SDK(there only have sd_app_evt_wait() at the end of main with a while(1) loop). We now meet a problem, under certain conditions ,the main thread is no longer running,while all interrupts seem work fine.

In order to pinpoint the bug, we simplified our program ,which only ran with main thread(lowest priority level), BLE interrupt(interrupt priority level 0 or level 2), APP timer with SWI0 and RTC1 interrupt(we change them to level 3), and UART prints(without interrupt).

The main flow is like this:

  1. there is a global(static) message queue , the timer will send a message to it every 500ms.

  2. there is a while(1) loop in the main thread, scanning the message queue, if valid message is in the queue, process it and loop back to the beginning of while(1).

  3. We added UART prints to show process of the message, so everytime of the loop ,there will be a lot of print output to show different status. and it also means the UART print would run very frequently because the loop time is tiny.

  4. We also have timer to check whether the while(1) loop is still running (main is not freezed),if not ,we will turn on the buzzer to indicate that, and we also can see that there is no more prints about the message queue showing up.

  5. We use softdevice_handler.c to handle the BLE connection events, we also add UART prints in the SWI2_IRQHandler() and intern_softdevice_events_execute().

Now weird thing comes, if we connect to the MCU while the main thread is scanning the message queue, producing large amount of UART print, then the UART print in SWI2_IRQHandler() will have large chance to break the print in main thread, if that happened, the main thread is no longer running ,even the BLE interrupt is finished and returned. After that we still can have BLE connection , app timer still run normally, which means all interrupts are good to trigger, but the main thread is just no longer running. if we remove all UART prints or just remove the UART prints in the BLE interrupt, this would not happen, the buzzer indicating the main thread not running is not triggered .We actually don`t know what cause this ,just can suspect the UART useage before and after the BLE interrupt may cause some kind of conflict. We are stuck here for several days ,it becomes a big problem for us since we have to use main thread to achieve our application, so any help will be appreciated. By the way ,we are using S110 V7.0, SDK V6.1. If any further information is needed or anything unclear, please also let me know. Thanx in advance.

  • I took the liberty to edit the formatting of your question as the indentation in front of each paragraph caused most of the question to be presented in verbatim with no soft line breaks etc. (This is because all posts on this forum are parsed as Markdown).

  • As long as the CPU is active (which it is as your interrupt handlers are running) the main thread will also do something, given that it has time to run. Without knowing anything about your code I would assume that one of the following things are happening:

    • Your main thread is in some unexpected state. (E.g. it could be in a eternal loop in an error handler such as the app_error_handler(), defined in components\libraries\util\app_error.c after an error code was used as input to APP_ERROR_CHECK())
    • One or more interrupt handlers are running constantly, giving no time for lower priority threads to run.

    Have you tried using a debugger to see what your code is doing when it is in the bad state?

  • HI,Einar Thorsrud , Thanks for you help , after using debugger,I think I found where the problem is ,it is all about NRF_UART0->EVENTS_TXDRDY, we have code section below: static void __uart_put(H_U8 ch) { NRF_UART0->TXD = (H_U16)ch;

    while (NRF_UART0->EVENTS_TXDRDY != 1)
    {
    	// Wait for TXD data to be sent.
    	//TEST
    	nrf_gpio_pin_set(ALARM_ENABLE_PORT);
    	
    }
    nrf_gpio_pin_clear(ALARM_ENABLE_PORT);
    //hs_tools_op()->_delay_ms(1);
    NRF_UART0->EVENTS_TXDRDY = 0;
    

    }

    If there is no interrupt or interrupt did not happened just at UART print(NOTE THAT in the interrupt handler ,there are also prints), this section worked normally, otherwise, the value of NRF_UART0->EVENTS_TXDRDY would stay at 0, then it is a dead loop. I found the cause of the problem, but I don`t know why this will happen, why the NRF_UART0->EVENTS_TXDRDY have wrong value,and after searching this forum,I know I can not change this value manually ,it is set by hardware. Can you help me with that? Thanks again for your help.

  • The TXDRDY flag is set by hardware, but must be cleared by software. Thus you should initialize it to zero when you configure UART (I assume you have done that?), and always set it to zero after the while loop, so that it is zero before you send the next byte (as you do in the code in your comment).

    Are you accessing the UART registers other places in your code, some with higher priorities? You could get problems in that case, if TXDRDY is cleared by one thread, before another that is waiting for it to be set. This is discussed in this thread.

    You could consider using the driver or the app_uart library.

  • Maybe the BLE interrupt which also calls UART prints has changed the value of TXDRDY, and disrupt the proccess of TXDRDY in the main thread. whatever ,since we confirmed the main thread is not dead, so we can solve this problem by simply adding a timeout for the __uart_put function. Now we moved to other problems of our application. Thanks a lot.

Related