]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/fr_tms570.c
Long switch statements replaced by maps in FlexRay Fr_GetPOCStatus
[pes-rpp/rpp-lib.git] / rpp / src / drv / fr_tms570.c
1 /**
2  * FlexRay Communication driver for TMS570 source file.
3  *
4  * @file fr_rms570.c
5  *
6  * @copyright Copyright (C) 2013 Czech Technical University in Prague
7  *
8  * @author Michal Horn <hornmich@fel.cvut.cz>
9  */
10
11 #include "drv/fr_tms570.h"
12 #include "sys/ti_drv_fray.h"
13 #include "binary.h"
14 #include "hal/port_def.h"
15
16 /**
17  * The structure maps a RX/TX buffer to a slot in the communication cycle.
18  */
19 typedef struct Fr_slot_buffer_map_st {
20         const Fr_TMS570LS_BufferConfigType* buffer_ptr; /**< Address of a buffer configuration assigned to the slot slot_id */
21         uint16_t slot_id; /**< An ID of the slot in the communication cycle. The value may not be equal to the slot_id value in the buffer configuration, after reconfiguration is done. */
22 } Fr_slot_buffer_map_t;
23
24 static Std_VersionInfoType Fr_versionInfo = {
25                 .vendorID = 0x00000001,
26                 .moduleID = 0x00000002,
27                 .sw_major_version = 0,
28                 .sw_minor_version = 1,
29                 .sw_patch_version = 0
30 };
31
32 /** Prepared spi command */
33 static uint32_t fray_spi_cmd = FRAY_SPICMD_INIT_VAL;
34 /** Shadow variable used during command sending */
35 static uint32_t fray_spi_cmd_sh;
36 /** Array of responses for each fray driver */
37 static uint32_t fray_spi_resp[FRAY_NUM_PORTS];
38 /** Array of port names to be easily accessible by indexing */
39 static const char* fray_port_names[FRAY_NUM_PORTS] = { PORT_NAME_FRAY1, PORT_NAME_FRAY2 };
40 /** Array of integers, where FlexRay cluster and node configuration
41  * parameters are stored to be accessible by indexes defined in Fr_GeneralTypes.h.
42  */
43 static uint32_t Fr_ConfigParPtrs[FR_CIDX_CNT];
44 /**
45  * Address of the unified structure with complete configuration of
46  * the FlexRay node (cluster, node, message RAM and buffer configuration)
47  */
48 static const Fr_ConfigType* Fr_Config;
49 /** Map of the buffers to their slot ID */
50 static Fr_slot_buffer_map_t Fr_buffer_slot_map[FR_MAX_BUFFERS_CNT];
51 /** Array of flags to determine if the buffer was or was not configured. */
52 static boolean_t Fr_BuffersConfigured[FR_MAX_BUFFERS_CNT];
53 /**  Array of computed data pointers addresses for each buffer. */
54 static int Fr_MsgRAMDataPtrs[FR_MAX_BUFFERS_CNT];
55 /**
56  * Address of the next free position in message RAM, which can be assigned
57  * to configured buffer. Addresses 32b words.
58  */
59 static uint32_t Fr_MsgRAMDataOffset;
60 /**
61  * Address of the first free position in message RAM, which can be assigned
62  * to the first configured buffer. Addresses 32b words.
63  */
64 static uint32_t Fr_MsgRAMDataStartAddress;
65
66 /**
67  *  Development error detection.
68  *  Comment this line to disable error detection and make function processing
69  *  faster, but more dangerous.
70  */
71
72 #define DET_ACTIVATED
73
74
75 #ifdef DET_ACTIVATED
76 /**
77  * A variable for driver state monitoring. The state value is used in several
78  * functions to determine if they are called in right order.
79  */
80 static Fr_TMS570LS_DriverState Fr_DrvState = FR_ST_DRV_NOT_INITIALIZED;
81 #endif
82
83
84 /**
85  * Create flags according to the index of the buffer, its configuration and node configuration.
86  * Flags created by this function are used in buffer configuration and reconfiguration functions.
87  *
88  * @param[in] buffer_cfg_ptr Address of the buffer configuration parameters
89  * @param[in] index of the buffer to which belong the parameters
90  *
91  * @return Buffer configuration flags. Their definition can be found in fr_tms570.h file as macros with prefixes FRAY_BUF_
92  */
93 uint32_t Fr_buffer_config_flags(const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr, uint8_t bufferIndex) {
94         uint32_t mode = 0;
95
96         mode = (buffer_cfg_ptr->msgBufferInterrupt == TRUE) ? FRAY_BUF_MBI_EN : FRAY_BUF_MBI_DIS;
97         mode |= (buffer_cfg_ptr->singleTransmit == TRUE) ? FRAY_BUF_TX_MODE_SINGLE : FRAY_BUF_TX_MODE_CONTINUOUS;
98         mode |= (buffer_cfg_ptr->payloadPreambleIndicatorTr == TRUE) ? FRAY_BUF_NM_EN : FRAY_BUF_NM_DIS;
99         mode |= (buffer_cfg_ptr->isTx == TRUE) ? FRAY_BUF_TX : FRAY_BUF_RX;
100         mode |= (buffer_cfg_ptr->channel == FR_CHANNEL_A || buffer_cfg_ptr->channel == FR_CHANNEL_AB) ? FRAY_BUF_CHA_EN : FRAY_BUF_CHA_DIS;
101         mode |= (buffer_cfg_ptr->channel == FR_CHANNEL_B || buffer_cfg_ptr->channel == FR_CHANNEL_AB) ? FRAY_BUF_CHB_EN : FRAY_BUF_CHB_DIS;
102         mode |= (buffer_cfg_ptr->rejectNullFrames == TRUE) ? FRAY_BUF_REJECT_NULL_FRAMES : FRAY_BUF_ACCEPT_NULL_FRAMES;
103         mode |= (buffer_cfg_ptr->rejectStaticSegment == TRUE) ? FRAY_BUF_REJECT_STATIC_SEGMENT : FRAY_BUF_ACCEPT_STATIC_SEGMENT;
104         mode |= FRAY_BUF_TXREQ_DIS;
105         if (bufferIndex == 0 || (bufferIndex == 1 && Fr_Config->msgRAMConfig->syncFramePayloadMultiplexEnabled == TRUE)) {      // Buffer 0 is always a key slot, if payload multiplexing is enabled, then buffer 1 serves for key slot as well.
106                 if (Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSTARTUP] == 1) {
107                         mode |= FRAY_BUF_SFI_EN;
108                 }
109                 if (Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSYNC] == 1) {
110                         mode |= FRAY_BUF_SYNC_EN;
111                 }
112         }
113         return mode;
114 }
115
116 /**
117  * Buffer is reconfigurable if it is not assigned to the key slot (slot for
118  * synchronization and startup) and reconfiguration is enabled in ode configuration
119  * parameters.
120  * RX FIFO buffer is never configurable.
121  *
122  * @return -1 if buffer reconfiguration is prohibited, otherwise returns index of the first buffer, which is reconfigurable.
123  */
124 int Fr_reconfigurable_buffer_index() {
125         int lowest_index = -1;
126         if (Fr_Config->msgRAMConfig->secureBuffers == FR_SB_STAT_REC_DISABLED_STAT_TR_DISABLED)
127                 lowest_index = frayREG->MRC_UN.MRC_ST.fdb_B8;
128         else if (Fr_Config->msgRAMConfig->secureBuffers == FR_SB_RECONFIG_ENABLED) {
129                 if (Fr_Config->nodeConfiguration->pKeySlotUsedForSync == TRUE ||
130                         Fr_Config->nodeConfiguration->pSingleSlotEnabled == TRUE
131                         ) {
132                         if (Fr_Config->msgRAMConfig->syncFramePayloadMultiplexEnabled)
133                                 lowest_index = 2;
134                         else
135                                 lowest_index = 1;
136                 }
137                 else
138                         lowest_index = 0;
139         }
140         else {
141                 lowest_index = -1;
142         }
143         return lowest_index;
144 }
145
146 /**
147  *  Compute CRC for message RAM header data
148  *
149  *  @param[in] Fr_LPduPtr   Pointer to header data
150  *  @return CRC code
151  */
152 static int Fr_header_crc_calc(const wrhs *Fr_LPduPtr) {
153   unsigned int header;
154
155   int CrcInit = 0x1A;
156   int length  = 20;
157   int CrcNext;
158   unsigned long CrcPoly  = 0x385;
159   unsigned long CrcReg_X = CrcInit;
160   unsigned long header_temp, reg_temp;
161
162   header  = ((Fr_LPduPtr->sync & 0x1)  << 19) | ((Fr_LPduPtr->sfi & 0x1) << 18);
163   header |= ((Fr_LPduPtr->fid & 0x7FF) <<  7) |  (Fr_LPduPtr->pl & 0x7F);
164
165   header   <<= 11;
166   CrcReg_X <<= 21;
167   CrcPoly  <<= 21;
168
169   while(length--) {
170     header    <<= 1;
171     header_temp = header & 0x80000000;
172     reg_temp    = CrcReg_X & 0x80000000;
173
174     if(header_temp ^ reg_temp){  // Step 1
175       CrcNext = 1;
176     } else {
177       CrcNext = 0;
178     }
179
180     CrcReg_X <<= 1;              // Step 2
181
182     if(CrcNext) {
183       CrcReg_X ^= CrcPoly;       // Step 3
184     }
185   }
186
187   CrcReg_X >>= 21;
188
189   return CrcReg_X;
190 }
191
192 /**
193  *  Retrieve data and header from message buffer into output buffer.
194  *
195  *  Upper software layers have to read the header and data from RDDS and RDHS registers.
196  *  @param[in]  buf_num     Number of buffer
197  */
198 static void Fr_buffer_receive_data_header(uint32_t buf_num) {
199     bc read_buffer;
200
201     read_buffer.obrs=buf_num;  // output buffer number
202     read_buffer.rdss=1;  // read data section
203     read_buffer.rhss=1;  // read header section
204
205     // ensure no transfer in progress on shadow registers
206     while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
207     frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
208     frayREG->OBCR_UN.OBCR_UL=((1 << 9) | (read_buffer.obrs & 0x3F)); //req=1, view=0
209     // wait for completion on shadow registers
210     while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
211
212     frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
213     frayREG->OBCR_UN.OBCR_UL=((1 << 8) | (read_buffer.obrs & 0x3F)); //req=0, view=1
214
215 }
216
217 /**
218  *  Transfer data to the message RAM using the input buffer
219  *
220  *  @param[in] Fr_LSduPtr   Pointer to data structure with input buffer settings
221  */
222 inline void Fr_transmit_tx_LPdu(const bc *Fr_LSduPtr) {
223     // ensure nothing is pending
224     while ((frayREG->IBCR_UN.IBCR_UL & 0x0008000) != 0);
225     frayREG->IBCM_UN.IBCM_UL=((Fr_LSduPtr->stxrh & 0x1) << 2) | ((Fr_LSduPtr->ldsh & 0x1) << 1) | (Fr_LSduPtr->lhsh & 0x1);
226     frayREG->IBCR_UN.IBCR_UL=(Fr_LSduPtr->ibrh & 0x3F);
227     // optimization possible for future by not gating like below
228     // wait for completion on host registers
229     while ((Fr_LSduPtr->ibsyh != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x00008000) != 0));
230     // wait for completion on shadow registers
231     while ((Fr_LSduPtr->ibsys != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x80000000) != 0));
232 }
233
234 /**
235  *  Fill the buffer configuration data structure with given data and transfer it to the message RAM header using the input buffer.
236  *
237  *  @param[in]  buf_num     number of buffer to be configured (0-128)
238  *  @param[in]  mode        Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
239  *  @param[in]  cyc_filter  Setting for cycle filter. 0 - disabled
240  *  @param[in]  frame_id    Id of the frame to be associated with the buffer
241  *  @param[in]  payload     Maximum data size in half-word
242  *  @param[in]  data_pointer    Address of the first word of data in buffer
243  */
244 static void Fr_config_buffer(uint32_t buf_num, uint16_t mode, uint32_t cyc_filter, uint32_t frame_id, uint32_t payload, uint32_t data_pointer) {
245     wrhs Fr_LPdu;
246     bc Fr_LSdu;
247     int wrhs1;
248     int wrhs2;
249
250     Fr_LPdu.mbi  = (mode&FRAY_BUF_MBI_EN) ? 1 : 0;   // message buffer interrupt
251     Fr_LPdu.txm  = (mode&FRAY_BUF_TX_MODE_CONTINUOUS) ? 0 : 1;   // transmission mode(0=continuous mode, 1=single mode)
252     Fr_LPdu.ppit = (mode&FRAY_BUF_NM_EN) ? 1 : 0;   // network management Enable
253     Fr_LPdu.cfg  = (mode&FRAY_BUF_TX) ? 1 : 0;   // message buffer configuration bit (0=RX, 1 = TX)
254     Fr_LPdu.chb  = (mode&FRAY_BUF_CHB_EN) ? 1 : 0;   // Ch B
255     Fr_LPdu.cha  = (mode&FRAY_BUF_CHA_EN) ? 1 : 0;   // Ch A
256     Fr_LPdu.cyc  = cyc_filter;   // Cycle Filtering Code (no cycle filtering)
257     Fr_LPdu.fid  = frame_id;   // Frame ID
258
259     // Write Header Section 2 (WRHS2)
260     Fr_LPdu.pl   = payload;   // Payload Length
261
262     // Write Header Section 3 (WRHS3)
263     Fr_LPdu.dp   = data_pointer;   // Pointer to start of data in message RAM
264
265     Fr_LPdu.sfi  = (mode&FRAY_BUF_SFI_EN) ? 1 : 0;   // startup frame indicator
266     Fr_LPdu.sync = (mode&FRAY_BUF_SYNC_EN) ? 1 : 0;   // sync frame indicator
267
268     // Write Header Section 2 (WRHS2)
269     Fr_LPdu.crc  = (mode&FRAY_BUF_TX) ? Fr_header_crc_calc(&Fr_LPdu) : 0;
270
271     // Input buffer configuration
272     Fr_LSdu.ibrh = buf_num;  // input buffer number
273     Fr_LSdu.ibsyh = 1; // check for input buffer busy host
274     Fr_LSdu.ibsys = 1; // check for input buffer busy shadow
275
276     Fr_LSdu.stxrh= (mode&FRAY_BUF_TXREQ_EN) ? 1 : 0;  // set transmission request
277     Fr_LSdu.ldsh = 0;  // load data section
278     Fr_LSdu.lhsh = 1;  // load header section
279     Fr_LSdu.obrs = 0;  // output buffer number
280     Fr_LSdu.rdss = 0;  // read data section
281     Fr_LSdu.rhss = 0;  // read header section
282
283     wrhs1  = ((Fr_LPdu.mbi) & 0x1)  <<29;
284     wrhs1 |= (Fr_LPdu.txm & 0x1)  << 28;
285     wrhs1 |= (Fr_LPdu.ppit & 0x1) << 27;
286     wrhs1 |= (Fr_LPdu.cfg & 0x1)  << 26;
287     wrhs1 |= (Fr_LPdu.chb & 0x1)  << 25;
288     wrhs1 |= (Fr_LPdu.cha & 0x1)  << 24;
289     wrhs1 |= (Fr_LPdu.cyc & 0x7F) << 16;
290     wrhs1 |= (Fr_LPdu.fid & 0x7FF);
291     frayREG->WRHS1_UN.WRHS1_UL = wrhs1;
292
293     wrhs2  = ((Fr_LPdu.pl & 0x7F) << 16) | (Fr_LPdu.crc & 0x7FF);
294     frayREG->WRHS2_UN.WRHS2_UL = wrhs2;
295
296     frayREG->WRHS3_UN.WRHS3_UL = (Fr_LPdu.dp & 0x7FF);
297
298     Fr_transmit_tx_LPdu(&Fr_LSdu);
299 }
300
301 /**
302  *  Fill FIFO filter rejection configuration and configure the buffer.
303  *
304  *  @param[in]  buf_num     number of buffer to be configured (0-128)
305  *  @param[in]  mode        Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
306  *  @param[in]  cyc_filter  Setting for cycle filter. 0 - disabled
307  *  @param[in]  frame_id    Id of the frame to be associated with the buffer
308  *  @param[in]  payload     Maximum data size in half-word
309  *  @param[in]  data_pointer    Address of the first word of data in buffer
310  */
311 static void Fr_configure_fifo_buffer(uint32_t buf_num, uint16_t mode, uint32_t cyc_filter, uint32_t frame_id, uint16_t fidMask, uint32_t payload, uint32_t data_pointer) {
312         frayREG->FRF_UN.FRF_ST.rnf = (mode&FRAY_BUF_REJECT_NULL_FRAMES) ? 1 : 0;
313         frayREG->FRF_UN.FRF_ST.rss = (mode&FRAY_BUF_REJECT_STATIC_SEGMENT) ? 1 : 0;
314         frayREG->FRF_UN.FRF_ST.fid_B11 = frame_id;
315         frayREG->FRFM_UN.FRFM_ST.mfid_B11 = fidMask;
316         frayREG->FRF_UN.FRF_ST.cyf_B7 = cyc_filter;
317         if (mode&FRAY_BUF_CHB_EN && mode&FRAY_BUF_CHA_EN) {
318                 frayREG->FRF_UN.FRF_ST.ch_B2 = 0;
319         }
320         else if (mode&FRAY_BUF_CHB_EN) {
321                 frayREG->FRF_UN.FRF_ST.ch_B2 = 1;
322         }
323         else if (mode&FRAY_BUF_CHA_EN) {
324                 frayREG->FRF_UN.FRF_ST.ch_B2 = 2;
325         }
326         else {
327                 frayREG->FRF_UN.FRF_ST.ch_B2 = 3;
328         }
329         Fr_config_buffer(buf_num, mode, cyc_filter, frame_id, payload, data_pointer);
330 }
331
332 /**
333  *  Load data to message buffer. Data must be copied into WRDS register before this function is called.
334  *
335  *  @param[in]  buf_num     Number of buffer
336  *  @param[in]  len         Number of words to be loaded from data to buffer
337  */
338 static void Fr_buffer_transmit_data(uint32_t buf_num) {
339     bc write_buffer;
340
341     write_buffer.ibrh = buf_num;  // input buffer number
342     write_buffer.stxrh= 1;  // set transmission request
343     write_buffer.ldsh = 1;  // load data section
344     write_buffer.lhsh = 0;  // load header section
345     write_buffer.ibsys = 0; // check for input buffer busy shadow
346     write_buffer.ibsyh = 1; // check for input buffer busy host
347     Fr_transmit_tx_LPdu(&write_buffer);
348 }
349
350
351 /** @fn wait_for_POC_ready(void)
352 *   @brief Wait until POC is not busy
353 */
354 inline void Fr_wait_for_POC_ready() {
355         // Wait for PBSY bit to clear - POC not busy.
356         // 1: Signals that the POC is busy and cannot accept a command from the host. CMD(3-0) is locked against write accesses.
357         while(((frayREG->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);
358 }
359
360 /** @fn clear_msg_ram(void)
361 *   @brief Clears FRAY message RAMs
362 *
363 *   Send command to POC to set all bits of message RAM to 0.
364 *   @return SUCCESS or FAILURE when command was not accepted
365 */
366 static int Fr_clear_msg_RAM() {
367     Fr_wait_for_POC_ready();
368     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CLEAR_RAMS;
369     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) {
370         return FAILURE;
371     }
372     Fr_wait_for_POC_ready();
373     return SUCCESS;
374 }
375
376
377 /**
378  * @brief Switch POC to config state from any other state
379  *
380  * After command to switch into config state is passed into CHI,
381  * the response is checked and if POC has reacted on the command,
382  * the function is waiting until POC is ready
383  *
384  * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
385  */
386 static Std_ReturnType Fr_POC_go_to_config() {
387         // write SUCC1 configuration
388     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CONFIG;
389     // Check if POC has accepted last command
390     if ((frayREG->SUCC1_UN.SUCC1_UL & 0xF) == 0x0)
391         return E_NOT_OK;
392     // Wait for PBSY bit to clear - POC not busy
393     Fr_wait_for_POC_ready();
394     return E_OK;
395 }
396
397 /**
398  * @brief Switch POC to ready state from config state
399  *
400  * After command to switch into ready state is passed into CHI,
401  * the response is checked and if POC has reacted on the command,
402  * the function is waiting until POC is ready
403  *
404  * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
405  */
406 static Std_ReturnType Fr_POC_go_to_ready_from_config() {
407     Fr_wait_for_POC_ready();
408     // For CHA and CHB network
409     if (frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 && frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
410         // Unlock sequence
411         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
412         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
413         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
414         // Unlock sequence
415         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
416         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
417         frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
418         // Unlock sequence
419         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
420         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
421         frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
422     }
423     // For CHA  network
424     else if(frayREG->SUCC1_UN.SUCC1_ST.ccha_B1){
425         // Unlock sequence
426         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
427         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
428         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
429         // Unlock sequence
430         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
431         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
432         frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
433     }
434     // For CHB  network
435     else if (frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
436         // Unlock sequence
437         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
438         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
439         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
440         // Unlock sequence
441         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
442         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
443         frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
444     }
445     else frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
446
447     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
448         return E_NOT_OK;
449
450     while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01)
451             ; // Waiting for READY state
452     return E_OK;
453 }
454
455 /**
456  * @brief Switch POC to ready state from startup state
457  *
458  * After command to switch into ready state is passed into CHI,
459  * the response is checked and if POC has reacted on the command,
460  * the function is waiting until POC is ready
461  *
462  * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
463  */
464 static Std_ReturnType Fr_POC_go_to_ready_from_startup() {
465         Fr_wait_for_POC_ready();
466     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
467     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
468         return E_NOT_OK;
469     while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01); // Wait until POC is not in ready state
470         Fr_wait_for_POC_ready();
471     return E_OK;
472 }
473
474 /**
475  * @brief Switch POC to startup state from ready state
476  *
477  * After command to switch into startup state is passed into CHI,
478  * the response is checked and if POC has reacted on the command,
479  * the function is waiting until POC is ready
480  *
481  * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
482  */
483 static Std_ReturnType Fr_POC_go_to_startup() {
484     Fr_wait_for_POC_ready();
485     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_RUN;
486     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
487         return (E_NOT_OK);
488     Fr_wait_for_POC_ready();
489     return (E_OK);
490 }
491
492 /**
493  * @brief Copy cluster config parameters into FlexRay configuration registers.
494  *
495  * This function does not check values ranges. This is a responsibility of higher
496  * layers. Cluster configuration parameters are copied from data structure
497  * into right bit position in configuration registers.
498  *
499  * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
500  */
501 void Fr_config_cluster_parameters(const Fr_TMS570LS_ClusterConfigType* clusterConfigPtr) {
502         frayREG->SUCC1_UN.SUCC1_ST.csa_B5 =  clusterConfigPtr->gColdStartAttempts;
503         frayREG->GTUC9_UN.GTUC9_ST.apo_B5 = clusterConfigPtr->gdActionPointOffset;
504         frayREG->PRTC1_UN.PRTC1_ST.casm_B7 =  clusterConfigPtr->gdCASRxLowMax;
505         frayREG->GTUC9_UN.GTUC9_ST.dsi_B2 = clusterConfigPtr->gdDynamicSlotIdlePhase;
506         frayREG->GTUC8_UN.GTUC8_ST.msl_B6 = clusterConfigPtr->gdMinislot;
507         frayREG->GTUC9_UN.GTUC9_ST.mapo_B5 =  clusterConfigPtr->gdMinislotActionPointOffset;
508         frayREG->GTUC7_UN.GTUC7_ST.ssl_B10 =  clusterConfigPtr->gdStaticSlot;
509         frayREG->PRTC1_UN.PRTC1_ST.tsst_B4 =  clusterConfigPtr->gdTSSTransmitter;
510         frayREG->PRTC2_UN.PRTC2_ST.rxi_B6 =  clusterConfigPtr->gdWakeupSymbolRxIdle;
511         frayREG->PRTC2_UN.PRTC2_ST.rxl_B6 =  clusterConfigPtr->gdWakeupSymbolRxLow;
512         frayREG->PRTC1_UN.PRTC1_ST.rxw_B9 =  clusterConfigPtr->gdWakeupSymbolRxWindow;
513         frayREG->PRTC2_UN.PRTC2_ST.txi_B8 =  clusterConfigPtr->gdWakeupSymbolTxIdle;
514         frayREG->PRTC2_UN.PRTC2_ST.txl_B6 =  clusterConfigPtr->gdWakeupSymbolTxLow;
515         frayREG->SUCC2_UN.SUCC2_ST.ltn_B4 =  clusterConfigPtr->gListenNoise;
516         frayREG->GTUC2_UN.GTUC2_ST.mpc_B14 = clusterConfigPtr->gMacroPerCycle;
517         frayREG->SUCC3_UN.SUCC3_ST.wcf_B4 = clusterConfigPtr->gMaxWithoutClockCorrectionFatal;
518         frayREG->SUCC3_UN.SUCC3_ST.wcp_B4 = clusterConfigPtr->gMaxWithoutClockCorrectionPassive;
519         frayREG->GTUC8_UN.GTUC8_ST.nms_B13 = clusterConfigPtr->gNumberOfMinislots;
520         frayREG->GTUC7_UN.GTUC7_ST.nss_B10 = clusterConfigPtr->gNumberOfStaticSlots;
521         frayREG->GTUC4_UN.GTUC4_ST.ocs_B14 = clusterConfigPtr->gOffsetCorrectionStart;
522         frayREG->MHDC_UN.MHDC_ST.sfdl_B7 = clusterConfigPtr->gPayloadLengthStatic;
523         frayREG->GTUC2_UN.GTUC2_ST.snm_B4 = clusterConfigPtr->gSyncNodeMax;
524         frayREG->GTUC4_UN.GTUC4_ST.nit_B14 = clusterConfigPtr->gdNIT;
525         frayREG->PRTC1_UN.PRTC1_ST.brp_B2 = clusterConfigPtr->gdSampleClockPeriod;
526         frayREG->NEMC_UN.NEMC_ST.nml_B4 = clusterConfigPtr->gNetworkManagementVectorLength;
527 }
528
529 #define __notInRange(val, min, max)     (((val) < (min)) || ((val) > (max)))
530
531 /**
532  * @brief Check cluster configuration parameters.
533  *
534  * This function checks values of the cluster configuration parameters,
535  * if they are in ranges noted in FlexRay specification.
536  *
537  * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
538  * @param [out] errCode Address where error flags will be stored.
539  *              We have 26 parameters to check. Every one of them has assigned its bit in this flag.
540  *              Error flags are defined as macros ERR_PARAM_nameOfParameter.
541  * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
542  */
543 Std_ReturnType Fr_check_cluster_parameters(const Fr_TMS570LS_ClusterConfigType* clusterConfigPtr, uint32_t* errCode) {
544         *errCode = ERR_PARAM_NO_ERROR;
545
546         if (__notInRange(clusterConfigPtr->gColdStartAttempts, 2, 31))          *errCode |= ERR_PARAM_gColdStartAttempts;
547         if (__notInRange(clusterConfigPtr->gdActionPointOffset, 1, 63))         *errCode |= ERR_PARAM_gdActionPointOffset;
548         if (__notInRange(clusterConfigPtr->gdCASRxLowMax, 67, 99))                      *errCode |= ERR_PARAM_gdCASRxLowMax;
549         if (clusterConfigPtr->gdDynamicSlotIdlePhase > 2)                                       *errCode |= ERR_PARAM_gdDynamicSlotIdlePhase;
550         if (__notInRange(clusterConfigPtr->gdMinislot, 2, 63))                          *errCode |= ERR_PARAM_gdMinislot;
551         if (__notInRange(clusterConfigPtr->gdMinislotActionPointOffset,
552                         1, 31))                                                                                                         *errCode |= ERR_PARAM_gdMinislotActionPointOffset;
553         if (__notInRange(clusterConfigPtr->gdStaticSlot, 4, 661))                       *errCode |= ERR_PARAM_gdStaticSlot;
554         if (__notInRange(clusterConfigPtr->gdTSSTransmitter, 3, 15))            *errCode |= ERR_PARAM_gdTSSTransmitter;
555         if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxIdle, 14, 59))       *errCode |= ERR_PARAM_gdWakeupSymbolRxIdle;
556         if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxLow, 11, 59))        *errCode |= ERR_PARAM_gdWakeupSymbolRxLow;
557         if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxWindow,
558                         76, 301))                                                                                                       *errCode |= ERR_PARAM_gdWakeupSymbolRxWindow;
559         if (__notInRange(clusterConfigPtr->gdWakeupSymbolTxIdle, 45, 180))      *errCode |= ERR_PARAM_gdWakeupSymbolTxIdle;
560         if (__notInRange(clusterConfigPtr->gdWakeupSymbolTxLow, 15, 60))        *errCode |= ERR_PARAM_gdWakeupSymbolTxLow;
561         if (__notInRange(clusterConfigPtr->gListenNoise, 2, 16))                        *errCode |= ERR_PARAM_gListenNoise;
562         if (__notInRange(clusterConfigPtr->gMacroPerCycle, 10, 16000))          *errCode |= ERR_PARAM_gMacroPerCycle;
563         if (__notInRange(clusterConfigPtr->gMaxWithoutClockCorrectionFatal,
564                         clusterConfigPtr->gMaxWithoutClockCorrectionPassive, 15))       *errCode |= ERR_PARAM_gMaxWithoutClockCorrectionFatal;
565         if (__notInRange(clusterConfigPtr->gMaxWithoutClockCorrectionPassive,
566                         1, 15))                                                                                                         *errCode |= ERR_PARAM_gMaxWithoutClockCorrectionPassive;
567         if (clusterConfigPtr->gNumberOfMinislots > 7986)                                        *errCode |= ERR_PARAM_gNumberOfMinislots;
568         if (__notInRange(clusterConfigPtr->gNumberOfStaticSlots,
569                         2, cStaticSlotIDMax))                                                                           *errCode |= ERR_PARAM_gNumberOfStaticSlots;
570         if (__notInRange(clusterConfigPtr->gOffsetCorrectionStart,
571                         9, 15999))                                                                                                      *errCode |= ERR_PARAM_gOffsetCorrectionStart;
572         if (clusterConfigPtr->gPayloadLengthStatic > cPayloadLengthMax)         *errCode |= ERR_PARAM_gPayloadLengthStatic;
573         if (__notInRange(clusterConfigPtr->gSyncNodeMax, 2, cSyncNodeMax))      *errCode |= ERR_PARAM_gSyncNodeMax;
574         if (__notInRange(clusterConfigPtr->gdNIT, 7, 0x3E7D))                                   *errCode |= ERR_PARAM_gdNIT;
575         if (clusterConfigPtr->gdSampleClockPeriod > 3)                                          *errCode |= ERR_PARAM_gdSampleClockPeriod;
576         if (clusterConfigPtr->gNetworkManagementVectorLength > 12)                      *errCode |= ERR_PARAM_gNetworkManagementVectorLength;
577
578         return (*errCode == 0) ? E_OK : E_NOT_OK;
579 }
580
581 /**
582  * @brief Copy node config parameters into FlexRay configuration registers.
583  *
584  * This function does not check values ranges. This is a responsibility of higher
585  * layers. Node configuration parameters are copied from data structure
586  * into right bit position in configuration registers.
587  *
588  * @param [in] nodeConfigPtr Address of structure with node configuration parameters
589  */
590 void Fr_config_node_parameters(const Fr_TMS570LS_NodeConfigType* nodeConfigPtr) {
591         frayREG->SUCC1_UN.SUCC1_ST.hcse_B1 = nodeConfigPtr->pAllowHaltDueToClock;
592         frayREG->SUCC1_UN.SUCC1_ST.pta_B5 = nodeConfigPtr->pAllowPassiveToActive;
593         if (nodeConfigPtr->pChannels == FR_CHANNEL_AB) {
594                 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 1;
595                 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 1;
596         }
597         else if (nodeConfigPtr->pChannels == FR_CHANNEL_A) {
598                 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 1;
599                 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 0;
600         }
601         else {
602                 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 0;
603                 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 1;
604         }
605         frayREG->GTUC6_UN.GTUC6_ST.asr_B11 = nodeConfigPtr->pdAcceptedStartupRange;
606         frayREG->GTUC5_UN.GTUC5_ST.cdd_B5 = nodeConfigPtr->pClusterDriftDamping;
607         frayREG->GTUC5_UN.GTUC5_ST.dca_B8 = nodeConfigPtr->pDelayCompensationA;
608         frayREG->GTUC5_UN.GTUC5_ST.dcb_B8 = nodeConfigPtr->pDelayCompensationB;
609         frayREG->GTUC5_UN.GTUC5_ST.dec_B8 = nodeConfigPtr->pDecodingCorrection;
610         frayREG->SUCC2_UN.SUCC2_ST.lt_B21 = nodeConfigPtr->pdListenTimeout;
611         frayREG->GTUC6_UN.GTUC6_ST.mod_B11 = nodeConfigPtr->pdMaxDrift;
612         frayREG->GTUC11_UN.GTUC11_ST.eoc_B3 = nodeConfigPtr->pExternOffsetCorrection;
613         frayREG->GTUC11_UN.GTUC11_ST.erc_B3 = nodeConfigPtr->pExternRateCorrection;
614         frayREG->SUCC1_UN.SUCC1_ST.txst_B1 = nodeConfigPtr->pKeySlotUsedForStartup;
615         frayREG->SUCC1_UN.SUCC1_ST.txsy_B1 = nodeConfigPtr->pKeySlotUsedForSync;
616         frayREG->MHDC_UN.MHDC_ST.slt_B13 =  nodeConfigPtr->pLatestTx;
617         frayREG->GTUC3_UN.GTUC3_ST.mioa_B7 = nodeConfigPtr->pMacroInitialOffsetA;
618         frayREG->GTUC3_UN.GTUC3_ST.miob_B7 = nodeConfigPtr->pMacroInitialOffsetB;
619         frayREG->GTUC3_UN.GTUC3_ST.uioa_B8 = nodeConfigPtr->pMicroInitialOffsetA;
620         frayREG->GTUC3_UN.GTUC3_ST.uiob_B8 = nodeConfigPtr->pMicroInitialOffsetB;
621         frayREG->GTUC1_UN.GTUC1_ST.ut_B20 = nodeConfigPtr->pMicroPerCycle;
622         frayREG->GTUC10_UN.GTUC10_ST.moc_B13 = nodeConfigPtr->pRateCorrectionOut;
623         frayREG->GTUC10_UN.GTUC10_ST.mrc_B11 = nodeConfigPtr->pOffsetCorrectionOut;
624         frayREG->SUCC1_UN.SUCC1_ST.tsm_B1 = nodeConfigPtr->pSingleSlotEnabled;
625         if (nodeConfigPtr->pWakeupChannel == FR_CHANNEL_A) {
626                 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 0;
627         }
628         else if (nodeConfigPtr->pWakeupChannel == FR_CHANNEL_B) {
629                 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 1;
630         }
631         frayREG->PRTC1_UN.PRTC1_ST.rwp_B6 = nodeConfigPtr->pWakeupPattern;
632         frayREG->PRTC1_UN.PRTC1_ST.brp_B2 = nodeConfigPtr->pSamplesPerMicrotick;
633         frayREG->EIR_UN.EIR_UL = 0xFFFFFFFF;
634
635 }
636
637 /**
638  * @brief Check node configuration parameters.
639  *
640  * This function checks values of the node configuration parameters,
641  * if they are in ranges noted in FlexRay specification.
642  *
643  * @param [in] nodeConfigPtr Address of structure with node configuration parameters
644  * @param [out] errCode Address where error flags will be stored.
645  *              We have 24 parameters to check. Every one of them has assigned its bit in this flag.
646  *              Error flags are defined as macros ERR_PARAM_nameOfParameter.
647  * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
648  */
649 Std_ReturnType Fr_check_node_parameters(const Fr_TMS570LS_NodeConfigType* nodeConfigPtr, uint32_t* errCode) {
650         *errCode = ERR_PARAM_NO_ERROR;
651
652         if (nodeConfigPtr->pAllowPassiveToActive > 31)          *errCode |= ERR_PARAM_pAllowPassiveToActive;
653         if (nodeConfigPtr->pChannels != FR_CHANNEL_A &&
654                 nodeConfigPtr->pChannels != FR_CHANNEL_B &&
655                 nodeConfigPtr->pChannels != FR_CHANNEL_AB )             *errCode |= ERR_PARAM_pChannels;
656         if (nodeConfigPtr->pdAcceptedStartupRange > 1875)       *errCode |= ERR_PARAM_pdAcceptedStartupRange;
657         if (nodeConfigPtr->pClusterDriftDamping > 20)           *errCode |= ERR_PARAM_pClusterDriftDamping;
658         if (nodeConfigPtr->pDelayCompensationA > 200)           *errCode |= ERR_PARAM_pDelayCompensationA;
659         if (nodeConfigPtr->pDelayCompensationB > 200)           *errCode |= ERR_PARAM_pDelayCompensationB;
660         if (__notInRange(nodeConfigPtr->pdListenTimeout, 1284, 1283846))        *errCode |= ERR_PARAM_pdListenTimeout;
661         if (__notInRange(nodeConfigPtr->pdMaxDrift, 2, 1923))                           *errCode |= ERR_PARAM_pdMaxDrift;
662         if (nodeConfigPtr->pExternOffsetCorrection > 7)         *errCode |= ERR_PARAM_pExternOffsetCorrection;
663         if (nodeConfigPtr->pExternRateCorrection > 7)           *errCode |= ERR_PARAM_pExternRateCorrection;
664         if (nodeConfigPtr->pKeySlotUsedForStartup == TRUE &&
665                 nodeConfigPtr->pKeySlotUsedForSync == FALSE)    *errCode |= ERR_PARAM_pKeySlotUsedForSync
666                                                                                                                                  |  ERR_PARAM_pKeySlotUsedForStartup;   // If pKeySlotUsedForStartup is set to true then pKeySlotUsedForSync must also be set to true.
667         if (nodeConfigPtr->pLatestTx > 7980)                            *errCode |= ERR_PARAM_pLatestTx;
668         if (__notInRange(nodeConfigPtr->pMacroInitialOffsetA, 2, 68))           *errCode |= ERR_PARAM_pMacroInitialOffsetA;
669         if (__notInRange(nodeConfigPtr->pMacroInitialOffsetB, 2, 68))           *errCode |= ERR_PARAM_pMacroInitialOffsetB;
670         if (nodeConfigPtr->pMicroInitialOffsetA > 239)          *errCode |= ERR_PARAM_pMicroInitialOffsetA;
671         if (nodeConfigPtr->pMicroInitialOffsetB > 239)          *errCode |= ERR_PARAM_pMicroInitialOffsetB;
672         if (__notInRange(nodeConfigPtr->pMicroPerCycle, 640, 640000)) *errCode |= ERR_PARAM_pMicroPerCycle;
673         if (__notInRange(nodeConfigPtr->pRateCorrectionOut, 2, 1923)) *errCode |= ERR_PARAM_pRateCorrectionOut;
674         if (__notInRange(nodeConfigPtr->pOffsetCorrectionOut, 5, 0x3BA2)) *errCode |= ERR_PARAM_pOffsetCorrectionOut;
675         if (nodeConfigPtr->pWakeupChannel != FR_CHANNEL_A &&
676                 nodeConfigPtr->pWakeupChannel != FR_CHANNEL_B ) *errCode |= ERR_PARAM_pWakeupChannel;
677         if (__notInRange(nodeConfigPtr->pWakeupPattern, 2, 63)) *errCode |= ERR_PARAM_pWakeupPattern;
678         if (nodeConfigPtr->pSamplesPerMicrotick > 3)            *errCode |= ERR_PARAM_pSamplesPerMicrotick;
679         if (__notInRange(nodeConfigPtr->pDecodingCorrection, 0xF, 0x8F))        *errCode |= ERR_PARAM_pDecodingCorrection;
680
681         return (*errCode == 0) ? E_OK : E_NOT_OK;
682 }
683
684 /**
685  * @brief Check Configuration parameters for all buffers
686  *
687  * This function checks configuration parameters.
688  * For FIFO buffers:
689  *              - All of them have to be RX
690  *              - All of them have the same payload <= 256B
691  *              - Same channels active
692  *              - Same cycle counter filter
693  *              - not coldstart
694  *              - not single/auto
695  *              - not reconfigurable
696  *              - frame ID can be 0, which means that all messages not received by others buffers are received in FIFO.
697  * For dynamic segment buffers and static segment buffers:
698  *              - frame ID must not be 0
699  *              - payload <= 256B
700  * The sum of all configured payloads must be <= 8KB.
701  *
702  * @param [in] statBufCfgPtr Address of structure with static buffers configuration parameters
703  * @param [in] dynBufCfgPtr Address of structure with dynamic buffers configuration parameters
704  * @param [in] fifoBufCfgPtr Address of structure with fifo buffers configuration parameters
705  * @param [in] statBufCnt Number of static buffers to be configured
706  * @param [in] dynBufCnt Number of dynamic buffers to be configured
707  * @param [in] fifoBufCnt Number of fifo buffers to be configured
708  * @param [out] errCode Address where error flags will be stored.
709  *              Flags are defined as ERR_PARAM_BUF.....
710  * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
711  */
712 Std_ReturnType Fr_check_buffer_parameters(const Fr_TMS570LS_BufferConfigType* statBufCfgPtr, const Fr_TMS570LS_BufferConfigType* dynBufCfgPtr, const Fr_TMS570LS_BufferConfigType* fifoBufCfgPtr,
713                 uint8_t statBufCnt, uint8_t dynBufCnt, uint8_t fifoBufCnt, uint32_t* errCode) {
714         uint32_t payloadTotal = 0;
715         *errCode = ERR_PARAM_NO_ERROR;
716         uint8_t fifoPayload, fifoCycleCounterFiltering;
717         Fr_ChannelType fifoChannels;
718         uint16_t fifoFidMask, fifoSlotId;
719         boolean_t fifoRejNullFr, fifoRejStatFr;
720         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr = NULL;
721
722
723         /* Check FIFO buffer parameters */
724         if (fifoBufCnt != 0 && fifoBufCfgPtr != NULL) {
725                 fifoChannels = fifoBufCfgPtr[0].channel;
726                 fifoCycleCounterFiltering = fifoBufCfgPtr[0].cycleCounterFiltering;
727                 fifoFidMask = fifoBufCfgPtr[0].fidMask;
728                 fifoSlotId = fifoBufCfgPtr[0].slotId;
729                 fifoPayload = fifoBufCfgPtr[0].maxPayload;
730                 fifoRejNullFr = fifoBufCfgPtr[0].rejectNullFrames;
731                 fifoRejStatFr = fifoBufCfgPtr[0].rejectStaticSegment;
732                 if (fifoPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFFIFO_PAYLOAD_HIGH;
733                 for (buffer_cfg_ptr = &fifoBufCfgPtr[0]; buffer_cfg_ptr < &fifoBufCfgPtr[fifoBufCnt]; buffer_cfg_ptr++) {
734                         if (buffer_cfg_ptr->channel != fifoChannels) *errCode |= ERR_PARAM_BUFFIFO_CHANNEL_DIFFERS;
735                         if (buffer_cfg_ptr->cycleCounterFiltering != fifoCycleCounterFiltering) *errCode |= ERR_PARAM_BUFFIFO_CCFILTER_DIFFERS;
736                         if (buffer_cfg_ptr->fidMask != fifoFidMask) *errCode |= ERR_PARAM_BUFFIFO_FIDMASK_DIFFERS;
737                         if (buffer_cfg_ptr->isTx == TRUE) *errCode |= ERR_PARAM_BUFFIFO_NOT_RX;
738                         if (buffer_cfg_ptr->maxPayload != fifoPayload) *errCode |= ERR_PARAM_BUFFIFO_PAYLOAD_DIFFERS;
739                         if (buffer_cfg_ptr->payloadPreambleIndicatorTr == TRUE) *errCode |= ERR_PARAM_BUFFIFO_PPIT;
740                         if (buffer_cfg_ptr->rejectNullFrames != fifoRejNullFr) *errCode |= ERR_PARAM_BUFFIFO_REJNULLFR_DIFFERS;
741                         if (buffer_cfg_ptr->rejectStaticSegment != fifoRejStatFr) *errCode |= ERR_PARAM_BUFFIFO_REJSTATFR_DIFFERS;
742                         if (buffer_cfg_ptr->slotId != fifoSlotId) *errCode |= ERR_PARAM_BUFFIFO_SLOTID_DIFFERS;
743                         payloadTotal += buffer_cfg_ptr->maxPayload;
744                 }
745         }
746         if (dynBufCfgPtr != NULL) {
747                 for (buffer_cfg_ptr = &dynBufCfgPtr[0]; buffer_cfg_ptr < &dynBufCfgPtr[dynBufCnt]; buffer_cfg_ptr++) {
748                         if (buffer_cfg_ptr->slotId == 0) *errCode |= ERR_PARAM_BUFDYN_FRAMEID_INVALID;
749                         if (buffer_cfg_ptr->maxPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFDYN_PAYLOAD_HIGH;
750                         if (buffer_cfg_ptr->channel == FR_CHANNEL_AB) *errCode |= ERR_PARAM_BUFDYN_CHANNELS;
751                         payloadTotal += buffer_cfg_ptr->maxPayload;
752                 }
753         }
754
755         if (statBufCfgPtr != NULL) {
756                 for (buffer_cfg_ptr = &statBufCfgPtr[0]; buffer_cfg_ptr < &statBufCfgPtr[statBufCnt]; buffer_cfg_ptr++) {
757                         if (buffer_cfg_ptr->slotId == 0) *errCode |= ERR_PARAM_BUFSTAT_FRAMEID_INVALID;
758                         if (buffer_cfg_ptr->maxPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFSTAT_PAYLOAD_HIGH;
759                         payloadTotal += buffer_cfg_ptr->maxPayload;
760                 }
761         }
762
763         if (payloadTotal > 8192/2) *errCode |= ERR_PARAM_BUF_TOTAL_PAYLOAD_HIGH;
764
765         return (*errCode == 0) ? E_OK : E_NOT_OK;
766 }
767
768 /**
769  * @brief Compute and set message RAM config parameters into FlexRay configuration registers.
770  *
771  * This function does not check values ranges. This is a responsibility of other functions.
772  * Message RAM configuration parameters are computed from data in the structure and
773  * written into right bit position in configuration registers.
774  *
775  * @param [in] msgRAMConfigPtr Address of structure with message RAM configuration parameters
776  * @return Number of configured buffers
777  */
778 uint8_t Fr_config_msgRAM_parameters(const Fr_TMS570LS_MsgRAMConfig* msgRAMConfigPtr) {
779         /* If dynSegmentBufferCount is not 0 then first dynamic buffer = statSegmentBufferCount.
780          * If dynSegmentBufferCount is 0 then first dynamic buffer is 0x80 (see TMS570LS31x documentation)
781          */
782         if (msgRAMConfigPtr->dynSegmentBufferCount == 0) {
783                 frayREG->MRC_UN.MRC_ST.fdb_B8 = 0x80;
784         }
785         else {
786                 frayREG->MRC_UN.MRC_ST.fdb_B8 = msgRAMConfigPtr->statSegmentBufferCount;
787         }
788         /* If fifoBufferCount is not 0 then first fifo buffer = statSegmentBufferCount + dynSegmentBufferCount
789          * If fifoBufferCount is 0 then first fifo buffer is 0x80 (see TMS570LS31x documentation)
790          */
791         if (msgRAMConfigPtr->fifoBufferCount == 0) {
792                 frayREG->MRC_UN.MRC_ST.ffb_B8 = 0x80;
793         }
794         else {
795                 frayREG->MRC_UN.MRC_ST.ffb_B8 = msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount;
796         }
797         /* Last configured buffer = statSegmentBufferCount + dynSegmentBufferCount + fifoBufferCount - 1 */
798         frayREG->MRC_UN.MRC_ST.lcb_B8 = msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount + msgRAMConfigPtr->fifoBufferCount - 1;
799
800         /* Secure buffers setting */
801         if (msgRAMConfigPtr->secureBuffers == FR_SB_RECONFIG_ENABLED) {
802                 frayREG->MRC_UN.MRC_ST.sec_B2 = 0;
803         }
804         else if (msgRAMConfigPtr->secureBuffers == FR_SB_STAT_REC_DISABLED_STAT_TR_DISABLED) {
805                 frayREG->MRC_UN.MRC_ST.sec_B2 = 1;
806         }
807         else if (msgRAMConfigPtr->secureBuffers == FR_SB_ALL_REC_DISABLED) {
808                 frayREG->MRC_UN.MRC_ST.sec_B2 = 2;
809         }
810         else {
811                 frayREG->MRC_UN.MRC_ST.sec_B2 = 3;
812         }
813
814         /* Sync frame payload multiplex setting */
815         if (msgRAMConfigPtr->syncFramePayloadMultiplexEnabled == TRUE) {
816                 frayREG->MRC_UN.MRC_ST.splm_B1 = 1;
817         }
818         else {
819                 frayREG->MRC_UN.MRC_ST.splm_B1 = 0;
820         }
821
822         return msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount + msgRAMConfigPtr->fifoBufferCount;
823 }
824
825 #define __notInRange(val, min, max)     (((val) < (min)) || ((val) > (max)))
826
827 /**
828  * @brief Check message RAM configuration parameters.
829  *
830  * This function checks values of the message RAM configuration parameters.
831  * FlexRay implementation in TMS570 can have up to 128 buffers configured, so
832  * the sum of all values buffer count must not exceed this ceiling.
833  *
834  *
835  * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
836  * @param [out] errCode Address where error flags will be stored.
837  *              Error flags are defined as macros ERR_PARAM_nameOfParameter.
838  * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
839  */
840 Std_ReturnType Fr_check_msgRAM_parameters(const Fr_TMS570LS_MsgRAMConfig* msgRAMConfigPtr, uint32_t* errCode) {
841         *errCode = ERR_PARAM_NO_ERROR;
842
843         if (__notInRange(msgRAMConfigPtr->statSegmentBufferCount, 1, 127))      *errCode |= ERR_PARAM_statSegmentBufferCount;
844         if (msgRAMConfigPtr->dynSegmentBufferCount >= FR_MAX_BUFFERS_CNT)       *errCode |= ERR_PARAM_dynSegmentBufferCount;
845         if (msgRAMConfigPtr->fifoBufferCount >= FR_MAX_BUFFERS_CNT)                     *errCode |= ERR_PARAM_fifoBufferCount;
846         if ((msgRAMConfigPtr->statSegmentBufferCount +
847                 msgRAMConfigPtr->dynSegmentBufferCount +
848                 msgRAMConfigPtr->fifoBufferCount) >= FR_MAX_BUFFERS_CNT)                *errCode |= ERR_PARAM_maxBuffLimit;
849
850         return (*errCode == 0) ? E_OK : E_NOT_OK;
851 }
852
853 void Fr_Init(const Fr_ConfigType* Fr_ConfigPtr) {
854         Fr_slot_buffer_map_t* buffer_slot_map_ptr;
855         uint8_t buffer_last_index;
856         boolean_t* buffers_configured_ptr;
857         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
858
859 #ifdef DET_ACTIVATED
860         if (Fr_ConfigPtr == NULL) {
861                 return;
862         }
863         if (Fr_DrvState != FR_ST_DRV_NOT_INITIALIZED) {
864                 return;
865         }
866 #endif
867         /* Save pointers for parameters indexed by CIDX indexes
868          * This array representation is used by Fr_ReadCCConfig function.
869          * Parameter thet are not configurable in tms570 FlexRay implementation
870          * are set as NULL.
871          */
872         Fr_ConfigParPtrs[FR_CIDX_GDCYCLE] = 0;
873         Fr_ConfigParPtrs[FR_CIDX_PMICROPERCYCLE] = Fr_ConfigPtr->nodeConfiguration->pMicroPerCycle;
874         Fr_ConfigParPtrs[FR_CIDX_PDLISTENTIMEOUT] = Fr_ConfigPtr->clusterConfiguration->gMacroPerCycle;
875         Fr_ConfigParPtrs[FR_CIDX_GDMACROTICK] = 0;
876         Fr_ConfigParPtrs[FR_CIDX_GNUMBEROFMINISLOTS] = Fr_ConfigPtr->clusterConfiguration->gNumberOfMinislots;
877         Fr_ConfigParPtrs[FR_CIDX_GNUMBEROFSTATICSLOTS] = Fr_ConfigPtr->clusterConfiguration->gNumberOfStaticSlots;
878         Fr_ConfigParPtrs[FR_CIDX_GDNIT] = Fr_ConfigPtr->clusterConfiguration->gdNIT;
879         Fr_ConfigParPtrs[FR_CIDX_GDSTATICSLOT] = Fr_ConfigPtr->clusterConfiguration->gdNIT;
880         Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXWINDOW] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxWindow;
881         Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTID] = 0;
882         Fr_ConfigParPtrs[FR_CIDX_PLATESTTX] = Fr_ConfigPtr->nodeConfiguration->pLatestTx;
883         Fr_ConfigParPtrs[FR_CIDX_POFFSETCORRECTIONOUT] = 0;
884         Fr_ConfigParPtrs[FR_CIDX_POFFSETCORRECTIONSTART] = 0;
885         Fr_ConfigParPtrs[FR_CIDX_PRATECORRECTIONOUT] = Fr_ConfigPtr->nodeConfiguration->pRateCorrectionOut;
886         Fr_ConfigParPtrs[FR_CIDX_PSECONDKEYSLOTID] = 0;
887         Fr_ConfigParPtrs[FR_CIDX_PDACCEPTEDSTARTUPRANGE] = Fr_ConfigPtr->nodeConfiguration->pdAcceptedStartupRange;
888         Fr_ConfigParPtrs[FR_CIDX_GCOLDSTARTATTEMPTS] = Fr_ConfigPtr->clusterConfiguration->gColdStartAttempts;
889         Fr_ConfigParPtrs[FR_CIDX_GCYCLECOUNTMAX] = 0;
890         Fr_ConfigParPtrs[FR_CIDX_GLISTENNOISE] = Fr_ConfigPtr->clusterConfiguration->gListenNoise;
891         Fr_ConfigParPtrs[FR_CIDX_GMAXWITHOUTCLOCKCORRECTFATAL] = Fr_ConfigPtr->clusterConfiguration->gMaxWithoutClockCorrectionFatal;
892         Fr_ConfigParPtrs[FR_CIDX_GMAXWITHOUTCLOCKCORRECTPASSIVE] = Fr_ConfigPtr->clusterConfiguration->gMaxWithoutClockCorrectionPassive;
893         Fr_ConfigParPtrs[FR_CIDX_GNETWORKMANAGEMENTVECTORLENGTH] = Fr_ConfigPtr->clusterConfiguration->gNetworkManagementVectorLength;
894         Fr_ConfigParPtrs[FR_CIDX_GPAYLOADLENGTHSTATIC] = Fr_ConfigPtr->clusterConfiguration->gPayloadLengthStatic;
895         Fr_ConfigParPtrs[FR_CIDX_GSYNCFRAMEIDCOUNTMAX] = 0;
896         Fr_ConfigParPtrs[FR_CIDX_GDACTIONPOINTOFFSET] = Fr_ConfigPtr->clusterConfiguration->gdActionPointOffset;
897         Fr_ConfigParPtrs[FR_CIDX_GDBIT] = 0;
898         Fr_ConfigParPtrs[FR_CIDX_GDCASRXLOWMAX] = Fr_ConfigPtr->clusterConfiguration->gdCASRxLowMax;
899         Fr_ConfigParPtrs[FR_CIDX_GDDYNAMICSLOTIDLEPHASE] = Fr_ConfigPtr->clusterConfiguration->gdDynamicSlotIdlePhase;
900         Fr_ConfigParPtrs[FR_CIDX_GDMINISLOTACTIONPOINTOFFSET] = Fr_ConfigPtr->clusterConfiguration->gdMinislotActionPointOffset;
901         Fr_ConfigParPtrs[FR_CIDX_GDMINISLOT] = Fr_ConfigPtr->clusterConfiguration->gdMinislot;
902         Fr_ConfigParPtrs[FR_CIDX_GDSAMPLECLOCKPERIOD] = Fr_ConfigPtr->clusterConfiguration->gdSampleClockPeriod;
903         Fr_ConfigParPtrs[FR_CIDX_GDSYMBOLWINDOW] = 0;
904         Fr_ConfigParPtrs[FR_CIDX_GDSYMBOLWINDOWACTIONPOINTOFFSET] = 0;
905         Fr_ConfigParPtrs[FR_CIDX_GDTSSTRANSMITTER] = Fr_ConfigPtr->clusterConfiguration->gdTSSTransmitter;
906         Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXIDLE] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxIdle;
907         Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXLOW] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxLow;
908         Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPTXACTIVE] = 0;
909         Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPTXIDLE] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolTxIdle;
910         Fr_ConfigParPtrs[FR_CIDX_PALLOWPASSIVETOACTIVE] = Fr_ConfigPtr->nodeConfiguration->pAllowPassiveToActive;
911         Fr_ConfigParPtrs[FR_CIDX_PCHANNELS] = Fr_ConfigPtr->nodeConfiguration->pChannels;
912         Fr_ConfigParPtrs[FR_CIDX_PCLUSTERDRIFTDAMPING] = Fr_ConfigPtr->nodeConfiguration->pClusterDriftDamping;
913         Fr_ConfigParPtrs[FR_CIDX_PDECODINGCORRECTION] = 0;
914         Fr_ConfigParPtrs[FR_CIDX_PDELAYCOMPENSATIONA] = Fr_ConfigPtr->nodeConfiguration->pDelayCompensationA;
915         Fr_ConfigParPtrs[FR_CIDX_PDELAYCOMPENSATIONB] = Fr_ConfigPtr->nodeConfiguration->pDelayCompensationB;
916         Fr_ConfigParPtrs[FR_CIDX_PMACROINITIALOFFSETA] = Fr_ConfigPtr->nodeConfiguration->pMacroInitialOffsetA;
917         Fr_ConfigParPtrs[FR_CIDX_PMACROINITIALOFFSETB] = Fr_ConfigPtr->nodeConfiguration->pMacroInitialOffsetB;
918         Fr_ConfigParPtrs[FR_CIDX_PMICROINITIALOFFSETA] = Fr_ConfigPtr->nodeConfiguration->pMicroInitialOffsetA;
919         Fr_ConfigParPtrs[FR_CIDX_PMICROINITIALOFFSETB] = Fr_ConfigPtr->nodeConfiguration->pMicroInitialOffsetB;
920         Fr_ConfigParPtrs[FR_CIDX_PPAYLOADLENGTHDYNMAX] = 0;
921         Fr_ConfigParPtrs[FR_CIDX_PSAMPLESPERMICROTICK] = Fr_ConfigPtr->nodeConfiguration->pSamplesPerMicrotick;
922         Fr_ConfigParPtrs[FR_CIDX_PWAKEUPCHANNEL] = Fr_ConfigPtr->nodeConfiguration->pWakeupChannel;
923         Fr_ConfigParPtrs[FR_CIDX_PWAKEUPPATTERN] = Fr_ConfigPtr->nodeConfiguration->pWakeupPattern;
924         Fr_ConfigParPtrs[FR_CIDX_PDMICROTICK] = 0;
925         Fr_ConfigParPtrs[FR_CIDX_GDIGNOREAFTERTX] = 0;
926         Fr_ConfigParPtrs[FR_CIDX_PALLOWHALTDUETOCLOCK] = Fr_ConfigPtr->nodeConfiguration->pAllowHaltDueToClock;
927         Fr_ConfigParPtrs[FR_CIDX_PEXTERNALSYNC] = 0;
928         Fr_ConfigParPtrs[FR_CIDX_PFALLBACKINTERNAL] = 0;
929         Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTONLYENABLED] = 0;
930         Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSTARTUP] = Fr_ConfigPtr->nodeConfiguration->pKeySlotUsedForStartup;
931         Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSYNC] = Fr_ConfigPtr->nodeConfiguration->pKeySlotUsedForSync;
932         Fr_ConfigParPtrs[FR_CIDX_PNMVECTOREARLYUPDATE] = 0;
933         Fr_ConfigParPtrs[FR_CIDX_PTWOKEYSLOTMODE] = 0;
934
935         /* Store whole configuration address
936          * This structured representation is used by other function in API.
937          */
938         Fr_Config = Fr_ConfigPtr;
939
940         /* Store pointers to structures with configuration parameters of buffers
941          * Reset configured flags for all buffers */
942         buffer_last_index = Fr_ConfigPtr->msgRAMConfig->statSegmentBufferCount;
943         for (buffer_slot_map_ptr = Fr_buffer_slot_map, buffers_configured_ptr = Fr_BuffersConfigured, buffer_cfg_ptr = Fr_ConfigPtr->staticBufferConfigs;
944                  buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
945                  buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
946                 ) { // Static segment buffers
947                 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
948                 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
949                 *buffers_configured_ptr = FALSE;
950         }
951         buffer_last_index += Fr_ConfigPtr->msgRAMConfig->dynSegmentBufferCount;
952         for (buffer_cfg_ptr = Fr_ConfigPtr->dynamicBufferConfigs;
953                  buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
954                  buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
955                 ) { // Dynamic segment buffers
956                 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
957                 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
958                 *buffers_configured_ptr = FALSE;
959         }
960         buffer_last_index += Fr_ConfigPtr->msgRAMConfig->fifoBufferCount;
961         for (buffer_cfg_ptr = Fr_ConfigPtr->fifoBufferConfigs;
962                  buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
963                  buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
964                 ) { // Fifo buffrers
965                 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
966                 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
967                 *buffers_configured_ptr = FALSE;
968         }
969
970 #ifdef DET_ACTIVATED
971         Fr_DrvState = FR_ST_DRV_INITIALIZED;
972 #endif
973 }
974
975 Std_ReturnType Fr_ControllerInit(uint8_t Fr_CtrlIdx) {
976         uint32_t errCode = ERR_PARAM_NO_ERROR;
977         uint32_t i;
978         uint8_t totalBufferCount;
979
980 #ifdef DET_ACTIVATED
981         if (Fr_DrvState < FR_ST_DRV_INITIALIZED) {
982                 return E_NOT_OK;
983         }
984 #endif
985
986         /* Switch CC into â€˜POC:config’ (from any other POCState) */
987         while (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_CONFIG) {
988                 if (Fr_POC_go_to_config() == E_NOT_OK) {
989                         return E_NOT_OK;
990                 }
991         }
992
993         /* Check Cluster config parameters */
994         if (Fr_check_cluster_parameters(Fr_Config->clusterConfiguration, &errCode) == E_NOT_OK) {
995                 return E_NOT_OK | errCode | FR_INIT_ERR_CLUSTER_CONFIG;
996         }
997         /* Check node config parameters */
998         if (Fr_check_node_parameters(Fr_Config->nodeConfiguration, &errCode) == E_NOT_OK) {
999                 return E_NOT_OK | errCode | FR_INIT_ERR_NODE_CONFIG;
1000         }
1001         /* Check msgRAM config parameters */
1002         if (Fr_check_msgRAM_parameters(Fr_Config->msgRAMConfig, &errCode) == E_NOT_OK) {
1003                 return E_NOT_OK | errCode | FR_INIT_ERR_MSGRAM_CONFIG;
1004         }
1005         /* Check buffers parameters */
1006         if (Fr_check_buffer_parameters(Fr_Config->staticBufferConfigs, Fr_Config->dynamicBufferConfigs, Fr_Config->fifoBufferConfigs,
1007                         Fr_Config->msgRAMConfig->statSegmentBufferCount, Fr_Config->msgRAMConfig->dynSegmentBufferCount, Fr_Config->msgRAMConfig->fifoBufferCount, &errCode) == E_NOT_OK) {
1008                 return E_NOT_OK | errCode | FR_INIT_ERR_BUFFPARAM_CONFIG;
1009         }
1010
1011         /* Clear message RAM */
1012         if (Fr_clear_msg_RAM() == FAILURE) {
1013                 return E_NOT_OK;
1014         }
1015
1016         /* Configure all FlexRay cluster, node and msgRAM parameters */
1017         Fr_config_cluster_parameters(Fr_Config->clusterConfiguration);
1018         Fr_config_node_parameters(Fr_Config->nodeConfiguration);
1019
1020         // Wait until CLEAR_RAMS command is complete
1021         while (frayREG->MHDS_UN.MHDS_ST.cram_B1 == 1)
1022                 ;
1023
1024         totalBufferCount = Fr_config_msgRAM_parameters(Fr_Config->msgRAMConfig);
1025         Fr_MsgRAMDataStartAddress = totalBufferCount*4U; // First data section after headers sections in message RAM.
1026         Fr_MsgRAMDataOffset = Fr_MsgRAMDataStartAddress;
1027
1028         /* Reset configured flags */
1029         for (i = 0; i < totalBufferCount; i++) {
1030                 Fr_BuffersConfigured[i] = FALSE;
1031         }
1032
1033         /* Configure all transmit/receive resources */
1034         for (i = 0; i < totalBufferCount; i++) {
1035                 if (Fr_PrepareLPdu(Fr_CtrlIdx, Fr_buffer_slot_map[i].buffer_ptr->slotId) == E_NOT_OK) {
1036                         return E_NOT_OK | FR_INIT_ERR_BUFF_CONFIG;
1037                 }
1038         }
1039
1040         /* Switch POC to ready state */
1041         if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1042                 return E_NOT_OK;
1043         }
1044 #ifdef DET_ACTIVATED
1045         Fr_DrvState = FR_ST_CTRL_INITIALIZED;
1046 #endif
1047         return E_OK;
1048 }
1049
1050 Std_ReturnType Fr_StartCommunication(uint8_t Fr_CtrlIdx) {
1051         uint32_t counter;
1052         uint32_t state_value;
1053         uint32_t csa;
1054 #ifdef DET_ACTIVATED
1055         if (Fr_CtrlIdx != 0) {
1056                 return E_NOT_OK;
1057         }
1058         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1059                 return E_NOT_OK;
1060         }
1061         if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_READY && frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_HALT) {
1062                 return E_NOT_OK;
1063         }
1064 #endif
1065         // Node halted, switch to ready
1066         if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_HALT) {
1067                 if (Fr_POC_go_to_config() == E_NOT_OK) {
1068                         return E_NOT_OK;
1069                 }
1070                 if (Fr_POC_go_to_config() == E_NOT_OK) {
1071                         return E_NOT_OK;
1072                 }
1073                 if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1074                         return E_NOT_OK;
1075                 }
1076         }
1077
1078         // Node is configured as coldstart
1079         if (Fr_Config->nodeConfiguration->pKeySlotUsedForStartup == TRUE) {
1080         // Start up loop
1081         while(1) {
1082             counter = 0;
1083             // Try to integrate into an existing network as following coldstarter
1084             if (Fr_POC_go_to_startup() == E_NOT_OK) {
1085                 return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_FOLLOW;        // Switch to run state error
1086             }
1087
1088             do {        // Wait until NORMAL_ACTIVE state or timeout
1089                 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1090                 counter++;
1091             } while ((state_value != FR_POCS_NORMAL_ACTIVE) && (counter < FR_FCS_LISTEN_TIMEOUT));
1092
1093             // No success in integration, try to initiate FlexRay network as leading coldstarter.
1094             if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_INTEGRATION_LISTEN){
1095                 csa = frayREG->CCSV_UN.CCSV_ST.rca_B5;
1096                 if (csa != 0) { // Some cold start attempts remaining
1097                     if (Fr_AllowColdstart(Fr_CtrlIdx) == E_NOT_OK) {
1098                         return E_NOT_OK | FR_STARTUP_ERR_CSINH_DIS;             // Cold start inhibit disabled error
1099                     }
1100                 }
1101             }
1102             do { // Wait until NORMAL_ACTIVE or INTEGRATION_LISTEN state
1103                 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1104             } while ( (state_value != FR_POCS_NORMAL_ACTIVE) && (state_value != FR_POCS_INTEGRATION_LISTEN));
1105             if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_NORMAL_ACTIVE) // Success, break the start up loop
1106                 break;
1107             if (Fr_POC_go_to_ready_from_startup() == E_NOT_OK) { // No success. Switch back to READY state
1108                 return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_READY;
1109             }
1110         }
1111         }
1112     // The node is not coldstarter, try to integrate into an existing network.
1113     else {
1114         if(Fr_POC_go_to_startup() == E_NOT_OK)  {
1115             return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_AS_NCOLD; // Switching to startup state as non-cold start node
1116         }
1117         else {
1118             // Wait until NORMAL_ACTIVE
1119             do {
1120                 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1121             } while (state_value != FR_POCS_NORMAL_ACTIVE);
1122         }
1123     }
1124         return E_OK;
1125 }
1126
1127 Std_ReturnType Fr_AllowColdstart(uint8_t Fr_CtrlIdx) {
1128 #ifdef DET_ACTIVATED
1129         if (Fr_CtrlIdx != 0) {
1130                 return E_NOT_OK;
1131         }
1132         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1133                 return E_NOT_OK;
1134         }
1135 #endif
1136     Fr_wait_for_POC_ready();
1137     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_ALLOW_COLDSTART;
1138     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1139         return E_NOT_OK;
1140     Fr_wait_for_POC_ready();
1141     return E_OK;
1142 }
1143
1144 Std_ReturnType Fr_AllSlots(uint8_t Fr_CtrlIdx) {
1145 #ifdef DET_ACTIVATED
1146         if (Fr_CtrlIdx != 0) {
1147                 return E_NOT_OK;
1148         }
1149         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1150                 return E_NOT_OK;
1151         }
1152 #endif
1153     Fr_wait_for_POC_ready();
1154     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_ALL_SLOTS;
1155     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1156         return E_NOT_OK;
1157     Fr_wait_for_POC_ready();
1158     return E_OK;
1159 }
1160
1161 Std_ReturnType Fr_HaltCommunication(uint8_t Fr_CtrlIdx) {
1162 #ifdef DET_ACTIVATED
1163         if (Fr_CtrlIdx != 0) {
1164                 return E_NOT_OK;
1165         }
1166         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1167                 return E_NOT_OK;
1168         }
1169 #endif
1170     Fr_wait_for_POC_ready();
1171     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_HALT;
1172     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1173         return E_NOT_OK;
1174     Fr_wait_for_POC_ready();
1175         return E_OK;
1176 }
1177
1178 Std_ReturnType Fr_AbortCommunication(uint8_t Fr_CtrlIdx) {
1179 #ifdef DET_ACTIVATED
1180         if (Fr_CtrlIdx != 0) {
1181                 return E_NOT_OK;
1182         }
1183         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1184                 return E_NOT_OK;
1185         }
1186 #endif
1187     Fr_wait_for_POC_ready();
1188     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_FREEZE;
1189     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1190         return E_NOT_OK;
1191     Fr_wait_for_POC_ready();
1192         return E_OK;
1193 }
1194
1195 Std_ReturnType Fr_SendWUP(uint8_t Fr_CtrlIdx) {
1196 #ifdef DET_ACTIVATED
1197         if (Fr_CtrlIdx != 0) {
1198                 return E_NOT_OK;
1199         }
1200         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1201                 return E_NOT_OK;
1202         }
1203 #endif
1204     Fr_wait_for_POC_ready();
1205     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_WAKEUP;
1206     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1207         return E_NOT_OK;
1208     Fr_wait_for_POC_ready();
1209         return E_OK;
1210 }
1211
1212 Std_ReturnType Fr_SetWakeupChannel(uint8_t Fr_CtrlIdx, Fr_ChannelType Fr_ChnlIdx) {
1213         Std_ReturnType retVal = E_OK;
1214
1215 #ifdef DET_ACTIVATED
1216         if (Fr_CtrlIdx != 0) {
1217                 return E_NOT_OK;
1218         }
1219         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1220                 return E_NOT_OK;
1221         }
1222         if (Fr_ChnlIdx == FR_CHANNEL_AB) {
1223                 return E_NOT_OK;
1224         }
1225         if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_READY) {
1226                 return E_NOT_OK;
1227         }
1228 #endif
1229         if (Fr_POC_go_to_config() == E_NOT_OK) {
1230                 return E_NOT_OK;
1231         }
1232         if (Fr_ChnlIdx == FR_CHANNEL_A) {
1233                 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 0;
1234                 retVal = E_OK;
1235         }
1236         else if (Fr_ChnlIdx == FR_CHANNEL_B) {
1237                 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 1;
1238                 retVal = E_OK;
1239         }
1240         else {
1241                 retVal = E_NOT_OK;
1242         }
1243         if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1244                 retVal = E_NOT_OK;
1245         }
1246
1247         return retVal;
1248 }
1249
1250 Std_ReturnType Fr_GetPOCStatus(uint8_t Fr_CtrlIdx, Fr_POCStatusType* Fr_POCStatusPtr) {
1251         static const Fr_SlotModeType slot_mode[4] = {FR_SLOTMODE_KEYSLOT, FR_SLOTMODE_INVALID, FR_SLOTMODE_ALL_PENDING, FR_SLOTMODE_ALL};
1252         static const Fr_ErrorModeType error_mode[4] = {FR_ERRORMODE_ACTIVE, FR_ERRORMODE_PASSIVE, FR_ERRORMODE_COMM_HALT, FR_ERRORMODE_INVALID};
1253         static const Fr_POCStateType poc_state[9] = {FR_POCSTATE_DEFAULT_CONFIG, FR_POCSTATE_READY, FR_POCSTATE_NORMAL_ACTIVE, FR_POCSTATE_NORMAL_PASSIVE,
1254                         FR_POCSTATE_HALT, FR_POCSTATE_MONITOR, FR_POCSTATE_LOOPBACK, FR_POCSTATE_INVALID, FR_POCSTATE_CONFIG};
1255         static const Fr_WakeupStatusType wup_state[8] = {FR_WAKEUP_UNDEFINED, FR_WAKEUP_RECEIVED_HEADER, FR_WAKEUP_RECEIVED_WUP, FR_WAKEUP_COLLISION_HEADER,
1256                         FR_WAKEUP_COLLISION_WUP, FR_WAKEUP_COLLISION_UNKNOWN, FR_WAKEUP_TRANSMITTED, FR_WAKEUP_INVALID};
1257         static const Fr_StartupStateType startup_state[11] = {FR_STARTUP_PREPARE, FR_STARTUP_COLDSTART_LISTEN, FR_STARTUP_COLDSTART_COLLISION_RESOLUTION,
1258                         FR_STARTUP_COLDSTART_CONSISTENCY_CHECK, FR_STARTUP_COLDSTART_GAP, FR_STARTUP_COLDSTART_JOIN, FR_STARTUP_INTEGRATION_COLDSTART_CHECK,
1259                         FR_STARTUP_INTEGRATION_LISTEN, FR_STARTUP_INTEGRATION_CONSISTENCY_CHECK, FR_STARTUP_INITIALIZE_SCHEDULE, FR_STARTUP_ABORT};
1260
1261 #ifdef DET_ACTIVATED
1262         if (Fr_CtrlIdx != 0) {
1263                 return E_NOT_OK;
1264         }
1265         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1266                 return E_NOT_OK;
1267         }
1268         if (Fr_POCStatusPtr == NULL) {
1269                 return E_NOT_OK;
1270         }
1271 #endif
1272         Fr_POCStatusPtr->SlotMode = slot_mode[frayREG->CCSV_UN.CCSV_ST.slm_B2]; /* Slot mode detection */
1273         Fr_POCStatusPtr->Freeze = (frayREG->CCSV_UN.CCSV_ST.fsi_B1 == 1) ? TRUE : FALSE;        /* Freeze request detection */
1274         Fr_POCStatusPtr->CHIHaltRequest = (frayREG->CCSV_UN.CCSV_ST.hrq_B1 == 1) ? TRUE : FALSE;        /* Halt request detection */
1275         Fr_POCStatusPtr->ColdstartNoise = (frayREG->CCSV_UN.CCSV_ST.csni_B1 == 1) ? TRUE : FALSE;       /* Coldstart noise detection */
1276         Fr_POCStatusPtr->ColdstartNoise = (frayREG->CCSV_UN.CCSV_ST.csni_B1 == 1) ? TRUE : FALSE;       /* Coldstart noise detection */
1277         Fr_POCStatusPtr->ErrorMode = error_mode[frayREG->CCEV_UN.CCEV_ST.errm_B2];      /* Error mode detection */
1278
1279         /* POC state detection */
1280         /* Startup substate detection */
1281         uint16_t pocs = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1282         Fr_POCStatusPtr->StartupState = FR_STARTUP_UNDEFINED;
1283         if (pocs > FR_POCSTATE_DEFAULT_CONFIG && pocs <= FR_POCSTATE_MONITOR) {
1284                 Fr_POCStatusPtr->State = poc_state[pocs];
1285         }
1286         else if (pocs >= FR_POCSTATE_LOOPBACK && pocs <= FR_POCSTATE_CONFIG) {
1287                 Fr_POCStatusPtr->State = poc_state[pocs-7];
1288         }
1289         else if (pocs >= FR_POCS_WAKEUP_STANDBY && pocs <= FR_POCS_WAKEUP_DETECT) {
1290                 Fr_POCStatusPtr->State = FR_POCSTATE_WAKEUP;
1291         }
1292         else if (pocs >= FR_POCS_STARTUP_PREPARE && pocs <= FR_POCS_ABORT_STARTUP) {
1293                 Fr_POCStatusPtr->State = FR_POCSTATE_STARTUP;
1294                 Fr_POCStatusPtr->StartupState = startup_state[frayREG->CCSV_UN.CCSV_ST.pocs_B6 - FR_POCS_STARTUP_PREPARE];
1295         }
1296         else {
1297                 Fr_POCStatusPtr->State = FR_POCSTATE_INVALID;
1298         }
1299
1300         /* Wakeup substate detection */
1301         Fr_POCStatusPtr->WakeupStatus = wup_state[frayREG->CCSV_UN.CCSV_ST.wsv_B3];
1302
1303         return E_OK;
1304 }
1305
1306 Std_ReturnType Fr_TransmitTxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, const uint8_t* Fr_LSduPtr, uint8_t Fr_LSduLength) {
1307         uint32_t word, buffer, index, bufferIndex;
1308 #ifdef DET_ACTIVATED
1309         if (Fr_CtrlIdx != 0) {
1310                 return E_NOT_OK;
1311         }
1312         if (Fr_LPduIdx > cSlotIDMax) {
1313                 return E_NOT_OK;
1314         }
1315         if (Fr_LSduPtr == NULL) {
1316                 return E_NOT_OK;
1317         }
1318         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1319                 return E_NOT_OK;
1320         }
1321
1322 #endif
1323         /* Find the index of the buffer in configuration data array */
1324         for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1325                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1326                         if (Fr_BuffersConfigured[bufferIndex] == TRUE && Fr_buffer_slot_map[bufferIndex].buffer_ptr->isTx == TRUE) {    // Buffer was configured already and is TX
1327                                 memset((void *)frayREG->WRDS, 0, sizeof(frayREG->WRDS));
1328                                 for (word = 0; word < (Fr_LSduLength+3)/4; word++) {
1329                                         index = word*4;
1330                                         buffer = Fr_LSduPtr[index++];
1331                                         buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 8 : 0;
1332                                         buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 16 : 0;
1333                                         buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 24 : 0;
1334                                         frayREG->WRDS[word] = buffer;
1335                                 }
1336                                 Fr_buffer_transmit_data(bufferIndex);
1337                                 return E_OK;
1338                         }
1339                 }
1340         }
1341         return E_NOT_OK;
1342 }
1343
1344 Std_ReturnType Fr_CancelTxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1345         uint8_t bufferIndex;
1346         uint8_t mode;
1347         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1348 #ifdef DET_ACTIVATED
1349         boolean_t canceled = FALSE;
1350         if (Fr_CtrlIdx != 0) {
1351                 return E_NOT_OK;
1352         }
1353         if (Fr_LPduIdx > cSlotIDMax) {
1354                 return E_NOT_OK;
1355         }
1356         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1357                 return E_NOT_OK;
1358         }
1359         if (Fr_Config->msgRAMConfig->secureBuffers != FR_SB_RECONFIG_ENABLED) {
1360                 return E_NOT_OK;
1361         }
1362 #endif
1363
1364         /* If bit IBCM.STXR in the input buffer command mask register is set (STXR = 1), the transmission request
1365          * flag TXR of the selected message buffer is automatically set after the message buffer has been updated.
1366          * If bit IBCM.STXR in the input buffer command mask register is reset (STXR = 0), the transmission request
1367          * flag TXR of the selected message buffer is reset. This can be used to stop transmission from message
1368          * buffers operated in continuous mode.
1369          */
1370
1371         /*
1372          * Write the same configuration into buffer headers with TXREQ disabled.
1373          */
1374         for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1375                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1376                         if (Fr_BuffersConfigured[bufferIndex] == TRUE) {        // Buffer was already configured
1377                                 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1378                                 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1379                                 if (buffer_cfg_ptr->isTx == TRUE) {
1380                                         Fr_config_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering,  buffer_cfg_ptr->slotId, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1381 #ifdef DET_ACTIVATED
1382                                         canceled = TRUE;
1383 #endif
1384                                 }
1385                         }
1386                 }
1387         }
1388
1389 #ifdef DET_ACTIVATED
1390         return (canceled == TRUE) ? E_OK : E_NOT_OK;
1391 #else
1392         return E_OK;
1393 #endif
1394 }
1395
1396 Std_ReturnType Fr_ReceiveRxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, uint8_t* Fr_LSduPtr, Fr_RxLPduStatusType* Fr_LPduStatusPtr, uint8_t* Fr_LSduLengthPtr) {
1397         volatile unsigned long * ndat[4] = {&frayREG->NDAT1_UN.NDAT1_UL, &frayREG->NDAT2_UN.NDAT2_UL, &frayREG->NDAT3_UN.NDAT3_UL, &frayREG->NDAT4_UN.NDAT4_UL};
1398         uint32_t bufferIndex;
1399         uint8_t word, byte;
1400         boolean_t bufferFound = FALSE;
1401         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1402         #define fifo_not_empty (frayREG->FSR_UN.FSR_ST.rfne_B1 == 1) // Macro that makes the code more readable, is undefined at the end of the function
1403
1404 #ifdef DET_ACTIVATED
1405         if (Fr_CtrlIdx != 0) {
1406                 return E_NOT_OK;
1407         }
1408         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1409                 return E_NOT_OK;
1410         }
1411         if (Fr_LPduIdx > cSlotIDMax) {
1412                 return E_NOT_OK;
1413         }
1414         if (Fr_LSduPtr == NULL) {
1415                 return E_NOT_OK;
1416         }
1417         if (Fr_LPduStatusPtr == NULL) {
1418                 return E_NOT_OK;
1419         }
1420         if (Fr_LSduLengthPtr == NULL) {
1421                 return E_NOT_OK;
1422         }
1423 #endif
1424         /* Find the index of the buffer in configuration data array */
1425         *Fr_LSduLengthPtr = 0;
1426         *Fr_LPduStatusPtr = FR_NOT_RECEIVED;
1427
1428         /*
1429          * Try to find new message in static and dynamic segment buffers at first:
1430          *      - Check New Data flag, if no new data received, return.
1431          *      - Load received data and header into the output buffer.
1432          *      - Store loaded payload from header of the output buffer.
1433          *      - Copy data from the output buffer to the Fr_LSduPtr address.
1434          *      If no new message has been retrieved, there is possibility that
1435          *      RX FIFO buffer has received it (for example when static or dynamic
1436          *      segment buffers has rejection filter for channel A, but FIFO for channel B).
1437          *      - Check if the Fr_LPduIdx can be accepted by the RX FIFO (FID combined with the mask.
1438          *      - Check if the FIFO is not empty
1439          *      - Pop data and header into an output buffer.
1440          *      - Detect if more data is available in the FIFO and set Fr_LPduStatusPtr.
1441          *      - Store loaded payload from header of the output buffer.
1442          *      - Copy data from the output buffer to the Fr_LSduPtr address.
1443          */
1444         for (bufferIndex = 0; bufferIndex < frayREG->MRC_UN.MRC_ST.ffb_B8; bufferIndex++) {     // Static and dynamic segment buffers
1445                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1446                         if (Fr_BuffersConfigured[bufferIndex] == TRUE) {        // Buffer was configured already
1447                                 bufferFound = TRUE;
1448                                 if (*ndat[bufferIndex/32] & (0x1 << bufferIndex%32)) {          // New data received
1449                                         Fr_buffer_receive_data_header(bufferIndex);     // Read data and header into output buffer
1450                                         *Fr_LPduStatusPtr = FR_RECEIVED;
1451                                         break;  // Buffer which received a message has been found, other buffers are irrelevant. According the FlexRay specification the buffer with lowest index has the highest priority.
1452                                 }
1453                         }
1454                 }
1455         }
1456         if (*Fr_LPduStatusPtr == FR_NOT_RECEIVED) {             // No message was received, try the FIFO.
1457                 bufferIndex = frayREG->MRC_UN.MRC_ST.ffb_B8;
1458                 if (Fr_BuffersConfigured[bufferIndex] == FALSE)
1459                         return E_NOT_OK;        // No FIFO configured
1460                 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1461                 if ((Fr_LPduIdx & (~buffer_cfg_ptr->fidMask)) != (buffer_cfg_ptr->slotId & (~buffer_cfg_ptr->fidMask)) ) {
1462                         bufferFound = TRUE;
1463                         if (fifo_not_empty) {   // The RX FIFO buffer is not empty
1464                                 Fr_buffer_receive_data_header(bufferIndex);  // Consume first element from FIFO
1465                                 if (fifo_not_empty) // FIFO not empty after last pop
1466                                         *Fr_LPduStatusPtr = FR_RECEIVED_MORE_DATA_AVAILABLE;
1467                                 else // FIFO empty after last pop
1468                                         *Fr_LPduStatusPtr = FR_RECEIVED;
1469                         }
1470                 }
1471         }
1472
1473         /*
1474          * Copy data from output register into address from parameter Fr_LSduPtr.
1475          * Data in the output register are 32b words,
1476          * Data in Fr_LSduPtr are 8b words.
1477          */
1478         *Fr_LSduLengthPtr = frayREG->RDHS2_UN.RDHS2_ST.plr_B7*2;        // Number of bytes copied into Fr_LSduPtr
1479         for (byte = 0, word = 0; word < *Fr_LSduLengthPtr/4; word++) {
1480                         Fr_LSduPtr[byte++] = frayREG->RDDS[word] & 0xFF;
1481                         Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF00) >> 8;
1482                         Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF0000) >> 16;
1483                         Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF000000) >> 24;
1484         }
1485
1486         return (bufferFound == TRUE) ? E_OK: E_NOT_OK;
1487         #undef fifo_not_empty
1488 }
1489
1490 Std_ReturnType Fr_CheckTxLPduStatus(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, Fr_TxLPduStatusType* Fr_TxLPduStatusPtr) {
1491         volatile unsigned long * txrq[4] = {&frayREG->TXRQ1_UN.TXRQ1_UL, &frayREG->TXRQ2_UN.TXRQ2_UL, &frayREG->TXRQ3_UN.TXRQ3_UL, &frayREG->TXRQ4_UN.TXRQ4_UL};
1492         uint8_t bufferIndex;
1493 #ifdef DET_ACTIVATED
1494         if (Fr_CtrlIdx != 0) {
1495                 return E_NOT_OK;
1496         }
1497         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1498                 return E_NOT_OK;
1499         }
1500         if (Fr_LPduIdx > cSlotIDMax) {
1501                 return E_NOT_OK;
1502         }
1503         if (Fr_TxLPduStatusPtr == NULL) {
1504                 return E_NOT_OK;
1505         }
1506 #endif
1507         for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1508                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1509                         if (Fr_BuffersConfigured[bufferIndex] == TRUE) {        // Buffer was configured already
1510                                 if (Fr_buffer_slot_map[bufferIndex].buffer_ptr->isTx == TRUE) {
1511                                         if (*txrq[bufferIndex/32] & (0x1 << bufferIndex%32)) {  // Transmit request is pending
1512                                                 *Fr_TxLPduStatusPtr = FR_NOT_TRANSMITTED;
1513                                         }
1514                                         else {
1515                                                 *Fr_TxLPduStatusPtr = FR_TRANSMITTED;
1516                                         }
1517                                         break;
1518                                 }
1519                         }
1520                 }
1521         }
1522         return E_OK;
1523 }
1524
1525 Std_ReturnType Fr_PrepareLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1526         uint32_t bufferIndex;
1527         uint32_t mode;
1528         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1529
1530 #ifdef DET_ACTIVATED
1531         if (Fr_CtrlIdx != 0) {
1532                 return E_NOT_OK;
1533         }
1534         if (Fr_DrvState < FR_ST_DRV_INITIALIZED) {
1535                 return E_NOT_OK;
1536         }
1537         if (Fr_LPduIdx > cSlotIDMax) {
1538                 return E_NOT_OK;
1539         }
1540 #endif
1541         /* Find the index of the buffer in configuration data array */
1542         for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1543                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1544                         if (Fr_BuffersConfigured[bufferIndex] == FALSE) {       // Buffer was not yet configured
1545                                 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1546                                 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1547                                 Fr_MsgRAMDataPtrs[bufferIndex] = Fr_MsgRAMDataOffset;
1548                                 if (bufferIndex >= frayREG->MRC_UN.MRC_ST.ffb_B8) { // This is RX FIFO buffer
1549                                         Fr_configure_fifo_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering,  buffer_cfg_ptr->slotId, buffer_cfg_ptr->fidMask, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1550                                 }
1551                                 else {  // Static/dynamic segment buffer
1552                                         Fr_config_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering, buffer_cfg_ptr->slotId, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1553                                 }
1554                                 /*
1555                                  * Calculate new address.
1556                                  * Payload contains the number of two-bytes words, Fr_MsgRAMDataPtrs contains addresses of 4B words in message RAM, all msgRAM addresses have
1557                                  * to be 4B aligned.
1558                                  * Offset has to be divided by two each time because  payload is in 2B words and msgRAM addresses are in 4B words.
1559                                  */
1560                                 Fr_MsgRAMDataOffset += ((buffer_cfg_ptr->maxPayload)%2U == 0U ? (buffer_cfg_ptr->maxPayload) : ((buffer_cfg_ptr->maxPayload)+1U))/2;
1561                                 Fr_BuffersConfigured[bufferIndex] = TRUE;
1562                         }
1563                 }
1564         }
1565         return E_OK;
1566 }
1567
1568 Std_ReturnType Fr_ReconfigLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, uint16_t Fr_FrameId, Fr_ChannelType Fr_ChnlIdx, uint8_t Fr_CycleFiltering, uint8_t Fr_PayloadLength) {
1569         uint32_t bufferIndex;
1570         int lowest_index = 0;
1571         uint8_t highest_index = frayREG->MRC_UN.MRC_ST.ffb_B8;
1572         uint32_t mode;
1573         const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1574
1575 #ifdef DET_ACTIVATED
1576         boolean_t reconfigured = FALSE;
1577         if (Fr_CtrlIdx != 0) {
1578                 return E_NOT_OK;
1579         }
1580         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1581                 return E_NOT_OK;
1582         }
1583 #endif
1584         lowest_index = Fr_reconfigurable_buffer_index();
1585         if (lowest_index == -1)
1586                 return E_NOT_OK | ERR_PARAM_RECONFIG_NOT_ALLOWED;
1587         if (Fr_FrameId == 0) {
1588                 return E_NOT_OK | ERR_PARAM_INVALID_FRAME_ID;
1589         }
1590         if (Fr_FrameId > Fr_Config->clusterConfiguration->gNumberOfStaticSlots &&
1591                         Fr_ChnlIdx == FR_CHANNEL_AB) {
1592                 return E_NOT_OK | ERR_PARAM_INVALID_CHANNEL;
1593         }
1594
1595         for (bufferIndex = lowest_index; bufferIndex < highest_index; bufferIndex++) {
1596                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1597                         if (Fr_BuffersConfigured[bufferIndex] == TRUE) {        // Buffer was configured already
1598                                 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1599                                 if (Fr_PayloadLength > buffer_cfg_ptr->maxPayload) {
1600                                         return E_NOT_OK | ERR_PARAM_PAYLOAD_TOO_BIG;
1601                                 }
1602                                 Fr_buffer_slot_map[bufferIndex].slot_id = Fr_FrameId;
1603                                 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1604                                 Fr_config_buffer(bufferIndex, mode, Fr_CycleFiltering, Fr_FrameId, Fr_PayloadLength, Fr_MsgRAMDataPtrs[bufferIndex]);
1605 #ifdef DET_ACTIVATED
1606                                 reconfigured = TRUE;
1607 #endif
1608                         }
1609                 }
1610         }
1611
1612 #ifdef DET_ACTIVATED
1613         if (reconfigured == FALSE)
1614                 return E_NOT_OK | ERR_PARAM_NO_BUFFER_FOUND;
1615 #endif
1616         return E_OK;
1617 }
1618
1619 Std_ReturnType Fr_DisableLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1620         uint8_t bufferIndexLimit;
1621         uint8_t bufferIndex;
1622         uint8_t mode;
1623         int lowest_index;
1624 #ifdef DET_ACTIVATED
1625         boolean_t disabled = FALSE;
1626         if (Fr_CtrlIdx != 0) {
1627                 return E_NOT_OK;
1628         }
1629         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1630                 return E_NOT_OK;
1631         }
1632         if (Fr_LPduIdx > cSlotIDMax) {
1633                 return E_NOT_OK;
1634         }
1635         if (Fr_Config->msgRAMConfig->secureBuffers != FR_SB_RECONFIG_ENABLED) {
1636                 return E_NOT_OK;
1637         }
1638 #endif
1639         /* Determine reconfigurable buffers from the data in MRC.SET bits */
1640         switch (frayREG->MRC_UN.MRC_ST.sec_B2) {
1641         case 0:
1642                 bufferIndexLimit = frayREG->MRC_UN.MRC_ST.ffb_B8;
1643                 break;
1644         case 1:
1645                 bufferIndexLimit = frayREG->MRC_UN.MRC_ST.fdb_B8;
1646                 break;
1647         default:
1648                 return E_OK;    // No reconfiguration enabled
1649         }
1650
1651         /* Find the index of the buffer in configuration data array */
1652         for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1653                 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1654                         if (Fr_BuffersConfigured[bufferIndex] == TRUE) {        // Buffer was not yet configured
1655                                 lowest_index = Fr_reconfigurable_buffer_index();
1656                                 if (lowest_index == -1) // Reconfiguration disabled
1657                                         break;
1658                                 if (bufferIndex < lowest_index)
1659                                         continue;
1660                                 if (bufferIndex < bufferIndexLimit) {   // Buffer is reconfigurable, reset its configuration registers.
1661                                         mode = 0;
1662                                         Fr_MsgRAMDataPtrs[bufferIndex] = 0;
1663                                         Fr_BuffersConfigured[bufferIndex] = FALSE;
1664                                         Fr_config_buffer(bufferIndex, mode, Fr_buffer_slot_map[bufferIndex].buffer_ptr->cycleCounterFiltering,
1665                                                         Fr_buffer_slot_map[bufferIndex].buffer_ptr->slotId,
1666                                                         Fr_buffer_slot_map[bufferIndex].buffer_ptr->maxPayload,
1667                                                         Fr_MsgRAMDataPtrs[bufferIndex]);
1668 #ifdef DET_ACTIVATED
1669                                         disabled = TRUE;
1670 #endif
1671                                 }
1672                         }
1673                 }
1674         }
1675 #ifdef DET_ACTIVATED
1676         return (disabled == TRUE) ? E_OK : E_NOT_OK;
1677 #else
1678         return E_OK;
1679 #endif
1680 }
1681
1682 Std_ReturnType Fr_GetGlobalTime(uint8_t Fr_CtrlIdx, uint8_t* Fr_CyclePtr, uint16_t* Fr_MacroTickPtr) {
1683 #ifdef DET_ACTIVATED
1684         if (Fr_CtrlIdx != 0) {
1685                 return E_NOT_OK;
1686         }
1687         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1688                 return E_NOT_OK;
1689         }
1690         if (Fr_CyclePtr == NULL) {
1691                 return E_NOT_OK;
1692         }
1693         if (Fr_MacroTickPtr == NULL) {
1694                 return E_NOT_OK;
1695         }
1696 #endif
1697         uint32_t time = frayREG->MTCCV_UN.MTCCV_UL;
1698         *Fr_CyclePtr = __mfld2val(MTCCV_CCV_MSK, time);
1699         *Fr_MacroTickPtr = __mfld2val(MTCCV_MTV_MSK, time);
1700         return E_OK;
1701 }
1702
1703 static inline uint32_t swap32(uint32_t x)
1704 {
1705         return  (x & 0x000000ff) << 24 |
1706                 (x & 0x0000ff00) << 8 |
1707                 (x & 0x00ff0000) >> 8 |
1708                 (x & 0xff000000) >> 24;
1709 }
1710
1711 Std_ReturnType Fr_GetNmVector(uint8_t Fr_CtrlIdx, uint8_t* Fr_NmVectorPtr) {
1712 #ifdef DET_ACTIVATED
1713         if (Fr_CtrlIdx != 0) {
1714                 return E_NOT_OK;
1715         }
1716         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1717                 return E_NOT_OK;
1718         }
1719         if (Fr_NmVectorPtr == NULL) {
1720                 return E_NOT_OK;
1721         }
1722 #endif
1723         *((uint32_t*)(Fr_NmVectorPtr+0)) = swap32(frayREG->NMV1_UN.NMV1_UL);
1724         *((uint32_t*)(Fr_NmVectorPtr+4)) = swap32(frayREG->NMV2_UN.NMV2_UL);
1725         *((uint32_t*)(Fr_NmVectorPtr+8)) = swap32(frayREG->NMV3_UL);
1726         return E_OK;
1727 }
1728
1729 Std_ReturnType Fr_GetNumOfStartupFrames(uint8_t Fr_CtrlIdx, uint8_t* Fr_NumOfStartupFramesPtr) {
1730         /* TODO: Implement - can not find this information in the datasheet */
1731         return E_OK;
1732 }
1733
1734 Std_ReturnType Fr_GetChannelStatus(uint8_t Fr_CtrlIdx, uint16_t* Fr_ChannelAStatusPtr, uint16_t* Fr_ChannelBStatusPtr) {
1735 #ifdef DET_ACTIVATED
1736         if (Fr_CtrlIdx != 0) {
1737                 return E_NOT_OK;
1738         }
1739         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1740                 return E_NOT_OK;
1741         }
1742         if (Fr_ChannelAStatusPtr == NULL) {
1743                 return E_NOT_OK;
1744         }
1745         if (Fr_ChannelBStatusPtr == NULL) {
1746                 return E_NOT_OK;
1747         }
1748 #endif
1749         *Fr_ChannelAStatusPtr = 0;
1750         *Fr_ChannelBStatusPtr = 0;
1751
1752         *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.vfra_B1;
1753         *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.seda_B1 << 1;
1754         *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.ceda_B1 << 2;
1755         *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.cia_B1 << 3;
1756         *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.sbva_B1 << 4;
1757         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.mtsa_B1 << 8;
1758         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sesa_B1 << 9;
1759         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbsa_B1 << 10;
1760         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.tcsa_B1 << 11;
1761         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sena_B1 << 12;
1762         *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbna_B1 << 13;
1763
1764         *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.vfrb_B1;
1765         *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.sedb_B1 << 1;
1766         *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.cedb_B1 << 2;
1767         *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.cib_B1 << 3;
1768         *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.sbvb_B1 << 4;
1769         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.mtsb_B1 << 8;
1770         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sesb_B1 << 9;
1771         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbsb_B1 << 10;
1772         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.tcsb_B1 << 11;
1773         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.senb_B1 << 12;
1774         *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbnb_B1 << 13;
1775
1776         return E_OK;
1777 }
1778
1779 Std_ReturnType Fr_GetClockCorrection(uint8_t Fr_CtrlIdx, int16_t* Fr_RateCorrectionPtr, int32_t* Fr_OffsetCorrectionPtr) {
1780 #ifdef DET_ACTIVATED
1781         if (Fr_CtrlIdx != 0) {
1782                 return E_NOT_OK;
1783         }
1784         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1785                 return E_NOT_OK;
1786         }
1787         if (Fr_RateCorrectionPtr == NULL) {
1788                 return E_NOT_OK;
1789         }
1790         if (Fr_OffsetCorrectionPtr == NULL) {
1791                 return E_NOT_OK;
1792         }
1793 #endif
1794         *Fr_RateCorrectionPtr = frayREG->RCV_UN.RCV_ST.rcv_B12;
1795         *Fr_OffsetCorrectionPtr = frayREG->OCV_UN.OCV_ST.ocv_B14;
1796
1797         return E_OK;
1798 }
1799
1800 Std_ReturnType Fr_GetSyncFrameList(uint8_t Fr_CtrlIdx, uint8_t Fr_ListSize, uint16_t* Fr_ChannelAEvenListPtr, uint16_t* Fr_ChannelBEvenListPtr, uint16_t* Fr_ChannelAOddListPtr, uint16_t* Fr_ChannelBOddListPtr) {
1801         uint32_t esid;
1802         uint32_t osid;
1803         uint8_t i;
1804 #ifdef DET_ACTIVATED
1805         if (Fr_CtrlIdx != 0) {
1806                 return E_NOT_OK;
1807         }
1808         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1809                 return E_NOT_OK;
1810         }
1811         if (Fr_ChannelAEvenListPtr == NULL) {
1812                 return E_NOT_OK;
1813         }
1814         if (Fr_ChannelBEvenListPtr == NULL) {
1815                 return E_NOT_OK;
1816         }
1817         if (Fr_ChannelAOddListPtr == NULL) {
1818                 return E_NOT_OK;
1819         }
1820         if (Fr_ChannelBOddListPtr == NULL) {
1821                 return E_NOT_OK;
1822         }
1823 #endif
1824
1825         if (Fr_ListSize > FR_MAX_SYNC_FRAME_LIST_SIZE) { // Limit list size to 15
1826                 Fr_ListSize = FR_MAX_SYNC_FRAME_LIST_SIZE;
1827         }
1828
1829         for (i = 0; i < Fr_ListSize; i++) {
1830                 esid = frayREG->ESID_UL[i];
1831                 osid = frayREG->OSID_UL[i];
1832
1833                 Fr_ChannelAEvenListPtr[i] = (__mfld2val(ESID_RXEA_MSK, esid) == 1) ? __mfld2val(ESID_EID_MSK, esid) : 0;
1834                 Fr_ChannelBEvenListPtr[i] = (__mfld2val(ESID_RXEB_MSK, esid) == 1) ? __mfld2val(ESID_EID_MSK, esid) : 0;
1835                 Fr_ChannelAOddListPtr[i] = (__mfld2val(OSID_RXOA_MSK, osid) == 1) ? __mfld2val(OSID_OID_MSK, osid) : 0;
1836                 Fr_ChannelBOddListPtr[i] = (__mfld2val(OSID_RXOB_MSK, osid) == 1) ? __mfld2val(OSID_OID_MSK, osid) : 0;
1837         }
1838
1839         for (i = Fr_ListSize; i < 15; i++) {
1840                 Fr_ChannelAEvenListPtr[i] = 0;
1841                 Fr_ChannelBEvenListPtr[i] = 0;
1842                 Fr_ChannelAOddListPtr[i] = 0;
1843                 Fr_ChannelBOddListPtr[i] = 0;
1844         }
1845
1846         return E_OK;
1847 }
1848
1849 Std_ReturnType Fr_GetWakeupRxStatus(uint8_t Fr_CtrlIdx, uint8_t* Fr_WakeupRxStatusPtr) {
1850 #ifdef DET_ACTIVATED
1851         if (Fr_CtrlIdx != 0) {
1852                 return E_NOT_OK;
1853         }
1854         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1855                 return E_NOT_OK;
1856         }
1857         if (Fr_WakeupRxStatusPtr == NULL) {
1858                 return E_NOT_OK;
1859         }
1860 #endif
1861
1862         *Fr_WakeupRxStatusPtr = 0;
1863         *Fr_WakeupRxStatusPtr |= frayREG->SIR_UN.SIR_ST.wupa_B1;
1864         *Fr_WakeupRxStatusPtr |= frayREG->SIR_UN.SIR_ST.wupb_B1 << 1;
1865         // Reset flags
1866         frayREG->SIR_UN.SIR_ST.wupa_B1 = 1;
1867         frayREG->SIR_UN.SIR_ST.wupb_B1 = 1;
1868         return E_OK;
1869 }
1870
1871 Std_ReturnType Fr_SetAbsoluteTimer(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx, uint8_t Fr_Cycle, uint16_t Fr_Offset) {
1872 #ifdef DET_ACTIVATED
1873         if (Fr_CtrlIdx != 0) {
1874                 return E_NOT_OK;
1875         }
1876         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1877                 return E_NOT_OK;
1878         }
1879         if (Fr_AbsTimerIdx > 1) {
1880                 return E_NOT_OK;
1881         }
1882         if (Fr_Offset > Fr_Config->clusterConfiguration->gMacroPerCycle) {
1883                 return E_NOT_OK;
1884         }
1885         if (Fr_Cycle & 0x80) {
1886                 return E_NOT_OK;
1887         }
1888 #endif
1889         if (Fr_AbsTimerIdx == 0) {
1890                 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 0;
1891                 frayREG->T0C_UN.T0C_ST.t0ms_B1 = 1;
1892                 frayREG->T0C_UN.T0C_ST.t0cc_B7 = Fr_Cycle;
1893                 frayREG->T0C_UN.T0C_ST.t0mo_B14 = Fr_Offset;
1894                 frayREG->SIR_UN.SIR_ST.ti0_B1 = 1;      // Reset interrupt
1895                 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 1;
1896         }
1897         else if (Fr_AbsTimerIdx == 1) {
1898                 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 0;
1899                 frayREG->T1C_UN.T1C_ST.t1ms_B1 = 1;
1900                 frayREG->T1C_UN.T1C_ST.t1mc_B14 = Fr_Cycle*Fr_Config->clusterConfiguration->gMacroPerCycle+Fr_Offset;
1901                 frayREG->SIR_UN.SIR_ST.ti1_B1 = 1;// Reset interrupt
1902                 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 1;
1903         }
1904         else {
1905                 return E_NOT_OK;
1906         }
1907
1908         return E_OK;
1909 }
1910
1911 Std_ReturnType Fr_CancelAbsoluteTimer(uint8_t Fr_CtrlIdx,       uint8_t Fr_AbsTimerIdx) {
1912 #ifdef DET_ACTIVATED
1913         if (Fr_CtrlIdx != 0) {
1914                 return E_NOT_OK;
1915         }
1916         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1917                 return E_NOT_OK;
1918         }
1919         if (Fr_AbsTimerIdx > 1) {
1920                 return E_NOT_OK;
1921         }
1922 #endif
1923         if (Fr_AbsTimerIdx == 0) {
1924                 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 0;
1925         }
1926         else if (Fr_AbsTimerIdx == 1) {
1927                 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 0;
1928         }
1929         else {
1930                 return E_NOT_OK;
1931         }
1932         return E_OK;
1933 }
1934
1935 Std_ReturnType Fr_EnableAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1936 #ifdef DET_ACTIVATED
1937         if (Fr_CtrlIdx != 0) {
1938                 return E_NOT_OK;
1939         }
1940         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1941                 return E_NOT_OK;
1942         }
1943         if (Fr_AbsTimerIdx > 1) {
1944                 return E_NOT_OK;
1945         }
1946 #endif
1947         frayREG->ILE_UN.ILE_ST.eint0_B1 = 1;
1948         if (Fr_AbsTimerIdx == 0) {
1949                 frayREG->SIES_UN.SIES_ST.ti0e_B1 = 1;
1950         }
1951         else if (Fr_AbsTimerIdx == 1) {
1952                 frayREG->SIES_UN.SIES_ST.ti0e_B1 = 1;
1953         }
1954         else {
1955                 return E_NOT_OK;
1956         }
1957         return E_OK;
1958 }
1959
1960 Std_ReturnType Fr_AckAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1961 #ifdef DET_ACTIVATED
1962         if (Fr_CtrlIdx != 0) {
1963                 return E_NOT_OK;
1964         }
1965         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1966                 return E_NOT_OK;
1967         }
1968         if (Fr_AbsTimerIdx > 1) {
1969                 return E_NOT_OK;
1970         }
1971 #endif
1972         if (Fr_AbsTimerIdx == 0) {
1973                 frayREG->SIR_UN.SIR_ST.ti0_B1 = 1;
1974         }
1975         else if (Fr_AbsTimerIdx == 1) {
1976                 frayREG->SIR_UN.SIR_ST.ti1_B1 = 1;
1977         }
1978         else {
1979                 return E_NOT_OK;
1980         }
1981         return E_OK;
1982 }
1983
1984 Std_ReturnType Fr_DisableAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1985 #ifdef DET_ACTIVATED
1986         if (Fr_CtrlIdx != 0) {
1987                 return E_NOT_OK;
1988         }
1989         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1990                 return E_NOT_OK;
1991         }
1992         if (Fr_AbsTimerIdx > 1) {
1993                 return E_NOT_OK;
1994         }
1995 #endif
1996         if (Fr_AbsTimerIdx == 0) {
1997                 frayREG->SIER_UN.SIER_ST.ti0e_B1 = 1;
1998         }
1999         else if (Fr_AbsTimerIdx == 1) {
2000                 frayREG->SIER_UN.SIER_ST.ti0e_B1 = 1;
2001         }
2002         else {
2003                 return E_NOT_OK;
2004         }
2005         return E_OK;
2006 }
2007
2008 Std_ReturnType Fr_GetAbsoluteTimerIRQStatus(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx, boolean_t* Fr_IRQStatusPtr) {
2009 #ifdef DET_ACTIVATED
2010         if (Fr_CtrlIdx != 0) {
2011                 return E_NOT_OK;
2012         }
2013         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
2014                 return E_NOT_OK;
2015         }
2016         if (Fr_AbsTimerIdx > 1) {
2017                 return E_NOT_OK;
2018         }
2019         if (Fr_IRQStatusPtr == NULL) {
2020                 return E_NOT_OK;
2021         }
2022 #endif
2023         if (Fr_AbsTimerIdx == 0) {
2024                 *Fr_IRQStatusPtr = (frayREG->SIR_UN.SIR_ST.ti0_B1 == 1) ? TRUE : FALSE;
2025         }
2026         else if (Fr_AbsTimerIdx == 1) {
2027                 *Fr_IRQStatusPtr = (frayREG->SIR_UN.SIR_ST.ti1_B1 == 1) ? TRUE : FALSE;
2028         }
2029         else {
2030                 return E_NOT_OK;
2031         }
2032         return E_OK;
2033 }
2034
2035 void Fr_GetVersionInfo(Std_VersionInfoType* VersioninfoPtr) {
2036 #ifdef DET_ACTIVATED
2037         if (VersioninfoPtr == NULL) {
2038                 return;
2039         }
2040 #endif
2041         VersioninfoPtr->vendorID = Fr_versionInfo.vendorID;
2042         VersioninfoPtr->moduleID = Fr_versionInfo.moduleID;
2043         VersioninfoPtr->sw_major_version = Fr_versionInfo.sw_major_version;
2044         VersioninfoPtr->sw_minor_version= Fr_versionInfo.sw_minor_version;
2045         VersioninfoPtr->sw_patch_version= Fr_versionInfo.sw_patch_version;
2046 }
2047
2048 Std_ReturnType Fr_ReadCCConfig( uint8_t Fr_CtrlIdx, uint8_t Fr_ConfigParamIdx, uint32_t* Fr_ConfigParamValuePtr) {
2049
2050 #ifdef DET_ACTIVATED
2051         if (Fr_CtrlIdx != 0) {
2052                 return E_NOT_OK;
2053         }
2054         if (Fr_ConfigParamIdx >= FR_CIDX_CNT) {
2055                 return E_NOT_OK;
2056         }
2057         if (Fr_ConfigParamValuePtr == NULL) {
2058                 return E_NOT_OK;
2059         }
2060         if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
2061                 return E_NOT_OK;
2062         }
2063 #endif
2064
2065         *Fr_ConfigParamValuePtr = Fr_ConfigParPtrs[Fr_ConfigParamIdx];
2066         return E_OK;
2067 }
2068
2069 int Fr_spi_transfer(uint8_t port) {
2070     uint32_t commands[2];
2071     port_desc_t* desc;
2072
2073     if (port > FRAY_NUM_PORTS) return -1;
2074     desc = hal_port_get_dsc(fray_port_names[port], -1);
2075     fray_spi_cmd_sh = fray_spi_cmd;
2076     commands[0] = (fray_spi_cmd_sh & 0xFF00) >> 8;
2077     commands[1] = (fray_spi_cmd_sh & 0xFF);
2078
2079     fray_spi_resp[port] = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
2080     return 0;
2081 }
2082
2083 int Fr_spi_response(uint8_t port) {
2084     if (port > FRAY_NUM_PORTS) return -1;
2085     return fray_spi_resp[port];
2086 }
2087
2088 int Fr_spi_get_cmd(uint8_t port) {
2089     if (port > FRAY_NUM_PORTS) return -1;
2090     return fray_spi_cmd;
2091 }