微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI WIFI设计交流 > 关于CC3200低功耗性能测试问题请教TI技术支持

关于CC3200低功耗性能测试问题请教TI技术支持

时间:10-02 整理:3721RD 点击:

我在运行idle_profile_nonos例程时,测试J12电流测试引脚的电流,发觉电流波动很大,按照例程输入sleep指令前和输入指令后测试的电流发觉没有什么明显的变化,而且输入sleep指令后终端就卡死了,按SW3想触发跳出LPDS也不知是否有反应,请问如何测试CC3200的低功耗性能

实验室实际测试功耗记录(测试代码idle_profile_nonos):
模式
条件
电流消耗
测试图
Datasheet
M4 Active(80MHz)+NWP connect AP
1
15.9mA
图1
15.3mA
M4 LPDS+NWP start but do nothing
2
282uA
图2
266uA M4 LPDS+NWP connect AP<1>
3 600uA~2mA(Avr=900uA)
图3 图4
825uA M4 LPDS+NWP Hib<2>
4 229uA
图5
120uA
M4 Hib+NWP Hib
5
10.65uA
图6
4uA 备注:M4 LPDS(RAM-Retained)/Hib(RAM-Not Retained) 唤醒:RTC+GPIO(UART复用GPIO)
M4 Active+NWP connect AP =15.9mA
M4 LPDS+NWP connect AP =600uA~2mA波动 大约平均功耗为800uA左右
M4 LPDS+NWP start but do nothing即 sl_start但不连接AP =282uA
M4 LPDS+NWP 进入Hib模式 229uA 注意此时网络已经断开,但是RAM还是保存的!
M4 Hib+NWP 进入Hib模式 10.65uA(注意Hib模式下测试的电流消耗为CC3200+SPI_Flash的功耗,而Datasheet上4uA是不包括SPI_Flash的功耗)

参考如下代码

// Standard includes
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

//driverlib includes
#include "hw_ints.h"
#include "hw_types.h"
#include "hw_memmap.h"
#include "interrupt.h"
#include "prcm.h"
#include "utils.h"
#include "rom.h"
#include "rom_map.h"


// Simplelink includes
#include "simplelink.h"

//middleware includes
#include "cc_types.h"
#include "cc_pm.h"
#include "cc_pm_ops.h"

// Common interface includes
#include "uart_if.h"
#include "udma_if.h"
//---------------------------------
//#include "network_if.h"
#include "utils_if.h."
//---------------------------------
#include "pinmux.h"
#include "common.h"

#define APPLICATION_VERSION "1.1.1"

//
// Values for below macros shall be modified as per access-point(AP) properties
// SimpleLink device will connect to following AP when application is executed
//
#define GPIO_SRC_WKUP PRCM_LPDS_GPIO13
#define LPDS_DUR_SEC 5
#define FOREVER 1
#define BUFF_SIZE 1472

#define WK_LPDS 0 /*Wake from LPDS */
#define WK_HIB 1 /*Wake from Hibernate */

/* commands */
#define APP_SLEEP 0x8
#define APP_SEND 0x10
#define APP_RECV 0x20
#define APP_ERROR 0x40

/* udp transmission related parameters */
#define IP_ADDR 0xFFFFFFFF /* broadcast */
#define PORT_NUM 5001
#define BUF_SIZE 1400
#define UDP_PACKET_COUNT 1000

unsigned char APconnect=1; //测试sl_start 后 连接AP和不连接AP的功耗
unsigned char LPDS=1;

enum ap_events{
EVENT_CONNECTION = 0x1,
EVENT_DISCONNECTION = 0x2,
EVENT_IP_ACQUIRED = 0x4,
WDOG_EXPIRED = 0x8,
CONNECTION_FAILED = 0x10
};

//****************************************************************************
// LOCAL FUNCTION PROTOTYPES
//****************************************************************************
void sl_WlanEvtHdlr(SlWlanEvent_t *pSlWlanEvent);
void sl_NetAppEvtHdlr(SlNetAppEvent_t *pNetAppEvent);
static void DisplayBanner();
static long WlanConnect();
void WlanDisconnect();
static void BoardInit();
void SwitchToStaMode(int iMode);

//*****************************************************************************
// GLOBAL VARIABLES -- Start
//*****************************************************************************
#ifndef USE_TIRTOS
#if defined(ccs) || defined(gcc)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif
#endif

unsigned long g_ulIpAddr = 0;
unsigned long g_ulStatus = 0;
char g_cErrBuff[100];
unsigned long g_ulDestinationIp = IP_ADDR; // Client IP address
unsigned int g_uiPortNum = PORT_NUM;
unsigned long g_ulPacketCount = UDP_PACKET_COUNT;
char g_cBsdBuf[BUF_SIZE];

