This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

In my Broadcaster Application the stack pointer for stack 'XdataStack' runs outside the stack range

Hello,

This time I try to program a broadcaster that sends temperature and humidity.
So I used the sample project SimpleBLEBroadcaster and replaced the files simpleBLEBroadcaster.c and simpleBLEBroadcaster.h with my own files MesUnit.c/.h this files I added to this Post.

My own task includes th following events:

- SYS_EVENT_MSG:

Just deallocates a received message

- START_DEVICE :

This Event is set by the init function of my task

Calls the function GAPRole_StartDevice for setting the callback function that is called,
when the profile state is changing (just used for switch an LED on and of)

Sets the event UPDATE_TEMP_RH

- UPDATE_TEMP_RH:

reads the temperature from an external sensor via I2C

updates the advertising data

sets a timer that will set the START_ADVERT event after 2s

- START_ADVERT:

starts the advertising 

sets a timer that will set the STOP_ADVERT event after 0,5s

- STOP_ADVERT:

stops the advertising 

sets a timer that will set the UPDATE_TEMP_RHevent after 4,2s

So a endless loop is created: UPDATE_TEMP_RH --> START_ADVERT -->  STOP_ADVERT --> UPDATE_TEMP_RH
Sometimes the advertising starts and stops a view times before the stack pointer runs outside the stack sometime it only stats once.

I don't know why. So can anybody help me please?MeasUnit.h

MeasUnit.c
#include "MeasUnit.h"
#include "att.h"
#include "gap.h"
#include "broadcaster.h"

#include "hal_i2c.h"

#define EXTERNAL_VOLTAGE_SUPPLY

// Nummer des MeasUnit-Task
uint8 MeasUnit_ProcessEvent_TaskID;
uint8 EndlessTask_TaskID;

gapAdvertisingParams_t params;

// Zeit bis die temperatur und Luftfeuchtigkeit upgedated werden
#define SLEEP_BETWEEN_MEASURING 6000

// What is the advertising interval when device is discoverable (units of 625us, 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL          480

//Callbackfunction that is called when Gap Role has changed
static void gapRoleChanged( gaprole_States_t newState );

static gapRolesCBs_t GapCallBacks =
{
  gapRoleChanged,       // Profile State Change Callbacks
  NULL           // When a valid RSSI is read from controller (not used by application)
};

uint8 myBleAddress[] = {0x00, 0x00, 0x19, 0x86, 0x22, 0x07};
uint8 timerset=0;
uint8 advertising_enable= TRUE;
bStatus_t bLED=0;


// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] = 
{ 
  // Flags; this sets the device to use limited discoverable
  // mode (advertises for 30 seconds at a time) instead of general
  // discoverable mode (advertises indefinitely)
  0x02,   // length of this data
  GAP_ADTYPE_FLAGS,
  GAP_ADTYPE_FLAGS_GENERAL+GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
  
   0x09,   // length of this data
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  0x54,   // 'T'
  0x65,   // 'e'
  0x6d,   //  'm'
  0x70,   //  'p'
  0x73,   // 's'
  0x65,   // 'e'
  0x6e,   // 'n'
  0x73,   // 's'
  

  // Tx power level
  0x02,   // length of this data
  GAP_ADTYPE_POWER_LEVEL,
  0,       // 0dBm  

  // three-byte broadcast of the data "1 2 3"
  0x08,   // length of this data including the data type byte
  GAP_ADTYPE_MANUFACTURER_SPECIFIC,      // manufacturer specific advertisement data type
  NT_COMPANY_ID,       // Company ID
  0x01,                // Node ID
  0x00,                // Temp LSB
  0x00,// Temp MSB
  0x00,// Luftf LSB
  0x00,// Luftf MSB
};


/*********************************************************************
 * @fn      SHT21_config
 *
 * @brief   This function is called for configurate the SHT21/25.
 *          SHT21/25 will be configurated that he reads Temperature 
 *          with 12 Bit and humidity with 8 Bit resolution.
 *
 * @param   No parameter
 * @return  No return
 */
void SHT21_config(void)
{
          uint8 w_Reg[3];
          uint8 r_Reg[3];
         
          do
          {
               P1 &= 0xBF;
               // Definiere den Inhalt f�r das Register welches per I2C gesendet wird
               //  ( Die Adresse des SHT21 wurde in der HalDriverInit Funktion definiert
            
               w_Reg[0] = write_userreg;               // Befehl zum schreiben in das User Register
               w_Reg[1] = 0x01;                        // Zu schreibender Inhalt f�r das Userregister (8 Bit RH and 12 Bit Temp)   
               w_Reg[2] = read_userreg;                // Befehl auslesen des User Registers    
               
               HalI2CWrite(3,w_Reg);                   // Sende die Daten des write Registers
                
               r_Reg[0] = 0;                           // Setze das read Register auf 0
               r_Reg[1] = 0;                           // Setze das read Register auf 0
               r_Reg[2] = 0;                           // Setze das read Register auf 0
                
               HalI2CRead(1,r_Reg);                    // Empfange den Inhalt des Userregisters des SHT21 
               
                
          } while(r_Reg[0] != 0x01);                   // Kontrolliere ob das Userregister des SHT21 korrekt ist, ...
                                                       //    ... wenn nicht schreibe ihn erneut
          if (HalI2CReady2Sleep())
          {
            HalI2CEnterSleep();
          }   
          return;
}



