Просмотр исходного кода

update

Signed-off-by: huhui <huhui@sharkgulf.com>
huhui 5 лет назад
Родитель
Сommit
88f0d92e07

+ 35 - 2
Application/app/sox/health.c

@@ -1,9 +1,11 @@
-#include "health.h"
+#include "bsp/gpio.h"
 #include "bsp/ml5238.h"
+#include "libs/logger.h"
 #include "state.h"
 #include "iostate.h"
+#include "measure.h"
 #include "measure_task.h"
-#include "libs/logger.h"
+#include "health.h"
 
 #define MAX_CURRENT_FOR_CHARGER (20*1000) //最大充电电流20A
 #define MIN_VOLTAGE_FOR_DISCHARGER (2.2f * CELLS_NUM * 1000) //允许能放电的最小电压
@@ -231,6 +233,37 @@ static int _is_low_temp(int8_t *temps){
 	return 0;
 }
 
+static uint8_t small_power_detect_count = 0;
+static void _aux_lock_timer_handler(shark_timer_t *t){
+	//有可能这个时候,用户发了关小电的指令
+	if (bms_state_get()->user_request & USER_REQUEST_SMALLCURRENT){
+		AUX_VOL_OPEN(1);
+		if (++small_power_detect_count >= 10){
+			delay_us(1000);
+			//端口电压小于阈值,判断为小电流短路
+			if (get_small_current_voltage() < SMALL_CURRENT_MIN_VOLTAGE){//real short
+				bms_health()->small_current_short = 1;
+				AUX_VOL_OPEN(0);
+				small_power_detect_count = 0;
+			}
+		}
+	}
+}
+static shark_timer_t _aux_lock_timer = {.handler = _aux_lock_timer_handler};
+void health_process_aux_lock(void){
+	if (io_state()->aux_lock_detect) {
+		if (AUX_VOL_IS_OPEN()){
+			AUX_VOL_OPEN(0);
+			shark_timer_post( &_aux_lock_timer, 1);
+		}
+	}else {
+		bms_health()->small_current_short = 0;
+		small_power_detect_count = 0;
+		shark_timer_cancel(&_aux_lock_timer);
+	}
+}
+
+
 void check_temp_state(void){
 	if (bms_state_get()->charging){
 		if (!_health.charger_over_temp){

+ 2 - 1
Application/app/sox/health.h

@@ -17,15 +17,16 @@ typedef struct {
 	uint32_t sigle_cell_lower_voltage:1;
 	uint32_t sigle_cell_over_voltage:1;
 	uint32_t load_current_short:1; //´óµç¶Ì·±£»¤
+	uint32_t small_current_short:1;
 	uint16_t internal_resistance;   //pack's internal resistance
 }bms_health_t;
 
-
 bms_health_t *bms_health(void);
 void health_init(void);
 void check_current_state(void);
 void check_voltage_state(void);
 void check_temp_state(void);
+void health_process_aux_lock(void);
 
 #endif /* _HEALTH_H__ */
 

+ 40 - 49
Application/app/sox/iostate.c

@@ -2,6 +2,7 @@
 #include "libs/shark_task.h"
 #include "libs/logger.h"
 #include "state.h"
+#include "health.h"
 #include "iostate.h"
 
 static io_state_t _io_state;
@@ -15,12 +16,11 @@ typedef struct io_timer{
 #define io_detect_intv_time 1
 #define io_debounce_time 50
 
-static io_timer_t hall_io;
-static io_timer_t charger_io;
-static io_timer_t aux_short_io;
-static io_timer_t dcdc_pwr_io;
-
 static void io_timer_handler(shark_timer_t *t);
+static io_timer_t hall_io = {._timer.handler = io_timer_handler};
+static io_timer_t charger_io = {._timer.handler = io_timer_handler};
+static io_timer_t aux_short_io = {._timer.handler = io_timer_handler};
+static io_timer_t dcdc_pwr_io = {._timer.handler = io_timer_handler};
 
 static void debug_io(void){
 	uint16_t *io = (uint16_t *)&_io_state;
@@ -33,14 +33,14 @@ void io_state_init(void){
 	_io_state.charger_detect = IS_CHARGER_IN();
 	_io_state.dcdc_good_detect= IS_DCDC_POWER_GOOD();
 	_io_state.aux_lock_detect = IS_AUX_VOL_LOCKED();
-	hall_io._timer.handler = io_timer_handler;
-	charger_io._timer.handler = io_timer_handler;
-	aux_short_io._timer.handler = io_timer_handler;
-	dcdc_pwr_io._timer.handler = io_timer_handler;
+
 	shark_timer_post(&hall_io._timer, io_detect_intv_time);
 	shark_timer_post(&charger_io._timer, io_detect_intv_time);
 	shark_timer_post(&aux_short_io._timer, io_detect_intv_time);
 	shark_timer_post(&dcdc_pwr_io._timer, io_detect_intv_time);
+
+	small_current_short_irq_enable(1);
+	
 	debug_io();
 }
 
@@ -65,39 +65,25 @@ static int _get_io_value(io_timer_t *t){
 }
 
 static void _set_io_value(io_timer_t *t){
-	__disable_irq();
 	if (t == &hall_io) {
 		_io_state.hall_detect = t->value;
-		hall_1_detect_irq_enable(1);
-		hall_2_detect_irq_enable(1);
 	}
 	if (t == &charger_io){
 		_io_state.charger_detect = t->value;
-		charger_detect_irq_enable(1);
-	}
-	if (t == &aux_short_io){
-		_io_state.aux_lock_detect = t->value;
-		small_current_short_irq_enable(1);
 	}
 	if (t == &dcdc_pwr_io){
 		_io_state.dcdc_good_detect = t->value;
-		dcdc_pwr_detect_irq_enable(1);
 	}
-	/* 可以解决丢中断的风险,如果开启中断的过程中,来IO中断,这个中断可能会被丢弃,
-	 * 所以,我们这里要再次检查io的状态和代码保存的状态是否一致,如果不一致需要重新
-	 * 启动定时间
-	*/
-	if (t->value != _get_io_value(t)){
-		shark_timer_post(&t->_timer, io_detect_intv_time);
-	}
-	__enable_irq();
-
+	if (t == &aux_short_io){
+		_io_state.aux_lock_detect = t->value;
+	}	
 	debug_io();
 }
 
 
 static void io_timer_handler(shark_timer_t *t){
 	io_timer_t *io_t = (io_timer_t *)t;
+	int aux_lock_changed = 0;
 	if (io_t->value == _get_io_value(io_t)){
 		io_t->detect_cnt ++;
 	}else{
@@ -107,43 +93,48 @@ static void io_timer_handler(shark_timer_t *t){
 	if (io_t->detect_cnt >= io_debounce_time){
 		io_t->detect_cnt = 0;
 		_set_io_value(io_t);
-	}else{
-		shark_timer_post(t, io_detect_intv_time);
+		if (io_t == &aux_short_io){
+			aux_lock_changed = 1;
+		}
+	}
+	shark_timer_post(t, io_detect_intv_time);
+	if (io_t == &aux_short_io && aux_lock_changed){
+		health_process_aux_lock();
 	}
 }
+
+
+static void small_current_irq_timer_handler(shark_timer_t *t){
+	_io_state.aux_lock_detect = 1;
+	health_process_aux_lock();
+}
+static shark_timer_t _small_current_irq_timer = {.handler = small_current_irq_timer_handler};
+void small_current_short_irq_handler(void){
+	shark_timer_post(&_small_current_irq_timer, 0);
+	io_debug("aux lock irq\n");
+}
+
+
 void charger_detect_irq_handler(void){
-	charger_io.value = IS_CHARGER_IN();
-	charger_io.detect_cnt = 0;
-	shark_timer_post(&charger_io._timer, io_detect_intv_time);
-	charger_detect_irq_enable(0);
+
 	io_debug("charger irq\n");
 }
 void hall1_detect_irq_handler(void){
-	hall_io.value = IS_HALL1_DETECTED()|| IS_HALL2_DETECTED();
-	hall_io.detect_cnt = 0;
-	shark_timer_post(&hall_io._timer, io_detect_intv_time);
-	hall_1_detect_irq_enable(0);
+
 	io_debug("hall 1 irq\n");
 }
 void hall2_detect_irq_handler(void){
-	hall_io.value = IS_HALL1_DETECTED()|| IS_HALL2_DETECTED();
-	hall_io.detect_cnt = 0;
-	shark_timer_post(&hall_io._timer, io_detect_intv_time);
-	hall_2_detect_irq_enable(0);
+
 	io_debug("hall 2 irq\n");
 }
-void small_current_short_handler(void){
-	aux_short_io.value = IS_AUX_VOL_LOCKED();
-	aux_short_io.detect_cnt = 0;
-	shark_timer_post(&aux_short_io._timer, io_detect_intv_time);
-	small_current_short_irq_enable(0);
-	io_debug("aux lock irq\n");
-}
+
+#if 0
 void dcdc_pwr_detect_irq_handler(void) {
 	dcdc_pwr_io.value = IS_DCDC_POWER_GOOD();
 	dcdc_pwr_io.detect_cnt = 0;
-	shark_timer_post(&dcdc_pwr_io._timer, io_detect_intv_time);
+	shark_timer_post(&dcdc_pwr_io._timer, 0);
 	dcdc_pwr_detect_irq_enable(0);
 	io_debug("dcdc lock irq");
 }
+#endif
 

+ 12 - 8
Application/app/sox/measure.c

@@ -35,7 +35,7 @@ static const float v_gd_ref = 3300.0f; //adc ref = 3.3v
 static const float max_gd_adc = 65535.0f;
 static const float v_cs1180_ref = 1235.0f;//cs1180 vref = 1.235v
 static const float max_cs1180_adc = 0x7FFFF;//
-static const float small_cur_r_sense = 360.0f;//mo
+static const float small_cur_r_sense = 360.0f;//欧姆
 static uint8_t adc_used = CS1180_ADC;//|GD32_ADC;
 
 static void __inline__ select_gain_10x(int select){	
@@ -95,9 +95,6 @@ void measure_adc_init(void){
 	adc_init();
 	current_calibrate();
 	cs1180_adc_init();
-	//AUX_VOL_OPEN(1);
-	//ml5238_enable_discharger_mosfet(1);
-	//ml5238_enable_charger_mosfet(1);
 }
 
 /* get battery pack's current (mA) */
@@ -151,16 +148,23 @@ void adc_select_for_pack_current(int adc){
 float get_cell_voltage(int cell){
 	ML5238_SELECT_CELL(cell);
 	delay_us(100);
-	float adc = adc_sample_avg(ADC_CHAN_VMON, 34);
+	float adc = adc_sample_avg(ADC_CHAN_VMON, 10);
 
 	return cell_real_vol((adc / max_gd_adc) * v_gd_ref);
 }
 
-/* get battery pack's aux current (mA) */
+/* get battery pack's aux current (MA) */
 float get_small_current(void){
-	float adc = adc_sample(ADC_CHAN_AUX_CURR, TRUE);
+	float adc = adc_sample_avg(ADC_CHAN_AUX_CURR, 10);
 
-	return (adc / max_gd_adc * v_gd_ref) / small_cur_r_sense * 1000;
+	return ((adc / max_gd_adc * v_gd_ref)) / small_cur_r_sense;
+}
+
+/* 用来判断小电流的情况下,电压小于某一个值认为小电流真正短路,比如16v*/
+float get_small_current_voltage(void){
+	float s_current_a = get_small_current();//MA
+
+	return s_current_a * (small_cur_r_sense + 28.0f);//28欧姆是mos的D极两个56的并联
 }
 
 int get_pcb_temperature(void){

+ 1 - 0
Application/app/sox/measure.h

@@ -5,6 +5,7 @@ void adc_select_for_pack_current(int adc);
 float get_pack_current(void);
 float get_cell_voltage(int cell);
 float get_small_current(void);
+float get_small_current_voltage(void);
 int get_pcb_temperature(void);
 int get_pack_temperature(int index);
 

+ 21 - 5
Application/app/sox/state.c

@@ -36,6 +36,7 @@ void bms_state_init(void){
 bms_state_t *bms_state_get(void){
 	return &_bms_state;
 }
+
 /*
  放电mos和充电mos的开关要小心:
  1. 大部分的情况下,尽量能做到同时开关,主要是用来保护被关闭那路mos的体二极管(不能过大电流)
@@ -85,10 +86,10 @@ static s32 _process_unheath(void){
 		return Health_Discharger_Failt;
 	}
 
-	if (io_state()->aux_lock_detect && AUX_VOL_IS_OPEN()) {
-		AUX_VOL_OPEN(0);
+	if (io_state()->aux_lock_detect || bms_health()->small_current_short) {
 		return Health_aux_Fault;
 	}
+	
 	return Health_Success;
 }
 
@@ -105,7 +106,7 @@ static void _process_user_request(s32 health){
 		if ((health & Health_aux_Fault) == 0){
 			AUX_VOL_OPEN(!!(_bms_state.user_request & USER_REQUEST_SMALLCURRENT));
 		}	
-		_bms_state.user_request = 0;//clear user request
+		_bms_state.user_request &= ~USER_REQUEST_PENDING;//clear user request pending
 	}
 }
 
@@ -136,9 +137,24 @@ static void _process_deepsleep(s32 health){
 	if (ml5238_is_charging() || ml5238_is_discharging() || IS_CHARGER_IN()){
 		return;
 	}
-	if (!(io_state()->hall_detect)){
-		mcu_enter_deepsleep();
+
+	if(io_state()->hall_detect){
+		return;
+	}
+
+	/*if (红外或者485通信没有超时){
+		return;
+	}*/
+
+	AUX_VOL_OPEN(1); 
+
+	delay_us(5000);//delay 5ms, to detect if short current
+
+	if (io_state()->aux_lock_detect){
+		return;
 	}
+	
+	mcu_enter_deepsleep();
 #endif	
 }
 

+ 3 - 0
Application/app/sox/state.h

@@ -19,6 +19,9 @@
 #define MAX_DIFF_BETWEEN_MIN_MAX_CELL 150 //0.15v ,压差超过这个值,开始balance
 #define MIN_DIFF_BETWEEN_MIN_MAX_CELL 050 //0.05v, 牙差低于这个数据,停止balance
 #define CELL_FUSION_VOLTAGE      3500 //LFP电池在3.5v的时候,开始发散,需要判断是否要balance
+#define SMALL_CURRENT_MIN_VOLTAGE (16.0f * 1000.0f) //判断小电流是否真实短路的,端口最小电压
+
+
 typedef struct{
 	uint16_t charging: 1;
 	uint16_t pack_balancing:1;

+ 2 - 0
Application/bsp/bsp.c

@@ -1,5 +1,6 @@
 #include "bsp/shark_bsp.h"
 #include "bsp/gpio.h"
+#include "bsp/uart.h"
 
 #if defined CONFIG_BOARD_SP700
 const char iap_board_name[] __attribute__((at(0x08002800))) = "SP700";
@@ -17,6 +18,7 @@ void bsp_init(void){
 	DCDC_VOL_OPEN(1);
 	system_clock_config(); //after dcdc open, MCU can run on full speed
 	SystemCoreClockUpdate();
+	shark_uart_init();
 }
 
 void wdog_start(int timeout){

+ 67 - 18
Application/bsp/gd32_adc.c

@@ -19,7 +19,7 @@ void adc_init(void){
 	gpio_mode_analog_input(GPIOB, GPIO_PIN_1|GPIO_PIN_0);
 
     /* config ADC clock */
-    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); //adc clock:28M 
+    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); //adc clock:7M 
 
 	rcu_periph_clock_enable(RCU_ADC);
 	adc_deinit();
@@ -37,7 +37,9 @@ void adc_init(void){
 	adc_discontinuous_mode_config(ADC_REGULAR_CHANNEL, 1);
 
 	adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
-
+#ifdef DMA_ADC_CH	
+	dma_config();
+#endif
 }
 
 #ifdef DMA_ADC_CH
@@ -71,39 +73,44 @@ void dma_config(void)
 }
 
 /* step 1 */
-int adc_start_sample(int chan){
+int adc_is_idle(void){
+	return adc_work == ADC_WORK_IDLE;
+}
+
+int adc_start_sample(int chan, int number){
 	//hardware oversample to 16bit
 	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
 	adc_oversample_mode_enable();
     /* use max convert time to make sure the adc work fine */
-    adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//239.5 + 12.5 = 242 cycle, 242/(28*1000000)
+    adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//55.5 + 12.5 = 68 cycle, 68/(7*1000000)
 	adc_enable();
-	adc_work = ADC_WORK_ING;
-}
-/* step 2 */
-int adc_start_calibration(void){
-	/* ADC calibration and reset calibration */
+	delay_us(1000); //MUST delay, for adc work fine
+	
 	adc_calibration_enable();
-}
-int adc_sample_avg(int chan, int times){
-    /* configure the number of remaining data to be transferred */
-    DMA_CHCNT(DMA_ADC_CH) = (times & DMA_CHANNEL_CNT_MASK);	
+    DMA_CHCNT(DMA_ADC_CH) = (number & DMA_CHANNEL_CNT_MASK);	
 	dma_channel_enable(DMA_ADC_CH);
 	/* ADC DMA function enable */
     adc_dma_mode_enable();
     /* ADC software trigger enable */
     adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
+	adc_work = ADC_WORK_ING;
 }
 
+
 void DMA_Channel0_IRQHandler(void){
 	adc_disable();
-	dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
 	dma_channel_disable(DMA_ADC_CH);
+	dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
+	adc_work = ADC_WORK_SAMPLE_COMPLTE
+}
+
+int adc_is_complete(void){
+	return adc_work == ADC_WORK_SAMPLE_COMPLTE;
 }
 
 int adc_get_sample(void){
-	if (adc_work != ADC_WORK_FINISH){
-		return 0x7FFFFFFF;
+	if (adc_work != ADC_WORK_SAMPLE_COMPLTE){
+		return adc_work;
 	}
 	int value = 0;
 	int count = DMA_CHCNT(DMA_ADC_CH) & DMA_CHANNEL_CNT_MASK;	
@@ -120,10 +127,51 @@ int adc_get_sample(void){
 			min = one;
 		}
 	}
-	adc_work = ADC_WORK_FINISH;
+	adc_work = ADC_WORK_IDLE;
 	return (value - min - max)/(count - 2);
 }
 
+int adc_sample_avg(int chan, int times){
+	int value = 0;
+	int count = 0;
+	int min = 0xFFFFF;
+	int max = -0xFFFFF;
+	if (adc_work == ADC_WORK_ING){
+		adc_disable();
+		dma_channel_disable(DMA_ADC_CH);
+		adc_dma_mode_disable();
+		dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
+		adc_work = ADC_WORK_IDLE;
+	}
+	//hardware oversample to 16bit
+	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
+	adc_oversample_mode_enable();
+    /* use max convert time to make sure the adc work fine */
+    adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
+	adc_enable();
+	delay_us(1000); //MUST delay, for adc work fine
+	/* ADC calibration and reset calibration */
+	adc_calibration_enable();
+
+	while(count < times){
+		adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
+    	while(SET != adc_flag_get(ADC_FLAG_EOC));
+    	int one = adc_regular_data_read();
+		adc_flag_clear(ADC_FLAG_EOC);		
+		value += (one & 0xFFFF);
+		count ++;
+		if (one > max){
+			max = one;
+		}
+		if (one < min) {
+			min = one;
+		}
+	}
+	adc_disable();
+	return (value - min - max)/(times-2);
+}
+
+
 #else
 
 int adc_sample(int chan, int calibration){
@@ -151,6 +199,7 @@ int adc_sample(int chan, int calibration){
 	return value & mask;
 }
 
+//times * 2.4ms
 int adc_sample_avg(int chan, int times){
 	int value = 0;
 	int count = 0;
@@ -160,7 +209,7 @@ int adc_sample_avg(int chan, int times){
 	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
 	adc_oversample_mode_enable();
     /* use max convert time to make sure the adc work fine */
-    adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//239.5 + 12.5 = 242 cycle, 242/(28*1000000)
+    adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
 	adc_enable();
 	delay_us(1000); //MUST delay, for adc work fine
 	/* ADC calibration and reset calibration */

+ 2 - 1
Application/bsp/gd32_adc.h

@@ -12,7 +12,8 @@
 
 #define ADC_WORK_IDLE 0
 #define ADC_WORK_ING 1
-#define ADC_WORK_FINISH 2
+#define ADC_WORK_SAMPLE_COMPLTE 2
+#define ADC_WORK_FINISH 3
 
 int adc_sample(int chan, int calibration);
 int adc_sample_avg(int chan, int times);

+ 1 - 1
Application/bsp/gpio.c

@@ -131,7 +131,7 @@ void hall_2_detect_irq_enable(int enable){
 void small_current_short_irq_enable(int enable){
 	if (enable){
 		syscfg_exti_line_config(EXTI_SOURCE_GPIOB, EXTI_SOURCE_PIN11);
-		exti_init(EXTI_11, EXTI_INTERRUPT, EXTI_TRIG_BOTH);
+		exti_init(EXTI_11, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
 		nvic_irq_enable(EXTI4_15_IRQn, 4U, 0U);
 		exti_interrupt_flag_clear(EXTI_11);
 		exti_interrupt_enable(EXTI_11);

+ 51 - 15
Application/bsp/i2c.c

@@ -6,12 +6,14 @@
 static int _gd32_i2c_rw_bytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *buffer, int length, int write);
 
 #define iic_device(id) ((id == 0)?I2C0:I2C1)
+static uint32_t i2c_clk[2];
+static uint8_t i2c_busy_count[2];
 
 static void _delay_1us(uint32_t n)
 {
 	while(n-->0)
 	{
-		int N=1000;
+		int N=100;
 		while(N-->0);
 	}
 }
@@ -36,27 +38,56 @@ static void _i2c_deinit(uint32_t i2c_periph)
     }
 }
 
+/*
+ * 当读写i2c slave设备的时候,MCU复位,有概率会导致slave设备永远会锁住总线,导致永远busy,复位MCU无效
+ * 这里,需要通过i2c的reset位配合sda,sck拉高,强行让slave释放总线
+*/
+static void gd32_i2c_busy_recovery(uint32_t i2c_periph){
+	if (i2c_periph == I2C0) {
+		gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8|GPIO_PIN_9);
+		gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8|GPIO_PIN_9);
+		gpio_bit_set(GPIOB, GPIO_PIN_6);
+		gpio_bit_set(GPIOB, GPIO_PIN_7);
+	} else {
+		gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10|GPIO_PIN_11);
+		gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10|GPIO_PIN_11);
+		gpio_bit_set(GPIOB, GPIO_PIN_10);
+		gpio_bit_set(GPIOB, GPIO_PIN_11);
+	}
+	i2c_software_reset_config(i2c_periph, 1);
+	_delay_1us(10);
+	i2c_software_reset_config(i2c_periph, 0);
+}
+
 
 void gd32_i2c_init(uint32_t i2c_device, uint32_t rate){
 	uint32_t device = iic_device(i2c_device);
 
 	rcu_periph_clock_enable(RCU_GPIOB);
 	if (device == I2C0) {
-		gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8|GPIO_PIN_9);
-		gpio_mode_af(GPIOB ,GPIO_PUPD_NONE, GPIO_PIN_8|GPIO_PIN_9);
 		rcu_periph_clock_enable(RCU_I2C0);
+		gd32_i2c_busy_recovery(I2C0);
 		_i2c_deinit(I2C0);
-	 	
-	} else {
-		gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_10|GPIO_PIN_11);
-		gpio_mode_af(GPIOB ,GPIO_PUPD_NONE, GPIO_PIN_10|GPIO_PIN_11);	
+		gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8|GPIO_PIN_9);
+		gpio_mode_af(GPIOB ,GPIO_PUPD_NONE, GPIO_PIN_8|GPIO_PIN_9);	 	
+	} else {	
 		rcu_periph_clock_enable(RCU_I2C1);
+		gd32_i2c_busy_recovery(I2C1);
 		_i2c_deinit(I2C1);
+		gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_10|GPIO_PIN_11);
+		gpio_mode_af(GPIOB ,GPIO_PUPD_NONE, GPIO_PIN_10|GPIO_PIN_11);		
 	}
 	i2c_clock_config(device, rate, I2C_DTCY_2);
 	i2c_enable(device);
 }
 
+void gd32_i2c_deinit(uint32_t i2c_index){
+	uint32_t device = iic_device(i2c_index);
+	i2c_disable(device);
+	_i2c_deinit(device);
+	rcu_periph_clock_disable(RCU_I2C0);
+}
+
 
 static int gd32_i2c_write_address(uint32_t deivce, uint8_t address, uint8_t write){
 	uint32_t times;
@@ -65,7 +96,7 @@ static int gd32_i2c_write_address(uint32_t deivce, uint8_t address, uint8_t writ
 	}
  
     I2C_DATA((deivce)) = address;
- 	for (times = 10000; times > 0; times--) {
+ 	for (times = 500; times > 0; times--) {
   		if (i2c_flag_get((deivce), I2C_FLAG_ADDSEND)) {
    			return 0;
   		}
@@ -93,7 +124,7 @@ int gd32_i2c_write_nbytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t
 
 
 static int gd32_i2c_wait_flags(uint32_t i2c_periph, i2c_flag_enum flag, FlagStatus status){
-	int remain = 100000;
+	int remain = 500;
 	while (i2c_flag_get(i2c_periph, flag) != status) {
 		if (remain-- <= 0){
 			return -1;
@@ -103,7 +134,7 @@ static int gd32_i2c_wait_flags(uint32_t i2c_periph, i2c_flag_enum flag, FlagStat
 }
 
 static void gd32_i2c_wait_stop(uint32_t i2c_periph){
-	int remain = 100000;
+	int remain = 500;
 	while(I2C_CTL0(i2c_periph) & 0x0200){
 		if (remain-- <= 0){
 			break;
@@ -111,18 +142,23 @@ static void gd32_i2c_wait_stop(uint32_t i2c_periph){
 	};
 }
 
-static int _gd32_i2c_rw_bytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *buffer, int length, int write){
+static int _gd32_i2c_rw_bytes(uint32_t i2c_index, uint8_t address, uint8_t reg, uint8_t *buffer, int length, int write){
 	int ret = length;
-	uint32_t device = iic_device(index);
+	uint32_t device = iic_device(i2c_index);
 
 	i2c_ackpos_config(device, length == 2?I2C_ACKPOS_NEXT:I2C_ACKPOS_CURRENT);
 	i2c_ack_config(device, I2C_ACK_ENABLE);
 
 	if (gd32_i2c_wait_flags(device, I2C_FLAG_I2CBSY, RESET) < 0){
-		ret = -1;
-		goto out_i2c_stop_on_bus;
+		i2c_busy_count[i2c_index]++;
+		if (i2c_busy_count[i2c_index] >= 10) {
+			gd32_i2c_deinit(i2c_index);
+			gd32_i2c_init(i2c_index, i2c_clk[i2c_index]);
+		}
+		return -1;
 	}
-	
+	i2c_busy_count[i2c_index] = 0;
+
 	//send reg
 	i2c_start_on_bus(device);
 

+ 2 - 2
Application/bsp/irqs.c

@@ -92,7 +92,7 @@ void __weak ml5238_irq_handler(void){}
 void __weak charger_detect_irq_handler(void){}
 void __weak hall1_detect_irq_handler(void){}
 void __weak hall2_detect_irq_handler(void){}
-void __weak small_current_short_handler(void){}
+void __weak small_current_short_irq_handler(void){}
 void __weak dcdc_pwr_detect_irq_handler(void) {}
 void EXTI4_15_IRQHandler(void){
 	if(RESET != exti_interrupt_flag_get(EXTI_4)){
@@ -120,7 +120,7 @@ void EXTI4_15_IRQHandler(void){
 	}
 	if(RESET != exti_interrupt_flag_get(EXTI_11)){
 		exti_interrupt_flag_clear(EXTI_11);
-		small_current_short_handler();
+		small_current_short_irq_handler();
 	}
 	//ms5238 irq
 	if(RESET != exti_interrupt_flag_get(EXTI_12)){

+ 8 - 0
Application/bsp/mcu_power_sleep.c

@@ -13,6 +13,13 @@ static void enable_wakeup_irq(void){
 	hall_2_detect_irq_enable(1);
 }
 
+static void disable_wakeup_irq(void){
+	charger_detect_irq_enable(0);
+	hall_1_detect_irq_enable(0);
+	hall_2_detect_irq_enable(0);
+}
+
+
 static void pre_deepsleep(void){
 #if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)
 	UART0_IR_EN(0);
@@ -57,6 +64,7 @@ void mcu_enter_deepsleep(void){
 	pre_deepsleep();
 	enable_wakeup_irq();
 	pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
+	disable_wakeup_irq();
 	post_deepsleep();
 }
 

+ 16 - 0
Project/SP700.uvoptx

@@ -181,6 +181,22 @@
           <ExecCommand></ExecCommand>
           <Expression>\\SP700\../Application/app/sox/state.c\114</Expression>
         </Bp>
+        <Bp>
+          <Number>2</Number>
+          <Type>0</Type>
+          <LineNumber>194</LineNumber>
+          <EnabledFlag>1</EnabledFlag>
+          <Address>0</Address>
+          <ByteObject>0</ByteObject>
+          <HtxType>0</HtxType>
+          <ManyObjects>0</ManyObjects>
+          <SizeOfObject>0</SizeOfObject>
+          <BreakByAccess>0</BreakByAccess>
+          <BreakIfRCount>0</BreakIfRCount>
+          <Filename>..\Application\app\sox\health.c</Filename>
+          <ExecCommand></ExecCommand>
+          <Expression></Expression>
+        </Bp>
       </Breakpoint>
       <WatchWindow1>
         <Ww>