Checks in the public Write() Method in DCD class

Hi all,

Can anyone help me make sense as it does not to me. In the above mentioned in DCD class we read: [Note: This is the write method in the public not in private section of the class]

Result write(const Address offset, const void* data, size_t length)
{
    if (offset >= Length)
        return DCD_INVALID_OFFSET;
    if (offset+length > Length)
        return DCD_INVALID_LENGTH;
    if (!length)
        return DCD_SUCCESS;

the first two checks are one stranger than the other and I can’t make sense of them: For starters the first one is implying that the offset of a field in the application_dct_t must not be greater than the size of that field which does not make any sense as they are unrelated quantities. The next check is even stranger: implying the offset of the field added to the length of the field should be less than or equal to the length of the field!!!

Thank you in advance!

Length is not the length (mark L vs l - C/C++ is case sensitive) of the field but the over-all length of the space occupied by all fields and neither the start nor the end of the field are allowed to hang over that limit.

1 Like

That’s embarrassing. Thanks @ScruffR. Sometimes an extra pair of eyes do wonders. I probably would not have spotted that if I stared at it for another week straight.

While we are on the topic I would appreciate if you or someone could clarify:

Firstly, Is there a reason why every write of any of the application_dct structure elements involves copying the entire current sector to the alternate sector with only the element in question over-writting its own corresponding offset and length, finally invalidating the current sector and on the next write the Sectors get swapped again and so on? Is it to balance the wear and tear of these two FLASH regions?

Secondly, looking at the binary on the Photon on the addresses which correspond to DCD (0x8004000 to 0x800C000) I am trying to figure out where the structure such as applicaiton_dct, etc are and I would have thought finding a valid header with a valid seal or watermark would have been good land marks to look for, but to my surprise I cannot find them, or is there a trickier or more elaborate way to locate them?

First question:
Flash writes can only clear bits but not set them. In order to set bits you need to perform a page erase (setting each and every bit in the page - which is actually the action that causes flash wear) and then clear all the bits supposed to read 0.

For the second I’d have to refer you to @BDub :wink:
But I’d guess, since we (or rather the copiler/linker) know where it is we don’t need a mark, since direct access is not the intended way.

1 Like

You can read out DCT memory with dfu-util. Address offsets and sizes are here: https://docs.particle.io/datasheets/photon-datasheet/#dct-layout

It should read from the page marked as valid.

For example, this will read out the public server key for a Photon:

dfu-util -d 2b04:d006 -a 1 -s 2082:402 -U server_key.der
1 Like

Thanks @ScruffR :ok_hand:

While I realize the linker and compiler do all the work in lining up the data bytes I elaborate further in my reply to @BDub's reply post, as I can't make sense of my photon's DCT data. Once I get my head around the right data in the right places, I'll let the linker do the work instead of me trying to line them up :stuck_out_tongue_winking_eye:

Thanks @BDub. Looks like I am working with an obsolete dct.h, as I checked on the github and you seem to have added extra fields: cloud_transport, a few alt_xxxx fields and device_id (previous device_id changed to device_code).

It seems that the documentation link you posted may need a correction, as it notes reserved2 is 1280 long whereas in the code it is clearly 628!

Having said all of that, my DCT data is still confusing: (Addresses below are offset of 0x08000000):


0003fa0 ffff ffff ffff ffff ffff ffff ffff ffff
*
0008000 0000 0000 0000 0000 0100 0001 5242 4d43
0008010 0000 0000 0000 0000 0000 0000 0000 0000
*
0008180 0000 0000 ffff ffff ffff ffff ffff ffff
0008190 ffff ffff ffff ffff ffff ffff ffff ffff
*
0009a30 0801 6e55 7469 4e79 7465 0000 0000 0000
0009a40 0000 0000 0000 0000 0000 0000 0000 0000
0009a50 0000 0000 0000 0000 0000 0000 0000 0400
0009a60 4000 0100 0000 0000 4000 4436 4232 4338
0009a70 3339 4232 4342 3943 3532 3143 3132 3335
0009a80 3342 4341 4546 4143 3630 3634 4442 4230
0009a90 3632 3534 4637 4432 3731 4238 3442 4136
0009aa0 3343 3336 3030 3834 3443 5508 696e 7974
0009ab0 654e 0074 0000 0000 0000 0000 0000 0000
0009ac0 0000 0000 0000 0000 0000 0000 0000 0000
0009ad0 0000 0000 0000 0000 0004 0040 0001 0000
0009ae0 0000 6408 6e61 7267 6e61 0039 0000 0000
0009af0 0000 0000 0000 0000 0000 0000 0000 0000
*
0009b20 0000 0800 6e55 7469 4e79 7465 0000 0000
0009b30 0000 0000 0000 0000 0000 0000 0000 0000
*
0009b50 0400 4000 0100 0000 0000 0800 6164 676e
0009b60 6172 396e 0000 0000 0000 0000 0000 0000
0009b70 0000 0000 0000 0000 0000 0000 0000 0000
*
0009b90 0000 0000 0000 0000 0000 0000 5508 696e
0009ba0 7974 654e 0074 0000 0000 0000 0000 0000
0009bb0 0000 0000 0000 0000 0000 0000 0000 0000
0009bc0 0000 0000 0000 0000 0000 0004 0040 0001
0009bd0 0000 0000 6408 6e61 7267 6e61 0039 0000
0009be0 0000 0000 0000 0000 0000 0000 0000 0000
*
0009c10 0000 0000 0800 6e55 7469 4e79 7465 0000
0009c20 0000 0000 0000 0000 0000 0000 0000 0000
*
0009c40 0000 0400 4000 0100 0000 0000 0800 6164
0009c50 676e 6172 396e 0000 0000 0000 0000 0000
0009c60 0000 0000 0000 0000 0000 0000 0000 0000


As can be seen, its data starts only at 0x8009a30 (offset of 0x1a30 or 6704 from 0x8008000) which is clearly way past the end of the DCT structure.

Also I notice my firmware is still monolithic and it has not been upgraded, although I did trying to put it in breathing cyan which is meant to OTA upgrade itself presumably to modular. This is because my module_info reads as (again offset of 0x8000000)


0020000 0000 2002 01d1 0802 0000 0000 0000 0000
0020010 0000 0000 0000 0000 0000 0000 0000 0000
*
0020180 0000 0000 0000 0802 fffc 0807 0000 0003
0020190 0006 0103 0000 0000 0000 0000 c484 0805
...

Address 0x80020192-3 is 0103 which indicates monolithic firmware.