7.26. SOFT_POWER_OFF
Overview
提供软关机低功耗接口使用方法和常见问题。
7.26.1. 应用示例
示例演示:
电源配置
关机唤醒IO选择配置(边缘选择等)
关机前的IO配置
电源和唤醒初始化
调用power_set_soft_poweroff关机。
example: 进入 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_SOFT_POWER_OFF_TEST_DEMO
。
Note
1.board.c 添加电源配置和IO唤醒配置参数,并添加到初始化。
//(1)----------------------------------电源配置参数------------------------------------------// static const struct low_power_param power_param = { .config = TCFG_LOWPOWER_LOWPOWER_SEL, .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持(不需要需修改) .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.4V 3.6V .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V .vdc14_dcdc = TRUE, //打开内部1.4VDCDC,关闭则用外部 .vdc14_lev = VDC14_VOL_SEL_LEVEL, //VDD1.4V配置 .sysvdd_lev = SYSVDD_VOL_SEL_LEVEL, //内核、sdram电压配置 .vlvd_enable = TRUE, //TRUE电压复位使能 .vlvd_value = VLVD_SEL_25V, //低电压复位电压值 }; //(2)-------------------------------- 唤醒IO配置 -------------------------------// /*******************可以使用多个IO,但是一组IO只能使用一个IO口,如PA组只能使用PA0-PA15其中一个***************/ //#define PORT_VCC33_CTRL_IO IO_PORTA_03 //VCC33 DCDC控制引脚,该引脚控制DCDC器件输出的3.3V连接芯片HPVDD、VDDIO、VDD33 #define PORT_WAKEUP_IO0 IO_PORTB_01 //软关机和休眠的唤醒引脚0 #define PORT_WAKEUP_IO1 IO_PORTA_01 //软关机和休眠的唤醒引脚1 //软关机硬件唤醒IO-0相关配置:PORT_WAKEUP_IO0 static const struct port_wakeup port0 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = 0x1, //保留参数 .iomap = PORT_WAKEUP_IO0, //唤醒IO口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO或睡眠唤醒,不需要写0 }; //软关机硬件唤醒IO-1相关配置:PORT_WAKEUP_IO1 static const struct port_wakeup port1 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = 0x2, //保留参数 .iomap = PORT_WAKEUP_IO1, //唤醒IO口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO或睡眠唤醒,不需要写0 }; //(3)-------------------------------- 保留项配置 -------------------------------// //无需更改 static const struct sub_wakeup sub_wkup = { .attribute = BLUETOOTH_RESUME, }; //无需更改 static const struct charge_wakeup charge_wkup = { .attribute = BLUETOOTH_RESUME, }; //唤醒参数配置 static const struct wakeup_param wk_param = { .port[0] = &port0,//配置IO组0 .port[1] = &port1,//配置IO组1 .sub = &sub_wkup, .charge = &charge_wkup, .lpres = NULL,//当使用正常工作时可长按复位功能,详情longpress例子 }; //(4)-------------------------------- 关机前IO配置 -------------------------------// /*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ static void board_set_soft_poweroff(void) { u32 IO_PORT; JL_PORT_FLASH_TypeDef *gpio[] = {JL_PORTA, JL_PORTB, JL_PORTC, JL_PORTD, JL_PORTE, JL_PORTF, JL_PORTG, JL_PORTH}; for (u8 p = 0; p < 8; ++p) { //flash sdram PD PE PF PG口不能进行配置,由内部完成控制 if (gpio[p] == JL_PORTD || gpio[p] == JL_PORTE || gpio[p] == JL_PORTF || gpio[p] == JL_PORTG) { continue; } for (u8 i = 0; i < 16; ++i) { IO_PORT = IO_PORTA_00 + p * 16 + i; gpio_set_pull_up(IO_PORT, 0); gpio_set_pull_down(IO_PORT, 0); gpio_set_direction(IO_PORT, 1); gpio_set_die(IO_PORT, 0); gpio_set_dieh(IO_PORT, 0); gpio_set_hd(IO_PORT, 0); gpio_set_hd1(IO_PORT, 0); gpio_latch_en(IO_PORT, 1); } } //尽量不能维持高电平(注意高电平功耗大),当软关机之后需要维持电平,则一并修改isd_config_rule.c文件的#PORT_INPUT和#PORT_OUTPUT配置才能在复位后也能维持所需电平 //DCDC电源类配置,软关机后IO只能低电平(高电平功耗大),因此需要电源高电平使能,低电平禁能,比如摄像头电源或LCD背光电源和芯片的HPVDD、VDDIO、VDD33等 #ifdef PORT_VCC33_CTRL_IO gpio_latch_en(PORT_VCC33_CTRL_IO, 0);//不锁存IO gpio_direction_output(PORT_VCC33_CTRL_IO, 0);//先拉低 gpio_set_pull_up(PORT_VCC33_CTRL_IO, 0);//关上拉 gpio_set_pull_down(PORT_VCC33_CTRL_IO, 1);//开下拉 gpio_set_direction(PORT_VCC33_CTRL_IO, 1);//设置输入 gpio_set_die(PORT_VCC33_CTRL_IO, 0);//关数字 gpio_set_dieh(PORT_VCC33_CTRL_IO, 0);//关p33相关 gpio_latch_en(PORT_VCC33_CTRL_IO, 1);//锁存IO状态 #endif } //(5)-------------------------------- 电源和唤醒初始化 -------------------------------// //电源初始化 static void board_power_init(void) { //DCDC电源类配置,开启后IO使能为高电平打开电源,比如摄像头电源或LCD背光电源和芯片的HPVDD、VDDIO、VDD33等 #ifdef PORT_VCC33_CTRL_IO gpio_direction_output(PORT_VCC33_CTRL_IO, 1); gpio_set_pull_up(PORT_VCC33_CTRL_IO, 1); gpio_set_pull_down(PORT_VCC33_CTRL_IO,0); #endif power_init(&power_param);//系统相关电源初始化 power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, NULL, NULL, board_set_soft_poweroff);//注册关机前回调函数 power_keep_state(POWER_KEEP_RESET);//0, POWER_KEEP_DACVDD | POWER_KEEP_RTC | POWER_KEEP_RESET ,//关机或睡眠后需要保持的功能 #ifdef CONFIG_OSC_RTC_ENABLE power_keep_state(POWER_KEEP_RTC);//当有RTC时,关机或睡眠后RTC继续维持走时 #endif power_wakeup_init(&wk_param);//唤醒参数初始化 } void board_init() { #ifdef CONFIG_OSC_RTC_ENABLE rtc_early_init(1);//使用外接RTC晶振打开CONFIG_OSC_RTC_ENABLE宏,则RTC时间为晶振计时计数 #else rtc_early_init(0);//不使用外接RTC晶振,则RTC时间为软件定时计数 #endif board_power_init(); }
在board_power_init的power_keep_state函数参数为关机要保持的功能 ,VMC手动复位:POWER_KEEP_RESET,DAC电源:POWER_KEEP_DACVDD,RTC走时:POWER_KEEP_RTC,需要则在传参或上即可。
关机函数之一: void power_set_soft_poweroff(void)
。
唤醒原因函数: int system_reset_reason_get(void)
, IO唤醒则函数返回值为 SYS_RST_PORT_WKUP
,各项原因文件: system_reset_reason.h
,
多IO唤醒原因获取函数: apps/common/system/system_reset_reason.c
文件的 int system_wakeup_port_get(void)
,当唤醒原因为IO唤醒则该函数返回>0(不是IO唤醒则小于0),使用返回值的位0到7来判断唤醒组,
对应值为board_xxx.c(如上述代码区域)的 static const struct wakeup_param wk_param
的port[x]参数,返回值的位0为1,即0x1,则对应port[0]的IO;返回值的位1为1,即0x2,则对应port[1]的IO;返回值的位2为1,即0x4,则对应port[2]的IO,以此类推。
//多个IO唤醒配置 static const struct port_wakeup port0 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = BLUETOOTH_RESUME, //保留参数 .iomap = IO_PORTA_00, //唤醒口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO唤醒,不需要写0 }; static const struct port_wakeup port1 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = BLUETOOTH_RESUME, //保留参数 .iomap = IO_PORTA_01, //唤醒口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO唤醒,不需要写0 }; static const struct port_wakeup port2 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = BLUETOOTH_RESUME, //保留参数 .iomap = IO_PORTA_02, //唤醒口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO唤醒,不需要写0 }; //... static const struct wakeup_param wk_param = { .port[0] = &port0,//多个IO唤醒配置则port从0开始 .port[1] = &port1, .port[2] = &port2, .sub = &sub_wkup, .charge = &charge_wkup, .lpres = &lpres_port, };
唤醒IO配置:如 static const struct port_wakeup port0
的iomap变量,可以设置IO_PORTA_01到IO_PORTH_15,芯片是791x则还可以设置IO_PORT_USB_DMA和IO_PORT_USB_DPA,如在791x设置usb0(FUSB)插入唤醒,则应当设置在IO_PORT_USB_DMA,usb1(HUSB)不支持持IO唤醒。
static const struct port_wakeup port0 = { .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 .attribute = BLUETOOTH_RESUME, //保留参数 .iomap = IO_PORT_USB_DMA, //唤醒口选择 .low_power = POWER_SLEEP_WAKEUP|POWER_OFF_WAKEUP, //低功耗IO唤醒,不需要写0 }; //... static const struct wakeup_param wk_param = { .port[0] = &port0,//port从0开始 .sub = &sub_wkup, .charge = &charge_wkup, .lpres = &lpres_port, };
app_config.h
添加电源配置参数(步骤1的board.c
使用)
//*********************************************************************************// // 低功耗配置 // //*********************************************************************************// #define TCFG_LOWPOWER_BTOSC_DISABLE 0 #define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //该宏在睡眠低功耗才用到,此处设置为0 #define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_32V //正常工作的内部vddio电压值,一般使用外部3.3V,内部设置需比外部3.3V小 #define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_21V //软关机或睡眠的内部vddio最低电压值 #define VDC14_VOL_SEL_LEVEL VDC14_VOL_SEL_140V //内部的1.4V默认1.4V #define SYSVDD_VOL_SEL_LEVEL SYSVDD_VOL_SEL_126V //系统内核电压,默认1.26V
7.26.2. 常见问题
1.当需要按键触发关机时,在调用power_set_soft_poweroff()函数前最好先等待按键释放完全再调用关机函数。
2.由于内部上下拉电阻精度不高(10K左右),因此IO唤醒的硬件IO需要外接上下拉电阻,具体看看需求接上拉还是下拉,系统进软关机后会把内部的上下拉都关闭,因此需要硬件上芯片外部上下拉电阻维持IO状态。