You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
4.9 KiB

4 months ago
#ifndef PROTECTION_H
#define PROTECTION_H
#include <stdint.h>
#include <stdbool.h>
/*
* Predefined Fault Types
*/
enum
{
FAULT_HW_BEGIN = 0,
FAULT_HW_VOUT_UVP = FAULT_HW_BEGIN,
FAULT_HW_DP_OVP,
FAULT_HW_DM_OVP,
FAULT_HW_OTP,
FAULT_HW_IOUT_OCP,
FAULT_HW_VOUT_OVP,
FAULT_HW_VBUS_SCP,
FAULT_HW_GATE_UVP,
FAULT_HW_VIN_OVP,
FAULT_HW_VIN_UVP,
FAULT_HW_CC_OV,
FAULT_HW_VCONN_OC,
FAULT_HW_V2_OC,
FAULT_HW_END,
};
enum
{
FAULT_SW_BEGIN = FAULT_HW_END,
FAULT_SW_VOUT_UVP = FAULT_SW_BEGIN,
FAULT_SW_DP_OVP,
FAULT_SW_DM_OVP,
FAULT_SW_OTP,
FAULT_SW_IOUT_OCP,
FAULT_SW_VOUT_OVP,
FAULT_SW_VBUS_SCP,
FAULT_SW_VIN_OVP,
FAULT_SW_VIN_UVP,
FAULT_SW_SYS_ERROR,
FAULT_SW_END,
};
#define FALUT_CODE_END FAULT_SW_END
#define FAULT_ALL_MASK (BIT(FAULT_SW_END) - 1)
#define FAULT_RANGE_MASK(begin, end) ((BIT(end) - 1) & ~(BIT(begin) - 1))
#define FAULT_HW_ALL_MASK FAULT_RANGE_MASK(FAULT_HW_BEGIN, FAULT_HW_END)
#define FAULT_SW_ALL_MASK FAULT_RANGE_MASK(FAULT_SW_BEGIN, FAULT_SW_END)
/*
* Fault Status
*/
typedef struct
{
uint32_t flag;
uint32_t status;
uint32_t mask;
} fault_info_s;
void update_fault_status(fault_info_s *status,
uint32_t fault_num, bool in_fault);
void mask_update_fault_status(fault_info_s *status, uint32_t fault_mask, uint32_t mask);
void set_fault_status(fault_info_s *status, uint32_t fault_mask);
void clear_fault_status(fault_info_s *status, uint32_t fault_mask);
static inline void mask_fault(fault_info_s *status, uint32_t fault_num)
{
status->mask |= BIT(fault_num);
}
static inline void unmask_fault(fault_info_s *status, uint32_t fault_num)
{
status->mask &= ~BIT(fault_num);
}
void clear_all_fault_flag(fault_info_s *status);
/*
* Faults detected through software
*/
typedef struct debouncer
{
uint16_t cnt;
uint16_t out;
} debouncer_s;
typedef struct debouncer_param
{
uint16_t up_time;
uint16_t down_time;
} debouncer_param_s;
typedef struct schmitt_trigger
{
uint16_t high_thresh;
uint16_t low_thresh;
} schmitt_trigger_s;
typedef struct
{
debouncer_s deb;
} soft_fault_s;
typedef struct
{
debouncer_param_s debouncer_param;
schmitt_trigger_s schmitt;
uint8_t trigger_type;
uint8_t fault_name;
} soft_fault_param_s;
#define TRIGGER_HIGH 0
#define TRIGGER_LOW 1
#define DEBOUNCER_INIT(initial_cnt, initial_output) \
{ \
.cnt = (initial_cnt), .out = (initial_output), \
}
#define SCHMITT_TRIGGER_INIT(high, low) \
{ \
.high_thresh = (high), \
.low_thresh = (low), \
}
#define SOFT_FAULT_PARAM_INIT(_high_thresh, _low_thresh, _trigger_time, _recover_time, _trigger_type, name) \
{ \
.debouncer_param = \
{ \
.up_time = (_trigger_time), \
.down_time = (_recover_time), \
}, \
.schmitt = SCHMITT_TRIGGER_INIT(_high_thresh, _low_thresh), \
.trigger_type = (_trigger_type), \
.fault_name = (name), \
}
bool soft_fault_check(soft_fault_s *fault, uint16_t input,
const soft_fault_param_s *param,
fault_info_s *status);
static inline void update_soft_fault_thresholds(soft_fault_param_s *param,
uint16_t high, uint16_t low)
{
param->schmitt.high_thresh = high;
param->schmitt.low_thresh = low;
}
typedef struct
{
soft_fault_s fault;
soft_fault_param_s param;
} soft_fault_ext_s;
#define SOFT_FAULT_EXT_INIT(_high_thresh, _low_thresh, _trigger_time, _recover_time, _trigger_type, name) \
{ \
.fault = { .deb = DEBOUNCER_INIT((_trigger_time), (0)), }, \
.param = SOFT_FAULT_PARAM_INIT(_high_thresh, _low_thresh, _trigger_time, _recover_time, _trigger_type, name), \
}
void soft_abn_check(soft_fault_ext_s *fault, uint16_t input, fault_info_s *status);
static inline void update_soft_fault_ext_thresholds(soft_fault_ext_s *fault_ext,
uint16_t high, uint16_t low)
{
update_soft_fault_thresholds(&fault_ext->param, high, low);
}
/*
* Fault Manager
*/
struct fault_mgr;
typedef struct fault_mgr fault_mgr_s;
typedef struct fault_mgr_ops
{
bool (*protect)(fault_mgr_s *mgr, uint32_t new_faults);
void (*recover)(fault_mgr_s *mgr);
} fault_mgr_ops_s;
#define FAULT_MGR_STATE_NORMAL 0
#define FAULT_MGR_STATE_FAULT 1
struct fault_mgr
{
fault_info_s fault_info;
uint32_t last_faults;
uint32_t recover_time;
const fault_mgr_ops_s *ops;
uint8_t state;
uint8_t name;
};
void fault_mgr_set_hiccup_time(fault_mgr_s *mgr, uint16_t hiccup_time);
static inline void regiser_fault_mgr_ops(fault_mgr_s *mgr,
const fault_mgr_ops_s *ops)
{
mgr->ops = ops;
}
void fault_manager_work(fault_mgr_s *mgr);
static inline bool fault_mgr_is_in_fault(fault_mgr_s *mgr)
{
return mgr->state != FAULT_MGR_STATE_NORMAL;
}
#endif /* PROTECTION_H */