//*****************************************************************************
// GLOBAL VARIABLES -- End
//*****************************************************************************

//*****************************************************************************
// Local Function Prototypes
//*****************************************************************************
extern void lp3p0_setup_power_policy(int power_policy);
extern int platform_init();
extern int set_rtc_as_wk_src(int pwr_mode, unsigned long time_interval,
bool is_periodic);
extern int set_gpio_as_wk_src(int pwr_mode, unsigned long wk_pin,
unsigned long trigger_type);
extern void set_host_irq_as_lpds_wk_src();

//*****************************************************************************
//
//! DisplayBanner
//!
//! \param none
//!
//! \return none
//!
//*****************************************************************************
static void
DisplayBanner()
{
UART_PRINT("\n\n\n\r");
UART_PRINT("\t\t *********************************************\n\r");
UART_PRINT("\t\t CC3200 Idle Profile Non Os Application \n\r");
UART_PRINT("\t\t *********************************************\n\r");
UART_PRINT("\n\n\n\r");

}

//*****************************************************************************
//
//! Application defined idle task hook
//!
//! \param none
//!
//! \return none
//!
//*****************************************************************************
void SimpleLinkSyncWaitLoopCallback()
{
//
// setting host IRQ as a wake up src
//
set_host_irq_as_lpds_wk_src(true);

//
// executing idle task
//
cc_idle_task_pm();

//
// removing host IRQ as a wake ip src
//
set_host_irq_as_lpds_wk_src(false);
}

//****************************************************************************
//
//! \brief This function handles WLAN events
//!
//! \param[in] pSlWlanEvent is the event passed to the handler
//!
//! \return None
//
//****************************************************************************
void sl_WlanEvtHdlr(SlWlanEvent_t *pSlWlanEvent)
{
switch(pSlWlanEvent->Event)
{
case SL_WLAN_CONNECT_EVENT:
UART_PRINT("C\n\r");
break;
case SL_WLAN_DISCONNECT_EVENT:
UART_PRINT("D\n\r");
break;
default:
break;
}
}

//****************************************************************************
//
//! \brief This function handles events for IP address acquisition via DHCP
//! indication
//!
//! \param[in] pNetAppEvent is the event passed to the handler
//!
//! \return None
//
//****************************************************************************
void sl_NetAppEvtHdlr(SlNetAppEvent_t *pNetAppEvent)
{
switch(pNetAppEvent->Event)
{
case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
case SL_NETAPP_IPV6_IPACQUIRED_EVENT:
g_ulIpAddr = pNetAppEvent->EventData.ipAcquiredV4.ip;
g_ulStatus = 1;
UART_PRINT("IP: %d.%d.%d.%d \n\r",(g_ulIpAddr&0xFF000000)>>24,
(g_ulIpAddr&0x00FF0000)>>16,
(g_ulIpAddr&0x0000FF00)>>8,
(g_ulIpAddr&0x000000FF));
break;
default:
break;
}
}

//*****************************************************************************
//
//! This function gets triggered when HTTP Server receives Application
//! defined GET and POST HTTP Tokens.
//!
//! \param pSlHttpServerEvent Pointer indicating http server event
//! \param pSlHttpServerResponse Pointer indicating http server response
//!
//! \return None
//!
//*****************************************************************************
void sl_HttpServerCallback(SlHttpServerEvent_t *pSlHttpServerEvent,
SlHttpServerResponse_t *pSlHttpServerResponse)
{
}

//*****************************************************************************
//
//! This function handles socket events indication
//!
//! \param[in] pSock - Pointer to Socket Event Info
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
{
//
// This application doesn't work w/ socket - Events are not expected
//

}

//****************************************************************************
//
//! \brief Connecting to a WLAN Accesspoint
//!
//! This function connects to the required AP (SSID_NAME) with Security
//! parameters specified in te form of macros at the top of this file
//!
//! \param[in] None
//!
//! \return status value
//!
//! \warning If the WLAN connection fails or we don't aquire an IP
//! address, It will be stuck in this function forever.
//
//****************************************************************************
static long WlanConnect()
{
SlSecParams_t secParams = {0};
long lRetVal = 0;

secParams.Key = (signed char*)SECURITY_KEY;
secParams.KeyLen = strlen(SECURITY_KEY);
secParams.Type = SECURITY_TYPE;

lRetVal = sl_WlanConnect((signed char*)SSID_NAME, strlen(SSID_NAME), 0, &secParams, 0);
ASSERT_ON_ERROR(lRetVal);

while(g_ulStatus != 1)
{
// Wait for WLAN Event
_SlNonOsMainLoopTask();
}

return SUCCESS;
}

