Example update
This commit is contained in:
parent
fc99553c8f
commit
90ec8819be
10 changed files with 306 additions and 477 deletions
|
|
@ -347,7 +347,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
/** Object Dictionary index */
|
||||
uint16_t index;
|
||||
/** Maximum sub-index in the OD object */
|
||||
/** Number of all sub-entries, including sub-entry at sub-index 0 */
|
||||
uint8_t subEntriesCount;
|
||||
/** Type of the odObject, indicated by @ref OD_objectTypes_t enumerator. */
|
||||
uint8_t odObjectType;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* @file CO_driver_target.h
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2020 Janez Paternoster
|
||||
* @copyright 2021 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
|
|
@ -42,122 +42,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Stack configuration override default values (all enabled in this example).
|
||||
/* Stack configuration override default values.
|
||||
* For more information see file CO_config.h. */
|
||||
#define CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE CO_CONFIG_FLAG_CALLBACK_PRE
|
||||
#define CO_CONFIG_GLOBAL_FLAG_TIMERNEXT CO_CONFIG_FLAG_TIMERNEXT
|
||||
|
||||
#ifndef CO_CONFIG_NMT
|
||||
#define CO_CONFIG_NMT (CO_CONFIG_NMT_CALLBACK_CHANGE | \
|
||||
CO_CONFIG_NMT_MASTER | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_HB_CONS
|
||||
#define CO_CONFIG_HB_CONS (CO_CONFIG_HB_CONS_ENABLE | \
|
||||
CO_CONFIG_HB_CONS_CALLBACK_MULTI | \
|
||||
CO_CONFIG_HB_CONS_QUERY_FUNCT | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
|
||||
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_EM
|
||||
#define CO_CONFIG_EM (CO_CONFIG_EM_PRODUCER | \
|
||||
CO_CONFIG_EM_PROD_CONFIGURABLE | \
|
||||
CO_CONFIG_EM_PROD_INHIBIT | \
|
||||
CO_CONFIG_EM_HISTORY | \
|
||||
CO_CONFIG_EM_STATUS_BITS | \
|
||||
CO_CONFIG_EM_CONSUMER | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_SDO_SRV
|
||||
#define CO_CONFIG_SDO_SRV (CO_CONFIG_SDO_SRV_SEGMENTED | \
|
||||
CO_CONFIG_SDO_SRV_BLOCK | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
|
||||
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_SDO_SRV_BUFFER_SIZE
|
||||
#define CO_CONFIG_SDO_SRV_BUFFER_SIZE 900
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_SDO_CLI
|
||||
#define CO_CONFIG_SDO_CLI (CO_CONFIG_SDO_CLI_ENABLE | \
|
||||
CO_CONFIG_SDO_CLI_SEGMENTED | \
|
||||
CO_CONFIG_SDO_CLI_BLOCK | \
|
||||
CO_CONFIG_SDO_CLI_LOCAL | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
|
||||
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_TIME
|
||||
#define CO_CONFIG_TIME (CO_CONFIG_TIME_ENABLE | \
|
||||
CO_CONFIG_TIME_PRODUCER | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_GFC
|
||||
#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | \
|
||||
CO_CONFIG_GFC_CONSUMER | \
|
||||
CO_CONFIG_GFC_PRODUCER)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_SRDO
|
||||
#define CO_CONFIG_SRDO (CO_CONFIG_SRDO_ENABLE | \
|
||||
CO_CONFIG_SRDO_CHECK_TX | \
|
||||
CO_CONFIG_RSRDO_CALLS_EXTENSION | \
|
||||
CO_CONFIG_TSRDO_CALLS_EXTENSION | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
|
||||
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_SRDO_MINIMUM_DELAY
|
||||
#define CO_CONFIG_SRDO_MINIMUM_DELAY 0
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_LSS
|
||||
#define CO_CONFIG_LSS (CO_CONFIG_LSS_SLAVE | \
|
||||
CO_CONFIG_LSS_SLAVE_FASTSCAN_DIRECT_RESPOND | \
|
||||
CO_CONFIG_LSS_MASTER | \
|
||||
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_GTW
|
||||
#define CO_CONFIG_GTW (CO_CONFIG_GTW_ASCII | \
|
||||
CO_CONFIG_GTW_ASCII_SDO | \
|
||||
CO_CONFIG_GTW_ASCII_NMT | \
|
||||
CO_CONFIG_GTW_ASCII_LSS | \
|
||||
CO_CONFIG_GTW_ASCII_LOG | \
|
||||
CO_CONFIG_GTW_ASCII_ERROR_DESC | \
|
||||
CO_CONFIG_GTW_ASCII_PRINT_HELP | \
|
||||
CO_CONFIG_GTW_ASCII_PRINT_LEDS)
|
||||
#define CO_CONFIG_GTW_BLOCK_DL_LOOP 1
|
||||
#define CO_CONFIG_GTWA_COMM_BUF_SIZE 2000
|
||||
#define CO_CONFIG_GTWA_LOG_BUF_SIZE 2000
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_CRC16
|
||||
#define CO_CONFIG_CRC16 (CO_CONFIG_CRC16_ENABLE)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_FIFO
|
||||
#define CO_CONFIG_FIFO (CO_CONFIG_FIFO_ENABLE | \
|
||||
CO_CONFIG_FIFO_ALT_READ | \
|
||||
CO_CONFIG_FIFO_CRC16_CCITT | \
|
||||
CO_CONFIG_FIFO_ASCII_COMMANDS | \
|
||||
CO_CONFIG_FIFO_ASCII_DATATYPES)
|
||||
#endif
|
||||
|
||||
#ifndef CO_CONFIG_TRACE
|
||||
#define CO_CONFIG_TRACE (CO_CONFIG_TRACE_ENABLE)
|
||||
#endif
|
||||
|
||||
|
||||
/* Basic definitions. If big endian, CO_SWAP_xx macros must swap bytes. */
|
||||
|
|
@ -218,7 +104,8 @@ typedef struct {
|
|||
size_t len;
|
||||
uint8_t subIndexOD;
|
||||
uint8_t attr;
|
||||
/* Additional variables */
|
||||
/* Additional variables (target specific) */
|
||||
void *addrNV;
|
||||
} CO_storage_entry_t;
|
||||
|
||||
|
||||
|
|
|
|||
111
example/CO_storageBlank.c
Normal file
111
example/CO_storageBlank.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* CANopen Object Dictionary storage object (blank example).
|
||||
*
|
||||
* @file CO_storageBlank.c
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2021 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
* For more information on CANopen see <http://www.can-cia.org/>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "CO_storageBlank.h"
|
||||
|
||||
|
||||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
|
||||
|
||||
|
||||
/*
|
||||
* Function for writing data on "Store parameters" command - OD object 1010
|
||||
*
|
||||
* For more information see file CO_storage.h, CO_storage_entry_t.
|
||||
*/
|
||||
static ODR_t storeBlank(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule) {
|
||||
|
||||
/* Open a file and write data to it */
|
||||
/* file = open(entry->pathToFileOrPointerToMemory); */
|
||||
CO_LOCK_OD(CANmodule);
|
||||
/* write(entry->addr, entry->len, file); */
|
||||
CO_UNLOCK_OD(CANmodule);
|
||||
|
||||
return ODR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function for restoring data on "Restore default parameters" command - OD 1011
|
||||
*
|
||||
* For more information see file CO_storage.h, CO_storage_entry_t.
|
||||
*/
|
||||
static ODR_t restoreBlank(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule){
|
||||
|
||||
/* disable (delete) the file, so default values will stay after startup */
|
||||
|
||||
return ODR_OK;
|
||||
}
|
||||
|
||||
|
||||
CO_ReturnError_t CO_storageBlank_init(CO_storage_t *storage,
|
||||
CO_CANmodule_t *CANmodule,
|
||||
OD_entry_t *OD_1010_StoreParameters,
|
||||
OD_entry_t *OD_1011_RestoreDefaultParam,
|
||||
CO_storage_entry_t *entries,
|
||||
uint8_t entriesCount,
|
||||
uint32_t *storageInitError)
|
||||
{
|
||||
CO_ReturnError_t ret;
|
||||
|
||||
/* verify arguments */
|
||||
if (storage == NULL || entries == NULL || entriesCount == 0
|
||||
|| storageInitError == NULL
|
||||
) {
|
||||
return CO_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
/* initialize storage and OD extensions */
|
||||
ret = CO_storage_init(storage,
|
||||
CANmodule,
|
||||
OD_1010_StoreParameters,
|
||||
OD_1011_RestoreDefaultParam,
|
||||
storeBlank,
|
||||
restoreBlank,
|
||||
entries,
|
||||
entriesCount);
|
||||
if (ret != CO_ERROR_NO) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize entries */
|
||||
*storageInitError = 0;
|
||||
for (uint8_t i = 0; i < entriesCount; i++) {
|
||||
CO_storage_entry_t *entry = &entries[i];
|
||||
|
||||
/* verify arguments */
|
||||
if (entry->addr == NULL || entry->len == 0 || entry->subIndexOD < 2) {
|
||||
*storageInitError = i;
|
||||
return CO_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Open a file and read data from file to entry->addr */
|
||||
/* file = open(entry->pathToFileOrPointerToMemory); */
|
||||
/* read(entry->addr, entry->len, file); */
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */
|
||||
56
example/CO_storageBlank.h
Normal file
56
example/CO_storageBlank.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* CANopen data storage object (blank example)
|
||||
*
|
||||
* @file CO_storageBlank.h
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2021 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
* For more information on CANopen see <http://www.can-cia.org/>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef CO_STORAGE_BLANK_H
|
||||
#define CO_STORAGE_BLANK_H
|
||||
|
||||
#include "301/CO_storage.h"
|
||||
|
||||
#if ((CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE) || defined CO_DOXYGEN
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* See socketCAN/storageLinux.h and 301/CO_storage.h for information and
|
||||
* full example */
|
||||
|
||||
CO_ReturnError_t CO_storageBlank_init(CO_storage_t *storage,
|
||||
CO_CANmodule_t *CANmodule,
|
||||
OD_entry_t *OD_1010_StoreParameters,
|
||||
OD_entry_t *OD_1011_RestoreDefaultParam,
|
||||
CO_storage_entry_t *entries,
|
||||
uint8_t entriesCount,
|
||||
uint32_t *storageInitError);
|
||||
|
||||
uint32_t CO_storageBlank_auto_process(CO_storage_t *storage,
|
||||
bool_t closeFiles);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE */
|
||||
|
||||
#endif /* CO_STORAGE_BLANK_H */
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
DRV_SRC = .
|
||||
CANOPEN_SRC = ..
|
||||
OD_SRC = .
|
||||
APPL_SRC = .
|
||||
|
||||
|
||||
|
|
@ -13,39 +12,34 @@ LINK_TARGET = canopennode_blank
|
|||
INCLUDE_DIRS = \
|
||||
-I$(DRV_SRC) \
|
||||
-I$(CANOPEN_SRC) \
|
||||
-I$(OD_SRC) \
|
||||
-I$(APPL_SRC)
|
||||
|
||||
|
||||
SOURCES = \
|
||||
$(DRV_SRC)/CO_driver_blank.c \
|
||||
$(DRV_SRC)/eeprom.c \
|
||||
$(DRV_SRC)/CO_storageBlank.c \
|
||||
$(CANOPEN_SRC)/301/CO_ODinterface.c \
|
||||
$(CANOPEN_SRC)/301/CO_SDOserver.c \
|
||||
$(CANOPEN_SRC)/301/CO_Emergency.c \
|
||||
$(CANOPEN_SRC)/301/CO_NMT_Heartbeat.c \
|
||||
$(CANOPEN_SRC)/301/CO_HBconsumer.c \
|
||||
$(CANOPEN_SRC)/301/CO_Emergency.c \
|
||||
$(CANOPEN_SRC)/301/CO_SDOserver.c \
|
||||
$(CANOPEN_SRC)/301/CO_TIME.c \
|
||||
$(CANOPEN_SRC)/301/CO_SYNC.c \
|
||||
$(CANOPEN_SRC)/301/CO_PDO.c \
|
||||
$(CANOPEN_SRC)/301/CO_TIME.c \
|
||||
$(CANOPEN_SRC)/301/CO_SDOclient.c \
|
||||
$(CANOPEN_SRC)/301/crc16-ccitt.c \
|
||||
$(CANOPEN_SRC)/301/CO_fifo.c \
|
||||
$(CANOPEN_SRC)/301/CO_storage.c \
|
||||
$(CANOPEN_SRC)/303/CO_LEDs.c \
|
||||
$(CANOPEN_SRC)/304/CO_GFC.c \
|
||||
$(CANOPEN_SRC)/304/CO_SRDO.c \
|
||||
$(CANOPEN_SRC)/305/CO_LSSslave.c \
|
||||
$(CANOPEN_SRC)/305/CO_LSSmaster.c \
|
||||
$(CANOPEN_SRC)/309/CO_gateway_ascii.c \
|
||||
$(CANOPEN_SRC)/extra/CO_trace.c \
|
||||
$(CANOPEN_SRC)/CANopen.c \
|
||||
$(OD_SRC)/CO_OD.c \
|
||||
$(APPL_SRC)/main_blank.c
|
||||
$(APPL_SRC)/OD.c \
|
||||
$(DRV_SRC)/main_blank.c
|
||||
|
||||
|
||||
OBJS = $(SOURCES:%.c=%.o)
|
||||
CC ?= gcc
|
||||
OPT = -g
|
||||
OPT =
|
||||
OPT += -g
|
||||
#OPT += -DCO_USE_GLOBALS
|
||||
#OPT += -DCO_MULTIPLE_OD
|
||||
CFLAGS = -Wall $(OPT) $(INCLUDE_DIRS)
|
||||
LDFLAGS =
|
||||
|
||||
|
|
|
|||
176
example/eeprom.c
176
example/eeprom.c
|
|
@ -1,176 +0,0 @@
|
|||
/**
|
||||
* Microcontroller specific code for CANopenNode nonvolatile variables.
|
||||
*
|
||||
* This file is a template for other microcontrollers.
|
||||
*
|
||||
* @file eeprom.h
|
||||
* @ingroup CO_eeprom
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2004 - 2020 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
* For more information on CANopen see <http://www.can-cia.org/>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "301/CO_driver.h"
|
||||
#include "301/CO_SDOserver.h"
|
||||
#include "301/CO_Emergency.h"
|
||||
#include "301/crc16-ccitt.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
|
||||
/**
|
||||
* OD function for accessing _Store parameters_ (index 0x1010) from SDO server.
|
||||
*
|
||||
* For more information see file CO_SDOserver.h.
|
||||
*/
|
||||
static CO_SDO_abortCode_t CO_ODF_1010(CO_ODF_arg_t *ODF_arg);
|
||||
static CO_SDO_abortCode_t CO_ODF_1010(CO_ODF_arg_t *ODF_arg){
|
||||
//CO_EE_t *ee;
|
||||
uint32_t value;
|
||||
CO_SDO_abortCode_t ret = CO_SDO_AB_NONE;
|
||||
|
||||
//ee = (CO_EE_t*) ODF_arg->object;
|
||||
value = CO_getUint32(ODF_arg->data);
|
||||
|
||||
if(!ODF_arg->reading){
|
||||
/* don't change the old value */
|
||||
memcpy(ODF_arg->data, ODF_arg->ODdataStorage, 4);
|
||||
|
||||
if(ODF_arg->subIndex == 1U){
|
||||
if(value == 0x65766173UL){
|
||||
/* write ee->OD_ROMAddress, ee->OD_ROMSize to eeprom (blocking function) */
|
||||
|
||||
/* verify data */
|
||||
if(0/*error*/){
|
||||
ret = CO_SDO_AB_HW;
|
||||
}
|
||||
}
|
||||
else{
|
||||
ret = CO_SDO_AB_DATA_TRANSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OD function for accessing _Restore default parameters_ (index 0x1011) from SDO server.
|
||||
*
|
||||
* For more information see file CO_SDOserver.h.
|
||||
*/
|
||||
static CO_SDO_abortCode_t CO_ODF_1011(CO_ODF_arg_t *ODF_arg);
|
||||
static CO_SDO_abortCode_t CO_ODF_1011(CO_ODF_arg_t *ODF_arg){
|
||||
//CO_EE_t *ee;
|
||||
uint32_t value;
|
||||
CO_SDO_abortCode_t ret = CO_SDO_AB_NONE;
|
||||
|
||||
//ee = (CO_EE_t*) ODF_arg->object;
|
||||
value = CO_getUint32(ODF_arg->data);
|
||||
|
||||
if(!ODF_arg->reading){
|
||||
/* don't change the old value */
|
||||
memcpy(ODF_arg->data, ODF_arg->ODdataStorage, 4);
|
||||
|
||||
if(ODF_arg->subIndex >= 1U){
|
||||
if(value == 0x64616F6CUL){
|
||||
/* Clear the eeprom */
|
||||
|
||||
}
|
||||
else{
|
||||
ret = CO_SDO_AB_DATA_TRANSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
CO_ReturnError_t CO_EE_init_1(
|
||||
CO_EE_t *ee,
|
||||
uint8_t *OD_EEPROMAddress,
|
||||
uint32_t OD_EEPROMSize,
|
||||
uint8_t *OD_ROMAddress,
|
||||
uint32_t OD_ROMSize)
|
||||
{
|
||||
/* verify arguments */
|
||||
if(ee==NULL || OD_EEPROMAddress==NULL || OD_ROMAddress==NULL){
|
||||
return CO_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
/* Configure eeprom */
|
||||
|
||||
|
||||
/* configure object variables */
|
||||
ee->OD_EEPROMAddress = OD_EEPROMAddress;
|
||||
ee->OD_EEPROMSize = OD_EEPROMSize;
|
||||
ee->OD_ROMAddress = OD_ROMAddress;
|
||||
ee->OD_ROMSize = OD_ROMSize;
|
||||
ee->OD_EEPROMCurrentIndex = 0U;
|
||||
ee->OD_EEPROMWriteEnable = false;
|
||||
|
||||
/* read the CO_OD_EEPROM from EEPROM, first verify, if data are OK */
|
||||
|
||||
/* read the CO_OD_ROM from EEPROM and verify CRC */
|
||||
|
||||
return CO_ERROR_NO;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
void CO_EE_init_2(
|
||||
CO_EE_t *ee,
|
||||
CO_ReturnError_t eeStatus,
|
||||
CO_SDO_t *SDO,
|
||||
CO_EM_t *em)
|
||||
{
|
||||
CO_OD_configure(SDO, OD_H1010_STORE_PARAM_FUNC, CO_ODF_1010, (void*)ee, 0, 0U);
|
||||
CO_OD_configure(SDO, OD_H1011_REST_PARAM_FUNC, CO_ODF_1011, (void*)ee, 0, 0U);
|
||||
if(eeStatus != CO_ERROR_NO){
|
||||
CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE, (uint32_t)eeStatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
void CO_EE_process(CO_EE_t *ee){
|
||||
if((ee != 0) && (ee->OD_EEPROMWriteEnable)/* && !isWriteInProcess()*/){
|
||||
uint32_t i;
|
||||
uint8_t RAMdata, eeData;
|
||||
|
||||
/* verify next word */
|
||||
if(++ee->OD_EEPROMCurrentIndex == ee->OD_EEPROMSize){
|
||||
ee->OD_EEPROMCurrentIndex = 0U;
|
||||
}
|
||||
i = ee->OD_EEPROMCurrentIndex;
|
||||
|
||||
/* read eeprom */
|
||||
RAMdata = ee->OD_EEPROMAddress[i];
|
||||
eeData = 0/*EE_readByte(i)*/;
|
||||
|
||||
/* if bytes in EEPROM and in RAM are different, then write to EEPROM */
|
||||
if(eeData != RAMdata){
|
||||
/* EE_writeByteNoWait(RAMdata, i);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
108
example/eeprom.h
108
example/eeprom.h
|
|
@ -1,108 +0,0 @@
|
|||
/**
|
||||
* Eeprom object for generic microcontroller.
|
||||
*
|
||||
* This file is a template for other microcontrollers.
|
||||
*
|
||||
* @file eeprom.h
|
||||
* @ingroup CO_eeprom
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2004 - 2020 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
* For more information on CANopen see <http://www.can-cia.org/>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EEPROM_H
|
||||
#define EEPROM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup CO_eeprom Nonvolatile storage
|
||||
* @ingroup CO_CANopen_extra
|
||||
* @{
|
||||
*
|
||||
* Storage of nonvolatile CANopen variables into the eeprom.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Eeprom object.
|
||||
*/
|
||||
typedef struct{
|
||||
uint8_t *OD_EEPROMAddress; /**< From CO_EE_init_1() */
|
||||
uint32_t OD_EEPROMSize; /**< From CO_EE_init_1() */
|
||||
uint8_t *OD_ROMAddress; /**< From CO_EE_init_1() */
|
||||
uint32_t OD_ROMSize; /**< From CO_EE_init_1() */
|
||||
uint32_t OD_EEPROMCurrentIndex; /**< Internal variable controls the OD_EEPROM vrite */
|
||||
bool_t OD_EEPROMWriteEnable; /**< Writing to EEPROM is enabled */
|
||||
}CO_EE_t;
|
||||
|
||||
|
||||
/**
|
||||
* First part of eeprom initialization. Called after microcontroller reset.
|
||||
*
|
||||
* @param ee This object will be initialized.
|
||||
* @param OD_EEPROMAddress Address of OD_EEPROM structure from object dictionary.
|
||||
* @param OD_EEPROMSize Size of OD_EEPROM structure from object dictionary.
|
||||
* @param OD_ROMAddress Address of OD_ROM structure from object dictionary.
|
||||
* @param OD_ROMSize Size of OD_ROM structure from object dictionary.
|
||||
*
|
||||
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_DATA_CORRUPT (Data in eeprom corrupt) or
|
||||
* CO_ERROR_CRC (CRC from MBR does not match the CRC of OD_ROM block in eeprom).
|
||||
*/
|
||||
CO_ReturnError_t CO_EE_init_1(
|
||||
CO_EE_t *ee,
|
||||
uint8_t *OD_EEPROMAddress,
|
||||
uint32_t OD_EEPROMSize,
|
||||
uint8_t *OD_ROMAddress,
|
||||
uint32_t OD_ROMSize);
|
||||
|
||||
|
||||
/**
|
||||
* Second part of eeprom initialization. Called after CANopen communication reset.
|
||||
*
|
||||
* @param ee - This object.
|
||||
* @param eeStatus - Return value from CO_EE_init_1().
|
||||
* @param SDO - SDO object.
|
||||
* @param em - Emergency object.
|
||||
*/
|
||||
void CO_EE_init_2(
|
||||
CO_EE_t *ee,
|
||||
CO_ReturnError_t eeStatus,
|
||||
CO_SDO_t *SDO,
|
||||
CO_EM_t *em);
|
||||
|
||||
|
||||
/**
|
||||
* Process eeprom object.
|
||||
*
|
||||
* Function must be called cyclically. It strores variables from OD_EEPROM data
|
||||
* block into eeprom byte by byte (only if values are different).
|
||||
*
|
||||
* @param ee This object.
|
||||
*/
|
||||
void CO_EE_process(CO_EE_t *ee);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* @file main_generic.c
|
||||
* @author Janez Paternoster
|
||||
* @copyright 2004 - 2020 Janez Paternoster
|
||||
* @copyright 2021 Janez Paternoster
|
||||
*
|
||||
* This file is part of CANopenNode, an opensource CANopen Stack.
|
||||
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
||||
|
|
@ -28,36 +28,63 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "CANopen.h"
|
||||
#include "OD.h"
|
||||
#include "CO_storageBlank.h"
|
||||
|
||||
|
||||
#define TMR_TASK_INTERVAL (1000) /* Interval of tmrTask thread in microseconds */
|
||||
#define INCREMENT_1MS(var) (var++) /* Increment 1ms variable in tmrTask */
|
||||
|
||||
#define log_printf(macropar_message, ...) \
|
||||
printf(macropar_message, ##__VA_ARGS__)
|
||||
|
||||
|
||||
/* Global variables and objects */
|
||||
volatile uint16_t CO_timer1ms = 0U; /* variable increments each millisecond */
|
||||
uint8_t LED_red, LED_green;
|
||||
/* default values for CO_CANopenInit() */
|
||||
#define NMT_CONTROL \
|
||||
CO_NMT_STARTUP_TO_OPERATIONAL \
|
||||
| CO_NMT_ERR_ON_ERR_REG \
|
||||
| CO_ERR_REG_GENERIC_ERR \
|
||||
| CO_ERR_REG_COMMUNICATION
|
||||
#define FIRST_HB_TIME 500
|
||||
#define SDO_SRV_TIMEOUT_TIME 1000
|
||||
#define SDO_CLI_TIMEOUT_TIME 500
|
||||
#define SDO_CLI_BLOCK false
|
||||
#define OD_STATUS_BITS NULL
|
||||
|
||||
|
||||
/* Global variables and objects */
|
||||
CO_t *CO = NULL; /* CANopen object */
|
||||
uint8_t LED_red, LED_green;
|
||||
|
||||
|
||||
/* main ***********************************************************************/
|
||||
int main (void){
|
||||
CO_ReturnError_t err;
|
||||
CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
|
||||
uint32_t heapMemoryUsed;
|
||||
void *CANmoduleAddress = NULL; /* CAN module address */
|
||||
void *CANptr = NULL; /* CAN module address */
|
||||
uint8_t pendingNodeId = 10; /* read from dip switches or nonvolatile memory, configurable by LSS slave */
|
||||
uint8_t activeNodeId = 10; /* Copied from CO_pendingNodeId in the communication reset section */
|
||||
uint16_t pendingBitRate = 125; /* read from dip switches or nonvolatile memory, configurable by LSS slave */
|
||||
|
||||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
|
||||
CO_storage_t storage;
|
||||
CO_storage_entry_t storageEntries[] = {
|
||||
{
|
||||
.addr = &OD_PERSIST_COMM,
|
||||
.len = sizeof(OD_PERSIST_COMM),
|
||||
.subIndexOD = 2,
|
||||
.attr = CO_storage_cmd | CO_storage_restore,
|
||||
.addrNV = NULL
|
||||
}
|
||||
};
|
||||
uint8_t storageEntriesCount = sizeof(storageEntries) / sizeof(storageEntries[0]);
|
||||
uint32_t storageInitError = 0;
|
||||
#endif
|
||||
|
||||
/* Configure microcontroller. */
|
||||
|
||||
|
||||
/* Allocate memory */
|
||||
err = CO_new(&heapMemoryUsed);
|
||||
if (err != CO_ERROR_NO) {
|
||||
CO = CO_new(NULL, &heapMemoryUsed);
|
||||
if (CO == NULL) {
|
||||
log_printf("Error: Can't allocate memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -65,38 +92,75 @@ int main (void){
|
|||
log_printf("Allocated %u bytes for CANopen objects\n", heapMemoryUsed);
|
||||
}
|
||||
|
||||
/* initialize EEPROM */
|
||||
|
||||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
|
||||
err = CO_storageBlank_init(&storage,
|
||||
CO->CANmodule,
|
||||
OD_ENTRY_H1010_storeParameters,
|
||||
OD_ENTRY_H1011_restoreDefaultParameters,
|
||||
storageEntries,
|
||||
storageEntriesCount,
|
||||
&storageInitError);
|
||||
|
||||
/* increase variable each startup. Variable is stored in EEPROM. */
|
||||
OD_powerOnCounter++;
|
||||
|
||||
log_printf("CANopenNode - Reset application, count = %d\n", OD_powerOnCounter);
|
||||
if (err != CO_ERROR_NO && err != CO_ERROR_DATA_CORRUPT) {
|
||||
log_printf("Error: Storage %d\n", storageInitError);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
while(reset != CO_RESET_APP){
|
||||
/* CANopen communication reset - initialize CANopen objects *******************/
|
||||
uint16_t timer1msPrevious;
|
||||
|
||||
log_printf("CANopenNode - Reset communication...\n");
|
||||
|
||||
/* disable CAN and CAN interrupts */
|
||||
/* Wait rt_thread. */
|
||||
CO->CANmodule->CANnormal = false;
|
||||
|
||||
/* Enter CAN configuration. */
|
||||
CO_CANsetConfigurationMode((void *)&CANptr);
|
||||
CO_CANmodule_disable(CO->CANmodule);
|
||||
|
||||
/* initialize CANopen */
|
||||
err = CO_CANinit(CANmoduleAddress, pendingBitRate);
|
||||
err = CO_CANinit(CO, CANptr, pendingBitRate);
|
||||
if (err != CO_ERROR_NO) {
|
||||
log_printf("Error: CAN initialization failed: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
err = CO_LSSinit(&pendingNodeId, &pendingBitRate);
|
||||
|
||||
CO_LSS_address_t lssAddress = {.identity = {
|
||||
.vendorID = OD_PERSIST_COMM.x1018_identity.vendor_ID,
|
||||
.productCode = OD_PERSIST_COMM.x1018_identity.productCode,
|
||||
.revisionNumber = OD_PERSIST_COMM.x1018_identity.revisionNumber,
|
||||
.serialNumber = OD_PERSIST_COMM.x1018_identity.serialNumber
|
||||
}};
|
||||
err = CO_LSSinit(CO, &lssAddress, &pendingNodeId, &pendingBitRate);
|
||||
if(err != CO_ERROR_NO) {
|
||||
log_printf("Error: LSS slave initialization failed: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
uint8_t activeNodeId = pendingNodeId;
|
||||
err = CO_CANopenInit(activeNodeId);
|
||||
|
||||
activeNodeId = pendingNodeId;
|
||||
uint32_t errInfo = 0;
|
||||
|
||||
err = CO_CANopenInit(CO, /* CANopen object */
|
||||
NULL, /* alternate NMT */
|
||||
NULL, /* alternate em */
|
||||
OD, /* Object dictionary */
|
||||
OD_STATUS_BITS, /* Optional OD_statusBits */
|
||||
NMT_CONTROL, /* CO_NMT_control_t */
|
||||
FIRST_HB_TIME, /* firstHBTime_ms */
|
||||
SDO_SRV_TIMEOUT_TIME, /* SDOserverTimeoutTime_ms */
|
||||
SDO_CLI_TIMEOUT_TIME, /* SDOclientTimeoutTime_ms */
|
||||
SDO_CLI_BLOCK, /* SDOclientBlockTransfer */
|
||||
activeNodeId,
|
||||
&errInfo);
|
||||
if(err != CO_ERROR_NO && err != CO_ERROR_NODE_ID_UNCONFIGURED_LSS) {
|
||||
log_printf("Error: CANopen initialization failed: %d\n", err);
|
||||
if (err == CO_ERROR_OD_PARAMETERS) {
|
||||
log_printf("Error: Object Dictionary entry 0x%X\n", errInfo);
|
||||
}
|
||||
else {
|
||||
log_printf("Error: CANopen initialization failed: %d\n", err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -109,35 +173,39 @@ int main (void){
|
|||
/* Configure CANopen callbacks, etc */
|
||||
if(!CO->nodeIdUnconfigured) {
|
||||
|
||||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
|
||||
if(storageInitError != 0) {
|
||||
CO_errorReport(CO->em, CO_EM_NON_VOLATILE_MEMORY,
|
||||
CO_EMC_HARDWARE, storageInitError);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log_printf("CANopenNode - Node-id not initialized\n");
|
||||
}
|
||||
|
||||
|
||||
/* start CAN */
|
||||
CO_CANsetNormalMode(CO->CANmodule[0]);
|
||||
CO_CANsetNormalMode(CO->CANmodule);
|
||||
|
||||
reset = CO_RESET_NOT;
|
||||
timer1msPrevious = CO_timer1ms;
|
||||
|
||||
log_printf("CANopenNode - Running...\n");
|
||||
fflush(stdout);
|
||||
|
||||
while(reset == CO_RESET_NOT){
|
||||
/* loop for normal program execution ******************************************/
|
||||
uint16_t timer1msCopy, timer1msDiff;
|
||||
|
||||
timer1msCopy = CO_timer1ms;
|
||||
timer1msDiff = timer1msCopy - timer1msPrevious;
|
||||
timer1msPrevious = timer1msCopy;
|
||||
|
||||
/* get time difference since last function call */
|
||||
uint32_t timeDifference_us = 500;
|
||||
|
||||
/* CANopen process */
|
||||
reset = CO_process(CO, (uint32_t)timer1msDiff*1000, NULL);
|
||||
reset = CO_process(CO, false, timeDifference_us, NULL);
|
||||
LED_red = CO_LED_RED(CO->LEDs, CO_LED_CANopen);
|
||||
LED_green = CO_LED_GREEN(CO->LEDs, CO_LED_CANopen);
|
||||
|
||||
/* Nonblocking application code may go here. */
|
||||
|
||||
/* Process EEPROM */
|
||||
/* Process automatic storage */
|
||||
|
||||
/* optional sleep for short time */
|
||||
}
|
||||
|
|
@ -149,7 +217,8 @@ int main (void){
|
|||
|
||||
|
||||
/* delete objects from memory */
|
||||
CO_delete((void*) 0/* CAN module address */);
|
||||
CO_CANsetConfigurationMode((void *)&CANptr);
|
||||
CO_delete(CO);
|
||||
|
||||
log_printf("CANopenNode finished\n");
|
||||
|
||||
|
|
@ -162,30 +231,25 @@ int main (void){
|
|||
void tmrTask_thread(void){
|
||||
|
||||
for(;;) {
|
||||
CO_LOCK_OD(co->CANmodule);
|
||||
if (!CO->nodeIdUnconfigured && CO->CANmodule->CANnormal) {
|
||||
bool_t syncWas = false;
|
||||
/* get time difference since last function call */
|
||||
uint32_t timeDifference_us = 1000;
|
||||
|
||||
/* sleep for interval */
|
||||
|
||||
INCREMENT_1MS(CO_timer1ms);
|
||||
|
||||
if(CO->CANmodule[0]->CANnormal) {
|
||||
bool_t syncWas;
|
||||
|
||||
/* Process Sync */
|
||||
syncWas = CO_process_SYNC(CO, TMR_TASK_INTERVAL, NULL);
|
||||
|
||||
/* Read inputs */
|
||||
CO_process_RPDO(CO, syncWas);
|
||||
#if (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE
|
||||
syncWas = CO_process_SYNC(CO, timeDifference_us, NULL);
|
||||
#endif
|
||||
#if (CO_CONFIG_PDO) & CO_CONFIG_RPDO_ENABLE
|
||||
CO_process_RPDO(CO, syncWas, timeDifference_us, NULL);
|
||||
#endif
|
||||
#if (CO_CONFIG_PDO) & CO_CONFIG_TPDO_ENABLE
|
||||
CO_process_TPDO(CO, syncWas, timeDifference_us, NULL);
|
||||
#endif
|
||||
|
||||
/* Further I/O or nonblocking application code may go here. */
|
||||
|
||||
/* Write outputs */
|
||||
CO_process_TPDO(CO, syncWas, TMR_TASK_INTERVAL, NULL);
|
||||
|
||||
/* verify timer overflow */
|
||||
if(0) {
|
||||
CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0U);
|
||||
}
|
||||
}
|
||||
CO_UNLOCK_OD(co->CANmodule);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ extern "C" {
|
|||
#define DBG_WRONG_NODE_ID "(%s) Wrong node ID \"%d\"", __func__
|
||||
#define DBG_WRONG_PRIORITY "(%s) Wrong RT priority \"%d\"", __func__
|
||||
#define DBG_NO_CAN_DEVICE "(%s) Can't find CAN device \"%s\"", __func__
|
||||
#define DBG_OBJECT_DICTIONARY "(%s) Error in Object Dictionary \"%s\"", __func__
|
||||
#define DBG_STORAGE "(%s) Error with storage \"%s\"", __func__
|
||||
#define DBG_OD_ENTRY "(%s) Error in Object Dictionary entry: 0x%X", __func__
|
||||
#define DBG_CAN_OPEN "(%s) CANopen error in %s, err=%d", __func__
|
||||
#define DBG_CAN_OPEN_INFO "CANopen device, Node ID = 0x%02X, %s"
|
||||
|
|
|
|||
|
|
@ -397,9 +397,10 @@ int main (int argc, char *argv[]) {
|
|||
CANptr.can_ifindex = if_nametoindex(CANdevice);
|
||||
}
|
||||
|
||||
/* Valid NodeId is 1..127 or 0xFF(unconfigured) in case of LSSslaveEnabled*/
|
||||
if((CO_pending.nodeId < 1 || CO_pending.nodeId > 127)
|
||||
&& CO_isLSSslaveEnabled(CO)
|
||||
&& CO_pending.nodeId != CO_LSS_NODE_ID_ASSIGNMENT
|
||||
&& (!CO_isLSSslaveEnabled(CO)
|
||||
|| CO_pending.nodeId != CO_LSS_NODE_ID_ASSIGNMENT)
|
||||
) {
|
||||
log_printf(LOG_CRIT, DBG_WRONG_NODE_ID, CO_pending.nodeId);
|
||||
printUsage(argv[0]);
|
||||
|
|
@ -447,7 +448,7 @@ int main (int argc, char *argv[]) {
|
|||
if (err != CO_ERROR_NO && err != CO_ERROR_DATA_CORRUPT) {
|
||||
char *filename = storageInitError < storageEntriesCount
|
||||
? storageEntries[storageInitError].filename : "???";
|
||||
log_printf(LOG_CRIT, DBG_OBJECT_DICTIONARY, filename);
|
||||
log_printf(LOG_CRIT, DBG_STORAGE, filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue