From b24866225a6301d3a663f874725e83c012dc25d3 Mon Sep 17 00:00:00 2001 From: Florent Duchon Date: Wed, 26 Dec 2012 17:36:00 +0100 Subject: digital/beacon: add bitcloud stack into common directory digital/zigbit --- .../PersistDataServer/src/pdsCrcService.c | 217 ++++++++++++++++ .../PersistDataServer/src/pdsDataServer.c | 206 +++++++++++++++ .../PersistDataServer/src/pdsWriteData.c | 286 +++++++++++++++++++++ 3 files changed, 709 insertions(+) create mode 100644 digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsCrcService.c create mode 100644 digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsDataServer.c create mode 100644 digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsWriteData.c (limited to 'digital/zigbit/bitcloud/stack/Components/PersistDataServer/src') diff --git a/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsCrcService.c b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsCrcService.c new file mode 100644 index 00000000..de9631dc --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsCrcService.c @@ -0,0 +1,217 @@ +/***************************************************************************//** + \file pdsCrcService.c + + \brief Persistence Data Server implementation + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 22/01/08 A. Khromykh - Created + 01/11/10 A. Razinkov - Modified +*****************************************************************************/ + +#ifdef _COMMISSIONING_ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include + +/****************************************************************************** +\brief Calculate CRC of persistent data stored in persist memory +\ +\param[out] crcStation - pointer to CRC service structure +******************************************************************************/ +void pdsCalculateCrc(PDS_ServiceCrc_t *crcStation) +{ + uint8_t tdata = 0; + MEMORY_DESCRIPTOR descriptor; + + if (NULL == crcStation) + return; + + crcStation->crc = 0; + descriptor.address = SYSTEM_BASE_EEPROM_ADDRESS; + descriptor.length = 1; + while (descriptor.address < csPersistentMemorySize) + { + descriptor.data = &tdata; + + pdsWaitMemoryFree(); + + if (EEPROM_ERROR == READ_MEMORY(&descriptor, NULL)) + { + crcStation->eepromState = PDS_EEPROM_ERROR; + return; + } + + pdsWaitMemoryFree(); + + crcStation->crc += tdata; + descriptor.address++; + } + crcStation->eepromState = PDS_SUCCESS; +} + +/****************************************************************************** +\brief Read CRC of stored data from persist memory +\ +\param[out] crcStation - pointer to CRC service structure +******************************************************************************/ +void pdsReadCrc(PDS_ServiceCrc_t *crcStation) +{ + MEMORY_DESCRIPTOR descriptor; + + if (NULL == crcStation) + return; + + descriptor.address = csPersistentMemorySize; + descriptor.length = 1; + while (descriptor.address < USER_BASE_EEPROM_ADDRESS) + { + descriptor.data = &(crcStation->crc); + + pdsWaitMemoryFree(); + + if (EEPROM_ERROR == READ_MEMORY(&descriptor, NULL)) + { + crcStation->eepromState = PDS_EEPROM_ERROR; + return; + } + + pdsWaitMemoryFree(); + + if (0xFF != crcStation->crc) + { + crcStation->position = descriptor.address; + crcStation->eepromState = PDS_SUCCESS; + return; + } + descriptor.address++; + } + crcStation->position = csPersistentMemorySize; + crcStation->eepromState = PDS_SUCCESS; +} + +/****************************************************************************** +\brief Clears whole CRC area in persist memory +\ +\return operation result +******************************************************************************/ +PDS_DataServerState_t pdsClearCrcArea(void) +{ + uint8_t value = 0xFF; + MEMORY_DESCRIPTOR descriptor; + uint8_t status; + + descriptor.data = &value; + descriptor.address = csPersistentMemorySize; + descriptor.length = 1; + + for (uint8_t i = 0; i < PDS_CRC_AREA; i++) + { + status = pdsWrite(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return status; + + descriptor.address++; + } + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Write CRC of stored data to persist memory. The ring buffer used +\ to increase persist memory life cycle +\ +\param[out] crcStation - pointer to CRC service structure +******************************************************************************/ +PDS_DataServerState_t pdsWriteCrc(void) +{ + PDS_ServiceCrc_t crcRead, crcCalc; + MEMORY_DESCRIPTOR descriptor; + uint8_t datadelete = 0xFF; + PDS_DataServerState_t status; + + pdsReadCrc(&crcRead); + if (PDS_EEPROM_ERROR == crcRead.eepromState) + return PDS_EEPROM_ERROR; + + pdsCalculateCrc(&crcCalc); + if (PDS_EEPROM_ERROR == crcCalc.eepromState) + return PDS_EEPROM_ERROR; + + if (0 == (uint8_t)(crcCalc.crc + crcRead.crc)) + return PDS_SUCCESS; + + crcCalc.crc = 0 - crcCalc.crc; + descriptor.address = crcRead.position; + descriptor.data = &datadelete; + descriptor.length = 1; + + status = pdsWrite(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return status; + + if (++descriptor.address >= USER_BASE_EEPROM_ADDRESS) + descriptor.address = csPersistentMemorySize; + descriptor.data = &(crcCalc.crc); + + status = pdsWrite(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return status; + + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Check if any valid data exists in persist memory +\ +\return operation result +******************************************************************************/ +PDS_DataServerState_t pdsCheckPersistMemory(void) +{ + PDS_ServiceCrc_t crcRead, crcCalc; + + pdsCalculateCrc(&crcCalc); + if (PDS_EEPROM_ERROR == crcCalc.eepromState) + return PDS_EEPROM_ERROR; + + pdsReadCrc(&crcRead); + if (PDS_EEPROM_ERROR == crcRead.eepromState) + return PDS_EEPROM_ERROR; + + if (0x00 == (uint8_t)(crcCalc.crc + crcRead.crc)) + return PDS_SUCCESS; + + return PDS_CRC_ERROR; +} + +#ifdef __DBG_PDS__ + uint8_t eepromCopy[0x400u]; + + void pdsDbgReadAllEeprom(void) + { + PDS_DataServerState_t status; + MEMORY_DESCRIPTOR descriptor; + + descriptor.address = 0; + descriptor.data = eepromCopy; + descriptor.length = 0x400u; + + status = pdsRead(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return; + } +#endif +#endif /* _COMMISSIONING_ */ +// eof pdsDataServer.c diff --git a/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsDataServer.c b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsDataServer.c new file mode 100644 index 00000000..530ac0a7 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsDataServer.c @@ -0,0 +1,206 @@ +/***************************************************************************//** + \file pdsDataServer.c + + \brief Persistence Data Server implementation + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 22/01/08 A. Khromykh - Created + 01/11/10 A. Razinkov - Modified +*****************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _COMMISSIONING_ +/****************************************************************************** + Prototypes section +******************************************************************************/ + +/****************************************************************************** + External variables section +******************************************************************************/ +/* Number of records in csPersistentMemTable*/ +extern const uint8_t csPersistentItemsAmount; + +/****************************************************************************** + Implementations section +******************************************************************************/ +/****************************************************************************** +\brief Persist Data Server initialization procedure +******************************************************************************/ +void PDS_Init(void) +{ + PDS_DataServerState_t status; + +#ifdef USE_LED + BSP_OpenLeds(); +#endif + + /* Check if any valid data exists in persist memory */ + status = pdsCheckPersistMemory(); + + /* Valid data exists - try to update from persist memory */ + if (PDS_SUCCESS == status) + { + if (PDS_EEPROM_ERROR != pdsUpdate()) + { + pdsStartPersistServer(); + } + } + + else if (PDS_EEPROM_ERROR != status) + { + pdsStartPersistServer(); + } +} + +/****************************************************************************** +\brief Set the default system area values and store persistent data to persist + memory + +\return operation result +******************************************************************************/ +PDS_DataServerState_t PDS_SetToDefault(void) +{ + MEMORY_DESCRIPTOR descriptor; + PDS_DataServerState_t status; + + CS_PdsDefaultValue(); + /* Store all persistent parameters */ + for (uint8_t index = 0; index < csPersistentItemsAmount; index++) + { + pdsPrepareMemoryAccess(index, &descriptor); + status = pdsWrite(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return status; + } + + /* Reset CRC area and rewrite CRC*/ + status = pdsClearCrcArea(); + if (status != PDS_SUCCESS) + return status; + status = pdsWriteCrc(); + if (status != PDS_SUCCESS) + return status; + + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief On-demand data storing in persist memory +******************************************************************************/ +void PDS_FlushData(void) +{ + if (SAVE_IS_STOPED == savingIsStarted) + { + /* Force timer to finish - store data immediately */ + HAL_StopAppTimer(&pdsEepromSaveServiceTimer); + pdsOnTimerSave(); + } + + while (SAVE_IS_STARTED == savingIsStarted) + { + SYS_ForceRunTask(); + } +} + +/***************************************************************************//** +\brief Must be called only from ::APL_TaskHandler() function.\n + Stops persist data server. +*******************************************************************************/ +void PDS_Stop(void) +{ + while (SAVE_IS_STARTED == savingIsStarted) + { + SYS_ForceRunTask(); + } + + HAL_StopAppTimer(&pdsEepromSaveServiceTimer); +} +#endif /* _COMMISSIONING_ */ + +/****************************************************************************** +\brief Read data from user area in persist memory + +\param[in] offset - data offset in persist memory +\param[in] length - data lenght +\param[out] data - pointer to user data area in RAM +\param[out] callback - callback to read-finished event handler + +\return operation result +******************************************************************************/ +PDS_DataServerState_t PDS_ReadUserData(uint16_t offset, uint8_t *data, uint16_t length, void (*callback)(void)) +{ + MEMORY_DESCRIPTOR descriptor; + PDS_DataServerState_t status; + + descriptor.address = USER_BASE_EEPROM_ADDRESS + offset; + descriptor.length = length; + descriptor.data = data; + + while(SAVE_IS_STARTED == savingIsStarted) + { + SYS_ForceRunTask(); + } + + if (NULL == callback) + callback = pdsDummyCallback; + + status = pdsRead(&descriptor, callback); + if (status != PDS_SUCCESS) + return status; + + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Write data to user area in persist memory +\ +\param[in] offset - data offset in persist memory +\param[in] length - data lenght +\param[out] data - pointer to user data area +\param[out] callback - callback to read-finished event handler + +\return operation result +******************************************************************************/ +PDS_DataServerState_t PDS_WriteUserData(uint16_t offset, uint8_t *data, uint16_t length, void (*callback)(void)) +{ + MEMORY_DESCRIPTOR descriptor; + PDS_DataServerState_t status; + + descriptor.address = USER_BASE_EEPROM_ADDRESS + offset; + descriptor.length = length; + descriptor.data = data; + + while(SAVE_IS_STARTED == savingIsStarted) + { + SYS_ForceRunTask(); + } + + if (NULL == callback) + callback = pdsDummyCallback; + + status = pdsWrite(&descriptor, callback); + if (status != PDS_SUCCESS) + return status; + + return PDS_SUCCESS; +} +// eof pdsDataServer.c diff --git a/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsWriteData.c b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsWriteData.c new file mode 100644 index 00000000..bb7f9859 --- /dev/null +++ b/digital/zigbit/bitcloud/stack/Components/PersistDataServer/src/pdsWriteData.c @@ -0,0 +1,286 @@ +/**************************************************************************//** + \file pdsWriteData.c + + \brief Periodic data save implementation + + \author + Atmel Corporation: http://www.atmel.com \n + Support email: avr@atmel.com + + Copyright (c) 2008-2011, Atmel Corporation. All rights reserved. + Licensed under Atmel's Limited License Agreement (BitCloudTM). + + \internal + History: + 22/01/08 A. Khromykh - Created + 01/11/10 A. Razinkov - Modified +*****************************************************************************/ +/****************************************************************************** + Includes section +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + Global variables section +******************************************************************************/ +uint8_t savingIsStarted = SAVE_IS_STOPED; + +#ifdef _COMMISSIONING_ +HAL_AppTimer_t pdsEepromSaveServiceTimer; + +/****************************************************************************** + External variables section +******************************************************************************/ +/* Configuration Server persistent memory table */ +extern const CS_PersistantData_t PROGMEM_DECLARE(csPersistentMemTable[]); + +/* Number of records in csPersistentMemTable*/ +extern const uint8_t csPersistentItemsAmount; + +/* Total size of memory occupied by persistent parameters */ +extern const uint16_t csPersistentMemorySize; + +/****************************************************************************** + Prototypes section +******************************************************************************/ +static PDS_DataServerState_t pdsCommit(void); +static bool pdsCommitStarted(MEMORY_DESCRIPTOR* descriptor); + +/****************************************************************************** + Implementation section +******************************************************************************/ +/****************************************************************************** +\brief Start internal PDS timer +\ +\param[in] typeInterval - set timer interval. Available intervals are: + PDS_LONG_INTERVAL - 5 minutes + PDS_SHORT_INTERVAL - 50 msec +\param[out] callback - callback on timer fired event + +******************************************************************************/ +void pdsStartPdsTimer(void (*callback)(void), uint8_t typeInterval) +{ + pdsEepromSaveServiceTimer.callback = callback; + if (PDS_LONG_INTERVAL == typeInterval) + { +#ifdef _POWER_FAILURE_ + uint32_t storingInterval; + + CS_ReadParameter(CS_PDS_STORING_INTERVAL_ID, &storingInterval); + pdsEepromSaveServiceTimer.interval = storingInterval; +#else + pdsEepromSaveServiceTimer.interval = STORE_TIMER_TIMEOUT; +#endif /* _POWER_FAILURE_ */ + } + else + pdsEepromSaveServiceTimer.interval = SHORT_TIMEOUT; + pdsEepromSaveServiceTimer.mode = TIMER_ONE_SHOT_MODE; + HAL_StartAppTimer(&pdsEepromSaveServiceTimer); +} + +/******************************************************************************* +\brief Start server work +*******************************************************************************/ +void pdsStartPersistServer(void) +{ + pdsStartPdsTimer(pdsOnTimerSave, PDS_LONG_INTERVAL); +} + +/****************************************************************************** +\brief Commit item value changes (if any) from Configuration Server to persist +\ memory +\ +\param[in] descriptor - memory descriptor to store parameter value + +\return true - if changes found and commit started; false - otherwise +******************************************************************************/ +static bool pdsCommitStarted(MEMORY_DESCRIPTOR* descriptor) +{ + uint8_t data; + MEMORY_DESCRIPTOR byteAccessDescriptor = + { + .data = &data, + .length = 1 + }; + + /* Check for any changes in byte-by-byte order */ + for (uint16_t i = 0; i < descriptor->length; i++) + { + byteAccessDescriptor.address = descriptor->address + i; + pdsRead(&byteAccessDescriptor, pdsDummyCallback); + /* Start rewrite out of date data in persist memory*/ + if (*byteAccessDescriptor.data != *((descriptor->data) + i)) + { + pdsWrite(descriptor, pdsOnTimerSave); + return true; + } + } + return false; +} + +/****************************************************************************** +\brief Update persistent items values in Configuration Server from persist memory +\ +\return Operation result +******************************************************************************/ +PDS_DataServerState_t pdsUpdate(void) +{ + PDS_DataServerState_t status; + MEMORY_DESCRIPTOR descriptor; + + for (uint8_t item = 0; item < csPersistentItemsAmount; item++) + { + pdsPrepareMemoryAccess(item, &descriptor); + status = pdsRead(&descriptor, pdsDummyCallback); + if (status != PDS_SUCCESS) + return status; + } + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Commit persistent memory changes (if any) from Configuration Server +\ to persist memory. Process comes iterative way - when some item stored, +\ this function will be called as a callback. +\ +\return Operation result +******************************************************************************/ +PDS_DataServerState_t pdsCommit(void) +{ + MEMORY_DESCRIPTOR descriptor; + static uint8_t item = 0; + + while (item < csPersistentItemsAmount) + { + pdsPrepareMemoryAccess(item, &descriptor); + if(pdsCommitStarted(&descriptor)) + return PDS_COMMIT_IN_PROGRESS; + + item++; + } + item = 0; + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Timer callback, initiates the commit process. +******************************************************************************/ +void pdsOnTimerSave(void) +{ +#ifdef USE_LED + BSP_OnLed(LED_YELLOW); +#endif + + savingIsStarted = SAVE_IS_STARTED; + + if (PDS_SUCCESS == pdsCommit()) + { + if (PDS_EEPROM_ERROR == pdsWriteCrc()) + { + pdsStartPdsTimer(pdsOnTimerSave, PDS_SHORT_INTERVAL); + } + else + { + pdsStartPersistServer(); +#ifdef USE_LED + BSP_OffLed(LED_YELLOW); +#endif + savingIsStarted = SAVE_IS_STOPED; + } + } +} + +/****************************************************************************** +\brief Locates parameter by it's index in persistent memory table. And prepares +\ memory descriptor to store parameter's value in EEPROM +\ +\param[in] index - index of the parameter in persistent memory table +\param[out]descriptor - memory descriptor to store parameter value +******************************************************************************/ +void pdsPrepareMemoryAccess(uint8_t index, MEMORY_DESCRIPTOR* descriptor) +{ + CS_PersistantData_t item; + + memcpy_P(&item, &csPersistentMemTable[index], sizeof(CS_PersistantData_t)); + + assert(item.value, PDS_PDSPREPAREMEMORYACCESS0); + descriptor->data = item.value; + descriptor->address = item.offset; + + /* Calculate item size using offsets */ + if (index == (csPersistentItemsAmount-1)) + { + descriptor->length = csPersistentMemorySize - item.offset; + } + else + { + CS_PersistantData_t nextItem; + memcpy_P(&nextItem, &csPersistentMemTable[index+1], sizeof(CS_PersistantData_t)); + assert(nextItem.value, PDS_PDSPREPAREMEMORYACCESS1); + descriptor->length = nextItem.offset - item.offset; + } +} +#endif /* _COMMISSIONING_ */ + +/****************************************************************************** +\brief Write data to persist memory +\ +\param[in] descriptor - memory descriptor to store parameter value +\param[out]callback - callback to write-finished event handler +******************************************************************************/ +PDS_DataServerState_t pdsWrite(MEMORY_DESCRIPTOR* descriptor, void (*callback)(void)) +{ + pdsWaitMemoryFree(); + if (EEPROM_ERROR == WRITE_MEMORY(descriptor, callback)) + return PDS_EEPROM_ERROR; + + if (callback == pdsDummyCallback) + pdsWaitMemoryFree(); + + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Read data from persist memory +\ +\param[in] descriptor - memory descriptor to read parameter value +\param[out]callback - callback to read-finished event handler +******************************************************************************/ +PDS_DataServerState_t pdsRead(MEMORY_DESCRIPTOR* descriptor, void (*callback)(void)) +{ + pdsWaitMemoryFree(); + if (EEPROM_ERROR == READ_MEMORY(descriptor, callback)) + return PDS_EEPROM_ERROR; + + if (callback == pdsDummyCallback) + pdsWaitMemoryFree(); + + return PDS_SUCCESS; +} + +/****************************************************************************** +\brief Wait until memory be ready for transaction +******************************************************************************/ +void pdsWaitMemoryFree(void) +{ + while(IS_MEMORY_BUSY()) + { + SYS_ForceRunTask(); + } +} + +/******************************************************************************* +\brief Dummy callback +*******************************************************************************/ +void pdsDummyCallback(void) +{} +// eof pdsDataServer.c -- cgit v1.2.3