适配并调通低功耗管理模块

This commit is contained in:
魔罗技术 2021-03-07 18:40:49 +08:00
parent fb73de238e
commit f118ab8e6b
27 changed files with 1034 additions and 112 deletions

186
README.md
View File

@ -1,21 +1,35 @@
# CodeBrick
## 介绍
一种无OS的MCU实用软件管理系统,包括任务轮询框架,命令管理器、低功耗管理、环形缓冲区等实用模块。
一种无OS的MCU实用软件框架,包括任务轮询管理,命令管理器、低功耗管理、环形缓冲区等实用模块。系统中广泛利用自定义段技术减少各个模块间的耦合关系,大大提供程序的可维护性。
### module模块
时间轮询框架,统一管理设备所有任务模块,使用例子:
## 主要功能
- 支持模块自动化管理,并提供不同优先等级初始化声明接口。
- 支持任务轮询管理,通过简单的宏声明即可实现,不需要复杂的声明调用。
- 支持低功耗管理,休眠与唤醒通知。
- 支持命令行解析,命令注册与执行。
- blink设备支持统一管理LED、震动马达、蜂鸣器
## 使用说明
1.使用此模块前需要系统提供滴答定时器,用于驱动任务轮询作业
完整的代码可以参考工程文件,系统开发平台如下:
MCUSTM32F401RET6
IDEIAR 7.4或者Keil MDK 4.72A
### 任务初始化及任务轮询管理(module)
使用此模块前需要系统提供滴答定时器用于驱动任务轮询作业。参考platform.c
```c
//定时器中断(提供系统滴答)
void timer_interrupt(void)
void SysTick_Handler(void)
{
systick_increase(SYS_TICK_INTERVAL); //增加系统节拍
}
```
2.任务初始化及注册(以按键扫描为例)
注册初始化入口及任务(参考自key_task.c)
```c
static void key_init(void)
@ -29,37 +43,56 @@ static void key_scan(void)
}
module_init("key", key_init); //注册按键初始化接口
task_register("key", key_scan, 20); //注册按键任务(20ms轮询1次)
driver_register("key", key_scan, 20); //注册按键任务(20ms轮询1次)
```
### 命令管理器(cli)
适用于设备间通信、在线调试、参数配置等, 使用例子(参考cli_task.c)
适用于在线调试、参数配置等(参考使用cli_task.c),用户可以通过串口输出命令行控制设备行为、查询设备状态等功能。
1. 定义命令行管理器
#### 命令格式
cli支持的命令行格式如下
<cmd name> < param1> < param2> < paramn> < \r\n >
<cmd name> ,< param1>, < param2>, < paramn>, < \r\n >
每行命令包含一个命令名称+命令参数(可选),命令名称及参数可以通过空格或者','进行分隔。
#### 系统默认命令
cli系统自带了2条默认命令分别是"?"与"help"命令,输入他们可以列出当前系统包含的命令列表,如下所示:
```C
? - alias for 'help'
help - list all command.
pm - Low power control command
reset - reset system
sysinfo - show system infomation.
```c
static cli_obj_t cli; /*命令行对象 */
```
2.命令行初始化及接口适配
#### 适配命令管理器
完整的例子可以参考cli_task.c.
```c
static cli_obj_t cli; /*命令管理器对象 */
/*
* @brief 命令行任务初始化
* @return none
*/
static void cli_task_init(void)
{
cli_port_t p = {tty.write, tty.read}; /*使用串口进行适配 */
cli_port_t p = {tty.write, tty.read}; /*读写接口 */
cli_init(&cli, &p); /*初始化命令行对象 */
cli_enable(&cli);
}
module_init("cli", cli_task_init);
```
3.命令行任务轮询
```c
cli_exec_cmd(&cli,"sysinfo"); /*显示系统信息*/
}
/*
* @brief 命令行任务处理
* @return none
@ -69,34 +102,123 @@ static void cli_task_process(void)
cli_process(&cli);
}
module_init("cli", cli_task_init);
task_register("cli", cli_task_process, 10); /*注册命令行任务*/
```
### comdef模块
包含常用宏定义,段定义、匿名类型等。
#### 命令注册
以复位命令为例(参考cmd_devinfo.c)
```C
#include "cli.h"
//...
/*
* @brief 复位命令
*/
int do_cmd_reset(struct cli_obj *o, int argc, char *argv[])
{
NVIC_SystemReset();
return 0;
}cmd_register("reset",do_cmd_reset, "reset system");
```
### 低功耗管理器(pm)
控制间歇运行降低系统功耗。其基本的工作原理是通过轮询系统中各个模块是否可以允许系统进入低功耗。实际上这是一种判决机制所有模块都具有有票否决权即只要有一个模块不允许休眠那么系统就不会进入休眠状态。pm模块在休眠前会统计出各个模块会返回最小允许休眠时长并以最小休眠时长为单位进行休眠。
#### 如何适配
使用前需要通过pm_init进行初始化适配并提供当前系统允许的最大休眠时间进入休眠的函数接口基本的接口定义如下
```C
/*低功耗适配器 ---------------------------------------------------------*/
typedef struct {
/**
* @brief 系统最大休眠时长(ms)
*/
unsigned int max_sleep_time;
/**
* @brief 进入休眠状态
* @param[in] time - 期待休眠时长(ms)
* @retval 实际休眠时长
* @note 休眠之后需要考虑两件事情,1个是需要定时起来给喂看门狗,否则会在休眠
* 期间发送重启.另外一件事情是需要补偿休眠时间给系统滴答时钟,否则会
* 造成时间不准。
*/
unsigned int (*goto_sleep)(unsigned int time);
}pm_adapter_t;
void pm_init(const pm_adapter_t *adt);
void pm_enable(void);
void pm_disable(void);
void pm_process(void);
```
完成的使用例子可以参考platform-lowpower.c默认情况下是禁用低功耗功能的读者可以去除工程中原来不带低功耗版本的platform.c并加入platform-lowpower.c文件进行编译即可使用。
#### 注册低功耗设备
以按键扫描为例,正常情况下,如果按键没有按下,那么系统休眠可以进入休眠状态,对按键功能是没有影响的。如果按键按下时,那么系统需要定时唤醒并轮询按键任务。
所以在一个低功耗系统下,为了不影响按键实时性需要处理好两个事情:
1. 系统休眠状态下,如果有按键按下,那系统系统应立即唤醒,以便处理接下来的扫描工作。
2. 如果按键按下时,系统可以进入休眠,但需要定时唤醒起来轮询按键任务。
对于第一种情况将按键配置为边沿中断唤醒即可以STM32F4为例(参考key_task.c),它支持外部中断唤醒功能。
```C
/*
* @brief 按键 io初始化
* PC0 -> key;
* @return none
*/
static void key_io_init(void)
{
/* Enable GPIOA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
gpio_conf(GPIOC, GPIO_Mode_IN, GPIO_PuPd_UP, GPIO_Pin_0);
//低功耗模式下,为了能够检测到按键,配置为中断唤醒
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource0);
exti_conf(EXTI_Line0, EXTI_Trigger_Falling, ENABLE);
nvic_conf(EXTI0_IRQn, 0x0F, 0x0F);
key_create(&key, readkey, key_event); /*创建按键*/
}
```
对于第二种情况可以通过pm_dev_register来处理当系统请求休眠时如果此时按键按下则返回下次唤醒时间即可如下面的例子所示。
```C
//参考key_task.c
#include "pm.h"
/*
* @brief 休眠通知
*/
static unsigned int key_sleep_notify(void)
{
return key_busy(&key) || readkey() ? 20 : 0; /* 非空闲时20ms要唤醒1次*/
} pm_dev_register("key", NULL, key_sleep_notify, NULL);
```
### blink模块
具有闪烁特性(led, motor, buzzer)的设备(led, motor, buzzer)管理
使用之前有两个注意事项:
使用步骤:
- 需要系统提供滴答时钟blick.c中是通过get_tick()接口获取依赖module模块
- 需要在任务中定时进行轮询
```c
//主程序入口
void main(void)
{
while (1) {
blink_dev_process(); //定时轮询
}
}
```
或者通过"module"模块的任务注册来实现
```c
task_register("blink", blink_dev_process, 50); //50ms轮询1次
```
***使用例子,以LED为例***
#### LED驱动
```c
blink_dev_t led; //定义led设备

