2 * FlexRay Communication driver for TMS570 source file.
6 * @copyright Copyright (C) 2013 Czech Technical University in Prague
8 * @author Michal Horn <hornmich@fel.cvut.cz>
11 #include "drv/fr_tms570.h"
12 #include "sys/ti_drv_fray.h"
14 #include "hal/port_def.h"
17 * The structure maps a RX/TX buffer to a slot in the communication cycle.
19 typedef struct Fr_slot_buffer_map_st {
20 const Fr_TMS570LS_BufferConfigType* buffer_ptr; /**< Address of a buffer configuration assigned to the slot slot_id */
21 uint16_t slot_id; /**< An ID of the slot in the communication cycle. The value may not be equal to the slot_id value in the buffer configuration, after reconfiguration is done. */
22 } Fr_slot_buffer_map_t;
24 static Std_VersionInfoType Fr_versionInfo = {
25 .vendorID = 0x00000001,
26 .moduleID = 0x00000002,
27 .sw_major_version = 0,
28 .sw_minor_version = 1,
32 /** Prepared spi command */
33 static uint32_t fray_spi_cmd = FRAY_SPICMD_INIT_VAL;
34 /** Shadow variable used during command sending */
35 static uint32_t fray_spi_cmd_sh;
36 /** Array of responses for each fray driver */
37 static uint32_t fray_spi_resp[FRAY_NUM_PORTS];
38 /** Array of port names to be easily accessible by indexing */
39 static const char* fray_port_names[FRAY_NUM_PORTS] = { PORT_NAME_FRAY1, PORT_NAME_FRAY2 };
40 /** Array of integers, where FlexRay cluster and node configuration
41 * parameters are stored to be accessible by indexes defined in Fr_GeneralTypes.h.
43 static uint32_t Fr_ConfigParPtrs[FR_CIDX_CNT];
45 * Address of the unified structure with complete configuration of
46 * the FlexRay node (cluster, node, message RAM and buffer configuration)
48 static const Fr_ConfigType* Fr_Config;
49 /** Map of the buffers to their slot ID */
50 static Fr_slot_buffer_map_t Fr_buffer_slot_map[FR_MAX_BUFFERS_CNT];
51 /** Array of flags to determine if the buffer was or was not configured. */
52 static boolean_t Fr_BuffersConfigured[FR_MAX_BUFFERS_CNT];
53 /** Array of computed data pointers addresses for each buffer. */
54 static int Fr_MsgRAMDataPtrs[FR_MAX_BUFFERS_CNT];
56 * Address of the next free position in message RAM, which can be assigned
57 * to configured buffer. Addresses 32b words.
59 static uint32_t Fr_MsgRAMDataOffset;
61 * Address of the first free position in message RAM, which can be assigned
62 * to the first configured buffer. Addresses 32b words.
64 static uint32_t Fr_MsgRAMDataStartAddress;
67 * Development error detection.
68 * Comment this line to disable error detection and make function processing
69 * faster, but more dangerous.
77 * A variable for driver state monitoring. The state value is used in several
78 * functions to determine if they are called in right order.
80 static Fr_TMS570LS_DriverState Fr_DrvState = FR_ST_DRV_NOT_INITIALIZED;
85 * Create flags according to the index of the buffer, its configuration and node configuration.
86 * Flags created by this function are used in buffer configuration and reconfiguration functions.
88 * @param[in] buffer_cfg_ptr Address of the buffer configuration parameters
89 * @param[in] index of the buffer to which belong the parameters
91 * @return Buffer configuration flags. Their definition can be found in fr_tms570.h file as macros with prefixes FRAY_BUF_
93 uint32_t Fr_buffer_config_flags(const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr, uint8_t bufferIndex) {
96 mode = (buffer_cfg_ptr->msgBufferInterrupt == TRUE) ? FRAY_BUF_MBI_EN : FRAY_BUF_MBI_DIS;
97 mode |= (buffer_cfg_ptr->singleTransmit == TRUE) ? FRAY_BUF_TX_MODE_SINGLE : FRAY_BUF_TX_MODE_CONTINUOUS;
98 mode |= (buffer_cfg_ptr->payloadPreambleIndicatorTr == TRUE) ? FRAY_BUF_NM_EN : FRAY_BUF_NM_DIS;
99 mode |= (buffer_cfg_ptr->isTx == TRUE) ? FRAY_BUF_TX : FRAY_BUF_RX;
100 mode |= (buffer_cfg_ptr->channel == FR_CHANNEL_A || buffer_cfg_ptr->channel == FR_CHANNEL_AB) ? FRAY_BUF_CHA_EN : FRAY_BUF_CHA_DIS;
101 mode |= (buffer_cfg_ptr->channel == FR_CHANNEL_B || buffer_cfg_ptr->channel == FR_CHANNEL_AB) ? FRAY_BUF_CHB_EN : FRAY_BUF_CHB_DIS;
102 mode |= (buffer_cfg_ptr->rejectNullFrames == TRUE) ? FRAY_BUF_REJECT_NULL_FRAMES : FRAY_BUF_ACCEPT_NULL_FRAMES;
103 mode |= (buffer_cfg_ptr->rejectStaticSegment == TRUE) ? FRAY_BUF_REJECT_STATIC_SEGMENT : FRAY_BUF_ACCEPT_STATIC_SEGMENT;
104 mode |= FRAY_BUF_TXREQ_DIS;
105 if (bufferIndex == 0 || (bufferIndex == 1 && Fr_Config->msgRAMConfig->syncFramePayloadMultiplexEnabled == TRUE)) { // Buffer 0 is always a key slot, if payload multiplexing is enabled, then buffer 1 serves for key slot as well.
106 if (Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSTARTUP] == 1) {
107 mode |= FRAY_BUF_SFI_EN;
109 if (Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSYNC] == 1) {
110 mode |= FRAY_BUF_SYNC_EN;
117 * Buffer is reconfigurable if it is not assigned to the key slot (slot for
118 * synchronization and startup) and reconfiguration is enabled in ode configuration
120 * RX FIFO buffer is never configurable.
122 * @return -1 if buffer reconfiguration is prohibited, otherwise returns index of the first buffer, which is reconfigurable.
124 int Fr_reconfigurable_buffer_index() {
125 int lowest_index = -1;
126 if (Fr_Config->msgRAMConfig->secureBuffers == FR_SB_STAT_REC_DISABLED_STAT_TR_DISABLED)
127 lowest_index = frayREG->MRC_UN.MRC_ST.fdb_B8;
128 else if (Fr_Config->msgRAMConfig->secureBuffers == FR_SB_RECONFIG_ENABLED) {
129 if (Fr_Config->nodeConfiguration->pKeySlotUsedForSync == TRUE ||
130 Fr_Config->nodeConfiguration->pSingleSlotEnabled == TRUE
132 if (Fr_Config->msgRAMConfig->syncFramePayloadMultiplexEnabled)
147 * Compute CRC for message RAM header data
149 * @param[in] Fr_LPduPtr Pointer to header data
152 static int Fr_header_crc_calc(const wrhs *Fr_LPduPtr) {
158 unsigned long CrcPoly = 0x385;
159 unsigned long CrcReg_X = CrcInit;
160 unsigned long header_temp, reg_temp;
162 header = ((Fr_LPduPtr->sync & 0x1) << 19) | ((Fr_LPduPtr->sfi & 0x1) << 18);
163 header |= ((Fr_LPduPtr->fid & 0x7FF) << 7) | (Fr_LPduPtr->pl & 0x7F);
171 header_temp = header & 0x80000000;
172 reg_temp = CrcReg_X & 0x80000000;
174 if(header_temp ^ reg_temp){ // Step 1
180 CrcReg_X <<= 1; // Step 2
183 CrcReg_X ^= CrcPoly; // Step 3
193 * Retrieve data and header from message buffer into output buffer.
195 * Upper software layers have to read the header and data from RDDS and RDHS registers.
196 * @param[in] buf_num Number of buffer
198 static void Fr_buffer_receive_data_header(uint32_t buf_num) {
201 read_buffer.obrs=buf_num; // output buffer number
202 read_buffer.rdss=1; // read data section
203 read_buffer.rhss=1; // read header section
205 // ensure no transfer in progress on shadow registers
206 while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
207 frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
208 frayREG->OBCR_UN.OBCR_UL=((1 << 9) | (read_buffer.obrs & 0x3F)); //req=1, view=0
209 // wait for completion on shadow registers
210 while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
212 frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
213 frayREG->OBCR_UN.OBCR_UL=((1 << 8) | (read_buffer.obrs & 0x3F)); //req=0, view=1
218 * Transfer data to the message RAM using the input buffer
220 * @param[in] Fr_LSduPtr Pointer to data structure with input buffer settings
222 inline void Fr_transmit_tx_LPdu(const bc *Fr_LSduPtr) {
223 // ensure nothing is pending
224 while ((frayREG->IBCR_UN.IBCR_UL & 0x0008000) != 0);
225 frayREG->IBCM_UN.IBCM_UL=((Fr_LSduPtr->stxrh & 0x1) << 2) | ((Fr_LSduPtr->ldsh & 0x1) << 1) | (Fr_LSduPtr->lhsh & 0x1);
226 frayREG->IBCR_UN.IBCR_UL=(Fr_LSduPtr->ibrh & 0x3F);
227 // optimization possible for future by not gating like below
228 // wait for completion on host registers
229 while ((Fr_LSduPtr->ibsyh != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x00008000) != 0));
230 // wait for completion on shadow registers
231 while ((Fr_LSduPtr->ibsys != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x80000000) != 0));
235 * Fill the buffer configuration data structure with given data and transfer it to the message RAM header using the input buffer.
237 * @param[in] buf_num number of buffer to be configured (0-128)
238 * @param[in] mode Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
239 * @param[in] cyc_filter Setting for cycle filter. 0 - disabled
240 * @param[in] frame_id Id of the frame to be associated with the buffer
241 * @param[in] payload Maximum data size in half-word
242 * @param[in] data_pointer Address of the first word of data in buffer
244 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) {
250 Fr_LPdu.mbi = (mode&FRAY_BUF_MBI_EN) ? 1 : 0; // message buffer interrupt
251 Fr_LPdu.txm = (mode&FRAY_BUF_TX_MODE_CONTINUOUS) ? 0 : 1; // transmission mode(0=continuous mode, 1=single mode)
252 Fr_LPdu.ppit = (mode&FRAY_BUF_NM_EN) ? 1 : 0; // network management Enable
253 Fr_LPdu.cfg = (mode&FRAY_BUF_TX) ? 1 : 0; // message buffer configuration bit (0=RX, 1 = TX)
254 Fr_LPdu.chb = (mode&FRAY_BUF_CHB_EN) ? 1 : 0; // Ch B
255 Fr_LPdu.cha = (mode&FRAY_BUF_CHA_EN) ? 1 : 0; // Ch A
256 Fr_LPdu.cyc = cyc_filter; // Cycle Filtering Code (no cycle filtering)
257 Fr_LPdu.fid = frame_id; // Frame ID
259 // Write Header Section 2 (WRHS2)
260 Fr_LPdu.pl = payload; // Payload Length
262 // Write Header Section 3 (WRHS3)
263 Fr_LPdu.dp = data_pointer; // Pointer to start of data in message RAM
265 Fr_LPdu.sfi = (mode&FRAY_BUF_SFI_EN) ? 1 : 0; // startup frame indicator
266 Fr_LPdu.sync = (mode&FRAY_BUF_SYNC_EN) ? 1 : 0; // sync frame indicator
268 // Write Header Section 2 (WRHS2)
269 Fr_LPdu.crc = (mode&FRAY_BUF_TX) ? Fr_header_crc_calc(&Fr_LPdu) : 0;
271 // Input buffer configuration
272 Fr_LSdu.ibrh = buf_num; // input buffer number
273 Fr_LSdu.ibsyh = 1; // check for input buffer busy host
274 Fr_LSdu.ibsys = 1; // check for input buffer busy shadow
276 Fr_LSdu.stxrh= (mode&FRAY_BUF_TXREQ_EN) ? 1 : 0; // set transmission request
277 Fr_LSdu.ldsh = 0; // load data section
278 Fr_LSdu.lhsh = 1; // load header section
279 Fr_LSdu.obrs = 0; // output buffer number
280 Fr_LSdu.rdss = 0; // read data section
281 Fr_LSdu.rhss = 0; // read header section
283 wrhs1 = ((Fr_LPdu.mbi) & 0x1) <<29;
284 wrhs1 |= (Fr_LPdu.txm & 0x1) << 28;
285 wrhs1 |= (Fr_LPdu.ppit & 0x1) << 27;
286 wrhs1 |= (Fr_LPdu.cfg & 0x1) << 26;
287 wrhs1 |= (Fr_LPdu.chb & 0x1) << 25;
288 wrhs1 |= (Fr_LPdu.cha & 0x1) << 24;
289 wrhs1 |= (Fr_LPdu.cyc & 0x7F) << 16;
290 wrhs1 |= (Fr_LPdu.fid & 0x7FF);
291 frayREG->WRHS1_UN.WRHS1_UL = wrhs1;
293 wrhs2 = ((Fr_LPdu.pl & 0x7F) << 16) | (Fr_LPdu.crc & 0x7FF);
294 frayREG->WRHS2_UN.WRHS2_UL = wrhs2;
296 frayREG->WRHS3_UN.WRHS3_UL = (Fr_LPdu.dp & 0x7FF);
298 Fr_transmit_tx_LPdu(&Fr_LSdu);
302 * Fill FIFO filter rejection configuration and configure the buffer.
304 * @param[in] buf_num number of buffer to be configured (0-128)
305 * @param[in] mode Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
306 * @param[in] cyc_filter Setting for cycle filter. 0 - disabled
307 * @param[in] frame_id Id of the frame to be associated with the buffer
308 * @param[in] payload Maximum data size in half-word
309 * @param[in] data_pointer Address of the first word of data in buffer
311 static void Fr_configure_fifo_buffer(uint32_t buf_num, uint16_t mode, uint32_t cyc_filter, uint32_t frame_id, uint16_t fidMask, uint32_t payload, uint32_t data_pointer) {
312 frayREG->FRF_UN.FRF_ST.rnf = (mode&FRAY_BUF_REJECT_NULL_FRAMES) ? 1 : 0;
313 frayREG->FRF_UN.FRF_ST.rss = (mode&FRAY_BUF_REJECT_STATIC_SEGMENT) ? 1 : 0;
314 frayREG->FRF_UN.FRF_ST.fid_B11 = frame_id;
315 frayREG->FRFM_UN.FRFM_ST.mfid_B11 = fidMask;
316 frayREG->FRF_UN.FRF_ST.cyf_B7 = cyc_filter;
317 if (mode&FRAY_BUF_CHB_EN && mode&FRAY_BUF_CHA_EN) {
318 frayREG->FRF_UN.FRF_ST.ch_B2 = 0;
320 else if (mode&FRAY_BUF_CHB_EN) {
321 frayREG->FRF_UN.FRF_ST.ch_B2 = 1;
323 else if (mode&FRAY_BUF_CHA_EN) {
324 frayREG->FRF_UN.FRF_ST.ch_B2 = 2;
327 frayREG->FRF_UN.FRF_ST.ch_B2 = 3;
329 Fr_config_buffer(buf_num, mode, cyc_filter, frame_id, payload, data_pointer);
333 * Load data to message buffer. Data must be copied into WRDS register before this function is called.
335 * @param[in] buf_num Number of buffer
336 * @param[in] len Number of words to be loaded from data to buffer
338 static void Fr_buffer_transmit_data(uint32_t buf_num) {
341 write_buffer.ibrh = buf_num; // input buffer number
342 write_buffer.stxrh= 1; // set transmission request
343 write_buffer.ldsh = 1; // load data section
344 write_buffer.lhsh = 0; // load header section
345 write_buffer.ibsys = 0; // check for input buffer busy shadow
346 write_buffer.ibsyh = 1; // check for input buffer busy host
347 Fr_transmit_tx_LPdu(&write_buffer);
351 /** @fn wait_for_POC_ready(void)
352 * @brief Wait until POC is not busy
354 inline void Fr_wait_for_POC_ready() {
355 // Wait for PBSY bit to clear - POC not busy.
356 // 1: Signals that the POC is busy and cannot accept a command from the host. CMD(3-0) is locked against write accesses.
357 while(((frayREG->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);
360 /** @fn clear_msg_ram(void)
361 * @brief Clears FRAY message RAMs
363 * Send command to POC to set all bits of message RAM to 0.
364 * @return SUCCESS or FAILURE when command was not accepted
366 static int Fr_clear_msg_RAM() {
367 Fr_wait_for_POC_ready();
368 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CLEAR_RAMS;
369 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) {
372 Fr_wait_for_POC_ready();
378 * @brief Switch POC to config state from any other state
380 * After command to switch into config state is passed into CHI,
381 * the response is checked and if POC has reacted on the command,
382 * the function is waiting until POC is ready
384 * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
386 static Std_ReturnType Fr_POC_go_to_config() {
387 // write SUCC1 configuration
388 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CONFIG;
389 // Check if POC has accepted last command
390 if ((frayREG->SUCC1_UN.SUCC1_UL & 0xF) == 0x0)
392 // Wait for PBSY bit to clear - POC not busy
393 Fr_wait_for_POC_ready();
398 * @brief Switch POC to ready state from config state
400 * After command to switch into ready state is passed into CHI,
401 * the response is checked and if POC has reacted on the command,
402 * the function is waiting until POC is ready
404 * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
406 static Std_ReturnType Fr_POC_go_to_ready_from_config() {
407 Fr_wait_for_POC_ready();
408 // For CHA and CHB network
409 if (frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 && frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
411 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
412 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
413 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
415 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
416 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
417 frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
419 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
420 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
421 frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
424 else if(frayREG->SUCC1_UN.SUCC1_ST.ccha_B1){
426 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
427 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
428 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
430 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
431 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
432 frayREG->SUCC1_UN.SUCC1_ST.mtsa_B1 = 1U;
435 else if (frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
437 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
438 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
439 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
441 frayREG->LCK_UN.LCK_ST.clk_B8 = 0xCE;
442 frayREG->LCK_UN.LCK_ST.clk_B8 = 0x31;
443 frayREG->SUCC1_UN.SUCC1_ST.mtsb_B1 = 1U;
445 else frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
447 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
450 while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01)
451 ; // Waiting for READY state
456 * @brief Switch POC to ready state from startup state
458 * After command to switch into ready state is passed into CHI,
459 * the response is checked and if POC has reacted on the command,
460 * the function is waiting until POC is ready
462 * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
464 static Std_ReturnType Fr_POC_go_to_ready_from_startup() {
465 Fr_wait_for_POC_ready();
466 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
467 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
469 while ((frayREG->CCSV_UN.CCSV_UL & 0x0000003F) != 0x01); // Wait until POC is not in ready state
470 Fr_wait_for_POC_ready();
475 * @brief Switch POC to startup state from ready state
477 * After command to switch into startup state is passed into CHI,
478 * the response is checked and if POC has reacted on the command,
479 * the function is waiting until POC is ready
481 * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
483 static Std_ReturnType Fr_POC_go_to_startup() {
484 Fr_wait_for_POC_ready();
485 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_RUN;
486 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
488 Fr_wait_for_POC_ready();
493 * @brief Copy cluster config parameters into FlexRay configuration registers.
495 * This function does not check values ranges. This is a responsibility of higher
496 * layers. Cluster configuration parameters are copied from data structure
497 * into right bit position in configuration registers.
499 * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
501 void Fr_config_cluster_parameters(const Fr_TMS570LS_ClusterConfigType* clusterConfigPtr) {
502 frayREG->SUCC1_UN.SUCC1_ST.csa_B5 = clusterConfigPtr->gColdStartAttempts;
503 frayREG->GTUC9_UN.GTUC9_ST.apo_B5 = clusterConfigPtr->gdActionPointOffset;
504 frayREG->PRTC1_UN.PRTC1_ST.casm_B7 = clusterConfigPtr->gdCASRxLowMax;
505 frayREG->GTUC9_UN.GTUC9_ST.dsi_B2 = clusterConfigPtr->gdDynamicSlotIdlePhase;
506 frayREG->GTUC8_UN.GTUC8_ST.msl_B6 = clusterConfigPtr->gdMinislot;
507 frayREG->GTUC9_UN.GTUC9_ST.mapo_B5 = clusterConfigPtr->gdMinislotActionPointOffset;
508 frayREG->GTUC7_UN.GTUC7_ST.ssl_B10 = clusterConfigPtr->gdStaticSlot;
509 frayREG->PRTC1_UN.PRTC1_ST.tsst_B4 = clusterConfigPtr->gdTSSTransmitter;
510 frayREG->PRTC2_UN.PRTC2_ST.rxi_B6 = clusterConfigPtr->gdWakeupSymbolRxIdle;
511 frayREG->PRTC2_UN.PRTC2_ST.rxl_B6 = clusterConfigPtr->gdWakeupSymbolRxLow;
512 frayREG->PRTC1_UN.PRTC1_ST.rxw_B9 = clusterConfigPtr->gdWakeupSymbolRxWindow;
513 frayREG->PRTC2_UN.PRTC2_ST.txi_B8 = clusterConfigPtr->gdWakeupSymbolTxIdle;
514 frayREG->PRTC2_UN.PRTC2_ST.txl_B6 = clusterConfigPtr->gdWakeupSymbolTxLow;
515 frayREG->SUCC2_UN.SUCC2_ST.ltn_B4 = clusterConfigPtr->gListenNoise;
516 frayREG->GTUC2_UN.GTUC2_ST.mpc_B14 = clusterConfigPtr->gMacroPerCycle;
517 frayREG->SUCC3_UN.SUCC3_ST.wcf_B4 = clusterConfigPtr->gMaxWithoutClockCorrectionFatal;
518 frayREG->SUCC3_UN.SUCC3_ST.wcp_B4 = clusterConfigPtr->gMaxWithoutClockCorrectionPassive;
519 frayREG->GTUC8_UN.GTUC8_ST.nms_B13 = clusterConfigPtr->gNumberOfMinislots;
520 frayREG->GTUC7_UN.GTUC7_ST.nss_B10 = clusterConfigPtr->gNumberOfStaticSlots;
521 frayREG->GTUC4_UN.GTUC4_ST.ocs_B14 = clusterConfigPtr->gOffsetCorrectionStart;
522 frayREG->MHDC_UN.MHDC_ST.sfdl_B7 = clusterConfigPtr->gPayloadLengthStatic;
523 frayREG->GTUC2_UN.GTUC2_ST.snm_B4 = clusterConfigPtr->gSyncNodeMax;
524 frayREG->GTUC4_UN.GTUC4_ST.nit_B14 = clusterConfigPtr->gdNIT;
525 frayREG->PRTC1_UN.PRTC1_ST.brp_B2 = clusterConfigPtr->gdSampleClockPeriod;
526 frayREG->NEMC_UN.NEMC_ST.nml_B4 = clusterConfigPtr->gNetworkManagementVectorLength;
529 #define __notInRange(val, min, max) (((val) < (min)) || ((val) > (max)))
532 * @brief Check cluster configuration parameters.
534 * This function checks values of the cluster configuration parameters,
535 * if they are in ranges noted in FlexRay specification.
537 * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
538 * @param [out] errCode Address where error flags will be stored.
539 * We have 26 parameters to check. Every one of them has assigned its bit in this flag.
540 * Error flags are defined as macros ERR_PARAM_nameOfParameter.
541 * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
543 Std_ReturnType Fr_check_cluster_parameters(const Fr_TMS570LS_ClusterConfigType* clusterConfigPtr, uint32_t* errCode) {
544 *errCode = ERR_PARAM_NO_ERROR;
546 if (__notInRange(clusterConfigPtr->gColdStartAttempts, 2, 31)) *errCode |= ERR_PARAM_gColdStartAttempts;
547 if (__notInRange(clusterConfigPtr->gdActionPointOffset, 1, 63)) *errCode |= ERR_PARAM_gdActionPointOffset;
548 if (__notInRange(clusterConfigPtr->gdCASRxLowMax, 67, 99)) *errCode |= ERR_PARAM_gdCASRxLowMax;
549 if (clusterConfigPtr->gdDynamicSlotIdlePhase > 2) *errCode |= ERR_PARAM_gdDynamicSlotIdlePhase;
550 if (__notInRange(clusterConfigPtr->gdMinislot, 2, 63)) *errCode |= ERR_PARAM_gdMinislot;
551 if (__notInRange(clusterConfigPtr->gdMinislotActionPointOffset,
552 1, 31)) *errCode |= ERR_PARAM_gdMinislotActionPointOffset;
553 if (__notInRange(clusterConfigPtr->gdStaticSlot, 4, 661)) *errCode |= ERR_PARAM_gdStaticSlot;
554 if (__notInRange(clusterConfigPtr->gdTSSTransmitter, 3, 15)) *errCode |= ERR_PARAM_gdTSSTransmitter;
555 if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxIdle, 14, 59)) *errCode |= ERR_PARAM_gdWakeupSymbolRxIdle;
556 if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxLow, 11, 59)) *errCode |= ERR_PARAM_gdWakeupSymbolRxLow;
557 if (__notInRange(clusterConfigPtr->gdWakeupSymbolRxWindow,
558 76, 301)) *errCode |= ERR_PARAM_gdWakeupSymbolRxWindow;
559 if (__notInRange(clusterConfigPtr->gdWakeupSymbolTxIdle, 45, 180)) *errCode |= ERR_PARAM_gdWakeupSymbolTxIdle;
560 if (__notInRange(clusterConfigPtr->gdWakeupSymbolTxLow, 15, 60)) *errCode |= ERR_PARAM_gdWakeupSymbolTxLow;
561 if (__notInRange(clusterConfigPtr->gListenNoise, 2, 16)) *errCode |= ERR_PARAM_gListenNoise;
562 if (__notInRange(clusterConfigPtr->gMacroPerCycle, 10, 16000)) *errCode |= ERR_PARAM_gMacroPerCycle;
563 if (__notInRange(clusterConfigPtr->gMaxWithoutClockCorrectionFatal,
564 clusterConfigPtr->gMaxWithoutClockCorrectionPassive, 15)) *errCode |= ERR_PARAM_gMaxWithoutClockCorrectionFatal;
565 if (__notInRange(clusterConfigPtr->gMaxWithoutClockCorrectionPassive,
566 1, 15)) *errCode |= ERR_PARAM_gMaxWithoutClockCorrectionPassive;
567 if (clusterConfigPtr->gNumberOfMinislots > 7986) *errCode |= ERR_PARAM_gNumberOfMinislots;
568 if (__notInRange(clusterConfigPtr->gNumberOfStaticSlots,
569 2, cStaticSlotIDMax)) *errCode |= ERR_PARAM_gNumberOfStaticSlots;
570 if (__notInRange(clusterConfigPtr->gOffsetCorrectionStart,
571 9, 15999)) *errCode |= ERR_PARAM_gOffsetCorrectionStart;
572 if (clusterConfigPtr->gPayloadLengthStatic > cPayloadLengthMax) *errCode |= ERR_PARAM_gPayloadLengthStatic;
573 if (__notInRange(clusterConfigPtr->gSyncNodeMax, 2, cSyncNodeMax)) *errCode |= ERR_PARAM_gSyncNodeMax;
574 if (__notInRange(clusterConfigPtr->gdNIT, 7, 0x3E7D)) *errCode |= ERR_PARAM_gdNIT;
575 if (clusterConfigPtr->gdSampleClockPeriod > 3) *errCode |= ERR_PARAM_gdSampleClockPeriod;
576 if (clusterConfigPtr->gNetworkManagementVectorLength > 12) *errCode |= ERR_PARAM_gNetworkManagementVectorLength;
578 return (*errCode == 0) ? E_OK : E_NOT_OK;
582 * @brief Copy node config parameters into FlexRay configuration registers.
584 * This function does not check values ranges. This is a responsibility of higher
585 * layers. Node configuration parameters are copied from data structure
586 * into right bit position in configuration registers.
588 * @param [in] nodeConfigPtr Address of structure with node configuration parameters
590 void Fr_config_node_parameters(const Fr_TMS570LS_NodeConfigType* nodeConfigPtr) {
591 frayREG->SUCC1_UN.SUCC1_ST.hcse_B1 = nodeConfigPtr->pAllowHaltDueToClock;
592 frayREG->SUCC1_UN.SUCC1_ST.pta_B5 = nodeConfigPtr->pAllowPassiveToActive;
593 if (nodeConfigPtr->pChannels == FR_CHANNEL_AB) {
594 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 1;
595 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 1;
597 else if (nodeConfigPtr->pChannels == FR_CHANNEL_A) {
598 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 1;
599 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 0;
602 frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 = 0;
603 frayREG->SUCC1_UN.SUCC1_ST.cchb_B1 = 1;
605 frayREG->GTUC6_UN.GTUC6_ST.asr_B11 = nodeConfigPtr->pdAcceptedStartupRange;
606 frayREG->GTUC5_UN.GTUC5_ST.cdd_B5 = nodeConfigPtr->pClusterDriftDamping;
607 frayREG->GTUC5_UN.GTUC5_ST.dca_B8 = nodeConfigPtr->pDelayCompensationA;
608 frayREG->GTUC5_UN.GTUC5_ST.dcb_B8 = nodeConfigPtr->pDelayCompensationB;
609 frayREG->GTUC5_UN.GTUC5_ST.dec_B8 = nodeConfigPtr->pDecodingCorrection;
610 frayREG->SUCC2_UN.SUCC2_ST.lt_B21 = nodeConfigPtr->pdListenTimeout;
611 frayREG->GTUC6_UN.GTUC6_ST.mod_B11 = nodeConfigPtr->pdMaxDrift;
612 frayREG->GTUC11_UN.GTUC11_ST.eoc_B3 = nodeConfigPtr->pExternOffsetCorrection;
613 frayREG->GTUC11_UN.GTUC11_ST.erc_B3 = nodeConfigPtr->pExternRateCorrection;
614 frayREG->SUCC1_UN.SUCC1_ST.txst_B1 = nodeConfigPtr->pKeySlotUsedForStartup;
615 frayREG->SUCC1_UN.SUCC1_ST.txsy_B1 = nodeConfigPtr->pKeySlotUsedForSync;
616 frayREG->MHDC_UN.MHDC_ST.slt_B13 = nodeConfigPtr->pLatestTx;
617 frayREG->GTUC3_UN.GTUC3_ST.mioa_B7 = nodeConfigPtr->pMacroInitialOffsetA;
618 frayREG->GTUC3_UN.GTUC3_ST.miob_B7 = nodeConfigPtr->pMacroInitialOffsetB;
619 frayREG->GTUC3_UN.GTUC3_ST.uioa_B8 = nodeConfigPtr->pMicroInitialOffsetA;
620 frayREG->GTUC3_UN.GTUC3_ST.uiob_B8 = nodeConfigPtr->pMicroInitialOffsetB;
621 frayREG->GTUC1_UN.GTUC1_ST.ut_B20 = nodeConfigPtr->pMicroPerCycle;
622 frayREG->GTUC10_UN.GTUC10_ST.moc_B13 = nodeConfigPtr->pRateCorrectionOut;
623 frayREG->GTUC10_UN.GTUC10_ST.mrc_B11 = nodeConfigPtr->pOffsetCorrectionOut;
624 frayREG->SUCC1_UN.SUCC1_ST.tsm_B1 = nodeConfigPtr->pSingleSlotEnabled;
625 if (nodeConfigPtr->pWakeupChannel == FR_CHANNEL_A) {
626 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 0;
628 else if (nodeConfigPtr->pWakeupChannel == FR_CHANNEL_B) {
629 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 1;
631 frayREG->PRTC1_UN.PRTC1_ST.rwp_B6 = nodeConfigPtr->pWakeupPattern;
632 frayREG->PRTC1_UN.PRTC1_ST.brp_B2 = nodeConfigPtr->pSamplesPerMicrotick;
633 frayREG->EIR_UN.EIR_UL = 0xFFFFFFFF;
638 * @brief Check node configuration parameters.
640 * This function checks values of the node configuration parameters,
641 * if they are in ranges noted in FlexRay specification.
643 * @param [in] nodeConfigPtr Address of structure with node configuration parameters
644 * @param [out] errCode Address where error flags will be stored.
645 * We have 24 parameters to check. Every one of them has assigned its bit in this flag.
646 * Error flags are defined as macros ERR_PARAM_nameOfParameter.
647 * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
649 Std_ReturnType Fr_check_node_parameters(const Fr_TMS570LS_NodeConfigType* nodeConfigPtr, uint32_t* errCode) {
650 *errCode = ERR_PARAM_NO_ERROR;
652 if (nodeConfigPtr->pAllowPassiveToActive > 31) *errCode |= ERR_PARAM_pAllowPassiveToActive;
653 if (nodeConfigPtr->pChannels != FR_CHANNEL_A &&
654 nodeConfigPtr->pChannels != FR_CHANNEL_B &&
655 nodeConfigPtr->pChannels != FR_CHANNEL_AB ) *errCode |= ERR_PARAM_pChannels;
656 if (nodeConfigPtr->pdAcceptedStartupRange > 1875) *errCode |= ERR_PARAM_pdAcceptedStartupRange;
657 if (nodeConfigPtr->pClusterDriftDamping > 20) *errCode |= ERR_PARAM_pClusterDriftDamping;
658 if (nodeConfigPtr->pDelayCompensationA > 200) *errCode |= ERR_PARAM_pDelayCompensationA;
659 if (nodeConfigPtr->pDelayCompensationB > 200) *errCode |= ERR_PARAM_pDelayCompensationB;
660 if (__notInRange(nodeConfigPtr->pdListenTimeout, 1284, 1283846)) *errCode |= ERR_PARAM_pdListenTimeout;
661 if (__notInRange(nodeConfigPtr->pdMaxDrift, 2, 1923)) *errCode |= ERR_PARAM_pdMaxDrift;
662 if (nodeConfigPtr->pExternOffsetCorrection > 7) *errCode |= ERR_PARAM_pExternOffsetCorrection;
663 if (nodeConfigPtr->pExternRateCorrection > 7) *errCode |= ERR_PARAM_pExternRateCorrection;
664 if (nodeConfigPtr->pKeySlotUsedForStartup == TRUE &&
665 nodeConfigPtr->pKeySlotUsedForSync == FALSE) *errCode |= ERR_PARAM_pKeySlotUsedForSync
666 | ERR_PARAM_pKeySlotUsedForStartup; // If pKeySlotUsedForStartup is set to true then pKeySlotUsedForSync must also be set to true.
667 if (nodeConfigPtr->pLatestTx > 7980) *errCode |= ERR_PARAM_pLatestTx;
668 if (__notInRange(nodeConfigPtr->pMacroInitialOffsetA, 2, 68)) *errCode |= ERR_PARAM_pMacroInitialOffsetA;
669 if (__notInRange(nodeConfigPtr->pMacroInitialOffsetB, 2, 68)) *errCode |= ERR_PARAM_pMacroInitialOffsetB;
670 if (nodeConfigPtr->pMicroInitialOffsetA > 239) *errCode |= ERR_PARAM_pMicroInitialOffsetA;
671 if (nodeConfigPtr->pMicroInitialOffsetB > 239) *errCode |= ERR_PARAM_pMicroInitialOffsetB;
672 if (__notInRange(nodeConfigPtr->pMicroPerCycle, 640, 640000)) *errCode |= ERR_PARAM_pMicroPerCycle;
673 if (__notInRange(nodeConfigPtr->pRateCorrectionOut, 2, 1923)) *errCode |= ERR_PARAM_pRateCorrectionOut;
674 if (__notInRange(nodeConfigPtr->pOffsetCorrectionOut, 5, 0x3BA2)) *errCode |= ERR_PARAM_pOffsetCorrectionOut;
675 if (nodeConfigPtr->pWakeupChannel != FR_CHANNEL_A &&
676 nodeConfigPtr->pWakeupChannel != FR_CHANNEL_B ) *errCode |= ERR_PARAM_pWakeupChannel;
677 if (__notInRange(nodeConfigPtr->pWakeupPattern, 2, 63)) *errCode |= ERR_PARAM_pWakeupPattern;
678 if (nodeConfigPtr->pSamplesPerMicrotick > 3) *errCode |= ERR_PARAM_pSamplesPerMicrotick;
679 if (__notInRange(nodeConfigPtr->pDecodingCorrection, 0xF, 0x8F)) *errCode |= ERR_PARAM_pDecodingCorrection;
681 return (*errCode == 0) ? E_OK : E_NOT_OK;
685 * @brief Check Configuration parameters for all buffers
687 * This function checks configuration parameters.
689 * - All of them have to be RX
690 * - All of them have the same payload <= 256B
691 * - Same channels active
692 * - Same cycle counter filter
695 * - not reconfigurable
696 * - frame ID can be 0, which means that all messages not received by others buffers are received in FIFO.
697 * For dynamic segment buffers and static segment buffers:
698 * - frame ID must not be 0
700 * The sum of all configured payloads must be <= 8KB.
702 * @param [in] statBufCfgPtr Address of structure with static buffers configuration parameters
703 * @param [in] dynBufCfgPtr Address of structure with dynamic buffers configuration parameters
704 * @param [in] fifoBufCfgPtr Address of structure with fifo buffers configuration parameters
705 * @param [in] statBufCnt Number of static buffers to be configured
706 * @param [in] dynBufCnt Number of dynamic buffers to be configured
707 * @param [in] fifoBufCnt Number of fifo buffers to be configured
708 * @param [out] errCode Address where error flags will be stored.
709 * Flags are defined as ERR_PARAM_BUF.....
710 * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
712 Std_ReturnType Fr_check_buffer_parameters(const Fr_TMS570LS_BufferConfigType* statBufCfgPtr, const Fr_TMS570LS_BufferConfigType* dynBufCfgPtr, const Fr_TMS570LS_BufferConfigType* fifoBufCfgPtr,
713 uint8_t statBufCnt, uint8_t dynBufCnt, uint8_t fifoBufCnt, uint32_t* errCode) {
714 uint32_t payloadTotal = 0;
715 *errCode = ERR_PARAM_NO_ERROR;
716 uint8_t fifoPayload, fifoCycleCounterFiltering;
717 Fr_ChannelType fifoChannels;
718 uint16_t fifoFidMask, fifoSlotId;
719 boolean_t fifoRejNullFr, fifoRejStatFr;
720 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr = NULL;
723 /* Check FIFO buffer parameters */
724 if (fifoBufCnt != 0 && fifoBufCfgPtr != NULL) {
725 fifoChannels = fifoBufCfgPtr[0].channel;
726 fifoCycleCounterFiltering = fifoBufCfgPtr[0].cycleCounterFiltering;
727 fifoFidMask = fifoBufCfgPtr[0].fidMask;
728 fifoSlotId = fifoBufCfgPtr[0].slotId;
729 fifoPayload = fifoBufCfgPtr[0].maxPayload;
730 fifoRejNullFr = fifoBufCfgPtr[0].rejectNullFrames;
731 fifoRejStatFr = fifoBufCfgPtr[0].rejectStaticSegment;
732 if (fifoPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFFIFO_PAYLOAD_HIGH;
733 for (buffer_cfg_ptr = &fifoBufCfgPtr[0]; buffer_cfg_ptr < &fifoBufCfgPtr[fifoBufCnt]; buffer_cfg_ptr++) {
734 if (buffer_cfg_ptr->channel != fifoChannels) *errCode |= ERR_PARAM_BUFFIFO_CHANNEL_DIFFERS;
735 if (buffer_cfg_ptr->cycleCounterFiltering != fifoCycleCounterFiltering) *errCode |= ERR_PARAM_BUFFIFO_CCFILTER_DIFFERS;
736 if (buffer_cfg_ptr->fidMask != fifoFidMask) *errCode |= ERR_PARAM_BUFFIFO_FIDMASK_DIFFERS;
737 if (buffer_cfg_ptr->isTx == TRUE) *errCode |= ERR_PARAM_BUFFIFO_NOT_RX;
738 if (buffer_cfg_ptr->maxPayload != fifoPayload) *errCode |= ERR_PARAM_BUFFIFO_PAYLOAD_DIFFERS;
739 if (buffer_cfg_ptr->payloadPreambleIndicatorTr == TRUE) *errCode |= ERR_PARAM_BUFFIFO_PPIT;
740 if (buffer_cfg_ptr->rejectNullFrames != fifoRejNullFr) *errCode |= ERR_PARAM_BUFFIFO_REJNULLFR_DIFFERS;
741 if (buffer_cfg_ptr->rejectStaticSegment != fifoRejStatFr) *errCode |= ERR_PARAM_BUFFIFO_REJSTATFR_DIFFERS;
742 if (buffer_cfg_ptr->slotId != fifoSlotId) *errCode |= ERR_PARAM_BUFFIFO_SLOTID_DIFFERS;
743 payloadTotal += buffer_cfg_ptr->maxPayload;
746 if (dynBufCfgPtr != NULL) {
747 for (buffer_cfg_ptr = &dynBufCfgPtr[0]; buffer_cfg_ptr < &dynBufCfgPtr[dynBufCnt]; buffer_cfg_ptr++) {
748 if (buffer_cfg_ptr->slotId == 0) *errCode |= ERR_PARAM_BUFDYN_FRAMEID_INVALID;
749 if (buffer_cfg_ptr->maxPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFDYN_PAYLOAD_HIGH;
750 if (buffer_cfg_ptr->channel == FR_CHANNEL_AB) *errCode |= ERR_PARAM_BUFDYN_CHANNELS;
751 payloadTotal += buffer_cfg_ptr->maxPayload;
755 if (statBufCfgPtr != NULL) {
756 for (buffer_cfg_ptr = &statBufCfgPtr[0]; buffer_cfg_ptr < &statBufCfgPtr[statBufCnt]; buffer_cfg_ptr++) {
757 if (buffer_cfg_ptr->slotId == 0) *errCode |= ERR_PARAM_BUFSTAT_FRAMEID_INVALID;
758 if (buffer_cfg_ptr->maxPayload > cPayloadLengthMax) *errCode |= ERR_PARAM_BUFSTAT_PAYLOAD_HIGH;
759 payloadTotal += buffer_cfg_ptr->maxPayload;
763 if (payloadTotal > 8192/2) *errCode |= ERR_PARAM_BUF_TOTAL_PAYLOAD_HIGH;
765 return (*errCode == 0) ? E_OK : E_NOT_OK;
769 * @brief Compute and set message RAM config parameters into FlexRay configuration registers.
771 * This function does not check values ranges. This is a responsibility of other functions.
772 * Message RAM configuration parameters are computed from data in the structure and
773 * written into right bit position in configuration registers.
775 * @param [in] msgRAMConfigPtr Address of structure with message RAM configuration parameters
776 * @return Number of configured buffers
778 uint8_t Fr_config_msgRAM_parameters(const Fr_TMS570LS_MsgRAMConfig* msgRAMConfigPtr) {
779 /* If dynSegmentBufferCount is not 0 then first dynamic buffer = statSegmentBufferCount.
780 * If dynSegmentBufferCount is 0 then first dynamic buffer is 0x80 (see TMS570LS31x documentation)
782 if (msgRAMConfigPtr->dynSegmentBufferCount == 0) {
783 frayREG->MRC_UN.MRC_ST.fdb_B8 = 0x80;
786 frayREG->MRC_UN.MRC_ST.fdb_B8 = msgRAMConfigPtr->statSegmentBufferCount;
788 /* If fifoBufferCount is not 0 then first fifo buffer = statSegmentBufferCount + dynSegmentBufferCount
789 * If fifoBufferCount is 0 then first fifo buffer is 0x80 (see TMS570LS31x documentation)
791 if (msgRAMConfigPtr->fifoBufferCount == 0) {
792 frayREG->MRC_UN.MRC_ST.ffb_B8 = 0x80;
795 frayREG->MRC_UN.MRC_ST.ffb_B8 = msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount;
797 /* Last configured buffer = statSegmentBufferCount + dynSegmentBufferCount + fifoBufferCount - 1 */
798 frayREG->MRC_UN.MRC_ST.lcb_B8 = msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount + msgRAMConfigPtr->fifoBufferCount - 1;
800 /* Secure buffers setting */
801 if (msgRAMConfigPtr->secureBuffers == FR_SB_RECONFIG_ENABLED) {
802 frayREG->MRC_UN.MRC_ST.sec_B2 = 0;
804 else if (msgRAMConfigPtr->secureBuffers == FR_SB_STAT_REC_DISABLED_STAT_TR_DISABLED) {
805 frayREG->MRC_UN.MRC_ST.sec_B2 = 1;
807 else if (msgRAMConfigPtr->secureBuffers == FR_SB_ALL_REC_DISABLED) {
808 frayREG->MRC_UN.MRC_ST.sec_B2 = 2;
811 frayREG->MRC_UN.MRC_ST.sec_B2 = 3;
814 /* Sync frame payload multiplex setting */
815 if (msgRAMConfigPtr->syncFramePayloadMultiplexEnabled == TRUE) {
816 frayREG->MRC_UN.MRC_ST.splm_B1 = 1;
819 frayREG->MRC_UN.MRC_ST.splm_B1 = 0;
822 return msgRAMConfigPtr->statSegmentBufferCount + msgRAMConfigPtr->dynSegmentBufferCount + msgRAMConfigPtr->fifoBufferCount;
825 #define __notInRange(val, min, max) (((val) < (min)) || ((val) > (max)))
828 * @brief Check message RAM configuration parameters.
830 * This function checks values of the message RAM configuration parameters.
831 * FlexRay implementation in TMS570 can have up to 128 buffers configured, so
832 * the sum of all values buffer count must not exceed this ceiling.
835 * @param [in] clusterConfigPtr Address of structure with cluster configuration parameters
836 * @param [out] errCode Address where error flags will be stored.
837 * Error flags are defined as macros ERR_PARAM_nameOfParameter.
838 * @return E_OK: Parameters are OK. E_NOT_OK: Some parameter is out of range.
840 Std_ReturnType Fr_check_msgRAM_parameters(const Fr_TMS570LS_MsgRAMConfig* msgRAMConfigPtr, uint32_t* errCode) {
841 *errCode = ERR_PARAM_NO_ERROR;
843 if (__notInRange(msgRAMConfigPtr->statSegmentBufferCount, 1, 127)) *errCode |= ERR_PARAM_statSegmentBufferCount;
844 if (msgRAMConfigPtr->dynSegmentBufferCount >= FR_MAX_BUFFERS_CNT) *errCode |= ERR_PARAM_dynSegmentBufferCount;
845 if (msgRAMConfigPtr->fifoBufferCount >= FR_MAX_BUFFERS_CNT) *errCode |= ERR_PARAM_fifoBufferCount;
846 if ((msgRAMConfigPtr->statSegmentBufferCount +
847 msgRAMConfigPtr->dynSegmentBufferCount +
848 msgRAMConfigPtr->fifoBufferCount) >= FR_MAX_BUFFERS_CNT) *errCode |= ERR_PARAM_maxBuffLimit;
850 return (*errCode == 0) ? E_OK : E_NOT_OK;
853 void Fr_Init(const Fr_ConfigType* Fr_ConfigPtr) {
854 Fr_slot_buffer_map_t* buffer_slot_map_ptr;
855 uint8_t buffer_last_index;
856 boolean_t* buffers_configured_ptr;
857 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
860 if (Fr_ConfigPtr == NULL) {
863 if (Fr_DrvState != FR_ST_DRV_NOT_INITIALIZED) {
867 /* Save pointers for parameters indexed by CIDX indexes
868 * This array representation is used by Fr_ReadCCConfig function.
869 * Parameter thet are not configurable in tms570 FlexRay implementation
872 Fr_ConfigParPtrs[FR_CIDX_GDCYCLE] = 0;
873 Fr_ConfigParPtrs[FR_CIDX_PMICROPERCYCLE] = Fr_ConfigPtr->nodeConfiguration->pMicroPerCycle;
874 Fr_ConfigParPtrs[FR_CIDX_PDLISTENTIMEOUT] = Fr_ConfigPtr->clusterConfiguration->gMacroPerCycle;
875 Fr_ConfigParPtrs[FR_CIDX_GDMACROTICK] = 0;
876 Fr_ConfigParPtrs[FR_CIDX_GNUMBEROFMINISLOTS] = Fr_ConfigPtr->clusterConfiguration->gNumberOfMinislots;
877 Fr_ConfigParPtrs[FR_CIDX_GNUMBEROFSTATICSLOTS] = Fr_ConfigPtr->clusterConfiguration->gNumberOfStaticSlots;
878 Fr_ConfigParPtrs[FR_CIDX_GDNIT] = Fr_ConfigPtr->clusterConfiguration->gdNIT;
879 Fr_ConfigParPtrs[FR_CIDX_GDSTATICSLOT] = Fr_ConfigPtr->clusterConfiguration->gdNIT;
880 Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXWINDOW] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxWindow;
881 Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTID] = 0;
882 Fr_ConfigParPtrs[FR_CIDX_PLATESTTX] = Fr_ConfigPtr->nodeConfiguration->pLatestTx;
883 Fr_ConfigParPtrs[FR_CIDX_POFFSETCORRECTIONOUT] = 0;
884 Fr_ConfigParPtrs[FR_CIDX_POFFSETCORRECTIONSTART] = 0;
885 Fr_ConfigParPtrs[FR_CIDX_PRATECORRECTIONOUT] = Fr_ConfigPtr->nodeConfiguration->pRateCorrectionOut;
886 Fr_ConfigParPtrs[FR_CIDX_PSECONDKEYSLOTID] = 0;
887 Fr_ConfigParPtrs[FR_CIDX_PDACCEPTEDSTARTUPRANGE] = Fr_ConfigPtr->nodeConfiguration->pdAcceptedStartupRange;
888 Fr_ConfigParPtrs[FR_CIDX_GCOLDSTARTATTEMPTS] = Fr_ConfigPtr->clusterConfiguration->gColdStartAttempts;
889 Fr_ConfigParPtrs[FR_CIDX_GCYCLECOUNTMAX] = 0;
890 Fr_ConfigParPtrs[FR_CIDX_GLISTENNOISE] = Fr_ConfigPtr->clusterConfiguration->gListenNoise;
891 Fr_ConfigParPtrs[FR_CIDX_GMAXWITHOUTCLOCKCORRECTFATAL] = Fr_ConfigPtr->clusterConfiguration->gMaxWithoutClockCorrectionFatal;
892 Fr_ConfigParPtrs[FR_CIDX_GMAXWITHOUTCLOCKCORRECTPASSIVE] = Fr_ConfigPtr->clusterConfiguration->gMaxWithoutClockCorrectionPassive;
893 Fr_ConfigParPtrs[FR_CIDX_GNETWORKMANAGEMENTVECTORLENGTH] = Fr_ConfigPtr->clusterConfiguration->gNetworkManagementVectorLength;
894 Fr_ConfigParPtrs[FR_CIDX_GPAYLOADLENGTHSTATIC] = Fr_ConfigPtr->clusterConfiguration->gPayloadLengthStatic;
895 Fr_ConfigParPtrs[FR_CIDX_GSYNCFRAMEIDCOUNTMAX] = 0;
896 Fr_ConfigParPtrs[FR_CIDX_GDACTIONPOINTOFFSET] = Fr_ConfigPtr->clusterConfiguration->gdActionPointOffset;
897 Fr_ConfigParPtrs[FR_CIDX_GDBIT] = 0;
898 Fr_ConfigParPtrs[FR_CIDX_GDCASRXLOWMAX] = Fr_ConfigPtr->clusterConfiguration->gdCASRxLowMax;
899 Fr_ConfigParPtrs[FR_CIDX_GDDYNAMICSLOTIDLEPHASE] = Fr_ConfigPtr->clusterConfiguration->gdDynamicSlotIdlePhase;
900 Fr_ConfigParPtrs[FR_CIDX_GDMINISLOTACTIONPOINTOFFSET] = Fr_ConfigPtr->clusterConfiguration->gdMinislotActionPointOffset;
901 Fr_ConfigParPtrs[FR_CIDX_GDMINISLOT] = Fr_ConfigPtr->clusterConfiguration->gdMinislot;
902 Fr_ConfigParPtrs[FR_CIDX_GDSAMPLECLOCKPERIOD] = Fr_ConfigPtr->clusterConfiguration->gdSampleClockPeriod;
903 Fr_ConfigParPtrs[FR_CIDX_GDSYMBOLWINDOW] = 0;
904 Fr_ConfigParPtrs[FR_CIDX_GDSYMBOLWINDOWACTIONPOINTOFFSET] = 0;
905 Fr_ConfigParPtrs[FR_CIDX_GDTSSTRANSMITTER] = Fr_ConfigPtr->clusterConfiguration->gdTSSTransmitter;
906 Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXIDLE] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxIdle;
907 Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPRXLOW] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolRxLow;
908 Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPTXACTIVE] = 0;
909 Fr_ConfigParPtrs[FR_CIDX_GDWAKEUPTXIDLE] = Fr_ConfigPtr->clusterConfiguration->gdWakeupSymbolTxIdle;
910 Fr_ConfigParPtrs[FR_CIDX_PALLOWPASSIVETOACTIVE] = Fr_ConfigPtr->nodeConfiguration->pAllowPassiveToActive;
911 Fr_ConfigParPtrs[FR_CIDX_PCHANNELS] = Fr_ConfigPtr->nodeConfiguration->pChannels;
912 Fr_ConfigParPtrs[FR_CIDX_PCLUSTERDRIFTDAMPING] = Fr_ConfigPtr->nodeConfiguration->pClusterDriftDamping;
913 Fr_ConfigParPtrs[FR_CIDX_PDECODINGCORRECTION] = 0;
914 Fr_ConfigParPtrs[FR_CIDX_PDELAYCOMPENSATIONA] = Fr_ConfigPtr->nodeConfiguration->pDelayCompensationA;
915 Fr_ConfigParPtrs[FR_CIDX_PDELAYCOMPENSATIONB] = Fr_ConfigPtr->nodeConfiguration->pDelayCompensationB;
916 Fr_ConfigParPtrs[FR_CIDX_PMACROINITIALOFFSETA] = Fr_ConfigPtr->nodeConfiguration->pMacroInitialOffsetA;
917 Fr_ConfigParPtrs[FR_CIDX_PMACROINITIALOFFSETB] = Fr_ConfigPtr->nodeConfiguration->pMacroInitialOffsetB;
918 Fr_ConfigParPtrs[FR_CIDX_PMICROINITIALOFFSETA] = Fr_ConfigPtr->nodeConfiguration->pMicroInitialOffsetA;
919 Fr_ConfigParPtrs[FR_CIDX_PMICROINITIALOFFSETB] = Fr_ConfigPtr->nodeConfiguration->pMicroInitialOffsetB;
920 Fr_ConfigParPtrs[FR_CIDX_PPAYLOADLENGTHDYNMAX] = 0;
921 Fr_ConfigParPtrs[FR_CIDX_PSAMPLESPERMICROTICK] = Fr_ConfigPtr->nodeConfiguration->pSamplesPerMicrotick;
922 Fr_ConfigParPtrs[FR_CIDX_PWAKEUPCHANNEL] = Fr_ConfigPtr->nodeConfiguration->pWakeupChannel;
923 Fr_ConfigParPtrs[FR_CIDX_PWAKEUPPATTERN] = Fr_ConfigPtr->nodeConfiguration->pWakeupPattern;
924 Fr_ConfigParPtrs[FR_CIDX_PDMICROTICK] = 0;
925 Fr_ConfigParPtrs[FR_CIDX_GDIGNOREAFTERTX] = 0;
926 Fr_ConfigParPtrs[FR_CIDX_PALLOWHALTDUETOCLOCK] = Fr_ConfigPtr->nodeConfiguration->pAllowHaltDueToClock;
927 Fr_ConfigParPtrs[FR_CIDX_PEXTERNALSYNC] = 0;
928 Fr_ConfigParPtrs[FR_CIDX_PFALLBACKINTERNAL] = 0;
929 Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTONLYENABLED] = 0;
930 Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSTARTUP] = Fr_ConfigPtr->nodeConfiguration->pKeySlotUsedForStartup;
931 Fr_ConfigParPtrs[FR_CIDX_PKEYSLOTUSEDFORSYNC] = Fr_ConfigPtr->nodeConfiguration->pKeySlotUsedForSync;
932 Fr_ConfigParPtrs[FR_CIDX_PNMVECTOREARLYUPDATE] = 0;
933 Fr_ConfigParPtrs[FR_CIDX_PTWOKEYSLOTMODE] = 0;
935 /* Store whole configuration address
936 * This structured representation is used by other function in API.
938 Fr_Config = Fr_ConfigPtr;
940 /* Store pointers to structures with configuration parameters of buffers
941 * Reset configured flags for all buffers */
942 buffer_last_index = Fr_ConfigPtr->msgRAMConfig->statSegmentBufferCount;
943 for (buffer_slot_map_ptr = Fr_buffer_slot_map, buffers_configured_ptr = Fr_BuffersConfigured, buffer_cfg_ptr = Fr_ConfigPtr->staticBufferConfigs;
944 buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
945 buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
946 ) { // Static segment buffers
947 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
948 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
949 *buffers_configured_ptr = FALSE;
951 buffer_last_index += Fr_ConfigPtr->msgRAMConfig->dynSegmentBufferCount;
952 for (buffer_cfg_ptr = Fr_ConfigPtr->dynamicBufferConfigs;
953 buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
954 buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
955 ) { // Dynamic segment buffers
956 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
957 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
958 *buffers_configured_ptr = FALSE;
960 buffer_last_index += Fr_ConfigPtr->msgRAMConfig->fifoBufferCount;
961 for (buffer_cfg_ptr = Fr_ConfigPtr->fifoBufferConfigs;
962 buffer_slot_map_ptr < &Fr_buffer_slot_map[buffer_last_index];
963 buffer_slot_map_ptr++, buffers_configured_ptr++, buffer_cfg_ptr++
965 buffer_slot_map_ptr->buffer_ptr = buffer_cfg_ptr;
966 buffer_slot_map_ptr->slot_id = buffer_cfg_ptr->slotId;
967 *buffers_configured_ptr = FALSE;
971 Fr_DrvState = FR_ST_DRV_INITIALIZED;
975 Std_ReturnType Fr_ControllerInit(uint8_t Fr_CtrlIdx) {
976 uint32_t errCode = ERR_PARAM_NO_ERROR;
978 uint8_t totalBufferCount;
981 if (Fr_DrvState < FR_ST_DRV_INITIALIZED) {
986 /* Switch CC into ‘POC:config’ (from any other POCState) */
987 while (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_CONFIG) {
988 if (Fr_POC_go_to_config() == E_NOT_OK) {
993 /* Check Cluster config parameters */
994 if (Fr_check_cluster_parameters(Fr_Config->clusterConfiguration, &errCode) == E_NOT_OK) {
995 return E_NOT_OK | errCode | FR_INIT_ERR_CLUSTER_CONFIG;
997 /* Check node config parameters */
998 if (Fr_check_node_parameters(Fr_Config->nodeConfiguration, &errCode) == E_NOT_OK) {
999 return E_NOT_OK | errCode | FR_INIT_ERR_NODE_CONFIG;
1001 /* Check msgRAM config parameters */
1002 if (Fr_check_msgRAM_parameters(Fr_Config->msgRAMConfig, &errCode) == E_NOT_OK) {
1003 return E_NOT_OK | errCode | FR_INIT_ERR_MSGRAM_CONFIG;
1005 /* Check buffers parameters */
1006 if (Fr_check_buffer_parameters(Fr_Config->staticBufferConfigs, Fr_Config->dynamicBufferConfigs, Fr_Config->fifoBufferConfigs,
1007 Fr_Config->msgRAMConfig->statSegmentBufferCount, Fr_Config->msgRAMConfig->dynSegmentBufferCount, Fr_Config->msgRAMConfig->fifoBufferCount, &errCode) == E_NOT_OK) {
1008 return E_NOT_OK | errCode | FR_INIT_ERR_BUFFPARAM_CONFIG;
1011 /* Clear message RAM */
1012 if (Fr_clear_msg_RAM() == FAILURE) {
1016 /* Configure all FlexRay cluster, node and msgRAM parameters */
1017 Fr_config_cluster_parameters(Fr_Config->clusterConfiguration);
1018 Fr_config_node_parameters(Fr_Config->nodeConfiguration);
1020 // Wait until CLEAR_RAMS command is complete
1021 while (frayREG->MHDS_UN.MHDS_ST.cram_B1 == 1)
1024 totalBufferCount = Fr_config_msgRAM_parameters(Fr_Config->msgRAMConfig);
1025 Fr_MsgRAMDataStartAddress = totalBufferCount*4U; // First data section after headers sections in message RAM.
1026 Fr_MsgRAMDataOffset = Fr_MsgRAMDataStartAddress;
1028 /* Reset configured flags */
1029 for (i = 0; i < totalBufferCount; i++) {
1030 Fr_BuffersConfigured[i] = FALSE;
1033 /* Configure all transmit/receive resources */
1034 for (i = 0; i < totalBufferCount; i++) {
1035 if (Fr_PrepareLPdu(Fr_CtrlIdx, Fr_buffer_slot_map[i].buffer_ptr->slotId) == E_NOT_OK) {
1036 return E_NOT_OK | FR_INIT_ERR_BUFF_CONFIG;
1040 /* Switch POC to ready state */
1041 if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1044 #ifdef DET_ACTIVATED
1045 Fr_DrvState = FR_ST_CTRL_INITIALIZED;
1050 Std_ReturnType Fr_StartCommunication(uint8_t Fr_CtrlIdx) {
1052 uint32_t state_value;
1054 #ifdef DET_ACTIVATED
1055 if (Fr_CtrlIdx != 0) {
1058 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1061 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_READY && frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_HALT) {
1065 // Node halted, switch to ready
1066 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_HALT) {
1067 if (Fr_POC_go_to_config() == E_NOT_OK) {
1070 if (Fr_POC_go_to_config() == E_NOT_OK) {
1073 if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1078 // Node is configured as coldstart
1079 if (Fr_Config->nodeConfiguration->pKeySlotUsedForStartup == TRUE) {
1083 // Try to integrate into an existing network as following coldstarter
1084 if (Fr_POC_go_to_startup() == E_NOT_OK) {
1085 return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_FOLLOW; // Switch to run state error
1088 do { // Wait until NORMAL_ACTIVE state or timeout
1089 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1091 } while ((state_value != FR_POCS_NORMAL_ACTIVE) && (counter < FR_FCS_LISTEN_TIMEOUT));
1093 // No success in integration, try to initiate FlexRay network as leading coldstarter.
1094 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_INTEGRATION_LISTEN){
1095 csa = frayREG->CCSV_UN.CCSV_ST.rca_B5;
1096 if (csa != 0) { // Some cold start attempts remaining
1097 if (Fr_AllowColdstart(Fr_CtrlIdx) == E_NOT_OK) {
1098 return E_NOT_OK | FR_STARTUP_ERR_CSINH_DIS; // Cold start inhibit disabled error
1102 do { // Wait until NORMAL_ACTIVE or INTEGRATION_LISTEN state
1103 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1104 } while ( (state_value != FR_POCS_NORMAL_ACTIVE) && (state_value != FR_POCS_INTEGRATION_LISTEN));
1105 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_NORMAL_ACTIVE) // Success, break the start up loop
1107 if (Fr_POC_go_to_ready_from_startup() == E_NOT_OK) { // No success. Switch back to READY state
1108 return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_READY;
1112 // The node is not coldstarter, try to integrate into an existing network.
1114 if(Fr_POC_go_to_startup() == E_NOT_OK) {
1115 return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_AS_NCOLD; // Switching to startup state as non-cold start node
1118 // Wait until NORMAL_ACTIVE
1120 state_value = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1121 } while (state_value != FR_POCS_NORMAL_ACTIVE);
1127 Std_ReturnType Fr_AllowColdstart(uint8_t Fr_CtrlIdx) {
1128 #ifdef DET_ACTIVATED
1129 if (Fr_CtrlIdx != 0) {
1132 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1136 Fr_wait_for_POC_ready();
1137 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_ALLOW_COLDSTART;
1138 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1140 Fr_wait_for_POC_ready();
1144 Std_ReturnType Fr_AllSlots(uint8_t Fr_CtrlIdx) {
1145 #ifdef DET_ACTIVATED
1146 if (Fr_CtrlIdx != 0) {
1149 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1153 Fr_wait_for_POC_ready();
1154 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_ALL_SLOTS;
1155 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1157 Fr_wait_for_POC_ready();
1161 Std_ReturnType Fr_HaltCommunication(uint8_t Fr_CtrlIdx) {
1162 #ifdef DET_ACTIVATED
1163 if (Fr_CtrlIdx != 0) {
1166 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1170 Fr_wait_for_POC_ready();
1171 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_HALT;
1172 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1174 Fr_wait_for_POC_ready();
1178 Std_ReturnType Fr_AbortCommunication(uint8_t Fr_CtrlIdx) {
1179 #ifdef DET_ACTIVATED
1180 if (Fr_CtrlIdx != 0) {
1183 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1187 Fr_wait_for_POC_ready();
1188 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_FREEZE;
1189 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1191 Fr_wait_for_POC_ready();
1195 Std_ReturnType Fr_SendWUP(uint8_t Fr_CtrlIdx) {
1196 #ifdef DET_ACTIVATED
1197 if (Fr_CtrlIdx != 0) {
1200 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1204 Fr_wait_for_POC_ready();
1205 frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_WAKEUP;
1206 if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
1208 Fr_wait_for_POC_ready();
1212 Std_ReturnType Fr_SetWakeupChannel(uint8_t Fr_CtrlIdx, Fr_ChannelType Fr_ChnlIdx) {
1213 Std_ReturnType retVal = E_OK;
1215 #ifdef DET_ACTIVATED
1216 if (Fr_CtrlIdx != 0) {
1219 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1222 if (Fr_ChnlIdx == FR_CHANNEL_AB) {
1225 if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 != FR_POCS_READY) {
1229 if (Fr_POC_go_to_config() == E_NOT_OK) {
1232 if (Fr_ChnlIdx == FR_CHANNEL_A) {
1233 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 0;
1236 else if (Fr_ChnlIdx == FR_CHANNEL_B) {
1237 frayREG->SUCC1_UN.SUCC1_ST.wucs_B1 = 1;
1243 if (Fr_POC_go_to_ready_from_config() == E_NOT_OK) {
1250 Std_ReturnType Fr_GetPOCStatus(uint8_t Fr_CtrlIdx, Fr_POCStatusType* Fr_POCStatusPtr) {
1251 static const Fr_SlotModeType slot_mode[4] = {FR_SLOTMODE_KEYSLOT, FR_SLOTMODE_INVALID, FR_SLOTMODE_ALL_PENDING, FR_SLOTMODE_ALL};
1252 static const Fr_ErrorModeType error_mode[4] = {FR_ERRORMODE_ACTIVE, FR_ERRORMODE_PASSIVE, FR_ERRORMODE_COMM_HALT, FR_ERRORMODE_INVALID};
1253 static const Fr_POCStateType poc_state[9] = {FR_POCSTATE_DEFAULT_CONFIG, FR_POCSTATE_READY, FR_POCSTATE_NORMAL_ACTIVE, FR_POCSTATE_NORMAL_PASSIVE,
1254 FR_POCSTATE_HALT, FR_POCSTATE_MONITOR, FR_POCSTATE_LOOPBACK, FR_POCSTATE_INVALID, FR_POCSTATE_CONFIG};
1255 static const Fr_WakeupStatusType wup_state[8] = {FR_WAKEUP_UNDEFINED, FR_WAKEUP_RECEIVED_HEADER, FR_WAKEUP_RECEIVED_WUP, FR_WAKEUP_COLLISION_HEADER,
1256 FR_WAKEUP_COLLISION_WUP, FR_WAKEUP_COLLISION_UNKNOWN, FR_WAKEUP_TRANSMITTED, FR_WAKEUP_INVALID};
1257 static const Fr_StartupStateType startup_state[11] = {FR_STARTUP_PREPARE, FR_STARTUP_COLDSTART_LISTEN, FR_STARTUP_COLDSTART_COLLISION_RESOLUTION,
1258 FR_STARTUP_COLDSTART_CONSISTENCY_CHECK, FR_STARTUP_COLDSTART_GAP, FR_STARTUP_COLDSTART_JOIN, FR_STARTUP_INTEGRATION_COLDSTART_CHECK,
1259 FR_STARTUP_INTEGRATION_LISTEN, FR_STARTUP_INTEGRATION_CONSISTENCY_CHECK, FR_STARTUP_INITIALIZE_SCHEDULE, FR_STARTUP_ABORT};
1261 #ifdef DET_ACTIVATED
1262 if (Fr_CtrlIdx != 0) {
1265 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1268 if (Fr_POCStatusPtr == NULL) {
1272 Fr_POCStatusPtr->SlotMode = slot_mode[frayREG->CCSV_UN.CCSV_ST.slm_B2]; /* Slot mode detection */
1273 Fr_POCStatusPtr->Freeze = (frayREG->CCSV_UN.CCSV_ST.fsi_B1 == 1) ? TRUE : FALSE; /* Freeze request detection */
1274 Fr_POCStatusPtr->CHIHaltRequest = (frayREG->CCSV_UN.CCSV_ST.hrq_B1 == 1) ? TRUE : FALSE; /* Halt request detection */
1275 Fr_POCStatusPtr->ColdstartNoise = (frayREG->CCSV_UN.CCSV_ST.csni_B1 == 1) ? TRUE : FALSE; /* Coldstart noise detection */
1276 Fr_POCStatusPtr->ColdstartNoise = (frayREG->CCSV_UN.CCSV_ST.csni_B1 == 1) ? TRUE : FALSE; /* Coldstart noise detection */
1277 Fr_POCStatusPtr->ErrorMode = error_mode[frayREG->CCEV_UN.CCEV_ST.errm_B2]; /* Error mode detection */
1279 /* POC state detection */
1280 /* Startup substate detection */
1281 uint16_t pocs = frayREG->CCSV_UN.CCSV_ST.pocs_B6;
1282 Fr_POCStatusPtr->StartupState = FR_STARTUP_UNDEFINED;
1283 if (pocs > FR_POCSTATE_DEFAULT_CONFIG && pocs <= FR_POCSTATE_MONITOR) {
1284 Fr_POCStatusPtr->State = poc_state[pocs];
1286 else if (pocs >= FR_POCSTATE_LOOPBACK && pocs <= FR_POCSTATE_CONFIG) {
1287 Fr_POCStatusPtr->State = poc_state[pocs-7];
1289 else if (pocs >= FR_POCS_WAKEUP_STANDBY && pocs <= FR_POCS_WAKEUP_DETECT) {
1290 Fr_POCStatusPtr->State = FR_POCSTATE_WAKEUP;
1292 else if (pocs >= FR_POCS_STARTUP_PREPARE && pocs <= FR_POCS_ABORT_STARTUP) {
1293 Fr_POCStatusPtr->State = FR_POCSTATE_STARTUP;
1294 Fr_POCStatusPtr->StartupState = startup_state[frayREG->CCSV_UN.CCSV_ST.pocs_B6 - FR_POCS_STARTUP_PREPARE];
1297 Fr_POCStatusPtr->State = FR_POCSTATE_INVALID;
1300 /* Wakeup substate detection */
1301 Fr_POCStatusPtr->WakeupStatus = wup_state[frayREG->CCSV_UN.CCSV_ST.wsv_B3];
1306 Std_ReturnType Fr_TransmitTxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, const uint8_t* Fr_LSduPtr, uint8_t Fr_LSduLength) {
1307 uint32_t word, buffer, index, bufferIndex;
1308 #ifdef DET_ACTIVATED
1309 if (Fr_CtrlIdx != 0) {
1312 if (Fr_LPduIdx > cSlotIDMax) {
1315 if (Fr_LSduPtr == NULL) {
1318 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1323 /* Find the index of the buffer in configuration data array */
1324 for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1325 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1326 if (Fr_BuffersConfigured[bufferIndex] == TRUE && Fr_buffer_slot_map[bufferIndex].buffer_ptr->isTx == TRUE) { // Buffer was configured already and is TX
1327 memset((void *)frayREG->WRDS, 0, sizeof(frayREG->WRDS));
1328 for (word = 0; word < (Fr_LSduLength+3)/4; word++) {
1330 buffer = Fr_LSduPtr[index++];
1331 buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 8 : 0;
1332 buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 16 : 0;
1333 buffer |= (index < Fr_LSduLength) ? Fr_LSduPtr[index++] << 24 : 0;
1334 frayREG->WRDS[word] = buffer;
1336 Fr_buffer_transmit_data(bufferIndex);
1344 Std_ReturnType Fr_CancelTxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1345 uint8_t bufferIndex;
1347 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1348 #ifdef DET_ACTIVATED
1349 boolean_t canceled = FALSE;
1350 if (Fr_CtrlIdx != 0) {
1353 if (Fr_LPduIdx > cSlotIDMax) {
1356 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1359 if (Fr_Config->msgRAMConfig->secureBuffers != FR_SB_RECONFIG_ENABLED) {
1364 /* If bit IBCM.STXR in the input buffer command mask register is set (STXR = 1), the transmission request
1365 * flag TXR of the selected message buffer is automatically set after the message buffer has been updated.
1366 * If bit IBCM.STXR in the input buffer command mask register is reset (STXR = 0), the transmission request
1367 * flag TXR of the selected message buffer is reset. This can be used to stop transmission from message
1368 * buffers operated in continuous mode.
1372 * Write the same configuration into buffer headers with TXREQ disabled.
1374 for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1375 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1376 if (Fr_BuffersConfigured[bufferIndex] == TRUE) { // Buffer was already configured
1377 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1378 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1379 if (buffer_cfg_ptr->isTx == TRUE) {
1380 Fr_config_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering, buffer_cfg_ptr->slotId, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1381 #ifdef DET_ACTIVATED
1389 #ifdef DET_ACTIVATED
1390 return (canceled == TRUE) ? E_OK : E_NOT_OK;
1396 Std_ReturnType Fr_ReceiveRxLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, uint8_t* Fr_LSduPtr, Fr_RxLPduStatusType* Fr_LPduStatusPtr, uint8_t* Fr_LSduLengthPtr) {
1397 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};
1398 uint32_t bufferIndex;
1400 boolean_t bufferFound = FALSE;
1401 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1402 #define fifo_not_empty (frayREG->FSR_UN.FSR_ST.rfne_B1 == 1) // Macro that makes the code more readable, is undefined at the end of the function
1404 #ifdef DET_ACTIVATED
1405 if (Fr_CtrlIdx != 0) {
1408 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1411 if (Fr_LPduIdx > cSlotIDMax) {
1414 if (Fr_LSduPtr == NULL) {
1417 if (Fr_LPduStatusPtr == NULL) {
1420 if (Fr_LSduLengthPtr == NULL) {
1424 /* Find the index of the buffer in configuration data array */
1425 *Fr_LSduLengthPtr = 0;
1426 *Fr_LPduStatusPtr = FR_NOT_RECEIVED;
1429 * Try to find new message in static and dynamic segment buffers at first:
1430 * - Check New Data flag, if no new data received, return.
1431 * - Load received data and header into the output buffer.
1432 * - Store loaded payload from header of the output buffer.
1433 * - Copy data from the output buffer to the Fr_LSduPtr address.
1434 * If no new message has been retrieved, there is possibility that
1435 * RX FIFO buffer has received it (for example when static or dynamic
1436 * segment buffers has rejection filter for channel A, but FIFO for channel B).
1437 * - Check if the Fr_LPduIdx can be accepted by the RX FIFO (FID combined with the mask.
1438 * - Check if the FIFO is not empty
1439 * - Pop data and header into an output buffer.
1440 * - Detect if more data is available in the FIFO and set Fr_LPduStatusPtr.
1441 * - Store loaded payload from header of the output buffer.
1442 * - Copy data from the output buffer to the Fr_LSduPtr address.
1444 for (bufferIndex = 0; bufferIndex < frayREG->MRC_UN.MRC_ST.ffb_B8; bufferIndex++) { // Static and dynamic segment buffers
1445 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1446 if (Fr_BuffersConfigured[bufferIndex] == TRUE) { // Buffer was configured already
1448 if (*ndat[bufferIndex/32] & (0x1 << bufferIndex%32)) { // New data received
1449 Fr_buffer_receive_data_header(bufferIndex); // Read data and header into output buffer
1450 *Fr_LPduStatusPtr = FR_RECEIVED;
1451 break; // Buffer which received a message has been found, other buffers are irrelevant. According the FlexRay specification the buffer with lowest index has the highest priority.
1456 if (*Fr_LPduStatusPtr == FR_NOT_RECEIVED) { // No message was received, try the FIFO.
1457 bufferIndex = frayREG->MRC_UN.MRC_ST.ffb_B8;
1458 if (Fr_BuffersConfigured[bufferIndex] == FALSE)
1459 return E_NOT_OK; // No FIFO configured
1460 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1461 if ((Fr_LPduIdx & (~buffer_cfg_ptr->fidMask)) != (buffer_cfg_ptr->slotId & (~buffer_cfg_ptr->fidMask)) ) {
1463 if (fifo_not_empty) { // The RX FIFO buffer is not empty
1464 Fr_buffer_receive_data_header(bufferIndex); // Consume first element from FIFO
1465 if (fifo_not_empty) // FIFO not empty after last pop
1466 *Fr_LPduStatusPtr = FR_RECEIVED_MORE_DATA_AVAILABLE;
1467 else // FIFO empty after last pop
1468 *Fr_LPduStatusPtr = FR_RECEIVED;
1474 * Copy data from output register into address from parameter Fr_LSduPtr.
1475 * Data in the output register are 32b words,
1476 * Data in Fr_LSduPtr are 8b words.
1478 *Fr_LSduLengthPtr = frayREG->RDHS2_UN.RDHS2_ST.plr_B7*2; // Number of bytes copied into Fr_LSduPtr
1479 for (byte = 0, word = 0; word < *Fr_LSduLengthPtr/4; word++) {
1480 Fr_LSduPtr[byte++] = frayREG->RDDS[word] & 0xFF;
1481 Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF00) >> 8;
1482 Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF0000) >> 16;
1483 Fr_LSduPtr[byte++] = (frayREG->RDDS[word] & 0xFF000000) >> 24;
1486 return (bufferFound == TRUE) ? E_OK: E_NOT_OK;
1487 #undef fifo_not_empty
1490 Std_ReturnType Fr_CheckTxLPduStatus(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx, Fr_TxLPduStatusType* Fr_TxLPduStatusPtr) {
1491 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};
1492 uint8_t bufferIndex;
1493 #ifdef DET_ACTIVATED
1494 if (Fr_CtrlIdx != 0) {
1497 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1500 if (Fr_LPduIdx > cSlotIDMax) {
1503 if (Fr_TxLPduStatusPtr == NULL) {
1507 for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1508 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1509 if (Fr_BuffersConfigured[bufferIndex] == TRUE) { // Buffer was configured already
1510 if (Fr_buffer_slot_map[bufferIndex].buffer_ptr->isTx == TRUE) {
1511 if (*txrq[bufferIndex/32] & (0x1 << bufferIndex%32)) { // Transmit request is pending
1512 *Fr_TxLPduStatusPtr = FR_NOT_TRANSMITTED;
1515 *Fr_TxLPduStatusPtr = FR_TRANSMITTED;
1525 Std_ReturnType Fr_PrepareLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1526 uint32_t bufferIndex;
1528 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1530 #ifdef DET_ACTIVATED
1531 if (Fr_CtrlIdx != 0) {
1534 if (Fr_DrvState < FR_ST_DRV_INITIALIZED) {
1537 if (Fr_LPduIdx > cSlotIDMax) {
1541 /* Find the index of the buffer in configuration data array */
1542 for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1543 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1544 if (Fr_BuffersConfigured[bufferIndex] == FALSE) { // Buffer was not yet configured
1545 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1546 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1547 Fr_MsgRAMDataPtrs[bufferIndex] = Fr_MsgRAMDataOffset;
1548 if (bufferIndex >= frayREG->MRC_UN.MRC_ST.ffb_B8) { // This is RX FIFO buffer
1549 Fr_configure_fifo_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering, buffer_cfg_ptr->slotId, buffer_cfg_ptr->fidMask, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1551 else { // Static/dynamic segment buffer
1552 Fr_config_buffer(bufferIndex, mode, buffer_cfg_ptr->cycleCounterFiltering, buffer_cfg_ptr->slotId, buffer_cfg_ptr->maxPayload, Fr_MsgRAMDataPtrs[bufferIndex]);
1555 * Calculate new address.
1556 * Payload contains the number of two-bytes words, Fr_MsgRAMDataPtrs contains addresses of 4B words in message RAM, all msgRAM addresses have
1558 * Offset has to be divided by two each time because payload is in 2B words and msgRAM addresses are in 4B words.
1560 Fr_MsgRAMDataOffset += ((buffer_cfg_ptr->maxPayload)%2U == 0U ? (buffer_cfg_ptr->maxPayload) : ((buffer_cfg_ptr->maxPayload)+1U))/2;
1561 Fr_BuffersConfigured[bufferIndex] = TRUE;
1568 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) {
1569 uint32_t bufferIndex;
1570 int lowest_index = 0;
1571 uint8_t highest_index = frayREG->MRC_UN.MRC_ST.ffb_B8;
1573 const Fr_TMS570LS_BufferConfigType* buffer_cfg_ptr;
1575 #ifdef DET_ACTIVATED
1576 boolean_t reconfigured = FALSE;
1577 if (Fr_CtrlIdx != 0) {
1580 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1584 lowest_index = Fr_reconfigurable_buffer_index();
1585 if (lowest_index == -1)
1586 return E_NOT_OK | ERR_PARAM_RECONFIG_NOT_ALLOWED;
1587 if (Fr_FrameId == 0) {
1588 return E_NOT_OK | ERR_PARAM_INVALID_FRAME_ID;
1590 if (Fr_FrameId > Fr_Config->clusterConfiguration->gNumberOfStaticSlots &&
1591 Fr_ChnlIdx == FR_CHANNEL_AB) {
1592 return E_NOT_OK | ERR_PARAM_INVALID_CHANNEL;
1595 for (bufferIndex = lowest_index; bufferIndex < highest_index; bufferIndex++) {
1596 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1597 if (Fr_BuffersConfigured[bufferIndex] == TRUE) { // Buffer was configured already
1598 buffer_cfg_ptr = Fr_buffer_slot_map[bufferIndex].buffer_ptr;
1599 if (Fr_PayloadLength > buffer_cfg_ptr->maxPayload) {
1600 return E_NOT_OK | ERR_PARAM_PAYLOAD_TOO_BIG;
1602 Fr_buffer_slot_map[bufferIndex].slot_id = Fr_FrameId;
1603 mode = Fr_buffer_config_flags(buffer_cfg_ptr, bufferIndex);
1604 Fr_config_buffer(bufferIndex, mode, Fr_CycleFiltering, Fr_FrameId, Fr_PayloadLength, Fr_MsgRAMDataPtrs[bufferIndex]);
1605 #ifdef DET_ACTIVATED
1606 reconfigured = TRUE;
1612 #ifdef DET_ACTIVATED
1613 if (reconfigured == FALSE)
1614 return E_NOT_OK | ERR_PARAM_NO_BUFFER_FOUND;
1619 Std_ReturnType Fr_DisableLPdu(uint8_t Fr_CtrlIdx, uint16_t Fr_LPduIdx) {
1620 uint8_t bufferIndexLimit;
1621 uint8_t bufferIndex;
1624 #ifdef DET_ACTIVATED
1625 boolean_t disabled = FALSE;
1626 if (Fr_CtrlIdx != 0) {
1629 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1632 if (Fr_LPduIdx > cSlotIDMax) {
1635 if (Fr_Config->msgRAMConfig->secureBuffers != FR_SB_RECONFIG_ENABLED) {
1639 /* Determine reconfigurable buffers from the data in MRC.SET bits */
1640 switch (frayREG->MRC_UN.MRC_ST.sec_B2) {
1642 bufferIndexLimit = frayREG->MRC_UN.MRC_ST.ffb_B8;
1645 bufferIndexLimit = frayREG->MRC_UN.MRC_ST.fdb_B8;
1648 return E_OK; // No reconfiguration enabled
1651 /* Find the index of the buffer in configuration data array */
1652 for (bufferIndex = 0; bufferIndex <= frayREG->MRC_UN.MRC_ST.lcb_B8; bufferIndex++) {
1653 if (Fr_buffer_slot_map[bufferIndex].slot_id == Fr_LPduIdx) {
1654 if (Fr_BuffersConfigured[bufferIndex] == TRUE) { // Buffer was not yet configured
1655 lowest_index = Fr_reconfigurable_buffer_index();
1656 if (lowest_index == -1) // Reconfiguration disabled
1658 if (bufferIndex < lowest_index)
1660 if (bufferIndex < bufferIndexLimit) { // Buffer is reconfigurable, reset its configuration registers.
1662 Fr_MsgRAMDataPtrs[bufferIndex] = 0;
1663 Fr_BuffersConfigured[bufferIndex] = FALSE;
1664 Fr_config_buffer(bufferIndex, mode, Fr_buffer_slot_map[bufferIndex].buffer_ptr->cycleCounterFiltering,
1665 Fr_buffer_slot_map[bufferIndex].buffer_ptr->slotId,
1666 Fr_buffer_slot_map[bufferIndex].buffer_ptr->maxPayload,
1667 Fr_MsgRAMDataPtrs[bufferIndex]);
1668 #ifdef DET_ACTIVATED
1675 #ifdef DET_ACTIVATED
1676 return (disabled == TRUE) ? E_OK : E_NOT_OK;
1682 Std_ReturnType Fr_GetGlobalTime(uint8_t Fr_CtrlIdx, uint8_t* Fr_CyclePtr, uint16_t* Fr_MacroTickPtr) {
1683 #ifdef DET_ACTIVATED
1684 if (Fr_CtrlIdx != 0) {
1687 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1690 if (Fr_CyclePtr == NULL) {
1693 if (Fr_MacroTickPtr == NULL) {
1697 uint32_t time = frayREG->MTCCV_UN.MTCCV_UL;
1698 *Fr_CyclePtr = __mfld2val(MTCCV_CCV_MSK, time);
1699 *Fr_MacroTickPtr = __mfld2val(MTCCV_MTV_MSK, time);
1703 static inline uint32_t swap32(uint32_t x)
1705 return (x & 0x000000ff) << 24 |
1706 (x & 0x0000ff00) << 8 |
1707 (x & 0x00ff0000) >> 8 |
1708 (x & 0xff000000) >> 24;
1711 Std_ReturnType Fr_GetNmVector(uint8_t Fr_CtrlIdx, uint8_t* Fr_NmVectorPtr) {
1712 #ifdef DET_ACTIVATED
1713 if (Fr_CtrlIdx != 0) {
1716 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1719 if (Fr_NmVectorPtr == NULL) {
1723 *((uint32_t*)(Fr_NmVectorPtr+0)) = swap32(frayREG->NMV1_UN.NMV1_UL);
1724 *((uint32_t*)(Fr_NmVectorPtr+4)) = swap32(frayREG->NMV2_UN.NMV2_UL);
1725 *((uint32_t*)(Fr_NmVectorPtr+8)) = swap32(frayREG->NMV3_UL);
1729 Std_ReturnType Fr_GetNumOfStartupFrames(uint8_t Fr_CtrlIdx, uint8_t* Fr_NumOfStartupFramesPtr) {
1730 /* TODO: Implement - can not find this information in the datasheet */
1734 Std_ReturnType Fr_GetChannelStatus(uint8_t Fr_CtrlIdx, uint16_t* Fr_ChannelAStatusPtr, uint16_t* Fr_ChannelBStatusPtr) {
1735 #ifdef DET_ACTIVATED
1736 if (Fr_CtrlIdx != 0) {
1739 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1742 if (Fr_ChannelAStatusPtr == NULL) {
1745 if (Fr_ChannelBStatusPtr == NULL) {
1749 *Fr_ChannelAStatusPtr = 0;
1750 *Fr_ChannelBStatusPtr = 0;
1752 *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.vfra_B1;
1753 *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.seda_B1 << 1;
1754 *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.ceda_B1 << 2;
1755 *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.cia_B1 << 3;
1756 *Fr_ChannelAStatusPtr |= frayREG->ACS_UN.ACS_ST.sbva_B1 << 4;
1757 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.mtsa_B1 << 8;
1758 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sesa_B1 << 9;
1759 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbsa_B1 << 10;
1760 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.tcsa_B1 << 11;
1761 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sena_B1 << 12;
1762 *Fr_ChannelAStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbna_B1 << 13;
1764 *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.vfrb_B1;
1765 *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.sedb_B1 << 1;
1766 *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.cedb_B1 << 2;
1767 *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.cib_B1 << 3;
1768 *Fr_ChannelBStatusPtr |= frayREG->ACS_UN.ACS_ST.sbvb_B1 << 4;
1769 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.mtsb_B1 << 8;
1770 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sesb_B1 << 9;
1771 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbsb_B1 << 10;
1772 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.tcsb_B1 << 11;
1773 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.senb_B1 << 12;
1774 *Fr_ChannelBStatusPtr |= frayREG->SWNIT_UN.SWNIT_ST.sbnb_B1 << 13;
1779 Std_ReturnType Fr_GetClockCorrection(uint8_t Fr_CtrlIdx, int16_t* Fr_RateCorrectionPtr, int32_t* Fr_OffsetCorrectionPtr) {
1780 #ifdef DET_ACTIVATED
1781 if (Fr_CtrlIdx != 0) {
1784 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1787 if (Fr_RateCorrectionPtr == NULL) {
1790 if (Fr_OffsetCorrectionPtr == NULL) {
1794 *Fr_RateCorrectionPtr = frayREG->RCV_UN.RCV_ST.rcv_B12;
1795 *Fr_OffsetCorrectionPtr = frayREG->OCV_UN.OCV_ST.ocv_B14;
1800 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) {
1804 #ifdef DET_ACTIVATED
1805 if (Fr_CtrlIdx != 0) {
1808 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1811 if (Fr_ChannelAEvenListPtr == NULL) {
1814 if (Fr_ChannelBEvenListPtr == NULL) {
1817 if (Fr_ChannelAOddListPtr == NULL) {
1820 if (Fr_ChannelBOddListPtr == NULL) {
1825 if (Fr_ListSize > FR_MAX_SYNC_FRAME_LIST_SIZE) { // Limit list size to 15
1826 Fr_ListSize = FR_MAX_SYNC_FRAME_LIST_SIZE;
1829 for (i = 0; i < Fr_ListSize; i++) {
1830 esid = frayREG->ESID_UL[i];
1831 osid = frayREG->OSID_UL[i];
1833 Fr_ChannelAEvenListPtr[i] = (__mfld2val(ESID_RXEA_MSK, esid) == 1) ? __mfld2val(ESID_EID_MSK, esid) : 0;
1834 Fr_ChannelBEvenListPtr[i] = (__mfld2val(ESID_RXEB_MSK, esid) == 1) ? __mfld2val(ESID_EID_MSK, esid) : 0;
1835 Fr_ChannelAOddListPtr[i] = (__mfld2val(OSID_RXOA_MSK, osid) == 1) ? __mfld2val(OSID_OID_MSK, osid) : 0;
1836 Fr_ChannelBOddListPtr[i] = (__mfld2val(OSID_RXOB_MSK, osid) == 1) ? __mfld2val(OSID_OID_MSK, osid) : 0;
1839 for (i = Fr_ListSize; i < 15; i++) {
1840 Fr_ChannelAEvenListPtr[i] = 0;
1841 Fr_ChannelBEvenListPtr[i] = 0;
1842 Fr_ChannelAOddListPtr[i] = 0;
1843 Fr_ChannelBOddListPtr[i] = 0;
1849 Std_ReturnType Fr_GetWakeupRxStatus(uint8_t Fr_CtrlIdx, uint8_t* Fr_WakeupRxStatusPtr) {
1850 #ifdef DET_ACTIVATED
1851 if (Fr_CtrlIdx != 0) {
1854 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1857 if (Fr_WakeupRxStatusPtr == NULL) {
1862 *Fr_WakeupRxStatusPtr = 0;
1863 *Fr_WakeupRxStatusPtr |= frayREG->SIR_UN.SIR_ST.wupa_B1;
1864 *Fr_WakeupRxStatusPtr |= frayREG->SIR_UN.SIR_ST.wupb_B1 << 1;
1866 frayREG->SIR_UN.SIR_ST.wupa_B1 = 1;
1867 frayREG->SIR_UN.SIR_ST.wupb_B1 = 1;
1871 Std_ReturnType Fr_SetAbsoluteTimer(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx, uint8_t Fr_Cycle, uint16_t Fr_Offset) {
1872 #ifdef DET_ACTIVATED
1873 if (Fr_CtrlIdx != 0) {
1876 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1879 if (Fr_AbsTimerIdx > 1) {
1882 if (Fr_Offset > Fr_Config->clusterConfiguration->gMacroPerCycle) {
1885 if (Fr_Cycle & 0x80) {
1889 if (Fr_AbsTimerIdx == 0) {
1890 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 0;
1891 frayREG->T0C_UN.T0C_ST.t0ms_B1 = 1;
1892 frayREG->T0C_UN.T0C_ST.t0cc_B7 = Fr_Cycle;
1893 frayREG->T0C_UN.T0C_ST.t0mo_B14 = Fr_Offset;
1894 frayREG->SIR_UN.SIR_ST.ti0_B1 = 1; // Reset interrupt
1895 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 1;
1897 else if (Fr_AbsTimerIdx == 1) {
1898 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 0;
1899 frayREG->T1C_UN.T1C_ST.t1ms_B1 = 1;
1900 frayREG->T1C_UN.T1C_ST.t1mc_B14 = Fr_Cycle*Fr_Config->clusterConfiguration->gMacroPerCycle+Fr_Offset;
1901 frayREG->SIR_UN.SIR_ST.ti1_B1 = 1;// Reset interrupt
1902 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 1;
1911 Std_ReturnType Fr_CancelAbsoluteTimer(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1912 #ifdef DET_ACTIVATED
1913 if (Fr_CtrlIdx != 0) {
1916 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1919 if (Fr_AbsTimerIdx > 1) {
1923 if (Fr_AbsTimerIdx == 0) {
1924 frayREG->T0C_UN.T0C_ST.t0rc_B1 = 0;
1926 else if (Fr_AbsTimerIdx == 1) {
1927 frayREG->T1C_UN.T1C_ST.t1rc_B1 = 0;
1935 Std_ReturnType Fr_EnableAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1936 #ifdef DET_ACTIVATED
1937 if (Fr_CtrlIdx != 0) {
1940 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1943 if (Fr_AbsTimerIdx > 1) {
1947 frayREG->ILE_UN.ILE_ST.eint0_B1 = 1;
1948 if (Fr_AbsTimerIdx == 0) {
1949 frayREG->SIES_UN.SIES_ST.ti0e_B1 = 1;
1951 else if (Fr_AbsTimerIdx == 1) {
1952 frayREG->SIES_UN.SIES_ST.ti0e_B1 = 1;
1960 Std_ReturnType Fr_AckAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1961 #ifdef DET_ACTIVATED
1962 if (Fr_CtrlIdx != 0) {
1965 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1968 if (Fr_AbsTimerIdx > 1) {
1972 if (Fr_AbsTimerIdx == 0) {
1973 frayREG->SIR_UN.SIR_ST.ti0_B1 = 1;
1975 else if (Fr_AbsTimerIdx == 1) {
1976 frayREG->SIR_UN.SIR_ST.ti1_B1 = 1;
1984 Std_ReturnType Fr_DisableAbsoluteTimerIRQ(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx) {
1985 #ifdef DET_ACTIVATED
1986 if (Fr_CtrlIdx != 0) {
1989 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
1992 if (Fr_AbsTimerIdx > 1) {
1996 if (Fr_AbsTimerIdx == 0) {
1997 frayREG->SIER_UN.SIER_ST.ti0e_B1 = 1;
1999 else if (Fr_AbsTimerIdx == 1) {
2000 frayREG->SIER_UN.SIER_ST.ti0e_B1 = 1;
2008 Std_ReturnType Fr_GetAbsoluteTimerIRQStatus(uint8_t Fr_CtrlIdx, uint8_t Fr_AbsTimerIdx, boolean_t* Fr_IRQStatusPtr) {
2009 #ifdef DET_ACTIVATED
2010 if (Fr_CtrlIdx != 0) {
2013 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
2016 if (Fr_AbsTimerIdx > 1) {
2019 if (Fr_IRQStatusPtr == NULL) {
2023 if (Fr_AbsTimerIdx == 0) {
2024 *Fr_IRQStatusPtr = (frayREG->SIR_UN.SIR_ST.ti0_B1 == 1) ? TRUE : FALSE;
2026 else if (Fr_AbsTimerIdx == 1) {
2027 *Fr_IRQStatusPtr = (frayREG->SIR_UN.SIR_ST.ti1_B1 == 1) ? TRUE : FALSE;
2035 void Fr_GetVersionInfo(Std_VersionInfoType* VersioninfoPtr) {
2036 #ifdef DET_ACTIVATED
2037 if (VersioninfoPtr == NULL) {
2041 VersioninfoPtr->vendorID = Fr_versionInfo.vendorID;
2042 VersioninfoPtr->moduleID = Fr_versionInfo.moduleID;
2043 VersioninfoPtr->sw_major_version = Fr_versionInfo.sw_major_version;
2044 VersioninfoPtr->sw_minor_version= Fr_versionInfo.sw_minor_version;
2045 VersioninfoPtr->sw_patch_version= Fr_versionInfo.sw_patch_version;
2048 Std_ReturnType Fr_ReadCCConfig( uint8_t Fr_CtrlIdx, uint8_t Fr_ConfigParamIdx, uint32_t* Fr_ConfigParamValuePtr) {
2050 #ifdef DET_ACTIVATED
2051 if (Fr_CtrlIdx != 0) {
2054 if (Fr_ConfigParamIdx >= FR_CIDX_CNT) {
2057 if (Fr_ConfigParamValuePtr == NULL) {
2060 if (Fr_DrvState != FR_ST_CTRL_INITIALIZED) {
2065 *Fr_ConfigParamValuePtr = Fr_ConfigParPtrs[Fr_ConfigParamIdx];
2069 int Fr_spi_transfer(uint8_t port) {
2070 uint32_t commands[2];
2073 if (port > FRAY_NUM_PORTS) return -1;
2074 desc = hal_port_get_dsc(fray_port_names[port], -1);
2075 fray_spi_cmd_sh = fray_spi_cmd;
2076 commands[0] = (fray_spi_cmd_sh & 0xFF00) >> 8;
2077 commands[1] = (fray_spi_cmd_sh & 0xFF);
2079 fray_spi_resp[port] = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
2083 int Fr_spi_response(uint8_t port) {
2084 if (port > FRAY_NUM_PORTS) return -1;
2085 return fray_spi_resp[port];
2088 int Fr_spi_get_cmd(uint8_t port) {
2089 if (port > FRAY_NUM_PORTS) return -1;
2090 return fray_spi_cmd;