foxBMS  1.0.2
The foxBMS Battery Management System API Documentation
database.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file database.c
44  * @author foxBMS Team
45  * @date 2015-08-18 (date of creation)
46  * @updated 2020-01-17 (date of last update)
47  * @ingroup ENGINE
48  * @prefix DATA
49  *
50  * @brief Database module implementation
51  *
52  * @details Implementation of database module
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "database.h"
57 
58 #include <string.h>
59 
60 /*========== Macros and Definitions =========================================*/
61 /**
62  * Maximum queue timeout time in milliseconds
63  */
64 #define DATA_QUEUE_TIMEOUT_MS ((TickType_t)10u)
65 
66 /**
67  * @brief Length of data Queue
68  */
69 #define DATA_QUEUE_LENGTH (1u)
70 
71 /**
72  * @brief Size of data Queue item
73  */
74 #define DATA_QUEUE_ITEM_SIZE (sizeof(DATA_QUEUE_MESSAGE_s))
75 
76 /**
77  * Maximum number of database entries that can be read or written during one
78  * access call to the database
79  */
80 #define DATA_MAX_ENTRIES_PER_ACCESS (4u)
81 
82 /**
83  * configuration struct of database device
84  */
85 typedef struct DATA_BASE_HEADER {
86  uint8_t nrDatabaseEntries; /*!< number of database entries */
87  DATA_BASE_s *pDatabase; /*!< pointer to the array with the database entries */
89 
90 /**
91  * struct for database queue, contains pointer to data, database entry and access type
92  */
93 typedef struct DATA_QUEUE_MESSAGE {
94  DATA_BLOCK_ACCESS_TYPE_e accesstype; /*!< read or write access type */
95  void *pDatabaseEntry[DATA_MAX_ENTRIES_PER_ACCESS]; /*!< reference by general pointer */
97 
98 /*========== Static Constant and Variable Definitions =======================*/
99 /** handle of the data queue */
100 static QueueHandle_t data_queue;
101 
102 /**
103  * @brief structure for static data queue
104  */
105 static StaticQueue_t dataQueueStructure;
106 
107 /**
108  * @brief size of Queue storage
109  * @details The array to use as the queue's storage area. This must be at
110  * least #DATA_QUEUE_LENGTH * #DATA_QUEUE_ITEM_SIZE
111  */
113 
114 /**
115  * @brief device configuration of database
116  * @details all attributes of device configuration are listed here (pointer to
117  * channel list, number of channels)
118  */
120  .nrDatabaseEntries = sizeof(data_database) / sizeof(DATA_BASE_s), /**< number of blocks (and block headers) */
121  .pDatabase = &data_database[0],
122 };
123 
124 /**
125  * @brief uniqueId to respective database entry selector
126  * @details This array is the link between the uniqueId of a database entry and
127  * the actual position of the database entry in data_database[]
128  */
130 
131 /*========== Extern Constant and Variable Definitions =======================*/
132 
133 /*========== Static Function Prototypes =====================================*/
134 
135 /*========== Static Function Implementations ================================*/
136 
137 /*========== Extern Function Implementations ================================*/
139  STD_RETURN_TYPE_e retval = STD_OK;
140  static_assert((sizeof(data_database) != 0u), "No database defined");
141  /* make sure that no basic assumptions are broken -- since data_database is
142  declared with length DATA_BLOCK_ID_MAX, this assert should never fail */
144  ((sizeof(data_database) / sizeof(DATA_BASE_s)) == (DATA_BLOCK_ID_MAX)), "Database array length error");
145 
146  /* Iterate over database and set respective read/write pointer for each database entry */
147  for (uint16_t i = 0u; i < data_baseHeader.nrDatabaseEntries; i++) {
148  /* Initialize database entry with 0, set write pointer to start of database entry */
149  uint8_t *pStartDatabaseEntryWR = (uint8_t *)data_baseHeader.pDatabase[i].pDatabaseEntry;
150 
151  /* Start after uniqueId entry. Set j'th byte to zero in database entry */
152  for (uint16_t j = 0u; j < (data_baseHeader.pDatabase + i)->datalength; j++) {
153  if (j >= sizeof(DATA_BLOCK_ID_e)) {
154  *pStartDatabaseEntryWR = 0;
155  }
156  pStartDatabaseEntryWR++;
157  }
158  }
159 
160  /* Configure link between uniqueId and database entry array position */
161  for (uint16_t databaseEntry = 0u; databaseEntry < data_baseHeader.nrDatabaseEntries; databaseEntry++) {
162  /* Get pointer to database header entry */
164  /* make sure that the database entry is not a null pointer (which would happen if an entry is missing
165  despite the ID existing) */
166  FAS_ASSERT(pHeader != NULL_PTR);
167  /* Get uniqueId */
168  DATA_BLOCK_ID_e blockId = pHeader->uniqueId;
169  if ((blockId < DATA_BLOCK_ID_MAX) && (databaseEntry < DATA_BLOCK_ID_MAX)) {
170  uniqueIdToDatabaseEntry[blockId] =
171  databaseEntry; /* e.g. uniqueIdToDatabaseEntry[<some id>] = configured database entry index */
172  } else {
173  /* Configuration error -> set retval to #STD_NOT_OK */
174  retval = STD_NOT_OK;
175  }
176  }
177 
178  /* Create a queue capable of containing a pointer of type DATA_QUEUE_MESSAGE_s
179  Data of Messages are passed by pointer as they contain a lot of data. */
181 
182  if (data_queue == NULL_PTR) {
183  /* Failed to create the queue */
184  retval = STD_NOT_OK;
185  }
186  return retval;
187 }
188 
189 void DATA_Task(void) {
190  DATA_QUEUE_MESSAGE_s receiveMessage;
191 
192  if (data_queue != NULL_PTR) {
193  if (xQueueReceive(data_queue, (&receiveMessage), (TickType_t)1) >
194  0) { /* scan queue and wait for a message up to a maximum amount of 1ms (block time) */
195  /* plausibility check, error if first pointer NULL_PTR */
196  FAS_ASSERT(receiveMessage.pDatabaseEntry[0] != NULL_PTR);
197  /* Iterate over pointer array and handle all access operations if pointer != NULL_PTR */
198  for (uint8_t queueEntry = 0u; queueEntry < DATA_MAX_ENTRIES_PER_ACCESS; queueEntry++) {
199  if (receiveMessage.pDatabaseEntry[queueEntry] != NULL_PTR) {
200  /* pointer to passed database struct */
201  void *pPassedDataStruct = receiveMessage.pDatabaseEntry[queueEntry];
202  /* Get access type (read or write) of passed data struct */
203  DATA_BLOCK_ACCESS_TYPE_e accesstype = receiveMessage.accesstype;
204 
205  /* Get pointer to database header entry */
206  DATA_BLOCK_HEADER_s *pHeader1 = (DATA_BLOCK_HEADER_s *)receiveMessage.pDatabaseEntry[queueEntry];
207  uint16_t entryIndex = uniqueIdToDatabaseEntry[(uint16_t)pHeader1->uniqueId];
208  /* Pointer to database struct representation of passed struct */
209  void *pDatabaseStruct = (void *)data_baseHeader.pDatabase[entryIndex].pDatabaseEntry;
210  /* Get datalength of database entry */
211  uint16_t datalength = data_baseHeader.pDatabase[entryIndex].datalength;
212 
213  /* Copy data either into database or passed database struct */
214  if (accesstype == DATA_WRITE_ACCESS) {
215  /* Pointer on datablock header of passed struct */
216  DATA_BLOCK_HEADER_s *pHeader = (DATA_BLOCK_HEADER_s *)pPassedDataStruct;
217  /* Update timestamps in passed database struct and then copy this struct into database */
218  pHeader->previousTimestamp = pHeader->timestamp;
219  pHeader->timestamp = OS_GetTickCount();
220  /* Copy passed struct in database struct */
221  /* memcpy has no return value therefore there is nothing to check: casting to void */
222  (void)memcpy(pDatabaseStruct, pPassedDataStruct, datalength);
223  } else if (accesstype == DATA_READ_ACCESS) {
224  /* Copy database entry in passed struct */
225  /* memcpy has no return value therefore there is nothing to check: casting to void */
226  (void)memcpy(pPassedDataStruct, pDatabaseStruct, datalength);
227  } else {
228  /* invalid database operation */
230  }
231  }
232  }
233  }
234  }
235 }
236 
237 void DATA_DummyFunction(void) {
238 }
239 
240 STD_RETURN_TYPE_e DATA_Read_1_DataBlock(void *pDataToReceiver0) {
241  /* Call write function with maximum number of database entries to prevent duplicated code */
242  return DATA_Read_4_DataBlocks(pDataToReceiver0, NULL_PTR, NULL_PTR, NULL_PTR);
243 }
244 
245 STD_RETURN_TYPE_e DATA_Read_2_DataBlocks(void *pDataToReceiver0, void *pDataToReceiver1) {
246  /* Call write function with maximum number of database entries to prevent duplicated code */
247  return DATA_Read_4_DataBlocks(pDataToReceiver0, pDataToReceiver1, NULL_PTR, NULL_PTR);
248 }
249 
250 STD_RETURN_TYPE_e DATA_Read_3_DataBlocks(void *pDataToReceiver0, void *pDataToReceiver1, void *pDataToReceiver2) {
251  /* Call write function with maximum number of database entries to prevent duplicated code */
252  return DATA_Read_4_DataBlocks(pDataToReceiver0, pDataToReceiver1, pDataToReceiver2, NULL_PTR);
253 }
254 
256  void *pDataToReceiver0,
257  void *pDataToReceiver1,
258  void *pDataToReceiver2,
259  void *pDataToReceiver3) {
260  STD_RETURN_TYPE_e retval = STD_NOT_OK;
261  DATA_QUEUE_MESSAGE_s data_send_msg;
262  TickType_t queuetimeout;
263 
264  queuetimeout = DATA_QUEUE_TIMEOUT_MS / portTICK_RATE_MS;
265  if (queuetimeout == 0) {
266  queuetimeout = 1;
267  }
268 
269  /* prepare send message with attributes of data block */
270  data_send_msg.pDatabaseEntry[0] = pDataToReceiver0;
271  data_send_msg.pDatabaseEntry[1] = pDataToReceiver1;
272  data_send_msg.pDatabaseEntry[2] = pDataToReceiver2;
273  data_send_msg.pDatabaseEntry[3] = pDataToReceiver3;
274  data_send_msg.accesstype = DATA_READ_ACCESS;
275 
276  /* Send a pointer to a message object and */
277  /* maximum block time: queuetimeout */
278  if (pdPASS == xQueueSend(data_queue, (void *)&data_send_msg, queuetimeout)) {
279  retval = STD_OK;
280  }
281  return retval;
282 }
283 
284 STD_RETURN_TYPE_e DATA_Write_1_DataBlock(void *pDataFromSender0) {
285  /* Call write function with maximum number of database entries to prevent duplicated code */
286  return DATA_Write_4_DataBlocks(pDataFromSender0, NULL_PTR, NULL_PTR, NULL_PTR);
287 }
288 
289 STD_RETURN_TYPE_e DATA_Write_2_DataBlocks(void *pDataFromSender0, void *pDataFromSender1) {
290  /* Call write function with maximum number of database entries to prevent duplicated code */
291  return DATA_Write_4_DataBlocks(pDataFromSender0, pDataFromSender1, NULL_PTR, NULL_PTR);
292 }
293 
294 STD_RETURN_TYPE_e DATA_Write_3_DataBlocks(void *pDataFromSender0, void *pDataFromSender1, void *pDataFromSender2) {
295  /* Call write function with maximum number of database entries to prevent duplicated code */
296  return DATA_Write_4_DataBlocks(pDataFromSender0, pDataFromSender1, pDataFromSender2, NULL_PTR);
297 }
298 
300  void *pDataFromSender0,
301  void *pDataFromSender1,
302  void *pDataFromSender2,
303  void *pDataFromSender3) {
304  STD_RETURN_TYPE_e retval = STD_NOT_OK;
305  DATA_QUEUE_MESSAGE_s data_send_msg;
306  TickType_t queuetimeout;
307 
308  queuetimeout = DATA_QUEUE_TIMEOUT_MS / portTICK_RATE_MS;
309  if (queuetimeout == (TickType_t)0) {
310  queuetimeout = 1;
311  }
312 
313  /* prepare send message with attributes of data block */
314  data_send_msg.pDatabaseEntry[0] = pDataFromSender0;
315  data_send_msg.pDatabaseEntry[1] = pDataFromSender1;
316  data_send_msg.pDatabaseEntry[2] = pDataFromSender2;
317  data_send_msg.pDatabaseEntry[3] = pDataFromSender3;
318 
319  data_send_msg.accesstype = DATA_WRITE_ACCESS;
320  /* Send a pointer to a message object and
321  maximum block time: queuetimeout */
322  if (pdPASS == xQueueSend(data_queue, (void *)&data_send_msg, queuetimeout)) {
323  retval = STD_OK;
324  }
325  return retval;
326 }
327 
328 extern bool DATA_DatabaseEntryUpdatedAtLeastOnce(void *pDatabaseEntry) {
329  bool retval = false;
330  DATA_BLOCK_HEADER_s *pHeader = (DATA_BLOCK_HEADER_s *)pDatabaseEntry;
331  if (!((pHeader->timestamp == 0u) && (pHeader->previousTimestamp == 0u))) {
332  /* Only possibility for timestamp AND previous timestamp to be 0 is, if
333  the database entry has never been updated. Thus if this is not the
334  case the database entry must have been updated */
335  retval = true;
336  }
337  return retval;
338 }
339 
340 extern bool DATA_DatabaseEntryUpdatedRecently(void *pDatabaseEntry, uint32_t timeInterval) {
341  bool retval = false;
342  uint32_t currentTimestamp = OS_GetTickCount();
343  DATA_BLOCK_HEADER_s *pHeader = (DATA_BLOCK_HEADER_s *)pDatabaseEntry;
344 
345  /* Unsigned integer arithmetic also works correctly if currentTimestap is
346  larger than pHeader->timestamp (timer overflow), thus no need to use abs() */
347  if (((currentTimestamp - pHeader->timestamp) <= timeInterval) &&
348  (DATA_DatabaseEntryUpdatedAtLeastOnce(pDatabaseEntry) == true)) {
349  /* Difference between current timestamp and last update timestamp is
350  smaller than passed time interval */
351  retval = true;
352  }
353  return retval;
354 }
355 
356 extern bool DATA_DatabaseEntryUpdatedWithinInterval(void *pDatabaseEntry, uint32_t timeInterval) {
357  bool retval = false;
358  uint32_t currentTimestamp = OS_GetTickCount();
359  DATA_BLOCK_HEADER_s *pHeader = (DATA_BLOCK_HEADER_s *)pDatabaseEntry;
360 
361  /* Unsigned integer arithmetic also works correctly if currentTimestap or is
362  larger than pHeader->timestamp (timer overflow), thus no need to use abs() */
363  if (((currentTimestamp - pHeader->timestamp) <= timeInterval) &&
364  ((pHeader->timestamp - pHeader->previousTimestamp) <= timeInterval) &&
365  (DATA_DatabaseEntryUpdatedAtLeastOnce(pDatabaseEntry) == true)) {
366  /* Difference between timestamps is smaller than passed time interval */
367  retval = true;
368  }
369  return retval;
370 }
371 
372 /*========== Externalized Static Function Implementations (Unit Test) =======*/
DATA_QUEUE_LENGTH
#define DATA_QUEUE_LENGTH
Length of data Queue.
Definition: database.c:69
dataQueueStructure
static StaticQueue_t dataQueueStructure
structure for static data queue
Definition: database.c:105
DATA_QUEUE_ITEM_SIZE
#define DATA_QUEUE_ITEM_SIZE
Size of data Queue item.
Definition: database.c:74
DATA_DatabaseEntryUpdatedRecently
bool DATA_DatabaseEntryUpdatedRecently(void *pDatabaseEntry, uint32_t timeInterval)
Checks if passed database entry has been updated within the last time interval.
Definition: database.c:340
data_baseHeader
static const DATA_BASE_HEADER_s data_baseHeader
device configuration of database
Definition: database.c:119
DATA_BASE
Definition: database_cfg.h:66
STD_RETURN_TYPE_e
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
DATA_BASE_HEADER
Definition: database.c:85
DATA_BLOCK_ACCESS_TYPE_e
enum DATA_BLOCK_ACCESS_TYPE DATA_BLOCK_ACCESS_TYPE_e
data block access types (read or write)
DATA_Write_1_DataBlock
STD_RETURN_TYPE_e DATA_Write_1_DataBlock(void *pDataFromSender0)
Stores a datablock in database.
Definition: database.c:284
DATA_Task
void DATA_Task(void)
trigger of database manager
Definition: database.c:189
DATA_DummyFunction
void DATA_DummyFunction(void)
Dummy void function of the database module.
Definition: database.c:237
DATA_MAX_ENTRIES_PER_ACCESS
#define DATA_MAX_ENTRIES_PER_ACCESS
Definition: database.c:80
DATA_Read_4_DataBlocks
STD_RETURN_TYPE_e DATA_Read_4_DataBlocks(void *pDataToReceiver0, void *pDataToReceiver1, void *pDataToReceiver2, void *pDataToReceiver3)
Reads a datablock in database by value.
Definition: database.c:255
DATA_BASE::datalength
uint16_t datalength
Definition: database_cfg.h:68
DATA_QUEUE_TIMEOUT_MS
#define DATA_QUEUE_TIMEOUT_MS
Definition: database.c:64
DATA_WRITE_ACCESS
@ DATA_WRITE_ACCESS
Definition: database.h:96
DATA_Write_3_DataBlocks
STD_RETURN_TYPE_e DATA_Write_3_DataBlocks(void *pDataFromSender0, void *pDataFromSender1, void *pDataFromSender2)
Stores a datablock in database.
Definition: database.c:294
data_queue
static QueueHandle_t data_queue
Definition: database.c:100
FAS_ASSERT
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
data_database
DATA_BASE_s data_database[]
channel configuration of database (data blocks)
Definition: database_cfg.c:169
uniqueIdToDatabaseEntry
static uint16_t uniqueIdToDatabaseEntry[DATA_BLOCK_ID_MAX]
uniqueId to respective database entry selector
Definition: database.c:129
DATA_Read_3_DataBlocks
STD_RETURN_TYPE_e DATA_Read_3_DataBlocks(void *pDataToReceiver0, void *pDataToReceiver1, void *pDataToReceiver2)
Reads a datablock in database by value.
Definition: database.c:250
DATA_QUEUE_MESSAGE_s
struct DATA_QUEUE_MESSAGE DATA_QUEUE_MESSAGE_s
DATA_BASE_HEADER::pDatabase
DATA_BASE_s * pDatabase
Definition: database.c:87
DATA_Write_2_DataBlocks
STD_RETURN_TYPE_e DATA_Write_2_DataBlocks(void *pDataFromSender0, void *pDataFromSender1)
Stores a datablock in database.
Definition: database.c:289
OS_GetTickCount
uint32_t OS_GetTickCount(void)
Returns OS based system tick value.
Definition: os.c:182
DATA_DatabaseEntryUpdatedWithinInterval
bool DATA_DatabaseEntryUpdatedWithinInterval(void *pDatabaseEntry, uint32_t timeInterval)
Checks if passed database entry has been periodically updated within the time interval.
Definition: database.c:356
STD_OK
@ STD_OK
Definition: fstd_types.h:72
DATA_READ_ACCESS
@ DATA_READ_ACCESS
Definition: database.h:97
STD_NOT_OK
@ STD_NOT_OK
Definition: fstd_types.h:73
DATA_BLOCKHEADER::previousTimestamp
uint32_t previousTimestamp
Definition: database_cfg.h:111
static_assert
#define static_assert(cond, msg)
static assertion macro
Definition: fassert.h:252
DATA_QUEUE_MESSAGE::accesstype
DATA_BLOCK_ACCESS_TYPE_e accesstype
Definition: database.c:94
DATA_QUEUE_MESSAGE
Definition: database.c:93
DATA_Read_1_DataBlock
STD_RETURN_TYPE_e DATA_Read_1_DataBlock(void *pDataToReceiver0)
Reads a datablock in database by value.
Definition: database.c:240
DATA_QUEUE_MESSAGE::pDatabaseEntry
void * pDatabaseEntry[DATA_MAX_ENTRIES_PER_ACCESS]
Definition: database.c:95
database.h
Database module header.
NULL_PTR
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:66
DATA_BLOCK_ID_e
enum DATA_BLOCK_ID DATA_BLOCK_ID_e
DATA_DatabaseEntryUpdatedAtLeastOnce
bool DATA_DatabaseEntryUpdatedAtLeastOnce(void *pDatabaseEntry)
Checks if passed database entry has been updated at least once.
Definition: database.c:328
DATA_BASE_HEADER::nrDatabaseEntries
uint8_t nrDatabaseEntries
Definition: database.c:86
DATA_BASE_HEADER_s
struct DATA_BASE_HEADER DATA_BASE_HEADER_s
FAS_TRAP
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:108
dataQueueStorageArea
static uint8_t dataQueueStorageArea[DATA_QUEUE_LENGTH *DATA_QUEUE_ITEM_SIZE]
size of Queue storage
Definition: database.c:112
DATA_Read_2_DataBlocks
STD_RETURN_TYPE_e DATA_Read_2_DataBlocks(void *pDataToReceiver0, void *pDataToReceiver1)
Reads a datablock in database by value.
Definition: database.c:245
DATA_Init
STD_RETURN_TYPE_e DATA_Init(void)
Initialization of database manager.
Definition: database.c:138
DATA_BLOCK_ID_MAX
@ DATA_BLOCK_ID_MAX
Definition: database_cfg.h:104
DATA_BASE::pDatabaseEntry
void * pDatabaseEntry
Definition: database_cfg.h:67
DATA_BLOCKHEADER::timestamp
uint32_t timestamp
Definition: database_cfg.h:110
DATA_Write_4_DataBlocks
STD_RETURN_TYPE_e DATA_Write_4_DataBlocks(void *pDataFromSender0, void *pDataFromSender1, void *pDataFromSender2, void *pDataFromSender3)
Stores a datablock in database.
Definition: database.c:299
DATA_BLOCKHEADER::uniqueId
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:109
DATA_BLOCKHEADER
Definition: database_cfg.h:108