View File

@ -7,7 +7,8 @@
*
* Change Logs:
* Date Author Notes
* 2015-07-03 Morro
* 2015-07-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-03-07 Morro <EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
******************************************************************************/
#ifndef _TTY_H_
@ -22,6 +23,7 @@ typedef struct {
unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read)(void *buf, unsigned int len);
bool (*tx_isfull)(void); /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool (*tx_isempty)(void); /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool (*rx_isempty)(void); /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}tty_t;

View File

@ -7,14 +7,13 @@
*
* Change Logs:
* Date Author Notes
*
* 2015-07-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#include "stm32f4xx.h"
#include "ringbuffer.h"
#include "tty.h"
#include "public.h"
#include <string.h>
#if (TTY_RXBUF_SIZE & (TTY_RXBUF_SIZE - 1)) != 0
#error "TTY_RXBUF_SIZE must be power of 2!"
#endif
@ -85,6 +84,12 @@ static bool tx_isfull(void)
return ring_buf_len(&rbsend) == TTY_TXBUF_SIZE;
}
/*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool tx_isempty(void)
{
return ring_buf_len(&rbsend) == 0;
}
/*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool rx_isempty(void)
{
@ -97,6 +102,7 @@ const tty_t tty = {
uart_write,
uart_read,
tx_isfull,
tx_isempty,
rx_isempty
};

View File

@ -59,6 +59,15 @@ void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeats)
}
}
/*
* @brief æ<EFBFBD>ж<EFBFBD>
*/
bool blink_dev_busy(blink_dev_t *dev)
{
return dev->ontime;
}
/*
* @brief blink<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] none
@ -75,7 +84,7 @@ void blink_dev_process(void)
dev->enable = true;
dev->ioctrl(true);
}
} else if(get_tick() - dev->tick < dev->offtime) { /**/
} else if(get_tick() - dev->tick < dev->offtime) {
if (dev->enable) {
dev->enable = false;
dev->ioctrl(false);
@ -92,3 +101,4 @@ void blink_dev_process(void)
}
}
}

View File

@ -8,6 +8,7 @@
* Change Logs:
* Date Author Notes
* 2019-04-01 Morro Initial version
* 2021-03-07 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>æ<EFBFBD>жϽӿ<EFBFBD>
******************************************************************************/
#ifndef _BLINK_H_
#define _BLINK_H_
@ -34,6 +35,8 @@ void blink_dev_create(blink_dev_t *dev, void (*ioctrl)(bool enable));
void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeat);
bool blink_dev_busy(blink_dev_t *dev);
void blink_dev_process(void);
#ifdef __cplusplus

View File

