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

Sending SMS is blocking program execution in nRF9160

Hi,

I'm using commands below to send SMS message in my application. SMS sending is working fine, but some reason during the AT+CMGS command program execution

Is blocked e.g. all the LEDs are stopped. CNMI mode is set to 3 so I just wondering is the modem waiting some Ack from the network? How to send SMS without blocking the program execution?

AT+CFUN=1

AT+CNUM
AT+CEREG?
AT+CNMI=3,2,0,1
AT+CMGS

I'm using the at command interface to send commands to modem.

Best Regards

Juha

Parents
  • Hi,

     

     

    CNMI mode is set to 3 so I just wondering is the modem waiting some Ack from the network? How to send SMS without blocking the program execution?

    If I understand correct, you are able to send SMS, but the AT command +CMGS hangs after sending one SMS.

    How are you implementing this in firmware?

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Yes, SMS sending is working. In the main program I will get trigger from my sensor driver and then I submit the SMS work to handle SMS sending.

    My trigger handler:

    static void trigger_handler(struct device *dev, struct sensor_trigger *trigger)
    {
          ARG_UNUSED(dev);
          switch ((int)trigger->type) {
          case SENSOR_BP3901_NOTIFICATION:
                ui_led_set_state(1, 1);
                if(gps_control_is_active()) {
                    gps_control_disable();
                }
                
                k_delayed_work_submit(&sms_work, 250);
                break;
          case SENSOR_BP3901_DRDY_READY:
                if(gps_control_is_active()) {
                    gps_control_disable();
                }
                k_delayed_work_submit(&data_work, K_NO_WAIT);
                break;
          default:
                printk("Unknown trigger event %d\r\n", trigger->type);
                break;
          }      
    }

    Work handler function:

    static void BP3901_sms_fn(struct k_work *work) {
    
        int ret;
        char sms_msg[PDU_MAX_LEN];
    
        networtk_time_str = get_network_time();
        gps_cloud_data.tag = sys_rand32_get();
    
        ret = create_sms_indication_message(sms_msg, PDU_MAX_LEN);
        if(ret != 0) {
            printk("SMS encode err=%d\n", ret);
            return;
        }
    
        sms_send(sms_msg);
    
        if(!gps_control_is_active()) {
            gps_control_enable();
        }
    }

    SMS sending function:

    static int sms_send(const char *msg)
    {
        int err;
        enum at_cmd_state state;
        static char at_resp[128];
        
        err = at_cmd_write(AT_CFUN, at_resp, AT_MAX_CMD_LEN, &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", AT_CFUN, err);
        }
    
        err = at_cmd_write(AT_CNUM, at_resp, AT_MAX_CMD_LEN, &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", AT_CNUM, err);                
        }
    
        err = at_cmd_write(AT_CEREG, at_resp, AT_MAX_CMD_LEN, &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", AT_CEREG, err);                
        }
      
        err = at_cmd_write(AT_CNMI, at_resp, AT_MAX_CMD_LEN, &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", AT_CNMI, err);        
        }
    
        /*err = at_cmd_write_with_callback(msg,
                                         sms_cmd_handler_fn,
    				     &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", "AT+CMGS", err);
        }   
                                      */
    
        err = at_cmd_write(msg, at_resp, AT_MAX_CMD_LEN, &state);
        if (err < 0) {
            printk("Could not send AT command to modem: %s %d\n\r", "AT+CMGS", err);
        }
    
        return 0;
    }
    

    Part of creating the AT+CMGS  message:

    char sms_message_str[PDU_MAX_LEN];
    
    n = sprintf(&sms_message_str[0],"%s", "AT+CMGS=");    
    n += sprintf(&sms_message_str[n],"%d%s", (pdu_len - (pdu[0]+1)) ,"\r");    
    for(int i = 0; i < pdu_len; i++)
         n +=sprintf(&sms_message_str[n], "%.2x", pdu[i]);    
    n += sprintf(&sms_message_str[n],"%s", "\x1A");

    Best Regards

    Juha

  • Hi Juha,

     

    Are you starting from a powered down state? If yes, then you should let the modem be able to successfully connect to the network before continuing with the rest of the sequence.

    See an example of this in the mqtt_simple: https://github.com/NordicPlayground/fw-nrfconnect-nrf/blob/master/samples/nrf9160/mqtt_simple/src/main.c#L357

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Here is my main loop code:

    void main(void)
    {
            
        
        #if defined(CONFIG_USE_UI_MODULE)
                ui_init(ui_evt_handler);
        #endif
    
        /*Put simulated data to GPS buffer,
          when the postion is found it will be replaced with real location data*/
        gps_cloud_data.data.buf = default_gps_data;
        gps_cloud_data.data.len = strlen(default_gps_data);
        gps_cloud_data.tag += 1;
    
        if (gps_cloud_data.tag == 0) {
            gps_cloud_data.tag = 0x1;
        }
    
        work_init();
        bp3901_nvs_init();
        bp3901_uart_init();
        modem_configure(); 
    
        while (true) {
            k_sleep(K_MSEC(5));
            //k_cpu_idle();
        }
    }

    Modem configure function:

    static void modem_configure(void)
    {
    #if defined(CONFIG_BSD_LIBRARY)
        if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
            /* Do nothing, modem is already turned on
             * and connected.
             */
        } else {
            int err;
    
            printk("Connecting to LTE network. ");
            printk("This may take several minutes.\n");
            ui_led_set_pattern(UI_LTE_CONNECTING);
    
            err = lte_lc_init_and_connect();
            if (err) {
                    printk("LTE link could not be established.\n");
                    error_handler(ERROR_LTE_LC, err);
            }
    
            printk("Connected to LTE network\n");
            lte_connected = true;
            ui_led_set_pattern(UI_LTE_CONNECTED);
            sensors_start();
        }
    #endif
    }

    Best Regards

    Juha

