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

Scheduler - Serial, Timer ( interrupt priority)- help needed

Hi, I have a simple application with logic is:
- every 3 or 20 seconds send some data via modem (based on AT commands),
- sending and receiving data via serial port to and from the modem,

Application:
I)
When we take MCU ON the application each 3s is asking about the range (till range == true). After then the timer is switching TIME_INTERVAL from 3s to for example each 20s
II)
If we have a range app. is sending in each timer interrupt some short data.

Problem description:
I'm using two interrupt handlers, first is from the timer and second is from a serial port. When I wrote the code application was hang up each time during sending the data. By the trial-and-error method, I found that if I will change in NRF_SERIAL_DRV_UART_CONFIG_DEF()
UART_DEFAULT_CONFIG_IRQ_PRIORITY) to 1
All start works fine.
I spoke with my friend and he tells me that I should use scheduler and maybe then such situation shouldn't have a place.
I put the code from nrf_serial_evt_handler() to scheduler but the problem is the same:
if UART_DEFAULT_CONFIG_IRQ_PRIORITY then an application is hanging but when I change the prior to 1 start works fine.

Question:
How it should look like properly of using the scheduler in my case? and what I'm doing wrong?

Code parts:

int main(void)
{
	ret_code_t ret;
	/*Initialization, peripheral configuration.*/
	board_system_init();
	/*Application part*/
	bc95_rst();
	application_timers_start();
	/*Say hello*/
    ret = nrf_serial_write(&serial_uart, "Sensor is ready.\r\n", strlen("NBIoT sensor ready.\r\n"), NULL, NRF_SERIAL_MAX_TIMEOUT);
    APP_ERROR_CHECK(ret);

    while (true)
    {
    	app_sched_execute();
    	CheckBuffer();
    }
}

void nrf_serial_evt_handler(struct nrf_serial_s const * p_serial, nrf_serial_event_t event){
	if(event == NRF_SERIAL_EVENT_RX_DATA){
		/*if rx any char - put it to array*/
		app_sched_event_put(NULL, 0, serial_scheduler_event_hanler);
	}else if (event == NRF_SERIAL_EVENT_TX_DONE) {
		/*invert led if something was send via serial to modem*/
		bsp_board_led_invert(3);
	}
}

void app_timer_timeout_handler(void * p_context){

	ret_code_t err_code, ret;

	app_timer_pause();

	if (rangeNB == false) {
		rangeReady();
	}else if (rangeNB == true && lng_int_set == false) {
		/*If we have range we can change time interval*/
		app_timer_stop(m_app_timer_id);
		err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL_20S , NULL);
		APP_ERROR_CHECK(err_code);
		app_timer_pause();
		lng_int_set = true;
		ret = nrf_serial_write(&serial_uart, "changing time interval to 20s\n", strlen("changing time interval to 20s\n"), NULL, 0);
		APP_ERROR_CHECK(ret);
		bsp_board_led_on(1);																		/*Device have a range*/
	}else if (rangeNB == true && lng_int_set == true) {
		/*
		 * Make measurment and send it -
		 * - not elegant construction because we are in interrupt handler (try move it to scheduler)
		 * */
	    char tx_mesg_open[] = "AT+NSOCR=DGRAM,17,5000,0\r\n";
    	char tx_mesg_udp[] = "AT+NSOST=0,000.000.000.000,5000,4,64757061\r\n";
	    char tx_mesg_close[] = "AT+NSOCL=0\r\n";
    	
	    (void)nrf_serial_write(&serial_uart, tx_mesg_open, strlen(tx_mesg_open), NULL, 0);
	    nrf_delay_ms(50);

	    (void)nrf_serial_write(&serial_uart, tx_mesg_udp, strlen(tx_mesg_udp), NULL, 0);
	    nrf_delay_ms(50);

	    (void)nrf_serial_write(&serial_uart, tx_mesg_close, strlen(tx_mesg_close), NULL, 0);
	    nrf_delay_ms(50);
	}

	app_timer_resume();

}

Logs from serial port:

Board to modem> [13:41:54:219] Sensor is ready.␍␊

Board to modem> [13:42:00:206] AT+CSQ␍␊

   Modem to board> [13:42:00:228] +CSQ:21,99␍␊

   Modem to board> [13:42:00:228] OK␍␊

Board to modem> [13:42:03:229] changing time interval to 20s␊

Board to modem> [13:42:23:199]

//After print "A" mcu  hangs

Parents Reply Children
  • No worries. Glad to hear that it works now. I forgot to mention earlier that interrupt priority 1 is reserved for the softdevice. 

  • Hi Vidar,

        regarding to Serial/UART port I have one more question about it:

    Problem description:

    Suppose that I want to send via nrf_serial_write() command some string.

    As next step I want to send second string - but I need to be sure that first was sent properly

    I know that we have event from serial NRF_SERIAL_EVENT_TX_DONE

    Question I:

    How to correctly wait till first string will be sent ?

    nrf_serial_write(&serial_uart, "long_string1\r\n", strlen("long_string1\r\n"), NULL,0);

    //how to wait here ? while(NRF_SERIAL_EVENT_TX_DONE) ? <- don't looks like good

    nrf_serial_write(&serial_uart, "long_string2\r\n", strlen("long_string2\r\n"), NULL,0);

    Question II:

    In what situation should we use (void)nrf_serial_flush(&serial_uart, 0); function ?

  • Hi,

    1. The write operations should become queued so it don't think it's necessary to add a wait between. Or is that not working in your case?

    2. It can be used in situations where you need to "pause" the application until the tx queue is empty. E.g., you want to make sure some data is transmitted before a reset.

Related