263 lines
7.2 KiB
C
263 lines
7.2 KiB
C
/******************************************************************************
|
||
* @file usr_led_status.c
|
||
* @brief 状态指示灯实现
|
||
* @author cyWu <1917507415@qq.com>
|
||
* @date 2026.08.03
|
||
* @version V1.0.0
|
||
* @history
|
||
* - V1.0.0, 2026.08.03, cyWu, 首次发布
|
||
*
|
||
* 显示规则:
|
||
* 红灯(PA8):上电常亮;COM(DTR)打开时 1Hz 闪烁(优先于常亮)
|
||
* 绿灯(PA7):BLE 已连接常亮;OTA 进行中 1Hz 闪烁(优先于常亮);否则熄灭
|
||
*
|
||
* 依赖:
|
||
* - BLE:usr_get_conn_service() != 0
|
||
* - COM:cdc_is_com_open() == 1(与 Dengle 暂停语义一致)
|
||
* - OTA:usr_get_ota_status() == 0(dual_ota_idle=0 表示忙)
|
||
******************************************************************************/
|
||
|
||
#include "system/includes.h"
|
||
#include "app_config.h"
|
||
#include "asm/gpio.h"
|
||
#include "usr_led_status.h"
|
||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||
#include "usb/device/cdc.h"
|
||
#endif
|
||
|
||
#define LOG_TAG_CONST APP
|
||
#define LOG_TAG "[LED]"
|
||
#define LOG_ERROR_ENABLE
|
||
#define LOG_DEBUG_ENABLE
|
||
#define LOG_INFO_ENABLE
|
||
#define LOG_CLI_ENABLE
|
||
#include "debug.h"
|
||
|
||
/*============================================================================*/
|
||
/* 私有宏 (Private macros) */
|
||
/*============================================================================*/
|
||
|
||
#define USR_LED_GREEN_PIN IO_PORTA_07 /**< 绿灯 */
|
||
#define USR_LED_RED_PIN IO_PORTA_08 /**< 红灯 */
|
||
|
||
/**
|
||
* LED 点亮电平:1=高电平点亮,0=低电平点亮
|
||
* 若实测灯反了,改此宏即可
|
||
*/
|
||
#define USR_LED_ON_LEVEL (0)
|
||
#define USR_LED_OFF_LEVEL (!(USR_LED_ON_LEVEL))
|
||
|
||
#define USR_LED_BLINK_HALF_MS (500) /**< 1Hz:亮/灭各 500ms */
|
||
#define USR_LED_HALF_TICKS (USR_LED_BLINK_HALF_MS / USR_LED_TICK_MS)
|
||
|
||
/*============================================================================*/
|
||
/* 私有类型 (Private types) */
|
||
/*============================================================================*/
|
||
|
||
typedef enum {
|
||
LED_MODE_OFF = 0,
|
||
LED_MODE_ON,
|
||
LED_MODE_BLINK
|
||
} LedMode_t;
|
||
|
||
/*============================================================================*/
|
||
/* 私有变量 (Private variables) */
|
||
/*============================================================================*/
|
||
|
||
static uint8_t s_initialized = 0;
|
||
static u16 s_tick_timer = 0;
|
||
static uint8_t s_blink_phase = 0; /**< 0=半周期灭侧,1=半周期亮侧 */
|
||
static uint8_t s_blink_cnt = 0; /**< 半周期内已走过的 tick 数 */
|
||
|
||
extern u16 usr_get_conn_service(void);
|
||
extern u8 usr_get_ota_status(void);
|
||
|
||
/*============================================================================*/
|
||
/* 私有函数声明 (Private function prototypes) */
|
||
/*============================================================================*/
|
||
|
||
static void usr_led_gpio_init(u32 pin);
|
||
static void usr_led_set(u32 pin, uint8_t on);
|
||
static uint8_t usr_led_is_com_open(void);
|
||
static uint8_t usr_led_is_ble_conn(void);
|
||
static uint8_t usr_led_is_ota_busy(void);
|
||
static void usr_led_apply(u32 pin, LedMode_t mode);
|
||
static void usr_led_tick(void *priv);
|
||
|
||
/*============================================================================*/
|
||
/* 公有函数实现 (Public API implementation) */
|
||
/*============================================================================*/
|
||
|
||
/**
|
||
* @brief 初始化状态灯
|
||
* @return UsrLed_Ret_t 错误码
|
||
*/
|
||
UsrLed_Ret_t usr_led_status_init(void)
|
||
{
|
||
if (s_initialized) {
|
||
return USR_LED_OK;
|
||
}
|
||
|
||
usr_led_gpio_init(USR_LED_GREEN_PIN);
|
||
usr_led_gpio_init(USR_LED_RED_PIN);
|
||
|
||
/* 上电:红灯常亮,绿灯熄灭 */
|
||
usr_led_set(USR_LED_RED_PIN, 1);
|
||
usr_led_set(USR_LED_GREEN_PIN, 0);
|
||
|
||
s_blink_phase = 1;
|
||
s_blink_cnt = 0;
|
||
s_initialized = 1;
|
||
|
||
if (s_tick_timer == 0) {
|
||
s_tick_timer = sys_timer_add(NULL, usr_led_tick, USR_LED_TICK_MS);
|
||
}
|
||
|
||
printf("usr_led_status_init ok (red=PA8 green=PA7)\n");
|
||
return USR_LED_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 主处理:刷新红/绿灯显示模式
|
||
*/
|
||
void usr_led_status_run(void)
|
||
{
|
||
LedMode_t red_mode;
|
||
LedMode_t green_mode;
|
||
|
||
if (!s_initialized) {
|
||
return;
|
||
}
|
||
|
||
/* 红灯:COM 打开 → 闪烁;否则上电常亮 */
|
||
if (usr_led_is_com_open()) {
|
||
red_mode = LED_MODE_BLINK;
|
||
} else {
|
||
red_mode = LED_MODE_ON;
|
||
}
|
||
|
||
/* 绿灯:OTA 忙 → 闪烁;BLE 已连 → 常亮;否则熄灭 */
|
||
if (usr_led_is_ota_busy()) {
|
||
green_mode = LED_MODE_BLINK;
|
||
} else if (usr_led_is_ble_conn()) {
|
||
green_mode = LED_MODE_ON;
|
||
} else {
|
||
green_mode = LED_MODE_OFF;
|
||
}
|
||
|
||
/* 任一灯在闪时推进公共 1Hz 相位,保证同频同相 */
|
||
if (red_mode == LED_MODE_BLINK || green_mode == LED_MODE_BLINK) {
|
||
s_blink_cnt++;
|
||
if (s_blink_cnt >= USR_LED_HALF_TICKS) {
|
||
s_blink_cnt = 0;
|
||
s_blink_phase ^= 1;
|
||
}
|
||
} else {
|
||
s_blink_cnt = 0;
|
||
s_blink_phase = 1;
|
||
}
|
||
|
||
usr_led_apply(USR_LED_RED_PIN, red_mode);
|
||
usr_led_apply(USR_LED_GREEN_PIN, green_mode);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前初始化状态
|
||
* @return UsrLed_Ret_t
|
||
*/
|
||
UsrLed_Ret_t usr_led_status_get_status(void)
|
||
{
|
||
if (!s_initialized) {
|
||
return USR_LED_ERR_NOT_INIT;
|
||
}
|
||
return USR_LED_OK;
|
||
}
|
||
|
||
/*============================================================================*/
|
||
/* 私有函数实现 (Private functions) */
|
||
/*============================================================================*/
|
||
|
||
/**
|
||
* @brief 配置 LED 引脚为推挽输出
|
||
* @param pin GPIO 宏(如 IO_PORTA_07)
|
||
*/
|
||
static void usr_led_gpio_init(u32 pin)
|
||
{
|
||
gpio_set_die(pin, 1);
|
||
gpio_set_pull_up(pin, 0);
|
||
gpio_set_pull_down(pin, 0);
|
||
gpio_direction_output(pin, USR_LED_OFF_LEVEL);
|
||
}
|
||
|
||
/**
|
||
* @brief 点亮/熄灭指定 LED
|
||
* @param pin GPIO
|
||
* @param on 1=亮,0=灭
|
||
*/
|
||
static void usr_led_set(u32 pin, uint8_t on)
|
||
{
|
||
gpio_direction_output(pin, on ? USR_LED_ON_LEVEL : USR_LED_OFF_LEVEL);
|
||
}
|
||
|
||
/**
|
||
* @brief COM 口是否打开(CDC DTR)
|
||
* @return 1=已打开,0=未打开/无 CDC
|
||
*/
|
||
static uint8_t usr_led_is_com_open(void)
|
||
{
|
||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||
return cdc_is_com_open() ? 1 : 0;
|
||
#else
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief BLE 是否已连接
|
||
* @return 1=已连接
|
||
*/
|
||
static uint8_t usr_led_is_ble_conn(void)
|
||
{
|
||
return (usr_get_conn_service() != 0) ? 1 : 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 是否正在 OTA(usr_get_ota_status==0 表示忙)
|
||
* @return 1=OTA 进行中
|
||
*/
|
||
static uint8_t usr_led_is_ota_busy(void)
|
||
{
|
||
return (usr_get_ota_status() == 0) ? 1 : 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 按模式驱动单灯
|
||
* @param pin GPIO
|
||
* @param mode 灭 / 常亮 / 闪烁
|
||
*/
|
||
static void usr_led_apply(u32 pin, LedMode_t mode)
|
||
{
|
||
switch (mode) {
|
||
case LED_MODE_ON:
|
||
usr_led_set(pin, 1);
|
||
break;
|
||
case LED_MODE_BLINK:
|
||
usr_led_set(pin, s_blink_phase);
|
||
break;
|
||
case LED_MODE_OFF:
|
||
default:
|
||
usr_led_set(pin, 0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief sys_timer 回调:100ms 刷新一次
|
||
* @param priv 未使用
|
||
*/
|
||
static void usr_led_tick(void *priv)
|
||
{
|
||
(void)priv;
|
||
usr_led_status_run();
|
||
}
|