nrf52 DK Bluetooth Connection Lost Due to Low Memory?

Hi,

we are using nrf52 DK and our custom mobile application. We are trying to collect 15000 sensor samples and finally we are trying to send array to mobile app via BLE. We store those samples into array called data_to_send. Array is defined as:uint8_t data_to_send[NUMBER_OF_SAMPLES_TO_COLLECT]; where NUMBER_OF_SAMPLES_TO_COLLECT is 15000.At first when CONFIG_MAIN_STACK_SIZE and CONFIG_BT_RX_STACK_SIZE in proj.conf were 4096 then we get the following error message before we are able to collect those 15000 samples.


�*** Booting Zephyr OS build 28a3fca7da5c ***0x20001f00 (BT RX)

After that we decreased the NUMBER_OF_SAMPLES_TO_COLLECT to 5000 and got the following error message:

[00:01:14.032,989] <err> os: ***** MPU FAULT *****
[00:01:14.032,989] <err> os:   Data Access Violation
[00:01:14.033,020] <err> os:   MMFAR Address: 0x200048c0
[00:01:14.033,050] <err> os: r0/a1:  0x000000c7  r1/a2:  0x00000000  r2/a3:  0x200041a0
[00:01:14.033,050] <err> os: r3/a4:  0x00000721 r12/ip:  0x0002e5c0 r14/lr:  0x000225cb
[00:01:14.033,081] <err> os:  xpsr:  0x01000000
[00:01:14.033,081] <err> os: Faulting instruction address (r15/pc): 0x000123d2
[00:01:14.033,142] <err> os: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0
[00:01:14.033,172] <err> os: Current thread: 0x20001f00 (BT RX)

Then we increased CONFIG_MAIN_STACK_SIZE and CONFIG_BT_RX_STACK_SIZE in proj.conf from 4096 to 8192.Right after when we have finished collecting 5000 samples we lose the BT connection. We get the following error message to terminal:
<err> bt_conn: not connected!
[00:01:21.406,860] <wrn> bt_hci_core: Not reporting packet for non-connected conn

Everything works just fine when we try to collect 4000 samples. Our current main stack size is 8192 and bt rx stack size is 8192. We tried to increase both to 10000 but the issue remains.