/*********************************************************************
 * @fn      PORT_config
 *
 * @brief   This function configurates the Controllerprts:
 *             P2.0 will be configurated and aktivated as an Interruptpin
 *             P0.7 will be defined as an output for the LED
 *             P1.2 will be defined as an output for enabling the voltage divider before the A/D-converter
 *
 * @param   No parameter
 * @return  No return
 */
void PORT_config(void)
{   
  // Ge�ndert 29.08.2012
  //************************
  //* Port 2 konfigurieren *
  //************************
  //IRCON2 &= 0xFE;        // Interruptflag l�schen 
  P2DIR &= 0xFF;         
//  P2DIR &= 0xFE;         // P2.0 Als Eingang
  //  PICTL |= 0x08;         // P2ICON = 1 -> P2.0 - P2.3 Interrupts with falling edge
  //IEN0  |= 0x80;         // Global enable of the Interrupts
  //P2IEN |= 0x01;         // Enable Port2.0 Interrupt
  //P2IEN &= 0x01;         //
  //IEN2  |= 0x02;         // Enable the Port 2 Interrupt
  
  //***********************
  // Port 0 konfigurieren *
  //***********************
  P0DIR |= 0x80;         // P0.7 als Ausgang (LED)
  P0 |= OWN_LED;         // LED anfangs ausschalten    //P0    |= 0x80;         // LED zum Anfang aus (Low-Aktiv)

  P0DIR &= 0xFE;         // Configuate P0.0 as an input
  APCFG |= 0x01;         // Configurate the P0.0 Pin as an analog input

  P0DIR |= 0x7C;         // P0.1 - P0.6 als Ausg�nge
  P0    &= 0x81;         // P0.1 - P0.6 auf LOW
  
  //************************  
  //* Port 1 konfigurieren *
  //************************ 
  P1DIR |= 0x40;         // P1.6 als Ausgang (Spannung an den SHT21 anlegen)
  P1    |= 0x40;         // Spannung noch nicht an den SHT21 anlegen (Low-Aktiv)
  
  P1DIR |= 0x04;         // P1.2 als Ausgang (Freischalten AD-Wandlung)
  P1    |= 0x04;         // Zu beginn nicht frei geschalten (Low-Aktiv)
  
  P1DIR |= 0xB9;         // P1.0, P1.3, P1.4, P1.5 und P1.7 als Ausg�nge       1011 1001 = 0xB9
  P1    |= 0x46;         // P1.0, P1.3, P1.4, P1.5 und P1.7 auf LOW            ~1011 1001 = 0100 0110 = 0x46

  
  
  return;
}


/*********************************************************************
 * @fn      MeasUnit_Init 
 *
 * @brief  Initializes the MeasUnit Task
 *
 * @param   uint8 task_id, uint16 events
 * @return  uint16 events 
 */

void MeasUnit_Init( uint8 task_id )
{
  MeasUnit_ProcessEvent_TaskID = task_id;
  PORT_config();
  SHT21_config();
        
  uint16 gapRole_AdvertOffTime = 200;          // Advert off after 100ms
  uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND;   // use non-connectable advertisements
  
  GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );
  GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
  GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );

  uint16 advInt = DEFAULT_ADVERTISING_INTERVAL;

  GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt );
  GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt );
  GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt );
  GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt );
  
  osal_set_event(MeasUnit_ProcessEvent_TaskID, START_DEVICE );
  
  
  params.eventType                = GAP_ADTYPE_ADV_NONCONN_IND;   //!< Advertise Event Type: @ref GAP_ADVERTISEMENT_TYPE_DEFINES
  params.initiatorAddrType        = ADDRTYPE_PUBLIC;              //!< Initiator's address type: @ref GAP_ADDR_TYPE_DEFINES
  //params.initiatorAddr            ={0,0,0,1,2,3};                 //!< Initiator's addr - used only with connectable directed eventType (ADV_EVTTYPE_CONNECTABLE_DIRECTED).
  params.channelMap               = GAP_ADVCHAN_ALL;              //!< Channel Map: Bit mask @ref GAP_ADVCHAN_DEFINES
  params.filterPolicy             = 0;                            //!< Filer Policy: @ref GAP_FILTER_POLICY_DEFINES. Ignored when directed advertising is used.
}