@ -40,6 +40,15 @@ bool key_create(key_t *key, int (*readkey)(void),
return 1;
}
/*******************************************************************************
* @brief æ<EFBFBD>ж<EFBFBD>
* @return none
******************************************************************************/
bool key_busy(key_t *k)
{
return k->tick != 0;
}
/*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>
* @return none

View File

@ -8,6 +8,7 @@
* Change Logs:
* Date Author Notes
* 2017-08-10 Morro Initial version
* 2021-03-07 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>æ<EFBFBD>жϽӿ<EFBFBD>
******************************************************************************/
#ifndef _KEY_H_
@ -47,6 +48,9 @@ typedef struct key_t {
bool key_create(key_t *key, int (*readkey)(void), /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
void (*event)(int type, unsigned int duration));
bool key_busy(key_t *k); /*æ<>ж<EFBFBD>*/
void key_scan_process(void); /*<2A><><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><E8B4A6>*/
#ifdef __cplusplus

View File

@ -7,19 +7,24 @@
*
* Change Logs:
* Date Author Notes
* 2021-01-17 Morro Initial version.
* 2021-03-02 Morro Initial version.
******************************************************************************/
#include "pm.h"
#include <stddef.h>
/**
* @brief pm<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @brief pm<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static const pm_adapter_t *pm_ctrl;
typedef struct {
const pm_adapter_t *adt;
bool enable;
}pm_watch_t;
static const pm_item_t pm_tbl_start SECTION("init.item.0");
static pm_watch_t pm_watch;
static const pm_item_t pm_tbl_end SECTION("init.item.2");
static const pm_item_t pm_tbl_start SECTION("pm.item.0");
static const pm_item_t pm_tbl_end SECTION("pm.item.2");
/*
* @brief ϵͳ<EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD><EFBFBD>
@ -28,7 +33,7 @@ static bool system_is_idle(void)
{
const pm_item_t *it;
for (it = &pm_tbl_start + 1; it < &pm_tbl_end; it++) {
if (!it->idle())
if (it->idle != NULL && !it->idle())
return false;
}
return true;
@ -40,25 +45,30 @@ static bool system_is_idle(void)
static void system_goto_sleep(void)
{
const pm_item_t *it;
const pm_adapter_t *adt;
unsigned int sleep_time;
unsigned int tmp;
unsigned int sleep_time = pm_ctrl->max_sleep_time;
adt = pm_watch.adt;
sleep_time = adt->max_sleep_time;
//<2F><><EFBFBD>ߴ<EFBFBD><DFB4><EFBFBD>
for (it = &pm_tbl_start + 1; it < &pm_tbl_end; it++) {
if (it->suspend == NULL)
if (it->sleep_notify == NULL)
continue;
it->suspend(&tmp); //<2F><><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>ڴ<EFBFBD><DAB4>´λ<C2B4><CEBB><EFBFBD>ʱ<EFBFBD><CAB1>
if (tmp < sleep_time) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
tmp = it->sleep_notify(); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>ڴ<EFBFBD><DAB4>´λ<C2B4><CEBB><EFBFBD>ʱ<EFBFBD><CAB1>
if (tmp && tmp < sleep_time) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
sleep_time = tmp;
}
pm_ctrl->goto_sleep(sleep_time);
adt->goto_sleep(sleep_time);
//<2F><><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD>
for (it = &pm_tbl_start + 1; it < &pm_tbl_end; it++) {
if (it->resume == NULL)
if (it->wakeup_notify == NULL)
continue;
it->resume();
it->wakeup_notify();
}
}
@ -68,7 +78,25 @@ static void system_goto_sleep(void)
*/
void pm_init(const pm_adapter_t *adt)
{
pm_ctrl = adt;
pm_watch.adt = adt;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>
* @retval none
*/
void pm_enable(void)
{
pm_watch.enable = true;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>
* @retval none
*/
void pm_disable(void)
{
pm_watch.enable = false;
}
/**
@ -77,7 +105,7 @@ void pm_init(const pm_adapter_t *adt)
*/
void pm_process(void)
{
if (!system_is_idle())
if (!pm_watch.enable || !system_is_idle())
return;
system_goto_sleep();
}

View File

@ -7,7 +7,7 @@
*
* Change Logs:
* Date Author Notes
* 2021-01-17 Morro Initial version.
* 2021-03-02 Morro Initial version.
******************************************************************************/
#ifndef _PM_H_
#define _PM_H_
@ -26,20 +26,20 @@ typedef struct {
const char *name;
/**
* @brief <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬(ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>pm_item_t<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @retval true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool (*idle)(void);
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[out] next_wakup_time - <EFBFBD>´λ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>λ:ms, 0 - <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
* @retval <EFBFBD>´λ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>λ:ms, 0 - <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
void (*suspend)(unsigned int *next_wakup_time);
unsigned int (*sleep_notify)(void);
/**
* @brief <EFBFBD>ָ<EFBFBD>
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
* @retval none
*/
void (*resume)(void);
void (*wakeup_notify)(void);
}pm_item_t;
/*<2A>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------------*/
@ -52,24 +52,32 @@ typedef struct {
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
* @param[in] time - <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(ms)
* @retval ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,1<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>δ<EFBFBD>ʱ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>׼<EFBFBD><EFBFBD>
*/
void (*goto_sleep)(unsigned int time);
unsigned int (*goto_sleep)(unsigned int time);
}pm_adapter_t;
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
* @param[in] name - <EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] idle - ָʾ<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] suspend - ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
* @param[in] resume - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
* @param[in] idle - ָʾ<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] sleep_notify - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL
* @param[in] wakeup_notify - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL
*/
#define pm_dev_register(name, idle, suspend, resume)\
__pm_item_register(name, idle, suspend, resume)
#define pm_dev_register(name, idle, sleep_notify, wakeup_notify)\
__pm_item_register(name, idle, sleep_notify, wakeup_notify)
void pm_init(const pm_adapter_t *adt);
void pm_enable(void);
void pm_disable(void);
void pm_process(void);
#endif

View File

@ -45,7 +45,7 @@
</option>
<option>
<name>MemFile</name>
<state>$TOOLKIT_DIR$\CONFIG\debugger\ST\STM32F405VG.ddf</state>
<state>$TOOLKIT_DIR$\CONFIG\debugger\ST\STM32F401xD.ddf</state>
</option>
<option>
<name>RunToEnable</name>
@ -85,7 +85,7 @@
</option>
<option>
<name>OCDynDriverList</name>
<state>STLINK_ID</state>
<state>JLINK_ID</state>
</option>
<option>
<name>OCLastSavedByProductVersion</name>
@ -117,7 +117,7 @@
</option>
<option>
<name>FlashLoadersV3</name>
<state>$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32F4xxx.board</state>
<state>$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32F401xD.board</state>
</option>
<option>
<name>OCImagesSuppressCheck1</name>
@ -603,7 +603,7 @@
</option>
<option>
<name>IjetCpuClockEdit</name>
<state>168.0</state>
<state>84.0</state>
</option>
<option>
<name>IjetSwoPrescalerList</name>
@ -844,7 +844,7 @@
</option>
<option>
<name>CCJLinkInterfaceRadio</name>
<state>0</state>
<state>1</state>
</option>
<option>
<name>OCJLinkAttachSlave</name>

