不过掉电状态的时候,RAM中的数据都会都是,所以掉电状态不能进行调试,需要直接将固件烧录到代码中。
经过一番尝试,在RGB-LED灯的实例基础上,结合掉电状态进行测试。
预期如下:
1. 板子启动后,RGB-LED呼吸灯自动启动
2. 按PBUTN按键 16秒以后,RGB-LED呼吸灯停止
3. 一会后,再按PBUTN或者WBUTN按键0.5秒以上,则RGB-LED呼吸灯恢复。
实际参考的两个例子如下:
1. samples/RGB-LED
2. samples/drivers/butn
合并后的代码如下:
- /*
- * Copyright (c) 2021 HPMicro
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
- #include <stdio.h>
- #include "board.h"
- #include "hpm_debug_console.h"
- #include "hpm_clock_drv.h"
- #include "hpm_pwm_drv.h"
- #include "hpm_butn_drv.h"
- #include "hpm_bpor_drv.h"
- #define TEST_BPOR HPM_BPOR
- #define TEST_BPOR_POWER_ON_CAUSE bpor_power_on_cause_wbutn
- #ifdef BOARD_RED_PWM
- #define RED_PWM_IRQ BOARD_RED_PWM_IRQ
- #define RED_PWM BOARD_RED_PWM
- #define RED_PWM_CMP BOARD_RED_PWM_CMP
- #define RED_PWM_CMP_INITIAL_ZERO BOARD_RED_PWM_CMP_INITIAL_ZERO
- #define RED_PWM_OUT BOARD_RED_PWM_OUT
- #define RED_PWM_CLOCK_NAME BOARD_RED_PWM_CLOCK_NAME
- #else
- #error BOARD_RED_PWM needs to be defined
- #endif
- #ifdef BOARD_GREEN_PWM
- #define GREEN_PWM_IRQ BOARD_GREEN_PWM_IRQ
- #define GREEN_PWM BOARD_GREEN_PWM
- #define GREEN_PWM_CMP BOARD_GREEN_PWM_CMP
- #define GREEN_PWM_CMP_INITIAL_ZERO BOARD_GREEN_PWM_CMP_INITIAL_ZERO
- #define GREEN_PWM_OUT BOARD_GREEN_PWM_OUT
- #define GREEN_PWM_CLOCK_NAME BOARD_BLUE_PWM_CLOCK_NAME
- #else
- #error BOARD_GREEN_PWM needs to be defined
- #endif
- #ifdef BOARD_BLUE_PWM
- #define BLUE_PWM_IRQ BOARD_BLUE_PWM_IRQ
- #define BLUE_PWM BOARD_BLUE_PWM
- #define BLUE_PWM_CMP BOARD_BLUE_PWM_CMP
- #define BLUE_PWM_CMP_INITIAL_ZERO BOARD_BLUE_PWM_CMP_INITIAL_ZERO
- #define BLUE_PWM_OUT BOARD_BLUE_PWM_OUT
- #define BLUE_PWM_CLOCK_NAME BOARD_BLUE_PWM_CLOCK_NAME
- #else
- #error BOARD_BLUE_PWM needs to be defined
- #endif
- #define PWM_PERIOD_IN_MS (1U)
- #define PWM_DUTY_STEP_COUNT (1000U)
- typedef struct {
- PWM_Type *pwm;
- uint32_t reload;
- uint32_t step;
- bool pwm_cmp_initial_zero;
- uint8_t pwm_irq;
- uint8_t pwm_cmp;
- uint8_t pwm_ch;
- } led_pwm_t;
- typedef enum {
- red = BOARD_RGB_RED,
- green = BOARD_RGB_GREEN,
- blue = BOARD_RGB_BLUE
- } led_index_t;
- led_pwm_t leds[3];
- uint32_t reload;
- volatile bool do_update;
- volatile led_index_t current;
- void pwm_isr(void)
- {
- pwm_clear_status(leds[current].pwm, PWM_IRQ_HALF_RELOAD);
- do_update = true;
- }
- SDK_DECLARE_EXT_ISR_M(RED_PWM_IRQ, pwm_isr)
- #if (GREEN_PWM_IRQ != RED_PWM_IRQ)
- SDK_DECLARE_EXT_ISR_M(GREEN_PWM_IRQ, pwm_isr)
- #endif
- #if (BLUE_PWM_IRQ != RED_PWM_IRQ) && (GREEN_PWM_IRQ != BLUE_PWM_IRQ)
- SDK_DECLARE_EXT_ISR_M(BLUE_PWM_IRQ, pwm_isr)
- #endif
- void config_pwm(PWM_Type * ptr, uint8_t pin, uint8_t cmp_index, uint32_t reload, bool cmp_initial_zero, uint8_t hw_event_cmp, bool off_level_high)
- {
- pwm_cmp_config_t cmp_config = {0};
- pwm_config_t pwm_config = {0};
- pwm_stop_counter(ptr);
- pwm_get_default_pwm_config(ptr, &pwm_config);
- pwm_get_default_cmp_config(ptr, &cmp_config);
- pwm_config.enable_output = false;
- pwm_config.dead_zone_in_half_cycle = 0;
- pwm_config.invert_output = !(cmp_initial_zero && off_level_high);
- /*
- * reload and start counter
- */
- pwm_set_reload(ptr, 0, reload);
- pwm_set_start_count(ptr, 0, 0);
- cmp_config.mode = pwm_cmp_mode_output_compare;
- cmp_config.cmp = cmp_initial_zero ? 0 : reload + 1;
- cmp_config.update_trigger = pwm_shadow_register_update_on_modify;
- /* config initial compare value which should take affect immediately */
- pwm_config_cmp(ptr, cmp_index, &cmp_config);
- /* update trigger type so that compare value will be updated on hardware event (RELOAD) */
- cmp_config.update_trigger = pwm_shadow_register_update_on_hw_event;
- /*
- * config pwm as output driven by cmp
- */
- if (status_success != pwm_setup_waveform(ptr, pin, &pwm_config, cmp_index, &cmp_config, 1)) {
- printf("failed to setup waveform\n");
- while(1);
- }
- /*
- * config hw event
- */
- cmp_config.cmp = reload - 1;
- cmp_config.update_trigger = pwm_shadow_register_update_on_hw_event;
- pwm_load_cmp_shadow_on_match(ptr, hw_event_cmp, &cmp_config);
- }
- void turn_on_rgb_led(led_index_t i)
- {
- PWM_Type *pwm;
- uint8_t pwm_cmp;
- uint32_t initial;
- /* make sure cmp value is set to initial, before enabling output */
- pwm = leds[i].pwm;
- pwm_cmp = leds[i].pwm_cmp;
- initial = leds[i].pwm_cmp_initial_zero ? 0 : (leds[i].reload + 1);
- pwm_update_raw_cmp_edge_aligned(pwm, pwm_cmp, initial);
- board_enable_output_rgb_led(i);
- }
- void turn_off_rgb_led(led_index_t i)
- {
- board_disable_output_rgb_led(i);
- }
- void update_rgb_led(void)
- {
- uint32_t duty;
- bool increase_step = true;
- PWM_Type *pwm;
- uint32_t reload, pwm_cmp, step;
- step = leds[current].step;
- reload = leds[current].reload;
- pwm = leds[current].pwm;
- pwm_cmp = leds[current].pwm_cmp;
- duty = step;
- pwm_enable_irq(pwm, PWM_IRQ_HALF_RELOAD);
- turn_on_rgb_led(current);
- while(!(!increase_step && (duty < 2 * step))) {
- if (increase_step && (duty + step > reload)) {
- increase_step = false;
- }
- if (increase_step) {
- duty += step;
- } else {
- duty -= step;
- }
- while (!do_update) {
- ;
- }
- pwm_update_raw_cmp_edge_aligned(pwm, pwm_cmp, duty);
- do_update = false;
- }
- turn_off_rgb_led(current);
- pwm_disable_irq(pwm, PWM_IRQ_HALF_RELOAD);
- }
- int main(void){
- uint32_t freq;
- uint32_t hw_event_cmp;
- board_init();
- init_butn_pins();
- board_init_rgb_pwm_pins();
- printf("rgb led example\n");
- freq = clock_get_frequency(RED_PWM_CLOCK_NAME);
- leds[red].reload = freq / 1000 * PWM_PERIOD_IN_MS - 1;
- leds[red].pwm = RED_PWM;
- leds[red].pwm_ch = RED_PWM_OUT;
- leds[red].pwm_cmp = RED_PWM_CMP;
- leds[red].pwm_cmp_initial_zero = RED_PWM_CMP_INITIAL_ZERO;
- leds[red].pwm_irq = RED_PWM_IRQ;
- freq = clock_get_frequency(GREEN_PWM_CLOCK_NAME);
- leds[green].reload = freq / 1000 * PWM_PERIOD_IN_MS - 1;
- leds[green].pwm = GREEN_PWM;
- leds[green].pwm_ch = GREEN_PWM_OUT;
- leds[green].pwm_cmp = GREEN_PWM_CMP;
- leds[green].pwm_cmp_initial_zero = GREEN_PWM_CMP_INITIAL_ZERO;
- leds[green].pwm_irq = GREEN_PWM_IRQ;
- freq = clock_get_frequency(BLUE_PWM_CLOCK_NAME);
- leds[blue].reload = freq / 1000 * PWM_PERIOD_IN_MS - 1;
- leds[blue].pwm = BLUE_PWM;
- leds[blue].pwm_ch = BLUE_PWM_OUT;
- leds[blue].pwm_cmp = BLUE_PWM_CMP;
- leds[blue].pwm_cmp_initial_zero = BLUE_PWM_CMP_INITIAL_ZERO;
- leds[blue].pwm_irq = BLUE_PWM_IRQ;
- hw_event_cmp = PWM_SOC_CMP_MAX_COUNT;
- for (uint8_t i = 0; i < PWM_SOC_CMP_MAX_COUNT; i++) {
- if ((i != RED_PWM_CMP) && (i != GREEN_PWM_CMP) && (i != BLUE_PWM_CMP)) {
- continue;
- }
- hw_event_cmp = i;
- break;
- }
- if (hw_event_cmp == PWM_SOC_CMP_MAX_COUNT) {
- printf("Failed to find a comparator for hardware event\n");
- while (1) {
- };
- }
- for (uint8_t i = 0; i < ARRAY_SIZE(leds); i++) {
- leds[i].step = leds[i].reload / PWM_DUTY_STEP_COUNT;
- config_pwm(leds[i].pwm, leds[i].pwm_ch, leds[i].pwm_cmp, leds[i].reload, leds[i].pwm_cmp_initial_zero, hw_event_cmp, BOARD_LED_OFF_LEVEL);
- pwm_start_counter(leds[i].pwm);
- intc_m_enable_irq_with_priority(leds[i].pwm_irq, 1);
- }
- bpor_select_power_on_cause(TEST_BPOR, TEST_BPOR_POWER_ON_CAUSE);
- printf("Please press PBUTN 16s to enter power down mode, then press PBUTN or WBUTN 0.5s to wake up from power down mode.\n");
- current = red;
- while(1) {
- update_rgb_led();
- do_update = false;
- current = (current + 1) % (blue + 1);
- }
- return 0;
- }
上述代码中,RGB-LED的呼吸灯模式,主要就是启用了PWM来进行控制,核心设置为:
- #define PWM_PERIOD_IN_MS (1U)
- #define PWM_DUTY_STEP_COUNT (1000U)
- freq = clock_get_frequency(RED_PWM_CLOCK_NAME);
- leds[red].reload = freq / 1000 * PWM_PERIOD_IN_MS - 1;
- leds[red].pwm = RED_PWM;
- leds[red].pwm_ch = RED_PWM_OUT;
- leds[red].pwm_cmp = RED_PWM_CMP;
- leds[red].pwm_cmp_initial_zero = RED_PWM_CMP_INITIAL_ZERO;
- leds[red].pwm_irq = RED_PWM_IRQ;
然后在update_rgb_led()中,启用对应的pwm输出,从而控制对应的灯。
而掉电模式,则主要由如下部分配置和处理:
- #define TEST_BPOR HPM_BPOR
- #define TEST_BPOR_POWER_ON_CAUSE bpor_power_on_cause_wbutn
- bpor_select_power_on_cause(TEST_BPOR, TEST_BPOR_POWER_ON_CAUSE);
将以上代码编译烧录到开发板,然后使用数字功率计测试不同状态下的运行功耗。
1. 正常运行情况下:
此时的运行电压为4.8V,电流为220+-2ma
2. 掉电状态:
按PBUTN16秒以上,呼吸灯熄灭,进入掉电状态:
此时的运行电压为4.8V,电流为76+-1ma
3. 恢复正常运行:
按PBUTN或者WBUTN 0.5秒以上,系统恢复,呼吸灯重新开始闪烁
此时的运行电压为4.8V,电流为220+-2ma
具体的操作过程视频如下:
通过上面的测试步骤,可以清晰得到,掉电状态下,系统功耗约为正常运行状态下的1/3。
因为上述测试,仅为PWM电量RGB-LED,所以功耗比不是特别大。
如果是运行更多的外设,功耗更大的情况下,那么就会更加的明显。
后续会进一步测试,获得更多的数据。