mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
fixes to enable partial programming (#132)
* fixes to enable partial programming (thanks to mumpf and proggerKA at KNX-UF!) * add PID_MCB_TABLE to TableObject * add CallBackProperty to send PID_MCB_TABLE * calculate crc checksum using Crc16Citt when state switches to LOAD_COMPLETED * add crc to save(), restore() and saveSize() to save crc to flash * add CallBackProperty for read and write of PID_PROG_VERSION to ApplicationProgramObject * create overrides for save, restore, and saveSize in ApplicationProgramObject to save _programVersion to flash * improve crc calculation * removed TableObject::crc16Citt method and use the one in bits.h * do not save crc in flash, instead calculate on-the-fly in CallbackProperty when state==LS_LOADED * use DataProperty to store PID_PROG_VERSION * WARNING: segmentSize calculation for crc calculation is currently not correct. Need to somehow access size of data in class that inherits from TableObject (e.g. ApplicationObject or RouterObject) * fix segment size in TableObject() * save size after TableObject::allocTable() is called. Also change save() and restore() to save _size to flash. Modify saveSize() * use _size to calculate crc value in CallbackProperty * reduce footprint, save 5 byte * add comment why _size field is needed * remove PID_MCB_TABLE from RouterObject * this is now implemented in TableObject
This commit is contained in:
parent
e57bbf9dbe
commit
1343ed0b7d
@ -29,6 +29,29 @@ ApplicationProgramObject::ApplicationProgramObject(Memory& memory)
|
||||
TableObject::initializeProperties(sizeof(properties), properties);
|
||||
}
|
||||
|
||||
uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
|
||||
{
|
||||
uint8_t programVersion[5];
|
||||
property(PID_PROG_VERSION)->read(programVersion);
|
||||
buffer = pushByteArray(programVersion, 5, buffer);
|
||||
|
||||
return TableObject::save(buffer);
|
||||
}
|
||||
|
||||
const uint8_t* ApplicationProgramObject::restore(const uint8_t* buffer)
|
||||
{
|
||||
uint8_t programVersion[5];
|
||||
buffer = popByteArray(programVersion, 5, buffer);
|
||||
property(PID_PROG_VERSION)->write(programVersion);
|
||||
|
||||
return TableObject::restore(buffer);
|
||||
}
|
||||
|
||||
uint16_t ApplicationProgramObject::saveSize()
|
||||
{
|
||||
return TableObject::saveSize() + 5; // sizeof(programVersion)
|
||||
}
|
||||
|
||||
uint8_t * ApplicationProgramObject::data(uint32_t addr)
|
||||
{
|
||||
return TableObject::data() + addr;
|
||||
|
@ -7,6 +7,9 @@ class ApplicationProgramObject : public TableObject
|
||||
{
|
||||
public:
|
||||
ApplicationProgramObject(Memory& memory);
|
||||
uint8_t* save(uint8_t* buffer) override;
|
||||
const uint8_t* restore(const uint8_t* buffer) override;
|
||||
uint16_t saveSize() override;
|
||||
uint8_t* data(uint32_t addr);
|
||||
uint8_t getByte(uint32_t addr);
|
||||
uint16_t getWord(uint32_t addr);
|
||||
|
@ -84,7 +84,6 @@ void RouterObject::initialize(CouplerModel model, uint8_t objIndex, DptMedium me
|
||||
Property* tableProperties[] =
|
||||
{
|
||||
new DataProperty( PID_COUPLER_SERVICES_CONTROL, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint8_t) 0), // written by ETS TODO: implement
|
||||
new DataProperty( PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0), // TODO: improve: move to TableObject once segment size handling is clear
|
||||
new DataProperty( PID_FILTER_TABLE_USE, true, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // default: invalid filter table, do not use, written by ETS
|
||||
new FunctionProperty<RouterObject>(this, PID_ROUTETABLE_CONTROL,
|
||||
// Command Callback of PID_ROUTETABLE_CONTROL
|
||||
@ -452,27 +451,9 @@ void RouterObject::beforeStateChange(LoadState& newState)
|
||||
if (newState != LS_LOADED)
|
||||
return;
|
||||
|
||||
// calculate crc16-ccitt for PID_MCB_TABLE
|
||||
updateMcb();
|
||||
|
||||
_filterTableGroupAddresses = (uint16_t*)data();
|
||||
}
|
||||
|
||||
void RouterObject::updateMcb()
|
||||
{
|
||||
uint8_t mcb[propertySize(PID_MCB_TABLE)];
|
||||
|
||||
static constexpr uint32_t segmentSize = kFilterTableSize;
|
||||
uint16_t crc16 = crc16Ccitt(data(), segmentSize);
|
||||
|
||||
pushInt(segmentSize, &mcb[0]); // Segment size
|
||||
pushByte(0x00, &mcb[4]); // CRC control byte -> 0: always valid -> according to coupler spec. it shall always be a valid CRC
|
||||
pushByte(0xFF, &mcb[5]); // Read access 4 bits + Write access 4 bits (unknown: value taken from real coupler device)
|
||||
pushWord(crc16, &mcb[6]); // CRC-16 CCITT of filter table
|
||||
|
||||
property(PID_MCB_TABLE)->write(mcb);
|
||||
}
|
||||
|
||||
void RouterObject::masterReset(EraseCode eraseCode, uint8_t channel)
|
||||
{
|
||||
if (eraseCode == FactoryReset)
|
||||
|
@ -52,8 +52,6 @@ private:
|
||||
void commandClearSetGroupAddress(uint16_t startAddress, uint16_t endAddress, bool bitIsSet);
|
||||
bool statusClearSetGroupAddress(uint16_t startAddress, uint16_t endAddress, bool bitIsSet);
|
||||
|
||||
void updateMcb();
|
||||
|
||||
bool _rfSbcRoutingEnabled = false;
|
||||
bool _ipSbcRoutingEnabled = false;
|
||||
uint16_t* _filterTableGroupAddresses = 0;
|
||||
|
@ -31,6 +31,8 @@ uint8_t* TableObject::save(uint8_t* buffer)
|
||||
{
|
||||
buffer = pushByte(_state, buffer);
|
||||
|
||||
buffer = pushInt(_size, buffer);
|
||||
|
||||
if (_data)
|
||||
buffer = pushInt(_memory.toRelative(_data), buffer);
|
||||
else
|
||||
@ -46,6 +48,8 @@ const uint8_t* TableObject::restore(const uint8_t* buffer)
|
||||
buffer = popByte(state, buffer);
|
||||
_state = (LoadState)state;
|
||||
|
||||
buffer = popInt(_size, buffer);
|
||||
|
||||
uint32_t relativeAddress = 0;
|
||||
buffer = popInt(relativeAddress, buffer);
|
||||
|
||||
@ -80,6 +84,8 @@ bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
|
||||
if (doFill)
|
||||
memset(_data, fillByte, size);
|
||||
|
||||
_size = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -229,7 +235,7 @@ void TableObject::errorCode(ErrorCode errorCode)
|
||||
|
||||
uint16_t TableObject::saveSize()
|
||||
{
|
||||
return 5 + InterfaceObject::saveSize();
|
||||
return 5 + InterfaceObject::saveSize() + sizeof(_size);
|
||||
}
|
||||
|
||||
void TableObject::initializeProperties(size_t propertiesSize, Property** properties)
|
||||
@ -267,6 +273,21 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert
|
||||
pushInt(obj->tableReference(), data);
|
||||
return 1;
|
||||
}),
|
||||
new CallbackProperty<TableObject>(this, PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0,
|
||||
[](TableObject* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
|
||||
if (obj->_state != LS_LOADED)
|
||||
return 0; // need to check return code for invalid
|
||||
|
||||
uint32_t segmentSize = obj->_size;
|
||||
uint16_t crc16 = crc16Ccitt(obj->data(), segmentSize);
|
||||
|
||||
pushInt(segmentSize, data); // Segment size
|
||||
pushByte(0x00, data + 4); // CRC control byte -> 0: always valid
|
||||
pushByte(0xFF, data + 5); // Read access 4 bits + Write access 4 bits
|
||||
pushWord(crc16, data + 6); // CRC-16 CCITT of data
|
||||
|
||||
return 1;
|
||||
}),
|
||||
new DataProperty(PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT)
|
||||
};
|
||||
//TODO: missing
|
||||
@ -284,4 +305,4 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert
|
||||
memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties));
|
||||
|
||||
InterfaceObject::initializeProperties(sizeof(allProperties), allProperties);
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ class TableObject: public InterfaceObject
|
||||
uint8_t* save(uint8_t* buffer) override;
|
||||
const uint8_t* restore(const uint8_t* buffer) override;
|
||||
uint16_t saveSize() override;
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* This method is called before the interface object enters a new ::LoadState.
|
||||
* If there is a error changing the state newState should be set to ::LS_ERROR and errorCode()
|
||||
@ -47,7 +47,7 @@ protected:
|
||||
void errorCode(ErrorCode errorCode);
|
||||
|
||||
void initializeProperties(size_t propertiesSize, Property** properties) override;
|
||||
|
||||
|
||||
private:
|
||||
uint32_t tableReference();
|
||||
bool allocTable(uint32_t size, bool doFill, uint8_t fillByte);
|
||||
@ -68,4 +68,11 @@ protected:
|
||||
LoadState _state = LS_UNLOADED;
|
||||
Memory& _memory;
|
||||
uint8_t *_data = 0;
|
||||
|
||||
/**
|
||||
* used to store size of data() in allocTable(), needed for calculation of crc in PID_MCB_TABLE.
|
||||
* This value is also saved and restored.
|
||||
* The size of the memory block cannot be used because it is changed during alignment to page size.
|
||||
*/
|
||||
uint32_t _size = 0;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user