我在运行idle_profile_nonos例程时,测试J12电流测试引脚的电流,发觉电流波动很大,按照例程输入sleep指令前和输入指令后测试的电流发觉没有什么明显的变化,而且输入sleep指令后终端就卡死了,按SW3想触发跳出LPDS也不知是否有反应,请问如何测试CC3200的低功耗性能
Terry Han:
实验室实际测试功耗记录(测试代码idle_profile_nonos):模式条件电流消耗测试图DatasheetM4 Active(80MHz)+NWP connect AP115.9mA图115.3mAM4 LPDS+NWP start but do nothing2282uA图2266uA M4 LPDS+NWP connect AP<1>3 600uA~2mA(Avr=900uA)图3 图4825uA M4 LPDS+NWP Hib<2>4 229uA图5120uAM4 Hib+NWP Hib510.65uA图64uA 备注:M4 LPDS(RAM-Retained)/Hib(RAM-Not Retained) 唤醒:RTC+GPIO(UART复用GPIO)M4 Active+NWP connect AP =15.9mAM4 LPDS+NWP connect AP =600uA~2mA波动 大约平均功耗为800uA左右M4 LPDS+NWP start but do nothing即 sl_start但不连接AP =282uAM4 LPDS+NWP 进入Hib模式 229uA 注意此时网络已经断开,但是RAM还是保存的!M4 Hib+NWP 进入Hib模式 10.65uA(注意Hib模式下测试的电流消耗为CC3200+SPI_Flash的功耗,而Datasheet上4uA是不包括SPI_Flash的功耗)
Terry Han:
参考如下代码
// 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 addressunsigned 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 voidDisplayBanner(){ 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 voidBoardInit(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);}