View File

@ -89,7 +89,7 @@
</option>
<option>
<name>OGChipSelectEditMenu</name>
<state>STM32F405VG ST STM32F405VG</state>
<state>STM32F401xD ST STM32F401xD</state>
</option>
<option>
<name>GenLowLevelInterface</name>
@ -149,7 +149,7 @@
</option>
<option>
<name>GFPUDeviceSlave</name>
<state>STM32F405VG ST STM32F405VG</state>
<state>STM32F401xD ST STM32F401xD</state>
</option>
<option>
<name>FPU2</name>
@ -731,7 +731,7 @@
</option>
<option>
<name>IlinkIcfFile</name>
<state>$TOOLKIT_DIR$\config\linker\ST\stm32f405xG.icf</state>
<state>$TOOLKIT_DIR$\config\linker\ST\stm32f401xD.icf</state>
</option>
<option>
<name>IlinkIcfFileSlave</name>
@ -1941,6 +1941,9 @@
<file>
<name>$PROJ_DIR$\..\framework\module.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\framework\pm.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\framework\queue.c</name>
</file>
@ -2006,6 +2009,9 @@
<file>
<name>$PROJ_DIR$\..\user\cmd\cmd_devinfo.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\cmd\cmd_pm.c</name>
</file>
</group>
<group>
<name>task</name>
@ -2013,7 +2019,7 @@
<name>$PROJ_DIR$\..\user\task\cli_task.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\task\task_key.c</name>
<name>$PROJ_DIR$\..\user\task\key_task.c</name>
</file>
</group>
<file>
@ -2025,8 +2031,14 @@
<file>
<name>$PROJ_DIR$\..\user\main.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\platform - lowpower.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\platform.c</name>
<excluded>
<configuration>Debug</configuration>
</excluded>
</file>
<file>
<name>$PROJ_DIR$\..\user\public.c</name>

View File

@ -2117,6 +2117,9 @@
<file>
<name>$PROJ_DIR$\..\framework\module.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\framework\pm.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\framework\queue.c</name>
</file>
@ -2182,6 +2185,9 @@
<file>
<name>$PROJ_DIR$\..\user\cmd\cmd_devinfo.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\cmd\cmd_pm.c</name>
</file>
</group>
<group>
<name>task</name>
@ -2189,7 +2195,7 @@
<name>$PROJ_DIR$\..\user\task\cli_task.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\task\task_key.c</name>
<name>$PROJ_DIR$\..\user\task\key_task.c</name>
</file>
</group>
<file>
@ -2201,6 +2207,9 @@
<file>
<name>$PROJ_DIR$\..\user\main.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\platform - lowpower.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\user\platform.c</name>
</file>

View File