//*****************************************************************************
//
//! Board Initialization & Configuration
//!
//! \param None
//!
//! \return None
//
//*****************************************************************************
static void
BoardInit(void)
{
/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS
//
// Set vector table base
//
#if defined(ccs) || defined(gcc)
IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)
IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif
//
// Enable Processor
//
MAP_IntMasterEnable();
MAP_IntEnable(FAULT_SYSTICK);

PRCMCC3200MCUInit();
}

//*****************************************************************************
//
//! Check the device mode and switch to STATION(STA) mode
//! restart the NWP to activate STATION mode
//!
//! \param iMode (device mode)
//!
//! \return None
//
//*****************************************************************************
void SwitchToStaMode(int iMode)
{
if(iMode != ROLE_STA)
{
sl_WlanSetMode(ROLE_STA);
MAP_UtilsDelay(80000);
sl_Stop(10);
MAP_UtilsDelay(80000);
sl_Start(NULL,NULL,NULL);
}

}

//*****************************************************************************
//
//! Parse the input string command
//!
//! \param buff is the input buffer cmd to be parsed
//! \param cmd is the pointer to the cmd code for the input command
//!
//!\return None
//
//*****************************************************************************
void ParseCmd(char* buff, signed char*cmd)
{
if(strcmp(buff, "sleep") == 0){
*cmd = APP_SLEEP;
}else if(strcmp(buff, "send") == 0){
*cmd = APP_SEND;
}else if(strcmp(buff, "recv") == 0){
*cmd = APP_RECV;
}else{
*cmd = APP_ERROR;
}
}


//****************************************************************************
//
//! Enter the HIBernate mode configuring the wakeup timer
//!
//! \param none
//!
//! This function
//! 1. Sets up the wakeup RTC timer
//! 2. Enables the RTC
//! 3. Enters into HIBernate
//!
//! \return None.
//
//****************************************************************************
void EnterHIBernate()
{
#define SLOW_CLK_FREQ (32*1024)
//
// Configure the HIB module RTC wake time
//
MAP_PRCMHibernateIntervalSet(5 * SLOW_CLK_FREQ);

//
// Enable the HIB RTC
//
// MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
//------------------------------------------------------------Hib模式下增加GPIO唤醒---------------------------------------------------------------
// PRCMHibernateWakeupSourceEnable入口参数
// PRCM_HIB_SLOW_CLK_CTR -PRCM_HIB_GPIO2 -PRCM_HIB_GPIO4 -PRCM_HIB_GPIO13 -PRCM_HIB_GPIO17 -PRCM_HIB_GPIO11 -PRCM_HIB_GPIO24 -PRCM_HIB_GPIO26
PRCMHibernateWakeupSourceEnable(PRCM_HIB_GPIO13);
PRCMHibernateWakeUpGPIOSelect(PRCM_HIB_GPIO13,PRCM_HIB_FALL_EDGE); //按键按下去产生上升沿,松开后产生下降沿!注意入口参数的顺序!
//------------------------------------------------------------------------------------------------------------------------------------------------

// DBG_PRINT("HIB: Entering HIBernate...\n\r");
UART_PRINT("Entering HIB\n\r");
MAP_UtilsDelay(80000);

//
// powering down SPI Flash to save power
//
Utils_SpiFlashDeepPowerDown();
//
// Enter HIBernate mode
//
MAP_PRCMHibernateEnter();
}

