| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #include <string.h>
- #include "libs/shark_libs.h"
- #include "spi.h"
- #include "ml5238.h"
- #include "libs/logger.h"
- static int ml5238_read(uint8_t regaddr, uint8_t *data);
- static void ml5238_clear_bits(uint8_t regaddr, uint8_t bit);
- static void ml5238_set_bits(uint8_t regaddr, uint8_t bit);
- static void irq_hander_in_timer(shark_timer_t *timer);
- static ml5238_notify_hander _handler;
- static shark_timer_t irq_task = {.handler = irq_hander_in_timer};
- void ml5238_init(void){
- spi0_init();
- ml5238_softreset();
- ml5238_irq_enable(1);
- }
- uint8_t ml5238_noop_register_rw(uint8_t data){
- uint8_t value = data;
- ml5238_write(ML5238_NOOP, value);
- value = 0xFF;
- ml5238_read(ML5238_NOOP, &value);
- return value;
- }
- void ml5238_register_notify_handler(ml5238_notify_hander handler){
- _handler = handler;
- }
- //小电流打开等效discharger mos打开
- int ml5238_charger_is_disconnect(int small_current_on){
- uint8_t value = 0;
- uint8_t fet = 0;
- ml5238_read(ML5238_FET, &fet);
- ml5238_read(ML5238_PSENSE, &value);
- if ((fet & FET_DF) || small_current_on){
- return (value & PSENSE_PSL);
- }
- return (value & PSENSE_PSH);
- }
- int ml5238_enable_load_detect(int enable){
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_RRS);
- if (enable){
- ml5238_set_bits(ML5238_RSENSE, RSENSE_ERS);
- }else {
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_ERS | RSENSE_IRS);
- }
- return 0;
- }
- int ml5238_is_load_disconnect(void){
- uint8_t value = 0;
- ml5238_read(ML5238_RSENSE, &value);
- return (value & RSENSE_RS);
- }
- #define IRS_IRQ 1 //load disconnect中断
- #define IPSL_IRQ 2 //charger over current
- #define ICS_IRQ 3 //短路中断
- int ml5238_enable_irq(int enable, int irq){
- if (irq == IRS_IRQ){
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_RRS);
- if (enable){
- ml5238_set_bits(ML5238_RSENSE, RSENSE_IRS);
- }else {
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_IRS);
- }
- }
- if (irq == IPSL_IRQ){
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSL);
- if (enable){
- ml5238_set_bits(ML5238_PSENSE, PSENSE_IPSL);
- }else {
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_IPSL);
- }
- }
- if (irq == ICS_IRQ){
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_RSC);
- if (enable){
- ml5238_set_bits(ML5238_RSENSE, RSENSE_ISC);
- }else {
- ml5238_clear_bits(ML5238_RSENSE, RSENSE_ISC);
- }
- }
- return 0;
- }
- //小电流打开等效discharger mos打开
- int ml5238_enable_charger_detect(int small_current_on, int enable){
- uint8_t fet = 0;
- ml5238_read(ML5238_FET, &fet);
- if ((fet & FET_DF) || small_current_on){ //discharger is on, used to detect charger over current
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSL);
- if (enable){
- ml5238_set_bits(ML5238_PSENSE, PSENSE_EPSL);
- }else {
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_EPSL);
- }
- }else { //discharger if off, used when powerdown, charger is insert
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSH);
- if (enable){
- ml5238_set_bits(ML5238_PSENSE, PSENSE_EPSH);
- }else {
- ml5238_clear_bits(ML5238_PSENSE, PSENSE_EPSH);
- }
- }
- return 0;
- }
- static int __inline__ _charger_mosfet_is_open(void){
- uint8_t data;
- ml5238_read(ML5238_FET, &data);
- return (data & FET_CF) != 0;
- }
- static int __inline__ _discharger_mosfet_is_open(void){
- uint8_t data;
- ml5238_read(ML5238_FET, &data);
- return (data & FET_DF) != 0;
- }
- int ml5238_is_charging(void){
- return _charger_mosfet_is_open();
- }
- int ml5238_is_discharging(void){
- return _discharger_mosfet_is_open();
- }
- void ml5238_cell_start_balance(uint16_t balance_mask){
- ml5238_write(ML5238_CBALH, (balance_mask >> 8) & 0xFF);
- ml5238_write(ML5238_CBALL, balance_mask & 0xFF);
- }
- int ml5238_enable_discharger_mosfet(int enable){
- uint8_t data;
- if (ml5238_read(ML5238_FET, &data) == 0){
- if ((data & FET_DF) == enable){
- return 0; //alread enable/disabled
- }
- data &= ~(FET_DF);
- if (enable){
- data |= (FET_DF | FET_DRV);
- }else {
- if ((data & FET_CF) == 0){
- data &= ~(FET_DRV);
- }
- }
- return ml5238_write(ML5238_FET, data);
- }
- return -1;
- }
- /* when enable charger the discharger mosfet also must be enabled for charging */
- int ml5238_enable_charger_mosfet(int enable){
- uint8_t data;
- if (ml5238_read(ML5238_FET, &data) == 0){
- if (((data & FET_CF) >> 1) == enable){
- return 0; //alread enable/disabled
- }
- data &= ~(FET_CF);
- if (enable){
- data |= (FET_CF | FET_DRV);
- }else {
- if ((data & FET_DF) == 0){
- data &= ~(FET_DRV);
- }
- }
- return ml5238_write(ML5238_FET, data);
- }
- return -1;
- }
- int ml5238_short_current_detect(int mode){
- uint8_t rsense = 0;
- if (mode >= SHORT_CURRENT_MODE_50A_100A){
- if (ml5238_read(ML5238_RSENSE, &rsense) == 0){
- if (ml5238_write(ML5238_SETSC, mode) == 0){
- rsense |= (RSENSE_ESC | RSENSE_ISC);//enable short current detect && irq
- rsense &= ~RSENSE_RSC;
- return ml5238_write(ML5238_RSENSE, rsense);
- }
- }
- }else {
- if (ml5238_read(ML5238_RSENSE, &rsense) == 0){
- rsense &= ~(RSENSE_ESC|RSENSE_ISC|RSENSE_RSC);
- return ml5238_write(ML5238_RSENSE, rsense);
- }
- }
- return -1;
- }
- int ml5238_is_short_current_enabled(int mode){
- uint8_t value = 0;
- if (ml5238_read(ML5238_SETSC, &value) < 0){
- return 0;
- }
- if (value != mode) {
- return 0;
- }
- value = 0;
- if (ml5238_read(ML5238_RSENSE, &value) < 0){
- return 0;
- }
- if ((value & (RSENSE_ESC | RSENSE_ISC)) != (RSENSE_ESC | RSENSE_ISC)){
- return 0;
- }
- if (value & RSENSE_RSC){
- return 0;
- }
- return 1;
- }
- void ml5238_softreset(void) {
- for(unsigned char i = 0u; i < 0x0Au; i++){
- ml5238_write((uint8_t)(ML5238_VMON + i), 0x00u);
- }
- }
- void ml5238_reg_log(void){
- uint8_t data = 0xFF;
- for(unsigned char i = 0u; i < 0x0Au; i++){
- ml5238_read((uint8_t)(ML5238_VMON + i), &data);
- sys_debug("Reg %d:0x%x\n", (ML5238_VMON + i), data);
- }
- }
- uint8_t ml5238_read_imon(void){
- uint8_t data = 0xFF;
- if (ml5238_read(ML5238_IMON, &data) < 0) {
- return 0xff;
- }
- return data;
- }
- void ml5238_power_down(void){
- do {
- ml5238_write(ML5238_PSENSE, PSENSE_EPSH|PSENSE_IPSH); //before power down, we must enable charger detect
- ml5238_write(ML5238_POWER, POWER_PDWN);
- }while(1);
- }
- void ml5238_power_save(int save){
- if (save) {
- ml5238_write(ML5238_PSENSE, 0);
- ML5238_VMON_DISABLE();
- ML5238_IMON_DISABLE();
- ml5238_write(ML5238_POWER, POWER_PSV);
- ml5238_irq_enable(1); //enable charger detect irq, to wakeup bms when charger insert
- spi0_deinit();
- }else {
- spi0_init();
- ml5238_write(ML5238_POWER, 0);
- }
- }
- static void __inline__ call_handler(int event){
- if (_handler) {
- _handler(event);
- }
- }
- static void irq_hander_in_timer(shark_timer_t *timer){
- uint8_t status = 0;
- ml5238_read(ML5238_STATUS, &status);
- if (status & STATUS_RPSL){//chargering over current
- sys_error("charger over current\n");
- ml5238_enable_charger_detect(0, 0);
- ml5238_enable_charger_detect(1, 0);
- call_handler(ML5238_Event_Charger_Over_Current);
- }
- if (status & STATUS_RSC) { //short current detect, close charger/discharger mosfet
- sys_error("short current\n");
- if (_charger_mosfet_is_open()) {
- ml5238_enable_charger_mosfet(0);
- }
- if (_discharger_mosfet_is_open()) {
- ml5238_enable_discharger_mosfet(0);
- }
- ml5238_short_current_detect(SHORT_CURRENT_MODE_DISABLE);
- call_handler(ML5238_Event_Short_Current);
- }
- if (status & STATUS_RRS) {//load disconnect, if short detect, we must wait load disconnected, and then can open discharger
- ml5238_enable_irq(0, IRS_IRQ);
- call_handler(ML5238_Event_Load_Disconnect);
- }
- }
- void ml5238_irq_handler(void){
- shark_timer_post(&irq_task, 0);
- }
- static void ml5238_set_bits(uint8_t regaddr, uint8_t bit) {
- uint8_t value;
- ml5238_read(regaddr, &value);
- ml5238_write(regaddr, value|bit);
- }
- static void ml5238_clear_bits(uint8_t regaddr, uint8_t bit) {
- uint8_t value;
- ml5238_read(regaddr, &value);
- ml5238_write(regaddr, value&(~bit));
- }
- int ml5238_write(uint8_t regaddr, uint8_t data){
- uint16_t send_data=(((uint16_t)regaddr)<<(0x09))|((uint16_t)data);
- ml5238_cs(0);
- int ret = spi0_send_uint16(send_data, NULL);
- ml5238_cs(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);
- int ret = spi0_send_uint16(send_data, data);
- ml5238_cs(1);
- return ret;
- }
|