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.

CC1110 Align with positive 32 kHz clock edge taking too long

Other Parts Discussed in Thread: SIMPLICITI

I'm using the CC1110 with SIMPLICITI 1.2.0. My main End Device function it's a simple loop that transmit the internal temperature over the radio and then enter PM2 for 5 minutes.

This is the main function:

void main()
{
/* Initialize Board */
BSP_Init();

/* Send Join request */ 
SMPL_Init(RxCB);

while (SMPL_SUCCESS != SMPL_Link(&sLinkID1))
{
   SPIN_ABOUT_A_SECOND; /* calls nwk_pllBackgrounder for us */
}

while (1)
    { 
      /* If Packets arrived */
        while(awake_flag)
        {
          if(sSemaphore) /* If there is packets...  */
          {
              sSemaphore = 0;              
              SMPL_Receive( sLinkID1, rxmsg, &length );
              processMessage(rxmsg, length);
          }
        }
      /* Send Sensor Data */
        GetSensorData(SensorData);
      /*Transmit frame */
        SMPL_Send(sLinkID1, SensorData, sizeof(SensorData));
      /* Set sleep timer and enter PM2 according to datasheet */ 
        BSP_SleepFor(PM2,1SECOND_RESOLUTION, Sleep_Time);
    }
}

The SleepFor function is form  the CC1110 Mini DK Software Example (swrc133) 

void BSP_SleepFor(uint8_t mode, uint8_t res, uint16_t steps)
{
  //  Set radio to sleep
  SMPL_Ioctl(IOCTL_OBJ_RADIO,IOCTL_ACT_RADIO_SLEEP,0);  
  IEN2 &= ~0x01;                          // Disable RF interrupt
  BSP_DISABLE_INTERRUPTS();
  
  BSP_SET_MAIN_CLOCK_RC();                // Set main clock source to RC oscillator
  
  // Update Sleep timer
  WORCTL = 0x04 + (res&0x03);             // Reset timer and set resolution, mask out the 2 LSB's.
  uint8_t temp = WORTIME0;                // Wait one full 32kHz cycle to allow sleep timer to reset
  while( temp == WORTIME0);
  temp = WORTIME0;
  while( temp == WORTIME0);
  
  WOREVT1 = (steps>>8);                   // Set timer high byte
  WOREVT0 = (uint8_t)steps;               // Set timer Low byte
  
  STIF = 0;                               // Clear Sleep Timer flag in IRCON
  WORIRQ = 0x10;                          // 0x12 Enable Interupts and clear module flag
  STIE = 1;                               // Enable Sleep Timer interrupt.
  
  BSP_ENABLE_INTERRUPTS();
  
  bsp_PowerMode(mode);
  
  BSP_SET_MAIN_CLOCK_XOSC();              // Set main clock source to External oscillator
  
  // Wake up the radio and set it in Idle 
  SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE,0);
  IEN2 |= 0x01;                           // Enable RF interrupt
}
void bsp_PowerMode(uint8_t mode)
{
  
  if (mode == POWER_MODE_2 || mode == POWER_MODE_3)
  {
    // NOTE! At this point, make sure all interrupts that will not be used to
    // wake from PM are disabled as described in chapter 13.1.3 of the datasheet.
    
    // Store current DMA channel 0 descriptor and abort any ongoing transfers if the channel is in use
    uint8_t storedDescHigh = DMA0CFGH;
    uint8_t storedDescLow = DMA0CFGL;
    uint8_t storedDmaArm = DMAARM;
    
    DMAARM |= 0x81;
    
    // Update descriptor with correct source 
    if( mode == 2 )
    {  
      dmaDesc[0] = (uint8_t) ((uint16_t)&pm2Buf >> 8);
      dmaDesc[1] = (uint8_t) (uint16_t)&pm2Buf;
    }
    else
    {  
      dmaDesc[0] = (uint8_t) ((uint16_t)&pm3Buf >> 8);
      dmaDesc[1] = (uint8_t) (uint16_t)&pm3Buf;
    }
    
    // Associate the descriptor with DMA channel 0 and arm the DMA channel 
    DMA0CFGH = (uint16_t)&dmaDesc >> 8;
    DMA0CFGL = (uint16_t)&dmaDesc;
    DMAARM = 0x01;
    
    // Allign with positive 32 kHz clock edge as described in chapter 13.8.2
    // in the datasheet.
    uint8_t temp = WORTIME0;
    while( temp == WORTIME0);
    
    // Make sure XOSC is powered down when entering PM2/3 and that cache of flash is disabled.
    MEMCTR |= 0x02;
    SLEEP = 0x04 | mode;
    
    // Enter power mode as described in chapter 13.1.3 in the datasheet.
    asm("NOP");
    asm("NOP");
    asm("NOP");
    if( SLEEP & 0x03 ) {
      asm("MOV 0xD7,#0x01");      // DMAREQ = 0x01;
      asm("NOP");                 // Needed to perfectly align the DMA transfer 
      asm("ORL 0x87,#0x01");      // PCON |= 0x01; 
      asm("NOP");
    }
    
    MEMCTR &= ~0x02;
    
    // Update with original DMA descriptor and arm.    
    DMA0CFGH = storedDescHigh;
    DMA0CFGL = storedDescLow;
    DMAARM = storedDmaArm;
  }
  else if ( mode == POWER_MODE_1 )
  {
    uint8_t temp = WORTIME0;
    while( temp == WORTIME0);
    
    SLEEP |= mode;
    asm("NOP");
    asm("NOP");
    asm("NOP");
    if ( SLEEP & 0x03 ) 
    {
      PCON |= 0x01;
      asm("NOP");
    }
  }
  else if ( mode == POWER_MODE_0 )
  {           
    PCON |= 0x01;
    asm("NOP");
  }
  else 
  {
    /* Not valid */    
  }
}

