TI论坛
直播中

张艳梅

7年用户 227经验值
私信 关注
[问答]

CC2530在osal调度下PM2模式休眠和工作时间是多少?

请教一个问题
cc2530(zstack-2.2.2-1.3.0),osal调度的PM2模式,如何自定义休眠时间和工作时间?


我现在是在ZED的
void zb_HandleOsalEvent( uint16 event )
[
.................

if ( event & MY_PERSONAL_ENTERPM2_EVT )
[
//P1_1 ^= 1;
myApp_StopReporting();
NLME_SetPollRate(myEnterpm2Period); // 60 000ms = 1 min

osal_start_timerEx( sapi_TaskID, MY_PERSONAL_ENTERPM2_EVT, myEnterpm2Period );
]
]


static uint16 myEnterpm2Period = 30000; 的时候,休眠30s,发送20s
static uint16 myEnterpm2Period = 40000; 的时候,休眠40s, 还是 发送20s
static uint16 myEnterpm2Period = 60000; 貌似直接就乱套了,也不休眠了,总是在发送


休眠时间 和 工作的时间,究竟怎么来做限制?
而在osal下,最大的休眠时间应该是65ms左右才对啊?
那工作时间,又该怎么来约束?

回帖(49)

李果

2020-8-7 00:46:59
OSAL调度系统的休眠时间并不是自己随便可以设置的,而是osal调度系统每次都是以最近一次要发生事件的timeout作为本次的休眠时间,如果你的系统有一个最小的30ms事件的周期性的发生,那么你的休眠时间只能是30ms了。
举报

张艳梅

2020-8-7 01:04:56
引用: wenlonghbo 发表于 2020-8-7 16:28
OSAL调度系统的休眠时间并不是自己随便可以设置的,而是osal调度系统每次都是以最近一次要发生事件的timeout作为本次的休眠时间,如果你的系统有一个最小的30ms事件的周期性的发生,那么你的休眠时间只能是30ms了。

    您说的我都明白,但是我在ZED的void zb_HandleOsalEvent( uint16 event )里面。
    有一个20ms的事件MY_PERSONAL_COLLECT_345_EVT
    我还有一个200ms的事件MY_PERSONAL_REPORT_345_EVT
    我还设置了另外一个事件MY_PERSONAL_ENTERPM2_EVT(比如说设置为40s),用于进入pm2状态。进入MY_PERSONAL_ENTERPM2_EVT事件以后,我利用myApp_StopReporting();来关掉20ms和200ms的定时器事件,但是不关40s的定时器事件。然后设置三个全部为0,这样让osal自动进入任务调度,按照您的说法,现在获取的休眠时间就应该是40s了
    当唤醒以后,我在hal_sleep.c里面HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);之后,设置正常的poll_rate值(1000,100,100),并且开启myApp_StartReporting();来开启20ms和200ms的定时器事件。然后等40s还有,再次进入我的MY_PERSONAL_ENTERPM2_EVT(40s)事件,由此循环。

    按照这个逻辑,如果我的MY_PERSONAL_ENTERPM2_EVT设置为40s,那是不是应该工作40s,然后进入pm2模式休眠40s,唤醒后再工作40s,由此循环?
    但事实上,如果这个值设置为40s了,实际上是工作20s,然后休眠40s。如果这个值设置为60s了,完全就没有休眠了,基本上都是工作状态。这是为什么呢???

--------------------------------------------------------------------------------------------------------------------------------------------------------
void zb_HandleOsalEvent( uint16 event )
[
static uint8 pData[2];
uint8 pDataForExtAdc[2];

if ( event & MY_START_EVT )
[
zb_StartRequest();
]
if ( event & MY_REPORT_TEMP_EVT )
[
// Read and report temperature value
pData[0] = TEMP_REPORT;
pData[1] = myApp_ReadTemperature();
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 2, pData, 0, AF_ACK_REQUEST, 0 );
osal_start_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod );
]
if ( event & MY_REPORT_BATT_EVT )
[
// Read battery value
// If battery level low, report battery value
pData[0] = BATTERY_REPORT;
pData[1] = myApp_ReadExtBattery(); // myApp_ReadBattery();
zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 2, pData, 0, AF_ACK_REQUEST, 0 );
osal_start_timerEx( sapi_TaskID, MY_REPORT_BATT_EVT, myBatteryCheckPeriod );
]

