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