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

FIFO uart stops sending when inside app_error_handler (flush doesnt do it)

i'm using uart for debugging, works fine and dandy except when in app_error_handler. There only the first character is being printed before we go into an infinite loop. Inside the error handler, i2c and spi work fine, just not uart... odd.

void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
    printf("%lu %s:%lu  ", error_code, (const char*)p_file_name, line_num);
    app_uart_flush();

    for (;;) {
        nrf_delay_ms(500);
        LEDS_OFF(BSP_LED_1_MASK);
        nrf_delay_ms(500);
        LEDS_ON(BSP_LED_1_MASK);
    }
}

I suspect that fifo mode needs timers since printing only one char is exactly the behaviour when i ommit APP_TIMER_INIT. But from my perspective app_error_handler is just a regular function on the stack, and i have not disabled timers anywhere.

Parents
  • I know this is an old thread but has anyone solved this issue? I am using UART for debugging with printf() and it is working fine in most of the code. If I do a while(ble_nus_string_send(...)!=NRF_SUCCESS), after my printf, the terminal shows only one character and program locks. Can anyone help?  

  • Hi

    The issue where you can't use an interrupt based driver from a high priority interrupt is not changed. The only solution to this issue is to use a non interrupt based driver. 

    Where are you calling the code from?
    In general calling functions like ble_nus_string_send in a loop is a bit risky, especially if you do it in an interrupt (like an event handler). It is wiser to set a flag if the BLE buffers are full, and try to send the packet again once the TX complete event occurs. 

    Best regards
    Torbjørn

  • Thanks for the help ovrebekk. I am not using printf in the interrupt. I am simply calling ble_nus_string_send after printf. Here's some example code:

    static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)
    {
    	printf("%s\r\n", p_data);
    
    if (p_data[0] == '1'){
    run_motor(0, 5000);
    }
    
    void run_motor(int direction, int nosteps){
    	printf("%s", "got here\r\n");
        unsigned char string_tosend[]= {"Motor Running"};
    // remove the following line and printf to terminal sends all charators
    // with following line in, the first charactor is sent (from nus_data_handler)
    // and the program stops
    	while(ble_nus_string_send(&m_nus, string_tosend, strlen((char*)string_tosend)) != NRF_SUCCESS);  
        motor_steps = nosteps;	
        current_steps = nosteps;
        motor_direction = direction;
        uint32_t err_code;
        err_code = app_timer_start(motor_step_timer_id, APP_TIMER_TICKS(MOTOR_TICKS, APP2_TIMER_PRESCALER), NULL);      APP_ERROR_CHECK(err_code);
    	err_code = app_timer_start(motor_run_timer_id , APP_TIMER_TICKS(nosteps, APP2_TIMER_PRESCALER), NULL);
        APP_ERROR_CHECK(err_code);
    }
    

    ble_nus_string_send is clobbering the printf for some reason. Could I check and wait for printf to send all characters before calling it?

Reply
  • Thanks for the help ovrebekk. I am not using printf in the interrupt. I am simply calling ble_nus_string_send after printf. Here's some example code:

    static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)
    {
    	printf("%s\r\n", p_data);
    
    if (p_data[0] == '1'){
    run_motor(0, 5000);
    }
    
    void run_motor(int direction, int nosteps){
    	printf("%s", "got here\r\n");
        unsigned char string_tosend[]= {"Motor Running"};
    // remove the following line and printf to terminal sends all charators
    // with following line in, the first charactor is sent (from nus_data_handler)
    // and the program stops
    	while(ble_nus_string_send(&m_nus, string_tosend, strlen((char*)string_tosend)) != NRF_SUCCESS);  
        motor_steps = nosteps;	
        current_steps = nosteps;
        motor_direction = direction;
        uint32_t err_code;
        err_code = app_timer_start(motor_step_timer_id, APP_TIMER_TICKS(MOTOR_TICKS, APP2_TIMER_PRESCALER), NULL);      APP_ERROR_CHECK(err_code);
    	err_code = app_timer_start(motor_run_timer_id , APP_TIMER_TICKS(nosteps, APP2_TIMER_PRESCALER), NULL);
        APP_ERROR_CHECK(err_code);
    }
    

    ble_nus_string_send is clobbering the printf for some reason. Could I check and wait for printf to send all characters before calling it?

Children
  • Hi

    Unless the SoftDevice is set up to use the app_scheduler module the nus_data_handler(..) will run in interrupt context. 

    Could you try to run the code from main context instead and see if it solves the issue?

    To test this simply create a flag that you set inside the nus_data_handler, and check the status of this flag in the main loop:

    static volatile bool update_motor = false;

    static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length)
    {
      printf("%s\r\n", p_data);

      if (p_data[0] == '1')
      {
        update_motor = true;
      }
    }

    // In main loop...

    if(update_motor)
    {
      update_motor = false;
      run_motor(0, 5000);
    }

    Best regards
    Torbjørn

Related