//****************************************************************************
// MAIN FUNCTION
//****************************************************************************
int main(void)
{
long lRetVal;
char cCmdBuff[20];
signed char cCmd = APP_SLEEP; //并非初始化为进入睡眠模式

SlSockAddrIn_t sAddr;
SlSockAddrIn_t sLocalAddr;
SlSockAddrIn_t sBrdAddr;
int iCounter;
int iAddrSize;
int iSockID;
int iStatus;
long lLoopCount = 0;
short sTestBufLen;
struct SlTimeval_t timeVal;

//
// Board Initialization
//
BoardInit();

//
// uDMA Initialization
//
UDMAInit();

//
// Configure the pinmux settings for the peripherals exercised
// Note: pinmux has been modified after the output from pin mux tools
// to enable sleep clk for the peripherals exercised
//
PinMuxConfig();

//
// Initialize the platform
//
platform_init(); //低功耗IO漏电流等处理

//
// Initialise the UART terminal
//
InitTerm();

//
// Display banner
//
DisplayBanner();

//
// starting the simplelink
//
// lRetVal = sl_Start(0, 0, 0);
lRetVal = sl_Start(NULL, NULL, NULL); //运行到这就无法调试了 Warning: **ERROR**: Unable to start execution 0x00000001
if (lRetVal < 0)
{
UART_PRINT("Failed to start the device \n\r");
LOOP_FOREVER();
}
//-------------------------------------------------测试--------------------------------------
if (APconnect==1)
{
//
// Swtich to STA mode if device is not
//
SwitchToStaMode(lRetVal);

//
// set connection policy
//
sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0, 0, 0, 0, 0), NULL, 0);
//
// Set the power management policy of NWP
// 并非通过下面方法设置NWP的低功耗模式!这只是nwp工作的模式!
lRetVal = sl_WlanPolicySet(SL_POLICY_PM, SL_NORMAL_POLICY, NULL, 0); //注意,设置NWP的电源模式,在nwp programming中4.6.1 Power Policy详细介绍
//Normal (Default) – Features the best tradeoff between traffic delivery time and power performance.
UART_PRINT("Trying to Connect to AP: %s ...\r\n",SSID_NAME);

//---------------------------------------------------连接AP-----------------------------------------------------
//Connecting to WLAN AP
//
lRetVal = WlanConnect();
if(lRetVal < 0)
{
UART_PRINT("Failed to establish connection w/ an AP \n\r");
LOOP_FOREVER();
}
//---------------------------------------------------------------------------------------------------------------
// filling the buffer
for (iCounter=0 ; iCounter<BUF_SIZE ; iCounter++)
{
g_cBsdBuf[iCounter] = (char)(iCounter % 10);
}
//---------------------------------------------------建立UDP的服务器-----------------------------------------------------
sTestBufLen = BUF_SIZE;
//filling the UDP server socket address
sLocalAddr.sin_family = SL_AF_INET;
sLocalAddr.sin_port = sl_Htons((unsigned short)PORT_NUM); //本地UDP的端口号
sLocalAddr.sin_addr.s_addr = 0;

//filling the UDP server socket address
sBrdAddr.sin_family = SL_AF_INET;
sBrdAddr.sin_port = sl_Htons((unsigned short)PORT_NUM); //目的UDP的端口号
sBrdAddr.sin_addr.s_addr = sl_Htonl((unsigned int)g_ulDestinationIp);

iAddrSize = sizeof(SlSockAddrIn_t);

// creating a UDP socket
iSockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0);

//------------------------------------------设置阻塞模式----------------------------------------
/* setting time out for socket recv */
timeVal.tv_sec = 5; // Seconds
timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resolution
sl_SetSockOpt(iSockID,SL_SOL_SOCKET,SL_SO_RCVTIMEO, (_u8 *)&timeVal, sizeof(timeVal)); //网络接收超时检查打开
//----------------------------------------------------------------------------------------------
// binding the UDP socket to the UDP server address
iStatus = sl_Bind(iSockID, (SlSockAddr_t *)&sLocalAddr, iAddrSize);
if( iStatus < 0 )
{
// error
sl_Close(iSockID);
ASSERT_ON_ERROR(iStatus);
}
//-------------------------------------------------------------------------------------------------------------------------
}
//--------------------------------------------------------------------------

//
// setting Apps power policy
//
// lp3p0_setup_power_policy(POWER_POLICY_STANDBY); //M4-core 进入LPDS 模式 一定把该模式下的唤醒源打开!
// lp3p0_setup_power_policy(POWER_POLICY_HIBERNATE); //M4-core 进入Hib 模式 不再使用!

UART_PRINT("enter one of the following command:\n\r");
UART_PRINT("sleep - for putting the system into LPDS mode\n\r");
UART_PRINT(" GPIO 13 and timer(5 sec) are the wk source configured\n\r");
UART_PRINT("recv - for receiving 1000 UDP packets\n\r");
UART_PRINT("send - for broadcasting 1000 UDP packets\n\r");