/*-------------------------------------------*/ 
if ( event & MY_PERSONAL_COLLECT_345_EVT )
[
myApp_Read345();


P0DIR |= 0x20;
P0SEL &= ~0x20;
P0_5 ^= 1;

osal_start_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT, myAdxl345CollectPeriod );
]
if ( event & MY_PERSONAL_REPORT_345_EVT )
[
// Read battery value
// If battery level low, report battery value

if( InitTimerFlag == 0x00 )
[
InitTimerFlag = 0x01;

P1DIR |= 0x02;
P1SEL &= ~0x02;
//P1_1 = 0;
P0DIR |= 0x40;
P0SEL &= ~0x40;
//P0_6 = 0;

]

// P1_1 ^= 1;
if ( ( (BufHead - BufTail) > 10) || ( ( (BufHead - BufTail)&0x7F) > 10) )
[
osal_memcpy(PacketData+1,&PreSendValue.PreSend[BufTail*4],40);
PacketData[0]= ADXL345_REPORT;

zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_ADC_CMD_ID2, 41, PacketData , 0,AF_ACK_REQUEST , 0 ); //AF_ACK_REQUEST
BufTail += 10;
BufTail %= 512;

P0DIR |= 0x40;
P0SEL &= ~0x40;
P0_6 ^= 1;

]

osal_start_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT, myAdxl345ReportPeriod );
Delay_1u(1);

//不发这个了,发一个counter
sprintf(SendCnt,"%dr",SendCounter);//将数值格式化为字符串
HalUARTWrite(0, (unsigned char*)&SendCnt,(unsigned char)osal_strlen( (void*)SendCnt ));
SendCounter += 40;
SendCounter %= 0xFFFF ;
]

if ( event & MY_PERSONAL_ENTERPM2_EVT ) // stop里面,不设置此事件(undo)
[

P0DIR |= 0x10;
P0SEL &= ~0x10;
P0_4 ^= 1;

myApp_StopReporting();

NLME_SetPollRate( 0 ); // 60 000ms = 1 min
NLME_SetQueuedPollRate( 0 );
NLME_SetResponseRate( 0 );

osal_start_timerEx( sapi_TaskID, MY_PERSONAL_ENTERPM2_EVT, myEnterpm2Period );
]
/*-------------------------------------------*/
if ( event & MY_FIND_COLLECTOR_EVT )
[
// Find and bind to a collector device
zb_BindDevice( TRUE, SENSOR_REPORT_ADC_CMD_ID2, (uint8 *)NULL );
]
] // void zb_HandleOsalEvent( uint16 event )

#define MY_PERSONAL_REPORT_VOLTAGE_EVT 0x0010 // 上报的采集电压值
#define MY_PERSONAL_COLLECT_345_EVT 0x0020 
#define MY_PERSONAL_REPORT_345_EVT 0x0040 // 上报的345值
#define MY_PERSONAL_ENTERPM2_EVT 0x0080
static uint16 myAdxl345CollectPeriod = 20;
static uint16 myAdxl345ReportPeriod = 200; // milliseconds毫秒
static uint16 myEnterpm2Period = 60000;

void myApp_StopReporting( void )
[
osal_stop_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT );
osal_stop_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT );
]


void halSleep( uint16 osal_timeout )
[
static uint32 timeout; // add static for debug
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 !defined (RTR_NWK) && 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();
/*---------------------------------*/
// P1DIR |= 0x02;
// P1SEL &= ~0x02;
// P1_1 ^= 1;
/*P2口*/
P2SEL &= ~0x07; // 通用io
P2DIR &= ~0x09; // 设置为输入
P2INP |= 0x19;
P2 = 0x00;
/*P1口*/
P1SEL &= ~0xFF; // 通用io
P1DIR &= ~0xFF; // 设置为输入
P1INP |= 0xFC;
P1 = 0x00;
/*P0口*/
P0SEL &= ~0xFF; // 通用io
P0DIR &= ~0xFF; // 设置为输入
P0INP |= 0xFF;
P0 = 0x00;

// P1DIR |= 0x03;
// P1SEL &= ~0x03;
// P1_0 = 0;
// P1_1 = 0;

// P0DIR &= ~0x03;
// P0SEL &= ~0x03;
// P0INP |= 0x03;
// P2INP &= ~0x20; //P0口bu拉
// P0_0 = 1;
// P0_1 = 1;
OBSSEL1 |= 0x80;
OBSSEL2 |= 0x80;
OBSSEL3 |= 0x80;
OBSSEL4 |= 0x80;
OBSSEL5 |= 0x80;
//
// TR0 |= 0x01;
/*---------------------------------*/
/* set CC2530 power mode, interrupt is disabled after this function */
HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);