@ -0,0 +1,109 @@
/**
******************************************************************************
* @file stm32f4xx_dbgmcu.h
* @author MCD Application Team
* @version V1.8.0
* @date 04-November-2016
* @brief This file contains all the functions prototypes for the DBGMCU firmware library.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_DBGMCU_H
#define __STM32F4xx_DBGMCU_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver
* @{
*/
/** @addtogroup DBGMCU
* @{
*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup DBGMCU_Exported_Constants
* @{
*/
#define DBGMCU_SLEEP ((uint32_t)0x00000001)
#define DBGMCU_STOP ((uint32_t)0x00000002)
#define DBGMCU_STANDBY ((uint32_t)0x00000004)
#define IS_DBGMCU_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFFF8) == 0x00) && ((PERIPH) != 0x00))
#define DBGMCU_TIM2_STOP ((uint32_t)0x00000001)
#define DBGMCU_TIM3_STOP ((uint32_t)0x00000002)
#define DBGMCU_TIM4_STOP ((uint32_t)0x00000004)
#define DBGMCU_TIM5_STOP ((uint32_t)0x00000008)
#define DBGMCU_TIM6_STOP ((uint32_t)0x00000010)
#define DBGMCU_TIM7_STOP ((uint32_t)0x00000020)
#define DBGMCU_TIM12_STOP ((uint32_t)0x00000040)
#define DBGMCU_TIM13_STOP ((uint32_t)0x00000080)
#define DBGMCU_TIM14_STOP ((uint32_t)0x00000100)
#define DBGMCU_RTC_STOP ((uint32_t)0x00000400)
#define DBGMCU_WWDG_STOP ((uint32_t)0x00000800)
#define DBGMCU_IWDG_STOP ((uint32_t)0x00001000)
#define DBGMCU_I2C1_SMBUS_TIMEOUT ((uint32_t)0x00200000)
#define DBGMCU_I2C2_SMBUS_TIMEOUT ((uint32_t)0x00400000)
#define DBGMCU_I2C3_SMBUS_TIMEOUT ((uint32_t)0x00800000)
#define DBGMCU_CAN1_STOP ((uint32_t)0x02000000)
#define DBGMCU_CAN2_STOP ((uint32_t)0x04000000)
#define IS_DBGMCU_APB1PERIPH(PERIPH) ((((PERIPH) & 0xF91FE200) == 0x00) && ((PERIPH) != 0x00))
#define DBGMCU_TIM1_STOP ((uint32_t)0x00000001)
#define DBGMCU_TIM8_STOP ((uint32_t)0x00000002)
#define DBGMCU_TIM9_STOP ((uint32_t)0x00010000)
#define DBGMCU_TIM10_STOP ((uint32_t)0x00020000)
#define DBGMCU_TIM11_STOP ((uint32_t)0x00040000)
#define IS_DBGMCU_APB2PERIPH(PERIPH) ((((PERIPH) & 0xFFF8FFFC) == 0x00) && ((PERIPH) != 0x00))
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
uint32_t DBGMCU_GetREVID(void);
uint32_t DBGMCU_GetDEVID(void);
void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState);
void DBGMCU_APB1PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState);
void DBGMCU_APB2PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_DBGMCU_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,180 @@
/**
******************************************************************************
* @file stm32f4xx_dbgmcu.c
* @author MCD Application Team
* @version V1.8.0
* @date 04-November-2016
* @brief This file provides all the DBGMCU firmware functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_dbgmcu.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver
* @{
*/
/** @defgroup DBGMCU
* @brief DBGMCU driver modules
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup DBGMCU_Private_Functions
* @{
*/
/**
* @brief Returns the device revision identifier.
* @param None
* @retval Device revision identifier
*/
uint32_t DBGMCU_GetREVID(void)
{
return(DBGMCU->IDCODE >> 16);
}
/**
* @brief Returns the device identifier.
* @param None
* @retval Device identifier
*/
uint32_t DBGMCU_GetDEVID(void)
{
return(DBGMCU->IDCODE & IDCODE_DEVID_MASK);
}
/**
* @brief Configures low power mode behavior when the MCU is in Debug mode.
* @param DBGMCU_Periph: specifies the low power mode.
* This parameter can be any combination of the following values:
* @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode
* @arg DBGMCU_STOP: Keep debugger connection during STOP mode
* @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode
* @param NewState: new state of the specified low power mode in Debug mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DBGMCU_PERIPH(DBGMCU_Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
DBGMCU->CR |= DBGMCU_Periph;
}
else
{
DBGMCU->CR &= ~DBGMCU_Periph;
}
}
/**
* @brief Configures APB1 peripheral behavior when the MCU is in Debug mode.
* @param DBGMCU_Periph: specifies the APB1 peripheral.
* This parameter can be any combination of the following values:
* @arg DBGMCU_TIM2_STOP: TIM2 counter stopped when Core is halted
* @arg DBGMCU_TIM3_STOP: TIM3 counter stopped when Core is halted
* @arg DBGMCU_TIM4_STOP: TIM4 counter stopped when Core is halted
* @arg DBGMCU_TIM5_STOP: TIM5 counter stopped when Core is halted
* @arg DBGMCU_TIM6_STOP: TIM6 counter stopped when Core is halted
* @arg DBGMCU_TIM7_STOP: TIM7 counter stopped when Core is halted
* @arg DBGMCU_TIM12_STOP: TIM12 counter stopped when Core is halted
* @arg DBGMCU_TIM13_STOP: TIM13 counter stopped when Core is halted
* @arg DBGMCU_TIM14_STOP: TIM14 counter stopped when Core is halted
* @arg DBGMCU_RTC_STOP: RTC Calendar and Wakeup counter stopped when Core is halted.
* @arg DBGMCU_WWDG_STOP: Debug WWDG stopped when Core is halted
* @arg DBGMCU_IWDG_STOP: Debug IWDG stopped when Core is halted
* @arg DBGMCU_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted
* @arg DBGMCU_I2C2_SMBUS_TIMEOUT: I2C2 SMBUS timeout mode stopped when Core is halted
* @arg DBGMCU_I2C3_SMBUS_TIMEOUT: I2C3 SMBUS timeout mode stopped when Core is halted
* @arg DBGMCU_CAN2_STOP: Debug CAN1 stopped when Core is halted
* @arg DBGMCU_CAN1_STOP: Debug CAN2 stopped when Core is halted
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DBGMCU_APB1PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DBGMCU_APB1PERIPH(DBGMCU_Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
DBGMCU->APB1FZ |= DBGMCU_Periph;
}
else
{
DBGMCU->APB1FZ &= ~DBGMCU_Periph;
}
}
/**
* @brief Configures APB2 peripheral behavior when the MCU is in Debug mode.
* @param DBGMCU_Periph: specifies the APB2 peripheral.
* This parameter can be any combination of the following values:
* @arg DBGMCU_TIM1_STOP: TIM1 counter stopped when Core is halted
* @arg DBGMCU_TIM8_STOP: TIM8 counter stopped when Core is halted
* @arg DBGMCU_TIM9_STOP: TIM9 counter stopped when Core is halted
* @arg DBGMCU_TIM10_STOP: TIM10 counter stopped when Core is halted
* @arg DBGMCU_TIM11_STOP: TIM11 counter stopped when Core is halted
* @param NewState: new state of the specified peripheral in Debug mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DBGMCU_APB2PeriphConfig(uint32_t DBGMCU_Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DBGMCU_APB2PERIPH(DBGMCU_Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
DBGMCU->APB2FZ |= DBGMCU_Periph;
}
else
{
DBGMCU->APB2FZ &= ~DBGMCU_Periph;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -447,6 +447,11 @@
<FileType>1</FileType>
<FilePath>..\framework\cli.c</FilePath>
</File>
<File>
<FileName>pm.c</FileName>
<FileType>1</FileType>
<FilePath>..\framework\pm.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -552,6 +557,51 @@
<FileType>1</FileType>
<FilePath>..\user\stm32f4xx_it.c</FilePath>
</File>
<File>
<FileName>platform - lowpower.c</FileName>
<FileType>1</FileType>
<FilePath>..\user\platform - lowpower.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>0</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
<Group>
@ -577,6 +627,11 @@
<FileType>1</FileType>
<FilePath>..\user\cmd\cmd_devinfo.c</FilePath>
</File>
<File>
<FileName>cmd_pm.c</FileName>
<FileType>1</FileType>
<FilePath>..\user\cmd\cmd_pm.c</FilePath>
</File>
</Files>
</Group>
</Groups>

37
user/cmd/cmd_pm.c Normal file
View File

@ -0,0 +1,37 @@
/******************************************************************************
* @brief <EFBFBD>͹<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021/03/07 Morro
******************************************************************************/
#include "cli.h"
#include "pm.h"
#include <stdlib.h>
/*
* @brief <EFBFBD>͹<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @example pm 0 - <EFBFBD><EFBFBD><EFBFBD>õ͹<EFBFBD><EFBFBD><EFBFBD>
* @example pm 1 - <EFBFBD><EFBFBD><EFBFBD>õ͹<EFBFBD><EFBFBD><EFBFBD>
*/
int do_cmd_pm(struct cli_obj *cli, int argc, char *argv[])
{
bool value;
if (argc != 2) {
cli->print(cli, "Command format error\r\n");
}
value = atoi(argv[1]);
if (value) {
pm_enable();
cli->print(cli, "Lowpower enable...\r\n");
} else {
pm_disable();
cli->print(cli, "Lowpower disable...\r\n");
}
return 0;
}cmd_register("pm", do_cmd_pm, "Low power control command");

