2 Replies Latest reply on Jan 21, 2016 6:51 PM by jim_1406701

    Hibernate Fails After User SFlash Write

    jim_1406701

      I've found lots of answers in this Forum as I've climbed the PRoC learning curve -- thank you all!

         

      I've found a curious interaction (PRoC CYBLE-022001 on a Pioneer Kit) to share:

         

      If I call CySysPmHibernate() after WriteUserSFlashRow() within a Critical Section (initiated via CyEnterCriticalSection() ), Hibernate fails to hold for a suitable GPIO interrupt.  Processing proceeds through CySysPmHibernate() call as though it wasn't there and the next line of code is executed.  Hibernate never happens, and there is no PRoC reset.

         

      The Hibernate call is adapted from Project #6 in the 100 Projects series.  WriteUserSFlashRow() is unchanged from Project #29.  AndyWarne mentions problems with clocks being restored completely by WriteUserSFlashRow() in this Forum Thread:  "http://www.cypress.com/forum/proc-ble/sflash?source=search&keywords=sflash%20%26%20ble&cat=community".  That does not appear to be what is happening here.

         

      The solution was to end the Critical Section (with CyExitCriticalSection() ) before the WriteUserSFlashRow() call as shown (*** NO CLUE comment) in this code listing.  Hibernate works properly with this code:

         

      -----------------------------------------------

         

      void EnterLowPowerMode(void)
      {
          CYBLE_BLESS_STATE_T blessState;
          uint8 intrStatus;
          
          uint32 data[USER_SFLASH_ROW_SIZE/4];    // User SFlash variables ************
          uint32 dataIndex;
          uint32 status;
          
      //********************************************************************************    
          /* Configure BLESS in Deep-Sleep mode */
          CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP);
          
          /* Prevent interrupts while entering system low power modes */
          intrStatus = CyEnterCriticalSection();
          
          /* Get the current state of BLESS block */
          blessState = CyBle_GetBleSsState();
          
          /* If BLESS is in Deep-Sleep mode or the XTAL oscillator is turning on,
           * and it's not time to hibernate, then PRoC BLE can enter Deep-Sleep mode
           * (1.3uA current consumption) */
          
          if((blessState == CYBLE_BLESS_STATE_ECO_ON || 
              blessState == CYBLE_BLESS_STATE_DEEPSLEEP) &&
              hibernate_time < HIBE_TIME)
          {
              CySysPmDeepSleep();
          }
          else if((blessState == CYBLE_BLESS_STATE_ECO_ON || 
              blessState == CYBLE_BLESS_STATE_DEEPSLEEP) &&
              hibernate_time >= HIBE_TIME)
          {
              // Save SaveData in User SFlash non-volatile memory, must write 128B row
              data[0] = SaveData;
              SaveData++;                // new value next time
              
              // load balance of user SFlash write buffer
             for(dataIndex = 1; dataIndex < (USER_SFLASH_ROW_SIZE/4); dataIndex++)
              {
                  data[dataIndex] = SFLASH_STARTING_VALUE;
              }
              
              CyExitCriticalSection(intrStatus);      // *** NO CLUE why SFlash write in crit sec prevents
                                                      //      Hibernate from working!!?!   Remove it.
              
              // write row 1 (Bytes 128-131 User SFlash)        
              status = WriteUserSFlashRow(1, &data[0]);
              
              // NOW Hibernate
              CySysPmHibernate();
          }
          
          CyExitCriticalSection(intrStatus);
      }

         

      -----------------------------------------------

         

      Anyone have an idea as to what is going on with the Critical Section interaction?

         

      Thanks.

         

      Jim