/*********************************************************************
 * @fn      MeasUnit_ProcessEvent 
 *
 * @brief  
 *
 * @param   uint8 task_id, uint16 events
 * @return  uint16 events 
 */
uint16 MeasUnit_ProcessEvent ( uint8 task_id, uint16 events )
{
  uint8    w_Reg[3];
  uint8    r_Reg[3];
  uint32   Temperatur_int;
  uint16   Luftfeuchte_int;
  uint8*   msgPtr;
          
  // Verschiedene Events Handeln
    if ( events & START_DEVICE )
  {
    // Start the Device
    VOID GAPRole_StartDevice( &GapCallBacks );
    
    osal_set_event(task_id, UPDATE_TEMP_RH);
    return (events ^ START_DEVICE );
  }
  
  
  if ( events & SYS_EVENT_MSG )
  {
    msgPtr = osal_msg_receive(Hal_TaskID);

    while (msgPtr)
    {
      /* Do something here - for now, just deallocate the msg and move on */

      /* De-allocate */
      osal_msg_deallocate( msgPtr );
      /* Next */
      msgPtr = osal_msg_receive( Hal_TaskID );
    }
    return (events ^ SYS_EVENT_MSG);
  }
  
  
  if (events & UPDATE_TEMP_RH)                   // Bereit zum messen
  {
    HalI2CExitSleep();                           

    /*****************************************************************************************************/
    /*** Temperatur einlesen *****************************************************************************/
    /*****************************************************************************************************/            
    
    w_Reg[0] = trig_t_h;                         // Lade das Triggerkommando zum Messen der Temperatur
    HalI2CWrite(1,w_Reg);                        // Sende das Triggerkommando zum Messen der Temperatur
    HalI2CRead(3,r_Reg);                         // Lese die Temperaturantwort in das read Register
    Temperatur_int    = ((r_Reg[0]*256)+(r_Reg[1]&0xF0)); 

    /* Urspr�ngliche Berechnung:
    Temperatur_float  = (float)Temperatur_int;
    Temperatur_float *= 175.720;
    Temperatur_float /= 65536.000;
    Temperatur_float -= 46.850;
    */

    //Neu umgeschriebene Berechnung:
    // X * 175720  =    X * (8 * 21965)
    Temperatur_int *= 21965;

    // Temperatur_int << 3;            // *8
    // Temperatur_int >> 16;           // /65536

    Temperatur_int >>= 13;             // 8/65536 = 1/8192
    Temperatur_int -= 46850;           // Temperatur in m�C
    
    Temperatur_int = Temperatur_int/1000; // Temp in �C
                                   
               

    /*** Luftfeuchtigkeit einlesen ***********************************************************************/
               
    w_Reg[0] = trig_rh_h;                             // Lade das Triggerkommando zum Messen der Luftfeuchtigkeit           
    HalI2CWrite(1,w_Reg);                             // Sende das Triggerkommando zum Messen der Temperatur
    HalI2CRead(3,r_Reg);                              // Lese die Luftfeuchteaturantwort in das read Register
    
    Luftfeuchte_int = r_Reg[0];

    /* Urspr�ngliche Berechnung:
    Luftfeuchte_int = ((125*(r_Reg[0]))/256);      // Umwandeln des Ergebnisses der Luftfeuchtigkeitsmessung
    Luftfeuchte_int = *Luftfeuchte_int-6; */
    
    //Neu umgeschriebene Berechnung:

    Luftfeuchte_int =  125*r_Reg[0];
    Luftfeuchte_int >>= 8;                       //   /256
    Luftfeuchte_int -= 6;                       // Luftfeuchte in %
                    
              
    if (HalI2CReady2Sleep())
    {HalI2CEnterSleep();}
    
    // Update the advertising data
    advertData[sizeof(advertData)-4] = Temperatur_int % 256; // Low Byte
    advertData[sizeof(advertData)-3] = Temperatur_int >> 8; // High Byte
    advertData[sizeof(advertData)-2] = Luftfeuchte_int % 256; // Low Byte LF
    advertData[sizeof(advertData)-1] = 0;        // High Byte Lf
         
//    bStatus_t stat = GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );

    bStatus_t stat = GAP_UpdateAdvertisingData( task_id, TRUE, sizeof(advertData),advertData );
    while (stat != SUCCESS)
    {
      stat = stat;
    }      

    timerset =  osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,START_ADVERT,2000);//    
    while (timerset != SUCCESS)
    {
      timerset = timerset;
    }
    
    return (events ^ UPDATE_TEMP_RH);// Reset READY_FOR_MEASURE Bit
  }    
  
  
  if (events & START_ADVERT)
  {  
    //bStatus_t stat_discoverable = GAP_MakeDiscoverable( task_id, &params );
    
    advertising_enable = TRUE;
    GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advertising_enable );
     
    timerset =  osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,STOP_ADVERT,500);//   
    while (timerset != SUCCESS)
    {
      timerset = timerset;
    }
    
    return (events ^ START_ADVERT);
  }
    
  
  if (events & STOP_ADVERT)
  {  
    uint8 gapRole_AdvEnabled;
    GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &gapRole_AdvEnabled);
    if (gapRole_AdvEnabled == TRUE)
    {
      //bStatus_t stat_endiscoverable = GAP_EndDiscoverable(task_id);
      //while (stat_endiscoverable != SUCCESS)
      //{ stat_endiscoverable = stat_endiscoverable;}
      
      advertising_enable = FALSE;
      GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advertising_enable );
    }
    
    timerset =  osal_start_timerEx(MeasUnit_ProcessEvent_TaskID,UPDATE_TEMP_RH,4200);//SLEEP_BETWEEN_MEASURING); 
    while (timerset != SUCCESS)
    {
      timerset = timerset;
    }
    return (events ^ STOP_ADVERT);
  }
  
  
  while (1) //Should never be reached
  {;}

