Skip to main content
Skip table of contents

20.0 Internal Flash [T-Series Datasheet]

Overview

T-series devices have non-volatile flash memory. This guide will often refer the flash memory as "internal flash".

Internal flash memory is divided into two regions:

  • The User Area - For storing user-data.

  • The Reserved Area - Used to store important device information such as calibration constants.

The size of the internal flash varies by device:

Device

Internal Flash Size

User Area Size

Reserved Area Size

T4

4 MB

2 MB

2 MB

T7

4 MB

2 MB

2 MB

T8

8 MB

4 MB

4 MB

Subsections

Flash Addresses

Internal flash is addressed by byte, but accessed by 32-bit values. That means that the first value is at address zero and the second is at address 4. (These are flash addresses—not to be confused with Modbus addresses.)

Following are some important flash addresses:

T4/T7

Address Name

Address

Length

Key

User Area

0x000000

2 MB

0x6615E336 (1712710454 in decimal)

Reserved Area

0x200000

2 MB

N/A

Calibration Constants (in Reserved Area)

0x3C4000

4 kB

0x43A24C42 (1134709826 in decimal)

T8

Address Name

Address

Length

Key

User Area

0x000000

4 MB

0x6615E336 (1712710454 in decimal)

Reserved Area

0x600000

4 MB

N/A

Calibration Constants (in Reserved Area)

0x687000

4 kB

0xA7863777 (2810591095 in decimal)

Reading

To read from flash, write the desired address to INTERNAL_FLASH_READ_POINTER and then read an even number of registers from INTERNAL_FLASH_READ:

To read a large number of registers from INTERNAL_FLASH_READ (such as more than ~25 registers), you must split the read into multiple packets while updating INTERNAL_FLASH_READ_POINTER each time. See the LJM explanation for how to perform large reads.

Writing and Erasing

Key

For a region to be written to or to be erased, the key for that region must be written to the INTERNAL_FLASH_KEY register:

The key prevents accidental overwrites. The value in INTERNAL_FLASH_KEY will be cleared when the Modbus packet that wrote it has been fully processed, so INTERNAL_FLASH_KEY must be written in the same packet that does INTERNAL_FLASH_WRITE or INTERNAL_FLASH_ERASE. The LJM Multiple Value functions simplify this. The LJM Multiple Value functions do not correctly split large reads (such as more than ~15 registers), so see the LJM explanation for how to perform large writes.

Writing

To write to flash, the area to be written to must first be erased. Once erased, write the key for the desired region to INTERNAL_FLASH_KEY, write the desired address to INTERNAL_FLASH_WRITE_POINTER, and then write an even number of registers to INTERNAL_FLASH_WRITE:

Erasing

Flash is erased 4 kB at a time. Erasing sets all bits to 1. To erase a 4 kB region, write the key for the desired region to INTERNAL_FLASH_KEY and the desired address to INTERNAL_FLASH_ERASE:

The address will be rounded down to the nearest 4 kB boundary. Boundaries are easy to identify when the address is displayed in hexadecimal because the lower three digits will be zero. 4 kB is hexadecimal is 0x1000.

Endurance

Flash memory can only be erased so many times before bit errors will start to occur; it is important not to erase or write flash needlessly. Typical life of flash memory is at least 10,000 cycles.

Examples

Internal Flash Examples - c#

// Erase address 0

numFrames = 2

aNames[0] = "INTERNAL_FLASH_KEY"

aNames[1] = "INTERNAL_FLASH_ERASE"

aWrites[0] = LJM.CONSTANTS.WRITE

aWrites[1] = LJM.CONSTANTS.WRITE

aNumValues[0] = 1

aNumValues[1] = 1

aValues[0] = 1712710454

aValues[1] = 0

LJM.eNames(handle, numFrames, aNames, aWrites, aNumValues, aValues, errorAddress)

// Write address 0 = 1234,

// write address 4 = 5678

numFrames = 3

aNames[0] = "INTERNAL_FLASH_KEY"

aNames[1] = "INTERNAL_FLASH_WRITE_POINTER"

aNames[2] = "INTERNAL_FLASH_WRITE"

aWrites[0] = LJM.CONSTANTS.WRITE

aWrites[1] = LJM.CONSTANTS.WRITE

aWrites[2] = LJM.CONSTANTS.WRITE

aNumValues[0] = 1

aNumValues[1] = 1

aNumValues[2] = 2

aValues[0] = 1712710454

aValues[1] = 0

aValues[2] = 1234

aValues[3] = 5678

LJM.eNames(handle, numFrames, aNames, aWrites, aNumValues, aValues, errorAddress)

// Read address 0 and address 4

numFrames = 2

aNames[0] = "INTERNAL_FLASH_READ_POINTER"

aNames[1] = "INTERNAL_FLASH_READ"

aWrites[0] = LJM.CONSTANTS.WRITE

aWrites[1] = LJM.CONSTANTS.READ

aNumValues[0] = 1

aNumValues[1] = 2

aValues[0] = 0

aValues[1] = 9999

aValues[2] = 9999

LJM.eNames(handle, numFrames, aNames, aWrites, aNumValues, aValues, errorAddress)

Console.WriteLine(aValues[1], aValues[2])

// Output:

// 1234 5678

For an embedded Lua scripting example see write_read_flash.lua.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.