Tool/software:
*I edited because I found a mistake in my code, but still not working.*
Hi,
I am programming the fuel gauge and I am entering in calibration mode by accessing UNSEALED mode. However, when I read the CONTROL_STATUS register (by sending {0x00, 0x01, 0x00, 0x00}) I always get 0x0000. This is how I am doing it:
This is the function to enable CALIBRATION mode:
void gau_enable_calib(void)
{
uint8_t u8OperationConfALowW[2];
uint8_t u8OperationConfAHighW[2];
uint8_t u8AccumW[2];
// uint8_t u8OpConfAR;
uint8_t u8AccMode = 0xA5;
uint8_t u8LenW[2];
uint8_t u8ChecksumW[2];
uint8_t u8GauStartW[3];
uint8_t u8EnableCalW[3];
bool boolStatusAccumW = false;
bool boolStatusEnableCal = false;
bool boolStatusGauStartW = false;
/*Enable DF write*/
gau_flash_write_enable();
/*Manufacturer access control Operation Config A decomposition addresses*/
gau_MAC_decomp(u8OperationConfALowW, u8OperationConfAHighW, u16OperationConfigA);
/*Gauge start address decomposition*/
gau_address_decomp(u8GauStartW, u16GauStart);
/*Enable calibration address decomposition*/
gau_address_decomp(u8EnableCalW, u16EnableCal);
/*Access Operation Config A in little endian format*/
gau_flash_access(u8OperationConfALowW, u8OperationConfAHighW);
/*MAC data to change to ACCUMULATOR mode*/
u8AccumW[0] = 0x40;
u8AccumW[1] = u8AccMode;
/*Change to ACCUMULATOR mode*/
boolStatusAccumW = SERCOM4_I2C_Write(u8GaugeAddrW, u8AccumW, sizeof(u8AccumW));
while(SERCOM4_I2C_IsBusy());
uint8_t u8Checksum = ~(u8OperationConfALowW[1] + u8OperationConfAHighW[1] + u8AccMode) & 0xFF;
/*Write Operation Config A checksum*/
gau_checksum_get_write(u8Checksum, u8ChecksumW);
/*Write Operation Config A length*/
gau_length_get_write(u8LenW, u8OperationConfALowW[1], u8OperationConfAHighW[1], u8AccMode, u8Checksum, 0, 0, 0);
/*Enable calibration*/
boolStatusEnableCal = SERCOM4_I2C_Write(u8GaugeAddrW, u8EnableCalW, sizeof(u8EnableCalW));
while (SERCOM4_I2C_IsBusy());
/*Gauge enable (PA18 in final product and demo) HIGH*/
PORT_PinSet(PORT_PIN_PA18);
boolStatusGauStartW = SERCOM4_I2C_Write(u8GaugeAddrW, u8GauStartW, sizeof(u8GauStartW));
while(SERCOM4_I2C_IsBusy());
}
And the function where I try to access UNSEALED mode is this one:
void gau_flash_write_enable(void)
{
uint8_t u8Unsealed1W[3];
uint8_t u8Unsealed2W[3];
uint8_t u8BlockDataW[2];
bool boolStatusUnsealed1W = false;
bool boolStatusUnsealed2W = false;
bool boolStatusBlockDataW = false;
/*Control and UNSEALED mode step 1 decomposition addresses*/
gau_MAC_decomp(u8Unsealed1LowW, u8Unsealed1HighW, u16UnsealedMode1);
/*Control and UNSEALED mode step 2 decomposition addresses*/
gau_MAC_decomp(u8Unsealed2LowW, u8Unsealed2HighW, u16UnsealedMode2);
/*Block Data control addresses*/
u8BlockDataW[0] = BLK_DATA_CTRL;
u8BlockDataW[1] = 0x00;
/*Enter UNSEALED mode*/
gau_flash_access(u8Unsealed1LowW, u8Unsealed1HighW);
gau_flash_access(u8Unsealed2LowW, u8Unsealed2HighW);
/*Enable writing in DF*/
boolStatusBlockDataW = SERCOM4_I2C_Write(u8GaugeAddrW, &u8BlockDataW[0], sizeof(u8BlockDataW));
while(SERCOM4_I2C_IsBusy());
}
gau_MAC_decomp() function is for decomposing the value 0x0414 and 0x3672 from Unseal Step 1/2 and sending it with little endian through 0x3E and 0x3F. What is the purpose of FullUnseal Step 1/2, by the way?
Carlos
Hi Carlos,
There are certain cmds available when the device is sealed, there are more in unseal mode and all cmds are available in unseal full access mode.
Was the unseal key changed at any point?
Regards,
Diego
Hi Diego,
Do you mean if I have overwritten it from the memory? If so, the answer is no, because u16UnsealedMode1 and u16UnsealedMode2 were declared above with the values directly, I don't access by address so they are "0x0414" and "0x3672".
It's true that once, by mistake I was passing the address explicitly instead of default values in those variables. But could that have been a problem?
I added a 5-ms delay after each gau_flash_access() call if that helped. Also, I verified the CONTROL_STATUS register inside the function gau_flash_write_enable() after enabling DF write with BlockDataControl(). I am getting 0x0000 (not \NUL \NUL) which is the problem I have; I think the value should be different from 0x0000 (at least having a 1 in bit 14 for UNSEALED mode).
Should I expect the value to be in big endian or little endian? The technical reference manual (sluubh1c.pdf) doesn't specify it. Same for the commands Voltage(), StateOffHealth() and all those.
Thanks.
Regards,
Carlos
Hello Carlos,
Data returned from the gauge will be in little endian format.
It's true that once, by mistake I was passing the address explicitly instead of default values in those variables. But could that have been a problem?
Yes, it is possible that this could have changed the keys.
Regards,
Adrian
Hi Adrian,
So is it crashed? Now it's useless the fuel gauge? I mean, I didn't rewrite the unseal keys, I put as values for BlockDataControl() the addresses instead of default values, as if I write any other value instead of the correct one. Here:
Thanks.
Regards,
Carlos
Hello Carlos,
Are you able to test out the functionality of your code on a new unit?
Regards,
Adrian
Hello Adrian,
By the moment I can't test it in a new unit. I am trying to reach TI feedback from the SLUUBH1C document because there are many things which are confusing. I still don't know what I have to send for reading CONTROL_STATUS register. I have also tried to RESET and GAUGE_START just before reading it and I get 0x0000, which makes no sense.
Then, I send BlockDataControl() as 0x62 0x00 as seen below and then I access UNSEALED mode in little endian.
After that, I read again CONTROL_STATUS register, and as previously it gives 0x0000. Why am I not making any change to that register? As technical reference manual is very interpretable, I have tried different things but I always read the same.
It would be very helpful if you could take a look at the screenshots, please.
As a comment, I am supplying my PCB with Power Profiler Kit II from Nordic, not a real battery. Is that a problem for write/read?
Thanks.
Carlos