Hi, I am trying to program nvm using SLG46824.The NVM programming code was ported from AN-CM-255 SLG46824_6 MTP Arduino Programming Example (MTP_Programmer).We are trying to develop a code so SLG46824 can be programmed via any host device. By using basic i2c smbus api's we are trying to program nvm. So in our code before writing, the device gets erased properly and even after soft reset,it shows erased data. When we try to program new nvm data, starting from sending control byte, it always returns -1.Are we missing any configuration or any write sequence is mismatched ?? Kindly help to understand the issue.
Thanks
Hi Shalaka,
To debug this issue, first you need to make sure your I2C communication to the SLG46824 is fully functional.(Provide proper pullup resistors on SDA and SCL, choose or start with slower I2C speed etc.)Also, start with only 16 bytes instead of the whole design file.
Have you been able to READ bytes from NVM via I2C, say a known NVM content of previously programmed device?Then you say:>So, in our code before writing, the device gets erased properly and even after soft reset it shows erased data.<<< When you say "the device gets erased properly"So, was the device already in Erased state or did you actually erase it by control codes via I2C.By using something like:
for (uint8_t i = 0; i < 16; i++) { writeReg(controlCode * 8 + 1, 0xE3, 0x80 + i); }
The write command in Arduino sketch writes the data that is saved in the nvmString[] or eepromString[]
When writing data to the SLG46824/6’s NVM, there are three techniques to avoid: ● Page writes with less than 16 bytes ● Page writes with more than 16 bytes ● Page writes that don’t begin at the first register within a page (IE: 0x10, 0x20, etc.)
If any of the above techniques are used, the MTP interface will disregard the I2C write to avoid loading the NVM with incorrect information. The 16 programmed bytes should be in the same page. Any I2C command that does not meet specific requirements willbe ignored and NVM will remain unprogrammed.
We recommend performing an I2C read of the NVM address space after writing to verify correct data transfer.
Hope this helps,
Thank you and Best regards,Renesas Electronics Online Support
Hi,
1.So, was the device already in Erased state or did you actually erase it by control codes via I2C.
>> Device was already programmed at first and then erased was performed by below method.
ret = i2c_smbus_write_byte(file, control_code);
ret = i2c_smbus_write_byte_data(file, 0xE3, (0x80 | i));
And after reset we checked the data was erased.
>> If write performed after erase While sending the control code,it returns -1.
Can you explain the chip level addressing in slg46824.As in above you have metioned (controlCode * 8 + 1).
As far as I have understood, We need to first send the control byte followed by word address and then the data.
In control byte - we have block address - For erase - It should be 00.
For NVM Data config. - It should be 02
What should be the control code in both the cases erase and write ? Our device is present at slave address 0x00.
First, the pseudo code I quoted is in context to some other code. Please don't take it literally.You are correct, normally, you need to first send the control byte followed by word address and then the data.
For Erase:Since you are dealing with writing just one register ERSR, it is easy:Setting b7 bit to “1” will start in internal erase cycle on the page.So, what you did works for erase: i2c_smbus_write_byte_data(file, 0xE3, (0x80 | i));
Control code for write:For I2C slave_address = 0x00; start with control_code = 0x00;Then, control_code |= NVM_CONFIG; //#define NVM_CONFIG 0x02 for NVM write
Now, assuming that you are able to read and write using I2C without issues, but you are not able to program NVM,it is not clear if you checked I2C ACK for every one of the 16 bytes you sent or you just say your code returns -1.In my first response, I mentioned under what conditions it can return NACK.This sounds like code implementation issue.I strongly suggest follow the details of In-System Programming guidelines described here ==>https://www.renesas.com/us/en/document/mat/system-programming-guide-slg468246
Best regards,
Renesas Electronics Online Support
Note that you need to call (per page) i2c_smbus_write_block_data() passing 16 bytes rather than calling i2c_smbus_write_byte() or i2c_smbus_write_byte_data() 16 times.
I guess we need to see more of your code.
After following all instructions, for write operation I performed below steps -
(slave address =0 ==> so control code =0, word_address = 2, write bit- 0 - so control_byte turns out to be 0x04 )
nvmString contains each row data as below-
__u8 nvmString0[16] = {0x8C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00};
int ret = 0;int control_byte = 0x04;int SlaveAddr = 0x00;
int addressForAckPolling = 0;sleep(2);
for (int i = 0; i < 12; i ++) { ret = i2c_smbus_write_byte(file, control_byte); if (ret < 0) { printf("Failed to write control code %d\n", ret); return ret; } ret = i2c_smbus_write_i2c_block_data(file, i << 4, 16, nvmString[i]); if (ret < 0) { printf("Write byte Data failed %d\n", i); return ret; }
if (ackPolling(addressForAckPolling) == -1) { return -1; } else { usleep(20); } }
Can you help with below queries -
1. Not able to write after page 11, block data write return value is -1(that's why iterating loop till 12). According to data sheet i2c addressing mapping - page 12 , 13 are reserved so it cannot be programmed ? but if that is the case page 4,5 is also reserved so write block data should fail at that particular page also, but it doesn't. Please correct if my understanding is wrong and let me understand why I am not able to program from page 12.
2. In write function - Before resetting, read 12 pages which was written from above logic- gives the new nvm written data properly.
3. After reset, it always shows erased data - not persisting new nvm data.So concluding write failed.
Please help me to understand, if missing any write sequence or how to trace the issue.
There are multiple issues with that code:- nvmString0 has only 16 bytes, but you write 12*16 bytes- nvmString0[i] is an __u8, not a pointer to 16 __u8 values- use nvmString0 + i*16 instead (after enlarging nvmString0)- do not write the control_byte with i2c_smbus_write_byte(), it's the I²C address and passed in struct i2c_client- control_byte is wrong, it writes to volatile memory. Use (addr<<3)|2 instead.
I have mentioned only page 0 data above using nvmString0 just for refernece. Similarly I do have other 16 pages data and those are stored in diff array as nvmString1,nvmString2 etc..
__u8 nvmString1[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
.....
Data is passed using below pointer -
__u8 *nvmString[] = { nvmString0,nvmString1,nvmString2,nvmString3,nvmString4,nvmString5,nvmString6,nvmString7,nvmString8,nvmString9,nvmString10,nvmString11,nvmString12,nvmString13,nvmString14,nvmString15};
ret = i2c_smbus_write_i2c_block_data(file, i << 4, 16, nvmString[i]);
In for loop I'm using *nvmString containing address of the particular page array.
Hope It's clear now.
2. do not write the control_byte with i2c_smbus_write_byte() -- > How should I pass this address then.Can you explain this Use (addr<<3)|2 instead.
That's in the code you haven't shown us. Probably you need to do this where ADDR is the current address of the SLG46824:
file->addr = (ADDR << 3) | 2; // NVM
control_code = (ADDR << 3) | 2; // NVM
Rather than sending control_byte via i2c_smbus_write_byte used write(file,control_code, 1) instead. Still new NVM data doesn't persist after reset. Before reset I can see the new nvm data in i2cdump.
For NVM write from QC , I send control_code = slave_address << 3 | (NVM_CONFIG).NVM_CONFIG is 0x02.
In word address - A3 to A0 is set to 0 A4 to A7 set according to page and data is sent page wise.
Page data is written successfully, read to verify the data written. But after reset, data doesn't persist. Is it possible data is not written to NVM rather to RAM due to which it is not persisting after reboot ? Is above mentioned way is appropriate to select NVM space or something is missing.
Also Is it possible to have a call/debug session to expedite the process and understand the issue?