4 * Created on: 12.2.2013
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.
13 //#include "drv_fray.h"
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 };
26 * @brief Function sends prepared command on SPI and stores response
28 * @param[in] port Index of flexray 0 or 1
29 * @return 0 when success, -1 when bad parameter
31 int fray_spi_transfer(uint8_t port) {
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);
41 fray_spi_resp[port] = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
46 * @brief Returns last spi response of selected fray port
48 * @param[in] port Index of flexray 0 or 1
49 * @return spi response or -1 when bad parameter
51 int fray_spi_response(uint8_t port) {
52 if (port > FRAY_NUM_PORTS) return -1;
53 return fray_spi_resp[port];
57 * @brief Returns last spi command of selected fray port
59 * @param[in] port Index of flexray 0 or 1
60 * @return spi command or -1 when bad parameter
62 int fray_spi_get_cmd(uint8_t port) {
63 if (port > FRAY_NUM_PORTS) return -1;
67 /** @fn clear_msg_ram(void)
68 * @brief Clears FRAY message RAMs
70 * Send command to POC to set all bits of message RAM to 0.
71 * @return SUCCESS or FAILURE when command was not accepted
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) {
79 fray_wait_for_POC_ready();
83 /** @fn wait_for_POC_ready(void)
84 * @brief Wait until POC is not busy
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);
92 /** @fn fray_init(cfg *Fr_ConfigPtr)
93 * @brief Set global configuration
95 * Copy configuration filled in structure into config registers
96 * @param Fr_ConfigPtr Pointer to structure with configuration
98 void fray_init(const cfg *Fr_ConfigPtr)
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;
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
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;
139 else if (mode&FRAY_BUF_CHA_EN) {
140 frayREG->FRF_UN.FRF_ST.ch_B2 = 3;
143 frayREG->FRF_UN.FRF_ST.ch_B2 = 2;
146 fray_config_buffer(buf_num, mode, cyc_filter, frame_id, payload, data_pointer);
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
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) {
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
170 // Write Header Section 2 (WRHS2)
171 Fr_LPdu.pl = payload; // Payload Length
173 // Write Header Section 3 (WRHS3)
174 Fr_LPdu.dp = data_pointer; // Pointer to start of data in message RAM
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
179 // Write Header Section 2 (WRHS2)
180 Fr_LPdu.crc = (mode&FRAY_BUF_TX) ? fray_header_crc_calc(&Fr_LPdu) : 0;
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
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
194 fray_prepare_LPdu(&Fr_LPdu);
195 fray_transmit_tx_LPdu(&Fr_LSdu);
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
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();
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) {
221 // Wait for PBSY bit to clear - POC not busy
222 fray_wait_for_POC_ready();
228 * Enable CYCSE interrupt
229 * Clear Errors and statuses
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
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
246 void fray_buffer_set_data(uint32_t buf_num, const uint32_t* data, uint32_t len) {
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];
259 fray_transmit_tx_LPdu(&write_buffer);
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
267 void fray_buffer_transmit_data(uint32_t buf_num) {
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);
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
286 void fray_buffer_get_data(uint32_t buf_num, uint32_t* data, uint32_t len) {
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];
300 * Retrieve data and header from message buffer into output buffer.
302 * Upper software layers have to read the header and data from RDDS and RDHS registers.
303 * @param[in] buf_num Number of buffer
305 void fray_buffer_receive_data_header(uint32_t buf_num) {
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);
316 * Wait for interrupt flag, that new communication cycle started
317 * Clears status flags
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
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
330 int fray_buffer_message_received(uint32_t buf_num) {
334 ndat = frayREG->NDAT1_UN.NDAT1_UL;
337 else if (buf_num < 64) {
338 ndat = frayREG->NDAT2_UN.NDAT2_UL;
339 offset = buf_num - 32;
341 else if (buf_num < 96) {
342 ndat = frayREG->NDAT3_UN.NDAT3_UL;
343 offset = buf_num - 64;
345 else if (buf_num < 128) {
346 ndat = frayREG->NDAT4_UN.NDAT4_UL;
347 offset = buf_num - 96;
353 return (ndat&(1<<offset));
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
361 int fray_startup_procedure(int is_coldstart) {
363 uint32_t state_value;
367 ok = fray_go_to_ready_state_from_config_state();
369 return FRAY_ERR_SW_CFG_READY; // Switching to ready state error
377 // try as following cold starter
378 ok = fray_go_to_startup_state();
380 return FRAY_ERR_SW_STUP_FOLLOW; // Switch to run error
382 // Wait until NORMAL_ACTIVE state or timeout
384 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
386 } while ((state_value != 0x02) && (counter < 10000000U));
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
393 // Try allow cold start
394 ok = fray_allow_coldstart();
396 return FRAY_ERR_CSINH_DIS; // Cold start inhibit disabled error
401 // Wait until NORMAL_ACTIVE or INTEGRATION_LISTEN state
403 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
404 } while ( (state_value != 0x02) && (state_value != 0x27));
406 // Success, break the start up loop
407 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == 0x02)
410 // No success. Switch back to READY state
412 ok = fray_go_to_ready_state_from_startup_state();
414 return FRAY_ERR_SW_STUP_READY; // Switch to READY failed
418 // Non-cold start branch
420 ok = fray_go_to_startup_state();
422 return FRAY_ERR_SW_STUP_AS_NCOLD; // Switching to startup state as non-cold start node
425 // Wait until NORMAL_ACTIVE
427 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
428 } while (state_value != 0x02);
437 /** @fn go_to_ready_state_from_config_state(void)
438 * @brief Set POC command
440 * Send command to POC to switch into READY state.
441 * @return SUCCESS or FAILURE
443 int fray_go_to_ready_state_from_config_state(void) {
444 fray_wait_for_POC_ready();
446 if (frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 && frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
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;
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;
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;
460 else if(frayREG->SUCC1_UN.SUCC1_ST.ccha_B1){
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;
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;
470 else if (frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
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;
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;
480 else frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
482 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
484 while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01)
485 ; //cekam dokud POC neni v ready stavu
489 /** @fn go_to_ready_state_from_startup_state(void)
490 * @brief Set POC command
492 * Send command to POC to switch into READY state.
493 * @return SUCCESS or FAILURE
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
503 /** @fn go_to_startup_state(void)
504 * @brief Set POC command
506 * Send command to POC to switch into RUN state.
507 * @return SUCCESS or FAILURE
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)
517 /** @fn allow_coldstart(void)
518 * @brief Allows cold start
520 * Send command to erase coldstart inhibit flag.
521 * This allows the node to start as coldstart node.
522 * @return SUCCESS or FAILURE
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)
533 * FlexRay delay used while network initiation.
535 * !This is busy waiting!
537 void fray_delay(void) {
538 volatile uint32_t delayval;
540 delayval = 375000; // 100000 are about 10ms
541 while(delayval-- > 0 )
545 /** @fn send_halt_command
546 * @brief Send HALT command
548 * Send command to the node to stop its activity after the end of
550 * @return SUCCESS or FAILURE
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)
561 * Compute CRC for message RAM header data
562 * @param[in] Fr_LPduPtr Pointer to header data
565 int fray_header_crc_calc(const wrhs *Fr_LPduPtr) {
571 unsigned long CrcPoly = 0x385;
572 unsigned long CrcReg_X = CrcInit;
573 unsigned long header_temp, reg_temp;
575 header = ((Fr_LPduPtr->sync & 0x1) << 19) | ((Fr_LPduPtr->sfi & 0x1) << 18);
576 header |= ((Fr_LPduPtr->fid & 0x7FF) << 7) | (Fr_LPduPtr->pl & 0x7F);
584 header_temp = header & 0x80000000;
585 reg_temp = CrcReg_X & 0x80000000;
587 if(header_temp ^ reg_temp){ // Step 1
593 CrcReg_X <<= 1; // Step 2
596 CrcReg_X ^= CrcPoly; // Step 3
606 * Prepare data to be transmitted to message RAM by input buffer,
607 * @param[in] Fr_LPduPtr Pointer to data structure to be send
609 void fray_prepare_LPdu(const wrhs *Fr_LPduPtr) {
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;
622 wrhs2 = ((Fr_LPduPtr->pl & 0x7F) << 16) | (Fr_LPduPtr->crc & 0x7FF);
623 frayREG->WRHS2_UN.WRHS2_UL = wrhs2;
625 frayREG->WRHS3_UN.WRHS3_UL = (Fr_LPduPtr->dp & 0x7FF);
629 * Transfer data from input buffer to message RAM
630 * @param[in] Fr_LSduPtr Pointer to data structure with input buffer settings
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));
645 * Receive data from message buffer into output buffer.
646 * @param[in] Fr_LSduPtr Pointer to data structure with output buffer settings
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);
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