1
0

214 کامیت‌ها 1454ac52bd ... 7681b0e8eb

نویسنده SHA1 پیام تاریخ
  kevin 7681b0e8eb 1. 重新加入充电充满后的放电校准系数 2 سال پیش
  kevin 1fbcf29a47 Revert "只有老化模式才显示最小容量" 2 سال پیش
  kevin d5b6894e31 只有老化模式才显示最小容量 2 سال پیش
  kevin 1b6569f302 解决放电系数在低温下的计算问题 2 سال پیش
  kevin 2a605fea03 加入充电过流日志 2 سال پیش
  kevin 098a237bae 放电系数需要通过充满电压进行二次校准 2 سال پیش
  huhui 8b4b845ca6 加入工厂测试结果写入和读取 3 سال پیش
  FuangCao cebc698778 support read chip id 3 سال پیش
  huhui 2be05d4b25 add discharger mos on/off record 3 سال پیش
  huhui 8871bfacd3 Revert "韩国低温充电" 3 سال پیش
  huhui 067b750fb9 韩国低温充电 3 سال پیش
  huhui 2cb20034c7 只有欠压后,充满才会校准最小容量 3 سال پیش
  huhui 48588cc5e8 fix build error 3 سال پیش
  huhui fd3329207d 上次充满不超过5天,本次充满后可以减小最小容量 3 سال پیش
  huhui b355f4a330 change version to V6 3 سال پیش
  huhui 62dbd09142 change version to V6 3 سال پیش
  huhui 2f9d1eab8e uart改回DMA模式,环形buffer初始化复位读写指针 3 سال پیش
  huhui aad41f79c8 debug 版本号00 3 سال پیش
  huhui ccd49d6277 休眠第一次2s唤醒,检查hall 3 سال پیش
  huhui 7506156905 1. uart 驱动使用uart接收,dma有问题 3 سال پیش
  huhui e3d4564716 修改版本号V6 3 سال پیش
  huhui 900b59fe3f 修改log,_discharger_no_full_coef 为 %f 3 سال پیش
  huhui 531deb9a53 解决正常充满,无法校准最小容量的问题 3 سال پیش
  huhui 800199f527 cell 均衡启动后,需要再电流回调中判断是否要停止均衡 3 سال پیش
  huhui a3993a9fcd 解决编译问题 3 سال پیش
  huhui b5ee69963c Merge remote-tracking branch 'origin/fast_discharger' into dev 3 سال پیش
  huhui 8ee0aa62bc Merge remote-tracking branch 'origin/master' into fast_discharger 3 سال پیش
  huhui 2e8905ac6a 开power的时候返回base info的信息,减少psxxx的交互指令 3 سال پیش
  huhui d423e89c55 1. 小电流触发保护,强制开启20次,原来10次, 1小时温升25° 3 سال پیش
  huhui 6780253c1f 加入soc版本号的判断 3 سال پیش
  huhui 22027b6a04 Merge remote-tracking branch 'origin/master' into fast_discharger 3 سال پیش
  huhui 0b5af4679a 强制充满不胖的充了多少容量 3 سال پیش
  huhui 857fab46f7 加入powerdown指令 3 سال پیش
  huhui c739e6f8ab 充满总压调整到53.5v,和53v 3 سال پیش
  huhui a8860abe8a 充电充满后,通过内部安时积分的计算加快放大倍率 3 سال پیش
  huhui cb02d83904 Merge remote-tracking branch 'origin/master' into dev 3 سال پیش
  huhui 14c075045c 记录欠压过压时的电流 3 سال پیش
  huhui 1de06f1726 Merge remote-tracking branch 'origin/master' into dev 3 سال پیش
  huhui dd08fa04f2 为校准的情况下,电池从小于100到100,置校准标志 3 سال پیش
  huhui cb3659fd28 欠压powerdown的计数器保持和欠压关电一致 3 سال پیش
  huhui a8dff1a287 event recoder 和master兼容 3 سال پیش
  huhui 01c31a96c2 Merge remote-tracking branch 'origin/master' into dev 3 سال پیش
  huhui b689397e82 充电保护不考虑是否在车上 4 سال پیش
  huhui 0000a4a290 解决新批次F330休眠功耗的问题 4 سال پیش
  huhui 868be32aa3 欠压校准最小容量事件2处理 4 سال پیش
  huhui 51ff9d12ed fix build warnning for sp600 4 سال پیش
  huhui c822b070f3 dev 分支版本号改为00 4 سال پیش
  huhui a49ae0cf9e Merge remote-tracking branch 'origin/master' into balance 4 سال پیش
  huhui b88a74c306 修复均衡时电芯的选择 4 سال پیش
  huhui 9b085ab068 event log温度上报错误 4 سال پیش
  huhui b5b941b6d4 按照手册ML5238的spi访问片选加一小延时 4 سال پیش
  huhui 50577b850e Revert "电流软保护这算到1s" 4 سال پیش
  huhui 423fe71c96 电压采集和电流采集分开,接近电压保护点的时候,需要加快电压采集 4 سال پیش
  huhui aafb6445f4 调整代码,便于理解 4 سال پیش
  huhui c743407e5f x10 gain下,电流持续小于10A,切到x50 gain 4 سال پیش
  huhui d234db62ca Merge remote-tracking branch 'origin/master' into balance 4 سال پیش
  huhui f07384fbe7 单电芯过压,欠压的时候记录4个温度信息 4 سال پیش
  huhui 0317ca6d13 电流软保护这算到1s 4 سال پیش
  huhui 60f5b3ca38 1. change delay_us when enable delay ticks, use delay ticks 4 سال پیش
  huhui e1396c0248 修改ML5238的gain的动态调整 4 سال پیش
  huhui a613a378e7 小电流短路过滤小于1s间隔的事件 4 سال پیش
  huhui 602d57fbc4 修复delay_us差太多的问题 4 سال پیش
  huhui 285b1f4c08 解决判定balance的错误 4 سال پیش
  huhui ed378d522a 重写被动均衡 4 سال پیش
  huhui e58c2423ec 欠压,过压log,单电芯用12bit表示,单位10mV 4 سال پیش
  huhui 893db73be2 过压,欠压记录最大最小电芯电压和总压 4 سال پیش
  huhui 896cc8ea12 解决重满校准最小容量,计算错误 4 سال پیش
  huhui 6e36e50e32 测量电芯电压选择电芯后需要等待事件到100us,原来只有16us 4 سال پیش
  huhui a5a7a09371 修改最小容量,需要处理当前容量 4 سال پیش
  huhui 35d5d22b98 PCBA测试:加入诊断灯的测试 4 سال پیش
  huhui 9afdda875a 充满校准最小容量后,记录最小容量 4 سال پیش
  huhui 00375c15f7 充满的时候,记录容量 4 سال پیش
  huhui a54c9dabf8 欠压后,24小时充满电,校准最小容量 4 سال پیش
  huhui 14e556f6fc 充满校准最小容量,使用0.2的低通滤波 4 سال پیش
  huhui c8700c1a62 解决如果有最小容量,会导致最小容量越来越大 4 سال پیش
  huhui af974ba146 add option for re-calibration what need clear life cycle 4 سال پیش
  huhui 64b7fc11c5 add max current event, and recorder min/max cell index 4 سال پیش
  huhui 3dad5f6f8c reset cell balance counter, when don't need balance 4 سال پیش
  huhui 1936d8d4ec 霍尔动都恢复到500ms,控制器修改电容 4 سال پیش
  huhui 3a5d030e75 充满后,如果计算的最小容量比原来的大,不更新最细容量,充电只可能让最小容量变小 4 سال پیش
  huhui 34b8ca4785 解决SP600编译错误的问题 4 سال پیش
  FuangCao 772059ee54 auto build config file add project name 4 سال پیش
  huhui 056d455876 判断电压状态在进入和recovery电压之间的时候需要复位计数器 4 سال پیش
  huhui d1797db441 Revert "加入I2c的出错恢复和log" 4 سال پیش
  huhui 9b74a868ff Revert "调整ML5238增益" 4 سال پیش
  huhui e3d53503ea 霍尔防抖修改到300ms 4 سال پیش
  huhui e5a0d0a28d 加入I2c的出错恢复和log 4 سال پیش
  huhui fd3c727216 调整ML5238增益 4 سال پیش
  huhui 42fc523233 Revert "放电过流软保护增加4倍的时间" 4 سال پیش
  huhui 789013a43c before reboot, need save soc 4 سال پیش
  huhui b487969e5c 霍尔防抖动修改为200ms,解决快速拨插电池导致大电没来得及关闭,短路的问题(新控制器电容变大了) 4 سال پیش
  huhui 4eec77a10c 老化模式,只有电流大于2A,才开始记录温度和时间 4 سال پیش
  huhui 386c6631d6 监测老化放电的温感差值 4 سال پیش
  huhui 125285ceae 老化模式加入温度采集保存,给测试工具读取 4 سال پیش
  huhui cf97e037d5 检测不到hall,退出老化模式 4 سال پیش
  huhui 1735e38d0f change version to V5 4 سال پیش
  huhui a6fa8c8ed2 add sp710 board 4 سال پیش
  huhui 5fa3ec268c 非老化模式,判充满54v 4 سال پیش
  huhui da183ca2dd 单电芯过压调整为3.65v 4 سال پیش
  huhui 240f77ca54 直接连接充电器,如果电量为100%,不充电 4 سال پیش
  huhui 171b3cca79 update cht8305 4 سال پیش
  huhui 32f20c10d4 Merge remote-tracking branch 'origin/cht8305_20220127' into pack_v2 4 سال پیش
  huhui 1393f21834 加入cht8305的初始化和复位,否则i2c 操作会出问题 4 سال پیش
  huhui c8e5712124 整车判断充满不判断电流,只要是正常充电,电压大于等于53.5判满 4 سال پیش
  huhui 08823ee878 单电芯过压修改为3.6v 4 سال پیش
  huhui 16fe5c6374 SP700新V2 pack pcb加入诊断LED灯 4 سال پیش
  huhui 044619e1ad fix: 老化模式也需要处理powerdown 4 سال پیش
  huhui 90a6fbd4f1 充满5s内主动关闭充电mos,不接受开充电mos指令 4 سال پیش
  huhui 20254a64a1 新协议PSxxx发送CAN_KEY_BMS_BASE_INFO的时候可以带上电池的使用环境,车上,还是在充电底座上 4 سال پیش
  huhui 12cfa531e2 fix: 充放电mos同开的时间判断修复 4 سال پیش
  huhui b7be44fa5c 放电过流软保护增加4倍的时间 4 سال پیش
  huhui a16ddf714b 返回health,is_charger_in 4 سال پیش
  huhui 27aaefd389 nv storage: when save all or erase, must stop write timer 4 سال پیش
  huhui 2d7f5e37b7 Revert "老化充满53.4v,配合老化柜" 4 سال پیش
  huhui 1190238140 老化充满53.4v,配合老化柜 4 سال پیش
  huhui af1cbc02fb 老化判断充满改为53v, 否则有概率导致老化过程单电芯超压,老化步骤停止 4 سال پیش
  huhui cd9ab20cbf 老化模式,校准的电压条件为53.5v, pack厂建议 4 سال پیش
  huhui e7c66b95b8 老化模式不开启均衡 4 سال پیش
  huhui de1e3bfae7 未校准的情况下,判断电压大于53.5v, 充电容量0.1AH, 认为充满 4 سال پیش
  huhui 8793dfab01 no hall clear ps charger mask 4 سال پیش
  huhui 9c6ce4b563 停止均衡需要确认成功 4 سال پیش
  huhui e7e49de607 总压欠压调整低温27v(15x1.8v), 常温33V(15x2.2v) 4 سال پیش
  huhui 53b6686771 SP600 add event record 4 سال پیش
  huhui 8928556be6 单电芯过压充满,保存总压到event record中 4 سال پیش
  huhui ac7c9b6f45 修改event record 最大存100个 4 سال پیش
  huhui 976b9a5361 去掉voltage的一些调试,event_record已经处理了 4 سال پیش
  huhui 8a51916e91 加入温度变化的事件 4 سال پیش
  huhui c7c8e15984 低温放到5度,低温恢复10度,低温单电芯1.8v欠压 4 سال پیش
  FuangCao 44a4362e95 remove fake log records 4 سال پیش
  FuangCao 186fc847ac Solve the problem of event log misaligned access 4 سال پیش
  huhui 572dbc3ad7 add test data 4 سال پیش
  huhui 167e33f640 change id to u32 4 سال پیش
  huhui 171d3b6347 add event record 4 سال پیش
  huhui 02ca1b8ece 单电芯过压,如果充电0.1HA,才强制电量满 4 سال پیش
  huhui 95598b1ac7 Revert "uart tx 配置为输入上拉,解决5.0板子功耗过高的问题" 4 سال پیش
  huhui a6b4556d63 enable porta clk in gpio_init 4 سال پیش
  huhui 8a8c5a2a71 板子休眠功耗修改为500uA 4 سال پیش
  huhui 1069c44d98 uart tx 配置为输入上拉,解决5.0板子功耗过高的问题 4 سال پیش
  huhui 024ca50409 fix: log error 4 سال پیش
  huhui 7fbe41080e nv storage update, when write error, don't update write index 4 سال پیش
  huhui f94e4e7869 fix: i2c recovery的clk没有初始化,i2c的rxtx配置为OD模式 4 سال پیش
  huhui 7c85893523 充电满,校准最小容量,加入0.5的低通滤波 4 سال پیش
  huhui 9656503b62 fix: build error 4 سال پیش
  huhui dc0f376c9e 未校准,欠压后清除最小容量 4 سال پیش
  huhui 005b258869 fix: recorder charger over voltage && discharger lower voltage error 4 سال پیش
  huhui 00ba217bd1 充电full后,调整最小容量,根据当前的容量和最大容量 4 سال پیش
  huhui bdd15cb6f6 修小容量:电流45A,取0.95,大于45A,取0.9 4 سال پیش
  huhui 3cec230040 单mos开,强开另外的mos等待时间给稍微长一些 4 سال پیش
  huhui e52e612454 记录和清除充放电异常电芯电压 4 سال پیش
  huhui a2c4e382ce 开关charger重试10次 4 سال پیش
  huhui 297f5445af 1. balance 时间3s停100ms 4 سال پیش
  huhui 845db84a7c 欠压充电0.1AH才校准到100% 4 سال پیش
  huhui 938da48a6f 单电芯过压改回3.8v 4 سال پیش
  huhui 77cf234819 fix: 单电芯充电过压,如果总电压小于53V,放电欠压后不记录最小容量 4 سال پیش
  huhui 4b4ddcb3c9 fix: build error 4 سال پیش
  huhui 0330317358 fix: 未充满过,检测到powerdown,最小容量不记录 4 سال پیش
  huhui 363216761e 1. 老化等测试模式下,powerdown不等待5s 4 سال پیش
  huhui 0ea404c096 fix: PCBA 测试,电芯电压测试判断小于3v或者大于3.4V失败 4 سال پیش
  huhui b63fcf814c fix: 老化等测试模式下也需要处理电芯异常情况 4 سال پیش
  huhui 5215610944 fix: 开启均衡前先判断单电芯电压是否过压 4 سال پیش
  huhui 0fe55bc2bd fix: 判断电流大小需要取绝对值 4 سال پیش
  huhui f4a35504b5 调整最小容量策略 4 سال پیش
  huhui 6f378b1883 欠压修改为2.2v,powerdown等待5s 4 سال پیش
  huhui 169d81affe 收到PSxxx发送的指令,清除老化模式 4 سال پیش
  huhui 1651fb378d 修改pcba的电芯电压测试 4 سال پیش
  huhui a575fa402b 欠压改为2.4v,欠压统一从100到200 4 سال پیش
  huhui 45c4bae7f7 Revert "powerdown前先reset一次,确保powerdown正确的" 4 سال پیش
  huhui 16023b3676 Revert "powerdown 之前判断5238是否正常,否则不powerdown和设置最小容量" 4 سال پیش
  huhui 4e10f3600e Revert "powerdown等待5s,同时不统计最小容量" 4 سال پیش
  huhui f9850afead Revert "加入pd down调试" 4 سال پیش
  huhui 0b0d679971 Revert "如果小于0.1C放电,多判断10倍的次数,才能欠压" 4 سال پیش
  huhui e4166ebbfd Revert "加入均衡次数的计数" 4 سال پیش
  huhui 5cd603f494 Revert "未校准状态下欠压,清除最小容量" 4 سال پیش
  huhui 824c188043 Revert "去掉注释掉的代码" 4 سال پیش
  huhui 0aae8890f0 去掉注释掉的代码 4 سال پیش
  huhui 3c4104b49c 未校准状态下欠压,清除最小容量 4 سال پیش
  huhui aa8124c4b0 加入均衡次数的计数 4 سال پیش
  huhui 9a5e8c4e74 如果小于0.1C放电,多判断10倍的次数,才能欠压 4 سال پیش
  huhui 3cfd17f25a 加入pd down调试 4 سال پیش
  huhui 67eef019f6 powerdown等待5s,同时不统计最小容量 4 سال پیش
  huhui 3c4dfb0e0f powerdown 之前判断5238是否正常,否则不powerdown和设置最小容量 4 سال پیش
  huhui 2e7c937a3b powerdown前先reset一次,确保powerdown正确的 4 سال پیش
  huhui 297fc8d02e add ml8238 api, and disable enhance mos driver after 3ms when open 4 سال پیش
  huhui 459c5b821c 放电大于10mA小于500mA,加快5%放电 4 سال پیش
  huhui 4e0378ce83 充电单电芯电压最大3.7v 4 سال پیش
  huhui 7115acbfc4 Revert "每次rtc或者其他方式唤醒后查询hall状态,如果有hall,需要退出休眠" 4 سال پیش
  huhui 5f2c51ddbb 每次rtc或者其他方式唤醒后查询hall状态,如果有hall,需要退出休眠 4 سال پیش
  huhui e48ace5972 1. 未校准的情况下欠压,强制电量为0 4 سال پیش
  huhui 3469d99592 fix: 未校准充电无法显示充满 4 سال پیش
  huhui edd2ca5114 fix: 判断5238和1180的测量出来的电流差值超过500mA,认为1180出错,reset 1180 4 سال پیش
  huhui fc1a60f989 cs1180去掉不用的代码 4 سال پیش
  huhui 5b267270ce fix: 未校准情况下,电池充满判断需要多延时一段时间 4 سال پیش
  huhui 42b0608ef0 update gitignore 4 سال پیش
  huhui 165576fc91 放电过程中,如果当前容量小于最小容量,并且还能继续放电,更新最小容量为当前容量 4 سال پیش
  huhui c738a4837c cs1180 adc return float,提高精度 4 سال پیش
  huhui 3fa8e15b8e 电池在车上放置,电流小于1A,加大放电倍率 4 سال پیش
  huhui 8dccfaf629 before enter sleep clear wakeup source 4 سال پیش
  huhui bfaafb2c1c 解决能量为负,导致剩余里程不准的问题 4 سال پیش
  huhui 4c204e6362 判断当前容量要大于最小容量才更新能量 4 سال پیش
  huhui baeab37666 判断当前容量要大于最小容量才更新电量 4 سال پیش
  huhui 6f92c83769 比较容量不能和0比,需要和最小容量比 4 سال پیش
  huhui 7d2aac42f9 估计容量小于0后,校准容量到最小容量 4 سال پیش
  huhui d6ef185783 加入uart reinit的计数 4 سال پیش
  huhui 5084a9e7f6 1. uart还原使用dma 4 سال پیش
  huhui 2e2a137cd8 通过判断UART_NUM来决定是否初始化第二个串口 4 سال پیش
  huhui b6cdc2832f 1. uart接收改为中断方式 4 سال پیش
  huhui ca37da40b4 加入统计温度移除的次数 4 سال پیش
  huhui 452107cbd2 加入soh的计算和获取 4 سال پیش
  huhui f07dd918b4 打开log同时触发一次打印 4 سال پیش
  huhui 4d0ff1ccc7 修改hall防抖时间,有hall 500ms,没hall 50ms 4 سال پیش
  huhui a373f9e328 加入hall检测不到的调试,记录时间 4 سال پیش
  FuangCao 7bfee8c6d1 add gpio command for pcba test 4 سال پیش
  huhui eb9d1ab98f 老协议接收不判断bms addr 4 سال پیش
  huhui 2ef60b0678 1. 加入精确延时函数task_udelay 4 سال پیش
55فایلهای تغییر یافته به همراه3754 افزوده شده و 600 حذف شده
  1. 1 0
      .gitignore
  2. 117 34
      Application/app/bms_message.c
  3. 72 0
      Application/app/event_record.c
  4. 47 0
      Application/app/event_record.h
  5. 29 5
      Application/app/iap.c
  6. 57 7
      Application/app/nv_storage.c
  7. 12 1
      Application/app/nv_storage.h
  8. 62 3
      Application/app/pcba_test.c
  9. 8 1
      Application/app/protocol.c
  10. 48 31
      Application/app/protocol.h
  11. 19 4
      Application/app/protocol_old.c
  12. 5 3
      Application/app/protocol_old.h
  13. 137 25
      Application/app/sox/health.c
  14. 54 29
      Application/app/sox/health.h
  15. 5 5
      Application/app/sox/iostate.c
  16. 61 17
      Application/app/sox/measure.c
  17. 63 23
      Application/app/sox/measure_task.c
  18. 2 0
      Application/app/sox/measure_task.h
  19. 261 106
      Application/app/sox/soc.c
  20. 14 3
      Application/app/sox/soc.h
  21. 321 80
      Application/app/sox/state.c
  22. 8 2
      Application/app/sox/state.h
  23. 11 1
      Application/bsp/AT24CXX.c
  24. 19 1
      Application/bsp/bsp.c
  25. 71 0
      Application/bsp/cht8305.c
  26. 22 0
      Application/bsp/cht8305.h
  27. 44 2
      Application/bsp/clock.c
  28. 4 2
      Application/bsp/clock.h
  29. 1 27
      Application/bsp/cs1180.c
  30. 12 3
      Application/bsp/gpio.c
  31. 2 0
      Application/bsp/gpio.h
  32. 3 3
      Application/bsp/i2c.c
  33. 10 1
      Application/bsp/mcu_power_sleep.c
  34. 42 1
      Application/bsp/ml5238.c
  35. 4 2
      Application/bsp/ml5238.h
  36. 112 11
      Application/bsp/uart.c
  37. 5 6
      Application/bsp/uart.h
  38. 1 0
      Application/libs/circle_buffer.c
  39. 7 1
      Application/libs/circle_buffer.h
  40. 3 0
      Application/libs/shark_task.h
  41. 15 0
      Application/libs/shark_utils.c
  42. 1 0
      Application/libs/shark_utils.h
  43. 64 52
      Project/SP600.uvoptx
  44. 5 0
      Project/SP600.uvprojx
  45. 64 52
      Project/SP600_15AH.uvoptx
  46. 5 0
      Project/SP600_15AH.uvprojx
  47. 77 53
      Project/SP700.uvoptx
  48. 10 0
      Project/SP700.uvprojx
  49. 976 0
      Project/SP710.uvoptx
  50. 753 0
      Project/SP710.uvprojx
  51. 1 1
      Project/version_sp600.cfg
  52. 1 1
      Project/version_sp600_15AH.cfg
  53. 1 1
      Project/version_sp700.cfg
  54. 2 0
      Project/version_sp710.cfg
  55. 3 0
      shark_build.conf

+ 1 - 0
.gitignore

@@ -20,3 +20,4 @@ sw_build_info.h
 *.PS
 *.WK3
 *.SearchResults
+*.si4project

+ 117 - 34
Application/app/bms_message.c

@@ -4,6 +4,7 @@
 #include "app/sox/measure_task.h"
 #include "app/sox/health.h"
 #include "app/sox/state.h"
+#include "app/sox/iostate.h"
 #include "bsp/gpio.h"
 #include "bsp/ml5238.h"
 #include "bsp/fmc_flash.h"
@@ -12,6 +13,8 @@
 #include "libs/logger.h"
 #include "protocol.h"
 #include "bms_message.h"
+#include "event_record.h"
+#include "protocol_old.h"
 
 extern char* bsp_get_fversion(void);
 
@@ -29,15 +32,62 @@ void bms_message_update_insert(int is_hall_detect){
 	}
 }
 