View File

@ -13,56 +13,57 @@
#include "module.h"
#include "public.h"
#include "led.h"
#include <stddef.h>
static blink_dev_t led[LED_TYPE_MAX]; /*<2A><><EFBFBD><EFBFBD>led<65>豸 ------------*/
/*
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PB4)
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PD4)
* @return none
*/
static void red_led_ctrl(bool level)
{
if (level)
GPIOC->ODR |= 1 << 4;
GPIOD->ODR |= 1 << 4;
else
GPIOC->ODR &= ~(1 << 4);
GPIOD->ODR &= ~(1 << 4);
}
/*
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PB5)
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PD5)
* @return none
*/
static void green_led_ctrl(bool level)
{
if (level)
GPIOC->ODR |= 1 << 5;
GPIOD->ODR |= 1 << 5;
else
GPIOC->ODR &= ~(1 << 5);
GPIOD->ODR &= ~(1 << 5);
}
/*
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PB6)
* @brief <EFBFBD><EFBFBD>ɫLED<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(PD6)
* @return none
*/
static void blue_led_ctrl(bool level)
{
if (level)
GPIOB->ODR |= 1 << 6;
GPIOD->ODR |= 1 << 6;
else
GPIOB->ODR &= ~(1 << 6);
GPIOD->ODR &= ~(1 << 6);
}
/*
* @brief led io<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* PB4 -> red; PB5 -> green; PB6-> blue;
* PD4 -> red; PD5 -> green; PD6-> blue;
* @return none
*/
static void led_io_init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD , ENABLE);
gpio_conf(GPIOB, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_4);
gpio_conf(GPIOB, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_5);
gpio_conf(GPIOB, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_6);
gpio_conf(GPIOD, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_4);
gpio_conf(GPIOD, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_5);
gpio_conf(GPIOD, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_6);
blink_dev_create(&led[LED_TYPE_RED], red_led_ctrl);
blink_dev_create(&led[LED_TYPE_GREEN], green_led_ctrl);
@ -75,6 +76,8 @@ static void led_io_init(void)
}
/*
* @brief led<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] type - led<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(LED_TYPE_XXX)
@ -109,3 +112,20 @@ void led_ctrl(led_type type, int mode, int reapeat)
driver_init("led", led_io_init); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>*/
task_register("led", blink_dev_process, 10); /*led<65><64><EFBFBD><EFBFBD>, 10ms<6D><73>ѯ1<D1AF><31>*/
/* <20>͹<EFBFBD><CDB9>Ĺ<EFBFBD><C4B9><EFBFBD> -----------------------------------------------------------------*/
#include "pm.h"
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
*/
static unsigned int led_sleep_notify(void)
{
int i;
for (i = 0; i < LED_TYPE_MAX; i++)
if (blink_dev_busy(&led[i]))
return 100; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>100ms<6D><73><EFBFBD><EFBFBD>1<EFBFBD><31>
return 0;
} pm_dev_register("led", NULL, led_sleep_notify, NULL);

229
user/platform - lowpower.c Normal file
View File

