#ifndef PROTECTION_H #define PROTECTION_H #include #include /* * 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 */