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