123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- /*
- * Copyright (c) 2019 Vestas Wind Systems A/S
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <settings/settings.h>
- #include <CANopen.h>
- #include <CO_Emergency.h>
- #include <CO_SDO.h>
- #include <canopennode.h>
- #define LOG_LEVEL CONFIG_CANOPEN_LOG_LEVEL
- #include <logging/log.h>
- LOG_MODULE_REGISTER(canopen_storage);
- /* 's', 'a', 'v', 'e' from LSB to MSB */
- #define STORE_PARAM_MAGIC 0x65766173UL
- /* 'l', 'o', 'a', 'd' from LSB to MSB */
- #define RESTORE_PARAM_MAGIC 0x64616F6CUL
- /* Variables for reporing errors through CANopen once the stack is up */
- static int canopen_storage_rom_error;
- static int canopen_storage_eeprom_error;
- static CO_SDO_abortCode_t canopen_odf_1010(CO_ODF_arg_t *odf_arg)
- {
- CO_EM_t *em = odf_arg->object;
- uint32_t value;
- int err;
- value = CO_getUint32(odf_arg->data);
- if (odf_arg->reading) {
- return CO_SDO_AB_NONE;
- }
- /* Preserve old value */
- memcpy(odf_arg->data, odf_arg->ODdataStorage, sizeof(uint32_t));
- if (odf_arg->subIndex != 1U) {
- return CO_SDO_AB_NONE;
- }
- if (value != STORE_PARAM_MAGIC) {
- return CO_SDO_AB_DATA_TRANSF;
- }
- err = canopen_storage_save(CANOPEN_STORAGE_ROM);
- if (err) {
- LOG_ERR("failed to save object dictionary ROM entries (err %d)",
- err);
- CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
- err);
- return CO_SDO_AB_HW;
- } else {
- LOG_DBG("saved object dictionary ROM entries");
- }
- return CO_SDO_AB_NONE;
- }
- static CO_SDO_abortCode_t canopen_odf_1011(CO_ODF_arg_t *odf_arg)
- {
- CO_EM_t *em = odf_arg->object;
- bool failed = false;
- uint32_t value;
- int err;
- value = CO_getUint32(odf_arg->data);
- if (odf_arg->reading) {
- return CO_SDO_AB_NONE;
- }
- /* Preserve old value */
- memcpy(odf_arg->data, odf_arg->ODdataStorage, sizeof(uint32_t));
- if (odf_arg->subIndex < 1U) {
- return CO_SDO_AB_NONE;
- }
- if (value != RESTORE_PARAM_MAGIC) {
- return CO_SDO_AB_DATA_TRANSF;
- }
- err = canopen_storage_erase(CANOPEN_STORAGE_ROM);
- if (err == -ENOENT) {
- LOG_DBG("no object dictionary ROM entries to delete");
- } else if (err) {
- LOG_ERR("failed to delete object dictionary ROM entries"
- " (err %d)", err);
- CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
- err);
- failed = true;
- } else {
- LOG_DBG("deleted object dictionary ROM entries");
- }
- #ifdef CONFIG_CANOPENNODE_STORAGE_HANDLER_ERASES_EEPROM
- err = canopen_storage_erase(CANOPEN_STORAGE_EEPROM);
- if (err == -ENOENT) {
- LOG_DBG("no object dictionary EEPROM entries to delete");
- } else if (err) {
- LOG_ERR("failed to delete object dictionary EEPROM entries"
- " (err %d)", err);
- CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
- err);
- failed = true;
- } else {
- LOG_DBG("deleted object dictionary EEPROM entries");
- }
- #endif
- if (failed) {
- return CO_SDO_AB_HW;
- }
- return CO_SDO_AB_NONE;
- }
- static int canopen_settings_set(const char *key, size_t len_rd,
- settings_read_cb read_cb, void *cb_arg)
- {
- const char *next;
- int nlen;
- ssize_t len;
- nlen = settings_name_next(key, &next);
- if (!strncmp(key, "eeprom", nlen)) {
- struct sCO_OD_EEPROM eeprom;
- len = read_cb(cb_arg, &eeprom, sizeof(eeprom));
- if (len < 0) {
- LOG_ERR("failed to restore object dictionary EEPROM"
- " entries (err %d)", len);
- canopen_storage_eeprom_error = len;
- } else {
- if ((eeprom.FirstWord == CO_OD_FIRST_LAST_WORD) &&
- (eeprom.LastWord == CO_OD_FIRST_LAST_WORD)) {
- memcpy(&CO_OD_EEPROM, &eeprom,
- sizeof(CO_OD_EEPROM));
- LOG_DBG("restored object dictionary EEPROM"
- " entries");
- } else {
- LOG_WRN("object dictionary EEPROM entries"
- " signature mismatch, skipping"
- " restore");
- }
- }
- return 0;
- } else if (!strncmp(key, "rom", nlen)) {
- struct sCO_OD_ROM rom;
- len = read_cb(cb_arg, &rom, sizeof(rom));
- if (len < 0) {
- LOG_ERR("failed to restore object dictionary ROM"
- " entries (err %d)", len);
- canopen_storage_rom_error = len;
- } else {
- if ((rom.FirstWord == CO_OD_FIRST_LAST_WORD) &&
- (rom.LastWord == CO_OD_FIRST_LAST_WORD)) {
- memcpy(&CO_OD_ROM, &rom, sizeof(CO_OD_ROM));
- LOG_DBG("restored object dictionary ROM"
- " entries");
- } else {
- LOG_WRN("object dictionary ROM entries"
- " signature mismatch, skipping"
- " restore");
- }
- }
- return 0;
- }
- return 0;
- }
- SETTINGS_STATIC_HANDLER_DEFINE(canopen, "canopen", NULL,
- canopen_settings_set, NULL, NULL);
- void canopen_storage_attach(CO_SDO_t *sdo, CO_EM_t *em)
- {
- CO_OD_configure(sdo, OD_H1010_STORE_PARAM_FUNC, canopen_odf_1010,
- em, 0U, 0U);
- CO_OD_configure(sdo, OD_H1011_REST_PARAM_FUNC, canopen_odf_1011,
- em, 0U, 0U);
- if (canopen_storage_eeprom_error) {
- CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
- canopen_storage_eeprom_error);
- }
- if (canopen_storage_rom_error) {
- CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
- canopen_storage_rom_error);
- }
- }
- int canopen_storage_save(enum canopen_storage storage)
- {
- int ret = 0;
- if (storage == CANOPEN_STORAGE_ROM) {
- ret = settings_save_one("canopen/rom", &CO_OD_ROM,
- sizeof(CO_OD_ROM));
- } else if (storage == CANOPEN_STORAGE_EEPROM) {
- ret = settings_save_one("canopen/eeprom", &CO_OD_EEPROM,
- sizeof(CO_OD_EEPROM));
- }
- return ret;
- }
- int canopen_storage_erase(enum canopen_storage storage)
- {
- int ret = 0;
- if (storage == CANOPEN_STORAGE_ROM) {
- ret = settings_delete("canopen/rom");
- } else if (storage == CANOPEN_STORAGE_EEPROM) {
- ret = settings_delete("canopen/eeprom");
- }
- return ret;
- }
|