Parents
  • void execute_cooling_period(int MTU_SIZE) {
      LOG_INF("execute_cooling_period");
    
      uint8_t data_to_send[NUMBER_OF_SAMPLES_TO_COLLECT];
      uint16_t data_index = 0;
      float pwm_to_write = 0.0;
      int new_pulse = 0;
    
      long long int TIME_TO_RUN_PID_IN_NS = 5000000000;
      long long int  COOLING_TARGET_TIME_IN_NS = 40000000000;
      long long int  DELTA_TIME = COOLING_TARGET_TIME_IN_NS - TIME_TO_RUN_PID_IN_NS;
    
      float PWM_start_value = 80;
      float PWM_end_value = 0;
      float delta_PWM = (PWM_end_value - PWM_start_value) / (DELTA_TIME);
      bool write_marker = true;
      int MARKER = 1500;
    
      int32_t force_signal_in_mv = calculate_millivolt_from_adc();
      float delta_y = -110.0f;      // Test with fixed force release
      float delta_x = COOLING_TARGET_TIME_IN_MS;
      float k = delta_y / delta_x;
      float b = force_signal_in_mv;
    
      // Define time parameters.
      timing_t start_time_cooling, current_time_cooling;
      uint64_t total_cycles_cooling;
      uint64_t total_ns_cooling;
    
      timing_t start_time_pid, current_time_pid;
      uint64_t total_cycles_pid;
      uint64_t total_ns_pid;
    
      // Initialize and start the timer. Get the starting time and set that value to start_time.
      timing_init();
      timing_start();
      start_time_cooling = timing_counter_get();
    
      bool islinear = false;
    
      while (!is_cooling_done) {
    
        // Update time
        current_time_cooling = timing_counter_get();
        total_cycles_cooling = timing_cycles_get(&start_time_cooling, &current_time_cooling);
        total_ns_cooling = timing_cycles_to_ns(total_cycles_cooling); 
    
        // Calculate moving average value
        int32_t millivolts = calculate_millivolt_from_adc();
        int32_t average = moving_average(millivolts);
    
        long long int delta_time = total_ns_cooling - start_time_cooling;
    
    
        
        if (total_ns_cooling >= PID_RUN_TIME) {
          islinear = true;
          
          // Do linear decrease of the pwm.
          long long int time = delta_time - TIME_TO_RUN_PID_IN_NS;
          pwm_to_write = delta_PWM * time + PWM_start_value;
          pwm_to_write = (int)scale_PWM_output_to_nanoseconds(pwm_to_write);
    
          LOG_INF("Total ns %llu. delta_time %llu. Time %llu. PWM to write %f", total_ns_cooling, delta_time, time, pwm_to_write);
    
          if (write_marker) {
            data_to_send[data_index++] = highByte((int) MARKER);
            data_to_send[data_index++] = lowByte((int) MARKER);
    
            data_to_send[data_index++] = highByte((int) MARKER);
            data_to_send[data_index++] = lowByte((int) MARKER);
    
            data_to_send[data_index++] = highByte((int) MARKER);
            data_to_send[data_index++] = lowByte((int) MARKER);
    
            write_marker = false;
          }
        } else {
    
          float target_setpoint = k * delta_time + b;
          pid.mySetpoint = target_setpoint;
    
          // Run PID. 
          current_time_pid = timing_counter_get();
          total_cycles_pid = timing_cycles_get(&start_time_cooling, &current_time_pid);
          total_ns_pid = timing_cycles_to_ns(total_cycles_pid);
    
          if (total_ns_pid >= SAMPLING_RATE) {
            current_time_pid = 0;
            total_cycles_pid = 0;
            total_ns_pid = 0;
    
            PID_Compute(&pid);
            new_pulse = scale_PID_output_to_nanoseconds();
            pwm_to_write = new_pulse;
    
            LOG_INF("PWM to write %f, target set point %f", pwm_to_write, target_setpoint);
          }
        }
    
        // Set new PWM value based on PID calculations.
        pwm_set(pwm_dev, DEFAULT_PWM_PORT, DEFAULT_PERIOD, pwm_to_write, 0);
        
        // Store moving average value into array. 
        data_to_send[data_index++] = highByte((int) average);
        data_to_send[data_index++] = lowByte((int) average);
    
        if (data_index >= NUMBER_OF_SAMPLES_TO_COLLECT) {
          LOG_INF("Data index is out of bounds. Exit loop");
          is_cooling_done = true;
          //data_index = 0;
        }
    
        //LOG_INF("Total ns %llu. Average value %u. Index %u", total_ns_cooling, average, data_index);
        //thread_analyzer_run();
        //thread_analyzer_print();
    
        k_sleep(K_MSEC(10));
      }
    
      // Stop timer.
      timing_stop();
    
      LOG_INF("Cooling is finished. Send data.");
    
      size_t array_size = sizeof(data_to_send) / sizeof(data_to_send[0]);
      LOG_INF("Size %zu", array_size);
    
      //send_data(*data_to_send, MTU_SIZE);
    
    
      for (int i = 0; i <= NUMBER_OF_SAMPLES_TO_COLLECT; i++) {
        data_to_send[i] = 0;
      }
    
      LOG_INF("Array cleaned");
    
      // After the cooling period is finished set PWM to 0 and give data transfer notify.
      pwm_set(pwm_dev, DEFAULT_PWM_PORT, DEFAULT_PERIOD, 0, 0);
      my_lbs_send_embedded_state_notify(IDLE, 1);
    }

  • Just don't put data_to_send on the stack. Refer to a C language tutorial if you needed to know how.

  • I would try to avoid dynamic memory allocation, if at all possible. I believe it is not recommended by Nordics either. 

Reply Children
No Data
Related