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