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.

BQ27220: MACDataLen comes up as 36 byte transfer

Part Number: BQ27220
Other Parts Discussed in Thread: BQSTUDIO

Hello,

I am following the example in Chapter 6.1 in the SLUUBD4 BQ27220 user manual.

Steps 1 – 7 are working fine, but the data length in Step 8 (MACDataLen) returns 36.  Since only 32 bytes (max) are possible for data transfer in the MACData buffer, how is 36 happening? 

I have also tried setting MACDataLen to 32 before executing step 5, but 36 still gets returned.

The routine (attached) that I am having trouble with is BQ27220::get_data_32(....).  Done on mbed.org K64F platform

uint32_t BQ27220::get_data_32(BQ27220_TypeDef& dataSTR, uint16_t sub_cmmd, int length)
{   
	if(length > 32) length = 32;	
	i2c_Buf[0] = BQ_SUB; //0x3e
	i2c_Buf[2] = sub_cmmd >> 8;
	i2c_Buf[1] = sub_cmmd & 255;
	//pc.printf("dat-32a: %02x %02x %02x \r\n", i2c_Buf[0], i2c_Buf[1], i2c_Buf[2]);
	_i2c.write((int)BQ27220_ADDR, i2c_Buf, 3, false);
	wait_us(66);
	Thread::wait(5);
	
	i2c_Buf[0] = BQ_MACDATASUM; //0x60
	_i2c.write((int)BQ27220_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27220_ADDR + 1, i2c_Buf, 1, false);
    wait_us(66);
	Thread::wait(5);
	dataSTR.macSumReg = dataSTR.i2c_Bufx[0];
	//pc.printf("dat-32c: %02x \r\n", i2c_Buf[0]);
	
	i2c_Buf[0] = BQ_MACDATALEN;  //0x61
	_i2c.write((int)BQ27220_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27220_ADDR + 1, i2c_Buf, 1, false);
	wait_us(66);
	Thread::wait(5);
	dataSTR.macLenReg = dataSTR.i2c_Bufx[0];
	uint8_t lx = dataSTR.macLenReg;
	//pc.printf("dat-32L: %02x \r\n", i2c_Buf[0]);
	if(lx > length) lx = length;
	
	i2c_Buf[0] = BQ_MACDATA; //0x40
	_i2c.write((int)BQ27220_ADDR, i2c_Buf, 1, true);
    _i2c.read((int)BQ27220_ADDR + 1, i2c_Buf, length, false);
	wait_us(66);
	Thread::wait(5);
	for(int i = 0; i < length; i++) {
		dataSTR.macData[i] = dataSTR.i2c_Bufx[i];
		pc.printf("%02x ", dataSTR.i2c_Bufx[i]);
	}
	
	dataSTR.checksum = calc_checksum(dataSTR, lx);
	pc.printf(" mdl: %3d  mdcs: %02x  cs: %02x \r\n", dataSTR.macLenReg, dataSTR.macSumReg, dataSTR.checksum);
	return ((uint32_t)dataSTR.subReg); 
}

  • The data length contains the 2 bytes address (register 0x3E/0x3F) and the check-sum register (0x60) and length register (0x61). So the total is 36 bytes.

    Note that the example in 6.1, step 13 also shows a length of 0x24 = 36 bytes.

  • Does the check-sum include in its calculation 0x3e, 0x3f and 0x61?
  • Now I am running into checksum calculation differences.  Below is a dump of all of the data areas in the BQ27220, 4000-41ff, 4800-49ff and 9100-92ff.

    The beginning of each line is the address (0x3e, 0x3f), 32 bytes of hex data, the length mdl: (decimal), the BQ checksum mdcs: (hex) and my checksum ccs: (hex)

    I added comma delimiters so the data can be put into a .csv file.  The BQ27220 is in full_access mode.

    OS,            0422,      ->, CFGUPDATE INITCOMP SEC0 (FULL)

    Only about 1/4 of the checksums (BQ27220 vs mine) are the same. I assume that some of the differences are to certain data areas where no real data actually exists.  However, there are areas that have valid data, but the checksums still do not match.  I put in the data into a spreadsheet and my calculations all appear to be correct. I do breakout the address (0x3e and 0x3f) into individual bytes for the checksum calculation.

    OTP ROM data
    4000,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: bf  ccs: bf
    4020,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 9f  ccs: 9f
    4040,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 7f  ccs: 7f
    4060,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 5f  ccs: 5f
    4080,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 3f  ccs: 3f
    40a0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 1f  ccs: 1f
    40c0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: ff  ccs: ff
    40e0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: df  ccs: df
    4100,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: be  ccs: be
    4120,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 9e  ccs: 9e
    4140,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 7e  ccs: 7e
    4160,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 5e  ccs: 5e
    4180,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 3e  ccs: 3e
    41a0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 3e  ccs: 1e
    41c0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 3e  ccs: fe
    41e0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 3e  ccs: de

    ROM default data
    4800,->,1c,98,02,d3,ff,b9,30,01,00,ef,05,11,05,01,00,00,10,01,00,3c,00,50,3c,00,64,3c,00,20,00,00,00,00, mdl: 36  mdcs: 5f  ccs: a1
    4820,->,14,00,00,01,c2,00,32,00,c8,10,68,00,00,00,64,00,19,28,04,84,10,00,00,01,09,00,00,96,00,af,02,20, mdl: 36  mdcs: 81  ccs: a0
    4840,->,00,14,05,00,0a,05,00,32,01,c2,14,14,00,08,09,f6,00,01,00,3c,00,3c,00,4b,00,28,00,3c,3c,01,02,26, mdl: 36  mdcs: 80  ccs: 9e
    4860,->,02,01,f4,02,58,02,02,26,f6,fc,18,32,0c,4e,02,0c,b2,04,14,36,72,ff,ff,ff,ff,00,00,01,2c,02,bc,9b, mdl: 36  mdcs: 7e  ccs: 44
    4880,->,c7,01,00,00,80,08,02,77,0a,01,80,01,00,08,18,14,05,dc,64,14,14,00,00,00,c8,00,00,64,64,08,0e,74, mdl: 36  mdcs: 24  ccs: 27
    48a0,->,00,64,1f,40,00,00,3c,02,3c,5a,0a,0c,8c,8c,0b,b8,0c,1c,00,05,10,68,10,04,64,5f,0c,80,0c,e4,06,08, mdl: 36  mdcs: 07  ccs: 89
    48c0,->,10,68,10,04,64,5f,00,10,2a,0b,b8,0b,b8,03,84,0e,74,00,64,0e,9f,00,95,03,63,0f,be,01,3c,09,00,00, mdl: 36  mdcs: 69  ccs: c0
    48e0,->,0b,d7,01,0d,39,01,0d,ad,01,10,4d,0f,cb,0f,55,0e,ed,0e,8d,0e,48,0e,23,0d,fe,0d,bb,0d,6f,0a,99,00, mdl: 36  mdcs: a0  ccs: 48
    4900,->,00,08,98,08,98,18,c0,0e,74,00,64,0e,9f,00,95,03,63,0f,be,01,3c,09,00,00,0b,d7,01,0d,39,01,0d,ad, mdl: 36  mdcs: 27  ccs: 19
    4920,->,01,10,4d,0f,cb,0f,55,0e,ed,0e,8d,0e,48,0e,23,0d,fe,0d,bb,0d,6f,0a,99,00,00,08,98,08,98,18,c0,0e, mdl: 36  mdcs: f9  ccs: c5
    4940,->,74,00,64,0e,9f,00,95,03,63,0f,be,01,3c,09,00,00,0b,d7,01,0d,39,01,0d,ad,01,10,4d,0f,cb,0f,55,0e, mdl: 36  mdcs: a5  ccs: 55
    4960,->,ed,0e,8d,0e,48,0e,23,0d,fe,0d,bb,0d,6f,0a,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 35  ccs: 55
    4980,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 35  ccs: 36
    49a0,->,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, mdl: 36  mdcs: 16  ccs: 16
    49c0,->,00,00,00,00,00,00,00,00,02,20,00,03,00,04,00,00,00,00,00,00,00,00,00,81,01,02,09,00,45,12,40,03, mdl: 36  mdcs: f6  ccs: a6
    49e0,->,00,00,00,00,00,00,00,00,02,20,00,03,00,04,00,00,00,00,00,00,00,00,00,81,01,02,09,00,45,12,40,03, mdl: 36  mdcs: 86  ccs: 86

    RAM data
    9100,->,00,af,ff,ff,ff,ec,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,f2,00,00,00,00,00, mdl: 36  mdcs: 25  ccs: e4
    9120,->,00,00,00,00,00,00,00,7f,ff,00,00,00,f2,be,e8,99,18,bb,f0,83,67,0c,b2,43,cf,2f,f1,00,0b,9d,00,00, mdl: 36  mdcs: c4  ccs: 5a
    9140,->,00,00,0c,e3,0c,e3,ff,ff,00,00,00,00,00,00,0c,e3,00,00,0b,9c,0b,ac,00,00,00,00,00,2b,7f,fa,c3,c3, mdl: 36  mdcs: 3a  ccs: db
    9160,->,ff,f0,0b,d6,7e,73,b6,45,93,0a,a5,22,00,f2,00,5a,0b,b8,04,56,64,09,09,64,00,00,00,00,00,00,33,76, mdl: 36  mdcs: bb  ccs: 02
    9180,->,00,00,00,00,00,05,86,22,9a,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,cb,d4,1a,05, mdl: 36  mdcs: e2  ccs: e9
    91a0,->,d4,86,4a,c6,b4,c2,6e,2b,03,7c,01,48,fd,a3,f6,75,12,58,2d,b7,1c,98,02,d3,ff,b9,30,01,00,ef,05,11, mdl: 36  mdcs: c9  ccs: bd
    91c0,->,05,01,00,00,10,01,00,3c,00,50,3c,00,64,3c,00,20,00,00,00,00,14,00,00,01,c2,00,32,00,c8,10,68,00, mdl: 36  mdcs: 9d  ccs: c6
    91e0,->,00,00,64,00,19,28,04,84,18,00,00,01,09,00,00,96,00,af,02,20,00,14,05,00,0a,05,00,32,01,c2,14,14, mdl: 36  mdcs: a6  ccs: 93
    9200,->,00,08,09,f6,00,01,00,3c,00,3c,00,4b,00,28,00,3c,3c,01,02,26,02,01,f4,02,58,02,02,26,f6,fc,18,32, mdl: 36  mdcs: 72  ccs: 22
    9220,->,0c,4e,02,0c,b2,04,14,36,72,ff,ff,ff,ff,00,00,01,2c,02,bc,9b,c7,01,00,00,80,08,02,77,0a,01,80,01, mdl: 36  mdcs: 02  ccs: 9c
    9240,->,00,08,18,14,05,dc,64,14,14,00,00,00,c8,00,00,64,64,08,0e,74,00,64,1f,40,00,00,3c,02,3c,5a,0a,0c, mdl: 36  mdcs: 7c  ccs: c5
    9260,->,8c,8c,0b,b8,0c,1c,00,05,10,68,10,04,64,5f,0c,80,0c,e4,06,08,10,68,10,04,64,5f,00,10,2a,0b,b8,0b, mdl: 36  mdcs: a5  ccs: d5
    9280,->,b8,03,84,0e,74,00,64,0e,9f,00,95,03,63,0f,be,01,3c,09,00,00,0b,d7,01,0d,39,01,0d,ad,01,10,4d,0f, mdl: 36  mdcs: b5  ccs: bc
    92a0,->,cb,0f,55,0e,ed,0e,8d,0e,48,0e,23,0d,fe,0d,bb,0d,6f,0a,99,00,25,d4,20,b5,69,13,00,8f,63,40,f0,cb, mdl: 36  mdcs: 9c  ccs: 58
    92c0,->,a4,36,41,b7,63,cb,5f,c6,c2,ff,d5,ad,3e,56,2f,31,70,8d,26,89,1a,12,f5,9c,a4,d9,0b,c8,cb,96,18,19, mdl: 36  mdcs: 38  ccs: 06
    92e0,->,3c,ef,55,4b,f8,c4,d0,19,18,0e,c5,7c,66,2a,10,68,11,df,95,c4,b3,b7,73,01,15,ef,f6,ad,50,eb,47,b1, mdl: 36  mdcs: e6  ccs: ad

  • The check sum is the 255 - the 8bit wide sum of the starting address and the block bytes.

    Example:

    W: AA 3E B4 91 FD 00 00 03 00 00 00 00 CB D4 1A 05 D4 86 4A C6 B4 C2 6E 2B 03 7C 01 48 FD A3 F6 75 12 58 2D B7

    W: AA 60 62 24

    Adding up B4 91 ... B7 equals 0D9D, so the check sum is 0xFF - 0x9D = 0x62

  • So far, I have not tried to write to RAM, only read.

    I put the above numbers into my spreadsheet and get the same results (0x62). I also dummied up some code with the numbers above and the checksum also comes out as 0x62.

    Q: Is the checksum valid when reading the 36 bytes from the BQ27220 ?
  • The check sum validity doesn't depend on how many bytes are read from the gauge. It will always return the check sum for the whole block.

  • Here is a more detailed "dump" of the entire BQ27220 data fields (like above).  To the best of my knowledge, the BQ27220 on this eval board has not been modified in any way.  I put the data into a spreadsheet.  Since Excel can to math in HEX very well, I had to convert the raw data to decimal (green formula) in the line directly below the raw data (orange lines).  Then I perform the checksum at the end of the line, (summed line, stripped and subtracted from 0xff and converted the result back to a hex byte) (blue formula). So, What I'm doing in the spreadsheet equates to what I am doing in my code since the results are identical.

    I still don't understand why my results are different from the BQ27220's checksum results in most cases (red text).

  • I cannot tell if the spreadsheet attached or not.
  • The gauge will auto increment its data pointer so you need to take this into consideration when reading the check sum.

    An easy method to update a specific parameter is this sequence:

    1. Enter CFG_UPDATE mode
    2. Write the address AND the parameter data to 0x3E+ (auto increment)
    3. Calculate the check sum: 0xFF - (sum of address and data) OR 0xFF
    4. Write the check sum to 0x60 and the total length of (address + parameter data + check sum + length) to 0x61
    5. Exite CFG_UPDATE mode

    Example: Set OT Chg Time to 8 seconds:
    OT Chg Time address = 0x9234
    Data = 0x08

    2. write 0x34 0x92 0x08 to registers starting at 0x3E
    3. check sum = 0xFF - (0x34 + 0x92 + 0x08) OR 0xFF = 0xFF - 0xCE = 0x31
    4. write 0x31 to 0x60 and 0x05 (=2 bytes address, 1 byte data, 1 byte check sum, 1 byte length) to 0x61

  • I did as above, but the returned checksum from 0x60 is always 0x40 off.  Of course, the data doesn't change either

    final_cs2:31

    cfg_OT_ct_cmmd: ->  3e 92 34 08

    cfg_OT_ct_cs:   ->  60 31

    cfg_OT_ct_len:  ->  61 05

    csl: f1

    ll: 05

    92,34,->,c7,01,00,00,80,08,02,77,0a,01,80,01,00,08,18,14,05,dc,64,14,14,00,00,00,c8,00,00,64,64,08,0e,74,

    Example changing to 3 instead of 8

    final_cs2:36

    cfg_OT_ct_cmmd: ->  3e 92 34 03

    cfg_OT_ct_cs:   ->  60 36

    cfg_OT_ct_len:  ->  61 05

    csl: f6

    ll: 05


    92,34,->,c7,01,00,00,80,08,02,77,0a,01,80,01,00,08,18,14,05,dc,64,14,14,00,00,00,c8,00,00,64,64,08,0e,74,

  • I am still receiving incorrect checksum results back from the BQ27220. 

    1. When I send the command above (0x9234), the checksum results are always off, but by multiples of 0x10 and the results change on almost every time I run the test (see below). 

    2. With the example in 6.1 of the user guide (0x929F), I still get a checksum error, but the results returned by the BQ27220 never change. 

    3. Finally, I can write to the Operation Configuration A register (0x9206) and it always returns the correct checksum.

    What I am doing:

    a test I created:                                                bq t
    i2c write to 0x3E (0x92, 0x34, 0x08)               ram124_cmmd: ->  3e 92 34 08
    calculated checksum                                       final_cs2: 31
    i2c write to 0x60 (0x31)                                   ram124_cs:   ->  60 31
    i2c write to 0x61 (0x05)                                   ram124_len:  ->  61 05
    i2c readback from 0x60                                   get_cs: a6
    i2c readback from 0x61                                   get_ln: 05

    //example 0x08 to addr:0x9234

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: 11
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: 11
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: 11
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: 11
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: d1
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: b1
    get_ln: 05

    bq t
    ram124_cmmd: ->  3e 92 34 08
    final_cs2: 31
    ram124_cs:   ->  60 31
    ram124_len:  ->  61 05
    get_cs: b1
    get_ln: 05

    //example 0x04b0 to addr:0x929f

    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

    bq t
    ram124_cmmd: ->  3e 92 9f b0 04
    final_cs2: 1a
    ram124_cs:   ->  60 1a
    ram124_len:  ->  61 06
    get_cs: e3
    get_ln: 06

  • Please try my previous example step by step. I verified this on the EVM with bqStudio / advanced communication. Please try this first in bqStudio with advanced communication. Once you can successfully perform a parameter update, then translate this to code and debug this by analyzing any differences.

    There must be something obscured in your implementation that prevents the gauge from updating data and check-sums as expected.

  • I finally got it to work late last night, but with the following conditions:

    1. Data transfers MUST fill and transfer the whole MACData buffer (32 bytes) in a read-modify-write set of operations.  Partial transfers (like the example above with a length of 0x05) do not work.

        1a. Is it possible that bqStudio hides this step from you?

    2. I must subtract 0x20 from the final calculated checksum before putting the result in MACdataSum (0x60).

    Thanks, this issue can be closed now,

    ...kevin

  • That's very good news!!

    About 1a: I've been able to execute single parameter updates without bqStudio so I don't think that this is due to bqStudio.
    About 2: That's strange. I don't know why this would be required?

    .Dominik.
  • hi,

    Need some clarification:

    1. Can any expert confirm if the #1. Data transfers MUST fill and transfer the whole MACData buffer (32 bytes) in a read-modify-write set of operations.  Partial transfers (like the example above with a length of 0x05) do not work?
    2. If the answer in #1 is partial transfer can be done. Then the next question is

      In BQ27220 TRM Page 65/88 Application example, I need to update “Data_len” at step 13. How to calculate this “Data_len”? Is it the same value read at step 8 or we need to calculate it based on the intermediate steps 9 to 12? I don't see step 9 to 12 got alter the data_len value. does that means data_len is the same value read at step8 and step 13?   

    best regards,
    kpk