+static void response_base_info(can_frame_t *frame) {
+	uint8_t *data = NULL;
+	int data_len = 0;	
+	binfo_cmd_resp_t bresp;
+	bresp.capacity = get_soc()->capacity;
+	if (get_soc()->coulomb_now >= get_soc()->coulomb_min) {
+		bresp.energy = get_soc()->coulomb_now - get_soc()->coulomb_min;
+	}else{
+		bresp.energy = 0;
+	}
+	bresp.pack_current = measure_value()->load_current;
+	bresp.pack_voltage = bms_state_get()->pack_voltage;
+	bresp.max_temp = -100;
+	for (int i = 0; i < PACK_TEMPS_NUM; i ++){
+		if (bresp.max_temp < measure_value()->pack_temp[i]){
+			bresp.max_temp = measure_value()->pack_temp[i];
+		}
+	}
+	bresp.health = bms_health()->i_status;
+	if (bms_is_ps_charger_in()) {/*如果在底座或者车上(有充电器),提前置位过高/低温充电标志*/
+		bresp.health |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14);
+	}
+	bresp.health &= ~(1 << 8);
+	bresp.health |= ((get_soc()->flags & SOC_FLAG_CALIBRATED) != 0) << 8;
+	stat_cmd_resp_t sresp;
+	sresp.insert = bms_insert;
+	sresp.is_charging = bms_state_get()->charging;
+	sresp.discharger_fet = ml5238_is_discharging();
+	sresp.charger_fet = ml5238_is_charging();
+	sresp.small_power = AUX_VOL_IS_OPEN();
+	sresp.is_balancing = bms_state_get()->pack_balancing;
+	sresp.health = (((uint16_t )(bms_health()->i_status)) != 0);
+	sresp.is_charger_in = io_state()->charger_detect_irq;
+	bresp.state = *((uint8_t*)&sresp);
+	data = (uint8_t *)&bresp;
+	data_len = sizeof(bresp);
+	if (frame->key == CAN_KEY_BMS_SET_POWER) {
+		u8 response[sizeof(bresp) + 1];
+		response[0] = 0;
+		memcpy(response + 1, data, data_len);
+		data = response;
+		data_len += 1;
+	}
+	protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+}
+
 void process_bms_message(can_frame_t *frame, int len){
 	int result = 0;
 	uint8_t *data = NULL;
 	int data_len = 0;
 	// set_log_all(L_debug);
 	switch(frame->key) {
-		case CAN_KEY_BMS_SET_POWER:
+		case CAN_KEY_BMS_SET_POWER: 
 			if (len != sizeof(pwr_cmd_t) || frame->head.can_addr != 0x42){//开关大电必须42发过来
 				result = 1;
+				protocol_send_ack(frame->head.can_addr, frame->key, result);
 			}else {
 				pwr_cmd_t *cmd = (pwr_cmd_t *)frame->data;
 				uint32_t user_request = USER_REQUEST_PENDING;
@@ -63,38 +113,15 @@ void process_bms_message(can_frame_t *frame, int len){
 					}
 				}
 				bms_state_get()->user_request = user_request;
+				response_base_info(frame);
 			}
-			protocol_send_ack(frame->head.can_addr, frame->key, result);
 			break;
 		case CAN_KEY_BMS_BASE_INFO:{
-			binfo_cmd_resp_t bresp;
-			bresp.capacity = get_soc()->capacity;
-			bresp.energy = get_soc()->coulomb_now - get_soc()->coulomb_min;
-			bresp.pack_current = measure_value()->load_current;
-			bresp.pack_voltage = bms_state_get()->pack_voltage;
-			bresp.max_temp = -100;
-			for (int i = 0; i < PACK_TEMPS_NUM; i ++){
-				if (bresp.max_temp < measure_value()->pack_temp[i]){
-					bresp.max_temp = measure_value()->pack_temp[i];
-				}
-			}
-			bresp.health = *((uint32_t *)bms_health());
-			if (bms_is_ps_charger_in()) {/*如果在底座或者车上(有充电器),提前置位过高/低温充电标志*/
-				bresp.health |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14);
+			if (len >= 1) {
+				uint8_t env = frame->data[0];
+				bms_set_ps_charger_in(1, (env == CW_CHE_SHANG_CHARGER || env == CW_CHONG_DIAN_ZUO));
 			}
-			bresp.health &= ~(1 << 8);
-			bresp.health |= ((get_soc()->flags & SOC_FLAG_CALIBRATED) != 0) << 8;
-			stat_cmd_resp_t sresp;
-			sresp.insert = bms_insert;
-			sresp.is_charging = bms_state_get()->charging;
-			sresp.discharger_fet = ml5238_is_discharging();
-			sresp.charger_fet = ml5238_is_charging();
-			sresp.small_power = AUX_VOL_IS_OPEN();
-			sresp.is_balancing = bms_state_get()->pack_balancing;
-			bresp.state = *((uint8_t*)&sresp);
-			data = (uint8_t *)&bresp;
-			data_len = sizeof(bresp);
-			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+			response_base_info(frame);
 			break;
 		}
 		case CAN_KEY_BMS_CHARG_INFO:{
@@ -109,6 +136,7 @@ void process_bms_message(can_frame_t *frame, int len){
 		case CAN_KEY_BMS_CLEAR:
 			bms_insert_ack = 1;
 			bms_insert = 0;
+			bms_work_mode_set(WORK_MODE_AGING_TEST, 0);
 			protocol_send_ack(frame->head.can_addr, frame->key, result);
 			break;
 		case CAN_KEY_BMS_GET_TIME:{
@@ -126,8 +154,8 @@ void process_bms_message(can_frame_t *frame, int len){
 			sresp.charger_fet = ml5238_is_charging();
 			sresp.small_power = AUX_VOL_IS_OPEN();
 			sresp.is_balancing = bms_state_get()->pack_balancing;
-			uint32_t *h = (uint32_t *)(bms_health());
-			sresp.health = (*h != 0);
+			sresp.health = (((uint16_t )(bms_health()->i_status)) != 0);
+			sresp.is_charger_in = io_state()->charger_detect_irq;
 			data = (uint8_t *)&sresp;
 			data_len = sizeof(sresp);
 			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
@@ -141,7 +169,18 @@ void process_bms_message(can_frame_t *frame, int len){
 			data_len = PACK_TEMPS_NUM * sizeof(int) + 1;
 			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
 			break;
-		}	
+		}
+		case CAN_KEY_AGING_TEMPS:{
+			u8 temps[2 * PACK_TEMPS_NUM * sizeof(int) + 2];
+			temps[0] = bms_state_get()->agint_cost_time/60; //分钟
+			temps[1] = PACK_TEMPS_NUM * 2;
+			memcpy(temps+2, bms_state_get()->aging_start_temp, PACK_TEMPS_NUM * sizeof(int));
+			memcpy(temps+PACK_TEMPS_NUM * sizeof(int)+2, bms_state_get()->aging_max_temp, PACK_TEMPS_NUM * sizeof(int));
+			data = temps;
+			data_len = 2 * PACK_TEMPS_NUM * sizeof(int) + 2;
+			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+			break;
+		}
 		case CAN_KEY_BMS_GET_CELLS: {
 			cell_cmd_resp_t cells;
 			cells.cell_num = CELLS_NUM;
@@ -168,8 +207,8 @@ void process_bms_message(can_frame_t *frame, int len){
 			break;
 		}
 		case CAN_KEY_BMS_GET_HEALTH_STAT:
-			data = (uint8_t *)bms_health();
-			data_len = sizeof(*bms_health());
+			data = (uint8_t *)(&bms_health()->i_status);
+			data_len = sizeof(bms_health()->i_status);
 			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
 			break;
 		case CAN_KEY_BMS_SET_WORK_MODE:
@@ -214,6 +253,10 @@ void process_bms_message(can_frame_t *frame, int len){
 				result = 1;
 			} else if (len < 2) {
 				set_log_all(frame->data[0]);
+				ml5238_reg_log(); //just for debug
+				cs1180_log();
+				health_log();
+				soc_log();
 				bms_state_log();
 			} else if (len < 3){
 				set_log_level(frame->data[0], frame->data[1]);
@@ -227,6 +270,46 @@ void process_bms_message(can_frame_t *frame, int len){
 			protocol_send_ack(frame->head.can_addr, frame->key, 1);
 			break;
 		}
+		case CAN_KEY_MIN_SOC:
+			get_soc()->coulomb_now -= get_soc()->coulomb_min;
+			if (get_soc()->coulomb_now < 0) {
+				get_soc()->coulomb_now = 0;
+			}
+			get_soc()->coulomb_min = (u32)frame->data[0] * 3600.0f;
+			get_soc()->coulomb_now += get_soc()->coulomb_min;
+			get_soc()->capacity =((get_soc()->coulomb_now - get_soc()->coulomb_min)/(get_soc()->coulomb_max - get_soc()->coulomb_min) + 0.005f) * 100;
+			nv_save_all_soc();
+			protocol_send_ack(frame->head.can_addr, frame->key, 1);
+			break;
+		case CAN_KEY_GET_EVENT: {
+			u8 event[sizeof(event_record_t) * 8 + 1];
+			u16 offset = DECODE_U16(frame->data);
+			int num = get_event(8, offset, event + 1);
+			*event = (u8)num;
+			protocol_send_bms_info(frame->head.can_addr, frame->key, event, sizeof(event_record_t) * num + 1);
+			break;
+		}
+		case CAN_KEY_POWERDOWN: {
+			if (len < 4) {
+				return;
+			}
+			/*magic 0xFF005AA5*/
+			if (frame->data[0] == 0xA5 && frame->data[1] == 0x5A && frame->data[2] == 0x00 && frame->data[3] == 0xFF) {
+				bms_work_mode_set(WORK_MODE_PCBA_TEST, 1);
+				system_power_down();
+			}
+			break;
+		}
+		case CAN_KEY_FACTORY_RESULT: {
+			if (len == 1) {
+				nv_save_factory_result(frame->data[0]);
+			}
+			uint8_t res = nv_read_factory_result();
+			protocol_send_ack(frame->head.can_addr, frame->key, res);
+			break;
+		}
+		default:
+			break;
 	}
 }
 

+ 72 - 0
Application/app/event_record.c

@@ -0,0 +1,72 @@
+#include <stdbool.h>
+#include <string.h>
+#include "event_record.h"
+#include "libs/shark_task.h"
+
+#define MAX_EVENT_SIZE 120
+static event_record_t _event[MAX_EVENT_SIZE];
+static int event_w_idx = 0;
+static bool _event_full = false;
+
+void push_event(event_id_t id, s32 data) {
+	if (id == Aux_Current_Short) {//when multi aux short, only recode the old
+		for (int i = 0; i < MAX_EVENT_SIZE; i++) {
+			if (_event[i].id == Aux_Current_Short) {
+				if (shark_get_seconds() - _event[i].timestamp <= 1) {
+					return;
+				}
+			}
+		}
+	}
+	event_record_t *pevent = &_event[event_w_idx];
+	event_w_idx = (event_w_idx + 1) % MAX_EVENT_SIZE;
+	if (event_w_idx == 0) {
+		_event_full = true;
+	}
+	pevent->id = id;
+	pevent->timestamp = shark_get_seconds();
+	pevent->data = data;
+}
+
+void push_event_persit(event_id_t id, s32 data) {
+	if (id == Discharger_Operate_Off || id == Discharger_Operate_On) {
+		for (int i = 0; i < MAX_EVENT_SIZE; i++) {
+			if (_event[i].id == id) {
+				_event[i].timestamp = shark_get_seconds();
+				_event[i].data = data;
+				return;
+			}
+		}
+	}
+	push_event(id, data);
+}
+
+static int _event_size(void) {
+	if (_event_full) {
+		return MAX_EVENT_SIZE;
+	}
+	return event_w_idx;
+}
+
+int get_event(int num, int offset, u8 *recoder) {
+	if (offset >= _event_size()) {
+		return 0;
+	}
+	num = MIN(num, _event_size()-offset);
+	int rtn = 0;
+
+	if (_event_full) {
+		offset += event_w_idx;
+	}
+
+	while(num > 0) {
+		memcpy(recoder, _event + offset % MAX_EVENT_SIZE, sizeof(event_record_t));
+		num --;
+		offset ++;
+		recoder += sizeof(event_record_t);
+		rtn ++;
+	}
+	return rtn;
+}
+
+

+ 47 - 0
Application/app/event_record.h

@@ -0,0 +1,47 @@
+#ifndef _Event_Recorde_H__
+#define _Event_Recorde_H__
+
+#include "libs/shark_types.h"
+
+typedef enum {
+	Cell_Under_Vol = 1,
+	Cell_Over_Vol,
+	Pack_Under_Vol,
+	Pack_Over_Vol,
+	Charger_Full,
+	Current_Short,
+	Aux_Current_Short,
+	Temp_High_Discharger,
+	Temp_Low_Discharger,
+	Temp_High_Charger,
+	Temp_Low_Charger,
+	Min_Cap_For_Full,
+	Min_Cap_For_DisCharger,
+	Temp_Changed,
+	Charger_Full_cap,
+	Max_current_persis,
+	Pack_Temp,          //17
+	Charger_Full_cap2,  //18
+	Cell_Under_Vol2,    //19
+	Cell_Over_Vol2,     //20
+	Min_Cap_For_DisCharger2,
+	Charger_no_full_capaticy,
+	Charger_no_full_ceof,
+	Cell_balance,
+	Discharger_Operate_Off,
+	Discharger_Operate_On,
+	Charger_Current_Ov,
+}event_id_t;
+
+typedef struct {
+	u32 id;
+	u32 timestamp;
+	s32 data;
+}event_record_t;
+
+void push_event(event_id_t id, s32 data);
+int get_event(int num, int offset, u8 *recoder);
+void push_event_persit(event_id_t id, s32 data);
+
+#endif /* _Event_Recorde_H__ */
+

+ 29 - 5
Application/app/iap.c

@@ -3,7 +3,7 @@
 #include "app/nv_storage.h"
 #include "bsp/fmc_flash.h"
 #include "bsp/shark_rtc.h"
-
+#include "libs/logger.h"
 static int iap_write_image(uint8_t *data, int len);
 static int iap_check_image(uint8_t *data, int len);
 void _reboot_timer_handler(shark_timer_t *t);
@@ -13,6 +13,17 @@ static u8 _write_success = 0;
 static int _write_position = 0;
 static shark_timer_t _reboot_timer = {.handler = _reboot_timer_handler,};
 
+void iap_read_chip_id(can_frame_t *frame)
+{
+	u8 buff[24];
+	u8 len;
+
+	buff[0] = buff[1] = 0x00;
+	len = shark_read_chip_id(buff + 2) + 2;
+
+	protocol_send_bms_info(frame->head.can_addr, frame->key, buff, len);
+}
+
 void process_iap_message(can_frame_t *frame, int len){
 	uint8_t *data = NULL;
 	int data_len = 0;
@@ -22,6 +33,7 @@ void process_iap_message(can_frame_t *frame, int len){
 				wdog_reload();
 				fmc_iap_write_magic(0xFFFFFFFF);
 				shark_rtc_set_backup(0x3000);
+				nv_save_all_soc();
 				NVIC_SystemReset();
 				while(1);
 			}
@@ -49,6 +61,7 @@ void process_iap_message(can_frame_t *frame, int len){
 			break;
 		case CAN_KEY_IAP_BOOT:
 			if (_write_success) {
+				nv_save_all_soc();
 				NVIC_SystemReset();
 				while(1);
 			} else {
@@ -56,7 +69,11 @@ void process_iap_message(can_frame_t *frame, int len){
 			}
 			break;
 		case CAN_KEY_IAP_STAT:
-			protocol_send_ack(frame->head.can_addr, frame->key, 0);
+			if (len > 0 && frame->data[0] == 0x01) {
+				iap_read_chip_id(frame);
+			} else {
+				protocol_send_ack(frame->head.can_addr, frame->key, 0);
+			}
 			break;
 		case CAN_EEY_IAP_READ_STRING:
 			iap_read_string(frame);
@@ -71,8 +88,15 @@ void process_iap_message(can_frame_t *frame, int len){
 			break;
 		case CAN_KET_ERASE_NV:
 			shark_rtc_set_backup(0x3002);
-			nv_erase_soc(0);
-			nv_erase_soc(1);
+			if (len == 0) {
+				nv_erase_all_soc(1);
+			}else {
+				if (frame->data[0] == 1) {//erase and clear cycle
+					nv_erase_all_soc(0);
+				}else {
+					nv_erase_all_soc(1);
+				}
+			}
 			shark_timer_post(&_reboot_timer, 100);
 			protocol_send_ack(frame->head.can_addr, frame->key, 1);
 			break;
@@ -83,6 +107,7 @@ void process_iap_message(can_frame_t *frame, int len){
 }
 
 void _reboot_timer_handler(shark_timer_t *t){
+	nv_save_all_soc();
 	NVIC_SystemReset();
 }
 
@@ -119,7 +144,6 @@ void iap_read_string(can_frame_t *frame)
 	protocol_send_bms_info(frame->head.can_addr, frame->key, buff, len + 4);
 }
 
-
 static int iap_check_image(uint8_t *data, int len) {
 	uint32_t size, checksum;
 	size = shark_decode_u24(data);

+ 57 - 7
Application/app/nv_storage.c

@@ -16,6 +16,8 @@ static void nv_save_soc_task(shark_timer_t *timer);
 static shark_timer_t _save_backup_timer = {.handler = nv_save_soc_task};
 #define SOC_SIZE (((sizeof(soc_t) + sizeof(uint16_t)) + 0xF)&(0xFFF0)) //需要16字节对齐
 #define SN_ADDR (SOC_ADDR + (SOC_SIZE * 2))
+#define SN_SIZE 32
+#define RES_ADDR (SN_ADDR + SN_SIZE)
 
 static uint8_t soc_write_pending = 0;
 static uint8_t soc_write_backup_index = 0;
@@ -68,6 +70,28 @@ int nv_read_sn(uint8_t *sn, int len){
 	return sn_info.len;
 }
 
+int nv_save_factory_result(uint8_t result) {
+	factory_t f;
+	f.result = result;
+	uint16_t crc16 = shark_crc16_update(0, (const u8 *)&f, sizeof(f) - 2);
+	f.crc = crc16;
+	return AT24CXX_Write(RES_ADDR, (uint8_t *)&f, sizeof(f));
+}
+
+uint8_t nv_read_factory_result(void) {
+	factory_t f;
+	if (AT24CXX_Read(RES_ADDR, (uint8_t *)&f, sizeof(f)) < 0) {
+		return 0xFF;
+	}
+	uint16_t crc16 = shark_crc16_update(0, (const u8 *)&f, sizeof(f) - 2);
+	if (f.crc != crc16) {
+		return 0xFF;
+	}
+	return f.result;
+}
+
+static int _soc_write_error = 0;
+static int _soc_write_success = 0;
 /* soc 保存,拆分每次保存一个byte,确保e2rom写操作不会占用太长时间 */
 void nv_save_soc(void){
 #if 0	
@@ -87,18 +111,27 @@ void nv_save_soc(void){
 #endif
 }
 
+void nv_storage_log(void) {
+	state_debug("soc nv write: %d, %d\n", _soc_write_success, _soc_write_error);
+}
+
 static void nv_save_soc_task(shark_timer_t *timer){
 	if (soc_write_pending == 0) {
 		return;
 	}
 	if (soc_write_index < sizeof(soc_data)){
-		AT24CXX_Write(SOC_ADDR + SOC_SIZE * soc_write_backup_index + soc_write_index, soc_data + soc_write_index, 1);
-		soc_write_index ++;
+		if (AT24CXX_Write(SOC_ADDR + SOC_SIZE * soc_write_backup_index + soc_write_index, soc_data + soc_write_index, 1) == 1) {
+			soc_write_index ++;
+			_soc_write_success ++;
+		}else {
+			_soc_write_error ++;
+		}
 	}else {
 		soc_write_index = 0;
 		soc_write_backup_index ++;
 		if (soc_write_backup_index == 2){
 			soc_write_pending = 0;
+			soc_write_backup_index = 0;
 			sys_debug("write soc to nv OK\n");
 			return;
 		}
@@ -121,16 +154,20 @@ static void nv_save_soc_by_backup(int index){
 	AT24CXX_Write(nv_addr + sizeof(soc_t),(uint8_t *)&crc16, sizeof(crc16));
 }
 
+static void stop_writer(void) {
+	shark_timer_cancel(&_save_backup_timer);
+	soc_write_index = 0;
+	soc_write_backup_index = 0;
+}
+
 void nv_save_all_soc(void){
+	stop_writer();
 	nv_save_soc_by_backup(0);
 	nv_save_soc_by_backup(1);
 }
 
-void nv_erase_soc(int index){
-	uint8_t data = 0xFF;
-	for (int i = 0; i < sizeof(soc_t) + sizeof(uint16_t); i++){
-		AT24CXX_Write(SOC_ADDR + SOC_SIZE * index + i, &data, 1);
-	}	
+void nv_erase_all_soc(int keep_cycle){
+	soc_clear_calibrate(keep_cycle);
 }
 
 int nv_restore_soc_by_backup(int index, soc_t *soc){
@@ -171,3 +208,16 @@ int nv_restore_soc(void){
 	return ((success0 == 0) || (success1 == 0))?0:-1;
 }
 
+uint8_t nv_get_sn_byte7(void) {
+	uint8_t sn[30] = {0};
+	int try_cnt = 20;
+	while (nv_read_sn(sn, sizeof(sn)) < 7) {
+		if (try_cnt-- < 0) {
+			break;
+		}
+	}
+	if (sn[0] == 0) {
+		return 'N';
+	}
+	return sn[6];
+}

+ 12 - 1
Application/app/nv_storage.h

@@ -8,13 +8,24 @@ typedef struct {
 	uint8_t sn[24];
 	uint16_t crc;
 }sn_t;
+
+typedef struct {
+	uint8_t result;
+	uint16_t crc;
+}factory_t;
+
 #pragma pack(pop)
 
 void nv_save_soc(void);
 int nv_restore_soc(void);
-void nv_erase_soc(int index);
+void nv_erase_all_soc(int keep_cycle);
 int nv_save_sn(uint8_t *sn, int len);
 int nv_read_sn(uint8_t *sn, int len);
 int nv_read_write_test(void);
 void nv_save_all_soc(void);
+void nv_storage_log(void);
+int nv_save_factory_result(uint8_t result);
+uint8_t nv_read_factory_result(void);
+uint8_t nv_get_sn_byte7(void);
+
 

+ 62 - 3
Application/app/pcba_test.c

@@ -10,6 +10,10 @@ static void pcba_test_timer_handler(shark_timer_t *timer);
 static shark_timer_t pcba_test_timer = {.handler = pcba_test_timer_handler};
 static int pcba_test_item = -1;
 static int powerdown_flags = 0;
+
+const rcu_periph_enum shark_gpio_rcus[] = { RCU_GPIOA, RCU_GPIOB, RCU_GPIOC, RCU_GPIOD, RCU_GPIOF, RCU_GPIOF };
+const u32 shark_gpio_ports[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOF, GPIOF };
+
 static void pcba_test_timer_handler(shark_timer_t *timer) {
 	if (pcba_test_item == 1) {
 		UART0_IR_EN(1);
@@ -107,7 +111,7 @@ int pcba_test(uint8_t *data, int len, uint8_t *response){
 	}else if (cmd == 0x11) {
 		response[resp_len ++] = ml5238_is_discharging() | ml5238_is_charging()<<1;
 	}else if (cmd == 0x22) {
-		uint16_t health = *(uint16_t *)bms_health();
+		uint16_t health = (uint16_t)bms_health()->i_status;
 		response[resp_len ++] = AUX_VOL_IS_OPEN();
 		response[resp_len ++] = health;
 		response[resp_len ++] = health >> 8;
@@ -143,8 +147,8 @@ int pcba_test(uint8_t *data, int len, uint8_t *response){
 	}else if (cmd == 0x17) {
 		uint8_t cell_index = 0;
 		for (int i = 0; i < CELLS_NUM; i++){
-			if (measure_value()->cell_vol[i] > 3000 && measure_value()->cell_vol[i] < 3400) {
-				cell_index = i;
+			if ((measure_value()->cell_vol[i] < 3000) || (measure_value()->cell_vol[i] > 3400)) {
+				cell_index = i + 1;
 				break;
 			}
 		}
@@ -184,7 +188,62 @@ int pcba_test(uint8_t *data, int len, uint8_t *response){
 		}
 	}else if (cmd == 0x21) {
 		response[resp_len ++] = powerdown_flags;
+	}else if (cmd == 0xC9) {
+		if (payload[2] == 0) {
+			DIANOCTIC_LED(0);
+		}else {
+			DIANOCTIC_LED(1);
+		}
+	} else if (cmd == 0xE1 && len > 4) { // gpio control
+		u8 index = (data[4] >> 4) & 0x0F;
+		u32 pin = 1 << (data[4] & 0x0F);
+		u32 port = shark_gpio_ports[index];
+		rcu_periph_enum rcu = shark_gpio_rcus[index];
+
+		rcu_periph_clock_enable(rcu);
+		response[resp_len++] = data[4];
+
+		if (len < 6 || data[5] == 0x00) { // input get
+			response[resp_len++] = gpio_input_bit_get(port, pin);
+		} else if (data[5] == 0x01) { // output set and get
+			if (len > 6) {
+				if (data[6] != 0x00) {
+					gpio_bit_set(port, pin);
+				} else {
+					gpio_bit_reset(port, pin);
+				}
+			}
+
+			response[resp_len++] = gpio_output_bit_get(port, pin);
+		} else if (data[5] == 0x02) { // input get
+			gpio_mode_input(port, GPIO_PUPD_NONE, pin);
+			response[resp_len++] = gpio_input_bit_get(port, pin);
+		} else if (data[5] == 0x03 && len > 6) { // output set and get
+			if (data[6] != 0x00) {
+				gpio_bit_set(port, pin);
+			} else {
+				gpio_bit_reset(port, pin);
+			}
+
+			gpio_mode_output(port, GPIO_PUPD_NONE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin);
+			response[resp_len++] = gpio_output_bit_get(port, pin);
+		} else if (data[5] == 0x04 && len > 6) { // input get
+			gpio_mode_input(port, data[6], pin);
+			response[resp_len++] = gpio_input_bit_get(port, pin);
+		} else if (data[5] == 0x05 && len > 8) { // output set
+			if (data[6] != 0x00) {
+				gpio_bit_set(port, pin);
+			} else {
+				gpio_bit_reset(port, pin);
+			}
+
+			gpio_mode_output(port, data[7], data[8], GPIO_OSPEED_50MHZ, pin);
+			response[resp_len++] = gpio_output_bit_get(port, pin);
+		} else {
+			response[resp_len++] = 0xFF;
+		}
 	}
+
 	response[2] = resp_len - 2;
 
 	return resp_len;

+ 8 - 1
Application/app/protocol.c

@@ -11,6 +11,10 @@ void protocol_send_bms_info(uint8_t dest, uint8_t key, uint8_t *data, int len){
 	can_frame_t can_frame;
 	CAN_OUT(&(can_frame.head), dest);
 	can_frame.key = key;
+#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)
+	u8 dumy_bytes[2] = {0xaa, 0xaa}; //ÈúìÍâÕý³£	
+	shark_uart_write_bytes(current_uart, dumy_bytes, sizeof(dumy_bytes));
+#endif
 	shark_uart_frame_start(current_uart, (uint8_t *)&can_frame, sizeof(can_frame));
 	shark_uart_frame_continue(current_uart, data, len);
 	shark_uart_frame_end(current_uart);	
@@ -53,7 +57,8 @@ void protocol_notify_old_frame(uart_enum_t uart_no){
 	head.checksum = _check_sum((uint8_t *)&head, head.size);
 	shark_uart_write_bytes(current_uart, (uint8_t *)&head, head.size);
 }
-
+extern u32 uart_new_prot;
+extern u64 uart_frame_time;
 void protocol_recv_frame(uart_enum_t uart_no, uint8_t *data, int len){
 	current_uart = uart_no;
 	if (len < sizeof(can_frame_t)){
@@ -65,6 +70,8 @@ void protocol_recv_frame(uart_enum_t uart_no, uint8_t *data, int len){
 		health_add_uart_error(0 ,0 ,1);
 		return;
 	}
+	uart_new_prot++;
+	uart_frame_time = shark_get_mseconds();
 
 	len -= sizeof(can_frame_t);
 	if (can_frame->key >= CAN_KEY_IAP_ENTER){

+ 48 - 31
Application/app/protocol.h

@@ -47,6 +47,32 @@ typedef struct {
 }can_frame_t;
 #pragma pack(pop)
 
+#define CAN_KEY_BMS_BASE_INFO 0x00 //电压,电流,能量, SOC,max temp
+#pragma  pack (push,1)
+typedef struct {
+	uint32_t pack_voltage;
+	int32_t  pack_current;
+	uint8_t  capacity;
+	uint32_t energy;   //能量,给PS100/200/310/360计算续航里程用
+	int8_t  max_temp;//最高的那个温度
+	uint32_t health :24;
+	uint32_t state  :8; // stat_cmd_resp_t
+}binfo_cmd_resp_t;
+#pragma pack(pop)
+
+#define CAN_KEY_GET_SN      0x05 //return string
+#define CAN_KEY_SET_SN      0x06 //string
+
+
+#define CAN_KEY_BMS_GET_CELLS   0x07
+#pragma  pack (push,1)
+typedef struct {
+	uint8_t cell_num;
+	uint16_t voltages[CELLS_NUM];
+}cell_cmd_resp_t;
+#pragma pack(pop)
+
+
 /* can key define */
 #define CAN_KEY_BMS_SET_POWER 0x0B //开关各种mos和小电流
 #pragma  pack (push,1)
@@ -61,6 +87,14 @@ typedef struct {
 }pwr_cmd_t;
 #pragma pack(pop)
 
+#define CAN_KEY_GET_VERSION 0x0c //return string
+
+
+#define CAN_KEY_BMS_TEMPS 0x11 //return int[4]
+
+
+#define CAN_KEY_AGING_TEMPS 0x12
+
 #define CAN_KEY_BMS_GET_STAT 0xa0 //bms_stat_t
 #pragma  pack (push,1)
 typedef struct {
@@ -75,18 +109,7 @@ typedef struct {
 }stat_cmd_resp_t;
 #pragma pack(pop)
 
-#define CAN_KEY_BMS_BASE_INFO 0x00 //电压,电流,能量, SOC,max temp
-#pragma  pack (push,1)
-typedef struct {
-	uint32_t pack_voltage;
-	int32_t  pack_current;
-	uint8_t  capacity;
-	uint32_t energy;   //能量,给PS100/200/310/360计算续航里程用
-	int8_t  max_temp;//最高的那个温度
-	uint32_t health :24;
-	uint32_t state  :8; // stat_cmd_resp_t
-}binfo_cmd_resp_t;
-#pragma pack(pop)
+
 
 #define CAN_KEY_BMS_CHARG_INFO 0xa1
 #pragma  pack (push,1)
@@ -96,13 +119,11 @@ typedef struct {
 }cinfo_cmd_resp_t;
 #pragma pack(pop)
 
-#define CAN_KEY_BMS_GET_CELLS   0x07
-#pragma  pack (push,1)
-typedef struct {
-	uint8_t cell_num;
-	uint16_t voltages[CELLS_NUM];
-}cell_cmd_resp_t;
-#pragma pack(pop)
+#define CAN_KEY_SET_LOGGER  0xa2 //byte 0:modle, byte1 level
+#define CAN_KEY_BMS_CLEAR   0xa3 //clear some flags used by PSxxx, exp: stat_cmd_resp_t.insert
+#define CAN_KEY_BMS_GET_HEALTH_STAT 0xa4 //return bms_health_t
+#define CAN_KEY_BMS_GET_TIME      0xa5 //return bms running times(second) uint32_t
+#define CAN_KEY_BMS_SET_WORK_MODE     0xa6 //byte0=mode, byte1=start/stop
 
 #define CAN_KEY_GET_SOC_INFO 0xa7
 typedef struct {
@@ -115,18 +136,6 @@ typedef struct {
 	uint32_t calibrated;	
 }soc_info_t;
 
-#define CAN_KEY_BMS_TEMPS 0x11 //return int[4]
-
-#define CAN_KEY_SET_LOGGER  0xa2 //byte 0:modle, byte1 level
-#define CAN_KEY_BMS_CLEAR   0xa3 //clear some flags used by PSxxx, exp: stat_cmd_resp_t.insert
-#define CAN_KEY_BMS_GET_HEALTH_STAT 0xa4 //return bms_health_t
-#define CAN_KEY_BMS_GET_TIME      0xa5 //return bms running times(second) uint32_t
-#define CAN_KEY_BMS_SET_WORK_MODE     0xa6 //byte0=mode, byte1=start/stop
-
-#define CAN_KEY_GET_VERSION 0x0c //return string
-#define CAN_KEY_SET_SN      0x06 //string
-#define CAN_KEY_GET_SN      0x05 //return string
-
 #define CAN_KEY_START_CALI  0xa8
 #pragma  pack (push,1)
 typedef struct {
@@ -150,6 +159,14 @@ typedef struct {
 }restore_nv_cmd_t;
 #pragma pack(pop)
 
+#define CAN_KEY_MIN_SOC 0xab /*设置最小容量,测试使用*/
+
+#define CAN_KEY_GET_EVENT 0xac /*获取事件信息*/
+
+#define CAN_KEY_POWERDOWN 0xad /* power down, magic:0xFF005AA5*/
+
+#define CAN_KEY_FACTORY_RESULT 0xb0
+
 #define CAN_KEY_IAP_ENTER   0xF0
 #define CAN_KEY_IAP_BEGIN   0xF1
 #define CAN_KEY_IAP_CHECK   0xF2

+ 19 - 4
Application/app/protocol_old.c

@@ -66,7 +66,7 @@ static int get_response_data(uint8_t *data, uint8_t operate, uint8_t result){
 		}
 	}
 	
-	response->health_state = *((uint16_t *)bms_health()) | (bms_health()->sigle_cell_lower_voltage << 1);
+	response->health_state = ((uint16_t)bms_health()->i_status) | (bms_health()->sigle_cell_lower_voltage << 1);
 	if (bms_is_ps_charger_in()) {
 		response->health_state |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14);
 	}
@@ -96,6 +96,7 @@ static int get_response_data(uint8_t *data, uint8_t operate, uint8_t result){
 		memset(&data[head->size], 0, sizeof(times_response_t));
 		times_response_t *resp = (times_response_t *)&data[head->size];
 		resp->charger_cycle = soc_get_cycle();
+		resp->soh = soc_get_soh();
 		head->size += sizeof(times_response_t);
 	}else if (operate == OP_CELL_VOL){
 		data[head->size ++] = CELLS_NUM;
@@ -111,6 +112,15 @@ static int get_response_data(uint8_t *data, uint8_t operate, uint8_t result){
 	}else if (operate == OP_READ_DETECT){
 		data[head->size++] = IS_HALL1_DETECTED() | IS_HALL2_DETECTED() << 1 | IS_CHARGER_IN() << 2;
 		data[head->size++] = IS_DCDC_POWER_GOOD() | AUX_VOL_IS_OPEN() << 1 | IS_AUX_VOL_LOCKED() << 2;
+	}else if (operate == OP_AGING_TEMPS) {
+		int8_t *idata = (int8_t *)data;
+		data[head->size ++] = bms_state_get()->agint_cost_time/60; //·ÖÖÓ
+		for (int i = 0; i < PACK_TEMPS_NUM; i++){
+			idata[head->size ++] = (int8_t)(bms_state_get()->aging_start_temp[i]);
+		}
+		for (int i = 0; i < PACK_TEMPS_NUM; i++){
+			idata[head->size ++] = (int8_t)(bms_state_get()->aging_max_temp[i]);
+		}
 	}
 
 	head->checksum = _checksum(data, head->size);
@@ -118,11 +128,12 @@ static int get_response_data(uint8_t *data, uint8_t operate, uint8_t result){
 	return head->size;
 }
 
-
+extern u32 uart_old_prot;
+extern u64 uart_frame_time;
 static int protocol_old_process_binary(uart_enum_t uart_no, uint8_t *data, int len){
 	current_uart = uart_no;
 	comm_head_t *head = (comm_head_t *)data;
-	if (head->type != bms_state_get()->bms_addr || head->dir != 0x16 || head->bStatus == 1 || head->size < sizeof(comm_head_t)){
+	if (/*head->type != bms_state_get()->bms_addr || */head->dir != 0x16 || head->bStatus == 1 || head->size < sizeof(comm_head_t)){
 		return -1;
 	}
 	uint16_t checksum = head->checksum;
@@ -130,12 +141,16 @@ static int protocol_old_process_binary(uart_enum_t uart_no, uint8_t *data, int l
 	if (checksum != _checksum(data, len)){
 		return -1;
 	}
-
+	uart_old_prot ++;
+	uart_frame_time = shark_get_mseconds();
 	data = head->data;
 	data += 6;
 	uint8_t operate = data[0];
 	uint8_t ps_charger = data[1];
 	bms_set_ps_charger_in(1, (ps_charger == CW_CHE_SHANG_CHARGER || ps_charger == CW_CHONG_DIAN_ZUO));
+	if ((ps_charger == CW_CHE_SHANG_CHARGER) || (ps_charger == CW_CHE_SHANG_NO_CHARGER)) {
+		bms_work_mode_set(WORK_MODE_AGING_TEST, 0);
+	}
 	data += 1;
 	uint8_t result = 1;
 	if (operate == OP_OPEN_FET){

+ 5 - 3
Application/app/protocol_old.h

@@ -43,7 +43,7 @@ typedef struct
 #pragma  pack (push,1)  
 typedef struct
 {
-	uint8_t res1[2];
+	uint16_t soh;
 	uint32_t charger_cycle;
 	uint8_t res2[36];
 }times_response_t;
@@ -62,14 +62,16 @@ enum
 	OP_ALARM_TIMES,
 	OP_CELL_VOL,//0x07
 	OP_TEMP_OTHER,//0x08
-	
+
+	OP_AGING_TEMPS = 0x0A,
+
 	OP_OPEN_FET = 0x0B,
 
 	OP_CLEAR_PAIR = OP_TEMP_OTHER + 1,
 	OP_READ_DETECT = 0x0D,
 	OP_UPDATE_SOFTWARE_REQ = 0x0E,
 	OP_UPDATE_SOFTWARE = 0x0F,
-	
+
 	OP_MAX
 };
 

+ 137 - 25
Application/app/sox/health.c

@@ -7,7 +7,7 @@
 #include "measure_task.h"
 #include "health.h"
 #include "Least_Square.h"
-
+#include "event_record.h"
 #if 0
 #define MIN_VOLTAGE_FOR_DISCHARGER (2.2f * CELLS_NUM * 1000) //允许能放电的最小电压
 #define MIN_VOLTAGE_FOR_RECOVERY_DISCHARGER (2.3f * CELLS_NUM * 1000) //恢复放电的最小电压
@@ -24,27 +24,27 @@ static int8_t discharger_normal_low_temp[PACK_TEMPS_NUM] = {-20,-20,-20,-25};//
 static int8_t discharger_normal_high_temp[PACK_TEMPS_NUM] = {55,55,55,75};//正常的放电最高温度
 static int8_t discharger_lower_low_temp[PACK_TEMPS_NUM] = {-25,-25,-25,-30}; //需要停止放电的最低温度
 static int8_t discharger_higher_high_temp[PACK_TEMPS_NUM] = {60,60,60,85};//需要停止放电的最高温度
-static int8_t work_lower_temp[PACK_TEMPS_NUM - 1] = {0,0,0}; //pcb温度不用判断
-static int8_t work_lower_temp_recovry[PACK_TEMPS_NUM - 1] = {5,5,5}; //pcb温度不用判断
+static int8_t work_lower_temp[PACK_TEMPS_NUM - 1] = {5,5,5}; //pcb温度不用判断
+static int8_t work_lower_temp_recovry[PACK_TEMPS_NUM - 1] = {10,10,10}; //pcb温度不用判断
 
 /*定义低温和正常温度下的电池保护参数, [0]低温参数, [1]常温参数 */
 /*能提供动力的最小电压*/
 static float min_discharger_power_vol[] = {32000, 38000}; //允许能提供动力的最小电压
 static float min_discharger_power_recovery_vol[] = {34000, 40000}; //恢复能提供动力的最小电压
-static float min_discharger_power_cell_vol[] = {2100, 2600}; //允许能提供动力的最小电芯电压
-static float min_discharger_power_recovery_cell_vol[] = {2200, 2700}; //恢复能提供动力的最小电芯电压
+static float min_discharger_power_cell_vol[] = {2100, 2400}; //允许能提供动力的最小电芯电压
+static float min_discharger_power_recovery_cell_vol[] = {2200, 2500}; //恢复能提供动力的最小电芯电压
 
 /*能提供大电的最小电压*/
-static float min_discharger_vol[] = {30000, 36000};//允许能放电的最小电压
-static float min_discharger_recovery_vol[] = {32000, 40000};//恢复放电的最小电压
-static float min_discharger_cell_vol[] = {1900, 2500};//允许能放电的最小电芯电压
-static float min_discharger_cell_recovery_vol[] = {2000, 2600};//恢复放电的最小电芯电压
+static float min_discharger_vol[] = {27000, 33000};//允许能放电的最小电压
+static float min_discharger_recovery_vol[] = {30000, 36000};//恢复放电的最小电压
+static float min_discharger_cell_vol[] = {1800, 2200};//允许能放电的最小电芯电压
+static float min_discharger_cell_recovery_vol[] = {1900, 2300};//恢复放电的最小电芯电压
 
 /*电池PowerDown的最小电压 */
-static float min_discharger_pdown_vol[] = {28000, 34000}; //power down的最小电压
-static float min_discharger_pdown_cell_vol[] = {1900, 2200};                        //power down的最小电芯电压
+static float min_discharger_pdown_vol[] = {26000, 30000}; //power down的最小电压
+static float min_discharger_pdown_cell_vol[] = {1600, 1800}; //power down的最小电芯电压
 
-#define MAX_TRY_FOR_AUX_SHORT 10
+#define MAX_TRY_FOR_AUX_SHORT 20
 
 /* health 模块,只检测状态,不做任何控制,如果有异常情况,控制中心会统一处理  */
 static void check_ml5238_state(int event);
@@ -60,8 +60,6 @@ static debounce_timer_t _load_detect_timer = {.max_count = 100, .interval = 10,
 static debounce_timer_t _charger_detect_timer = {.max_count = 500, .interval = 10, ._timer.handler = charger_detect_handler};
 static shark_timer_t _clear_short_current_timer = {.handler = clear_short_current_handler};
 static error_counts_t error_counts;
-static u16 discharger_lower_cell_voltage = 0;
-static u16 discharger_lower_voltage = 0;
 
 void health_init(void){
 	/* 5238如果有异常情况,比如短路,负载移除,通过这个handler上报 */
@@ -79,8 +77,9 @@ void health_log(void){
 	health_debug("hard short:%d\n", error_counts.hard_current_short);
 	health_debug("work temp: %d\n", _health.is_work_temp_normal);
 	health_debug("aux_short: %d, %d\n", error_counts.aux_short, error_counts.aux_real_short);
-	health_debug("lower voltage: %d, %d, %d, %d\n", discharger_lower_cell_voltage, discharger_lower_voltage, error_counts.cell_under_voltage, error_counts.pack_under_voltage);
+	health_debug("lower voltage: %d, %d\n", error_counts.cell_under_voltage, error_counts.pack_under_voltage);
 	health_debug("uart error %d, %d, %d\n", error_counts.uart_crc_error, error_counts.uart_len_error, error_counts.uart_dir_error);
+	health_debug("Temp abnormal: %d,%d,%d,%d\n", error_counts.discharger_high_temp, error_counts.charger_high_temp, error_counts.discharger_lower_temp, error_counts.charger_lower_temp);
 }
 
 bms_health_t *bms_health(){
@@ -144,6 +143,7 @@ static void check_ml5238_state(int event){
 		shark_timer_post(&_charger_detect_timer._timer, _charger_detect_timer.interval);
 	}else if (event == ML5238_Event_Short_Current) { //ml5238触发短路保护,充放电mos全部关闭
 		_health.load_current_short = 1;
+		push_event(Current_Short, 1);
 		error_counts.hard_current_short ++;
 		ml5238_enable_load_detect(1); //打开负载检测
 		shark_timer_post(&_load_detect_timer._timer, _load_detect_timer.interval);
@@ -180,6 +180,7 @@ void check_current_state(void){
 				_health.charger_over_current = 1;
 				_charger_over_current.count = 0;
 				health_warning("charger over current\n");
+				push_event(Charger_Current_Ov, (s32)current);
 				shark_timer_post(&_charger_detect_timer._timer, _charger_detect_timer.interval);
 			}
 		}
@@ -188,6 +189,7 @@ void check_current_state(void){
 		if (!_health.load_current_short){
 			if (soft_current_push(current)) {
 				_health.load_current_short = 1;
+				push_event(Current_Short, 0);
 				error_counts.soft_current_short ++;
 				//_discharger_over_current.count = 0;
 				ml5238_enable_load_detect(1); //打开负载检测
@@ -199,12 +201,12 @@ void check_current_state(void){
 }
 
 /* 检测pack电压,cell电压,pack电压过低触发powerdown*/
-static debounce_t _discharger_lower_voltage = {.count = 0, .max_count = 20, .init_count = 0};
-static debounce_t _power_down_voltage = {.count = 0, .max_count = 20, .init_count = 0};
-static debounce_t _sigle_cell_discharger_lower_vol = {.count = 0, .max_count = 100, .init_count = 0};
-static debounce_t _sigle_cell_charger_max_vol = {.count = 0, .max_count = 20, .init_count = 0};
+static debounce_t _discharger_lower_voltage = {.count = 0, .max_count = 200, .init_count = 0};
+static debounce_t _power_down_voltage = {.count = 0, .max_count = 200, .init_count = 0};
+static debounce_t _sigle_cell_discharger_lower_vol = {.count = 0, .max_count = 200, .init_count = 0};
+static debounce_t _sigle_cell_charger_max_vol = {.count = 0, .max_count = 200, .init_count = 0};
 static debounce_t _shut_discharger_lower_voltage = {.count = 0, .max_count = 20,.init_count = 0};
-static debounce_t _shut_discharger_cell_lower_voltage = {.count = 0, .max_count = 400,.init_count = 0};
+static debounce_t _shut_discharger_cell_lower_voltage = {.count = 0, .max_count = 20,.init_count = 0};
 
 static int judge_debounce(int input, debounce_t *d){
 	if (input) {
@@ -221,7 +223,7 @@ static int judge_debounce(int input, debounce_t *d){
 }
 
 static int _can_powerdown(void){
-	if (io_state()->charger_detect_irq || bms_state_get()->charging || !bms_work_is_normal()){
+	if (io_state()->charger_detect_irq || bms_state_get()->charging){
 		return 0;
 	}
 	if ((bms_state_get()->pack_voltage <= min_discharger_pdown_vol[_health.is_work_temp_normal] ||
@@ -231,8 +233,67 @@ static int _can_powerdown(void){
 	return 0;
 }
 
+static void _single_low_judge_current(bool set) {
+	if (!set){
+		bms_health()->b_flags &= ~(B_FLAGS_SINGLE_LOW_CURRENT | B_FLAGS_SINGLE_MID_CURRENT | B_FLAGS_SINGLE_BIG_CURRENT | B_FLAGS_SINGLE_LARGER_CURRENT);
+		return;
+	}
+	int load_current = abs(measure_value()->load_current);
+	if (load_current < MAX_HA*1000/2) { // 0.5C ???
+		bms_health()->b_flags |= B_FLAGS_SINGLE_LOW_CURRENT;
+	}else if (load_current < MAX_HA*1000) { // 1C ???
+		bms_health()->b_flags |= B_FLAGS_SINGLE_MID_CURRENT;
+	}else if (load_current < MAX_HA * 1000 * 3/2) { // 1.5C ???
+		bms_health()->b_flags |= B_FLAGS_SINGLE_BIG_CURRENT;
+	}else {
+		bms_health()->b_flags |= B_FLAGS_SINGLE_LARGER_CURRENT;
+	}
+}
+static void _pack_low_judge_current(bool set) {
+	if (!set){
+		bms_health()->b_flags &= ~(B_FLAGS_PACK_LOW_CURRENT | B_FLAGS_PACK_MID_CURRENT | B_FLAGS_PACK_BIG_CURRENT | B_FLAGS_PACK_LARGER_CURRENT);
+		return;
+	}
+	int load_current = abs(measure_value()->load_current);
+	if (load_current < MAX_HA*1000/2) {
+		bms_health()->b_flags |= B_FLAGS_PACK_LOW_CURRENT;
+	}else if (load_current < MAX_HA*1000) {
+		bms_health()->b_flags |= B_FLAGS_PACK_MID_CURRENT;
+	}else if (load_current < MAX_HA * 1000 * 3/2){
+		bms_health()->b_flags |= B_FLAGS_PACK_BIG_CURRENT;
+	}else {
+		bms_health()->b_flags |= B_FLAGS_PACK_LARGER_CURRENT;
+	}
+}
+typedef union {
+	u32 data;
+	s8  ds8[4];
+}temp_u;
+static void push_cell_event(event_id_t id){
+	u16 max_v = bms_state_get()->cell_max_vol / 10;
+	u16 min_v = bms_state_get()->cell_min_vol / 10;
+	u32 max = ((bms_state_get()->cell_index_of_max_vol << 12) & 0xF000) | (max_v & 0x0FFF);
+	u32 min = ((bms_state_get()->cell_index_of_min_vol << 12) & 0xF000) | (min_v & 0x0FFF);
+
+	push_event(id, max << 16 | min);
+
+	temp_u t = {0};
+	for (int i = 0; i < PACK_TEMPS_NUM; i++){		
+		t.ds8[i] = (s8)measure_value()->pack_temp[i];
+	}
+	push_event(Pack_Temp, t.data);
+	push_event(Max_current_persis, measure_value()->load_current);
+}
 
 void check_voltage_state(void) {
+	static uint16_t _charging = 0xFFFF;
+	if (_charging != bms_state_get()->charging) {
+		if (bms_state_get()->charging) {
+		}else {
+			error_counts.cell_under_voltage = 0;
+		}
+		_charging = bms_state_get()->charging;
+	}
 	if (bms_state_get()->charging){ //check sigle cell's voltage for charger
 		_health.discharger_shutpower_voltage = 0;
 		_health.sigle_cell_lower_voltage = 0;
@@ -241,6 +302,7 @@ void check_voltage_state(void) {
 		if ((bms_state_get()->cell_max_vol>= SIGLE_CELL_MAX_CHARGER_VOLTAGE)){
 			if (judge_debounce(!_health.sigle_cell_over_voltage, &_sigle_cell_charger_max_vol)){
 				_health.sigle_cell_over_voltage = 1;
+				push_cell_event(Cell_Over_Vol2);
 				sys_debug("sigle cell %d\n", bms_state_get()->cell_max_vol);
 			}
 		}else if ((bms_state_get()->cell_max_vol < SIGLE_CELL_MAX_CHARGER_VOLTAGE)){
@@ -256,46 +318,56 @@ void check_voltage_state(void) {
 		if ((bms_state_get()->cell_min_vol <= min_discharger_cell_vol[_health.is_work_temp_normal])){
 			if (judge_debounce(!_health.sigle_cell_lower_voltage, &_sigle_cell_discharger_lower_vol)){
 				_health.sigle_cell_lower_voltage = 1;
+				push_cell_event(Cell_Under_Vol2);
+				_single_low_judge_current(true);
 				error_counts.cell_under_voltage++;
-				discharger_lower_cell_voltage = bms_state_get()->cell_min_vol;
 			}
 		}else if ((bms_state_get()->cell_min_vol >= min_discharger_cell_recovery_vol[_health.is_work_temp_normal])){
+			_single_low_judge_current(false);
 			if (judge_debounce(_health.sigle_cell_lower_voltage, &_sigle_cell_discharger_lower_vol)){
 				_health.sigle_cell_lower_voltage = 0;
 			}
+		}else {
+			debounce_reset(_sigle_cell_discharger_lower_vol);
 		}
 		//check sigle pack's voltage for discharger
 		if (bms_state_get()->pack_voltage <= min_discharger_vol[_health.is_work_temp_normal]){
 			if (judge_debounce(!_health.discharger_lower_voltage, &_discharger_lower_voltage)){
 				_health.discharger_lower_voltage = 1;
+				push_event(Pack_Under_Vol, bms_state_get()->pack_voltage);
+				_pack_low_judge_current(true);
 				error_counts.pack_under_voltage++;
-				discharger_lower_voltage = bms_state_get()->pack_voltage;
 			}
 		}else if (bms_state_get()->pack_voltage >= min_discharger_recovery_vol[_health.is_work_temp_normal]){
+			_pack_low_judge_current(false);
 			if (judge_debounce(_health.discharger_lower_voltage, &_discharger_lower_voltage)){
 				_health.discharger_lower_voltage = 0;
 			}
+		}else {
+			debounce_reset(_discharger_lower_voltage);
 		}
 		//check for shutdown power
 		if ((bms_state_get()->cell_min_vol <= min_discharger_power_cell_vol[_health.is_work_temp_normal])){
 			if (judge_debounce(!_health.discharger_cell_shutpower_voltage, &_shut_discharger_cell_lower_voltage)){
 				_health.discharger_cell_shutpower_voltage = 1;
-				discharger_lower_cell_voltage = bms_state_get()->cell_min_vol;
 			}
 		}else if ((bms_state_get()->cell_min_vol >= min_discharger_power_recovery_cell_vol[_health.is_work_temp_normal])){
 			if (judge_debounce(_health.discharger_cell_shutpower_voltage, &_shut_discharger_cell_lower_voltage)){
 				_health.discharger_cell_shutpower_voltage = 0;
 			}
+		}else {
+			debounce_reset(_shut_discharger_cell_lower_voltage);
 		}
 		if ((bms_state_get()->pack_voltage <= min_discharger_power_vol[_health.is_work_temp_normal])){
 			if (judge_debounce(!_health.discharger_shutpower_voltage, &_shut_discharger_lower_voltage)){
 				_health.discharger_shutpower_voltage = 1;
-				discharger_lower_voltage = bms_state_get()->pack_voltage;
 			}
 		}else if ((bms_state_get()->pack_voltage >= min_discharger_power_recovery_vol[_health.is_work_temp_normal])){
 			if (judge_debounce(_health.discharger_shutpower_voltage, &_shut_discharger_lower_voltage)){
 				_health.discharger_shutpower_voltage = 0;
 			}
+		}else {
+			debounce_reset(_shut_discharger_lower_voltage);
 		}
 	}	
 
@@ -307,7 +379,13 @@ void check_voltage_state(void) {
 			 * system will power on with powerdown_lower_voltage cleared
 			*/			
 			_health.powerdown_lower_voltage = 1;
+			_health.sigle_cell_lower_voltage = 1;
+			_health.pd_time = shark_get_seconds();
 		}
+	}else {
+		_health.powerdown_lower_voltage = 0;
+		_power_down_voltage.count = _power_down_voltage.init_count;
+		_health.pd_time = shark_get_seconds();
 	}
 	debug_health();
 }
@@ -323,6 +401,27 @@ static debounce_t _discharger_lower_temp_count  = {.count = 0, .max_count = 8, .
 static debounce_t _discharger_normal_temp_count = {.count = 0, .max_count = 8, .init_count = 0};
 static debounce_t _work_lower_temp_count = 		{.count = 0, .max_count = 8, .init_count = 0};
 
+static int _get_max_temp(int size){
+	int max = -1000;
+	for (int i = 0; i < size; i++){
+		if (measure_value()->pack_temp[i] >= max){
+			max = measure_value()->pack_temp[i];
+		}
+	}
+	return max;
+}
+
+static int _get_min_temp(int size){
+	int min = 1000;
+	for (int i = 0; i < size; i++){
+		if (measure_value()->pack_temp[i] < min){
+			min = measure_value()->pack_temp[i];
+		}
+	}
+	return min;
+}
+
+
 static int _is_over_temp(int8_t *temps, int size){
 	int count = 0;
 	for (int i = 0; i < size; i++){
@@ -359,6 +458,9 @@ static void _aux_lock_timer_handler(shark_timer_t *t){
 		int short_voltage = get_small_current_voltage()/1000;
 		int pack_voltage = bms_state_get()->pack_voltage/1000;
 		if (short_voltage >= AUX_SHORT_DIFF_VOLTAGE) {
+			if (_health.small_current_short == 0) {
+				push_event(Aux_Current_Short, short_voltage);
+			}
 			_health.small_current_short = 1;
 			error_counts.aux_short ++;
 			AUX_VOL_OPEN(0);
@@ -423,6 +525,8 @@ void check_temp_state(void){
 		}
 		if (debounce_reach_max(_charger_over_temp_count)){
 			_health.over_temp_deny_charger = 1;
+			push_event(Temp_High_Charger, _get_max_temp(4));
+			error_counts.charger_high_temp ++;
 			debounce_reset(_charger_over_temp_count);
 		}			
 	}
@@ -434,6 +538,8 @@ void check_temp_state(void){
 		}
 		if (debounce_reach_max(_charger_lower_temp_count)) {
 			_health.lower_temp_deny_charger = 1;
+			push_event(Temp_Low_Charger, _get_min_temp(4));
+			error_counts.charger_lower_temp ++;
 			debounce_reset(_charger_lower_temp_count);
 		}
 	}
@@ -458,6 +564,8 @@ void check_temp_state(void){
 		}
 		if (debounce_reach_max(_discharger_over_temp_count)){
 			_health.over_temp_deny_discharger = 1;
+			push_event(Temp_High_Discharger, _get_max_temp(4));
+			error_counts.discharger_high_temp ++;
 			debounce_reset(_discharger_over_temp_count);
 		}			
 	}
@@ -470,6 +578,8 @@ void check_temp_state(void){
 		}
 		if (debounce_reach_max(_discharger_lower_temp_count)) {
 			_health.lower_temp_deny_discharger = 1;
+			push_event(Temp_Low_Discharger, _get_min_temp(4));
+			error_counts.discharger_lower_temp ++;
 			debounce_reset(_discharger_lower_temp_count);
 		}
 	}
@@ -491,6 +601,7 @@ void check_temp_state(void){
 			debounce_inc(_work_lower_temp_count);
 			if (debounce_reach_max(_work_lower_temp_count)){
 				_health.is_work_temp_normal = 1;
+				push_event(Temp_Changed, 1);
 				debounce_reset(_work_lower_temp_count);
 			}
 		}else {
@@ -501,6 +612,7 @@ void check_temp_state(void){
 			debounce_inc(_work_lower_temp_count);
 			if (debounce_reach_max(_work_lower_temp_count)){
 				_health.is_work_temp_normal = 0;
+				push_event(Temp_Changed, 0);
 				debounce_reset(_work_lower_temp_count);
 			}
 		}else {

+ 54 - 29
Application/app/sox/health.h

@@ -4,7 +4,7 @@
 #include "bsp/shark_bsp.h"
 
 #define MAX_CURRENT_FOR_CHARGER (30*1000) //最大充电电流20A
-#define SIGLE_CELL_MAX_CHARGER_VOLTAGE (3800)//最大允许充电电压,3.9v,考虑到采样的误差取 3.88
+#define SIGLE_CELL_MAX_CHARGER_VOLTAGE (3650)//最大允许充电电压,3.9v,考虑到采样的误差取 3.88
 #define MAX_CURRENT_FOR_DISCHARGER (120 * 1000) //软件采样的电流保护
 #define AUX_SHORT_REAL_DIFF_VOLTAGE (5) //判断小电流是否真实短路的,端口压差
 #define AUX_SHORT_DIFF_VOLTAGE (7.5f) //判断小电流是否保护,28欧姆上的电压,能抗300mA
@@ -14,43 +14,60 @@
  * xxx_under_temp: 表示过低温(温度过低)
 */
 typedef struct {
-	uint32_t charger_over_voltage:1;
-	uint32_t discharger_lower_voltage:1; //关闭大电流输出
-	uint32_t small_current_short:1;
-	uint32_t load_current_short:1; //大电短路保护
+	union {
+		uint32_t i_status;
+		struct {
+			uint32_t charger_over_voltage:1;
+			uint32_t discharger_lower_voltage:1; //关闭大电流输出
+			uint32_t small_current_short:1;
+			uint32_t load_current_short:1; //大电短路保护
 
-	uint32_t charger_current:1; //不需要
-	uint32_t discharger_current:1;
-	uint32_t charger_over_current:1;
-	uint32_t discharger_over_current:1;
+			uint32_t charger_current:1; //不需要
+			uint32_t discharger_current:1;
+			uint32_t charger_over_current:1;
+			uint32_t discharger_over_current:1;
 
-	uint32_t res1 :1;//ST_TOTAL_CHRG
-	uint32_t charger_cells_vol_diff_over:1; //充电cell的电压差异超过阈值
-	uint32_t power_save:1;
-	uint32_t powerdown_lower_voltage:1;
+			uint32_t res1 :1;//ST_TOTAL_CHRG
+			uint32_t charger_cells_vol_diff_over:1; //充电cell的电压差异超过阈值
+			uint32_t power_save:1;
+			uint32_t powerdown_lower_voltage:1;
 
-	uint32_t charger_lower_temp:1;
-	uint32_t discharger_lower_temp:1;
-	uint32_t charger_over_temp:1;
-	uint32_t discharger_over_temp:1;
+			uint32_t charger_lower_temp:1;
+			uint32_t discharger_lower_temp:1;
+			uint32_t charger_over_temp:1;
+			uint32_t discharger_over_temp:1;
 
-	uint32_t sigle_cell_lower_voltage:1; //关闭大电流输出
-	uint32_t sigle_cell_over_voltage:1;
-	uint32_t discharger_shutpower_voltage:1; //关闭动力
-	uint32_t discharger_cell_shutpower_voltage:1; //关闭动力
+			uint32_t sigle_cell_lower_voltage:1; //关闭大电流输出
+			uint32_t sigle_cell_over_voltage:1;
+			uint32_t discharger_shutpower_voltage:1; //关闭动力
+			uint32_t discharger_cell_shutpower_voltage:1; //关闭动力
 
-	uint32_t hall_is_detected:1;
-	uint32_t lower_temp_deny_charger:1;
-	uint32_t lower_temp_deny_discharger:1;
-	uint32_t over_temp_deny_charger:1;
-	uint32_t over_temp_deny_discharger:1;
-
-	uint32_t is_work_temp_normal:1;
-	uint32_t small_current_real_short:1; //真实短路
+			uint32_t hall_is_detected:1;
+			uint32_t lower_temp_deny_charger:1;
+			uint32_t lower_temp_deny_discharger:1;
+			uint32_t over_temp_deny_charger:1;
+			uint32_t over_temp_deny_discharger:1;
 
+			uint32_t is_work_temp_normal:1;
+			uint32_t small_current_real_short:1; //真实短路
+		};
+	};
 	uint8_t    internal_resistance[CELLS_NUM];   //cell's internal resistance
+	uint32_t      pd_time;
+	uint32_t      b_flags;
 }bms_health_t;
 
+#define B_FLAGS_SINGLE_LOW_CURRENT 0x1
+#define B_FLAGS_SINGLE_MID_CURRENT 0x2
+#define B_FLAGS_SINGLE_BIG_CURRENT 0x4
+#define B_FLAGS_SINGLE_LARGER_CURRENT 0x8
+
+#define B_FLAGS_PACK_LOW_CURRENT 0x10
+#define B_FLAGS_PACK_MID_CURRENT 0x20
+#define B_FLAGS_PACK_BIG_CURRENT 0x40
+#define B_FLAGS_PACK_LARGER_CURRENT 0x80
+
+
 typedef struct {
 	uint32_t soft_current_short;
 	uint32_t hard_current_short;
@@ -58,6 +75,10 @@ typedef struct {
 	uint32_t aux_real_short;
 	uint32_t cell_under_voltage;
 	uint32_t pack_under_voltage;
+	uint32_t discharger_high_temp;
+	uint32_t discharger_lower_temp;
+	uint32_t charger_high_temp;
+	uint32_t charger_lower_temp;
 	uint32_t uart_crc_error;
 	uint32_t uart_len_error;
 	uint32_t uart_dir_error;
@@ -73,6 +94,10 @@ void health_stop_aux_detect(void);
 uint32_t bms_health_pack_lower_voltage(void);
 uint32_t bms_health_cell_lower_voltage(void);
 void health_log(void);
+#define health_is_low_current() (bms_health()->b_flags & (B_FLAGS_SINGLE_LOW_CURRENT | B_FLAGS_PACK_LOW_CURRENT))
+#define health_is_mid_current() (bms_health()->b_flags & (B_FLAGS_SINGLE_MID_CURRENT | B_FLAGS_PACK_MID_CURRENT))
+#define health_is_big_current() (bms_health()->b_flags & (B_FLAGS_SINGLE_BIG_CURRENT | B_FLAGS_PACK_BIG_CURRENT)) 
+#define health_is_larger_current() (bms_health()->b_flags & (B_FLAGS_SINGLE_LARGER_CURRENT | B_FLAGS_PACK_LARGER_CURRENT)) 
 
 #endif /* _HEALTH_H__ */
 

+ 5 - 5
Application/app/sox/iostate.c

@@ -22,7 +22,7 @@ typedef struct io_timer{
 #define io_debounce_time 50
 
 static void io_timer_handler(shark_timer_t *t);
-static io_timer_t hall_io = {._timer.handler = io_timer_handler, .debounce_time_zero = 100, .debounce_time_one = 100};
+static io_timer_t hall_io = {._timer.handler = io_timer_handler, .debounce_time_zero = 500, .debounce_time_one = 50};
 static io_timer_t charger_io = {._timer.handler = io_timer_handler, .debounce_time_zero = 50, .debounce_time_one = 50};
 static io_timer_t aux_short_io = {._timer.handler = io_timer_handler, .debounce_time_zero = 50, .debounce_time_one = 50};
 static io_timer_t dcdc_pwr_io = {._timer.handler = io_timer_handler, .debounce_time_zero = 50, .debounce_time_one = 50};
@@ -36,10 +36,10 @@ void iostate_log(void){
 
 void io_state_init(void){
 	set_log_level(MOD_IO, L_debug);
-	_io_state.hall_detect = IS_HALL1_DETECTED()|| IS_HALL2_DETECTED();
-	_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() && AUX_VOL_IS_OPEN();
+	hall_io.value = _io_state.hall_detect = IS_HALL1_DETECTED()|| IS_HALL2_DETECTED();
+	charger_io.value = _io_state.charger_detect = IS_CHARGER_IN();
+	dcdc_pwr_io.value = _io_state.dcdc_good_detect= IS_DCDC_POWER_GOOD();
+	aux_short_io.value = _io_state.aux_lock_detect = IS_AUX_VOL_LOCKED() && AUX_VOL_IS_OPEN();
 
 	shark_timer_post(&hall_io._timer, io_detect_intv_time);
 	shark_timer_post(&charger_io._timer, io_detect_intv_time);

+ 61 - 17
Application/app/sox/measure.c

@@ -49,17 +49,23 @@ static const float max_cs1180_adc = 0x7FFFF;//
 static const float small_cur_r_sense = 0.360f;//ŷķ
 uint32_t check_gain_error = 0;
 static u64      check_gain_time = 0;
+u32   dgain_switch_count = 0;
+u32   cgain_switch_count = 0;
 static least_square_t adc_cali[2]; // y = ax + b
 
 #define GD32_ADC_READ_TIMES 128
 
-static int __inline__ _is_x10_gain(void){
+static int __inline__ is_x10_gain(void){
 	return imon_gain_now == imon_gain_10x;
 }
 
+static int __inline__ is_x50_gain(void){
+	return imon_gain_now == imon_gain_50x;
+}
+
 static void __inline__ check_gain(void){
 	int count = 5;
-	while (_is_x10_gain() && !ML5238_IS_10X()){
+	while (is_x10_gain() && !ML5238_IS_10X()){
 		ML5238_IMON_OUT_10X();
 		check_gain_error ++;
 		if (count-- <= 0) {
@@ -67,7 +73,7 @@ static void __inline__ check_gain(void){
 		}
 	}
 	count = 5;
-	while (!_is_x10_gain() && !ML5238_IS_50X()){
+	while (is_x50_gain() && !ML5238_IS_50X()){
 		ML5238_IMON_OUT_50X();
 		check_gain_error ++;
 		if (count-- <= 0) {
@@ -76,7 +82,7 @@ static void __inline__ check_gain(void){
 	}
 }
 
-static void __inline__ select_gain_10x(int select){	
+static void __inline__ _select_gain_10x(int select){
 	if (select){
 		ML5238_IMON_OUT_10X();
 		imon_gain_now = imon_gain_10x;
@@ -92,6 +98,15 @@ static void __inline__ select_gain_10x(int select){
 	check_gain();
 }
 
+static void __inline select_gain_10x(void) {
+	_select_gain_10x(1);
+}
+
+static void __inline select_gain_50x(void) {
+	_select_gain_10x(0);
+}
+
+
 float get_ml5238_gain(void){
 	return imon_gain_now;
 }
@@ -136,9 +151,9 @@ void current_calibrate(void){
 	current_10x_calibrate();
 	current_50x_calibrate();
 #ifdef gain_default_50x
-	select_gain_10x(0);
+	select_gain_50x();
 #else
-	select_gain_10x(1);
+	select_gain_10x();
 #endif
 }
 
@@ -159,20 +174,49 @@ static float get_current_by_ml5238(void){
 
 /* get battery pack's current (mA) */
 static float get_pack_current_by_gd(void){
+	static u64 debounce_change_10xgain = 0;
+	static u64 debounce_change_50xgain = 0;
 	u64 time_now = shark_get_mseconds();
-	if (time_now - check_gain_time >= 100) {
+	if (time_now - check_gain_time >= 1000) {
 		check_gain();
 		check_gain_time = time_now;
 	}
 	float adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
-	if (adc >= (max_gd_adc - 255.0f) && (!_is_x10_gain())){//overflow, use 10x gain
-		select_gain_10x(1);
-		adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
-	}else if (abs(adc - vim0_now) <= 255.0f && (_is_x10_gain())){// is too small, select 50x gain
-		select_gain_10x(0); 
-		adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);		
+	if (is_x10_gain()) { //is x10 gian
+		debounce_change_50xgain = shark_get_mseconds();
+		if ((adc < vim0_now) && (vim0_now - adc) <= 200) { //charging below about 16A, changed to 50x gain
+			select_gain_50x();
+			adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
+			cgain_switch_count ++;
+		}else if (adc > vim0_now) { //discharging below about 10A, changed to 50x gain(after 5s, avoid change gain freqencely)
+			if ((adc - vim0_now) <= 130) {
+				if ((shark_get_mseconds() - debounce_change_10xgain) >= 5*1000) {
+					select_gain_50x();
+					adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
+					debounce_change_10xgain = shark_get_mseconds();
+					dgain_switch_count ++;
+				}
+			}else {
+				debounce_change_10xgain = shark_get_mseconds();
+			}
+		}
+	}else { //is x50 gain
+		debounce_change_10xgain = shark_get_mseconds();
+		if (vim0_now - adc >= 1120){//charging >= 18A, full is 1241(20A)
+			select_gain_10x();
+			adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
+			cgain_switch_count ++;
+		}else if (adc - vim0_now >= 2170) { //discharing >= 35A, full is 2850(46A)
+			if ((shark_get_mseconds() - debounce_change_50xgain) >= 500) { //after 500ms
+				select_gain_10x();
+				adc = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
+				debounce_change_50xgain = shark_get_mseconds();
+				dgain_switch_count ++;
+			}
+		}else {
+			debounce_change_50xgain = shark_get_mseconds();
+		}
 	}
-
 	float cali_adc = ML5238_V_RSENSER(adc, vim0_now, imon_gain_now);
 
 	return (int)((cali_adc / max_gd_adc) * v_gd_ref / r_sense * 1000);
@@ -251,9 +295,9 @@ int measure_start_cali(uint8_t adc, uint8_t gain, uint8_t samples){
 	sys_debug("start cali %d, %d, %d\n", adc, gain, samples);
 	if (adc == GD32_ADC) {
 		if (gain == 10) {
-			select_gain_10x(1);
+			select_gain_10x();
 		}else if (gain == 50) {
-			select_gain_10x(0);
+			select_gain_50x();
 		}else {
 			return 0;
 		}
@@ -290,7 +334,7 @@ int measure_stop_cali(uint8_t adc, uint8_t gain){
 		}
 		sys_debug("stop %f, %f\n", adc_cali[adc].coeff.Ka, adc_cali[adc].coeff.Cb);
 	}
-	select_gain_10x(0);
+	select_gain_50x();
 	return adc_cali[adc].finished;
 }
 

+ 63 - 23
Application/app/sox/measure_task.c

@@ -19,7 +19,8 @@ struct means_task {
 	u8  index;
 };
 
-static void init_current_voltage_task(void);
+static void init_current_task(void);
+static void init_voltage_task(void);
 static void init_temp_task(void);
 
 void measure_task_init(measure_notify cn, measure_notify vn, measure_notify tn){
@@ -27,7 +28,8 @@ void measure_task_init(measure_notify cn, measure_notify vn, measure_notify tn){
 	_voltage_notify = vn;
 	_temperature_notify = tn;
 	measure_adc_init();
-	init_current_voltage_task();
+	init_current_task();
+	init_voltage_task();
 	init_temp_task();
 	set_log_level(MOD_MEASURE, L_debug);
 }
@@ -37,50 +39,88 @@ measure_value_t * measure_value(void){
 }
 extern uint32_t check_gain_error;
 extern int gd32_adc_error;
+extern u32 dgain_switch_count, cgain_switch_count;
 void measure_log(void){
 	measure_debug("Current %.4f -- %.4f\n", (float)_measure_value.load_current/1000.0f, (float)_measure_value.current_5238/1000.0f);
-	for (int i = 0; i < CELLS_NUM; i++){
-		//measure_debug("Cell[%d]: %.3fv\n", i, _measure_value.cell_vol[i]/1000.0f);
-	}
 	measure_debug("Gain:%f, Off %f, check error = %d, %d\n", get_ml5238_gain(), get_ml5238_vos(), check_gain_error, gd32_adc_error);
+	measure_debug("Gain switch: %d, %d\n", dgain_switch_count, cgain_switch_count);
 }
 /*
  * 测量电芯电压,计算出总电压, 测量总电流,放电和充电
 */
-static struct means_task _current_voltage_task;
-static u32 current_voltage_task_handler(void);
-static void init_current_voltage_task(void){
-	_current_voltage_task._task.handler = current_voltage_task_handler;
-	_current_voltage_task.delay = 25;
-	_current_voltage_task.index = CELLS_NUM;
+static struct means_task _current_task;
+static struct means_task _voltage_task;
+
+static u32 current_task_handler(void);
+static u32 voltage_task_handler(void);
+static void init_current_task(void){
+	_current_task._task.handler = current_task_handler;
+	_current_task.delay = 25;
 	_measure_value.load_current = get_pack_current(&_measure_value.current_5238);
-	for (int i = 0; i < CELLS_NUM; i++){
-		_measure_value.cell_vol[i] = get_cell_voltage(i);
-	}
-	shark_task_add(&_current_voltage_task._task);
+
+	shark_task_add(&_current_task._task);
 }
 
-static u32 current_voltage_task_handler(void){
+static u32 current_task_handler(void){
 	if (bms_work_is_calibrating()){
-		return _current_voltage_task.delay;
+		return _current_task.delay;
 	}
 	/* 测量电流 */
 	_measure_value.load_current = get_pack_current(&_measure_value.current_5238);
 	_current_notify();//通知bms state 有新的电流数据
 
+	if (abs(_measure_value.load_current) >= MIN_CURRENT_FOR_CS1180) {
+		return 5;
+	}
+	return _current_task.delay;
+}
+
+static void init_voltage_task(void){
+	_voltage_task._task.handler = voltage_task_handler;
+	_voltage_task.delay = 50;
+	_voltage_task.index = CELLS_NUM;
+	_measure_value.min_vol = 10000;
+	_measure_value.max_vol = 0;
+	for (int i = 0; i < CELLS_NUM; i++){
+		_measure_value.cell_vol[i] = get_cell_voltage(i);
+		if (_measure_value.cell_vol[i] > _measure_value.max_vol) {
+			_measure_value.max_vol = _measure_value.cell_vol[i];
+		}
+		if (_measure_value.cell_vol[i] < _measure_value.min_vol) {
+			_measure_value.min_vol = _measure_value.cell_vol[i];
+		}		
+	}
+	shark_task_add(&_voltage_task._task);
+}
+
+static u32 voltage_task_handler(void){
+	if (bms_work_is_calibrating()){
+		return _voltage_task.delay;
+	}
+
 	if (bms_state_get()->pack_balancing){ //if balance, do'nt sample cell voltage
-		return _current_voltage_task.delay;
+		return _voltage_task.delay;
 	}	
 	//用内阻对cell的电压进行补偿,充电减,放电加
-	_current_voltage_task.index = (_current_voltage_task.index + 1) % CELLS_NUM;
-	_measure_value.cell_vol[_current_voltage_task.index] = get_cell_voltage(_current_voltage_task.index) - bms_health()->internal_resistance[_current_voltage_task.index] * _measure_value.load_current/1000;
+	_voltage_task.index = (_voltage_task.index + 1) % CELLS_NUM;
+	_measure_value.cell_vol[_voltage_task.index] = get_cell_voltage(_voltage_task.index) - bms_health()->internal_resistance[_voltage_task.index] * _measure_value.load_current/1000;
+	if (_measure_value.cell_vol[_voltage_task.index] > _measure_value.max_vol) {
+		_measure_value.max_vol = _measure_value.cell_vol[_voltage_task.index];
+	}
+	if (_measure_value.cell_vol[_voltage_task.index] < _measure_value.min_vol) {
+		_measure_value.min_vol = _measure_value.cell_vol[_voltage_task.index];
+	}
 	_voltage_notify();//通知bms state 有新的电压数据
-	if (abs(_measure_value.load_current) >= MIN_CURRENT_FOR_CS1180) {
-		return 5;
+	//接近过压或者欠压,加快采集速度
+	if ((_measure_value.min_vol < 2300) || (_measure_value.max_vol > 3600)) {
+		if (abs(_measure_value.load_current) >= MIN_CURRENT_FOR_CS1180){
+			return 5;
+		}
 	}
-	return _current_voltage_task.delay;
+	return _voltage_task.delay;
 }
 
+
 /*
  * 测量4个温度
 */

+ 2 - 0
Application/app/sox/measure_task.h

@@ -8,6 +8,8 @@ typedef struct{
 	int current_5238;
 	int      pack_temp[PACK_TEMPS_NUM];
 	uint16_t cell_vol[CELLS_NUM]; //mV
+	uint16_t min_vol;
+	uint16_t max_vol;
 }measure_value_t;
 typedef void (*measure_notify)(void);
 

+ 261 - 106
Application/app/sox/soc.c

@@ -6,6 +6,7 @@
 #include "Least_Square.h"
 #include "health.h"
 #include "state.h"
+#include "event_record.h"
 
 #define LEAST_SQUARE 0
 
@@ -13,19 +14,27 @@ static soc_t _soc;
 static uint8_t chargering = 0;
 static u64     current_sample_ts = 0; //ms
 static u32     force_full_ts = 0xFFFFFFFF; //s
-static float     soc_delta_time = 0;
-static float     max_soc_delta_time = 0;
+static u32     force_empty_ts = 0xFFFFFFFF; //s
+static float   soc_delta_time = 0;
+static float   max_soc_delta_time = 0;
 static float _charger_coefficient = 1.0f;
 static float _discharger_coefficient = 1.0f;
-uint32_t charger_remain_time = 0;
-uint8_t battery_temp_state = 0;
-static const float _discharger_gain[] = {1.0f/*>0度*/, 1.002f/*-2<t<=0*/, 1.005f/*-5<t<=-2*/, 1.008f/*-10<t<=-5*/, 1.02f/*-15<t<=-10*/, 1.04f/*-20<t<=-15*/};
+static float _discharger_no_full_coef = 1.0f;
+static uint32_t charger_remain_time = 0;
+static uint8_t  version_changed = 0;
+static bool    b_sn_byte7_f = false;
+static float   small_20_dischr = 0;
+static const float _discharger_gain[] = {1.0f/*>0度*/, 1.03f/*-2<t<=0*/, 1.06f/*-5<t<=-2*/, 1.08f/*-10<t<=-5*/, 1.11f/*-15<t<=-10*/, 1.15f/*-20<t<=-15*/};
 #define MAX_TIME_FULL_TO_EMPTY (5 * 24 * 3600) //充满到欠压5天内达到,可以校准最小电量
+#define MAX_TIME_EMPTY_TO_FULL (24 * 3600) //欠压到充满24小时内达到,可以校准最小电量
 #define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
 #define DEFALUT_MIN_COULOMB (25.0f * 3600.0f)
 #define FULL_MAX_VOLTAGE_CHARGING (53500)//mV
+#define FULL_MAX_VOLTAGE_STOP_CHARGING (53000)
+#define AGINT_TEST_MAX_VOLTAGE_CHARGING (53000) //mV
 #define FULL_MAX_VOLTAGE (54000) //mV
 #define FULL_MIN_CURRENT (500.0f) //mA
+//static double start_charger_coulomb = 0.0f; //开始充电时候的容量
 static void calibrate_soc_by_ocv(void);
 static void _soc_clear(void);
 
@@ -47,6 +56,9 @@ void soc_init(void){
 		soc_warning("SOC: nv storage is not inited, use default value!!\n");
 		_soc_clear();
 	}
+	if (nv_get_sn_byte7() == 'F') {
+		b_sn_byte7_f = true;
+	}
 	//如果最大容量和默认不一致,需要重新校准
 	if (_soc.coulomb_max != DEFALUT_MAX_COULOMB) {
 		_soc_clear();
@@ -55,19 +67,53 @@ void soc_init(void){
 	if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
 		calibrate_soc_by_ocv();
 		nv_save_soc();
+	}else {
+		if (_soc.capacity == 100) {
+			force_full_ts = shark_get_seconds() + 1;
+		}else if (_soc.capacity == 0) {
+			force_empty_ts = shark_get_seconds() + 1;
+		}
+	}
+	if (soc_get_version() != SOC_CURRENT_VERSION) {
+		_soc.current_real_coulomb = (_soc.coulomb_now - _soc.coulomb_min);
+		version_changed = 1;
+		soc_set_version(SOC_CURRENT_VERSION);
+		nv_save_all_soc();
 	}
 	soc_log();
 }
 
+u8 soc_get_version(void) {
+	return SOC_FLAG_TO_VER(_soc.flags);
+}
+
+void soc_set_version(u8 version) {
+	if (version > 7) {
+		return;
+	}
+	_soc.flags &= ~SOC_FLAG_VERSON_MASK;
+	_soc.flags |= SOC_FLAG_VERSION(version);
+}
+
 static void _soc_clear(void){
 	_soc.coulomb_min = 0;
 	_soc.coulomb_max = DEFALUT_MAX_COULOMB; //30HA,这个值最总需要soh模块给
-	_soc.flags = 0;
+	_soc.flags = SOC_FLAG_VERSION(SOC_CURRENT_VERSION);
 	_soc.charger_coulomb = 0;
 	_soc.pre_charger_coulomb = 0;
 	_soc.dischrger_coulomb = 0;
 	_soc.pre_discharger_coulomb = 0;
 	_soc.total_coulomb = 0;
+	_soc.current_real_coulomb = 0;
+}
+
+void soc_clear_calibrate(int keep_cycle) {
+	float total = _soc.total_coulomb;
+	_soc_clear();
+	if (keep_cycle) {
+		_soc.total_coulomb = total;
+	}
+	nv_save_all_soc();
 }
 
 void soc_restore_by_iap(uint8_t flags, uint8_t capaticy){
@@ -135,7 +181,16 @@ static void soc_update_discharger_coeff(void){
 				coff = 1.01f;
 			}
 		}
+		if ((abs(measure_value()->load_current) > 10.0f) && (abs(measure_value()->load_current) < 500)) {
+			coff = 1.05f;
+		}else {
+			coff = _discharger_no_full_coef * coff;
+		}
+		
 		_discharger_coefficient = _discharger_coefficient * coff;
+		if (b_sn_byte7_f) {
+			_discharger_coefficient = _discharger_coefficient * 1.09f;
+		}
 	}
 }
 
@@ -183,13 +238,12 @@ void soc_log(void){
 	soc_debug("C min: %.4f\n", TOHA(_soc.coulomb_min));
 	soc_debug("C max: %.4f\n", TOHA(_soc.coulomb_max));
 	soc_debug("C char: %.4f\n", TOHA(_soc.charger_coulomb));
-	soc_debug("C dischar: %.4f\n", TOHA(_soc.dischrger_coulomb));
-	soc_debug("C pre char: %.4f\n", TOHA(_soc.pre_discharger_coulomb));
-	soc_debug("C pre dischar: %.4f\n", TOHA(_soc.pre_charger_coulomb));
+	soc_debug("C dischar: %.4f, F:%c\n", TOHA(_soc.dischrger_coulomb), b_sn_byte7_f?'Y':'N');
+	soc_debug("C version: %d, %d\n", soc_get_version(), version_changed);
 	soc_debug("C tol: %.2f\n", _soc.total_coulomb);
-	soc_debug("C energy: %f\n", _soc.energy);
-	soc_debug("C delta time %f,%f, -- %d\n", max_soc_delta_time, soc_delta_time, force_full_ts);
-	soc_debug("C discharger coefficient = %f\n", _discharger_coefficient);
+	soc_debug("C real_coulomb: %f\n", _soc.current_real_coulomb);
+	soc_debug("C delta time %f, %f, -- %d\n", max_soc_delta_time, soc_delta_time, force_full_ts);
+	soc_debug("C discharger coefficient = %f, %f, %f\n", _discharger_coefficient, _discharger_no_full_coef, small_20_dischr);
 	if (chargering){
 		soc_debug("C remain %d\n", charger_remain_time);
 	}
@@ -201,34 +255,20 @@ static void calibrate_soc_by_ocv(void){
 	for (int i = 0; i < CELLS_NUM; i++){
 		pack_vol += measure_value()->cell_vol[i];
 	}
-	if (pack_vol < (2700 * CELLS_NUM)){
+	if (pack_vol <= (48000)){
 		_soc.capacity = 0;
-	}else if (pack_vol < (2900 * CELLS_NUM)){
+	}else if (pack_vol <= 49000){
 		_soc.capacity = 5;
-	}else if (pack_vol < (2950 * CELLS_NUM)){
-		_soc.capacity = 15;
-	}else if (pack_vol < (3000 * CELLS_NUM)){
+	}else if (pack_vol <= 50000){
+		_soc.capacity = 10;
+	}else if (pack_vol <= 51000){
 		_soc.capacity = 30;
-	}else if (pack_vol < (3050 * CELLS_NUM)){
-		_soc.capacity = 40;
-	}else if (pack_vol < (3100 * CELLS_NUM)){
-		_soc.capacity = 45;
-	}else if (pack_vol < (3150 * CELLS_NUM)){
+	}else if (pack_vol <= 52000){
 		_soc.capacity = 50;
-	}else if (pack_vol < (3200 * CELLS_NUM)){
-		_soc.capacity = 55;
-	}else if (pack_vol < (3250 * CELLS_NUM)){
-		_soc.capacity = 65;
-	}else if (pack_vol < (3300 * CELLS_NUM)){
-		_soc.capacity = 75;
-	}else if (pack_vol < (3400 * CELLS_NUM)){
-		_soc.capacity = 85;
-	}else if (pack_vol < (3500 * CELLS_NUM)){
-		_soc.capacity = 90;
-	}else if (pack_vol < (3550 * CELLS_NUM)){
-		_soc.capacity = 95;
+	}else if (pack_vol <= 53000){
+		_soc.capacity = 60;
 	}else {
-		_soc.capacity = 100;
+		_soc.capacity = 80;
 	}
 	_soc.coulomb_now = (_soc.coulomb_max - _soc.coulomb_min) * _soc.capacity / 100.0f + _soc.coulomb_min;
 	soc_warning("SOC: calibrate_soc_by_ocv -> capacity = %d, pack_voltage = %d\n", _soc.capacity, pack_vol);
@@ -245,8 +285,11 @@ static __inline__ float _delta_time(void){
 }
 
 static __inline__ int can_modify_min_cap(void){
+	if (force_full_ts == 0) {
+		return 0;
+	}
 	if (shark_get_seconds() > force_full_ts){
-		if ((shark_get_seconds() - force_full_ts) > MAX_TIME_FULL_TO_EMPTY) {
+		if ((shark_get_seconds() - force_full_ts) >= MAX_TIME_FULL_TO_EMPTY) {
 			return 0;
 		}else {
 			return 1;
@@ -255,8 +298,84 @@ static __inline__ int can_modify_min_cap(void){
 	return 0;
 }
 
+
+static __inline__ int can_modify_min_when_full(void){
+	if (force_empty_ts == 0) {
+		return 0;
+	}
+	if (shark_get_seconds() > force_empty_ts){
+		if ((shark_get_seconds() - force_empty_ts) >= MAX_TIME_EMPTY_TO_FULL) {
+			return 0;
+		}else {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static bool is_force_full = false;
+static u32  force_full_time = 0;
+bool soc_is_force_full(void) {
+	if (is_force_full) {
+		if (shark_get_seconds() >= 5 + force_full_time) {
+			is_force_full = false;
+		}
+	}
+	return is_force_full;
+}
+
+#define min_cap_lfp 0.5f
 static void _force_capacity_full(void){
+	is_force_full = true;
+	force_full_time = shark_get_seconds();
+	double curr_min_cap = 0.0f;
+
+	if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
+		_soc.current_real_coulomb = _soc.coulomb_max;
+		_discharger_no_full_coef = 1.0f;
+	}
+
+	if (_soc.current_real_coulomb < _soc.coulomb_max) {
+		curr_min_cap = _soc.coulomb_max - _soc.current_real_coulomb;
+	}
+
+	if (can_modify_min_when_full()) { //当前容量没到最大容量
+		//don't trust if curr_min_cap big than before
+		if (curr_min_cap <= _soc.coulomb_min) {
+			_soc.coulomb_min = _soc.coulomb_min * (1.0f - min_cap_lfp) + curr_min_cap * min_cap_lfp; //lowpass filter
+		}
+	}
+	if (curr_min_cap <= _soc.coulomb_min) {
+		_discharger_no_full_coef = 1.0f;
+	}else {
+		double delta_min = curr_min_cap - _soc.coulomb_min;
+		_discharger_no_full_coef = 1.0f + delta_min/(_soc.coulomb_max - _soc.coulomb_min);
+	}
+
+	u32 cap_x10 = (u32)(_soc.current_real_coulomb / 3600.0f * 10);
+	u32 min_x10 = (u32)(curr_min_cap / 3600.0f * 10);
+	push_event(Charger_Full_cap2, ((min_x10 & 0xFFFF) << 16) | (cap_x10 & 0xFFFF));
+	// 认为本次充电正常
+	if (bms_state_get()->pack_voltage >= 53000) {
+		_soc.current_real_coulomb = _soc.coulomb_max - _soc.coulomb_min;
+		_discharger_no_full_coef = 1.0f;
+	}else if (bms_state_get()->pack_voltage >= (53000 - 200)) {
+		_discharger_no_full_coef = MIN(_discharger_no_full_coef, 1.005f);
+	}else if (bms_state_get()->pack_voltage >= (53000 - 400)) {
+		_discharger_no_full_coef = MIN(_discharger_no_full_coef, 1.01f);
+	}else if (bms_state_get()->pack_voltage >= (53000 - 800)) {
+		_discharger_no_full_coef = MIN(_discharger_no_full_coef, 1.015f);
+	}else if (bms_state_get()->pack_voltage >= (53000 - 1000)) {
+		_discharger_no_full_coef = MIN(_discharger_no_full_coef, 1.02f);
+	}else {
+		_discharger_no_full_coef = MIN(_discharger_no_full_coef, 1.03f);
+	}
+	push_event(Charger_no_full_ceof, (u32)(_discharger_no_full_coef * 10000));
+
+	//充满后,当前容量设置为最大容量
 	_soc.capacity = 100;
+	_soc.coulomb_now = _soc.coulomb_max;
+
 	force_full_ts = shark_get_seconds();
 }
 
@@ -265,19 +384,9 @@ static int _soc_is_under_voltage(void) {
 		bms_health()->discharger_lower_voltage);
 }
 
-#if 0
-static int _soc_force_capaticy(uint8_t capaticy){
-	float cap = (float)capaticy / 100.0f;
-	float min = (_soc.coulomb_now - cap * _soc.coulomb_max)/(1.0f - cap);
-	if (min > 0.0f) {
-		_soc.coulomb_min = min;
-		_soc.capacity = capaticy;
-		force_full_ts = 0xFFFFFFFF;
-		return 1;
-	}
-	return 0;
+static int _is_normal_charging(void) {
+	return (_soc.charger_coulomb >= (0.1f * 3600.0f));
 }
-#endif
 
 static int _soc_update_by_ocv(uint8_t prev_charge_status){
 	static int ocv_full_count = 0;
@@ -288,52 +397,55 @@ static int _soc_update_by_ocv(uint8_t prev_charge_status){
 	}
 	if (!chargering){
 		if (_soc.capacity && _soc_is_under_voltage()) {
-			soc_warning("judge calib min col %d - %d\n", shark_get_seconds(), force_full_ts);
+			soc_warning("judge calib min col %d - %d\n", shark_get_seconds(), force_empty_ts);
 			if (can_modify_min_cap()){
-				_soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池在常温下进入powerdown,最小容量修正为当前容量
-				soc_warning("calicablite coulomb_min %f\n", _soc.coulomb_min);
+				if (health_is_low_current()) {
+					_soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池在常温下进入powerdown,最小容量修正为当前容量
+				}else if (health_is_mid_current()) {
+					_soc.coulomb_min = _soc.coulomb_now * 1.0f;
+				}else if (health_is_big_current()){
+					_soc.coulomb_min = _soc.coulomb_now * 0.95f;
+				}else {
+					_soc.coulomb_min = _soc.coulomb_now * 0.9f;
+				}
+				_soc.coulomb_now = _soc.coulomb_min;
 			}else {
 				_soc.coulomb_now = _soc.coulomb_min;
 			}
+			u32 cap_x10 = (u32)(_soc.coulomb_now / 3600.0f * 10);
+			push_event(Min_Cap_For_DisCharger2, (bms_state_get()->pack_voltage << 16) | (cap_x10 & 0xFFFF));
+			force_empty_ts = shark_get_seconds();
 			_soc.capacity = 0;
+			_soc.current_real_coulomb = 0.0f;
 			return 1;
-		}
-#if 0
-		else if ((!prev_charge_status) && (bms_state_get()->cell_min_vol <= 2900) && (_soc.capacity > 10)) {
-			/* 如果单电芯最小电压小于2.9v,并且容量大于10%,需要校准到10% */
-			if (ocv_force_capaticy++ >= 10) {
-				return _soc_force_capaticy(10);
-			}
-		}else {
-			ocv_force_capaticy = 0;
-		}
-#endif		
-	}
-	if (chargering || prev_charge_status) {
-		//ocv_force_capaticy = 0;
-		/*
-		if (bms_state_get()->ps_charger_mask && !bms_state_get()->ps_charger_in) { //ps100 上报无充电器,不做处理
-			ocv_full_count = 0;
-			return changed;
-		}*/
-		if (bms_health()->sigle_cell_over_voltage) { //单电芯过压强制充满
-			_force_capacity_full();
-			ocv_full_count = 0;
-			return 1;
-		}
-		if (chargering && (_soc.capacity != 100)) {
-			if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING) && (measure_value()->load_current <= FULL_MIN_CURRENT)){
-				if (ocv_full_count++ >= 100) { //连续100次(小电流采集30ms一次,就是3s时间)电压和电流满足条件,强制充满
+		}	
+	}
+	if ((chargering || prev_charge_status) && (_soc.capacity != 100)) {
+		if (chargering) { 
+			if (bms_health()->sigle_cell_over_voltage) { //单电芯过压强制充满
+				_force_capacity_full();
+				push_event(Charger_Full, bms_state_get()->pack_voltage);
+				ocv_full_count = 0;
+				changed = 1;
+			}else if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING)){
+				if (ocv_full_count++ >= CELLS_NUM) { //连续100次(电流采集25(小于4A)或者5ms一次)电压和电流满足条件,强制充满
 					_force_capacity_full();
+					push_event(Charger_Full, bms_state_get()->pack_voltage);
 					ocv_full_count = 0;
 					changed = 1;
 				}
+			}else if (bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) {
+				_force_capacity_full();
+				push_event(Charger_Full, bms_state_get()->pack_voltage);
+				ocv_full_count = 0;
+				changed = 1;
 			}else {
 				ocv_full_count = 0;
 			}
-		}else if (!chargering && prev_charge_status && (_soc.capacity != 100)){
-			if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) && (((_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min)) >= 0.998f)){//充电容量几乎接近最大容量
+		} else if (prev_charge_status){
+			if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_STOP_CHARGING) && _is_normal_charging()){//充电容量几乎接近最大容量
 				_force_capacity_full();
+				push_event(Charger_Full, 1);
 				changed = 1;
 			}
 		}
@@ -347,22 +459,37 @@ int soc_update_by_ocv(void){
 
 
 static void soc_calibrate(uint8_t prev_charge_status){
-	static int cali_full_count = 0;
 	if (!(_soc.flags & SOC_FLAG_CALIBRATED)){
 		if (chargering){//用ocv进行严格校准
 			if (_soc.capacity != 100){
-				if ((measure_value()->load_current <= FULL_MIN_CURRENT) && (bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_CHARGING)){
-					cali_full_count ++;
-				}
-				if (cali_full_count == 10 || bms_health()->sigle_cell_over_voltage) {
-					soc_debug("calibrate Capacity to 100, measure_value()->load_current %d\n", measure_value()->load_current);
-					_force_capacity_full();
+				if (!bms_work_is_normal()) {
+					if ((bms_state_get()->pack_voltage >= AGINT_TEST_MAX_VOLTAGE_CHARGING)){
+						_force_capacity_full();
+						push_event(Charger_Full, 12);
+					}else if (bms_health()->sigle_cell_over_voltage) {
+						_force_capacity_full();
+						push_event(Charger_Full, 13);
+					}
+				}else {
+					if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_CHARGING)){
+						_force_capacity_full();
+						push_event(Charger_Full, 10);
+					}else if (bms_health()->sigle_cell_over_voltage) {
+						_force_capacity_full();
+						push_event(Charger_Full, 1);
+					}
 				}
 			}
 		}else if (prev_charge_status){
-			if((_soc.capacity != 100) && ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) || bms_health()->sigle_cell_over_voltage)){
+			if((_soc.capacity != 100) && ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_STOP_CHARGING) || bms_health()->sigle_cell_over_voltage)){
 				soc_debug("calibrate Capacity to 100\n");
 				_force_capacity_full();
+				push_event(Charger_Full, 2);
+			}
+		}else {
+			if (_soc.capacity && _soc_is_under_voltage()) {
+				 _soc.coulomb_now = _soc.coulomb_min = 0;
+				_soc.capacity = 0;
 			}
 		}
 	}
@@ -393,15 +520,31 @@ uint32_t soc_get_cycle(void){
 	return _soc.total_coulomb/MAX_HA/2;
 }
 
+uint8_t soc_get_soh(void){
+	return (_soc.coulomb_max - _soc.coulomb_min)/_soc.coulomb_max * 100;
+}
+
 uint32_t soc_get_charger_remain_time(void){
 	return charger_remain_time;
 }
 
+//not energy recovery when riding
+int soc_is_normal_charging(void) {
+	return _is_normal_charging();
+}
+
 static void soc_update_by_current_and_time(float current_now, float delta_time, uint8_t prev_charge_status){
 	double current = current_now / 1000.0f; //A
 	double delta_q = current * delta_time; 
 	uint8_t est_capaticy = _soc.capacity;
 	int update_capticy = 0;
+	uint8_t prev_cap = _soc.capacity;
+
+	if (!chargering) {
+		soc_update_discharger_coeff();
+		delta_q = delta_q * _discharger_coefficient;
+	}
+	
 	double est_coulomb = _soc.coulomb_now + delta_q;//计算当前容量,充电加, 放电减
 
 	if (est_coulomb < 0){
@@ -409,18 +552,34 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
 	}else if (est_coulomb > _soc.coulomb_max) {
 		est_coulomb = _soc.coulomb_max;
 	}
-	est_capaticy = ((est_coulomb - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
-	
+	if (est_coulomb >= _soc.coulomb_min) {
+		est_capaticy = ((est_coulomb - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
+	}
 	if (chargering){
 		delta_q = delta_q * _charger_coefficient;
+		_soc.current_real_coulomb += abs(delta_q);
+		if (_soc.current_real_coulomb > _soc.coulomb_max) {
+			_soc.current_real_coulomb = _soc.coulomb_max;
+		}
 		_soc.charger_coulomb += abs(delta_q);
 		if ((est_capaticy < 100) && (est_capaticy >= _soc.capacity)){ //充电,容量不能等于100,需要靠电压和充电电流来矫正到100
 			update_capticy = 1;
 		}
 	}else {
-		soc_update_discharger_coeff();
-		delta_q = delta_q * _discharger_coefficient;
+		if (_soc.capacity > 20) {
+			small_20_dischr = 0;
+		}else {
+			small_20_dischr += abs(delta_q);
+		}
 		_soc.dischrger_coulomb += abs(delta_q);
+		_soc.current_real_coulomb -= abs(delta_q) / _discharger_no_full_coef;
+		if (_soc.current_real_coulomb < 0) {
+			_soc.current_real_coulomb = 0;
+		}	
+
+		if (est_coulomb < _soc.coulomb_min) {
+			_soc.coulomb_min = est_coulomb;
+		}
 		if ((est_capaticy > 0) && (est_capaticy <= _soc.capacity)) {  //放电,容量不能等于0,需要靠欠压或者PowerDown 矫正到0
 			update_capticy = 1;
 		}
@@ -438,24 +597,14 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
 	soc_calibrate(prev_charge_status);
 
 	//如果没有校准过,充电过程中,电量100%后,设置校准标志位
-	if (chargering && (_soc.capacity == 100)){
-		_soc.coulomb_now = _soc.coulomb_max;//充满后,当前容量设置为最大容量
+	if ((_soc.capacity == 100) && (prev_cap < 100)){
 		if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
 			_soc.flags |= SOC_FLAG_CALIBRATED;
 			update_capticy = 1;
 			soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
-		}else { //如果校准过,单电芯过压,100%的容量,设置最大容量为当前容量
-			if (bms_health()->sigle_cell_over_voltage){
-#if 0	/* 暂时去掉,最大容量不变化,只校准欠压后的可放电的最小容量 */			
-				if ((_soc.coulomb_now >= DEFALUT_MIN_COULOMB) && (_soc.coulomb_now <= DEFALUT_MAX_COULOMB)) {
-					_soc.coulomb_max = _soc.coulomb_now;
-					soc_warning("signal cell over vol, cap full, reset coul max to coul now: %f\n", _soc.coulomb_max);
-				}
-#endif 				
-			}
 		}
 	}
-	_soc.energy = bms_state_get()->pack_voltage/1000.f * (_soc.coulomb_now - _soc.coulomb_min);
+
 	if (update_capticy) {
 		nv_save_soc();
 	}
@@ -464,7 +613,7 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
 
 /*休眠bms功耗 + 电芯自放电 28天 3% (28天1AH)*/
 void soc_update_for_deepsleep(float sleep_time){
-	soc_update_by_current_and_time(-(0.32f + 1000.0f/(24.f * 28.f)), sleep_time, 0); //休眠功耗310uA(300uA + 10uA固定消耗)
+	soc_update_by_current_and_time(-(0.50f + 1000.0f/(24.f * 28.f)), sleep_time, 0); //休眠功耗310uA(300uA + 10uA固定消耗)
 	current_sample_ts = shark_get_mseconds(); //唤醒后复位采集时间,如果不采集会重复计算
 }
 
@@ -474,7 +623,7 @@ void soc_update(void){
 		_soc.pre_charger_coulomb = _soc.charger_coulomb;
 		_soc.charger_coulomb = 0;//clear charing
 		_soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
-		chargering = 1;
+		chargering = 1;	
 #if LEAST_SQUARE==1		
 		start_least_square(0);
 #endif
@@ -485,6 +634,12 @@ void soc_update(void){
 		_soc.total_coulomb += _soc.pre_discharger_coulomb / 3600.0f;
 		chargering = 0;
 		charger_remain_time = 0;
+		small_20_dischr = 0;
+		if (_is_normal_charging() && (_soc.capacity != 100)) {
+			u32 charger_cap_x10 = (u32)(_soc.charger_coulomb / 3600.0f * 10);
+			u32 cur_cap_x10 = (u32)(_soc.coulomb_now / 3600.0f * 10);
+			push_event(Charger_no_full_capaticy, ((cur_cap_x10 & 0xFFFF) << 16) | (charger_cap_x10 & 0xFFFF));
+		}
 		soc_warning("changed to dischargering, current = %d\n", measure_value()->load_current);
 	}
 #if LEAST_SQUARE==1	

+ 14 - 3
Application/app/sox/soc.h

@@ -2,15 +2,19 @@
 #include "libs/shark_libs.h"
 #include "bsp/shark_bsp.h"
 
-#define SOC_FLAG_CALIBRATED 1 //已经校准
+#define SOC_CURRENT_VERSION 1
+#define SOC_FLAG_VERSON_MASK (0x0E)
+#define SOC_FLAG_CALIBRATED (0x1 << 0) //已经校准
+#define SOC_FLAG_VERSION(v) (((v)<<1)& SOC_FLAG_VERSON_MASK)
+#define SOC_FLAG_TO_VER(f) (((f) & SOC_FLAG_VERSON_MASK) >> 1)
 typedef struct {
 	uint8_t flags; //比如是否校准等
 	double coulomb_now; /*AH, 若导线中载有1安培的稳定电流,则在1秒内通过导线横截面积的电量为1库仑 */
 	uint8_t capacity;  /* 电池的容量百分比 */
 	double coulomb_min;
 	double coulomb_max;
-	double power; //功率,当前的电压 x 当前的电流(w)
-	double energy; //当前的能量(wh)
+	double charger_cmin; //充电计算的最小容量
+	double current_real_coulomb; //当前的能量(wh)
 	double charger_coulomb; //本次充电的AH
 	double dischrger_coulomb; //本次放电的AH
 
@@ -24,9 +28,16 @@ void soc_init(void);
 void soc_update(void);
 int soc_update_by_ocv(void);
 uint32_t soc_get_cycle(void);
+uint8_t soc_get_soh(void);
 uint32_t soc_get_charger_remain_time(void);
 soc_t *get_soc(void);
 void soc_log(void);
 void soc_update_for_deepsleep(float sleep_time);
 void soc_restore_by_iap(uint8_t flags, uint8_t capaticy);
+u8 soc_get_version(void);
+void soc_set_version(u8 version);
+bool soc_is_force_full(void);
+void soc_clear_calibrate(int keep_cycle);
+int soc_is_normal_charging(void);
+
 

+ 321 - 80
Application/app/sox/state.c

@@ -1,8 +1,10 @@
+#include <string.h>
 #include "bsp/gpio.h"
 #include "bsp/ml5238.h"
 #include "bsp/cs1180.h"
 #include "bsp/uart.h"
 #include "bsp/mcu_power_sleep.h"
+#include "bsp/cht8305.h"
 #include "app/sox/measure.h"
 #include "app/sox/measure_task.h"
 #include "libs/shark_task.h"
@@ -12,6 +14,7 @@
 #include "soc.h"
 #include "state.h"
 #include "iostate.h"
+#include "event_record.h"
 
 #define ALLOW_DEEP_SLEEP 1
 #define SLEEP_IGNORE_UNHEALTH 0
@@ -26,7 +29,8 @@ static void _temperature_notify(void);
 static u32 _bms_main_task_handler(void);
 static void _debug_timer_handler(shark_timer_t *t);
 static void _process_power_down(void);
-static uint8_t calc_cell_voltage(void);
+static void calc_cell_voltage(void);
+static int _can_close_mos_no_hall(void);
 
 static bms_state_t _bms_state;
 static int pcb_temp = 100;
@@ -38,10 +42,30 @@ static int open_dfet = 0;
 static int open_dfet_failt = 0;
 static int close_dfet_reson = 0;
 static int close_dfet_no_hall = 0;
+static int no_hall_time[5];
+static int no_hall_count = 0;
+u64 uart_frame_time = 0;
+static u32 uart_reinit_count = 0;
+static void put_no_hall_time(void){
+	no_hall_time[no_hall_count] = shark_get_seconds();
+	no_hall_count = (no_hall_count + 1) % 5;
+}
+
+static void log_no_hall_time(void){
+	state_debug("current time %d\n", shark_get_seconds());
+	for (int i = 0; i < 5; i++){
+		state_debug("no hall time[%d]:%d\n", i, no_hall_time[i]);
+	}
+}
+
 void bms_state_init(void){
 	set_log_level(MOD_STATE, L_debug);
-	state_debug("BMS System Starting......\n");	
+	state_debug("BMS System Starting......\n");
+#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)
+	cht8305_reset();
+#endif
 	_bms_state.cell_index_of_max_vol = 0xff;
+	_bms_state.cell_index_of_min_vol = 0xff;
 	_bms_state.bms_addr = 0x30;
 	measure_task_init(_current_notify, _voltage_notify, _temperature_notify);
 	io_state_init();
@@ -54,6 +78,8 @@ void bms_state_init(void){
 
 	pcb_temp = measure_value()->pack_temp[PCB_TEMP_INDEX];
 
+	uart_frame_time = shark_get_mseconds();
+
 	set_log_all(L_disable);
 }
 
@@ -103,13 +129,16 @@ int bms_is_ps_charger_in(void){
 	return _bms_state.ps_charger_mask && _bms_state.ps_charger_in;
 }
 void bms_state_log(void){
+	soc_log();
 	state_debug("Life Time: %d\n", shark_get_seconds());
 	state_debug("Sleep Time: %ds\n", get_system_sleep_time());
 	state_debug("ml5238 cali: %d\n", ml5238_cali_count);
-	state_debug("ps charger mask:in %d, %d\n", _bms_state.ps_charger_mask, _bms_state.ps_charger_in);
-	state_debug("open dfet %d - %d - %d - %d\n", open_dfet, open_dfet_failt, close_dfet_reson, close_dfet_no_hall);
+	state_debug("open dfet %d - %d - 0x%x - %d\n", open_dfet, open_dfet_failt, close_dfet_reson, close_dfet_no_hall);
 	state_debug("Reset Reson 0x%x\n", bsp_get_rst_reson());
 	state_debug("BackUp value 0x%x\n", bsp_get_backup());
+	state_debug("Debug: %d, %d. uart reinit=%d\n", shark_uart_timeout(), io_state()->hall_detect, uart_reinit_count);
+	log_no_hall_time();
+	nv_storage_log();
 #if 0
 	state_debug("Charging: %d\n", _bms_state.charging);
 	state_debug("WorkMode %d\n", _bms_state.work_mode);
@@ -175,7 +204,13 @@ void discharger_open(int open){
 
 
 void charger_open(int open) {
-	ml5238_enable_charger_mosfet(open);
+	int retry = 10;
+	while( open != ml5238_is_charging()) {
+		ml5238_enable_charger_mosfet(open);
+		if (retry-- <= 0) {
+			break;
+		}
+	}
 }
 
 
@@ -202,28 +237,20 @@ static s32 _process_unheath(void){
 	u32 unhealth = Health_Success;
 	if (bms_health()->load_current_short) {//短路检测后,关闭充放电mos
 		discharger_open(0);
+		push_event_persit(Discharger_Operate_Off, 5);
 		charger_open(0); //disable charger mosfet
 		start_aux_power(0);
 		_bms_state.charging = 0;
 		close_dfet_reson = 2;
 		unhealth = (Health_Discharger_Failt | Health_charger_Fault);
 	}
-	if (!bms_work_is_normal()){
-		return unhealth; //测试模式只关注短路保护
-	}
 	if (bms_health()->charger_over_current || bms_health()->charger_over_temp || bms_health()->charger_lower_temp ||
 				bms_health()->charger_over_voltage || bms_health()->sigle_cell_over_voltage){
-		if (_bms_state.ps_charger_mask && !_bms_state.ps_charger_in){
-
-		}else {
-			charger_open(0); //disable charger mosfet
-			unhealth |= Health_charger_Fault;
-		}
+		charger_open(0); //disable charger mosfet
+		unhealth |= Health_charger_Fault;
 	}
 	if (bms_health()->over_temp_deny_charger|| bms_health()->lower_temp_deny_charger) {
-		if (_bms_state.ps_charger_mask && !_bms_state.ps_charger_in){
-
-		}else if (_bms_state.charging) {
+		if (_bms_state.charging) {
 			charger_open(0); //disable charger mosfet
 			unhealth |= Health_charger_Fault;
 		}
@@ -234,6 +261,7 @@ static s32 _process_unheath(void){
 			unhealth |= Health_aux_Fault;
 		}
 		discharger_open(0); //disable charger mosfet
+		push_event_persit(Discharger_Operate_Off, 4);
 		close_dfet_reson = (bms_health()->discharger_over_temp == 1)?3:4;
 		unhealth |= Health_Discharger_Failt;
 	}
@@ -246,6 +274,7 @@ static s32 _process_unheath(void){
 			start_aux_power(0);
 			if (ml5238_is_discharging()) {
 				close_dfet_reson = (bms_health()->sigle_cell_lower_voltage == 1) ?5:6;
+				push_event_persit(Discharger_Operate_Off, 3);
 				discharger_open(0);
 			}
 		}
@@ -254,23 +283,28 @@ static s32 _process_unheath(void){
 	if (bms_health()->over_temp_deny_discharger|| bms_health()->lower_temp_deny_discharger) {
 		if (!_bms_state.charging) {
 			close_dfet_reson = (bms_health()->over_temp_deny_discharger == 1)?7:8;
+			push_event_persit(Discharger_Operate_Off, 2);
 			discharger_open(0); //disable discharger mosfet
 		}
 		unhealth |= (Health_Discharger_Failt | Health_Fault_Can_Sleep);		
 	}
-	if (io_state()->aux_lock_detect || bms_health()->small_current_short) {
+	if (bms_health()->small_current_real_short) {
 		unhealth |= Health_aux_Fault;
 		if (bms_health()->small_current_real_short) {
 			unhealth |= Health_Discharger_Failt;
 		}
 	}
-	
+	if (soc_is_force_full()) {
+		charger_open(0); //disable charger mosfet
+		unhealth |= (Health_charger_Fault |Health_Fault_Can_Sleep);
+	}
 	return unhealth;
 }
 
 
 //处理PS100/310/320/360,充电底座,充电柜的指令或者bms自己发给自己的指令
 static void _process_user_request(s32 health){
+	bool mos_drv = false;
 	if (_bms_state.user_request & USER_REQUEST_PENDING){
 		//开关小电
 		if (_bms_state.user_request & USER_REQUEST_SMALLCURRENT_OFF){
@@ -278,6 +312,8 @@ static void _process_user_request(s32 health){
 		}
 		if (_bms_state.user_request & USER_REQUEST_DISCHARGER_OFF){
 			discharger_open(0);
+			push_event_persit(Discharger_Operate_Off, 1);
+			close_dfet_reson |= (3 << 24);
 		}
 		if (_bms_state.user_request & USER_REQUEST_CHARGER_OFF){
 			charger_open(0);
@@ -290,17 +326,31 @@ static void _process_user_request(s32 health){
 		}
 		if (_bms_state.user_request & USER_REQUEST_CHARGER_ON){
 			if (!(health & Health_charger_Fault)){
-				charger_open(1);
+				if ((io_state()->hall_detect) || !_can_close_mos_no_hall()){
+					charger_open(1);
+					mos_drv = true;
+				}
 			}
 		}
 		if (_bms_state.user_request & USER_REQUEST_DISCHARGER_ON) {
 			open_dfet ++;
 			if (!(health & Health_Discharger_Failt)){
-				discharger_open(1);
+				if ((io_state()->hall_detect || _bms_state.charging) || !_can_close_mos_no_hall()){
+					push_event_persit(Discharger_Operate_On, 10);
+					discharger_open(1);
+					mos_drv = true;
+				}else {
+					push_event_persit(Discharger_Operate_On, 20);
+				}
 			}else {
+				push_event_persit(Discharger_Operate_On, 30);
 				open_dfet_failt ++;
 			}
 		}
+		if (mos_drv && ml5238_is_mosdrv_strong()) {
+			task_udelay(3000);
+			ml5238_disable_mosdrv();
+		}
 		_bms_state.user_request &= ~USER_REQUEST_PENDING;//clear user request pending
 	}
 }
@@ -308,6 +358,9 @@ static void _process_user_request(s32 health){
 static void _process_power_down(void){
 #if (ALLOW_POWER_DOWN==1)	
 	if (bms_health()->powerdown_lower_voltage){
+		if (bms_work_is_normal() && (shark_get_seconds() < bms_health()->pd_time + 5)) {//超过5s powerdown
+			return;
+		}
 		state_debug("BMS System PowerDown!!\n");
 
 		if (bms_work_is_normal() && soc_update_by_ocv()) {
@@ -361,7 +414,8 @@ static void _process_deepsleep(s32 health){
 	if (!bms_work_is_normal()){
 		return; //测试模式下不休眠
 	}
-	if (ml5238_is_charging() || ml5238_is_discharging() || io_state()->charger_detect_irq || _bms_state.charging){
+	if (ml5238_is_charging() || ml5238_is_discharging() || io_state()->charger_detect_irq || _bms_state.charging || 
+		_bms_state.pack_balancing){
 		return;
 	}
 
@@ -379,11 +433,13 @@ static void _process_deepsleep(s32 health){
 	if (shark_get_mseconds() < (_sleep_time + 3 * 1000)){
 		return;
 	}
-	
+	printf("SYSTEM: enter sleep\n");
+	shark_uart_flush();
 	nv_save_all_soc();
 	mcu_enter_deepsleep();
 	soc_update_for_deepsleep(mcu_get_sleeptime());//补偿休眠的功耗
 	_sleep_time = shark_get_mseconds();
+	uart_frame_time = shark_get_mseconds();
 #endif	
 }
 
@@ -396,23 +452,30 @@ static int _can_close_mos_no_hall(void){
 }
 
 static void _process_iostate_changed(s32 unhealth){
-	if (!(io_state()->hall_detect)&& _can_close_mos_no_hall()){
+	if (!(io_state()->hall_detect)){
 		bms_set_ps_charger_in(0, 0);
-		if (ml5238_is_discharging() && (!_bms_state.charging)){
-			discharger_open(0);
-			close_dfet_no_hall ++;
-			open_dfet = open_dfet_failt = 0; //clear open dfet count
+		if (bms_work_is_aging_test()) {
+			bms_work_mode_set(WORK_MODE_AGING_TEST, 0);//close aging test mode
 		}
-		if (!AUX_VOL_IS_OPEN() && !bms_health()->load_current_short && !io_state()->aux_lock_detect && !bms_health()->small_current_short){
-			start_aux_power(1);
-		}
-		if (!io_state()->charger_detect_irq && ml5238_is_charging() && (!_bms_state.charging)){
-			charger_open(0);
+		if (_can_close_mos_no_hall()) {
+			if (ml5238_is_discharging() && (!_bms_state.charging)){
+				push_event_persit(Discharger_Operate_Off, 256);
+				discharger_open(0);
+				put_no_hall_time();
+				close_dfet_no_hall ++;
+				open_dfet = open_dfet_failt = 0; //clear open dfet count
+			}
+			if (!AUX_VOL_IS_OPEN() && !bms_health()->load_current_short && !io_state()->aux_lock_detect && !bms_health()->small_current_short){
+				start_aux_power(1);
+			}
+			if (!io_state()->charger_detect_irq && ml5238_is_charging() && (!_bms_state.charging)){
+				charger_open(0);
+			}
 		}
 	}
 	if (io_state()->charger_detect_irq && ((unhealth & Health_charger_Fault) == 0) && (_bms_state.cell_max_vol < SIGLE_CELL_MAX_CHARGER_VOLTAGE)) {
 		if (!ml5238_is_charging() && shark_uart_timeout()){//不在车上,底座上,充电柜上,检测到充电器插入,自动打开充电,否则的话,只能通过指令来打开充电mos
-			if (!(bms_health()->over_temp_deny_charger|| bms_health()->lower_temp_deny_charger)) {
+			if (!(bms_health()->over_temp_deny_charger|| bms_health()->lower_temp_deny_charger)&& (get_soc()->capacity < 100)) {
 				charger_open(1);
 			}
 		}
@@ -426,34 +489,58 @@ static void _process_iostate_changed(s32 unhealth){
 	}
 }
 
+static void _bms_uart_workaround(void) {
+	if (io_state()->hall_detect != 1){
+		return;
+	}
+	if (shark_get_mseconds() >= (uart_frame_time + 3000)){
+		UART0_IR_EN(0);
+		UART1_IR_EN(0);
+		task_udelay(50 * 1000);
+		UART0_IR_EN(1);
+		UART1_IR_EN(1);
+		uart_reinit_count++;
+		uart_frame_time = shark_get_mseconds();
+	}
+}
+
 static u32 _bms_main_task_handler(void){
 	s32 unhealth = _process_unheath();
 	_process_user_request(unhealth);
 	_process_deepsleep(unhealth);
 	_process_power_down();
 	_process_iostate_changed(unhealth);
+	_bms_uart_workaround();
 	return 0;
 }
 
 extern void show_leds_for_charging(uint8_t charging);
 static debounce_t _charging_detect = {.count = 0, .max_count = 10, .init_count = 0};
 static int cs1180_may_error_count = 0;
+static bool _cs1180_may_error(void) {
+	//cs1180 not working
+	if (measure_value()->load_current == measure_value()->current_5238) {
+		return false;
+	}
+	//cs1180检测到充电电流,5238检测到负电流
+	if ((measure_value()->load_current >= MIN_START_CHARGER_CURRENT) && (measure_value()->current_5238 <= 0)) {
+		return true;
+	}
+	//cs1180 和 5238的测量电流差超过阈值
+	if (abs(measure_value()->load_current - measure_value()->current_5238) >= MIN_DIFF_BT_5238_1180) {
+		return true;
+	}
+	return false;
+}
 static void check_charging(){
 	/* 解决cs1180可能出错,导致误判充电,离仓后无法休眠 */
-	int may_error = 0;
-	if (measure_value()->load_current >= MIN_START_CHARGER_CURRENT) {
-		if (measure_value()->load_current != measure_value()->current_5238) {
-			if (measure_value()->current_5238 <= 0) { //cs1180检测到充电电流,5238检测到负电流
-				if (++cs1180_may_error_count >= _charging_detect.max_count/2) {
-					measure_value()->load_current = measure_value()->current_5238;
-					cs1180_adc_shutdown();
-					cs1180_may_error_count = 0;
-				}
-				may_error = 1;
-			}
+	if (_cs1180_may_error()) {
+		if (++cs1180_may_error_count >= _charging_detect.max_count/2) {
+			measure_value()->load_current = measure_value()->current_5238;
+			cs1180_adc_shutdown();
+			cs1180_may_error_count = 0;
 		}
-	}
-	if (may_error == 0) {
+	}else {
 		cs1180_may_error_count = 0;
 	}
 	if ((measure_value()->load_current >= MIN_START_CHARGER_CURRENT)) {
@@ -489,9 +576,12 @@ static void check_charging(){
 static int _min_current_for_both_mos_count = 0;
 static u32 _check_mos_time = 0;
 static __INLINE u32 _open_all_mos_time(void){
-	if (abs(measure_value()->load_current) >= MIN_CURRENT_FOR_BOTH_MOS_OPEN * 2){
+	if (abs(measure_value()->load_current) >= MIN_CURRENT_FOR_BOTH_MOS_OPEN * 11){
 		return 0;
 	}
+	if (abs(measure_value()->load_current) >= MIN_CURRENT_FOR_BOTH_MOS_OPEN * 6) {
+		return 5;
+	}	
 	if (abs(measure_value()->load_current) >= MIN_CURRENT_FOR_BOTH_MOS_OPEN) {
 		return 10;
 	}
@@ -505,9 +595,11 @@ static void _check_mos_stat(void){
 			int cmos = ml5238_is_charging();
 			if (dmos + cmos == 0){
 				//state_error("current = %d, but all mos is closed\n", measure_value()->load_current);
+				_check_mos_time = shark_get_seconds();
 				return;
 			}
 			if (dmos == 1 && cmos == 1){
+				_check_mos_time = shark_get_seconds();
 				return;
 			}
 			if (shark_get_seconds() >= (_check_mos_time + _open_all_mos_time())) {
@@ -523,10 +615,16 @@ static void _check_mos_stat(void){
 		}
 	}else {
 		_min_current_for_both_mos_count = 0;
+		_check_mos_time = shark_get_seconds();
 	}
 }
-
+#if (ALLOW_5238_BALANCE==1)
+static bool check_stop_balance(void) ;
+#endif
 static void _current_notify(void){
+#if (ALLOW_5238_BALANCE==1)
+	check_stop_balance();
+#endif
 	check_charging();
 	check_current_state(); //check health of current
 	_check_mos_stat();
@@ -540,52 +638,166 @@ static void _current_notify(void){
  * 木桶效应,目标是电压最高的那个cell,尽量压制,不让电压再升高,或者升高的尽量慢一些
 */
 static void _balance_timer_handler(shark_timer_t *t);
-
 static shark_timer_t _balance_timer = {.handler = _balance_timer_handler};
+static void _start_balance(uint16_t mask) {
+	int success = ml5238_cell_start_balance(mask);
+	if (success ) {
+		if (mask == 0) {
+			_bms_state.pack_balancing = 0;
+		}else {
+			_bms_state.pack_balancing = 1;
+		}
+	}
+}
 
-static debounce_t _cell_balance = {.count = 0, .max_count = 10, .init_count = 0};
+static void _stop_balance(void) {
+	_start_balance(0);
+}
 
 static void _balance_timer_handler(shark_timer_t *t){
-	ml5238_cell_start_balance(0);
-	_bms_state.pack_balancing = 0;
+	_stop_balance();
+	if (_bms_state.pack_balancing) {
+		shark_timer_post(&_balance_timer, 1);
+	}
 }
 
-static uint32_t get_balance_mask(uint8_t current_max_index){
-	return BIT(current_max_index);
-}
 
-static void check_cell_balance(uint8_t current_max_index){
-	if (!_bms_state.charging){ //not charging, need not do balance
-		if (_bms_state.pack_balancing){
-			_bms_state.pack_balancing = 0;
-			_cell_balance.count = 10;
-			ml5238_cell_start_balance(0);
-			shark_timer_cancel(&_balance_timer);
+static u16 _search_direct(u16 *delta_v, u8 current_cell, u8 *depth, u8 dir) {
+	u16 delta_next, delta_prev;
+	u8  idx_prev, idx_next;
+	u8  balance_idx = 255;
+
+	for (int i = 0; i < CELLS_NUM/2 + 1; i++) {
+		*depth ++;
+		//get the delta v of the prev and current
+		if (current_cell == 0) {
+			idx_prev = CELLS_NUM - 1;
+		}else {
+			idx_prev = current_cell - 1;
+		}
+		delta_prev = delta_v[idx_prev];
+
+		//get the delta v of the next and current
+#if 0
+		if (current_cell == CELLS_NUM - 1) {
+			idx_next = 0;
+		}else {
+			idx_next = current_cell + 1;
+		}
+#endif
+		idx_next = current_cell;
+		delta_next = delta_v[idx_next];
+
+		//use the max delta v of the prev and next
+		if (delta_prev >= delta_next) {
+			if(delta_prev >= MAX_DIFF_BETWEEN_MIN_MAX_CELL){
+				balance_idx = idx_prev; //balance with prev cell
+				break;
+			}
+		}else {
+			if(delta_next >= MAX_DIFF_BETWEEN_MIN_MAX_CELL){
+				balance_idx = idx_next; //balance with next cell
+				break;
+			}
+		}
+		if (dir == 1) {//search forword
+			current_cell = (current_cell + 1) % CELLS_NUM;
+		}else {        //search backwork
+			if (current_cell == 0) {
+				current_cell = CELLS_NUM - 1;
+			}else {
+				current_cell -= 1;
+			}
 		}
-		return;
 	}
-	if ((!_bms_state.pack_balancing && _bms_state.cell_max_vol < MAX_CELL_VOLTAGE_FOR_BALACNE) || _bms_state.pack_balancing){
+	return balance_idx;
+}
+static u32 get_balance_maskV2(void) {
+	u16 delta_v[CELLS_NUM];
+	u16 *pcellv = measure_value()->cell_vol;
+
+	//calc the delta v of the Neighboring cells
+	delta_v[CELLS_NUM - 1] = abs(pcellv[CELLS_NUM-1] - pcellv[0]);
+	for (int i = 0; i < CELLS_NUM - 1; i++) {
+		delta_v[i] = abs(pcellv[i] - pcellv[i + 1]);
+	}
+	u8 depth_next = 0, depth_prev = 0;
+	u8 idx_next = _search_direct(delta_v, _bms_state.cell_index_of_max_vol, &depth_next, 1);// search from max to next....
+	u8 idx_prev = _search_direct(delta_v, _bms_state.cell_index_of_max_vol, &depth_prev, 0);// search from max to prev
+	//chose the min depth whitch near from max voltage cell
+	if (depth_next < depth_prev) {
+		return BIT(idx_next);
+	}else if (depth_prev < depth_next) {
+		return BIT(idx_prev);
+	}else {
+		if (idx_next < CELLS_NUM) {
+			return BIT(idx_next);
+		}
+		if (idx_prev < CELLS_NUM) {
+			return BIT(idx_prev);
+		}
+	}
+	return 0;
+}
+
+#define BALANCE_TIME (10 * 60) //S
+static u8 g_is_charging = 0;
+static u8 can_do_balance(void) {
+	u8 balance = 0;
+	//when stop normal(not energy recovery) charging, need check balance
+	if (g_is_charging && (!_bms_state.charging && soc_is_normal_charging())) {
+		balance = 1;
+	}
+	g_is_charging = _bms_state.charging;
+	//if already balancing, do nothing
+	if (_bms_state.pack_balancing) {
+		balance = 0;
+	}
+
+	return balance;
+}
+
+static u8 need_stop_balance(void) {
+	if (measure_value()->load_current < -100.0 || g_is_charging) {
+		return 1;
+	}
+	return 0;
+}
+
+static void check_cell_balance(void){
+	if (check_stop_balance()) {
 		return;
 	}
-	if (_bms_state.cell_max_vol >= MAX_CELL_VOLTAGE_FOR_BALACNE){
-		debounce_inc(_cell_balance);
-	}else {
-		debounce_reset(_cell_balance);
+	u16 mask = get_balance_maskV2();
+	if (mask) {
+		push_event(Cell_balance, mask);
+		_start_balance(mask);
+		shark_timer_post(&_balance_timer, BALANCE_TIME * 1000); //stop balance after BALANCE_TIME
 	}
-	if (!_bms_state.pack_balancing && debounce_reach_max(_cell_balance)){
-		_bms_state.pack_balancing = 1;
-		ml5238_cell_start_balance(get_balance_mask(current_max_index));
-		shark_timer_post(&_balance_timer, 30 * 1000); //stop balance after 30s
-		debounce_reset(_cell_balance);
+	state_debug("Cell balance mask 0x%x\n", mask);
+}
+
+static bool check_stop_balance(void) {
+	if (!can_do_balance()) {
+		if (need_stop_balance()) {
+			if (_bms_state.pack_balancing){
+				_stop_balance();
+				push_event(Cell_balance, 0);
+				shark_timer_cancel(&_balance_timer);
+			}
+		}
+		return true;
 	}
-	_bms_state.cell_index_of_max_vol = current_max_index;	
+	return false;
 }
+
 #endif
-static uint8_t calc_cell_voltage(void){
+static void calc_cell_voltage(void){
 	uint16_t voltage = 0;
 	uint16_t max_cell = 0;
 	uint16_t min_cell = 0xf000;
 	uint8_t max_index = 0;
+	uint8_t min_index = 0;
 	for (int i = 0; i < CELLS_NUM; i++){
 		voltage += measure_value()->cell_vol[i];
 		if (max_cell < measure_value()->cell_vol[i]){
@@ -594,23 +806,26 @@ static uint8_t calc_cell_voltage(void){
 		}
 		if (min_cell > measure_value()->cell_vol[i]){
 			min_cell = measure_value()->cell_vol[i];
+			min_index = i;
 		}		
 	}
 	_bms_state.pack_voltage = voltage;
 	_bms_state.cell_max_vol = max_cell;
-	_bms_state.cell_min_vol = min_cell;	
-	return max_index;
+	_bms_state.cell_min_vol = min_cell;
+	_bms_state.cell_index_of_min_vol = min_index;
+	_bms_state.cell_index_of_max_vol = max_index;	
 }
 
 static void _voltage_notify(void){
-	uint8_t max_index = calc_cell_voltage();
+	calc_cell_voltage();
 	check_voltage_state(); //check health of cell voltage
 #if (ALLOW_5238_BALANCE==1)
-	check_cell_balance(max_index);
+	check_cell_balance();
 #endif
 }
 
 static void _temperature_notify(void){
+	static uint8_t _bms_aging_test = 0;
 	int pcb_current_temp = measure_value()->pack_temp[PCB_TEMP_INDEX];
 	if (abs(pcb_temp - pcb_current_temp) >= 5){//pcb温度变化超过5度,需要重新校准ML5238
 		if (pcb_temp_count ++ >= 5) {
@@ -624,5 +839,31 @@ static void _temperature_notify(void){
 		pcb_temp_count = 0;
 	}
 	check_temp_state(); //check health of cell/pcb temperature
+	if (bms_work_is_aging_test()) {
+		if (abs(measure_value()->load_current) >= 2000) {
+			if (_bms_aging_test == 0) {
+				memcpy(_bms_state.aging_start_temp, measure_value()->pack_temp, PACK_TEMPS_NUM * sizeof(int));
+				memcpy(_bms_state.aging_max_temp, measure_value()->pack_temp, PACK_TEMPS_NUM * sizeof(int));
+				_bms_state.aging_real_start = 0;
+				_bms_state.agint_cost_time = 0;
+				_bms_aging_test = 1;
+			}
+			if (_bms_state.aging_real_start == 0) {
+				_bms_state.aging_real_start = shark_get_seconds();
+			}
+			for (int i = 0; i < PACK_TEMPS_NUM; i++) {
+				if (_bms_state.aging_max_temp[i] < measure_value()->pack_temp[i]) {
+					_bms_state.aging_max_temp[i] = measure_value()->pack_temp[i];
+				}
+			}
+		}else {
+			if(_bms_state.aging_real_start > 0){
+				_bms_state.agint_cost_time += (shark_get_seconds() - _bms_state.aging_real_start);
+				_bms_state.aging_real_start = 0;
+			}
+		}
+	}else {
+		_bms_aging_test = 0;
+	}
 }
 

+ 8 - 2
Application/app/sox/state.h

@@ -14,11 +14,12 @@
 #define BATT_USED_BY_CHARGER_DOCKER 2
 #define HATT_USED_BY_CHARGER_BOX 3
 
+#define MIN_DIFF_BT_5238_1180     500
 #define MIN_START_CHARGER_CURRENT 300 //ma, 如果有正向超过 MIN_START_CHARGER_CURRENT的电流,认为在充电
 #define MIN_START_LOADING_CURRENT 5  //ma, 如果有反向小于 MIN_START_LOADING_CURRENT的电流,认为在放电
-#define MAX_DIFF_BETWEEN_MIN_MAX_CELL 150 //0.15v ,压差超过这个值,开始balance
+#define MAX_DIFF_BETWEEN_MIN_MAX_CELL 100 //0.15v ,压差超过这个值,开始balance
 #define MIN_DIFF_BETWEEN_MIN_MAX_CELL 050 //0.05v, 牙差低于这个数据,停止balance
-#define MAX_CELL_VOLTAGE_FOR_BALACNE 3650
+#define MAX_CELL_VOLTAGE_FOR_BALACNE 3600
 #define CELL_FUSION_VOLTAGE      3500 //LFP电池在3.5v的时候,开始发散,需要判断是否要balance
 
 
@@ -31,10 +32,15 @@ typedef struct{
 	uint16_t cell_max_vol;
 	uint16_t cell_min_vol;
 	uint8_t  cell_index_of_max_vol;
+	uint8_t  cell_index_of_min_vol;
 	int      used_by;//where this battery is used for: on motor, on charger docker, on charger box, NONE
 	uint32_t user_request;
 	uint32_t work_mode;//正常模式,老化测试模式,pcba测试模测试,整机测试模式
 	uint8_t  bms_addr;
+	int      aging_start_temp[PACK_TEMPS_NUM];
+	int      aging_max_temp[PACK_TEMPS_NUM];
+	uint32_t aging_real_start;
+	uint32_t agint_cost_time;
 }bms_state_t;
 
 #define WORK_MODE_NORMAL 0      //正常模式

+ 11 - 1
Application/bsp/AT24CXX.c

@@ -1,5 +1,6 @@
 #include "i2c.h"
 #include "AT24CXX.h"
+#include "clock.h"
 
 void AT24CXX_Init(void)
 {
@@ -45,6 +46,11 @@ int AT24CXX_Read(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)
 		if (try_count-- <= 0){
 			return -1;
 		}
+		if ((try_count % 20) == 0) {
+			AT24CXX_DeInit();
+			task_udelay(1000);
+			AT24CXX_Init();
+		}
 	};
 	return NumToRead;
 }  
@@ -57,7 +63,11 @@ static int AT24CXX_Write_Pages(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumT
 		if (try_count-- <= 0){
 			return -1;
 		}
-
+		if ((try_count % 20) == 0) {
+			AT24CXX_DeInit();
+			task_udelay(1000);
+			AT24CXX_Init();
+		}
 	};
 	return 0;
 }

+ 19 - 1
Application/bsp/bsp.c

@@ -5,12 +5,18 @@
 #include "bsp/shark_rtc.h"
 #include "bsp/clock.h"
 #include "bsp/fmc_flash.h"
+#include "bsp/cht8305.h"
 #include "libs/logger.h"
+#include "libs/shark_task.h"
 #include "version.h"
 #include <string.h>
 
 #if defined CONFIG_BOARD_SP700
+#ifdef SP710_V2
+const char iap_board_name[] __attribute__((at(0x08002800))) = "SP710";
+#else
 const char iap_board_name[] __attribute__((at(0x08002800))) = "SP700";
+#endif
 #elif defined CONFIG_BOARD_SP600
 const char iap_board_name[] __attribute__((at(0x08002800))) = "SP600";
 #endif
@@ -20,6 +26,8 @@ const char iap_fw_name[] __attribute__((at(0x08002C00))) = "App";
 extern void system_clock_config(void);
 extern void SystemCoreClockUpdate(void);
 extern void gpio_key_init(void);
+static void dianostic_timer_handler(shark_timer_t *timer);
+static shark_timer_t _dianostic_stop_timer = {.handler = dianostic_timer_handler};
 
 #ifndef CONFIG_DEBUG
 #define CONFIG_DEBUG 0
@@ -36,18 +44,28 @@ void bsp_init(void){
 	system_clock_config(); //after dcdc open, MCU can run on full speed
 	SystemCoreClockUpdate();
 	rcu_all_reset_flag_clear();
+	task_ticks_enable();
 	gpio_init();
 	set_log_level(MOD_SYSTEM, L_debug);
 	shark_uart_init(SHARK_UART0);
-#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)	
+#if UART_NUM==2
 	shark_uart_init(SHARK_UART1);
 #endif
 	AT24CXX_Init();
+#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)
+	cht8305_init();
+#endif
 	AUX_VOL_OPEN(0);
 	gpio_key_init();
+	DIANOCTIC_LED(1);
+	shark_timer_post(&_dianostic_stop_timer, 5000);
 	RTC_BKP0 = 0;
 }
 
+static void dianostic_timer_handler(shark_timer_t *timer) {
+	DIANOCTIC_LED(0);
+}
+
 uint32_t bsp_get_rst_reson(void){
 	return reset_source;
 }

+ 71 - 0
Application/bsp/cht8305.c

@@ -0,0 +1,71 @@
+#include "cht8305.h"
+#include "libs/shark_task.h"
+#include "libs/logger.h"
+static int i2c_read(u8 reg, u16 *data);
+static int i2c_write(u8 reg, u16 data);
+
+static bool _ready = false;
+static int _init_count = 0;
+void cht8305_init(void) {
+	u16 data;
+	if (i2c_read(ID_Reg, &data) == 2) {
+		if (data == CHT8305_ID) {
+			if (i2c_write(Config_Reg, 0x1000) >= 0) {
+				_ready = true;
+			}
+		}
+	}
+}
+
+bool cht8305_ready(void) {
+	return _ready;
+}
+
+void cht8305_reset(void) {
+	if (_ready) {
+		state_debug("cht8305 ready\n");
+	}else {
+		state_debug("cht8305 not ready reinit\n");
+		cht8305_init();
+	}
+	if (_ready) {
+		u16 data = 0x8000; //reset
+		i2c_write(Config_Reg, data);
+		i2c_read(Config_Reg, &data);
+		state_debug("data = 0x%x\n", data);	
+	}
+}
+
+u8 cht8305_get_humidity(void){
+	if (!_ready) {
+		_init_count ++;
+		if (_init_count <= 20) {
+			cht8305_init();
+		}
+		return 0xFF;
+	}
+	u16 data = 0;
+	if (i2c_read(Humi_Reg, &data) == 2) {
+		u32 data32 = data << 10;
+		u32 humidity = 100 * data32/((1<<16) - 1) >> 10;
+		return (u8) humidity;
+	}
+	return 0xFF;
+}
+
+
+static int i2c_read(u8 reg, u16 *data) {
+	u8 reg_value[2] = {0x00, 0x00};
+	int ret = gd32_i2c_read_nbytes(0, CHT8305_I2C_ADDR, reg, reg_value, 2);
+	if (ret == 2) {
+		*data = ((reg_value[0] << 8)&0xFF00) | reg_value[1];
+	}
+	return ret;
+}
+
+static int i2c_write(u8 reg, u16 data) {
+	u8 reg_value[2];
+	reg_value[0] = (data>>8) & 0xFF;
+	reg_value[1] = data & 0xFF;
+	return gd32_i2c_write_nbytes(0, CHT8305_I2C_ADDR, reg, reg_value, 2);
+}

+ 22 - 0
Application/bsp/cht8305.h

@@ -0,0 +1,22 @@
+#ifndef _CHT8305_H__
+#define _CHT8305_H__
+
+#include "bsp/shark_bsp.h"
+#include "bsp/i2c.h"
+#include "libs/shark_types.h"
+
+#define CHT8305_I2C_ADDR 0x80
+
+#define Temp_Reg 0x00
+#define Humi_Reg 0x01
+#define Config_Reg 0x02
+#define ID_Reg 0xFE
+
+#define CHT8305_ID 0x5959
+
+void cht8305_init(void);
+void cht8305_reset(void);
+bool cht8305_ready(void);
+u8 cht8305_get_humidity(void);
+
+#endif /* _CHT8305_H__ */

+ 44 - 2
Application/bsp/clock.c

@@ -2,11 +2,53 @@
 #include "gd32f3x0.h"
 
 extern uint32_t SystemCoreClock;
+static u8 delay_ticks_enable = 0;
 void delay_us(uint32_t us){
-	uint32_t insr_num = (SystemCoreClock /40000000 + 1) * us;// 1000000;
-	while(insr_num-->0);
+	if (delay_ticks_enable) {
+		task_udelay(us);
+		return;
+	}
+	uint32_t insr_num = (SystemCoreClock /1000000) * us * 4;// 1000000;
+	while(insr_num-->0); //have 4 instr
+}
+
+void task_ticks_enable(void)
+{
+	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
+	delay_ticks_enable = 1;
+}
+
+u32 task_ticks_abs(void)
+{
+	return DWT->CYCCNT;
+}
+
+u32 task_ticks_rel(u32 start)
+{
+	u32 ticks = DWT->CYCCNT;
+
+	if (ticks >= start) {
+		return ticks - start;
+	}
+
+	return 0xFFFFFFFF - start + ticks + 1;
+}
+
+void task_ticks_delay(u32 ticks)
+{
+	u32 start;
+
+	start = task_ticks_abs();
+	while (task_ticks_rel(start) < ticks);
+}
+
+void task_udelay(u32 delay)
+{
+	task_ticks_delay(delay * (SystemCoreClock / 1000000));
 }
 
+
 uint32_t get_sys_clock(void){
 	return SystemCoreClock;
 }

+ 4 - 2
Application/bsp/clock.h

@@ -1,7 +1,9 @@
 #ifndef _CLOCK_H__
 #define _CLOCK_H__
-#include <stdint.h>
-void delay_us(uint32_t us);
+#include "libs/shark_types.h"
+void delay_us(u32 us);
+void task_ticks_enable(void);
+void task_udelay(u32 delay); /* 精确延时, 必须在bsp_init后才能使用 */
 uint32_t get_sys_clock(void);
 uint32_t get_ahb_clock(void);
 uint32_t get_apb1_clock(void);

+ 1 - 27
Application/bsp/cs1180.c

@@ -372,32 +372,6 @@ float cs1180_adc_sample(int *valide)
 		cs1180_ready_error ++;
 		return 0.0f;
 	}
-#if 0
-	int retry = 5;
-	while(retry-- >= 0) {
-		cs1180_cs(0);
-		cs1180_send_cmd(CS1180_RDATA);
-		delay_us(60);
-		data[0] = cs1180_read_data(0xFF);
-		data[1] = cs1180_read_data(0xFF);
-		data[2] = cs1180_read_data(0xFF);
-		cs1180_cs(1);
-		a = (data[0] << 16) | (data[1] << 8) | data[2];
-		a >>= 4;
-		if (a != 0xFFFFF){//spi 上拉,所以如果读到的数据全F,说明可能cs1180没有数据输出,通过判断ready来确定是否要重读
-			break;
-		}
-		delay_us(100);
-		if (IS_CS1180_NOT_READY()){
-			break;
-		}
-		sys_warning("cs1180 read adc retry!!!!\n");
-	}
-	if ((a == 0xFFFFF) && !IS_CS1180_NOT_READY() && (valide != NULL)){
-		sys_error("cs1180 adc is not valide\n");
-		*valide = 0;
-	}
-#endif
 
 	cs1180_cs(0);
 	cs1180_send_cmd(CS1180_RDATA);
@@ -430,7 +404,7 @@ float cs1180_adc_sample(int *valide)
 	}else {
 		a = a&0x7FFFF;
 	}
-	return (int)(((float)a / _cs1180_gain));
+	return (((float)a / _cs1180_gain));
 }
 
 

+ 12 - 3
Application/bsp/gpio.c

@@ -1,9 +1,16 @@
 #include "gpio.h"
 /* all pins used as gpio(input/output/irq) must be defined here */
 void gpio_init(void){
-	rcu_periph_clock_enable(RCU_GPIOB);
-	rcu_periph_clock_enable(RCU_GPIOC);
-	rcu_periph_clock_enable(RCU_GPIOF);
+	rcu_periph_clock_enable(RCU_GPIOA); 
+	rcu_periph_clock_enable(RCU_GPIOB); 
+	rcu_periph_clock_enable(RCU_GPIOC); 
+	rcu_periph_clock_enable(RCU_GPIOD); 
+	rcu_periph_clock_enable(RCU_GPIOF);  
+	//GPIO_CTL(GPIOA) = 0xFFFFFFFF; 
+	GPIO_CTL(GPIOB) = 0xFFFFFFFF; 
+	GPIO_CTL(GPIOC) = 0xFFFFFFFF; 
+	GPIO_CTL(GPIOD) = 0xFFFFFFFF; 
+	GPIO_CTL(GPIOF) = 0xFFFFFFFF;
 
 #if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)	
 	//hall 2 detect
@@ -26,6 +33,8 @@ void gpio_init(void){
     //老的sp700+cs1180上,GPIOA8和GPIOB15连在一起,为了不影响B15 pin的spi 功能,A8pin需要设置为输入
 	gpio_mode_analog_input(GPIOA, GPIO_PIN_8);
 #endif
+    //disnoctic led
+	gpio_mode_output(GPIOF, GPIO_PUPD_PULLUP, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_6);
 #elif (CONFIG_BOARD_TYPE==SHARK_BOARD_SP600)
 	//key
 	gpio_mode_input(GPIOA, GPIO_PUPD_NONE, GPIO_PIN_0);

+ 2 - 0
Application/bsp/gpio.h

@@ -39,6 +39,7 @@ void gpio_init(void);
 /*detect hall 1&2 */
 #define IS_HALL1_DETECTED() (!gpio_input_bit_get(GPIOC, GPIO_PIN_15))
 #define IS_HALL2_DETECTED() (!gpio_input_bit_get(GPIOC, GPIO_PIN_13))
+#define DIANOCTIC_LED(s) gpio_bit_write(GPIOF,GPIO_PIN_6,(s == 0)?SET:RESET)
 
 #define LED0_ON(x) {}
 #define LED1_ON(x) {}
@@ -70,6 +71,7 @@ void gpio_init(void);
 
 #define UART0_IR_EN(x) RS485_PWR_ENABLE(x)
 #define UART1_IR_EN(x) {}
+#define DIANOCTIC_LED(s) {}
 #endif
 
 #define LED_ALL_ON(x) {LED0_ON(x); LED1_ON(x); LED2_ON(x); LED3_ON(x); LED4_ON(x);}

+ 3 - 3
Application/bsp/i2c.c

@@ -62,7 +62,7 @@ static void gd32_i2c_busy_recovery(uint32_t i2c_periph){
 
 void gd32_i2c_init(uint32_t i2c_device, uint32_t rate){
 	uint32_t device = iic_device(i2c_device);
-
+	i2c_clk[i2c_device] = rate;
 	rcu_periph_clock_enable(RCU_GPIOB);
 	if (device == I2C0) {
 		rcu_periph_clock_enable(RCU_I2C0);
@@ -70,14 +70,14 @@ void gd32_i2c_init(uint32_t i2c_device, uint32_t rate){
 		_i2c_deinit(I2C0);
 		gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_8|GPIO_PIN_9);
 		gpio_mode_af(GPIOB ,GPIO_PUPD_PULLUP, GPIO_PIN_8|GPIO_PIN_9);
-		//gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8|GPIO_PIN_9);
+		gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,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_PULLUP, GPIO_PIN_10|GPIO_PIN_11);
-		//gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_10|GPIO_PIN_11);
+		gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_10|GPIO_PIN_11);
 	}
 	i2c_clock_config(device, rate, I2C_DTCY_2);
 	i2c_enable(device);

+ 10 - 1
Application/bsp/mcu_power_sleep.c

@@ -7,6 +7,7 @@
 #include "bsp/i2c.h"
 #include "bsp/shark_rtc.h"
 #include "bsp/AT24CXX.h"
+#include "bsp/cht8305.h"
 #include "app/sox/iostate.h"
 #include "bsp/gd32_adc.h"
 
@@ -32,7 +33,7 @@ uint32_t get_system_sleep_time(void){
 static int enable_wakeup_irq(void){
 	//hall_1_detect_irq_enable(1);
 	//hall_2_detect_irq_enable(1);
-	return shark_rtc_start_alarm(RTC_ALARM_FOR_SLEEP);
+	return shark_rtc_start_alarm(2);
 }
 
 static void disable_wakeup_irq(void){
@@ -61,6 +62,8 @@ static void wait_dcdc_good(void) {
 }
 static int pre_deepsleep(void){
 	LED_ALL_ON(0);
+	DIANOCTIC_LED(0);
+	_wakeup_source = 0;
 	systick_close();
 	shark_rtc_set_backup(0xF0);
 	shark_uart_deinit(SHARK_UART0);
@@ -124,6 +127,9 @@ static void post_deepsleep(void){
 	shark_uart_init(SHARK_UART1);
 #endif
 	AT24CXX_Init();
+#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP700)
+	cht8305_reset();
+#endif
 	shark_rtc_set_backup(0xFB);
 	wdog_set_timeout(4);
 	shark_rtc_set_backup(0xFC);
@@ -156,6 +162,9 @@ void mcu_enter_deepsleep(void){
 		}else { //rtc second wrap
 			_sleep_second_time_now += 60 - start_time + end_time;
 		}
+		if (IS_HALL1_DETECTED()|| IS_HALL2_DETECTED()) {
+			mcu_sleep_set_wakeup_source(WAKEUP_SOURCE_HALL1);
+		}
 		if (_wakeup_source & WAKEUP_SOURCE_RTC) {
 			wdog_reload();
 			shark_rtc_set_backup(0xFF2);

+ 42 - 1
Application/bsp/ml5238.c

@@ -134,9 +134,18 @@ int ml5238_is_discharging(void){
 	return _discharger_mosfet_is_open();
 }
 
-void ml5238_cell_start_balance(uint16_t balance_mask){
+int ml5238_cell_start_balance(uint16_t balance_mask){
 	ml5238_write(ML5238_CBALH, (balance_mask >> 8) & 0xFF);
 	ml5238_write(ML5238_CBALL, balance_mask & 0xFF);
+	uint8_t datah = 0xFF;
+	uint8_t datal = 0xFF;
+	if ((ml5238_read(ML5238_CBALH, &datah) == 0) && (ml5238_read(ML5238_CBALL, &datal) == 0)) {
+		if ((datah == ((balance_mask >> 8) & 0xFF)) && (datal == (balance_mask & 0xFF))) {
+			return 1;
+		}
+	}
+
+	return 0;
 }
 
 
@@ -180,6 +189,32 @@ int ml5238_enable_charger_mosfet(int enable){
 	return -1;
 }
 
+int ml5238_enable_all_mosfet(int enable) {
+	if (enable) {
+		return ml5238_write(ML5238_FET, (FET_CF | FET_DF | FET_DRV));
+	}else {
+		return ml5238_write(ML5238_FET, 0);
+	}
+}
+
+int ml5238_disable_mosdrv(void){
+	
+	uint8_t data;
+	if ((ml5238_read(ML5238_FET, &data) == 0) && (data & FET_DRV)){
+		data &= ~FET_DRV;
+		return ml5238_write(ML5238_FET, data);
+	}
+	return -1;
+}
+
+int ml5238_is_mosdrv_strong(void){
+	
+	uint8_t data = 0xFF;
+	if ((ml5238_read(ML5238_FET, &data) == 0) && (data & FET_DRV)){
+		return 1;
+	}
+	return -1;
+}
 
 int ml5238_short_current_detect(int mode){
 	uint8_t rsense = 0;
@@ -316,15 +351,21 @@ static void ml5238_clear_bits(uint8_t regaddr, uint8_t bit) {
 int ml5238_write(uint8_t regaddr, uint8_t data){
 	uint16_t send_data=(((uint16_t)regaddr)<<(0x09))|((uint16_t)data);
 	ml5238_cs(0);
+	task_udelay(1); //min 100ns
 	int ret = spi0_send_uint16(send_data, NULL);
+	task_udelay(1);
 	ml5238_cs(1);
+	task_udelay(1);
 	return ret;
 }
 
 static int ml5238_read(uint8_t regaddr, uint8_t *data){
 	uint16_t send_data=((((uint16_t)regaddr)<<(0x09))|0x0100u)|((uint16_t)0x00u);
 	ml5238_cs(0);
+	task_udelay(1);
 	int ret = spi0_send_uint16(send_data, data);
+	task_udelay(1);
 	ml5238_cs(1);
+	task_udelay(1);
 	return ret;
 }

+ 4 - 2
Application/bsp/ml5238.h

@@ -8,7 +8,7 @@ int ml5238_enable_charger_mosfet(int enable);
 int ml5238_short_current_detect(int mode);
 int ml5238_is_load_disconnect(void);
 int ml5238_enable_load_detect(int enable);
-void ml5238_cell_start_balance(uint16_t balance_mask);
+int ml5238_cell_start_balance(uint16_t balance_mask);
 void ml5238_power_down(void);
 void ml5238_power_save(int save);
 int ml5238_charger_is_disconnect(int small_current_on);
@@ -19,7 +19,9 @@ int ml5238_is_short_current_enabled(int mode);
 uint8_t ml5238_noop_register_rw(uint8_t data);//ml5238 ¶Áд²âÊÔ
 void ml5238_reg_log(void);
 uint8_t ml5238_read_imon(void);
-
+int ml5238_enable_all_mosfet(int enable);
+int ml5238_disable_mosdrv(void);
+int ml5238_is_mosdrv_strong(void);
 
 typedef void (*ml5238_notify_hander)(int event);
 void ml5238_register_notify_handler(ml5238_notify_hander handler);

+ 112 - 11
Application/bsp/uart.c

@@ -1,7 +1,10 @@
 #include "uart.h"
 #include "bsp/shark_bsp.h"
 #include "bsp/gpio.h"
+#include "bsp/clock.h"
 #include "libs/shark_libs.h"
+#include "libs/shark_task.h"
+#include "libs/logger.h"
 
 #define SHARK_UART_BAUDRATE				38400
 
@@ -38,17 +41,33 @@
 #define SHARK_UART1_rx_dma_clk			RCU_DMA
 
 // ================================================================================
+#define ENABLE_RX_DMA 1
 
 static u8 shark_uart0_tx_cache[SHARK_UART_TX_MEM_SIZE];
 #if UART_NUM==2
 static u8 shark_uart1_tx_cache[SHARK_UART_TX_MEM_SIZE];
 #endif
-static u8 shark_uart_rx_cache[SHARK_UART_RX_MEM_SIZE];
+
+static u8 shark_uart0_rx_cache[SHARK_UART_RX_MEM_SIZE];
+#if UART_NUM==2
+static u8 shark_uart1_rx_cache[SHARK_UART_RX_MEM_SIZE];
+#endif
+
 static shark_uart_t _shark_uart[UART_NUM];
 static shark_task_t _uart_task;
 static u64 _rx_time;
+u32 uart_rx_bytes = 0;
+u32 uart_old_prot = 0;
+u32 uart_new_prot = 0;
+u32 uart_tx_bytes = 0;
+static u32 uart_run_times[2];
+static u32 uart_irq_times[2];
 ///static bool uart_no_data = false;
+#if ENABLE_RX_DMA==1
 #define update_dma_w_pos(uart) circle_update_write_position(&uart->rx_queue, SHARK_UART_RX_MEM_SIZE - DMA_CHCNT(uart->rx_dma_ch))
+#else
+#define update_dma_w_pos(uart){}
+#endif
 extern void protocol_recv_frame(uart_enum_t uart_no, char *data, int len);
 extern void protocol_old_recv_frame(uart_enum_t uart_no, uint8_t *data, int len);
 extern void health_add_uart_error(uint32_t c, uint32_t l, uint32_t d);
@@ -65,6 +84,10 @@ static bool shark_uart_on_rx_frame(shark_uart_t *uart)
 		health_add_uart_error(1, 0, 0);
 		return false;
 	}
+#if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP600)
+    //wait 250us to give the time for PS200 485 switch to rx mode
+	task_udelay(250);
+#endif
 	protocol_recv_frame(_uart_index(uart->uart_com), (char *)uart->rx_frame, uart->rx_length);
 	return true;
 }
@@ -72,6 +95,7 @@ static bool shark_uart_on_rx_frame(shark_uart_t *uart)
 static void shark_uart_rx(shark_uart_t *uart){
 	while(1) {
 		u8 data;
+		uart_run_times[_uart_index(uart->uart_com)] ++;
 		update_dma_w_pos(uart);
 		if (circle_get_one_data(&uart->rx_queue, &data) != 1) {
 			if (shark_get_mseconds() >= (5 + _rx_time)) {
@@ -90,6 +114,7 @@ static void shark_uart_rx(shark_uart_t *uart){
 			}
 			break;
 		}
+		uart_rx_bytes ++;
 		_rx_time = shark_get_mseconds();
 		uart->rx_frame_old_prot[uart->rx_length_old_prot ++] = data;
 		if (uart->rx_length_old_prot == sizeof(uart->rx_frame_old_prot)){
@@ -110,7 +135,7 @@ static void shark_uart_rx(shark_uart_t *uart){
 				}
 				uart->rx_length = 0xFFFF;
 				uart->start = false;
-				break;
+				return;
 			case CH_ESC:
 				uart->escape = true;
 				break;
@@ -159,6 +184,7 @@ static void shark_uart_dma_tx(shark_uart_t *uart)
 		}
 
 		byte_queue_skip(&uart->tx_queue, uart->tx_length);
+		dma_flag_clear(uart->tx_dma_ch, DMA_FLAG_FTF);
 		DMA_CHCTL(uart->tx_dma_ch) = value & (~DMA_CHXCTL_CHEN);
 	}
 
@@ -166,8 +192,6 @@ static void shark_uart_dma_tx(shark_uart_t *uart)
 	if (uart->tx_length > 0) {
 		DMA_CHCNT(uart->tx_dma_ch) = uart->tx_length;
 		DMA_CHMADDR(uart->tx_dma_ch) = (u32) byte_queue_head(&uart->tx_queue);
-
-		dma_flag_clear(uart->tx_dma_ch, DMA_FLAG_FTF);
 		DMA_CHCTL(uart->tx_dma_ch) = value | DMA_CHXCTL_CHEN;
 	}
 }
@@ -176,6 +200,7 @@ static void shark_uart_dma_tx(shark_uart_t *uart)
 
 static void shark_uart_write(shark_uart_t *uart, const u8 *buff, u16 size)
 {
+	uart_tx_bytes += size;
 	while (size > 0) {
 		u16 length = byte_queue_write(&uart->tx_queue, buff, size);
 
@@ -192,7 +217,11 @@ static void shark_uart_write(shark_uart_t *uart, const u8 *buff, u16 size)
 
 static void shark_uart_write_byte(shark_uart_t *uart, u8 value)
 {
-	shark_uart_write(uart, &value, 1);
+	//shark_uart_write(uart, &value, 1);
+	byte_queue_write(&uart->tx_queue, &value, 1);
+	if (byte_queue_get_used(&uart->tx_queue) > 64) {
+		shark_uart_dma_tx(uart);
+	}
 }
 
 
@@ -221,7 +250,7 @@ static void shark_uart_tx_dma_init(shark_uart_t *uart){
 #endif
 }
 
-
+#if ENABLE_RX_DMA==1
 static void shark_uart_rx_dma_init(shark_uart_t *uart){
 	dma_parameter_struct dma_init_struct;
 	rcu_periph_clock_enable(_uart_index(uart->uart_com)== SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk);
@@ -241,7 +270,7 @@ static void shark_uart_rx_dma_init(shark_uart_t *uart){
 	dma_channel_enable(uart->rx_dma_ch);
 	usart_dma_receive_config(uart->uart_com, USART_DENR_ENABLE);
 }
-
+#endif
 static void shark_uart_pin_init(shark_uart_t *uart){
 	if (_uart_index(uart->uart_com) == SHARK_UART0) {
 		rcu_periph_clock_enable(SHARK_UART0_clk);
@@ -288,7 +317,15 @@ static void shark_uart_device_init(shark_uart_t *uart){
 	usart_hardware_flow_cts_config(uart->uart_com, USART_CTS_DISABLE);
 	usart_receive_config(uart->uart_com, USART_RECEIVE_ENABLE);
 	usart_transmit_config(uart->uart_com, USART_TRANSMIT_ENABLE);
-	
+
+#if ENABLE_RX_DMA==0
+	usart_overrun_disable(uart->uart_com);//must add
+	usart_lin_mode_disable(uart->uart_com);
+	usart_receiver_timeout_disable(uart->uart_com);
+	usart_reception_error_dma_disable(uart->uart_com);
+
+	usart_interrupt_enable(uart->uart_com,USART_INT_RBNE);
+#endif
 }
 
 static u32 shark_uart_handler(void)
@@ -308,15 +345,35 @@ static u32 shark_uart_handler(void)
 	return 0;
 }
 
+void shark_uart_log(void){
+	shark_uart_t *uart = _shark_uart + SHARK_UART0;
+	sys_debug("Debug: %d, %d, %d, %d\n", uart_tx_bytes, uart_rx_bytes, uart_new_prot, uart_old_prot);
+	sys_debug("uart0: %d, %d, %d, %d, %d\n", uart_run_times[0], uart->rx_queue.r_pos, uart->rx_queue.w_pos, uart->rx_queue.buffer_len, uart_irq_times[0]);
+#if ENABLE_RX_DMA==1
+	sys_debug("dma0: %d\n", DMA_CHCNT(uart->rx_dma_ch));
+#endif
+#if UART_NUM==2
+	uart = _shark_uart + SHARK_UART1;
+	sys_debug("uart1: %d, %d, %d, %d, %d\n", uart_run_times[1], uart->rx_queue.r_pos, uart->rx_queue.w_pos, uart->rx_queue.buffer_len, uart_irq_times[1]);
+#if ENABLE_RX_DMA==1
+	sys_debug("dma1: %d\n", DMA_CHCNT(uart->rx_dma_ch));
+#endif
+#endif
+}
+
 void shark_uart_flush(void){
 	shark_uart_t *uart = _shark_uart + SHARK_UART0;
 	if (uart->uart_com != 0) {
-		shark_uart_dma_tx(uart);
+		while(!byte_queue_empty(&uart->tx_queue)) {
+			shark_uart_dma_tx(uart);
+		}
 	}
 #if UART_NUM==2	
 	uart = _shark_uart + SHARK_UART1;
 	if (uart->uart_com != 0) {
-		shark_uart_dma_tx(uart);
+		while(!byte_queue_empty(&uart->tx_queue)) {
+			shark_uart_dma_tx(uart);
+		}
 	}
 #endif	
 }
@@ -348,6 +405,15 @@ static u8 *tx_cache_addr(uart_enum_t uart_no){
 #endif
 }
 
+static u8 *rx_cache_addr(uart_enum_t uart_no){
+#if UART_NUM==2
+	return (uart_no == SHARK_UART0)?shark_uart0_rx_cache:shark_uart1_rx_cache;
+#else
+	return shark_uart0_rx_cache;
+#endif
+}
+
+
 void shark_uart_deinit(uart_enum_t uart_no){
 	shark_uart_t *uart = _shark_uart + uart_no;
 	if (uart->uart_com != 0) {
@@ -362,8 +428,14 @@ void shark_uart_deinit(uart_enum_t uart_no){
 	}
 	if (uart_no == SHARK_UART0) {
 		UART0_IR_EN(0);
+#if ENABLE_RX_DMA==0
+		nvic_irq_disable(USART0_IRQn);
+#endif
 	}else {
 		UART1_IR_EN(0);
+#if ENABLE_RX_DMA==0
+		nvic_irq_disable(USART1_IRQn);
+#endif
 	}
 }
 
@@ -383,7 +455,7 @@ void shark_uart_init(uart_enum_t uart_no)
 	uart->tx_length = 0;
 	uart->uart_com = (uart_no == SHARK_UART0)?SHARK_UART0_com:SHARK_UART1_com;
 
-	circle_buffer_init(&uart->rx_queue, shark_uart_rx_cache, SHARK_UART_TX_MEM_SIZE);
+	circle_buffer_init(&uart->rx_queue, rx_cache_addr(uart_no), SHARK_UART_RX_MEM_SIZE);
 	byte_queue_init(&uart->tx_queue,tx_cache_addr(uart_no), SHARK_UART_TX_MEM_SIZE);
 
 	uart->rx_dma_ch = (uart_no == SHARK_UART0)?SHARK_UART0_rx_dma_ch:SHARK_UART1_rx_dma_ch;
@@ -391,7 +463,9 @@ void shark_uart_init(uart_enum_t uart_no)
 
 	shark_uart_pin_init(uart);
 	shark_uart_device_init(uart);
+#if ENABLE_RX_DMA==1
 	shark_uart_rx_dma_init(uart);
+#endif
 	shark_uart_tx_dma_init(uart);
 	usart_enable(uart->uart_com);
 	
@@ -401,13 +475,39 @@ void shark_uart_init(uart_enum_t uart_no)
 	}
 	if (uart_no == SHARK_UART0) {
 		UART0_IR_EN(1);
+#if ENABLE_RX_DMA==0
+		nvic_irq_enable(USART0_IRQn, 3, 0);
+#endif
 	}else {
 		UART1_IR_EN(1);
+#if ENABLE_RX_DMA==0
+		nvic_irq_enable(USART1_IRQn, 3, 0);
+#endif
 	}
 	_rx_time = shark_get_mseconds();
 	uart->uart_no_data = false;
 }
 
+#if ENABLE_RX_DMA==0
+void USART0_IRQHandler(void){
+	if(usart_flag_get(USART0, USART_FLAG_RBNE) == SET){
+		shark_uart_t *uart = _shark_uart + SHARK_UART0;
+		uart_irq_times[0] ++;
+		u8 c = usart_data_receive(USART0);
+		circle_put_one_data(&uart->rx_queue, c);
+	}
+}
+
+void USART1_IRQHandler(void){
+	if(usart_flag_get(USART1, USART_FLAG_RBNE) == SET){
+		shark_uart_t *uart = _shark_uart + SHARK_UART1;
+		uart_irq_times[1] ++;
+		u8 c = usart_data_receive(USART1);
+		circle_put_one_data(&uart->rx_queue, c);
+	}
+}
+#endif
+
 static void shark_uart_write_byte_esc(shark_uart_t *uart, u8 value)
 {
 	switch (value) {
@@ -455,6 +555,7 @@ static void shark_uart_tx_end(shark_uart_t *uart)
 {
 	shark_uart_write_esc(uart, (u8 *)&uart->tx_crc16, sizeof(uart->tx_crc16));
 	shark_uart_write_byte(uart, CH_END);
+	shark_uart_dma_tx(uart);
 }
 
 void shark_uart_write_frame(uart_enum_t uart_no, uint8_t *bytes, int len){

+ 5 - 6
Application/bsp/uart.h

@@ -13,9 +13,11 @@
 
 #define SHARK_UART_TX_MEM_SIZE			512
 #define SHARK_UART_RX_MEM_SIZE			512
+#define RX_FRAME_MAX_LEN 260
+#define RX_OLD_FRAME_MAX_LEN 256
 
 typedef enum {
-	SHARK_UART0,
+	SHARK_UART0 = 0,
 	SHARK_UART1,
 	SHARK_UART2,
 	SHARK_UART3,
@@ -23,8 +25,6 @@ typedef enum {
 	SHARK_UART_COUNT
 } uart_enum_t;
 
-#define RX_FRAME_MAX_LEN 260
-
 typedef struct {
 	byte_queue_t tx_queue;
 	c_buffer_t rx_queue;
@@ -35,7 +35,7 @@ typedef struct {
 	uint32_t uart_com;//uart device
 	uint8_t rx_frame[RX_FRAME_MAX_LEN];
 	uint16_t rx_length;
-	uint8_t rx_frame_old_prot[256];
+	uint8_t rx_frame_old_prot[RX_OLD_FRAME_MAX_LEN];
 	uint16_t rx_length_old_prot;
 	bool escape;
 	bool start;
@@ -51,6 +51,5 @@ void shark_uart_frame_end(uart_enum_t uart_no);
 void shark_uart_write_bytes(uart_enum_t uart_no, u8 *buff, u16 size);
 void shark_uart_flush(void);
 bool shark_uart_timeout(void);
-
-
+void shark_uart_log(void);
 

+ 1 - 0
Application/libs/circle_buffer.c

@@ -8,6 +8,7 @@ static int circle_get_read_space(c_buffer_t *cbuff);
 void circle_buffer_init(c_buffer_t *cbuff, uint8_t *buffer, int16_t max_len){
 	cbuff->buffer = buffer;
 	cbuff->buffer_len = max_len;
+	circle_reset(cbuff);
 }
 
 void circle_reset(c_buffer_t *cbuff){

+ 7 - 1
Application/libs/circle_buffer.h

@@ -19,7 +19,13 @@ typedef struct {
 
 //used by dma
 static __inline__ void circle_update_write_position(c_buffer_t *cbuff, int pos){
-	cbuff->w_pos = pos;
+	if (pos != 0) {
+		if (pos == cbuff->buffer_len) {
+			cbuff->w_pos = 0;
+		}else {
+			cbuff->w_pos = pos;
+		}
+	}
 }
 
 static __inline__ int circle_get_read_position(c_buffer_t *cbuff){

+ 3 - 0
Application/libs/shark_task.h

@@ -21,3 +21,6 @@ void shark_timer_post(shark_timer_t *timer, u32 delay);
 void shark_timer_cancel(shark_timer_t *timer);
 void shark_task_add(shark_task_t *task);
 void shark_task_run(void);
+
+
+

+ 15 - 0
Application/libs/shark_utils.c

@@ -1,4 +1,6 @@
 #include "shark_utils.h"
+#include "bsp/shark_bsp.h"
+#include "string.h"
 
 const u16 shark_crc16_table[] = {
 	0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48, 0x9DC1,
@@ -117,3 +119,16 @@ void shark_encode_u32(u8 *buff, u32 value)
 	buff[3] = value >> 24;
 }
 
+u8 shark_read_chip_id(u8 *buff)
+{
+#ifdef GD32F3x0
+	u32 values[] = { REG32(0x1FFFF7AC), REG32(0x1FFFF7B0), REG32(0x1FFFF7B4), REG32(0x1FFFF7E0) };
+#else
+	u32 values[] = { REG32(0x1FFFF7E8), REG32(0x1FFFF7EC), REG32(0x1FFFF7F0), REG32(0x1FFFF7E0) };
+#endif
+
+	memcpy(buff, values, sizeof(values));
+
+	return sizeof(values);
+}
+

+ 1 - 0
Application/libs/shark_utils.h

@@ -20,6 +20,7 @@ u32 shark_decode_u32(const u8 *buff);
 void shark_encode_u16(u8 *buff, u16 value);
 void shark_encode_u24(u8 *buff, u32 value);
 void shark_encode_u32(u8 *buff, u32 value);
+u8 shark_read_chip_id(u8 *buff);
 u32 shark_iap_checksum_put(u32 crc, const u8 *buff, u32 length);
 u32 shark_iap_checksum_finish(u32 crc);
 u32 shark_iap_checksum_init(void);

+ 64 - 52
Project/SP600.uvoptx

@@ -308,6 +308,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>10</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\event_record.c</PathWithFileName>
+      <FilenameWithoutPath>event_record.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -318,7 +330,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>10</FileNumber>
+      <FileNumber>11</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -330,7 +342,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>11</FileNumber>
+      <FileNumber>12</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -342,7 +354,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>12</FileNumber>
+      <FileNumber>13</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -354,7 +366,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>13</FileNumber>
+      <FileNumber>14</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -366,7 +378,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>14</FileNumber>
+      <FileNumber>15</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -378,7 +390,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>15</FileNumber>
+      <FileNumber>16</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -390,7 +402,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>16</FileNumber>
+      <FileNumber>17</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -402,7 +414,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>17</FileNumber>
+      <FileNumber>18</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -422,7 +434,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>18</FileNumber>
+      <FileNumber>19</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -434,7 +446,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>19</FileNumber>
+      <FileNumber>20</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -446,7 +458,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>20</FileNumber>
+      <FileNumber>21</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -458,7 +470,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>21</FileNumber>
+      <FileNumber>22</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -470,7 +482,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>22</FileNumber>
+      <FileNumber>23</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -482,7 +494,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>23</FileNumber>
+      <FileNumber>24</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -494,7 +506,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>24</FileNumber>
+      <FileNumber>25</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -506,7 +518,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>25</FileNumber>
+      <FileNumber>26</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -518,7 +530,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>26</FileNumber>
+      <FileNumber>27</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -530,7 +542,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>27</FileNumber>
+      <FileNumber>28</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -542,7 +554,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>28</FileNumber>
+      <FileNumber>29</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -554,7 +566,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>29</FileNumber>
+      <FileNumber>30</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -566,7 +578,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>30</FileNumber>
+      <FileNumber>31</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -578,7 +590,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>31</FileNumber>
+      <FileNumber>32</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -598,7 +610,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>32</FileNumber>
+      <FileNumber>33</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -610,7 +622,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>33</FileNumber>
+      <FileNumber>34</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -622,7 +634,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>34</FileNumber>
+      <FileNumber>35</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -634,7 +646,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>35</FileNumber>
+      <FileNumber>36</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -646,7 +658,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>36</FileNumber>
+      <FileNumber>37</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -666,7 +678,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>37</FileNumber>
+      <FileNumber>38</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -678,7 +690,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>38</FileNumber>
+      <FileNumber>39</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -690,7 +702,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>39</FileNumber>
+      <FileNumber>40</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -702,7 +714,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>40</FileNumber>
+      <FileNumber>41</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -714,7 +726,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>41</FileNumber>
+      <FileNumber>42</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -726,7 +738,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>42</FileNumber>
+      <FileNumber>43</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -738,7 +750,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>43</FileNumber>
+      <FileNumber>44</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -750,7 +762,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>44</FileNumber>
+      <FileNumber>45</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -762,7 +774,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>45</FileNumber>
+      <FileNumber>46</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -774,7 +786,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>46</FileNumber>
+      <FileNumber>47</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -786,7 +798,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>47</FileNumber>
+      <FileNumber>48</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -798,7 +810,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>48</FileNumber>
+      <FileNumber>49</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -810,7 +822,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>49</FileNumber>
+      <FileNumber>50</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -822,7 +834,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>50</FileNumber>
+      <FileNumber>51</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -834,7 +846,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>51</FileNumber>
+      <FileNumber>52</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -846,7 +858,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>52</FileNumber>
+      <FileNumber>53</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -858,7 +870,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>53</FileNumber>
+      <FileNumber>54</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -870,7 +882,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>54</FileNumber>
+      <FileNumber>55</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -882,7 +894,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>55</FileNumber>
+      <FileNumber>56</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -894,7 +906,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>56</FileNumber>
+      <FileNumber>57</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -906,7 +918,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>57</FileNumber>
+      <FileNumber>58</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -918,7 +930,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>58</FileNumber>
+      <FileNumber>59</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -930,7 +942,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>59</FileNumber>
+      <FileNumber>60</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -950,7 +962,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>60</FileNumber>
+      <FileNumber>61</FileNumber>
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -962,7 +974,7 @@
     </File>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>61</FileNumber>
+      <FileNumber>62</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>

+ 5 - 0
Project/SP600.uvprojx

@@ -428,6 +428,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\app\key_leds.c</FilePath>
             </File>
+            <File>
+              <FileName>event_record.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\event_record.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>

+ 64 - 52
Project/SP600_15AH.uvoptx

@@ -283,6 +283,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>10</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\event_record.c</PathWithFileName>
+      <FilenameWithoutPath>event_record.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -293,7 +305,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>10</FileNumber>
+      <FileNumber>11</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -305,7 +317,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>11</FileNumber>
+      <FileNumber>12</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -317,7 +329,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>12</FileNumber>
+      <FileNumber>13</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -329,7 +341,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>13</FileNumber>
+      <FileNumber>14</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -341,7 +353,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>14</FileNumber>
+      <FileNumber>15</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -353,7 +365,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>15</FileNumber>
+      <FileNumber>16</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -365,7 +377,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>16</FileNumber>
+      <FileNumber>17</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -377,7 +389,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>17</FileNumber>
+      <FileNumber>18</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -397,7 +409,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>18</FileNumber>
+      <FileNumber>19</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -409,7 +421,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>19</FileNumber>
+      <FileNumber>20</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -421,7 +433,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>20</FileNumber>
+      <FileNumber>21</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -433,7 +445,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>21</FileNumber>
+      <FileNumber>22</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -445,7 +457,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>22</FileNumber>
+      <FileNumber>23</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -457,7 +469,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>23</FileNumber>
+      <FileNumber>24</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -469,7 +481,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>24</FileNumber>
+      <FileNumber>25</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -481,7 +493,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>25</FileNumber>
+      <FileNumber>26</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -493,7 +505,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>26</FileNumber>
+      <FileNumber>27</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -505,7 +517,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>27</FileNumber>
+      <FileNumber>28</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -517,7 +529,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>28</FileNumber>
+      <FileNumber>29</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -529,7 +541,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>29</FileNumber>
+      <FileNumber>30</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -541,7 +553,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>30</FileNumber>
+      <FileNumber>31</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -553,7 +565,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>31</FileNumber>
+      <FileNumber>32</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -573,7 +585,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>32</FileNumber>
+      <FileNumber>33</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -585,7 +597,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>33</FileNumber>
+      <FileNumber>34</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -597,7 +609,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>34</FileNumber>
+      <FileNumber>35</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -609,7 +621,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>35</FileNumber>
+      <FileNumber>36</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -621,7 +633,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>36</FileNumber>
+      <FileNumber>37</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -641,7 +653,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>37</FileNumber>
+      <FileNumber>38</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -653,7 +665,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>38</FileNumber>
+      <FileNumber>39</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -665,7 +677,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>39</FileNumber>
+      <FileNumber>40</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -677,7 +689,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>40</FileNumber>
+      <FileNumber>41</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -689,7 +701,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>41</FileNumber>
+      <FileNumber>42</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -701,7 +713,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>42</FileNumber>
+      <FileNumber>43</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -713,7 +725,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>43</FileNumber>
+      <FileNumber>44</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -725,7 +737,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>44</FileNumber>
+      <FileNumber>45</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -737,7 +749,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>45</FileNumber>
+      <FileNumber>46</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -749,7 +761,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>46</FileNumber>
+      <FileNumber>47</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -761,7 +773,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>47</FileNumber>
+      <FileNumber>48</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -773,7 +785,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>48</FileNumber>
+      <FileNumber>49</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -785,7 +797,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>49</FileNumber>
+      <FileNumber>50</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -797,7 +809,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>50</FileNumber>
+      <FileNumber>51</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -809,7 +821,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>51</FileNumber>
+      <FileNumber>52</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -821,7 +833,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>52</FileNumber>
+      <FileNumber>53</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -833,7 +845,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>53</FileNumber>
+      <FileNumber>54</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -845,7 +857,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>54</FileNumber>
+      <FileNumber>55</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -857,7 +869,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>55</FileNumber>
+      <FileNumber>56</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -869,7 +881,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>56</FileNumber>
+      <FileNumber>57</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -881,7 +893,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>57</FileNumber>
+      <FileNumber>58</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -893,7 +905,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>58</FileNumber>
+      <FileNumber>59</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -905,7 +917,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>59</FileNumber>
+      <FileNumber>60</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -925,7 +937,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>60</FileNumber>
+      <FileNumber>61</FileNumber>
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -937,7 +949,7 @@
     </File>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>61</FileNumber>
+      <FileNumber>62</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>

+ 5 - 0
Project/SP600_15AH.uvprojx

@@ -428,6 +428,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\app\key_leds.c</FilePath>
             </File>
+            <File>
+              <FileName>event_record.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\event_record.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>

+ 77 - 53
Project/SP700.uvoptx

@@ -140,7 +140,7 @@
         <SetRegEntry>
           <Number>0</Number>
           <Key>JL2CM3</Key>
-          <Name>-U20080643 -O78 -S2 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F3x0.FLM -FS08000000 -FL010000 -FP0($$Device:GD32F330C8$Flash\GD32F3x0.FLM)</Name>
+          <Name>-U81480416 -O78 -S2 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F3x0.FLM -FS08000000 -FL010000 -FP0($$Device:GD32F330C8$Flash\GD32F3x0.FLM)</Name>
         </SetRegEntry>
         <SetRegEntry>
           <Number>0</Number>
@@ -328,6 +328,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>10</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\event_record.c</PathWithFileName>
+      <FilenameWithoutPath>event_record.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -338,7 +350,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>10</FileNumber>
+      <FileNumber>11</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -350,7 +362,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>11</FileNumber>
+      <FileNumber>12</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -362,7 +374,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>12</FileNumber>
+      <FileNumber>13</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -374,7 +386,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>13</FileNumber>
+      <FileNumber>14</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -386,7 +398,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>14</FileNumber>
+      <FileNumber>15</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -398,7 +410,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>15</FileNumber>
+      <FileNumber>16</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -410,7 +422,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>16</FileNumber>
+      <FileNumber>17</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -422,7 +434,7 @@
     </File>
     <File>
       <GroupNumber>2</GroupNumber>
-      <FileNumber>17</FileNumber>
+      <FileNumber>18</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -442,7 +454,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>18</FileNumber>
+      <FileNumber>19</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -454,7 +466,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>19</FileNumber>
+      <FileNumber>20</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -466,7 +478,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>20</FileNumber>
+      <FileNumber>21</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -478,7 +490,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>21</FileNumber>
+      <FileNumber>22</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -490,7 +502,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>22</FileNumber>
+      <FileNumber>23</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -502,7 +514,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>23</FileNumber>
+      <FileNumber>24</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -514,7 +526,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>24</FileNumber>
+      <FileNumber>25</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -526,7 +538,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>25</FileNumber>
+      <FileNumber>26</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -538,7 +550,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>26</FileNumber>
+      <FileNumber>27</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -550,7 +562,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>27</FileNumber>
+      <FileNumber>28</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -562,7 +574,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>28</FileNumber>
+      <FileNumber>29</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -574,7 +586,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>29</FileNumber>
+      <FileNumber>30</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -586,7 +598,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>30</FileNumber>
+      <FileNumber>31</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -598,7 +610,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>31</FileNumber>
+      <FileNumber>32</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -608,6 +620,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>33</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\cht8305.c</PathWithFileName>
+      <FilenameWithoutPath>cht8305.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -618,7 +642,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>32</FileNumber>
+      <FileNumber>34</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -630,7 +654,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>33</FileNumber>
+      <FileNumber>35</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -642,7 +666,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>34</FileNumber>
+      <FileNumber>36</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -654,7 +678,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>35</FileNumber>
+      <FileNumber>37</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -666,7 +690,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>36</FileNumber>
+      <FileNumber>38</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -686,7 +710,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>37</FileNumber>
+      <FileNumber>39</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -698,7 +722,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>38</FileNumber>
+      <FileNumber>40</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -710,7 +734,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>39</FileNumber>
+      <FileNumber>41</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -722,7 +746,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>40</FileNumber>
+      <FileNumber>42</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -734,7 +758,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>41</FileNumber>
+      <FileNumber>43</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -746,7 +770,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>42</FileNumber>
+      <FileNumber>44</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -758,7 +782,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>43</FileNumber>
+      <FileNumber>45</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -770,7 +794,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>44</FileNumber>
+      <FileNumber>46</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -782,7 +806,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>45</FileNumber>
+      <FileNumber>47</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -794,7 +818,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>46</FileNumber>
+      <FileNumber>48</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -806,7 +830,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>47</FileNumber>
+      <FileNumber>49</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -818,7 +842,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>48</FileNumber>
+      <FileNumber>50</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -830,7 +854,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>49</FileNumber>
+      <FileNumber>51</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -842,7 +866,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>50</FileNumber>
+      <FileNumber>52</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -854,7 +878,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>51</FileNumber>
+      <FileNumber>53</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -866,7 +890,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>52</FileNumber>
+      <FileNumber>54</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -878,7 +902,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>53</FileNumber>
+      <FileNumber>55</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -890,7 +914,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>54</FileNumber>
+      <FileNumber>56</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -902,7 +926,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>55</FileNumber>
+      <FileNumber>57</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -914,7 +938,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>56</FileNumber>
+      <FileNumber>58</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -926,7 +950,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>57</FileNumber>
+      <FileNumber>59</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -938,7 +962,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>58</FileNumber>
+      <FileNumber>60</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -950,7 +974,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>59</FileNumber>
+      <FileNumber>61</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -970,7 +994,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>60</FileNumber>
+      <FileNumber>62</FileNumber>
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -982,7 +1006,7 @@
     </File>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>61</FileNumber>
+      <FileNumber>63</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>

+ 10 - 0
Project/SP700.uvprojx

@@ -428,6 +428,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\app\key_leds.c</FilePath>
             </File>
+            <File>
+              <FileName>event_record.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\event_record.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>
@@ -548,6 +553,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\bsp\fmc_flash.c</FilePath>
             </File>
+            <File>
+              <FileName>cht8305.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\cht8305.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>

+ 976 - 0
Project/SP710.uvoptx

@@ -0,0 +1,976 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
+
+  <SchemaVersion>1.0</SchemaVersion>
+
+  <Header>### uVision Project, (C) Keil Software</Header>
+
+  <Extensions>
+    <cExt>*.c</cExt>
+    <aExt>*.s*; *.src; *.a*</aExt>
+    <oExt>*.obj; *.o</oExt>
+    <lExt>*.lib</lExt>
+    <tExt>*.txt; *.h; *.inc</tExt>
+    <pExt>*.plm</pExt>
+    <CppX>*.cpp</CppX>
+    <nMigrate>0</nMigrate>
+  </Extensions>
+
+  <DaveTm>
+    <dwLowDateTime>0</dwLowDateTime>
+    <dwHighDateTime>0</dwHighDateTime>
+  </DaveTm>
+
+  <Target>
+    <TargetName>GD32F330C8</TargetName>
+    <ToolsetNumber>0x4</ToolsetNumber>
+    <ToolsetName>ARM-ADS</ToolsetName>
+    <TargetOption>
+      <CLKADS>12000000</CLKADS>
+      <OPTTT>
+        <gFlags>1</gFlags>
+        <BeepAtEnd>1</BeepAtEnd>
+        <RunSim>0</RunSim>
+        <RunTarget>1</RunTarget>
+        <RunAbUc>0</RunAbUc>
+      </OPTTT>
+      <OPTHX>
+        <HexSelection>1</HexSelection>
+        <FlashByte>65535</FlashByte>
+        <HexRangeLowAddress>0</HexRangeLowAddress>
+        <HexRangeHighAddress>0</HexRangeHighAddress>
+        <HexOffset>0</HexOffset>
+      </OPTHX>
+      <OPTLEX>
+        <PageWidth>79</PageWidth>
+        <PageLength>66</PageLength>
+        <TabStop>8</TabStop>
+        <ListingPath>.\Listings\</ListingPath>
+      </OPTLEX>
+      <ListingPage>
+        <CreateCListing>1</CreateCListing>
+        <CreateAListing>1</CreateAListing>
+        <CreateLListing>1</CreateLListing>
+        <CreateIListing>0</CreateIListing>
+        <AsmCond>1</AsmCond>
+        <AsmSymb>1</AsmSymb>
+        <AsmXref>0</AsmXref>
+        <CCond>1</CCond>
+        <CCode>0</CCode>
+        <CListInc>0</CListInc>
+        <CSymb>0</CSymb>
+        <LinkerCodeListing>0</LinkerCodeListing>
+      </ListingPage>
+      <OPTXL>
+        <LMap>1</LMap>
+        <LComments>1</LComments>
+        <LGenerateSymbols>1</LGenerateSymbols>
+        <LLibSym>1</LLibSym>
+        <LLines>1</LLines>
+        <LLocSym>1</LLocSym>
+        <LPubSym>1</LPubSym>
+        <LXref>0</LXref>
+        <LExpSel>0</LExpSel>
+      </OPTXL>
+      <OPTFL>
+        <tvExp>1</tvExp>
+        <tvExpOptDlg>0</tvExpOptDlg>
+        <IsCurrentTarget>1</IsCurrentTarget>
+      </OPTFL>
+      <CpuCode>0</CpuCode>
+      <DebugOpt>
+        <uSim>0</uSim>
+        <uTrg>1</uTrg>
+        <sLdApp>1</sLdApp>
+        <sGomain>1</sGomain>
+        <sRbreak>1</sRbreak>
+        <sRwatch>1</sRwatch>
+        <sRmem>1</sRmem>
+        <sRfunc>1</sRfunc>
+        <sRbox>1</sRbox>
+        <tLdApp>1</tLdApp>
+        <tGomain>1</tGomain>
+        <tRbreak>1</tRbreak>
+        <tRwatch>1</tRwatch>
+        <tRmem>1</tRmem>
+        <tRfunc>0</tRfunc>
+        <tRbox>1</tRbox>
+        <tRtrace>1</tRtrace>
+        <sRSysVw>1</sRSysVw>
+        <tRSysVw>1</tRSysVw>
+        <sRunDeb>0</sRunDeb>
+        <sLrtime>0</sLrtime>
+        <bEvRecOn>1</bEvRecOn>
+        <bSchkAxf>0</bSchkAxf>
+        <bTchkAxf>0</bTchkAxf>
+        <nTsel>0</nTsel>
+        <sDll></sDll>
+        <sDllPa></sDllPa>
+        <sDlgDll></sDlgDll>
+        <sDlgPa></sDlgPa>
+        <sIfile></sIfile>
+        <tDll></tDll>
+        <tDllPa></tDllPa>
+        <tDlgDll></tDlgDll>
+        <tDlgPa></tDlgPa>
+        <tIfile></tIfile>
+        <pMon>BIN\UL2CM3.DLL</pMon>
+      </DebugOpt>
+      <TargetDriverDllRegistry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>UL2CM3</Key>
+          <Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F3x0 -FS08000000 -FL010000 -FP0($$Device:GD32F330C8$Flash\GD32F3x0.FLM))</Name>
+        </SetRegEntry>
+      </TargetDriverDllRegistry>
+      <Breakpoint/>
+      <Tracepoint>
+        <THDelay>0</THDelay>
+      </Tracepoint>
+      <DebugFlag>
+        <trace>0</trace>
+        <periodic>0</periodic>
+        <aLwin>0</aLwin>
+        <aCover>0</aCover>
+        <aSer1>0</aSer1>
+        <aSer2>0</aSer2>
+        <aPa>0</aPa>
+        <viewmode>0</viewmode>
+        <vrSel>0</vrSel>
+        <aSym>0</aSym>
+        <aTbox>0</aTbox>
+        <AscS1>0</AscS1>
+        <AscS2>0</AscS2>
+        <AscS3>0</AscS3>
+        <aSer3>0</aSer3>
+        <eProf>0</eProf>
+        <aLa>0</aLa>
+        <aPa1>0</aPa1>
+        <AscS4>0</AscS4>
+        <aSer4>0</aSer4>
+        <StkLoc>0</StkLoc>
+        <TrcWin>0</TrcWin>
+        <newCpu>0</newCpu>
+        <uProt>0</uProt>
+      </DebugFlag>
+      <LintExecutable></LintExecutable>
+      <LintConfigFile></LintConfigFile>
+      <bLintAuto>0</bLintAuto>
+      <bAutoGenD>0</bAutoGenD>
+      <LntExFlags>0</LntExFlags>
+      <pMisraName></pMisraName>
+      <pszMrule></pszMrule>
+      <pSingCmds></pSingCmds>
+      <pMultCmds></pMultCmds>
+      <pMisraNamep></pMisraNamep>
+      <pszMrulep></pszMrulep>
+      <pSingCmdsp></pSingCmdsp>
+      <pMultCmdsp></pMultCmdsp>
+    </TargetOption>
+  </Target>
+
+  <Group>
+    <GroupName>Application</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>1</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\main.c</PathWithFileName>
+      <FilenameWithoutPath>main.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>2</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\protocol.c</PathWithFileName>
+      <FilenameWithoutPath>protocol.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>3</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\bms_message.c</PathWithFileName>
+      <FilenameWithoutPath>bms_message.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>4</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\pc_message.c</PathWithFileName>
+      <FilenameWithoutPath>pc_message.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>5</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\nv_storage.c</PathWithFileName>
+      <FilenameWithoutPath>nv_storage.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>6</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\iap.c</PathWithFileName>
+      <FilenameWithoutPath>iap.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>7</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\protocol_old.c</PathWithFileName>
+      <FilenameWithoutPath>protocol_old.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>8</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\pcba_test.c</PathWithFileName>
+      <FilenameWithoutPath>pcba_test.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>9</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\key_leds.c</PathWithFileName>
+      <FilenameWithoutPath>key_leds.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>10</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\event_record.c</PathWithFileName>
+      <FilenameWithoutPath>event_record.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>SOX</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>11</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\state.c</PathWithFileName>
+      <FilenameWithoutPath>state.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>12</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\iostate.c</PathWithFileName>
+      <FilenameWithoutPath>iostate.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>13</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\measure.c</PathWithFileName>
+      <FilenameWithoutPath>measure.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>14</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\measure_task.c</PathWithFileName>
+      <FilenameWithoutPath>measure_task.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>15</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\health.c</PathWithFileName>
+      <FilenameWithoutPath>health.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>16</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\soc.c</PathWithFileName>
+      <FilenameWithoutPath>soc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>17</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\Least_Square.c</PathWithFileName>
+      <FilenameWithoutPath>Least_Square.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>18</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\soft_current_protect.c</PathWithFileName>
+      <FilenameWithoutPath>soft_current_protect.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>BSP</GroupName>
+    <tvExp>1</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>19</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\gpio.c</PathWithFileName>
+      <FilenameWithoutPath>gpio.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>20</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\irqs.c</PathWithFileName>
+      <FilenameWithoutPath>irqs.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>21</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\spi.c</PathWithFileName>
+      <FilenameWithoutPath>spi.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>22</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\cs1180.c</PathWithFileName>
+      <FilenameWithoutPath>cs1180.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>23</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\ml5238.c</PathWithFileName>
+      <FilenameWithoutPath>ml5238.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>24</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\AT24CXX.c</PathWithFileName>
+      <FilenameWithoutPath>AT24CXX.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>25</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\i2c.c</PathWithFileName>
+      <FilenameWithoutPath>i2c.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>26</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\uart.c</PathWithFileName>
+      <FilenameWithoutPath>uart.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>27</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\gd32_adc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32_adc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>28</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\clock.c</PathWithFileName>
+      <FilenameWithoutPath>clock.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>29</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\bsp.c</PathWithFileName>
+      <FilenameWithoutPath>bsp.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>30</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\mcu_power_sleep.c</PathWithFileName>
+      <FilenameWithoutPath>mcu_power_sleep.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>31</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\shark_rtc.c</PathWithFileName>
+      <FilenameWithoutPath>shark_rtc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>32</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\fmc_flash.c</PathWithFileName>
+      <FilenameWithoutPath>fmc_flash.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>33</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\bsp\cht8305.c</PathWithFileName>
+      <FilenameWithoutPath>cht8305.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>Libs</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>34</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\shark_task.c</PathWithFileName>
+      <FilenameWithoutPath>shark_task.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>35</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\byte_queue.c</PathWithFileName>
+      <FilenameWithoutPath>byte_queue.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>36</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\shark_utils.c</PathWithFileName>
+      <FilenameWithoutPath>shark_utils.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>37</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\logger.c</PathWithFileName>
+      <FilenameWithoutPath>logger.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>38</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\circle_buffer.c</PathWithFileName>
+      <FilenameWithoutPath>circle_buffer.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>GD32F30x_Drivers</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>39</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_adc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_adc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>40</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_cec.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_cec.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>41</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_cmp.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_cmp.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>42</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_crc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_crc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>43</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_ctc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_ctc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>44</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dac.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_dac.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>45</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dbg.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_dbg.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>46</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dma.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_dma.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>47</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_exti.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_exti.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>48</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_fmc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_fmc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>49</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_fwdgt.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_fwdgt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>50</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_gpio.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_gpio.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>51</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_i2c.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_i2c.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>52</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_misc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_misc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>53</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_pmu.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_pmu.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>54</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_rcu.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_rcu.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>55</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_rtc.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_rtc.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>56</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_spi.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_spi.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>57</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_syscfg.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_syscfg.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>58</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_timer.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_timer.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>59</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_tsi.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_tsi.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>60</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_usart.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_usart.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>61</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_wwdgt.c</PathWithFileName>
+      <FilenameWithoutPath>gd32f3x0_wwdgt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>StartUp</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>6</GroupNumber>
+      <FileNumber>62</FileNumber>
+      <FileType>2</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\CMSIS\GD32F3x0\Source\startup_gd32f3x0.s</PathWithFileName>
+      <FilenameWithoutPath>startup_gd32f3x0.s</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>6</GroupNumber>
+      <FileNumber>63</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Librarys\CMSIS\GD32F3x0\Source\system_gd32f3x0.c</PathWithFileName>
+      <FilenameWithoutPath>system_gd32f3x0.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+</ProjectOpt>

+ 753 - 0
Project/SP710.uvprojx

@@ -0,0 +1,753 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
+
+  <SchemaVersion>2.1</SchemaVersion>
+
+  <Header>### uVision Project, (C) Keil Software</Header>
+
+  <Targets>
+    <Target>
+      <TargetName>GD32F330C8</TargetName>
+      <ToolsetNumber>0x4</ToolsetNumber>
+      <ToolsetName>ARM-ADS</ToolsetName>
+      <pCCUsed>5060750::V5.06 update 6 (build 750)::.\ARMCC</pCCUsed>
+      <uAC6>0</uAC6>
+      <TargetOption>
+        <TargetCommonOption>
+          <Device>GD32F330C8</Device>
+          <Vendor>GigaDevice</Vendor>
+          <PackID>GigaDevice.GD32F3x0_DFP.2.0.0</PackID>
+          <PackURL>http://gd32mcu.com/data/documents/pack/</PackURL>
+          <Cpu>IRAM(0x20000000,0x02000) IROM(0x08000000,0x10000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
+          <FlashUtilSpec></FlashUtilSpec>
+          <StartupFile></StartupFile>
+          <FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F3x0 -FS08000000 -FL010000 -FP0($$Device:GD32F330C8$Flash\GD32F3x0.FLM))</FlashDriverDll>
+          <DeviceId>0</DeviceId>
+          <RegisterFile>$$Device:GD32F330C8$Device\Include\gd32f3x0.h</RegisterFile>
+          <MemoryEnv></MemoryEnv>
+          <Cmp></Cmp>
+          <Asm></Asm>
+          <Linker></Linker>
+          <OHString></OHString>
+          <InfinionOptionDll></InfinionOptionDll>
+          <SLE66CMisc></SLE66CMisc>
+          <SLE66AMisc></SLE66AMisc>
+          <SLE66LinkerMisc></SLE66LinkerMisc>
+          <SFDFile>$$Device:GD32F330C8$SVD\GD32F3x0.svd</SFDFile>
+          <bCustSvd>0</bCustSvd>
+          <UseEnv>0</UseEnv>
+          <BinPath></BinPath>
+          <IncludePath></IncludePath>
+          <LibPath></LibPath>
+          <RegisterFilePath></RegisterFilePath>
+          <DBRegisterFilePath></DBRegisterFilePath>
+          <TargetStatus>
+            <Error>0</Error>
+            <ExitCodeStop>0</ExitCodeStop>
+            <ButtonStop>0</ButtonStop>
+            <NotGenerated>0</NotGenerated>
+            <InvalidFlash>1</InvalidFlash>
+          </TargetStatus>
+          <OutputDirectory>.\Output\SP710\</OutputDirectory>
+          <OutputName>SP710</OutputName>
+          <CreateExecutable>1</CreateExecutable>
+          <CreateLib>0</CreateLib>
+          <CreateHexFile>0</CreateHexFile>
+          <DebugInformation>1</DebugInformation>
+          <BrowseInformation>1</BrowseInformation>
+          <ListingPath>.\Listings\</ListingPath>
+          <HexFormatSelection>1</HexFormatSelection>
+          <Merge32K>0</Merge32K>
+          <CreateBatchFile>0</CreateBatchFile>
+          <BeforeCompile>
+            <RunUserProg1>0</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name></UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopU1X>0</nStopU1X>
+            <nStopU2X>0</nStopU2X>
+          </BeforeCompile>
+          <BeforeMake>
+            <RunUserProg1>1</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name>SharkFwVersion gen ..\Application\version.h ./version_sp710.cfg</UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopB1X>0</nStopB1X>
+            <nStopB2X>0</nStopB2X>
+          </BeforeMake>
+          <AfterMake>
+            <RunUserProg1>1</RunUserProg1>
+            <RunUserProg2>1</RunUserProg2>
+            <UserProg1Name>fromelf --bin --output ./Output/SP710.bin ./Output/SP710/SP710.axf</UserProg1Name>
+            <UserProg2Name>SharkFwVersion mv  ./Output/SP710.bin</UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopA1X>0</nStopA1X>
+            <nStopA2X>0</nStopA2X>
+          </AfterMake>
+          <SelectedForBatchBuild>0</SelectedForBatchBuild>
+          <SVCSIdString></SVCSIdString>
+        </TargetCommonOption>
+        <CommonProperty>
+          <UseCPPCompiler>0</UseCPPCompiler>
+          <RVCTCodeConst>0</RVCTCodeConst>
+          <RVCTZI>0</RVCTZI>
+          <RVCTOtherData>0</RVCTOtherData>
+          <ModuleSelection>0</ModuleSelection>
+          <IncludeInBuild>1</IncludeInBuild>
+          <AlwaysBuild>0</AlwaysBuild>
+          <GenerateAssemblyFile>0</GenerateAssemblyFile>
+          <AssembleAssemblyFile>0</AssembleAssemblyFile>
+          <PublicsOnly>0</PublicsOnly>
+          <StopOnExitCode>3</StopOnExitCode>
+          <CustomArgument></CustomArgument>
+          <IncludeLibraryModules></IncludeLibraryModules>
+          <ComprImg>1</ComprImg>
+        </CommonProperty>
+        <DllOption>
+          <SimDllName>SARMCM3.DLL</SimDllName>
+          <SimDllArguments> -REMAP -MPU</SimDllArguments>
+          <SimDlgDll>DCM.DLL</SimDlgDll>
+          <SimDlgDllArguments>-pCM4</SimDlgDllArguments>
+          <TargetDllName>SARMCM3.DLL</TargetDllName>
+          <TargetDllArguments> -MPU</TargetDllArguments>
+          <TargetDlgDll>TCM.DLL</TargetDlgDll>
+          <TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
+        </DllOption>
+        <DebugOption>
+          <OPTHX>
+            <HexSelection>1</HexSelection>
+            <HexRangeLowAddress>0</HexRangeLowAddress>
+            <HexRangeHighAddress>0</HexRangeHighAddress>
+            <HexOffset>0</HexOffset>
+            <Oh166RecLen>16</Oh166RecLen>
+          </OPTHX>
+        </DebugOption>
+        <Utilities>
+          <Flash1>
+            <UseTargetDll>1</UseTargetDll>
+            <UseExternalTool>0</UseExternalTool>
+            <RunIndependent>0</RunIndependent>
+            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
+            <Capability>1</Capability>
+            <DriverSelection>4096</DriverSelection>
+          </Flash1>
+          <bUseTDR>1</bUseTDR>
+          <Flash2>BIN\UL2CM3.DLL</Flash2>
+          <Flash3>"" ()</Flash3>
+          <Flash4></Flash4>
+          <pFcarmOut></pFcarmOut>
+          <pFcarmGrp></pFcarmGrp>
+          <pFcArmRoot></pFcArmRoot>
+          <FcArmLst>0</FcArmLst>
+        </Utilities>
+        <TargetArmAds>
+          <ArmAdsMisc>
+            <GenerateListings>0</GenerateListings>
+            <asHll>1</asHll>
+            <asAsm>1</asAsm>
+            <asMacX>1</asMacX>
+            <asSyms>1</asSyms>
+            <asFals>1</asFals>
+            <asDbgD>1</asDbgD>
+            <asForm>1</asForm>
+            <ldLst>0</ldLst>
+            <ldmm>1</ldmm>
+            <ldXref>1</ldXref>
+            <BigEnd>0</BigEnd>
+            <AdsALst>1</AdsALst>
+            <AdsACrf>1</AdsACrf>
+            <AdsANop>0</AdsANop>
+            <AdsANot>0</AdsANot>
+            <AdsLLst>1</AdsLLst>
+            <AdsLmap>1</AdsLmap>
+            <AdsLcgr>1</AdsLcgr>
+            <AdsLsym>1</AdsLsym>
+            <AdsLszi>1</AdsLszi>
+            <AdsLtoi>1</AdsLtoi>
+            <AdsLsun>1</AdsLsun>
+            <AdsLven>1</AdsLven>
+            <AdsLsxf>1</AdsLsxf>
+            <RvctClst>0</RvctClst>
+            <GenPPlst>0</GenPPlst>
+            <AdsCpuType>"Cortex-M4"</AdsCpuType>
+            <RvctDeviceName></RvctDeviceName>
+            <mOS>0</mOS>
+            <uocRom>0</uocRom>
+            <uocRam>0</uocRam>
+            <hadIROM>1</hadIROM>
+            <hadIRAM>1</hadIRAM>
+            <hadXRAM>0</hadXRAM>
+            <uocXRam>0</uocXRam>
+            <RvdsVP>2</RvdsVP>
+            <RvdsMve>0</RvdsMve>
+            <RvdsCdeCp>0</RvdsCdeCp>
+            <hadIRAM2>0</hadIRAM2>
+            <hadIROM2>0</hadIROM2>
+            <StupSel>8</StupSel>
+            <useUlib>1</useUlib>
+            <EndSel>0</EndSel>
+            <uLtcg>0</uLtcg>
+            <nSecure>0</nSecure>
+            <RoSelD>3</RoSelD>
+            <RwSelD>3</RwSelD>
+            <CodeSel>0</CodeSel>
+            <OptFeed>0</OptFeed>
+            <NoZi1>0</NoZi1>
+            <NoZi2>0</NoZi2>
+            <NoZi3>0</NoZi3>
+            <NoZi4>0</NoZi4>
+            <NoZi5>0</NoZi5>
+            <Ro1Chk>0</Ro1Chk>
+            <Ro2Chk>0</Ro2Chk>
+            <Ro3Chk>0</Ro3Chk>
+            <Ir1Chk>1</Ir1Chk>
+            <Ir2Chk>0</Ir2Chk>
+            <Ra1Chk>0</Ra1Chk>
+            <Ra2Chk>0</Ra2Chk>
+            <Ra3Chk>0</Ra3Chk>
+            <Im1Chk>1</Im1Chk>
+            <Im2Chk>0</Im2Chk>
+            <OnChipMemories>
+              <Ocm1>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm1>
+              <Ocm2>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm2>
+              <Ocm3>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm3>
+              <Ocm4>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm4>
+              <Ocm5>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm5>
+              <Ocm6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm6>
+              <IRAM>
+                <Type>0</Type>
+                <StartAddress>0x20000000</StartAddress>
+                <Size>0x2000</Size>
+              </IRAM>
+              <IROM>
+                <Type>1</Type>
+                <StartAddress>0x8000000</StartAddress>
+                <Size>0x10000</Size>
+              </IROM>
+              <XRAM>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </XRAM>
+              <OCR_RVCT1>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT1>
+              <OCR_RVCT2>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT2>
+              <OCR_RVCT3>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT3>
+              <OCR_RVCT4>
+                <Type>1</Type>
+                <StartAddress>0x8002000</StartAddress>
+                <Size>0x10000</Size>
+              </OCR_RVCT4>
+              <OCR_RVCT5>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT5>
+              <OCR_RVCT6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT6>
+              <OCR_RVCT7>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT7>
+              <OCR_RVCT8>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT8>
+              <OCR_RVCT9>
+                <Type>0</Type>
+                <StartAddress>0x20000000</StartAddress>
+                <Size>0x2000</Size>
+              </OCR_RVCT9>
+              <OCR_RVCT10>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT10>
+            </OnChipMemories>
+            <RvctStartVector></RvctStartVector>
+          </ArmAdsMisc>
+          <Cads>
+            <interw>1</interw>
+            <Optim>2</Optim>
+            <oTime>0</oTime>
+            <SplitLS>0</SplitLS>
+            <OneElfS>1</OneElfS>
+            <Strict>0</Strict>
+            <EnumInt>0</EnumInt>
+            <PlainCh>0</PlainCh>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <wLevel>2</wLevel>
+            <uThumb>0</uThumb>
+            <uSurpInc>0</uSurpInc>
+            <uC99>1</uC99>
+            <uGnu>1</uGnu>
+            <useXO>0</useXO>
+            <v6Lang>0</v6Lang>
+            <v6LangP>3</v6LangP>
+            <vShortEn>1</vShortEn>
+            <vShortWch>1</vShortWch>
+            <v6Lto>0</v6Lto>
+            <v6WtE>0</v6WtE>
+            <v6Rtti>0</v6Rtti>
+            <VariousControls>
+              <MiscControls></MiscControls>
+              <Define>CONFIG_BOARD_SP700,CONFIG_CAN_IAP,SP710_V2</Define>
+              <Undefine></Undefine>
+              <IncludePath>..\Librarys\CMSIS\5.7.0\Include;..\Librarys\CMSIS\GD32F3x0\Include;..\Librarys\GD32F3x0_Drivers\include;..\Application\app;..\Application</IncludePath>
+            </VariousControls>
+          </Cads>
+          <Aads>
+            <interw>1</interw>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <thumb>0</thumb>
+            <SplitLS>0</SplitLS>
+            <SwStkChk>0</SwStkChk>
+            <NoWarn>0</NoWarn>
+            <uSurpInc>0</uSurpInc>
+            <useXO>0</useXO>
+            <ClangAsOpt>4</ClangAsOpt>
+            <VariousControls>
+              <MiscControls></MiscControls>
+              <Define></Define>
+              <Undefine></Undefine>
+              <IncludePath></IncludePath>
+            </VariousControls>
+          </Aads>
+          <LDads>
+            <umfTarg>1</umfTarg>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <noStLib>0</noStLib>
+            <RepFail>1</RepFail>
+            <useFile>0</useFile>
+            <TextAddressRange>0x08000000</TextAddressRange>
+            <DataAddressRange>0x20000000</DataAddressRange>
+            <pXoBase></pXoBase>
+            <ScatterFile></ScatterFile>
+            <IncludeLibs></IncludeLibs>
+            <IncludeLibsPath></IncludeLibsPath>
+            <Misc></Misc>
+            <LinkerInputFile></LinkerInputFile>
+            <DisabledWarnings></DisabledWarnings>
+          </LDads>
+        </TargetArmAds>
+      </TargetOption>
+      <Groups>
+        <Group>
+          <GroupName>Application</GroupName>
+          <Files>
+            <File>
+              <FileName>main.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\main.c</FilePath>
+            </File>
+            <File>
+              <FileName>protocol.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\protocol.c</FilePath>
+            </File>
+            <File>
+              <FileName>bms_message.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\bms_message.c</FilePath>
+            </File>
+            <File>
+              <FileName>pc_message.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\pc_message.c</FilePath>
+            </File>
+            <File>
+              <FileName>nv_storage.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\nv_storage.c</FilePath>
+            </File>
+            <File>
+              <FileName>iap.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\iap.c</FilePath>
+            </File>
+            <File>
+              <FileName>protocol_old.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\protocol_old.c</FilePath>
+            </File>
+            <File>
+              <FileName>pcba_test.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\pcba_test.c</FilePath>
+            </File>
+            <File>
+              <FileName>key_leds.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\key_leds.c</FilePath>
+            </File>
+            <File>
+              <FileName>event_record.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\event_record.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>SOX</GroupName>
+          <Files>
+            <File>
+              <FileName>state.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\state.c</FilePath>
+            </File>
+            <File>
+              <FileName>iostate.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\iostate.c</FilePath>
+            </File>
+            <File>
+              <FileName>measure.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\measure.c</FilePath>
+            </File>
+            <File>
+              <FileName>measure_task.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\measure_task.c</FilePath>
+            </File>
+            <File>
+              <FileName>health.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\health.c</FilePath>
+            </File>
+            <File>
+              <FileName>soc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\soc.c</FilePath>
+            </File>
+            <File>
+              <FileName>Least_Square.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\Least_Square.c</FilePath>
+            </File>
+            <File>
+              <FileName>soft_current_protect.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\soft_current_protect.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>BSP</GroupName>
+          <Files>
+            <File>
+              <FileName>gpio.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\gpio.c</FilePath>
+            </File>
+            <File>
+              <FileName>irqs.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\irqs.c</FilePath>
+            </File>
+            <File>
+              <FileName>spi.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\spi.c</FilePath>
+            </File>
+            <File>
+              <FileName>cs1180.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\cs1180.c</FilePath>
+            </File>
+            <File>
+              <FileName>ml5238.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\ml5238.c</FilePath>
+            </File>
+            <File>
+              <FileName>AT24CXX.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\AT24CXX.c</FilePath>
+            </File>
+            <File>
+              <FileName>i2c.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\i2c.c</FilePath>
+            </File>
+            <File>
+              <FileName>uart.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\uart.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32_adc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\gd32_adc.c</FilePath>
+            </File>
+            <File>
+              <FileName>clock.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\clock.c</FilePath>
+            </File>
+            <File>
+              <FileName>bsp.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\bsp.c</FilePath>
+            </File>
+            <File>
+              <FileName>mcu_power_sleep.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\mcu_power_sleep.c</FilePath>
+            </File>
+            <File>
+              <FileName>shark_rtc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\shark_rtc.c</FilePath>
+            </File>
+            <File>
+              <FileName>fmc_flash.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\fmc_flash.c</FilePath>
+            </File>
+            <File>
+              <FileName>cht8305.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\bsp\cht8305.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>Libs</GroupName>
+          <Files>
+            <File>
+              <FileName>shark_task.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\shark_task.c</FilePath>
+            </File>
+            <File>
+              <FileName>byte_queue.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\byte_queue.c</FilePath>
+            </File>
+            <File>
+              <FileName>shark_utils.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\shark_utils.c</FilePath>
+            </File>
+            <File>
+              <FileName>logger.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\logger.c</FilePath>
+            </File>
+            <File>
+              <FileName>circle_buffer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\circle_buffer.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>GD32F30x_Drivers</GroupName>
+          <Files>
+            <File>
+              <FileName>gd32f3x0_adc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_adc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_cec.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_cec.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_cmp.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_cmp.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_crc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_crc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_ctc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_ctc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_dac.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dac.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_dbg.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dbg.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_dma.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_dma.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_exti.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_exti.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_fmc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_fmc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_fwdgt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_fwdgt.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_gpio.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_gpio.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_i2c.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_i2c.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_misc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_misc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_pmu.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_pmu.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_rcu.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_rcu.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_rtc.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_rtc.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_spi.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_spi.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_syscfg.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_syscfg.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_timer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_timer.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_tsi.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_tsi.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_usart.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_usart.c</FilePath>
+            </File>
+            <File>
+              <FileName>gd32f3x0_wwdgt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\GD32F3x0_Drivers\Source\gd32f3x0_wwdgt.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>StartUp</GroupName>
+          <Files>
+            <File>
+              <FileName>startup_gd32f3x0.s</FileName>
+              <FileType>2</FileType>
+              <FilePath>..\Librarys\CMSIS\GD32F3x0\Source\startup_gd32f3x0.s</FilePath>
+            </File>
+            <File>
+              <FileName>system_gd32f3x0.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Librarys\CMSIS\GD32F3x0\Source\system_gd32f3x0.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+      </Groups>
+    </Target>
+  </Targets>
+
+  <RTE>
+    <apis/>
+    <components/>
+    <files/>
+  </RTE>
+
+  <LayerInfo>
+    <Layers>
+      <Layer>
+        <LayName>&lt;Project Info&gt;</LayName>
+        <LayDesc></LayDesc>
+        <LayUrl></LayUrl>
+        <LayKeys></LayKeys>
+        <LayCat></LayCat>
+        <LayLic></LayLic>
+        <LayTarg>0</LayTarg>
+        <LayPrjMark>1</LayPrjMark>
+      </Layer>
+    </Layers>
+  </LayerInfo>
+
+</Project>

+ 1 - 1
Project/version_sp600.cfg

@@ -1,2 +1,2 @@
 project: RSP623FL
-version: 3
+version: 00

+ 1 - 1
Project/version_sp600_15AH.cfg

@@ -1,2 +1,2 @@
 project: RSP615FL
-version: 3
+version: 00

+ 1 - 1
Project/version_sp700.cfg

@@ -1,2 +1,2 @@
 project: HSP730FL
-version: 3
+version: 6

+ 2 - 0
Project/version_sp710.cfg

@@ -0,0 +1,2 @@
+project: HSP730FL
+version: 20

+ 3 - 0
shark_build.conf

@@ -1,11 +1,14 @@
 project: Project/SP700.uvprojx
 version: Project/version.txt
 output: Project/Output
+name: SP700
 
 project: Project/SP600.uvprojx
 version: Project/version.txt
 output: Project/Output
+name: SP600
 
 project: Project/SP600_15AH.uvprojx
 version: Project/version.txt
 output: Project/Output
+name: SP600_15AH