]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/fray.c
Merge branch 'master' of rtime.felk.cvut.cz:pes-rpp/rpp-lib
[pes-rpp/rpp-lib.git] / rpp / src / drv / fray.c
1 /*
2  * fray.c
3  *
4  *  Created on: 12.2.2013
5  *      Author: Michal Horn
6  *              Martin Zeman
7  *
8  *  This file contains function for getting fray status as spi respons
9  *  and functions for FlexRay initialization and usage.
10  *  FlexRay chips on SPI are read only.
11  */
12
13 //#include "drv_fray.h"
14 #include "drv/drv.h"
15
16 /** Prepared spi command */
17 uint32_t fray_spi_cmd = FRAY_SPICMD_INIT_VAL;
18 /** Shadow variable used during command sending */
19 uint32_t fray_spi_cmd_sh;
20 /** Array of responses for each fray driver */
21 uint32_t fray_spi_resp[FRAY_NUM_PORTS];
22 /** Array of port names to be easily accessible by indexing */
23 const char* fray_port_names[FRAY_NUM_PORTS] = { PORT_NAME_FRAY1, PORT_NAME_FRAY2 };
24
25 /**
26  * @brief   Function sends prepared command on SPI and stores response
27  *
28  * @param[in] port Index of flexray 0 or 1
29  * @return 0 when success, -1 when bad parameter
30  */
31 int fray_spi_transfer(uint8_t port) {
32     uint32_t commands[2];
33     port_desc_t* desc;
34
35     if (port > FRAY_NUM_PORTS) return -1;
36     desc = hal_port_get_dsc(fray_port_names[port], -1);
37     fray_spi_cmd_sh = fray_spi_cmd;
38     commands[0] = (fray_spi_cmd_sh & 0xFF00) >> 8;
39     commands[1] = (fray_spi_cmd_sh & 0xFF);
40
41     fray_spi_resp[port] = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
42     return 0;
43 }
44
45 /**
46  * @brief Returns last spi response of selected fray port
47  *
48  * @param[in] port Index of flexray 0 or 1
49  * @return spi response or -1 when bad parameter
50  */
51 int fray_spi_response(uint8_t port) {
52     if (port > FRAY_NUM_PORTS) return -1;
53     return fray_spi_resp[port];
54 }
55
56 /**
57  * @brief Returns last spi command of selected fray port
58  *
59  * @param[in] port Index of flexray 0 or 1
60  * @return spi command or -1 when bad parameter
61  */
62 int fray_spi_get_cmd(uint8_t port) {
63     if (port > FRAY_NUM_PORTS) return -1;
64     return fray_spi_cmd;
65 }
66
67 /** @fn clear_msg_ram(void)
68 *   @brief Clears FRAY message RAMs
69 *
70 *   Send command to POC to set all bits of message RAM to 0.
71 *   @return SUCCESS or FAILURE when command was not accepted
72 */
73 int fray_clear_msg_ram() {
74     fray_wait_for_POC_ready();
75     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CLEAR_RAMS;
76     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) {
77         return FAILURE;
78     }
79     fray_wait_for_POC_ready();
80     return SUCCESS;
81 }
82
83 /** @fn wait_for_POC_ready(void)
84 *   @brief Wait until POC is not busy
85 */
86 void fray_wait_for_POC_ready() {
87     // Wait for PBSY bit to clear - POC not busy.
88     // 1: Signals that the POC is busy and cannot accept a command from the host. CMD(3-0) is locked against write accesses.
89     while(((frayREG->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);
90 }
91
92 /** @fn fray_init(cfg *Fr_ConfigPtr)
93 *   @brief Set global configuration
94 *
95 *   Copy configuration filled in structure into config registers
96 *   @param Fr_ConfigPtr Pointer to structure with configuration
97 */
98 void fray_init(const cfg *Fr_ConfigPtr)
99 {
100     frayREG->SUCC1_UN.SUCC1_UL = 0x0C401000;    // Keep default value
101     frayREG->MRC_UN.MRC_UL       = Fr_ConfigPtr->mrc;
102     frayREG->PRTC1_UN.PRTC1_UL   = Fr_ConfigPtr->prtc1;
103     frayREG->PRTC2_UN.PRTC2_UL   = Fr_ConfigPtr->prtc2;
104     frayREG->MHDC_UN.MHDC_UL     = Fr_ConfigPtr->mhdc;
105     frayREG->GTUC1_UN.GTUC1_UL   = Fr_ConfigPtr->gtu1;
106     frayREG->GTUC2_UN.GTUC2_UL   = Fr_ConfigPtr->gtu2;
107     frayREG->GTUC3_UN.GTUC3_UL   = Fr_ConfigPtr->gtu3;
108     frayREG->GTUC4_UN.GTUC4_UL   = Fr_ConfigPtr->gtu4;
109     frayREG->GTUC5_UN.GTUC5_UL   = Fr_ConfigPtr->gtu5;
110     frayREG->GTUC6_UN.GTUC6_UL   = Fr_ConfigPtr->gtu6;
111     frayREG->GTUC7_UN.GTUC7_UL   = Fr_ConfigPtr->gtu7;
112     frayREG->GTUC8_UN.GTUC8_UL   = Fr_ConfigPtr->gtu8;
113     frayREG->GTUC9_UN.GTUC9_UL   = Fr_ConfigPtr->gtu9;
114     frayREG->GTUC10_UN.GTUC10_UL = Fr_ConfigPtr->gtu10;
115     frayREG->GTUC11_UN.GTUC11_UL = Fr_ConfigPtr->gtu11;
116     frayREG->SUCC2_UN.SUCC2_UL   = Fr_ConfigPtr->succ2;
117     frayREG->SUCC3_UN.SUCC3_UL   = Fr_ConfigPtr->succ3;
118     frayREG->SUCC1_UN.SUCC1_ST.txst_B1   = 1;
119     frayREG->SUCC1_UN.SUCC1_ST.txsy_B1   = 1;
120 }
121 /**
122  *  Fill FIFO filter rejectin configuration and configure buffer.
123  *  @param[in]  buf_num     number of buffer to be configured (0-128)
124  *  @param[in]  mode        Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
125  *  @param[in]  cyc_filter  Setting for cycle filter. 0 - disabled
126  *  @param[in]  frame_id    Id of the frame to be associated with the buffer
127  *  @param[in]  payload     Maximum data size in half-word
128  *  @param[in]  data_pointer    Address of the first word of data in buffer
129  */
130 void fray_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) {
131         frayREG->FRF_UN.FRF_ST.rnf = (mode&FRAY_BUF_REJECT_NULL_FRAMES) ? 1 : 0;
132         frayREG->FRF_UN.FRF_ST.rss = (mode&FRAY_BUF_REJECT_STATIC_SEGMENT) ? 1 : 0;
133         frayREG->FRF_UN.FRF_ST.fid_B11 = frame_id;
134         frayREG->FRFM_UN.FRFM_ST.mfid_B11 = 0x0;
135         frayREG->FRF_UN.FRF_ST.cyf_B7 = cyc_filter;
136         if (mode&FRAY_BUF_CHB_EN && mode&FRAY_BUF_CHA_EN) {
137                 frayREG->FRF_UN.FRF_ST.ch_B2 = 0;
138         }
139         else if (mode&FRAY_BUF_CHA_EN) {
140                 frayREG->FRF_UN.FRF_ST.ch_B2 = 3;
141         }
142         else {
143                 frayREG->FRF_UN.FRF_ST.ch_B2 = 2;
144         }
145         frame_id = 0;
146         fray_config_buffer(buf_num, mode, cyc_filter, frame_id, payload, data_pointer);
147 }
148
149 /**
150  *  Fill buffer configuration data structure with given data and transfer it to the message RAM header.
151  *  @param[in]  buf_num     number of buffer to be configured (0-128)
152  *  @param[in]  mode        Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
153  *  @param[in]  cyc_filter  Setting for cycle filter. 0 - disabled
154  *  @param[in]  frame_id    Id of the frame to be associated with the buffer
155  *  @param[in]  payload     Maximum data size in half-word
156  *  @param[in]  data_pointer    Address of the first word of data in buffer
157  */
158 void fray_config_buffer(uint32_t buf_num, uint16_t mode, uint32_t cyc_filter, uint32_t frame_id, uint32_t payload, uint32_t data_pointer) {
159     wrhs Fr_LPdu;
160     bc Fr_LSdu;
161     Fr_LPdu.mbi  = (mode&FRAY_BUF_MBI_EN) ? 1 : 0;   // message buffer interrupt
162     Fr_LPdu.txm  = (mode&FRAY_BUF_TX_MODE_CONTINUOUS) ? 0 : 1;   // transmission mode(0=continuous mode, 1=single mode)
163     Fr_LPdu.ppit = (mode&FRAY_BUF_NM_EN) ? 1 : 0;   // network management Enable
164     Fr_LPdu.cfg  = (mode&FRAY_BUF_TX) ? 1 : 0;   // message buffer configuration bit (0=RX, 1 = TX)
165     Fr_LPdu.chb  = (mode&FRAY_BUF_CHB_EN) ? 1 : 0;   // Ch B
166     Fr_LPdu.cha  = (mode&FRAY_BUF_CHA_EN) ? 1 : 0;   // Ch A
167     Fr_LPdu.cyc  = cyc_filter;   // Cycle Filtering Code (no cycle filtering)
168     Fr_LPdu.fid  = frame_id;   // Frame ID
169
170     // Write Header Section 2 (WRHS2)
171     Fr_LPdu.pl   = payload;   // Payload Length
172
173     // Write Header Section 3 (WRHS3)
174     Fr_LPdu.dp   = data_pointer;   // Pointer to start of data in message RAM
175
176     Fr_LPdu.sfi  = (mode&FRAY_BUF_SFI_EN) ? 1 : 0;   // startup frame indicator
177     Fr_LPdu.sync = (mode&FRAY_BUF_SYNC_EN) ? 1 : 0;   // sync frame indicator
178
179     // Write Header Section 2 (WRHS2)
180     Fr_LPdu.crc  = (mode&FRAY_BUF_TX) ? fray_header_crc_calc(&Fr_LPdu) : 0;
181
182     // Input buffer configuration
183     Fr_LSdu.ibrh = buf_num;  // input buffer number
184     Fr_LSdu.ibsyh = 1; // check for input buffer busy host
185     Fr_LSdu.ibsys = 1; // check for input buffer busy shadow
186
187     Fr_LSdu.stxrh= (mode&FRAY_BUF_TXREQ_EN) ? 1 : 0;  // set transmission request
188     Fr_LSdu.ldsh = 0;  // load data section
189     Fr_LSdu.lhsh = 1;  // load header section
190     Fr_LSdu.obrs = 0;  // output buffer number
191     Fr_LSdu.rdss = 0;  // read data section
192     Fr_LSdu.rhss = 0;  // read header section
193
194     fray_prepare_LPdu(&Fr_LPdu);
195     fray_transmit_tx_LPdu(&Fr_LSdu);
196 }
197
198 /**
199  *  Initialize POC. At first go to CONFIG state, then run the unlock sequence
200  *  and at the end go to READY state
201  *  @return SUCCESS or FAILURE
202  */
203 int fray_controler_init() {
204     int result = SUCCESS;
205     // write SUCC1 configuration
206     frayREG->SUCC1_UN.SUCC1_UL = 0x0F1FFB00 | CMD_CONFIG;
207     // Check if POC has accepted last command
208     if ((frayREG->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
209     // Wait for PBSY bit to clear - POC not busy
210     fray_wait_for_POC_ready();
211
212     // unlock CONFIG and enter READY state
213     frayREG->LCK_UN.LCK_ST.clk_B8=0xCE;
214     frayREG->LCK_UN.LCK_ST.clk_B8=0x31;
215     // write SUCC1 configuration
216     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4=(0xFB00 | CMD_READY);
217     // Check if POC has accepted last command
218     if ((frayREG->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) {
219         result = FAILURE;
220     }
221     // Wait for PBSY bit to clear - POC not busy
222     fray_wait_for_POC_ready();
223     return result;
224 }
225
226 /**
227  *  Enable IRQ on int1
228  *  Enable CYCSE interrupt
229  *  Clear Errors and statuses
230  */
231 void fray_init_irq() {
232     frayREG->EIR_UN.EIR_UL       = 0xFFFFFFFF; // Clear Error Int.
233     frayREG->SIR_UN.SIR_UL       = 0xFFFFFFFF; // Clear Status Int.
234     frayREG->SILS_UN.SILS_UL     = 0x00000000; // all Status Int. to eray_int0
235     frayREG->SIER_UN.SIER_UL     = 0xFFFFFFFF; // Disable all Status Int.
236     frayREG->SIES_UN.SIES_UL     = 0x00000004; // Enable CYCSE Int.
237     frayREG->ILE_UN.ILE_UL       = 0x00000002; // enable eray_int1
238 }
239
240 /**
241  *  Load data to message buffer.
242  *  @param[in]  buf_num     Number of buffer
243  *  @param[in]  data        Pointer to data array
244  *  @param[in]  len         Number of words to be loaded from data to buffer
245  */
246 void fray_buffer_set_data(uint32_t buf_num, const uint32_t* data, uint32_t len) {
247     bc write_buffer;
248     uint32_t i;
249
250     write_buffer.ibrh = buf_num;  // input buffer number
251     write_buffer.stxrh= 1;  // set transmission request
252     write_buffer.ldsh = 1;  // load data section
253     write_buffer.lhsh = 0;  // load header section
254     write_buffer.ibsys = 0; // check for input buffer busy shadow
255     write_buffer.ibsyh = 1; // check for input buffer busy host
256     for (i = 0; i < len; i++) {
257         frayREG->WRDS[i] = data[i];
258     }
259     fray_transmit_tx_LPdu(&write_buffer);
260 }
261
262 /**
263  *  Load data to message buffer. Data must be copied into WRDS register before thic function is called.
264  *  @param[in]  buf_num     Number of buffer
265  *  @param[in]  len         Number of words to be loaded from data to buffer
266  */
267 void fray_buffer_transmit_data(uint32_t buf_num) {
268     bc write_buffer;
269
270     write_buffer.ibrh = buf_num;  // input buffer number
271     write_buffer.stxrh= 1;  // set transmission request
272     write_buffer.ldsh = 1;  // load data section
273     write_buffer.lhsh = 0;  // load header section
274     write_buffer.ibsys = 0; // check for input buffer busy shadow
275     write_buffer.ibsyh = 1; // check for input buffer busy host
276     fray_transmit_tx_LPdu(&write_buffer);
277 }
278
279
280 /**
281  *  Retrieve data from message buffer.
282  *  @param[in]  buf_num     Number of buffer
283  *  @param[out] data        Pointer to array, where retrieved data will be stored.
284  *  @param[in]  len         Number of words to be loaded from data to buffer
285  */
286 void fray_buffer_get_data(uint32_t buf_num, uint32_t* data, uint32_t len) {
287     bc read_buffer;
288     uint32_t i;
289
290     read_buffer.obrs=buf_num;  // output buffer number
291     read_buffer.rdss=1;  // read data section
292     read_buffer.rhss=0;  // read header section
293     fray_receive_rx_LPdu(&read_buffer);
294     for (i = 0; i < len; i++) {
295         data[i] = frayREG->RDDS[i];
296     }
297 }
298
299 /**
300  *  Retrieve data and header from message buffer into output buffer.
301  *
302  *  Upper software layers have to read the header and data from RDDS and RDHS registers.
303  *  @param[in]  buf_num     Number of buffer
304  */
305 void fray_buffer_receive_data_header(uint32_t buf_num) {
306     bc read_buffer;
307
308     read_buffer.obrs=buf_num;  // output buffer number
309     read_buffer.rdss=1;  // read data section
310     read_buffer.rhss=1;  // read header section
311     fray_receive_rx_LPdu(&read_buffer);
312 }
313
314
315 /**
316  *  Wait for interrupt flag, that new communication cycle started
317  *  Clears status flags
318  */
319 void fray_wait_for_new_cycle() {
320     frayREG->SIR_UN.SIR_UL = 0xFFFFFFFF;            // clear all status int. flags
321     while ((frayREG->SIR_UN.SIR_UL & 0x4) == 0x0);    // wait for CYCS interrupt flag
322     frayREG->SIR_UN.SIR_UL = 0xFFFFFFFF;            // clear all status int. flags
323 }
324
325 /**
326  *  Check if some new message was received to the message buffer.
327  *  @param[in]  buf_num     Number of the buffer to be checked
328  *  @return 1 when new message is available, otherwise 0
329  */
330 int fray_buffer_message_received(uint32_t buf_num) {
331     uint32_t ndat;
332     uint32_t offset = 0;
333     if (buf_num < 32) {
334         ndat = frayREG->NDAT1_UN.NDAT1_UL;
335         offset = buf_num;
336     }
337     else if (buf_num < 64) {
338         ndat = frayREG->NDAT2_UN.NDAT2_UL;
339         offset = buf_num - 32;
340     }
341     else if (buf_num < 96) {
342         ndat = frayREG->NDAT3_UN.NDAT3_UL;
343         offset = buf_num - 64;
344     }
345     else if (buf_num < 128) {
346         ndat = frayREG->NDAT4_UN.NDAT4_UL;
347         offset = buf_num - 96;
348     }
349     else {
350         return -1;
351     }
352
353     return (ndat&(1<<offset));
354 }
355
356 /**
357  *  Process the FlexRay startup procedure according diagrams in FlexRay protocol specification.
358  *  @param[in]  is_coldstar     Specifies if node is coldstart or if it can be just integrated to existing network
359  *  @return     SUCCESS or error code
360  */
361 int fray_startup_procedure(int is_coldstart) {
362     uint32_t counter;
363     uint32_t state_value;
364     uint32_t csa;
365     int ok = SUCCESS;
366
367     ok = fray_go_to_ready_state_from_config_state();
368     if(ok == FAILURE) {
369         return FRAY_ERR_SW_CFG_READY;   // Switching to ready state error
370     }
371     else {
372         // Cold start branch
373         if (is_coldstart){
374             // Start up loop
375             while(1) {
376                 counter = 0;
377                 // try as following cold starter
378                 ok = fray_go_to_startup_state();
379                 if(ok == FAILURE){
380                     return FRAY_ERR_SW_STUP_FOLLOW; // Switch to run error
381                 }
382                 // Wait until NORMAL_ACTIVE state or timeout
383                 do {
384                     state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
385                     counter++;
386                 } while ((state_value != 0x02) && (counter < 10000000U));
387
388                 // No success in integration
389                 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == 0x27){
390                     csa = frayREG->CCSV_UN.CCSV_ST.rca_B5;
391                     // Some cold starts attempts remains
392                     if (csa != 0){
393                         // Try allow cold start
394                         ok = fray_allow_coldstart();
395                         if(ok == FAILURE){
396                             return FRAY_ERR_CSINH_DIS;  // Cold start inhibit disabled error
397                         }
398                     }
399                 }
400
401                 // Wait until NORMAL_ACTIVE or INTEGRATION_LISTEN state
402                 do {
403                     state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
404                 } while ( (state_value != 0x02) && (state_value != 0x27));
405
406                 // Success, break the start up loop
407                 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == 0x02)
408                     break;
409
410                 // No success. Switch back to READY state
411                 fray_delay();
412                 ok = fray_go_to_ready_state_from_startup_state();
413                 if (ok == FAILURE) {
414                     return FRAY_ERR_SW_STUP_READY;  // Switch to READY failed
415                 }
416             }
417         }
418         // Non-cold start branch
419         else {
420             ok = fray_go_to_startup_state();
421             if(ok == FAILURE)  {
422                 return FRAY_ERR_SW_STUP_AS_NCOLD; // Switching to startup state as non-cold start node
423             }
424             else {
425                 // Wait until NORMAL_ACTIVE
426                 do {
427                     state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
428                 } while (state_value != 0x02);
429             }
430         }
431     }
432     if (ok != SUCCESS)
433         return FAILURE;
434     return SUCCESS;
435 }
436
437 /** @fn go_to_ready_state_from_config_state(void)
438 *   @brief Set POC command
439 *
440 *   Send command to POC to switch into READY state.
441 *   @return SUCCESS or FAILURE
442 */
443 int fray_go_to_ready_state_from_config_state(void) {
444     fray_wait_for_POC_ready();
445
446     if (frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 && frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
447         //odemykaci sekvence
448         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
449         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
450         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
451         //odemykaci sekvence
452         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
453         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
454         frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
455         //odemykaci sekvence
456         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
457         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
458         frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
459     }
460     else if(frayREG->SUCC1_UN.SUCC1_ST.ccha_B1){
461         //odemykaci sekvence
462         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
463         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
464         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
465         //odemykaci sekvence
466         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
467         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
468         frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
469     }
470     else if (frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
471         //odemykaci sekvence
472         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
473         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
474         frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
475         //odemykaci sekvence
476         frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
477         frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
478         frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
479     }
480     else frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
481
482     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
483         return (FAILURE);
484     while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01)
485             ; //cekam dokud POC neni v ready stavu
486     return (SUCCESS);
487 }
488
489 /** @fn go_to_ready_state_from_startup_state(void)
490 *   @brief Set POC command
491 *
492 *   Send command to POC to switch into READY state.
493 *   @return SUCCESS or FAILURE
494 */
495 int fray_go_to_ready_state_from_startup_state(void){
496     fray_wait_for_POC_ready();
497     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
498     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) return (FAILURE);
499     while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01); //cekam dokud POC neni v ready stavu
500     return (SUCCESS);
501 }
502
503 /** @fn go_to_startup_state(void)
504 *   @brief Set POC command
505 *
506 *   Send command to POC to switch into RUN state.
507 *   @return SUCCESS or FAILURE
508 */
509 int fray_go_to_startup_state(void) {
510     fray_wait_for_POC_ready();
511     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_RUN;
512     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
513         return (FAILURE);
514     return (SUCCESS);
515 }
516
517 /** @fn allow_coldstart(void)
518 *   @brief Allows cold start
519 *
520 *   Send command to erase coldstart inhibit flag.
521 *   This allows the node to start as coldstart node.
522 *   @return SUCCESS or FAILURE
523 */
524 int fray_allow_coldstart(void) {
525     fray_wait_for_POC_ready();
526     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_ALLOW_COLDSTART;
527     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
528         return (FAILURE);
529     return (SUCCESS);
530 }
531
532 /**
533  *  FlexRay delay used while network initiation.
534  *
535  *  !This is busy waiting!
536  */
537 void fray_delay(void) {
538     volatile uint32_t delayval;
539
540     delayval = 375000;   // 100000 are about 10ms
541     while(delayval-- > 0 )
542         ;
543 }
544
545 /** @fn send_halt_command
546 *   @brief Send HALT command
547 *
548 *   Send command to the node to stop its activity after the end of
549 *   actual cycle.
550 *   @return SUCCESS or FAILURE
551 */
552 int fray_halt(void) {
553     fray_wait_for_POC_ready();
554     frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = 6U;
555     if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
556         return (FAILURE);
557     return (SUCCESS);
558 }
559
560 /**
561  *  Compute CRC for message RAM header data
562  *  @param[in] Fr_LPduPtr   Pointer to header data
563  *  @return CRC code
564  */
565 int fray_header_crc_calc(const wrhs *Fr_LPduPtr) {
566   unsigned int header;
567
568   int CrcInit = 0x1A;
569   int length  = 20;
570   int CrcNext;
571   unsigned long CrcPoly  = 0x385;
572   unsigned long CrcReg_X = CrcInit;
573   unsigned long header_temp, reg_temp;
574
575   header  = ((Fr_LPduPtr->sync & 0x1)  << 19) | ((Fr_LPduPtr->sfi & 0x1) << 18);
576   header |= ((Fr_LPduPtr->fid & 0x7FF) <<  7) |  (Fr_LPduPtr->pl & 0x7F);
577
578   header   <<= 11;
579   CrcReg_X <<= 21;
580   CrcPoly  <<= 21;
581
582   while(length--) {
583     header    <<= 1;
584     header_temp = header & 0x80000000;
585     reg_temp    = CrcReg_X & 0x80000000;
586
587     if(header_temp ^ reg_temp){  // Step 1
588       CrcNext = 1;
589     } else {
590       CrcNext = 0;
591     }
592
593     CrcReg_X <<= 1;              // Step 2
594
595     if(CrcNext) {
596       CrcReg_X ^= CrcPoly;       // Step 3
597     }
598   }
599
600   CrcReg_X >>= 21;
601
602   return CrcReg_X;
603 }
604
605 /**
606  *  Prepare data to be transmitted to message RAM by input buffer,
607  *  @param[in]  Fr_LPduPtr  Pointer to data structure to be send
608  */
609 void fray_prepare_LPdu(const wrhs *Fr_LPduPtr) {
610     int wrhs1;
611     int wrhs2;
612     wrhs1  = ((Fr_LPduPtr->mbi) & 0x1)  <<29;
613     wrhs1 |= (Fr_LPduPtr->txm & 0x1)  << 28;
614     wrhs1 |= (Fr_LPduPtr->ppit & 0x1) << 27;
615     wrhs1 |= (Fr_LPduPtr->cfg & 0x1)  << 26;
616     wrhs1 |= (Fr_LPduPtr->chb & 0x1)  << 25;
617     wrhs1 |= (Fr_LPduPtr->cha & 0x1)  << 24;
618     wrhs1 |= (Fr_LPduPtr->cyc & 0x7F) << 16;
619     wrhs1 |= (Fr_LPduPtr->fid & 0x7FF);
620     frayREG->WRHS1_UN.WRHS1_UL = wrhs1;
621
622     wrhs2  = ((Fr_LPduPtr->pl & 0x7F) << 16) | (Fr_LPduPtr->crc & 0x7FF);
623     frayREG->WRHS2_UN.WRHS2_UL = wrhs2;
624
625     frayREG->WRHS3_UN.WRHS3_UL = (Fr_LPduPtr->dp & 0x7FF);
626 }
627
628 /**
629  *  Transfer data from input buffer to message RAM
630  *  @param[in] Fr_LSduPtr   Pointer to data structure with input buffer settings
631  */
632 void fray_transmit_tx_LPdu(const bc *Fr_LSduPtr) {
633     // ensure nothing is pending
634     while ((frayREG->IBCR_UN.IBCR_UL & 0x0008000) != 0);
635     frayREG->IBCM_UN.IBCM_UL=((Fr_LSduPtr->stxrh & 0x1) << 2) | ((Fr_LSduPtr->ldsh & 0x1) << 1) | (Fr_LSduPtr->lhsh & 0x1);
636     frayREG->IBCR_UN.IBCR_UL=(Fr_LSduPtr->ibrh & 0x3F);
637     // optimization possible for future by not gating like below
638     // wait for completion on host registers
639     while ((Fr_LSduPtr->ibsyh != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x00008000) != 0));
640     // wait for completion on shadow registers
641     while ((Fr_LSduPtr->ibsys != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x80000000) != 0));
642 }
643
644 /**
645  *  Receive data from message buffer into output buffer.
646  *  @param[in]  Fr_LSduPtr  Pointer to data structure with output buffer settings
647  */
648 void fray_receive_rx_LPdu(const bc *Fr_LSduPtr) {
649     // ensure no transfer in progress on shadow registers
650     while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
651     frayREG->OBCM_UN.OBCM_UL=(((Fr_LSduPtr->rdss & 0x1) << 1) | (Fr_LSduPtr->rhss & 0x1));
652     frayREG->OBCR_UN.OBCR_UL=((1 << 9) | (Fr_LSduPtr->obrs & 0x3F)); //req=1, view=0
653     // wait for completion on shadow registers
654     while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
655
656     frayREG->OBCM_UN.OBCM_UL=(((Fr_LSduPtr->rdss & 0x1) << 1) | (Fr_LSduPtr->rhss & 0x1));
657     frayREG->OBCR_UN.OBCR_UL=((1 << 8) | (Fr_LSduPtr->obrs & 0x3F)); //req=0, view=1
658 }