419 lines
12 KiB
C
419 lines
12 KiB
C
#include "bk_gpio.h"
|
||
#include <os/os.h>
|
||
#include <os/mem.h>
|
||
#include <common/bk_kernel_err.h>
|
||
#include <driver/gpio.h>
|
||
#include <driver/hal/hal_gpio_types.h>
|
||
#include "gpio_driver.h"
|
||
#include <led_blink.h>
|
||
#include <string.h>
|
||
#include <components/log.h>
|
||
|
||
#define TAG "led_blink"
|
||
|
||
#define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__)
|
||
#define LOGW(...) BK_LOGW(TAG, ##__VA_ARGS__)
|
||
#define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__)
|
||
#define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__)
|
||
|
||
static LedControlBlock led_pool[MAX_LED_NUM];
|
||
static beken_mutex_t led_mutex = NULL;
|
||
|
||
typedef struct {
|
||
int led1; // 第一个LED句柄
|
||
int led2; // 第二个LED句柄
|
||
beken_timer_t timer; // 共享定时器
|
||
uint32_t interval; // 交替间隔
|
||
bool current_state; // 当前主导状态
|
||
} AlternateGroup;
|
||
static AlternateGroup s_alt_group;
|
||
|
||
static int led_handle_1 = 0;
|
||
static int led_handle_2 = 0;
|
||
static bool s_timer_initialized = false;
|
||
|
||
static int led_register(uint8_t gpio);
|
||
|
||
static void led_set_state(uint8_t led_handle, LedState new_state, uint32_t time);
|
||
|
||
static void led_unregister(uint8_t led_handle);
|
||
|
||
static void led_set_alternate(uint8_t led_handle_1, uint8_t led_handle_2, uint32_t interval_ms);
|
||
|
||
static void led_vote_error(uint8_t led_handle,ErrorType err_type);
|
||
|
||
static void led_resolve_error(uint8_t led_handle,ErrorType err_type);
|
||
|
||
static void update_active_error(LedControlBlock* led);
|
||
|
||
static void restore_normal_state(LedControlBlock* led);
|
||
|
||
static void alternate_timer_cb(void *arg) {
|
||
rtos_lock_mutex(&led_mutex);
|
||
|
||
// 交替状态
|
||
s_alt_group.current_state = !s_alt_group.current_state;
|
||
|
||
// 更新LED1状态
|
||
LedControlBlock* led_1 = &led_pool[s_alt_group.led1];
|
||
led_1->led_status = s_alt_group.current_state;
|
||
|
||
if (led_1->led_status == 0)
|
||
{
|
||
bk_gpio_set_value(led_1->gpio_num,0x0);
|
||
} else {
|
||
bk_gpio_set_value(led_1->gpio_num,0x2);
|
||
}
|
||
// 更新LED2状态(取反)
|
||
LedControlBlock* led_2 = &led_pool[s_alt_group.led2];
|
||
led_2->led_status = !s_alt_group.current_state;
|
||
if (led_2->led_status == 0)
|
||
{
|
||
bk_gpio_set_value(led_2->gpio_num,0x0);
|
||
} else {
|
||
bk_gpio_set_value(led_2->gpio_num,0x2);
|
||
}
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
//设置交替闪
|
||
static void led_set_alternate(uint8_t led_handle_1, uint8_t led_handle_2, uint32_t interval_ms) {
|
||
|
||
bk_err_t ret;
|
||
// 参数校验
|
||
if(led_handle_1 == led_handle_2 || led_handle_1 <0 || led_handle_2 <0 ||
|
||
led_handle_1 >= MAX_LED_NUM || led_handle_2 >= MAX_LED_NUM) return;
|
||
|
||
if((led_pool[led_handle_1].state == LED_ALTERNATE) && (led_pool[led_handle_2].state == LED_ALTERNATE))
|
||
return;
|
||
|
||
rtos_lock_mutex(&led_mutex);
|
||
|
||
// 配置交替组
|
||
s_alt_group.led1 = led_handle_1;
|
||
s_alt_group.led2 = led_handle_2;
|
||
s_alt_group.interval = interval_ms;
|
||
|
||
// 初始化LED状态
|
||
led_pool[led_handle_1].state = LED_ALTERNATE;
|
||
led_pool[led_handle_2].state = LED_ALTERNATE;
|
||
led_pool[led_handle_1].alt_partner = led_handle_2;
|
||
led_pool[led_handle_2].alt_partner = led_handle_1;
|
||
|
||
// 创建/重置定时器
|
||
if (!s_timer_initialized)
|
||
{
|
||
s_timer_initialized = true;
|
||
ret = rtos_init_timer(&s_alt_group.timer,interval_ms, alternate_timer_cb, NULL);
|
||
BK_ASSERT(kNoErr == ret);
|
||
}
|
||
// 强制设置初始状态
|
||
s_alt_group.current_state = true;
|
||
bk_gpio_set_value(led_pool[led_handle_1].gpio_num, 0x2);
|
||
bk_gpio_set_value(led_pool[led_handle_2].gpio_num, 0x0);
|
||
|
||
ret = rtos_start_timer(&s_alt_group.timer);
|
||
BK_ASSERT(kNoErr == ret);
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
static void timer_callback(void *arg) {
|
||
int led_handle = (int)arg;
|
||
LedControlBlock* led = &led_pool[led_handle];
|
||
bool should_stop = false;
|
||
|
||
if (led->blink_duration == LED_LAST_FOREVER)
|
||
{
|
||
should_stop = false;
|
||
}else if(led->blink_duration >= 0)
|
||
{
|
||
uint32_t now = rtos_get_time();
|
||
if (now - led->blink_start >= led->blink_duration)
|
||
{
|
||
should_stop = true;
|
||
}
|
||
|
||
}
|
||
|
||
if (led->active_error != ERROR_TYPE_COUNT)
|
||
{
|
||
LOGI("enter the anomaly\r\n");
|
||
led->led_status = !led->led_status;
|
||
if (led->led_status == 1)
|
||
{
|
||
bk_gpio_set_value(led->gpio_num,0x2);
|
||
} else {
|
||
bk_gpio_set_value(led->gpio_num,0x0);
|
||
}
|
||
}else if (should_stop)
|
||
{
|
||
LOGI("blink time's up\r\n");
|
||
rtos_stop_timer(&led->timer);
|
||
bk_gpio_set_value(led->gpio_num,0x0);
|
||
led->state = LED_OFF;
|
||
}else if(led->state == LED_FAST_BLINK || led->state == LED_SLOW_BLINK)
|
||
{
|
||
led->led_status = !led->led_status;
|
||
if (led->led_status == 1)
|
||
{
|
||
bk_gpio_set_value(led->gpio_num,0x2);
|
||
} else {
|
||
bk_gpio_set_value(led->gpio_num,0x0);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
void led_driver_init() {
|
||
int ret = rtos_init_mutex(&led_mutex);
|
||
BK_ASSERT(kNoErr == ret);
|
||
memset(led_pool, 0, sizeof(led_pool));
|
||
led_handle_1 = led_register(RED_LED);
|
||
led_handle_2 = led_register(GREEN_LED);
|
||
}
|
||
|
||
|
||
int led_register(uint8_t gpio) {
|
||
bk_err_t ret;
|
||
rtos_lock_mutex(&led_mutex);
|
||
// 查找空闲控制块
|
||
for(int i=0; i<MAX_LED_NUM; i++){
|
||
if(led_pool[i].gpio_num == 0){
|
||
led_pool[i].gpio_num = gpio;
|
||
led_pool[i].active_error = ERROR_TYPE_COUNT;
|
||
ret = rtos_init_timer(&led_pool[i].timer,100, timer_callback, (void*)i);
|
||
BK_ASSERT(kNoErr == ret);
|
||
rtos_unlock_mutex(&led_mutex);
|
||
return i; // 返回LED句柄
|
||
}
|
||
}
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
return -1; // 注册失败
|
||
}
|
||
|
||
|
||
static void led_set_state(uint8_t led_handle, LedState new_state, uint32_t time) {
|
||
if(led_handle < 0 || led_handle >= MAX_LED_NUM)
|
||
return;
|
||
|
||
rtos_lock_mutex(&led_mutex);
|
||
LedControlBlock* led = &led_pool[led_handle];
|
||
|
||
if(led->state == LED_ALTERNATE && new_state != LED_ALTERNATE) {
|
||
// 停止交替定时器
|
||
if(s_alt_group.led1 == led_handle ||
|
||
s_alt_group.led2 == led_handle) {
|
||
rtos_stop_timer(&s_alt_group.timer);
|
||
}
|
||
|
||
//Another LED status clear
|
||
bk_gpio_set_value(led_pool[led->alt_partner].gpio_num, 0x0);
|
||
led_pool[led->alt_partner].state = LED_OFF;
|
||
|
||
// 解除伙伴关系
|
||
if(led->alt_partner != -1) {
|
||
led_pool[led->alt_partner].alt_partner = -1;
|
||
led->alt_partner = -1;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (led->active_error == ERROR_TYPE_COUNT){
|
||
led->state = new_state;
|
||
switch (new_state) {
|
||
case LED_OFF:
|
||
rtos_stop_timer(&led->timer);
|
||
bk_gpio_set_value(led->gpio_num,0x0);
|
||
break;
|
||
|
||
case LED_ON:
|
||
led->blink_duration = time;
|
||
led->blink_start = rtos_get_time();
|
||
rtos_start_timer(&led->timer);
|
||
bk_gpio_set_value(led->gpio_num,0x2);
|
||
break;
|
||
|
||
case LED_FAST_BLINK:
|
||
led->interval = LED_FAST_BLINK_TIME;
|
||
led->blink_duration = time;
|
||
led->blink_start = rtos_get_time();
|
||
rtos_change_period(&led->timer, LED_FAST_BLINK_TIME);
|
||
rtos_start_timer(&led->timer);
|
||
break;
|
||
|
||
case LED_SLOW_BLINK:
|
||
led->interval = LED_SLOW_BLINK_TIME;
|
||
led->blink_duration = time;
|
||
led->blink_start = rtos_get_time();
|
||
rtos_change_period(&led->timer, LED_SLOW_BLINK_TIME);
|
||
rtos_start_timer(&led->timer);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
|
||
void led_unregister(uint8_t led_handle) {
|
||
if(led_handle < 0 || led_handle >= MAX_LED_NUM) return;
|
||
|
||
rtos_lock_mutex(&led_mutex);
|
||
rtos_deinit_timer(&led_pool[led_handle].timer);
|
||
memset(&led_pool[led_handle], 0, sizeof(LedControlBlock));
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
|
||
void led_vote_error(uint8_t led_handle, ErrorType err_type) {
|
||
if (led_handle < 0 || led_handle >= MAX_LED_NUM)
|
||
{
|
||
LOGE("error's led_handle , led_handle is %d\r\n",led_handle);
|
||
return;
|
||
}
|
||
|
||
rtos_lock_mutex(&led_mutex);
|
||
LedControlBlock* led = &led_pool[led_handle];
|
||
// 对应错误计数器增加
|
||
if (led->error_counts[err_type]++ == 0) {
|
||
// 首次投票此类型错误,可能触发状态变更
|
||
update_active_error(led);
|
||
}
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
void led_resolve_error(uint8_t led_handle, ErrorType err_type) {
|
||
if (led_handle < 0 || led_handle >= MAX_LED_NUM) return;
|
||
|
||
rtos_lock_mutex(&led_mutex);
|
||
LedControlBlock* led = &led_pool[led_handle];
|
||
if (led->error_counts[err_type] > 0 && --led->error_counts[err_type] == 0) {
|
||
// 该类型错误计数器归零,重新评估状态
|
||
update_active_error(led);
|
||
}
|
||
|
||
rtos_unlock_mutex(&led_mutex);
|
||
}
|
||
|
||
static void update_active_error(LedControlBlock* led) {
|
||
// 确定当前最高优先级错误
|
||
ErrorType new_active = ERROR_TYPE_COUNT;
|
||
for (int i = 0; i < ERROR_TYPE_COUNT; i++) {
|
||
if (led->error_counts[i] > 0) {
|
||
new_active = (ErrorType)i;
|
||
break; // 按优先级顺序遍历,第一个非零即最高
|
||
}
|
||
}
|
||
|
||
// 状态切换处理
|
||
if (new_active != led->active_error) {
|
||
rtos_stop_timer(&led->timer); // 停止当前定时器
|
||
|
||
if (new_active != ERROR_TYPE_COUNT) {
|
||
// 切换到新错误类型
|
||
led->active_error = new_active;
|
||
const int period = (new_active == ERROR_CRITICAL) ? LED_FAST_BLINK_TIME : LED_SLOW_BLINK_TIME;
|
||
os_printf("period is %d\r\n",period);
|
||
rtos_change_period(&led->timer, period);
|
||
rtos_start_timer(&led->timer);
|
||
led->state = (new_active == ERROR_CRITICAL) ? LED_FAST_BLINK : LED_SLOW_BLINK;
|
||
} else {
|
||
// 无错误,恢复正常状态
|
||
LOGI("Abnormal recovery\r\n");
|
||
restore_normal_state(led);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void restore_normal_state(LedControlBlock* led) {
|
||
|
||
led->active_error = ERROR_TYPE_COUNT;
|
||
|
||
if (led->blink_duration > 0) {
|
||
// 重新启动自动熄灭计时
|
||
int period = led->interval;
|
||
led->blink_start = rtos_get_time();
|
||
rtos_change_period(&led->timer, period);
|
||
rtos_start_timer(&led->timer);
|
||
} else {
|
||
bk_gpio_set_value(led->gpio_num,0x0);
|
||
}
|
||
}
|
||
|
||
void led_app_set(led_operate_t oper, uint32_t time)
|
||
{
|
||
LOGI("%s:oper=%d,t=%d\r\n", __func__, oper, time);
|
||
|
||
switch(oper)
|
||
{
|
||
case LED_OFF_GREEN:
|
||
led_set_state(led_handle_2,LED_OFF,0);
|
||
break;
|
||
|
||
case LED_ON_GREEN:
|
||
led_set_state(led_handle_2,LED_ON,time);
|
||
break;
|
||
|
||
case LED_FAST_BLINK_GREEN:
|
||
led_set_state(led_handle_2,LED_FAST_BLINK,time);
|
||
break;
|
||
|
||
case LED_SLOW_BLINK_GREEN:
|
||
led_set_state(led_handle_2,LED_SLOW_BLINK,time);
|
||
break;
|
||
|
||
case LED_OFF_RED:
|
||
led_set_state(led_handle_1,LED_OFF,0);
|
||
break;
|
||
|
||
case LED_ON_RED:
|
||
led_set_state(led_handle_1,LED_ON,time);
|
||
break;
|
||
|
||
case LED_FAST_BLINK_RED:
|
||
led_set_state(led_handle_1,LED_FAST_BLINK,time);
|
||
break;
|
||
|
||
case LED_SLOW_BLINK_RED:
|
||
led_set_state(led_handle_1,LED_SLOW_BLINK,time);
|
||
break;
|
||
|
||
case LED_REG_GREEN_ALTERNATE:
|
||
led_set_alternate(led_handle_1,led_handle_2,500);
|
||
break;
|
||
|
||
case LED_REG_GREEN_ALTERNATE_OFF:
|
||
led_set_state(led_handle_1,LED_OFF,0);
|
||
led_set_state(led_handle_2,LED_OFF,0);
|
||
break;
|
||
|
||
case LED_ERROR_CRITICAL:
|
||
led_vote_error(led_handle_1,ERROR_CRITICAL);
|
||
break;
|
||
|
||
case LED_ERROR_WARNING:
|
||
led_vote_error(led_handle_1,ERROR_WARNING);
|
||
break;
|
||
|
||
case LED_ERROR_CRITICAL_CLOSE:
|
||
led_resolve_error(led_handle_1,ERROR_CRITICAL);
|
||
break;
|
||
|
||
case LED_ERROR_WARNING_CLOSE:
|
||
led_resolve_error(led_handle_1,ERROR_WARNING);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
} |