Reply
  • Hi Håkon,

    Here is my main loop code:

    void main(void)
    {
            
        
        #if defined(CONFIG_USE_UI_MODULE)
                ui_init(ui_evt_handler);
        #endif
    
        /*Put simulated data to GPS buffer,
          when the postion is found it will be replaced with real location data*/
        gps_cloud_data.data.buf = default_gps_data;
        gps_cloud_data.data.len = strlen(default_gps_data);
        gps_cloud_data.tag += 1;
    
        if (gps_cloud_data.tag == 0) {
            gps_cloud_data.tag = 0x1;
        }
    
        work_init();
        bp3901_nvs_init();
        bp3901_uart_init();
        modem_configure(); 
    
        while (true) {
            k_sleep(K_MSEC(5));
            //k_cpu_idle();
        }
    }

    Modem configure function:

    static void modem_configure(void)
    {
    #if defined(CONFIG_BSD_LIBRARY)
        if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
            /* Do nothing, modem is already turned on
             * and connected.
             */
        } else {
            int err;
    
            printk("Connecting to LTE network. ");
            printk("This may take several minutes.\n");
            ui_led_set_pattern(UI_LTE_CONNECTING);
    
            err = lte_lc_init_and_connect();
            if (err) {
                    printk("LTE link could not be established.\n");
                    error_handler(ERROR_LTE_LC, err);
            }
    
            printk("Connected to LTE network\n");
            lte_connected = true;
            ui_led_set_pattern(UI_LTE_CONNECTED);
            sensors_start();
        }
    #endif
    }

    Best Regards

    Juha

Children
  • If you are not putting the modem in flight mode, or in offline mode, then there's no need to send the AT+CFUN command. If you are; then you need to wait for the link to be established again.

    Q1: How is the device stuck? Do you get a fault or an assert? What is the log output?

    Q2: Have you tried the exact same in at_client, to see how it behaves there?

    Q3: Have you tried sending a static SMS, to see if the firmware hangs in the snprintf handling?

     

    Kind regards,

    Håkon

Related