This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ27421EVM-G1A: BQ27421EVM-G1A. Data flash checksum error?

Part Number: BQ27421EVM-G1A
Other Parts Discussed in Thread: BQ27421-G1

I am having an issue validating my checksum. First, I would like to say that there seem to be four different ways to perform the checksum calculation, depending on which reference is used. Thus far I have referenced the following documents and performed trial an error with each method, but I am being stopped by an overarching issue (checksum register reads as zero unless I read it two times in a row, in which case I get 0xAC).

All of these agree that you need to independently calculate the checksum and then write it to the checksum register before pushing your block memory data to the ROM (I think). However, the first reference seems to think that this calculation can be independent of the previous checksum register value. According to this first reference, you can simply sum the block data address, the data bytes written, invert the sum, and write it to the register. I have tried this and it does not work. This leaves me attempting the other methods, which involve taking the previous checksum register value, inverting it, and sometimes subtracting the old data byte values and doing a mod() to the result, then... so on. The other method does not involve dividing or remainders. It just asks that you invert the old checksum register value, subtract the old data value bytes, add the new data value bytes, invert the number again, and write the LSB to the checksum register. 

I would be attempting those later two methods, but as I said, my checksum register always reads as zero, unless I read it twice in a row (and by twice in a row I do not mean reading two databytes in the same I2C command, I mean performing an I2C write command on that same register as soon as the last one finished), in which case the second time I get 0xAC. To my understanding, I should be expecting something close to 0xE8, since that is what you should expect for -G1B.

Has anyone else run into this? I can confirm that I am not writing too fast or losing data because my loop reads the data and sends the data correctly hundreds of times according to my sniffer.

I can also confirm that my 0x06 flag is giving me 10011000, so I am in CFGUPMODE, the battery is detected, and OCVTAKEN is set.

  • We are looking into this and will get back to you shortly- tomorrow at the latest
    thanks
    Onyx
  • Writing the check sum triggers a block transfer from the temporary 32 byte block buffer (starting at address 0x40) to the actual internal data memory location.

    The gauge will only perform this transfer if the check sum is correct. The gauge always calculates the check sum for the whole 32 byte block internally so the easiest way to handle this from a driver perspective is to read the whole block starting at address 0x40 to a 32 byte buffer, replace the data in this buffer for the parameters that you want to change, write the whole block back to 0x40+ and then calculate the check sum by adding up every byte in this buffer, mask it with 0xFF and subtract this from 0xFF. Then write this number to 0x60, which triggers the internal date transfer process.

    The other, more "complex" methods use the previous check sum together with the old and new data for only the parameters that you want to change to calculate the new check sum. The end result is the exact same check sum as if you'd calculate it for the whole 32 byte block.

    There's example code in

  • Thanks Dominik and Onyx,

    I have listened to your suggestion and attempted to write 32 bytes of edited parameters back to address 0x40, but I get nacked on my fourth byte of the 32. I have a feeling that this may be because I read all of the data and immediately try to write it back without first sending 0x61, 0x00 followed by 0x3E, 0x52, followed by 0x3F, 0x00.... however, several references do not show this to be necessary. I will inspect my code and look for errors. If you recognize the issue of being nacked on the fourth byte, please let me know.
  • Here is a confirmed working example (I tested this myself today):

    Set Design Capacity to 2000mAh for bq27421G1A (all following two digit registers and addresses are hexadecimal):

    1. Reset (default values)

    2. SET_CFGUPDATE: write 13 00 to registers 00 and 01

    3. Select class "state", block #0: write 52 00 to registers 3E and 3F

    4. Read block: read 32(dec) bytes from registers 40+: 40 00 00 00 00 81 0E DB 0E A8 05 3C 13 60 05 3C 0C 80 00 C8 00 32 00 14 03 E8 01 00 64 10 04 00
        05 3C = 1340mAh. This will be changed to 07 D0 = 2000mAh

    5. Select class "state", block #0: write 52 00 to registers 3E and 3F

    6. Write block: write 32(dec) bytes to registers 40+: 40 00 00 00 00 81 0E DB 0E A8 07 D0 13 60 05 3C 0C 80 00 C8 00 32 00 14 03 E8 01 00 64 10 04 00

    7. Calculate check sum: Add up all 32(dec) bytes from step 6: = 0x06E9. Check sum = 0xFF - (0x06E9 & 0x00FF) = 0xFF - 0xE9 = 0x16

    8. Write check sum to register 60

    9. Select class "state", block #0: write 52 00 to registers 3E and 3F

    10. Read check sum from register 60. This must (and will) return 16

    11. Issue SOFT_RESET: write 42 00 to register 00 and 01

    12. Done!

  • Dominik,

    My read looks very similar to yours, other than the fact that you are showing 31 bytes being read rather than 32. My 32nd byte is 0xAC (strangely similar to the result that I get if I try to read the checksum register twice in a row).

    Is the 0x40 a part of your checksum? In my understanding, you write to 0x40 and then read the next 31 bytes. Should you then include 0x40 as byte 1 in the checksum?

    Also, I continue to get nacked when I attempt to write more than 4 bytes at a time. I thought that this may have had something to do with the fact that I am running at ~115kHz rather than 100kHz, but I added a few up and down clock cycles to my duty cycle, and I still get this issue.  

    I just attempted to checksum with the 0x40 at the beginning and leave out the 0xAC at the end. This did not work. I also attempted to only write to the registers that I wanted to edit, so that I didn't have to write more than three bytes at a time. This also did not work. One reason that this may not have worked is because I did it the following way

    wr 0x3E, 0x52

    wr 0x3F, 0x00

    wr 0x4A, byte1, byte2 (I get nacked here)

    wr 0x4C, byte1, byte2 (Acked here)

    wr 0x50, byte1, byte2 (Acked here)

    wr 0x5B, byte1, byte2 (Acked here)

    My leading suspicion as of now is that I am writing the data back incorrectly. Something about my incremental write command must be wrong, because it nacks my fourth byte.

    Is there something wrong with the following?

    read the 32 bytes,

    wr 0x3E, 0x52

    wr 0x3F, 0x00

    wr 0x40, 0x00, 0x00, 0x00, 0x00,(I get nacked here) 0x81...etc

    Thanks again! 

  • Also, keep in mind that I gave up on looking at my checksum register a long time ago. I just calculated my old checksum to see what it should have been, and it should be 0x53 if I include 0x40 in the checksum and don't invert. Instead of giving me that value, it always gives me zero.

    (Instead of checking if my checksums are equal, I have been storing the variables that I want to change into static variables before I alter them, then I alter them, and then I compare the old and new values. If they are not equal I repeat. On the repeat attempt, the variables should be equal.)

    Can anyone explain why my checksum register only gives a zero?

    Thanks!