1
0
Fork 0

Pass CO_CANmodule_t argument to all the CO_LOCK_...() and CO_UNLOCK_...() macros.

https://github.com/CANopenNode/CANopenNode/issues/162#issuecomment-777438875
This commit is contained in:
Janez 2021-03-02 21:28:22 +01:00
parent 9b3f329d52
commit fc81777097
17 changed files with 146 additions and 71 deletions

View file

@ -739,7 +739,7 @@ void CO_error(CO_EM_t *em, bool_t setError, const uint8_t errorBit,
#endif
/* safely write data, and increment pointers */
CO_LOCK_EMCY();
CO_LOCK_EMCY(em->CANdevTx);
if (setError) *errorStatusBits |= bitmask;
else *errorStatusBits &= ~bitmask;
@ -763,7 +763,7 @@ void CO_error(CO_EM_t *em, bool_t setError, const uint8_t errorBit,
}
#endif /* (CO_CONFIG_EM) & (CO_CONFIG_EM_PRODUCER | CO_CONFIG_EM_HISTORY) */
CO_UNLOCK_EMCY();
CO_UNLOCK_EMCY(em->CANdevTx);
#if (CO_CONFIG_EM) & CO_CONFIG_FLAG_CALLBACK_PRE
#if (CO_CONFIG_EM) & CO_CONFIG_EM_PRODUCER

View file

@ -70,9 +70,7 @@ OD_size_t OD_readOriginal(OD_stream_t *stream, uint8_t subIndex,
}
}
CO_LOCK_OD();
memcpy(buf, dataOrig, dataLenToCopy);
CO_UNLOCK_OD();
return dataLenToCopy;
}
@ -127,9 +125,7 @@ OD_size_t OD_writeOriginal(OD_stream_t *stream, uint8_t subIndex,
return 0;
}
CO_LOCK_OD();
memcpy(dataOrig, buf, dataLenToCopy);
CO_UNLOCK_OD();
return dataLenToCopy;
}

View file

