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