@ -0,0 +1,229 @@
/******************************************************************************
* @brief ƽ̨<EFBFBD><EFBFBD><EFBFBD>س<EFBFBD>ʼ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
******************************************************************************/
#include "module.h"
#include "public.h"
#include "config.h"
#include "platform.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "tty.h"
#include "pm.h"
/*
* @brief RTC<EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD>־
*/
static volatile bool is_rtc_wakekup = false;
/*
* @brief ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD>)
*/
static unsigned int system_idle_time = 0;
/*
* @brief rtc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
* @param[in] none
* @return none
*/
void RTC_WKUP_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_WUT) != RESET) {
RTC_ClearITPendingBit(RTC_IT_WUT);
EXTI_ClearITPendingBit(EXTI_Line22);
systick_increase(SYS_TICK_INTERVAL);
is_rtc_wakekup = true;
}
}
/*
* @brief RTC<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
*/
void rtc_init(void)
{
volatile unsigned int retry = 0;
/* Allow access to RTC */
PWR_BackupAccessCmd(ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Enable the LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */
do{
retry++;
} while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && retry < 20000);
if (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET) {
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
} else {
RCC_LSEConfig(RCC_LSE_OFF);
/* <20>ⲿ<EFBFBD><E2B2BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʹ<><CAB9><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD> */
RCC_LSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET){ }
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
}
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
}
/*
* @brief rtc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] none(1~4000ms)
*/
void rtc_wakeup_config(unsigned int ms)
{
RTC_WakeUpCmd(DISABLE);
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div2);
RTC_SetWakeUpCounter((unsigned int )((ms * 16384.0 / 1000.0) + 0.5 ) - 1);
exti_conf(EXTI_Line22, EXTI_Trigger_Rising, ENABLE);
nvic_conf(RTC_WKUP_IRQn, 0, 0);
RTC_ClearITPendingBit(RTC_IT_WUT);
RTC_ITConfig(RTC_IT_WUT, ENABLE);
RTC_WakeUpCmd(ENABLE);
}
/**
* @brief <EFBFBD><EFBFBD>ֹͣģʽ<EFBFBD>л<EFBFBD><EFBFBD>Ѻ<EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>HSE<EFBFBD><EFBFBD>PLL
*/
static void system_wakup_config(void)
{
volatile unsigned int retry = 0;
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET && ++retry < 200000)
{
}
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while (RCC_GetSYSCLKSource() != 0x08)
{
}
}
/*
* @brief ϵͳ<EFBFBD><EFBFBD><EFBFBD>߽ӿ<EFBFBD>ʵ<EFBFBD><EFBFBD>
* @param[in] ms - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,1<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>δ<EFBFBD>ʱ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* ϵͳʱ<EFBFBD>Ӳ<EFBFBD>׼.
* @return ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
*/
static unsigned int system_sleep(unsigned int ms)
{
unsigned int start_time = get_tick();
/**
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>sleep_timeָ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>rtc_wakeup_config<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>λ<EFBFBD>
<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD>STM32F4ϵ<EFBFBD><EFBFBD>MCU
<EFBFBD><EFBFBD>˵,<EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD>³<EFBFBD><EFBFBD><EFBFBD>RTC<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>ֹͣ<EFBFBD><EFBFBD>,û<EFBFBD><EFBFBD><EFBFBD><EFBFBD>L4һ<EFBFBD><EFBFBD>ӵ<EFBFBD>е͹<EFBFBD><EFBFBD>Ķ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ͻȻ<EFBFBD>ⲿ<EFBFBD>жϻ<EFBFBD><EFBFBD>ѣ<EFBFBD>ϵͳ<EFBFBD>δ<EFBFBD>ʱ<EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>F4ϵ<EFBFBD><EFBFBD>MCU<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>ϵͳֻ<EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>[rtc_wakeup_config],<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ΪSYS_TICK_INTERVAL(Ĭ<EFBFBD><EFBFBD>10ms)Ϊ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>Ъ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><EFBFBD>
<EFBFBD>ϻ<EFBFBD><EFBFBD>Ѷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><EFBFBD>ϵͳ<EFBFBD>δ<EFBFBD>ʱ<EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD>,ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۼ<EFBFBD><EFBFBD>޹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>
*/
while (get_tick() - start_time < ms) {
is_rtc_wakekup = false;
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
if (!is_rtc_wakekup) //<2F>ⲿ<EFBFBD>жϻ<D0B6><CFBB><EFBFBD>
break;
}
system_wakup_config(); //<2F><><EFBFBD><EFBFBD>HSE
//printf("Sleep Time:%d isrtc:%d...\r\n\r\n", get_tick() - start_time, is_rtc_wakekup);
return get_tick() - start_time;
}
/*
* @brief <EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static const pm_adapter_t pm_adapter = {
MAX_DOG_FEED_TIME * 8 / 10, //ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>Ѳ<EFBFBD>ι<EFBFBD><CEB9>
system_sleep
};
/*
* @brief Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] none
* @return none
*/
static void bsp_init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
tty.init(115200);
SystemCoreClockUpdate();
RCC_APB2PeriphClockLPModeCmd(RCC_APB2Periph_SYSCFG,ENABLE);
rtc_init();
rtc_wakeup_config(SYS_TICK_INTERVAL); //ʹ<><CAB9>RTC<54><43><EFBFBD><EFBFBD>ϵͳ
wdog_conf(MAX_DOG_FEED_TIME); //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD>
pm_init(&pm_adapter); //<2F><>ʼ<EFBFBD><CABC><EFBFBD>͹<EFBFBD><CDB9>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD>
pm_enable(); //<2F><><EFBFBD>õ͹<C3B5><CDB9>Ĺ<EFBFBD><C4B9><EFBFBD>
//
//<2F>͹<EFBFBD><CDB9><EFBFBD>ģʽ<C4A3><CABD><><CEAA><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>1 RXΪ<58><CEAA><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
//
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource10);
exti_conf(EXTI_Line10, EXTI_Trigger_Falling, ENABLE);
nvic_conf(EXTI15_10_IRQn, 5, 1);
}system_init("bsp", bsp_init);
/*
* @brief <EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>printf
*/
int fputc(int c, FILE *f)
{
tty.write(&c, 1);
while (tty.tx_isfull()) {} //<2F><>ֹ<EFBFBD><D6B9>LOG
return c;
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϴ<EFBFBD><EFBFBD><EFBFBD>
*/
void EXTI15_10_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line10);
EXTI_ClearITPendingBit(EXTI_Line8);
system_idle_time = get_tick(); //<2F><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
/*
* @brief Ĭ<EFBFBD>Ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ż,3S<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD>
*/
static bool system_is_idle(void)
{
return is_timeout(system_idle_time, 3000) && tty.rx_isempty() && tty.tx_isempty();
}pm_dev_register("sys", system_is_idle, NULL, NULL);
/*
* @brief <EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void pm_task(void)
{
pm_process();
}task_register("pm", pm_task, 0);
/*
* @brief ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void wdog_task(void)
{
IWDG_ReloadCounter();
}task_register("dog", wdog_task, 1000);

View File

@ -1,5 +1,5 @@
/******************************************************************************
* @brief ƽ̨<EFBFBD><EFBFBD><EFBFBD>س<EFBFBD>ʼ<EFBFBD><EFBFBD>
* @brief ƽ̨<EFBFBD><EFBFBD><EFBFBD>س<EFBFBD>ʼ<EFBFBD><EFBFBD>(<EFBFBD>޵͹<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD>)
*
* Copyright (c) 2020, <morro_luo@163.com>
*
@ -47,5 +47,13 @@ static void bsp_init(void)
SystemCoreClockUpdate();
SysTick_Config(SystemCoreClock / (1000 / SYS_TICK_INTERVAL)); //<2F><><EFBFBD><EFBFBD>ϵͳʱ<CDB3><CAB1>
NVIC_SetPriority(SysTick_IRQn, 0);
wdog_conf(MAX_DOG_FEED_TIME); //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD>
}system_init("bsp", bsp_init);
/*
* @brief ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void wdog_task(void)
{
IWDG_ReloadCounter();
}task_register("dog", wdog_task, 1000);

View File

@ -15,7 +15,10 @@
#include <stdbool.h>
#define LOWPOWER_MODE 1 /* ʹ<>ܵ͹<DCB5><CDB9><EFBFBD>ģʽ*/
#define SYS_TICK_INTERVAL 10 /* ϵͳ<CFB5>δ<EFBFBD>ʱ<EFBFBD><CAB1>(ms) */
#define MAX_DOG_FEED_TIME 10 * 1000 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD>ι<EFBFBD><CEB9>ʱ<EFBFBD><CAB1>*/
bool is_timeout(unsigned int start, unsigned int timeout);

