2024-10-01 01:10 AM
Hi I was just wondering if someone could help point out where I could be going wrong with my implementation of write NDEF function. This is a very rough implementation but I believe I am following the correct message structure. I know my i2c mem write commands are working as I have tested the addresses. When I use the ST25 Tap app I don't see NDEF storage being populated.
My implementation:
HAL_StatusTypeDef write_ndef_pressure_message(int32_t pressure_mmHg_scaled) {
HAL_StatusTypeDef status;
// Create a buffer for the pressure message (e.g., "123.45 mmHg")
char pressure_str[16]; // Max size for the pressure string (with decimals and unit)
snprintf(pressure_str, sizeof(pressure_str), "%ld.%02ld mmHg", pressure_mmHg_scaled / 100, pressure_mmHg_scaled % 100);
uint16_t message_len = strlen(pressure_str);
// Ensure the total length doesn't exceed the memory limit
if (message_len + NDEF_HEADER_SIZE > 32) {
message_len = 32 - NDEF_HEADER_SIZE; // Limit to 32 bytes (adjust based on available memory size)
}
// 1. Clear User Memory Area 1 (32 bytes for this example)
uint8_t clear_memory[32] = {0}; // Clear memory
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, USER_MEMORY_START, I2C_MEMADD_SIZE_16BIT, clear_memory, 32, HAL_MAX_DELAY);
// Ensure the device is ready for the next operation (check readiness)
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5); // Small delay to allow the device to complete the write
}
// 2. Adjust NDEF Header for the correct payload length
NDEF_Text_Header[2] = message_len; // Set the correct payload length in the NDEF header
// 3. Write the NDEF header to User Memory Area 1
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, USER_MEMORY_START, I2C_MEMADD_SIZE_16BIT, NDEF_Text_Header, NDEF_HEADER_SIZE, HAL_MAX_DELAY);
// Ensure the device is ready for the next operation (check readiness)
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5); // Small delay to allow the device to complete the write
}
// 4. Write the NDEF payload (pressure value as string) right after the header
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, USER_MEMORY_START + NDEF_HEADER_SIZE, I2C_MEMADD_SIZE_16BIT, (uint8_t*)pressure_str, message_len, HAL_MAX_DELAY);
// Ensure the device is ready for the next operation (check readiness)
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5); // Small delay to allow the device to complete the write
}
return status;
}
Thank you.
2024-10-01 08:05 AM - edited 2024-10-01 08:07 AM
Hi,
can you dump the user memory from block #0 to the last block being used by your NDEF and share it with us? You can use the ST25 NFC Tap application to dump the memory content
Rgds
BT
2024-10-01 05:17 PM
2024-10-02 12:19 AM
Hi,
the NDEF message seems to be written starting from block 0:
This is not compilant with NFC Forum T5T technical specification. Block 0 should contain the so-called Capability Container (aka CC). See Application Note AN4911 (ST25DV-I2C, ST25TV16K and ST25TV64K configuration to support a NDEF message).
Rgds
BT
2024-10-16 11:24 PM
Hi,
I just tried to update my code according to the document you sent but it is still not appearing in the NDEF section of the app.
// NDEF Header: Text Record (UTF-8)
uint8_t NDEF_Text_Header[NDEF_HEADER_SIZE] = {
0xD1, // MB, ME, SR, TNF = 0x1 (Well-known type)
0x01, // Type Length = 1 byte (for text)
0x00, // Payload Length (to be updated dynamically based on the pressure value string)
0x54, // Type = 'T' (for text record)
0x02, // UTF-8 encoding, language code length = 2
0x65, // 'e' (for "en" language code)
0x6E, // 'n' (for "en" language code)
0x00
};
// 8-byte Capability Container for ST25DV64K
uint8_t CapabilityContainer[8] = {
0xE2, // Magic number (2-byte address mode)
0x40, // Version + Access (1.x, Read/Write allowed)
0x00, // Reserved
0x00, // Additional feature information
0x00, // Reserved
0x00, // Reserved
0x03, // MLEN high byte (1023 blocks used for NDEF area)
0xFF // MLEN low byte (1023 blocks used for NDEF area)
};
// Function to write the Capability Container (CC) to Block 0
HAL_StatusTypeDef write_capability_container(void) {
HAL_StatusTypeDef status;
// Write the CC to Block 0 (8 bytes)
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, CC_BLOCK, I2C_MEMADD_SIZE_16BIT, CapabilityContainer, 8, HAL_MAX_DELAY);
if (status != HAL_OK) {
// Handle error
return status;
}
// Ensure the device is ready for the next operation
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5);
}
return status;
}
HAL_StatusTypeDef write_ndef_pressure_message(int32_t pressure_mmHg_scaled) {
HAL_StatusTypeDef status;
status = write_capability_container();
// Create a buffer for the pressure message (e.g., "123.45 mmHg")
char pressure_str[20]; // Max size for the pressure string (with decimals and unit)
snprintf(pressure_str, sizeof(pressure_str), "%ld.%02ld mmHg", pressure_mmHg_scaled / 100, pressure_mmHg_scaled % 100);
uint16_t message_len = strlen(pressure_str);
// Ensure the total length doesn't exceed the memory limit
if (message_len + NDEF_HEADER_SIZE > 32) {
message_len = 32 - NDEF_HEADER_SIZE; // Limit to 32 bytes (adjust based on available memory size)
}
// 1. Adjust NDEF Header for the correct payload length
NDEF_Text_Header[2] = message_len; // Set the correct payload length in the NDEF header
// 2. Write the NDEF header to User Memory Area 1
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, NDEF_BLOCK_START, I2C_MEMADD_SIZE_16BIT, NDEF_Text_Header, NDEF_HEADER_SIZE, HAL_MAX_DELAY);
// Ensure the device is ready for the next operation (check readiness)
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5); // Small delay to allow the device to complete the write
}
// 3. Write the NDEF payload (pressure value as string) right after the header
status = HAL_I2C_Mem_Write(&hi2c1, ST25DV_I2C_DATA_ADDRESS, NDEF_BLOCK_START + NDEF_HEADER_SIZE, I2C_MEMADD_SIZE_16BIT, (uint8_t*)pressure_str, message_len, HAL_MAX_DELAY);
// Ensure the device is ready for the next operation (check readiness)
while (HAL_I2C_IsDeviceReady(&hi2c1, ST25DV_I2C_DATA_ADDRESS, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_Delay(5); // Small delay to allow the device to complete the write
}
return status;
}
Any advice for where I am going wrong?
Thanks
2024-10-17 05:03 AM - edited 2024-10-17 07:05 AM
Hi,
block #0 does not have a valid Capability Container and the NDEF TLV seems to start in the middle of the second block:
Your memory should look like:
In this dump, block #0 and block #1contains a valid CC starting with E2 (i.e. support of 2-byte address mode) and the NDEF TLV starts just after the CC (i.e. at the beginning of block #2).
Make sure to follow Application Note AN4911.
Rgds
BT
2024-10-18 09:05 PM
Hi,
I have read AN4911 but I am still having a hard time understanding the NDEF header, namely what values to put.
Could each byte of the example be explained, please?
Thanks
2024-10-22 02:39 AM
Hi,
In the example, block #0 and #1 contain an 8-bytes Capability Container (CC). The various bytes of the CC are described in §3.1 of AN4911. The format of the 8-bytes CC is shown in table 4 of AN4911
Then, the NDEF TLV starts on Block #2:
Rgds
BT