@ -404,6 +404,10 @@ OD_entry_t *OD_find(OD_t *od, uint16_t index);
* Find sub-object with specified sub-index on OD entry returned by OD_find.
* Function populates io structure with sub-object data.
*
* @warning
* Read and write functions may be called from different threads, so critical
* sections in custom functions must be observed, see @ref CO_critical_sections.
*
* @param entry OD entry returned by @ref OD_find().
* @param subIndex Sub-index of the variable from the OD object.
* @param [out] io Structure will be populated on success.
@ -428,6 +432,21 @@ static inline uint16_t OD_getIndex(const OD_entry_t *entry) {
}
/**
* Check, if OD variable is mappable to PDO or SRDO.
*
* If OD variable is mappable, then it may be necessary to protect read/write
* access from mainline function. See @ref CO_critical_sections.
*
* @param stream Object Dictionary stream object.
*
* @return true, if OD variable is mappable.
*/
static inline bool_t OD_mappable(OD_stream_t *stream) {
return (stream->attribute & (ODA_TRPDO | ODA_TRSRDO)) != 0;
}
/**
* Restart read or write operation on OD variable
*
@ -476,8 +495,7 @@ uint32_t OD_getSDOabCode(ODR_t returnCode);
*
* @warning
* Read and write functions may be called from different threads, so critical
* sections in custom functions must be protected with @ref CO_LOCK_OD() and
* @ref CO_UNLOCK_OD().
* sections in custom functions must be observed, see @ref CO_critical_sections.
*
* @param entry OD entry returned by @ref OD_find().
* @param extension Extension object, which must be initialized externally.

View file

@ -622,9 +622,13 @@ CO_SDO_return_t CO_SDOclientDownload(CO_SDOclient_t *SDO_C,
}
if (abortCode == CO_SDO_AB_NONE) {
ODR_t odRet;
bool_t lock = OD_mappable(&SDO_C->OD_IO.stream);
/* write data to Object Dictionary */
if (lock) { CO_LOCK_OD(SDO_C->CANdevTx); }
SDO_C->OD_IO.write(&SDO_C->OD_IO.stream, SDO_C->subIndex,
buf, count, &odRet);
if (lock) { CO_UNLOCK_OD(SDO_C->CANdevTx); }
/* verify for errors in write */
if (odRet != ODR_OK && odRet != ODR_PARTIAL) {
@ -1211,11 +1215,14 @@ CO_SDO_return_t CO_SDOclientUpload(CO_SDOclient_t *SDO_C,
? countData : countFifo;
uint8_t buf[countBuf + 1];
ODR_t odRet;
bool_t lock = OD_mappable(&SDO_C->OD_IO.stream);
/* load data from OD variable into the buffer */
if (lock) { CO_LOCK_OD(SDO_C->CANdevTx); }
OD_size_t countRd = SDO_C->OD_IO.read(&SDO_C->OD_IO.stream,
SDO_C->subIndex,
buf, countBuf, &odRet);
if (lock) { CO_UNLOCK_OD(SDO_C->CANdevTx); }
if (odRet != ODR_OK && odRet != ODR_PARTIAL) {
abortCode = (CO_SDO_abortCode_t)OD_getSDOabCode(odRet);

View file

@ -552,8 +552,13 @@ static bool_t validateAndWriteToOD(CO_SDOserver_t *SDO,
/* write data */
ODR_t odRet;
bool_t lock = OD_mappable(&SDO->OD_IO.stream);
if (lock) { CO_LOCK_OD(SDO->CANdevTx); }
SDO->OD_IO.write(&SDO->OD_IO.stream, SDO->subIndex,
SDO->buf, SDO->bufOffsetWr, &odRet);
if (lock) { CO_UNLOCK_OD(SDO->CANdevTx); }
SDO->bufOffsetWr = 0;
/* verify write error value */
@ -609,10 +614,14 @@ static bool_t readFromOd(CO_SDOserver_t *SDO,
/* load data from OD variable into the buffer */
ODR_t odRet;
uint8_t *bufShifted = SDO->buf + countRemain;
bool_t lock = OD_mappable(&SDO->OD_IO.stream);
if (lock) { CO_LOCK_OD(SDO->CANdevTx); }
OD_size_t countRd = SDO->OD_IO.read(&SDO->OD_IO.stream, SDO->subIndex,
bufShifted,
countRdRequest,
&odRet);
if (lock) { CO_UNLOCK_OD(SDO->CANdevTx); }
if (odRet != ODR_OK && odRet != ODR_PARTIAL) {
*abortCode = (CO_SDO_abortCode_t)OD_getSDOabCode(odRet);
@ -843,8 +852,13 @@ CO_SDO_return_t CO_SDOserver_process(CO_SDOserver_t *SDO,
/* Copy data */
ODR_t odRet;
bool_t lock = OD_mappable(&SDO->OD_IO.stream);
if (lock) { CO_LOCK_OD(SDO->CANdevTx); }
SDO->OD_IO.write(&SDO->OD_IO.stream, SDO->subIndex,
buf, dataSizeToWrite, &odRet);
if (lock) { CO_UNLOCK_OD(SDO->CANdevTx); }
if (odRet != ODR_OK) {
abortCode = (CO_SDO_abortCode_t)OD_getSDOabCode(odRet);
SDO->state = CO_SDO_ST_ABORT;
@ -1283,9 +1297,13 @@ CO_SDO_return_t CO_SDOserver_process(CO_SDOserver_t *SDO,
#else /* Expedited transfer only */
/* load data from OD variable */
ODR_t odRet;
bool_t lock = OD_mappable(&SDO->OD_IO.stream);
if (lock) { CO_LOCK_OD(SDO->CANdevTx); }
OD_size_t count = SDO->OD_IO.read(&SDO->OD_IO.stream, SDO->subIndex,
&SDO->CANtxBuff->data[4], 4,
&odRet);
if (lock) { CO_UNLOCK_OD(SDO->CANdevTx); }
/* strings are allowed to be shorter */
if (odRet == ODR_PARTIAL

View file

@ -380,19 +380,30 @@ typedef struct {
* Otherwise mutexes or semaphores can be used.
*
* #### Reentrant functions
* Functions CO_CANsend() from C_driver.h, CO_errorReport() from CO_Emergency.h
* and CO_errorReset() from CO_Emergency.h may be called from different threads.
* Critical sections must be protected. Either by disabling scheduler or
* interrupts or by mutexes or semaphores.
* Functions CO_CANsend() from C_driver.h, and CO_error() from CO_Emergency.h
* may be called from different threads. Critical sections must be protected.
* Either by disabling scheduler or interrupts or by mutexes or semaphores.
* Lock/unlock macro is called with pointer to CAN module, which may be used
* inside.
*
* #### Object Dictionary variables
* In general, there are two threads, which accesses OD variables: mainline and
* timer. CANopenNode initialization and SDO server runs in mainline. PDOs runs
* in faster timer thread. Processing of PDOs must not be interrupted by
* mainline. Mainline thread must protect sections, which accesses the same OD
* variables as timer thread. This care must also take the application. Note
* that not all variables are allowed to be mapped to PDOs, so they may not need
* to be protected. SDO server protects sections with access to OD variables.
* In general, there are two threads, which accesses OD variables: mainline
* (initialization, storage, SDO access) and timer (PDO access). CANopenNode
* uses locking mechanism, where SDO server (or other mainline code) prevents
* execution of the real-time thread at the moment it reads or writes OD
* variable. CO_LOCK_OD(CAN_MODULE) and CO_UNLOCK_OD(CAN_MODULE) macros
* are used to protect:
* - Whole real-time thread,
* - SDO server protects read/write access to OD variable, if specific OD
* variable has ODA_TRPDO or ODA_TRSRDO from @ref OD_attributes_t set. If
* those attributes are not set, OD variable is not locked by SDO server.
* Locking of long OD variables, not accessible from real-time thread, may
* block RT thread.
* - Any mainline code, which accesses PDO-mappable OD variable, must protect
* read/write with locking macros. Use @ref OD_mappable() for check.
* - Other cases, where non-PDO-mappable OD variable is used inside real-time
* thread by some other part of the user application must be considered with
* special care.
*
* #### Synchronization functions for CAN receive
* After CAN message is received, it is pre-processed in CANrx_callback(), which
@ -411,17 +422,17 @@ typedef struct {
*/
/** Lock critical section in CO_CANsend() */
#define CO_LOCK_CAN_SEND()
#define CO_LOCK_CAN_SEND(CAN_MODULE)
/** Unlock critical section in CO_CANsend() */
#define CO_UNLOCK_CAN_SEND()
#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
/** Lock critical section in CO_errorReport() or CO_errorReset() */
#define CO_LOCK_EMCY()
#define CO_LOCK_EMCY(CAN_MODULE)
/** Unlock critical section in CO_errorReport() or CO_errorReset() */
#define CO_UNLOCK_EMCY()
#define CO_UNLOCK_EMCY(CAN_MODULE)
/** Lock critical section when accessing Object Dictionary */
#define CO_LOCK_OD()
#define CO_LOCK_OD(CAN_MODULE)
/** Unock critical section when accessing Object Dictionary */
#define CO_UNLOCK_OD()
#define CO_UNLOCK_OD(CAN_MODULE)
/** Check if new message has arrived */
#define CO_FLAG_READ(rxNew) ((rxNew) != NULL)

View file

@ -65,7 +65,7 @@ static OD_size_t OD_write_1010(OD_stream_t *stream, uint8_t subIndex,
if (subIndex == 1 || entry->subIndexOD == subIndex) {
if (found == 0) found = 1;
if ((entry->attr & CO_storage_cmd) != 0) {
ODR_t code = storage->store(entry);
ODR_t code = storage->store(entry, storage->CANmodule);
if (code != ODR_OK) *returnCode = code;
found = 2;
}
@ -117,7 +117,7 @@ static OD_size_t OD_write_1011(OD_stream_t *stream, uint8_t subIndex,
if (subIndex == 1 || entry->subIndexOD == subIndex) {
if (found == 0) found = 1;
if ((entry->attr & CO_storage_restore) != 0) {
ODR_t code = storage->restore(entry);
ODR_t code = storage->restore(entry, storage->CANmodule);
if (code != ODR_OK) *returnCode = code;
found = 2;
}
@ -131,10 +131,13 @@ static OD_size_t OD_write_1011(OD_stream_t *stream, uint8_t subIndex,
CO_ReturnError_t CO_storage_init(CO_storage_t *storage,
CO_CANmodule_t *CANmodule,
OD_entry_t *OD_1010_StoreParameters,
OD_entry_t *OD_1011_RestoreDefaultParameters,
ODR_t (*store)(CO_storage_entry_t *entry),
ODR_t (*restore)(CO_storage_entry_t *entry),
ODR_t (*store)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule),
ODR_t (*restore)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule),
CO_storage_entry_t *entries,
uint8_t entriesCount)
{
@ -144,6 +147,7 @@ CO_ReturnError_t CO_storage_init(CO_storage_t *storage,
}
/* Configure object variables */
storage->CANmodule = CANmodule;
storage->store = store;
storage->restore = restore;
storage->entries = entries;

View file

@ -104,8 +104,11 @@ typedef enum {
typedef struct {
OD_extension_t OD_1010_extension; /**< Extension for OD object */
OD_extension_t OD_1011_extension; /**< Extension for OD object */
ODR_t (*store)(CO_storage_entry_t *entry); /**< From CO_storage_init() */
ODR_t (*restore)(CO_storage_entry_t *entry); /**< From CO_storage_init() */
CO_CANmodule_t *CANmodule; /**< From CO_storage_init() */
ODR_t (*store)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule); /**< From CO_storage_init() */
ODR_t (*restore)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule); /**< From CO_storage_init() */
CO_storage_entry_t *entries; /**< From CO_storage_init() */
uint8_t entriesCount; /**< From CO_storage_init() */
} CO_storage_t;
@ -121,6 +124,7 @@ typedef struct {
*
* @param storage This object will be initialized. It must be defined by
* application and must exist permanently.
* @param CANmodule CAN device, used for @ref CO_LOCK_OD() macro.
* @param OD_1010_StoreParameters OD entry for 0x1010 -"Store parameters".
* Entry is optional, may be NULL.
* @param OD_1011_RestoreDefaultParameters OD entry for 0x1011 -"Restore default
@ -146,10 +150,13 @@ typedef struct {
* @return CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
*/
CO_ReturnError_t CO_storage_init(CO_storage_t *storage,
CO_CANmodule_t *CANmodule,
OD_entry_t *OD_1010_StoreParameters,
OD_entry_t *OD_1011_RestoreDefaultParameters,
ODR_t (*store)(CO_storage_entry_t *entry),
ODR_t (*restore)(CO_storage_entry_t *entry),
ODR_t (*store)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule),
ODR_t (*restore)(CO_storage_entry_t *entry,
CO_CANmodule_t *CANmodule),
CO_storage_entry_t *entries,
uint8_t entriesCount);

View file

@ -916,6 +916,7 @@ CO_ReturnError_t CO_CANopenInit(CO_t *co,
uint8_t nodeId,
uint32_t *errInfo)
{
(void)SDOclientTimeoutTime_ms; (void)SDOclientBlockTransfer;
CO_ReturnError_t err;
if (co == NULL

View file

@ -23,6 +23,8 @@ The term **OD entry** means structure element, which contains some basic propert
### Access
Application and the stack have access to OD objects via universal @ref OD_t object and @ref OD_find() function. No direct access to custom structures, which define object dictionary, is required. Properties for specific OD variable is fetched with @ref OD_getSub() function. Access to actual variable is via **read** and **write** functions. Pointer to those two functions is fetched by @ref OD_getSub(). See @ref OD_stream_t. See also shortcuts: @ref CO_ODgetSetters, for access to data of different type.
Note that OD variables can be accessed from different threads. CANopenNode basically runs in two threads: fast real-time (PDO processing, etc.) and time non-critical mainline (SDO etc.). Both threads have access to OD variables, so care must be taken into account. CANopenNode uses locking mechanism, where SDO server prevents execution of the real-time thread at the moment it reads or writes OD variable. The same protection of the OD variables is necessary in @ref CO_storage. For more information see @ref CO_critical_sections in CO_driver.h.
### Example usage
```c
extern OD_t *ODxyz;

View file

@ -200,7 +200,7 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer){
err = CO_ERROR_TX_OVERFLOW;
}
CO_LOCK_CAN_SEND();
CO_LOCK_CAN_SEND(CANmodule);
/* if CAN TX buffer is free, copy message to it */
if(1 && CANmodule->CANtxCount == 0){
CANmodule->bufferInhibitFlag = buffer->syncFlag;
@ -211,7 +211,7 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer){
buffer->bufferFull = true;
CANmodule->CANtxCount++;
}
CO_UNLOCK_CAN_SEND();
CO_UNLOCK_CAN_SEND(CANmodule);
return err;
}
@ -221,7 +221,7 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer){
void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule){
uint32_t tpdoDeleted = 0U;
CO_LOCK_CAN_SEND();
CO_LOCK_CAN_SEND(CANmodule);
/* Abort message from CAN module, if there is synchronous TPDO.
* Take special care with this functionality. */
if(/*messageIsOnCanBuffer && */CANmodule->bufferInhibitFlag){
@ -244,7 +244,7 @@ void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule){
buffer++;
}
}
CO_UNLOCK_CAN_SEND();
CO_UNLOCK_CAN_SEND(CANmodule);
if(tpdoDeleted != 0U){

View file

@ -233,16 +233,16 @@ typedef struct {
/* (un)lock critical section in CO_CANsend() */
#define CO_LOCK_CAN_SEND()
#define CO_UNLOCK_CAN_SEND()
#define CO_LOCK_CAN_SEND(CAN_MODULE)
#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
#define CO_LOCK_EMCY()
#define CO_UNLOCK_EMCY()
#define CO_LOCK_EMCY(CAN_MODULE)
#define CO_UNLOCK_EMCY(CAN_MODULE)
/* (un)lock critical section when accessing Object Dictionary */
#define CO_LOCK_OD()
#define CO_UNLOCK_OD()
#define CO_LOCK_OD(CAN_MODULE)
#define CO_UNLOCK_OD(CAN_MODULE)
/* Synchronization between CAN receive and message processing threads. */
#define CO_MemoryBarrier()

View file

@ -370,34 +370,38 @@ typedef struct {
#ifdef CO_SINGLE_THREAD
#define CO_LOCK_CAN_SEND()
#define CO_UNLOCK_CAN_SEND()
#define CO_LOCK_EMCY()
#define CO_UNLOCK_EMCY()
#define CO_LOCK_OD()
#define CO_UNLOCK_OD()
#define CO_LOCK_CAN_SEND(CAN_MODULE)
#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
#define CO_LOCK_EMCY(CAN_MODULE)
#define CO_UNLOCK_EMCY(CAN_MODULE)
#define CO_LOCK_OD(CAN_MODULE)
#define CO_UNLOCK_OD(CAN_MODULE)
#define CO_MemoryBarrier()
#else
/* (un)lock critical section in CO_CANsend() - unused */
#define CO_LOCK_CAN_SEND()
#define CO_UNLOCK_CAN_SEND()
#define CO_LOCK_CAN_SEND(CAN_MODULE)
#define CO_UNLOCK_CAN_SEND(CAN_MODULE)
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
extern pthread_mutex_t CO_EMCY_mutex;
static inline int CO_LOCK_EMCY() {
static inline int CO_LOCK_EMCY(CO_CANmodule_t *CANmodule) {
(void)CANmodule;
return pthread_mutex_lock(&CO_EMCY_mutex);
}
static inline void CO_UNLOCK_EMCY() {
static inline void CO_UNLOCK_EMCY(CO_CANmodule_t *CANmodule) {
(void)CANmodule;
(void)pthread_mutex_unlock(&CO_EMCY_mutex);
}
/* (un)lock critical section when accessing Object Dictionary */
extern pthread_mutex_t CO_OD_mutex;
static inline int CO_LOCK_OD() {
static inline int CO_LOCK_OD(CO_CANmodule_t *CANmodule) {
(void)CANmodule;
return pthread_mutex_lock(&CO_OD_mutex);
}
static inline void CO_UNLOCK_OD() {
static inline void CO_UNLOCK_OD(CO_CANmodule_t *CANmodule) {
(void)CANmodule;
(void)pthread_mutex_unlock(&CO_OD_mutex);
}

View file

@ -329,7 +329,7 @@ void CO_epoll_processRT(CO_epoll_t *ep,
if (!realtime || ep->timerEvent) {
uint32_t *pTimerNext_us = realtime ? NULL : &ep->timerNext_us;
CO_LOCK_OD();
CO_LOCK_OD(co->CANmodule);
if (!co->nodeIdUnconfigured && co->CANmodule->CANnormal) {
bool_t syncWas = false;
@ -346,7 +346,7 @@ void CO_epoll_processRT(CO_epoll_t *ep,
#endif
(void) syncWas; (void) pTimerNext_us;
}
CO_UNLOCK_OD();
CO_UNLOCK_OD(co->CANmodule);
}
}

View file

@ -438,6 +438,7 @@ int main (int argc, char *argv[]) {
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE
uint8_t pendingNodeIdOriginal = CO_pending.nodeId;
err = CO_storageLinux_init(&storage,
CO->CANmodule,
OD_ENTRY_H1010_storeParameters,
OD_ENTRY_H1011_restoreDefaultParameters,
storageEntries,
@ -512,9 +513,9 @@ int main (int argc, char *argv[]) {
/* Wait rt_thread. */
if(!firstRun) {
CO_LOCK_OD();
CO_LOCK_OD(CO->CANmodule);
CO->CANmodule->CANnormal = false;
CO_UNLOCK_OD();
CO_UNLOCK_OD(CO->CANmodule);
}
/* Enter CAN configuration. */
@ -695,17 +696,17 @@ int main (int argc, char *argv[]) {
storageIntervalTimer += epMain.timeDifference_us;
}
else {
uint32_t err = CO_storageLinux_auto_process(&storage, false);
if(err != storageErrorPrev && !CO->nodeIdUnconfigured) {
if(err != 0) {
uint32_t mask = CO_storageLinux_auto_process(&storage, false);
if(mask != storageErrorPrev && !CO->nodeIdUnconfigured) {
if(mask != 0) {
CO_errorReport(CO->em, CO_EM_NON_VOLATILE_AUTO_SAVE,
CO_EMC_HARDWARE, err);
CO_EMC_HARDWARE, mask);
}
else {
CO_errorReset(CO->em, CO_EM_NON_VOLATILE_AUTO_SAVE, 0);
}
}
storageErrorPrev = err;
storageErrorPrev = mask;
storageIntervalTimer = 0;
}
#endif

View file

@ -37,7 +37,8 @@
*
* For more information see file CO_storage.h, CO_storage_entry_t.
*/
static ODR_t storeLinux(CO_storage_entry_t *entry) {
static ODR_t storeLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule) {
(void) CANmodule;
ODR_t ret = ODR_OK;
uint16_t crc_store;
@ -64,10 +65,10 @@ static ODR_t storeLinux(CO_storage_entry_t *entry) {
ret = ODR_HW;
}
else {
CO_LOCK_OD();
CO_LOCK_OD(CANmodule);
size_t cnt = fwrite(entry->addr, 1, entry->len, fp);
crc_store = crc16_ccitt(entry->addr, entry->len, 0);
CO_UNLOCK_OD();
CO_UNLOCK_OD(CANmodule);
cnt += fwrite(&crc_store, 1, sizeof(crc_store), fp);
fclose(fp);
if (cnt != (entry->len + sizeof(crc_store))) {
@ -123,7 +124,8 @@ static ODR_t storeLinux(CO_storage_entry_t *entry) {
*
* For more information see file CO_storage.h, CO_storage_entry_t.
*/
static ODR_t restoreLinux(CO_storage_entry_t *entry) {
static ODR_t restoreLinux(CO_storage_entry_t *entry, CO_CANmodule_t *CANmodule){
(void) CANmodule;
ODR_t ret = ODR_OK;
/* close the file first, if auto storage */
@ -161,6 +163,7 @@ static ODR_t restoreLinux(CO_storage_entry_t *entry) {
CO_ReturnError_t CO_storageLinux_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,
@ -168,7 +171,6 @@ CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
uint32_t *storageInitError)
{
CO_ReturnError_t ret;
*storageInitError = 0;
/* verify arguments */
if (storage == NULL || entries == NULL || entriesCount == 0
@ -179,6 +181,7 @@ CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
/* initialize storage and OD extensions */
ret = CO_storage_init(storage,
CANmodule,
OD_1010_StoreParameters,
OD_1011_RestoreDefaultParam,
storeLinux,
@ -190,6 +193,7 @@ CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
}
/* initialize entries */
*storageInitError = 0;
for (uint8_t i = 0; i < entriesCount; i++) {
CO_storage_entry_t *entry = &entries[i];
bool_t dataCorrupt = false;
@ -288,9 +292,9 @@ uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,
if (crc != entry->crc) {
size_t cnt;
rewind(entry->fp);
CO_LOCK_OD();
CO_LOCK_OD(storage->CANmodule);
cnt = fwrite(entry->addr, 1, entry->len, entry->fp);
CO_UNLOCK_OD();
CO_UNLOCK_OD(storage->CANmodule);
cnt += fwrite(&crc, 1, sizeof(crc), entry->fp);
fflush(entry->fp);
if (cnt == (entry->len + sizeof(crc))) {

View file

@ -55,6 +55,7 @@ extern "C" {
*
* @param storage This object will be initialized. It must be defined by
* application and must exist permanently.
* @param CANmodule CAN device, used for @ref CO_LOCK_OD() macro.
* @param OD_1010_StoreParameters OD entry for 0x1010 -"Store parameters".
* Entry is optional, may be NULL.
* @param OD_1011_RestoreDefaultParam OD entry for 0x1011 -"Restore default
@ -70,6 +71,7 @@ extern "C" {
* CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OUT_OF_MEMORY.
*/
CO_ReturnError_t CO_storageLinux_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,