View File

@ -114,3 +114,24 @@ void uart_conf(USART_TypeDef *port, int baudrate)
USART_Cmd(port, ENABLE);
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] Tout - ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<EFBFBD><EFBFBD>(ms)
* @return none
*/
void wdog_conf(unsigned int Tout)
{
IWDG_WritERR_ACCESSCmd(IWDG_WritERR_ACCESS_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_256);
//LSI = 40 Khz
//Tout=(256<35><36>reload) / 40
IWDG_SetReload(Tout * 40 / 256);
IWDG_ReloadCounter();
IWDG_Enable();
IWDG_WritERR_ACCESSCmd(IWDG_WritERR_ACCESS_Disable);
}

View File

@ -22,4 +22,7 @@ void timer_conf(TIM_TypeDef* TIMx, unsigned int hz);
void uart_conf(USART_TypeDef *port, int baudrate);
void wdog_conf(unsigned int Tout);
#endif

View File

@ -35,7 +35,7 @@
//#include "stm32f4xx_crc.h"
//#include "stm32f4xx_cryp.h"
//#include "stm32f4xx_dac.h"
//#include "stm32f4xx_dbgmcu.h"
#include "stm32f4xx_dbgmcu.h"
//#include "stm32f4xx_dcmi.h"
//#include "stm32f4xx_dma.h"
#include "stm32f4xx_exti.h"

View File

@ -13,7 +13,7 @@
#include "tty.h"
#include "cli.h"
static cli_obj_t cli; /*<2A><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD> */
static cli_obj_t cli; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>

View File

@ -13,6 +13,7 @@
#include "key.h"
#include "module.h"
#include "public.h"
#include <stddef.h>
static key_t key; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
@ -24,17 +25,35 @@ static void key_event(int type, unsigned int duration);
*/
static int readkey(void)
{
return GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0;
return GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0;
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϴ<EFBFBD><EFBFBD><EFBFBD>
*/
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD> io<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* PC4 -> key;
* PC0 -> key;
* @return none
*/
static void key_io_init(void)
{
gpio_conf(GPIOC, GPIO_Mode_IN, GPIO_PuPd_UP, GPIO_Pin_4);
/* Enable GPIOA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
gpio_conf(GPIOC, GPIO_Mode_IN, GPIO_PuPd_UP, GPIO_Pin_0);
//<2F>͹<EFBFBD><CDB9><EFBFBD>ģʽ<C4A3><CABD><><CEAA><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>жϻ<D0B6><CFBB><EFBFBD>
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource0);
exti_conf(EXTI_Line0, EXTI_Trigger_Falling, ENABLE);
nvic_conf(EXTI0_IRQn, 0x0F, 0x0F);
key_create(&key, readkey, key_event); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}
@ -45,7 +64,7 @@ static void key_io_init(void)
static void key_event(int type, unsigned int duration)
{
if (type == KEY_PRESS)
led_ctrl(LED_TYPE_GREEN, LED_MODE_FAST, 3); /*<2A>̰<EFBFBD>,<2C>̵<EFBFBD><CCB5><EFBFBD>3<EFBFBD><33>*/
led_ctrl(LED_TYPE_GREEN, LED_MODE_SLOW, 3); /*<2A>̰<EFBFBD>,<2C>̵<EFBFBD><CCB5><EFBFBD>3<EFBFBD><33>*/
else if (type == KEY_LONG_DOWN)
led_ctrl(LED_TYPE_GREEN, LED_MODE_ON, 0); /*<2A><><EFBFBD><EFBFBD>,<2C>̵Ƴ<CCB5><C6B3><EFBFBD>*/
else if (type == KEY_LONG_UP)
@ -54,3 +73,14 @@ static void key_event(int type, unsigned int duration)
driver_init("key", key_io_init); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>*/
task_register("key", key_scan_process, 20); /*<2A><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 20ms<6D><73>ѯ1<D1AF><31>*/
/* <20>͹<EFBFBD><CDB9>Ĺ<EFBFBD><C4B9><EFBFBD> -----------------------------------------------------------------*/
#include "pm.h"
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ
*/
static unsigned int key_sleep_notify(void)
{
return (key_busy(&key) || readkey()) ? 20 : 0; /* <20>ǿ<EFBFBD><C7BF><EFBFBD>ʱ20msҪ<73><D2AA><EFBFBD><EFBFBD>1<EFBFBD><31>*/
} pm_dev_register("key", NULL, key_sleep_notify, NULL);

14
user/task/pm_task.c Normal file
View File

@ -0,0 +1,14 @@
/******************************************************************************
* @brief <EFBFBD>͹<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/07/11 Morro
******************************************************************************/
#include "pm.h"
#include "public.h"