/*************************************************************************************************** * @fn HalLedOnOff * * @brief Turns specified LED ON or OFF * * @param leds - LED bit mask * mode - LED_ON,LED_OFF, * * @return none ***************************************************************************************************/ void HalLedOnOff (uint8 leds, uint8 mode) { if (leds & HAL_LED_1) { if (mode == HAL_LED_MODE_ON) { HAL_TURN_ON_LED1(); } else { HAL_TURN_OFF_LED1(); } } if (leds & HAL_LED_2) { if (mode == HAL_LED_MODE_ON) { HAL_TURN_ON_LED2(); } else { HAL_TURN_OFF_LED2(); } } if (leds & HAL_LED_3) { if (mode == HAL_LED_MODE_ON) { HAL_TURN_ON_LED3(); } else { HAL_TURN_OFF_LED3(); } } if (leds & HAL_LED_4) { if (mode == HAL_LED_MODE_ON) { HAL_TURN_ON_LED4(); } else { HAL_TURN_OFF_LED4(); } } /* Remember current state */ if (mode) { HalLedState |= leds; } else { HalLedState &= (leds ^ 0xFF); } }
void sleep(void) { if (HAL_STATE_LED2()) { HAL_TURN_OFF_LED1(); HAL_TURN_OFF_LED3(); HAL_TURN_ON_LED2(); for(uint8 n=0;n<30;n++) for(uint8 i=0;i<200;i++) MicroWait(50000); HAL_TURN_OFF_LED2(); //sbBinded = 0; } }
/*************************************************************************************************** * @fn HalLedOnOff * * @brief Turns specified LED ON or OFF * * @param leds - LED bit mask * mode - LED_ON,LED_OFF, * * @return none ***************************************************************************************************/ void HalLedOnOff( uint8 leds, uint8 mode ) { if ( leds & HAL_LED_1 ) { if ( mode == HAL_LED_MODE_ON ) HAL_TURN_ON_LED1(); else HAL_TURN_OFF_LED1(); } if ( leds & HAL_LED_2 ) { if ( mode == HAL_LED_MODE_ON ) HAL_TURN_ON_LED2(); else HAL_TURN_OFF_LED2(); } if ( leds & HAL_LED_3 ) { if ( mode == HAL_LED_MODE_ON ) HAL_TURN_ON_LED3(); else HAL_TURN_OFF_LED3(); } if ( leds & HAL_LED_4 ) { if ( mode == HAL_LED_MODE_ON ) HAL_TURN_ON_LED4(); else HAL_TURN_OFF_LED4(); } // Remember current state if ( mode ) ledState |= leds; else ledState &= (0xff ^ leds); }
/************************************************************************************************** * @fn halAssertHazardLights * * @brief Blink LEDs to indicate an error. * * @param none * * @return none ************************************************************************************************** */ void halAssertHazardLights(void) { enum { DEBUG_DATA_RSTACK_HIGH_OFS, DEBUG_DATA_RSTACK_LOW_OFS, DEBUG_DATA_TX_ACTIVE_OFS, DEBUG_DATA_RX_ACTIVE_OFS, #if (defined HAL_MCU_AVR) || (defined HAL_MCU_CC2430) DEBUG_DATA_INT_MASK_OFS, #elif (defined HAL_MCU_CC2530) || (defined HAL_MCU_CC2533) DEBUG_DATA_INT_MASK0_OFS, DEBUG_DATA_INT_MASK1_OFS, #endif DEBUG_DATA_SIZE }; uint8 buttonHeld; uint8 debugData[DEBUG_DATA_SIZE]; /* disable all interrupts before anything else */ HAL_DISABLE_INTERRUPTS(); /*------------------------------------------------------------------------------- * Initialize LEDs and turn them off. */ HAL_BOARD_INIT(); HAL_TURN_OFF_LED1(); HAL_TURN_OFF_LED2(); HAL_TURN_OFF_LED3(); HAL_TURN_OFF_LED4(); /*------------------------------------------------------------------------------- * Master infinite loop. */ for (;;) { buttonHeld = 0; /*------------------------------------------------------------------------------- * "Hazard lights" loop. A held keypress will exit this loop. */ do { HAL_LED_BLINK_DELAY(); /* toggle LEDS, the #ifdefs are in case HAL has logically remapped non-existent LEDs */ #if (HAL_NUM_LEDS >= 1) HAL_TOGGLE_LED1(); #if (HAL_NUM_LEDS >= 2) HAL_TOGGLE_LED2(); #if (HAL_NUM_LEDS >= 3) HAL_TOGGLE_LED3(); #if (HAL_NUM_LEDS >= 4) HAL_TOGGLE_LED4(); #endif #endif #endif #endif /* escape hatch to continue execution, set escape to '1' to continue execution */ { static uint8 escape = 0; if (escape) { escape = 0; return; } } /* break out of loop if button is held long enough */ if (HAL_PUSH_BUTTON1()) { buttonHeld++; } else { buttonHeld = 0; } } while (buttonHeld != 10); /* loop until button is held specified number of loops */ /*------------------------------------------------------------------------------- * Just exited from "hazard lights" loop. */ /* turn off all LEDs */ HAL_TURN_OFF_LED1(); HAL_TURN_OFF_LED2(); HAL_TURN_OFF_LED3(); HAL_TURN_OFF_LED4(); /* wait for button release */ HAL_DEBOUNCE(!HAL_PUSH_BUTTON1()); /*------------------------------------------------------------------------------- * Load debug data into memory. */ #ifdef HAL_MCU_AVR { uint8 * pStack; pStack = (uint8 *) SP; pStack++; /* point to return address on stack */ debugData[DEBUG_DATA_RSTACK_HIGH_OFS] = *pStack; pStack++; debugData[DEBUG_DATA_RSTACK_LOW_OFS] = *pStack; } debugData[DEBUG_DATA_INT_MASK_OFS] = EIMSK; #endif #if (defined HAL_MCU_CC2430) debugData[DEBUG_DATA_INT_MASK_OFS] = RFIM; #elif (defined HAL_MCU_CC2530) || (defined HAL_MCU_CC2533) debugData[DEBUG_DATA_INT_MASK0_OFS] = RFIRQM0; debugData[DEBUG_DATA_INT_MASK1_OFS] = RFIRQM1; #endif #if (defined HAL_MCU_AVR) || (defined HAL_MCU_CC2430) || (defined HAL_MCU_CC2530) || \ (defined HAL_MCU_CC2533) || (defined HAL_MCU_MSP430) debugData[DEBUG_DATA_TX_ACTIVE_OFS] = macTxActive; debugData[DEBUG_DATA_RX_ACTIVE_OFS] = macRxActive; #endif /* initialize for data dump loop */ { uint8 iBit; uint8 iByte; iBit = 0; iByte = 0; /*------------------------------------------------------------------------------- * Data dump loop. A button press cycles data bits to an LED. */ while (iByte < DEBUG_DATA_SIZE) { /* wait for key press */ while(!HAL_PUSH_BUTTON1()); /* turn on all LEDs for first bit of byte, turn on three LEDs if not first bit */ HAL_TURN_ON_LED1(); HAL_TURN_ON_LED2(); HAL_TURN_ON_LED3(); if (iBit == 0) { HAL_TURN_ON_LED4(); } else { HAL_TURN_OFF_LED4(); } /* wait for debounced key release */ HAL_DEBOUNCE(!HAL_PUSH_BUTTON1()); /* turn off all LEDs */ HAL_TURN_OFF_LED1(); HAL_TURN_OFF_LED2(); HAL_TURN_OFF_LED3(); HAL_TURN_OFF_LED4(); /* output value of data bit to LED1 */ if (debugData[iByte] & (1 << (7 - iBit))) { HAL_TURN_ON_LED1(); } else { HAL_TURN_OFF_LED1(); } /* advance to next bit */ iBit++; if (iBit == 8) { iBit = 0; iByte++; } } } /* * About to enter "hazard lights" loop again. Turn off LED1 in case the last bit * displayed happened to be one. This guarantees all LEDs are off at the start of * the flashing loop which uses a toggle operation to change LED states. */ HAL_TURN_OFF_LED1(); } }
/******************************************************************************* * @fn halSleep * * @brief This function is called from the OSAL task loop using and * existing OSAL interface. It sets the low power mode of the LL * and the CC2540. * * input parameters * * @param osal_timeout - Next OSAL timer timeout, in msec. * * output parameters * * @param None. * * @return None. */ void halSleep( uint32 osal_timeout ) { uint32 timeout; uint32 llTimeout; uint32 sleepTimer; halDriverBegPM(); #ifdef DEBUG_GPIO // TEMP P1_0 = 1; #endif // DEBUG_GPIO if (osal_timeout > MAX_16BIT_TIMEOUT) { osal_timeout = MAX_16BIT_TIMEOUT; } // get LL timeout value already converted to 32kHz ticks LL_TimeToNextRfEvent( &sleepTimer, &llTimeout ); // check if no OSAL timeout // Note: If the next wake event is due to an OSAL timeout, then wakeForRF // will already be FALSE, and the call to LL_TimeToNExtRfEvent will // already have taken a snapshot of the Sleep Timer. if (osal_timeout == 0) { // use common variable timeout = llTimeout; // check if there's time before the next radio event // Note: Since the OSAL timeout is zero, then if the radio timeout is // not zero, the next wake (if one) will be due to the radio event. wakeForRF = (timeout != 0) ? TRUE : FALSE; } else // OSAL timeout is non-zero { // convet OSAL timeout to sleep time // Note: Could be early by one 32kHz timer tick due to rounding. timeout = HAL_SLEEP_MS_TO_32KHZ( osal_timeout ); // so check time to radio event is non-zero, and if so, use shorter value if ((llTimeout != 0) && (llTimeout < timeout)) { // use common variable timeout = llTimeout; // the next ST wake time is due to radio wakeForRF = TRUE; } else // OSAL timeout will be used to wake { // so take a snapshot of the sleep timer for sleep based on OSAL timeout sleepTimer = halSleepReadTimer(); // the next ST wake time is not due to radio wakeForRF = FALSE; } } // HAL_SLEEP_PM3 is entered only if the timeout is zero halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER; #ifdef DEBUG_GPIO // TEMP P1_0 = 0; #endif // DEBUG_GPIO // check if sleep should be entered if ( (timeout > PM_MIN_SLEEP_TIME) || (timeout == 0) ) { halIntState_t ien0, ien1, ien2; #ifdef DEBUG_GPIO // TEMP P1_0 = 1; #endif // DEBUG_GPIO HAL_ASSERT( HAL_INTERRUPTS_ARE_ENABLED() ); HAL_DISABLE_INTERRUPTS(); // check if radio allows sleep, and if so, preps system for shutdown if ( LL_PowerOffReq(halPwrMgtMode) == LL_SLEEP_REQUEST_ALLOWED ) { #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) // get peripherals ready for sleep HalKeyEnterSleep(); #endif // ((defined HAL_KEY) && (HAL_KEY == TRUE)) #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_OFF_LED3(); #else // use this to turn LEDs off during sleep HalLedEnterSleep(); #endif // HAL_SLEEP_DEBUG_LED // enable sleep timer interrupt if (timeout != 0) { // check if the time to next wake event is greater than max sleep time if (timeout > MAX_SLEEP_TIME ) { // it is, so limit to max allowed sleep time (~510s) halSleepSetTimer( sleepTimer, MAX_SLEEP_TIME ); } else // not more than allowed sleep time { // so set sleep time to actual amount halSleepSetTimer( sleepTimer, timeout ); } } // prep CC254x power mode HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode); // save interrupt enable registers and disable all interrupts HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2); HAL_ENABLE_INTERRUPTS(); #ifdef DEBUG_GPIO // TEMP P1_0 = 0; #endif // DEBUG_GPIO // set CC254x power mode; interrupts are disabled after this function // Note: Any ISR that could wake the device from sleep needs to use // CLEAR_SLEEP_MODE(), which will clear the halSleepPconValue flag // used to enter sleep mode, thereby preventing the device from // missing this interrupt. HAL_SLEEP_SET_POWER_MODE(); #ifdef DEBUG_GPIO // TEMP P1_0 = 1; #endif // DEBUG_GPIO // check if ST interrupt pending, and if not, clear wakeForRF flag // Note: This is needed in case we are not woken by the sleep timer but // by for example a key press. In this case, the flag has to be // cleared as we are not just before a radio event. // Note: There is the possiblity that we may wake from an interrupt just // before the sleep timer would have woken us just before a radio // event, in which case power will be wasted as we will probably // enter this routine one or more times before the radio event. // However, this is presumably unusual, and isn't expected to have // much impact on average power consumption. if ( (wakeForRF == TRUE) && !(IRCON & 0x80) ) { wakeForRF = FALSE; } // restore interrupt enable registers HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2); // power on the LL; blocks until completion // Note: This is done here to ensure the 32MHz XOSC has stablized, in // case it is needed (e.g. the ADC is used by the joystick). LL_PowerOnReq( (halPwrMgtMode == CC2540_PM3), wakeForRF ); #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_ON_LED3(); #else //!HAL_SLEEP_DEBUG_LED // use this to turn LEDs back on after sleep HalLedExitSleep(); #endif // HAL_SLEEP_DEBUG_LED #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) // handle peripherals (void)HalKeyExitSleep(); #endif // ((defined HAL_KEY) && (HAL_KEY == TRUE)) } HAL_ENABLE_INTERRUPTS(); } halDriverEndPM(); #ifdef DEBUG_GPIO // TEMP P1_0 = 0; #endif // DEBUG_GPIO return; }
/************************************************************************************************** * @fn halSleep * * @brief This function is called from the OSAL task loop using and existing OSAL * interface. It sets the low power mode of the MAC and the CC2530. * * input parameters * * @param osal_timeout - Next OSAL timer timeout. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void halSleep( uint16 osal_timeout ) { uint32 timeout; uint32 macTimeout = 0; /* get next OSAL timer expiration converted to 320 usec units */ timeout = HAL_SLEEP_MS_TO_320US(osal_timeout); if (timeout == 0) { timeout = MAC_PwrNextTimeout(); } else { /* get next MAC timer expiration */ macTimeout = MAC_PwrNextTimeout(); /* get lesser of two timeouts */ if ((macTimeout != 0) && (macTimeout < timeout)) { timeout = macTimeout; } } /* HAL_SLEEP_PM2 is entered only if the timeout is zero and * the device is a stimulated device. */ halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER; /* DEEP sleep can only be entered when zgPollRate == 0. * This is to eliminate any possibility of entering PM3 between * two network timers. */ #if ZG_BUILD_ENDDEVICE_TYPE && defined (NWK_AUTO_POLL) if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) || (timeout == 0 && zgPollRate == 0)) #else if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) || (timeout == 0)) #endif { halIntState_t ien0, ien1, ien2; HAL_ASSERT(HAL_INTERRUPTS_ARE_ENABLED()); HAL_DISABLE_INTERRUPTS(); /* always use "deep sleep" to turn off radio VREG on CC2530 */ if (halSleepPconValue != 0 && MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS) { /* The PCON value is not zero. There is no interrupt overriding the * sleep decision. Also, the radio granted the sleep request. */ #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) /* get peripherals ready for sleep */ HalKeyEnterSleep(); #endif #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_OFF_LED3(); #else /* use this to turn LEDs off during sleep */ HalLedEnterSleep(); #endif /* enable sleep timer interrupt */ if (timeout != 0) { if (timeout > HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME )) { timeout -= HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ); halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME )); } else { /* set sleep timer */ halSleepSetTimer(timeout); } /* set up sleep timer interrupt */ HAL_SLEEP_TIMER_CLEAR_INT(); HAL_SLEEP_TIMER_ENABLE_INT(); } #ifdef HAL_SLEEP_DEBUG_LED if (halPwrMgtMode == CC2530_PM1) { HAL_TURN_ON_LED1(); } else { HAL_TURN_OFF_LED1(); } #endif if (ZNP_CFG1_UART == znpCfg1) { HalUARTSuspend(); } /* Prep CC2530 power mode */ HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode); /* save interrupt enable registers and disable all interrupts */ HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2); HAL_ENABLE_INTERRUPTS(); /* set CC2530 power mode, interrupt is disabled after this function * Note that an ISR (that could wake up from power mode) which runs * between the previous instruction enabling interrupts and before * power mode is set would switch the halSleepPconValue so that * power mode shall not be entered in such a case. */ HAL_SLEEP_SET_POWER_MODE(); /* Disable interrupt immediately */ HAL_DISABLE_INTERRUPTS(); /* restore interrupt enable registers */ HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2); /* disable sleep timer interrupt */ HAL_SLEEP_TIMER_DISABLE_INT(); if (ZNP_CFG1_UART == znpCfg1) { HalUARTResume(); } #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_ON_LED3(); #else /* use this to turn LEDs back on after sleep */ HalLedExitSleep(); #endif #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) /* handle peripherals */ (void)HalKeyExitSleep(); #endif /* power on the MAC; blocks until completion */ MAC_PwrOnReq(); HAL_ENABLE_INTERRUPTS(); /* For CC2530, T2 interrupt won’t be generated when the current count is greater than * the comparator. The interrupt is only generated when the current count is equal to * the comparator. When the CC2530 is waking up from sleep, there is a small window * that the count may be grater than the comparator, therefore, missing the interrupt. * This workaround will call the T2 ISR when the current T2 count is greater than the * comparator. The problem only occurs when POWER_SAVING is turned on, i.e. the 32KHz * drives the chip in sleep and SYNC start is used. */ macMcuTimer2OverflowWorkaround(); } else { /* Sleep request is not granted. Check PCON value to see why the sleep is not granted. */ if (halSleepPconValue == 0) { /* An interrupt may have changed the sleep decision. Do not sleep at all. Turn on * the interrupt, exit normally, and the next sleep will be allowed. */ HAL_ENABLE_INTERRUPTS(); } else { /* PCON value is okay but Radio cannot enter power mode hence just put CPU to idle mode. * Interrupt will be enabled in halSleepEnterIdleMode(). */ halSleepEnterIdleMode(timeout); } } } else if (timeout > PM_MIN_IDLE_TIME) { /* Timeout is too close to enter power mode. Try idle mode. */ HAL_DISABLE_INTERRUPTS(); /* Interrupt will be enabled in halSleepEnterIdleMode(). */ halSleepEnterIdleMode(timeout); } }
/************************************************************************************************** * @fn halSleep * * @brief This function is called from the OSAL task loop using and existing OSAL * interface. It sets the low power mode of the MAC and the CC2530. * * input parameters * * @param osal_timeout - Next OSAL timer timeout. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void halSleep( uint16 osal_timeout ) { uint32 timeout; uint32 macTimeout = 0; halAccumulatedSleepTime = 0; /* get next OSAL timer expiration converted to 320 usec units */ timeout = HAL_SLEEP_MS_TO_320US(osal_timeout); if (timeout == 0) { timeout = MAC_PwrNextTimeout(); } else { /* get next MAC timer expiration */ macTimeout = MAC_PwrNextTimeout(); /* get lesser of two timeouts */ if ((macTimeout != 0) && (macTimeout < timeout)) { timeout = macTimeout; } } /* HAL_SLEEP_PM2 is entered only if the timeout is zero and * the device is a stimulated device. */ halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER; /* DEEP sleep can only be entered when zgPollRate == 0. * This is to eliminate any possibility of entering PM3 between * two network timers. */ #if ZG_BUILD_ENDDEVICE_TYPE && defined (NWK_AUTO_POLL) if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) || (timeout == 0 && zgPollRate == 0)) #else if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) || (timeout == 0)) #endif { halIntState_t ien0, ien1, ien2; HAL_ASSERT(HAL_INTERRUPTS_ARE_ENABLED()); HAL_DISABLE_INTERRUPTS(); /* always use "deep sleep" to turn off radio VREG on CC2530 */ if (MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS) { #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) /* get peripherals ready for sleep */ HalKeyEnterSleep(); #endif #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_OFF_LED3(); #else /* use this to turn LEDs off during sleep */ HalLedEnterSleep(); #endif /* enable sleep timer interrupt */ if (timeout != 0) { if (timeout > HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME )) { timeout -= HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ); halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME )); } else { /* set sleep timer */ halSleepSetTimer(timeout); } /* set up sleep timer interrupt */ HAL_SLEEP_TIMER_CLEAR_INT(); HAL_SLEEP_TIMER_ENABLE_INT(); } #ifdef HAL_SLEEP_DEBUG_LED if (halPwrMgtMode == CC2530_PM1) { HAL_TURN_ON_LED1(); } else { HAL_TURN_OFF_LED1(); } #endif /* save interrupt enable registers and disable all interrupts */ HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2); HAL_ENABLE_INTERRUPTS(); /* set CC2530 power mode, interrupt is disabled after this function */ HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode); /* the interrupt is disabled - see halSetSleepMode() */ /* restore interrupt enable registers */ HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2); /* disable sleep timer interrupt */ HAL_SLEEP_TIMER_DISABLE_INT(); /* Calculate timer elasped */ halAccumulatedSleepTime += (HalTimerElapsed() / TICK_COUNT); #ifdef HAL_SLEEP_DEBUG_LED HAL_TURN_ON_LED3(); #else /* use this to turn LEDs back on after sleep */ HalLedExitSleep(); #endif #if ((defined HAL_KEY) && (HAL_KEY == TRUE)) /* handle peripherals */ (void)HalKeyExitSleep(); #endif /* power on the MAC; blocks until completion */ MAC_PwrOnReq(); HAL_ENABLE_INTERRUPTS(); /* For CC2530, T2 interrupt won’t be generated when the current count is greater than * the comparator. The interrupt is only generated when the current count is equal to * the comparator. When the CC2530 is waking up from sleep, there is a small window * that the count may be grater than the comparator, therefore, missing the interrupt. * This workaround will call the T2 ISR when the current T2 count is greater than the * comparator. The problem only occurs when POWER_SAVING is turned on, i.e. the 32KHz * drives the chip in sleep and SYNC start is used. */ macMcuTimer2OverflowWorkaround(); } else { HAL_ENABLE_INTERRUPTS(); } } }