return (events);
}


static void gapRoleChanged( gaprole_States_t newState )
{
    P0 |= OWN_LED;              // schalte LED aus (Low aktiv)       

        
  switch ( newState )
  {
    case GAPROLE_STARTED:
      {    
        uint8 ownAddress[B_ADDR_LEN];
        GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);  
      }
      break;
      
    case GAPROLE_ADVERTISING:
      {     
        P0 &= ~(OWN_LED);     // Schalte die LED ein
      }
      break;

    case GAPROLE_WAITING:
      {        
      }
      break;          

    case GAPROLE_ERROR:
      {          
        while(1); //For debugging
      }
      break;      
      
    default:
      {  
        while(1); //For debugging
      }        
      break; 
  }
}


void EndlessTask_Init( uint8 task_id )
{
  EndlessTask_TaskID = task_id;
  osal_set_event(task_id,0x01);
  return;
}

uint16 EndlessTask_ProcessEvent ( uint8 task_id, uint16 events )
{
  return events;
}





/***********************************************************************************************/
/** P2 Interrupt Handling **********************************************************************/
/***********************************************************************************************/


/*********************************************************************
 * @fn      Interruptroutine1
 *
 * @brief   This interruptfunction will be called by pressing 
 *          the external button for acyclic measuring and sending
 *          It just calls the function P2_interrupthandling
 *
 * @param   No parameter
 * @return  No return 
 */
/*
_PRAGMA(vector=P2INT_VECTOR) __near_func __interrupt void Interruptroutine1 (void)
{

  P2_InterruptHandling();

  return;
}
*/
/*********************************************************************
 * @fn      P2_InterruptHandling
 *
 * @brief   This is called after an Interrupt on P2.0 occourred. 
 *          It turns on the LED, sets the events START_MEASURING in task init_measuring,
 *          ENOUGH_POWER_FOR_SEND in task send_data and LED_AUS in task led_blink.
 *          
 *          So after turning on the LED, there will be a measuring, then the 
 *          measured data will be sent and the LED wibb be turned off
 *
 * @param   No parameter
 * @return  No return 
 */
 
/*
void P2_InterruptHandling(void)
{
  if ( P2IFG & 0x01 )
  {   
    P2IEN &= ~0x01;                // Disable Port2.0 Interrupt

    P0 &= ~(OWN_LED);              // schalte LED ein (Low aktiv)
    P2IF = 0;
    P2IFG &= 0xE0;  
   
  }    

  
  IRCON2 &= 0xFE;
  
  return;
}*/

  • Hello Alexander,
    You are manually turning advertisement on and off therefore you should set gapRole_AdvertOffTime = 0 and remove the GAP_ADTYPE_FLAGS_GENERAL from advertData.

    If that does not help maybe you could try to simplify your application and only send a simple static payload to try to narrow down the root cause. Let me know how it works out.
  • Hallo Eirik,

    Thanks for your answer.

    I changed the things you wrote.
    The behavior is the same, just with the difference,
    that the program hangs in the stack in llStopTimer2

    here is the call stack:
    - llStopTimer2
    - LL-PowerOffReq
    - halSleep
    - osal_pwrmgr_powerconserve
    - osal_run_system
    - osal_start_system
    - main
    - [?call_main + 0xb]

    when POWER_SAVING isn't defined, everything works fine.
    But this is not an option because the target later should be powered by a little solar cell.

    So do you have any other idea how to resolve this problem?
  • Hello Alex,
    Can you try to narrow down what the last instruction are in the assembly window?
    What kind of HW are you using?
    Have you mounted and enabled an external 32 kHz XTAL?