do{

UART_PRINT("cmd#");
//
// get cmd over UART
//
// GetCmd(cCmdBuff, 20); //阻塞CPU运行

//
// parse the command
//
// ParseCmd(cCmdBuff, &cCmd);

// if(cCmd == APP_SLEEP)
if(LPDS==1)
{

//
// set timer and gpio as wake src
//
// set_rtc_as_wk_src(WK_LPDS, LPDS_DUR_SEC, false); //测试LPDS功耗,不使用定时器唤醒,仅使用GPIO唤醒!
// set_gpio_as_wk_src(WK_LPDS, GPIO_SRC_WKUP, PRCM_LPDS_FALL_EDGE);
//------------------------------------------------------------------注意!---------------------------------------------------------------------------------------------
// set_gpio_as_wk_src(WK_HIB, GPIO_SRC_WKUP, PRCM_LPDS_FALL_EDGE); //必须设置进入Hib模式下的中断唤醒源,
//注意在sl_Stop(10)之前不要启动该语句,否则NWP在sl_Stop(10)之后就自动进入了Hib模式但是唤醒源并没设置OK,直接屏蔽该语句,用EnterHIBernate();即可
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//M4-LPDS+NWP-hib(带UART跳线帽RX/TX=3.3V)=10.6uA 拔掉跳线帽(CC3200-RX/TX=0.1V)=14.5uA
UART_PRINT("M4-LPDS+NWP-hib"); //将CC3200-RX引脚接到GND/VCC=3.3V电流下降到10.65uA;CC3200-TX引脚接到GND/VCC=3.3V电流不发生变化.
/* close socket & stop device */ //Tip:CC3200启动过程中电流在几十mA,但是进入LPDS/Hib模式后电流在uA级别,此时电流档位精度不够,
//此时快速将电流mA档位切换到uA档位,虽然此时J12已经断开,但是注意到J12后面有两个100uF电容在给
//CC3200供电,因此切换完成后电流再补充到电容两端及CC3200电流消耗!
//D5/D6 ON problem.J2 and J3 are shorted by default, so the GPIO 10 and GPIO 11 are pulled up to VCC.
// sl_Close(iSockID); // 关不关闭socket对功耗没有影响,NWP已经停止工作了,socket自然也就关闭了
// sl_Stop(10); 
UART_PRINT("Test\n\r"); // 改为sl_Stop(10)/sl_Stop(1)均可进入此低功耗模式;
// M4-hib+NWP-hib模式下sl_Stop(10)/sl_Stop(1)/sl_Stop(0)均可进入低功耗模式电流消耗为10uA~14uA左右
// MAP_UtilsDelay(80000); // 延时0.5s让串口的数据打印出来后,M4核再进入低功耗模式.
//
// powering down SPI Flash to save power
//
// Utils_SpiFlashDeepPowerDown(); 
// cc_idle_task_pm(); 
//-------------------------------------------------------------------------------------
// Stop the NWP driver
// lRetVal = Network_IF_DeInitDriver(); 
// if(lRetVal < 0)
// {
// UART_PRINT("Failed to stop SimpleLink Device\n\r");
// LOOP_FOREVER();
// }
//During Hib mode the entire SOC loses its state, including the MCU subsystem, the NWP subsystem
EnterHIBernate(); //Hib模式用这个进入低功耗,测试屏蔽掉sl_stop(10)即打开NWP连接AP情况下让M4进入Hib模式,测得功耗为10.65uA,与执行sl_stop(10)功耗一致!
//注意Hib模式下测试的电流消耗包括CC3200+SPI_Flash的功耗,而Datasheet上4uA是不包括SPI_Flash的功耗哦
//-------------------------------------------------------------------------------------
UART_PRINT("M4-Active+NWP-hib\n\r"); //测试程序从LPDS唤醒后从哪开始运行---此处!
}
else if(cCmd == APP_RECV)
{
lLoopCount = 0;
/// waits for 1000 packets from a UDP client
while (lLoopCount < g_ulPacketCount)
{
iStatus = sl_RecvFrom(iSockID, g_cBsdBuf, sTestBufLen, 0,( SlSockAddr_t *)&sAddr, (SlSocklen_t*)&iAddrSize );
if( iStatus < 0 )
{
//error
break;
}
lLoopCount++;
}
UART_PRINT("Recieved %u packets successfully \n\r",lLoopCount);
if(lLoopCount != g_ulPacketCount)
{
if(iStatus == SL_EAGAIN)
{
UART_PRINT("timed out\n\r");
}
else
{
UART_PRINT("recv error: %d\n\r", iStatus);
}
}
}
else if(cCmd == APP_SEND)
{
lLoopCount = 0;
// sending 1000 packets to the UDP server
while (lLoopCount < g_ulPacketCount)
{
// sending packet
iStatus = sl_SendTo(iSockID, g_cBsdBuf, sTestBufLen, 0,(SlSockAddr_t *)&sBrdAddr, iAddrSize);
if( iStatus <= 0 )
{
// error
UART_PRINT("send error\n\r");
break;
}
lLoopCount++;
}
UART_PRINT("Sent %u packets successfully\n\r",lLoopCount);
}
}while(FOREVER);
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top