My problem is that the function SleepFor() it's taking too long to enter in PM2 (around 1 second most of the times). I did some debugging and found that the delay is when aligning with the 32KHz clock edge ( while( temp == WORTIME0) ).

I also found that every time the CC1110 wakes up and receives a command (which is not every time it wakes up) there is no delay aligning with the 32KHz clock edge.

My question is: Is there any way to reduce the time aligning with the clock edge?

My application has very limited energy resources. So, 3mA absorption (Active mode current) per 1 second  it's too much.

I hope someone can give me a solution.

Thanks,

Abel.

  • Hi Abel

    You must follow the recommendation in the data sheet and also in the errata note when entering PM2. Entering power modes must be aligned to the 32 kHz clock edge (if power modes are entered on an edge you risk that the SLEEP timer will sleep 128 times too long).

    I cannot understand that entering PM2 should take 1 s. How are you measuring this time?

    The sleep timer logic is running at a 256 Hz clock (if the sleep time is above ~4 ms) so if this is the case waiting for the edge will take up to 3.906 msec.

    However, doing this twice will worst case take a little less than 8 ms, far from the 1 s you are seeing.

    BR

    Siri

  • If you want to decrease time delay for entering PM2 there are need to use minimal resolution. Change resolution to SLEEP_32_MS_RESOLUTION

  • Hi Siri,

    thank you for the prompt reply.

    I'm measuring the time with a current probe and the oscilloscope. Here attached there is an oscilloscope screenshot were 1mV equals 1mA. As it can be seen the ED wakes up at point "A", it transmits three frames (it absorb ~35mA in Tx) and then at point "B" calls the function "BSP_SleepFor()". However, it can be seen that from point "B" to point "C" there is still ~3.7mA of absorption and the time is 2 second in this case (instead of the 1 second mentioned by me before). So, it takes even more time.

     

    Best regards,

    Abel.

  • Hi Vladislav,

    thank you very much for your suggestion. Indeed, it was the timer resolution. I noticed that reducing the timer resolution the synchronization time was reduced according to this value.

    Best regards,

    Abel.