/*The macro HAL_SLEEP_SET_POWER_MODE() shuts down the radio and core.
Try setting a breakpoint at this location to determine if sleep is being
disallowed at some earlier point.*/

/* 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抰 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();
/*----------------------*/
P1DIR |= 0x02;
P1SEL &= ~0x02;
P1_1 ^= 1;
NLME_SetPollRate( 1000 ); // 休眠完了设置为正常的poll时间间隔
NLME_SetQueuedPollRate( 100 );
NLME_SetResponseRate( 100 );

/*重新初始化每个引脚*/
/*P0口上有P0.0、P0.1拨码开关使用时初始化|P0.2(RX)、P0.3(TX)【需要】初始化|P0.4(校准ADXL345外部中断按键)使用时初始化|
P0.5、P0.6、P0.7未使用空闲【unused pins 处理】*/
P0SEL |= 0x0C;

P0DIR &= ~0xE0;
P0SEL &= ~0xE0;
P0INP &= ~0xE0;
P2INP &= ~0x20;
/*P2口上有个LED灯*/
P1DIR |= 0x01;
P1SEL &= ~0x01;
/*P1口上P1.0(ADXL345 Supply)、P1.1、P1.2(SCL)、P1.3(SDA)使用时初始化|P1.4~P1.7作为sniffer引脚使用,可不自行初始化*/
myApp_StartReporting(); //解决外部定义问题
/*----------------------*/
]
else
[
HAL_ENABLE_INTERRUPTS();
]
]
]



void myApp_StartReporting( void )
[
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_COLLECT_345_EVT, myAdxl345CollectPeriod ); 
osal_start_timerEx( sapi_TaskID, MY_PERSONAL_REPORT_345_EVT, myAdxl345ReportPeriod );
]
举报

李果

2020-8-7 01:11:33
引用: 望望Ll 发表于 2020-8-7 16:46
    您说的我都明白,但是我在ZED的void zb_HandleOsalEvent( uint16 event )里面。
    有一个20ms的事件MY_PERSONAL_COLLECT_345_EVT,
    我还有一个200ms的事件MY_PERSONAL_REPORT_345_EVT,

如果你开启了power_saving功能以后,在20ms 200ms的工作过程中也会再休眠和活动状态间切换的。
能否把时间改短一点,测试下?
举报

连涣艺

2020-8-7 01:25:58
引用: wenlonghbo 发表于 2020-8-7 16:53
如果你开启了power_saving功能以后,在20ms 200ms的工作过程中也会再休眠和活动状态间切换的。
能否把时间改短一点,测试下?

您好,我有个问题,在对ZStack的SampleApp的终端节点设置进入PM2工作模式时,测得的工作电流始终无法降低,正常工作时测得的电流为12mA,休眠时测得的电流为11mA或者12mA(测试方法是用万用表串入电源输入电路中,观察电流值)。
我设置终端节点设置进入PM2工作模式的步骤如下:
1.打开POWER_SAVING 预编译
2.f8wConfig_cfg 中的RFD_RCVC_ALWAYS_ON=FALSE
3.f8wConfig_cfg中四个DPoll_RATE设为0
4.ZGlobals.c中三个PollRate设为0
5.Onboard.c文件中,OnboardKeyIntEnable=HAL_KEY_INTERUPT_ENABLE
6.hal_drivers.c中if(!Hal_KeyIntEnable)中的语句关掉
7.osal_pwrmgr_init(void)中pwrmgr_attribute.pwrmgr_device=PWRMGR_BATTERY

在网上搜了不少方法,也参考了TI官方的文档“Power Management For The CC2530.pdf”,以及“Measuring Power Consumption of CC2530 with Z-Stack(swra292AN079).PDF”。
按照上述设置,感觉终端节点并未进入睡眠状态,能不能给一个比较详细的设置方法呢?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分