The reason for the size discrepancy is alignment on ARM CPUs. The rules are:
- Any 4-byte variable (int, long, uint32_t, int32_t, float, time32_t, …) must be 4-byte aligned (address ending in 0x0, 0x4, 0x8, 0xC).
- Any 8-byte variable (double, long long, uint64_t, time_t, …) also must be 4-byte aligned.
- Any 2-byte variable (short, uint16_t, int16_t) must be 2-byte aligned (address ending in 0x0, 0x2, 0x4, 0x6, …)
- Any 1-byte variable (char, unsigned char, uint8_t, int8_t, bool, …) can be at any address.
The compiler automatically makes structures that comply with the rules. Some examples:
uint8_t nodeNumber; // Assigned by the gateway on joining the network
uint8_t structuresVersion; // Version of the data structures (system and data)
uint16_t magicNumber; // A way to identify nodes and gateways so they can trust each other
This actually is 4 bytes because the uint16_t happens to be 2-byte aligned.
uint8_t stayConnected; // Version of the device firmware (integer - aligned to particle prodict firmware)
uint8_t resetCount; // reset count of device (0-256)
uint8_t messageCount; // This is how many messages the Gateay has composed for the day
// <-- there's a filler uint8_t here
time_t lastHookResponse;
This part, however, is 12 bytes, not 7. The reason is that lastHookResponse must be 4-byte aligned, so there’s an extra filler byte inserted.
The second issue is that time_t is 64 bits (8 bytes) long. This is because the C++ standard library (newlib) switched to this a few years ago to eliminate the problem with the Unix clock rolling over to 0 in 2038.
This caused some issues, however, as parts of Device OS still depend on it being 32 bits long. If you look at the Device OS calls, they return a time32_t, not a time_t, because they use the older 32-bit time format.
The only other caveat is that structures are always rounded up to 4-byte alignment.
This is all of the offsets:
0000074628 [app] INFO: 16 nodeNumber
0000074629 [app] INFO: 17 structuresVersion
0000074629 [app] INFO: 18 magicNumber
0000074629 [app] INFO: 20 stayConnected
0000074629 [app] INFO: 21 resetCount
0000074630 [app] INFO: 22 messageCount
0000074630 [app] INFO: 24 lastHookResponse
0000074631 [app] INFO: 32 lastConnection
0000074631 [app] INFO: 40 lastConnectionDuration
0000074631 [app] INFO: 42 frequencyMinutes
0000074632 [app] INFO: 44 updatedFrequencyMinutes
0000074632 [app] INFO: 46 alertCodeGateway
0000074632 [app] INFO: 48 alertTimestampGateway
0000074633 [app] INFO: 56 openTime
0000074633 [app] INFO: 57 closeTime
0000074633 [app] INFO: 58 verizonSIM
0000074634 [app] INFO: 59 sensorType
0000074634 [app] INFO: sizeof(SysData): 64
And how I generated them:
Log.info("%2u nodeNumber", offsetof(SysData, nodeNumber));
Log.info("%2u structuresVersion", offsetof(SysData, structuresVersion));
Log.info("%2u magicNumber", offsetof(SysData, magicNumber));
Log.info("%2u stayConnected", offsetof(SysData, stayConnected));
Log.info("%2u resetCount", offsetof(SysData, resetCount));
Log.info("%2u messageCount", offsetof(SysData, messageCount));
Log.info("%2u lastHookResponse", offsetof(SysData, lastHookResponse));
Log.info("%2u lastConnection", offsetof(SysData, lastConnection));
Log.info("%2u lastConnectionDuration", offsetof(SysData, lastConnectionDuration));
Log.info("%2u frequencyMinutes", offsetof(SysData, frequencyMinutes));
Log.info("%2u updatedFrequencyMinutes", offsetof(SysData, updatedFrequencyMinutes));
Log.info("%2u alertCodeGateway", offsetof(SysData, alertCodeGateway));
Log.info("%2u alertTimestampGateway", offsetof(SysData, alertTimestampGateway));
Log.info("%2u openTime", offsetof(SysData, openTime));
Log.info("%2u closeTime", offsetof(SysData, closeTime));
Log.info("%2u verizonSIM", offsetof(SysData, verizonSIM));
Log.info("%2u sensorType", offsetof(SysData, sensorType));
Log.info("sizeof(SysData): %u", sizeof(SysData));
Correct on calling sysStatus that way.