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