#include "drv/fr_tms570.h"
#include "sys/ti_drv_fray.h"
-#include "drv/fray.h"
#include "binary.h"
+#include "hal/port_def.h"
-Std_VersionInfoType Fr_versionInfo = {
+static Std_VersionInfoType Fr_versionInfo = {
.vendorID = 0x00000001,
.moduleID = 0x00000002,
.sw_major_version = 0,
.sw_patch_version = 0
};
+/** Prepared spi command */
+static uint32_t fray_spi_cmd = FRAY_SPICMD_INIT_VAL;
+/** Shadow variable used during command sending */
+static uint32_t fray_spi_cmd_sh;
+/** Array of responses for each fray driver */
+static uint32_t fray_spi_resp[FRAY_NUM_PORTS];
+/** Array of port names to be easily accessible by indexing */
+static const char* fray_port_names[FRAY_NUM_PORTS] = { PORT_NAME_FRAY1, PORT_NAME_FRAY2 };
+/** Array of integers, where FlexRay cluster and node configuration
+ * parameters are stored to be accessible by indexes defined in Fr_GeneralTypes.h.
+ */
static uint32_t Fr_ConfigParPtrs[FR_CIDX_CNT];
-const Fr_ConfigType* Fr_Config;
-const Fr_TMS570LS_BufferConfigType* Fr_BuffersPtrs[FR_MAX_BUFFERS_CNT]; /** < Array of address of configuration data to each buffer. */
-boolean_t Fr_BuffersConfigured[FR_MAX_BUFFERS_CNT]; /**< Array of flags to determine if the buffer was or was not configured. */
-int Fr_MsgRAMDataPtrs[FR_MAX_BUFFERS_CNT]; /**< Array of computed data pointers addresses for each buffer. */
-uint32_t Fr_MsgRAMDataOffset; /**< Address of the next free position in message RAM, which can be assigned to configured buffer. Addresses 32b words. */
-uint32_t Fr_MsgRAMDataStartAddress; /**< Address of the first free position in message RAM, which can be assigned to the first configured buffer. Addresses 32b words. */
+/**
+ * Address of the unified structure with complete configuration of
+ * the FlexRay node (cluster, node, message RAM and buffer configuration)
+ */
+static const Fr_ConfigType* Fr_Config;
+/** Array of address of configuration data to each buffer. */
+static const Fr_TMS570LS_BufferConfigType* Fr_BuffersPtrs[FR_MAX_BUFFERS_CNT];
+/** Array of flags to determine if the buffer was or was not configured. */
+static boolean_t Fr_BuffersConfigured[FR_MAX_BUFFERS_CNT];
+/** Array of computed data pointers addresses for each buffer. */
+static int Fr_MsgRAMDataPtrs[FR_MAX_BUFFERS_CNT];
+/**
+ * Address of the next free position in message RAM, which can be assigned
+ * to configured buffer. Addresses 32b words.
+ */
+static uint32_t Fr_MsgRAMDataOffset;
+/**
+ * Address of the first free position in message RAM, which can be assigned
+ * to the first configured buffer. Addresses 32b words.
+ */
+static uint32_t Fr_MsgRAMDataStartAddress;
+
+/**
+ * Development error detection.
+ * Comment this line to disable error detection and make function processing
+ * faster, but more dangerous.
+ */
+
+#define DET_ACTIVATED
+
+
#ifdef DET_ACTIVATED
-Fr_TMS570LS_DriverState Fr_DrvState = FR_ST_DRV_NOT_INITIALIZED;
+/**
+ * A variable for driver state monitoring. The state value is used in several
+ * functions to determine if they are called in right order.
+ */
+static Fr_TMS570LS_DriverState Fr_DrvState = FR_ST_DRV_NOT_INITIALIZED;
#endif
+/**
+ * Compute CRC for message RAM header data
+ *
+ * @param[in] Fr_LPduPtr Pointer to header data
+ * @return CRC code
+ */
+static int Fr_header_crc_calc(const wrhs *Fr_LPduPtr) {
+ unsigned int header;
+
+ int CrcInit = 0x1A;
+ int length = 20;
+ int CrcNext;
+ unsigned long CrcPoly = 0x385;
+ unsigned long CrcReg_X = CrcInit;
+ unsigned long header_temp, reg_temp;
+
+ header = ((Fr_LPduPtr->sync & 0x1) << 19) | ((Fr_LPduPtr->sfi & 0x1) << 18);
+ header |= ((Fr_LPduPtr->fid & 0x7FF) << 7) | (Fr_LPduPtr->pl & 0x7F);
+
+ header <<= 11;
+ CrcReg_X <<= 21;
+ CrcPoly <<= 21;
+
+ while(length--) {
+ header <<= 1;
+ header_temp = header & 0x80000000;
+ reg_temp = CrcReg_X & 0x80000000;
+
+ if(header_temp ^ reg_temp){ // Step 1
+ CrcNext = 1;
+ } else {
+ CrcNext = 0;
+ }
+
+ CrcReg_X <<= 1; // Step 2
+
+ if(CrcNext) {
+ CrcReg_X ^= CrcPoly; // Step 3
+ }
+ }
+
+ CrcReg_X >>= 21;
+
+ return CrcReg_X;
+}
+
+/**
+ * Retrieve data and header from message buffer into output buffer.
+ *
+ * Upper software layers have to read the header and data from RDDS and RDHS registers.
+ * @param[in] buf_num Number of buffer
+ */
+static void Fr_buffer_receive_data_header(uint32_t buf_num) {
+ bc read_buffer;
+
+ read_buffer.obrs=buf_num; // output buffer number
+ read_buffer.rdss=1; // read data section
+ read_buffer.rhss=1; // read header section
+
+ // ensure no transfer in progress on shadow registers
+ while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
+ frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
+ frayREG->OBCR_UN.OBCR_UL=((1 << 9) | (read_buffer.obrs & 0x3F)); //req=1, view=0
+ // wait for completion on shadow registers
+ while (((frayREG->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
+
+ frayREG->OBCM_UN.OBCM_UL=(((read_buffer.rdss & 0x1) << 1) | (read_buffer.rhss & 0x1));
+ frayREG->OBCR_UN.OBCR_UL=((1 << 8) | (read_buffer.obrs & 0x3F)); //req=0, view=1
+
+}
+
+/**
+ * Transfer data to the message RAM using the input buffer
+ *
+ * @param[in] Fr_LSduPtr Pointer to data structure with input buffer settings
+ */
+inline void Fr_transmit_tx_LPdu(const bc *Fr_LSduPtr) {
+ // ensure nothing is pending
+ while ((frayREG->IBCR_UN.IBCR_UL & 0x0008000) != 0);
+ frayREG->IBCM_UN.IBCM_UL=((Fr_LSduPtr->stxrh & 0x1) << 2) | ((Fr_LSduPtr->ldsh & 0x1) << 1) | (Fr_LSduPtr->lhsh & 0x1);
+ frayREG->IBCR_UN.IBCR_UL=(Fr_LSduPtr->ibrh & 0x3F);
+ // optimization possible for future by not gating like below
+ // wait for completion on host registers
+ while ((Fr_LSduPtr->ibsyh != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x00008000) != 0));
+ // wait for completion on shadow registers
+ while ((Fr_LSduPtr->ibsys != 0) && ((frayREG->IBCR_UN.IBCR_UL & 0x80000000) != 0));
+}
+
+/**
+ * Fill the buffer configuration data structure with given data and transfer it to the message RAM header using the input buffer.
+ *
+ * @param[in] buf_num number of buffer to be configured (0-128)
+ * @param[in] mode Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
+ * @param[in] cyc_filter Setting for cycle filter. 0 - disabled
+ * @param[in] frame_id Id of the frame to be associated with the buffer
+ * @param[in] payload Maximum data size in half-word
+ * @param[in] data_pointer Address of the first word of data in buffer
+ */
+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) {
+ wrhs Fr_LPdu;
+ bc Fr_LSdu;
+ int wrhs1;
+ int wrhs2;
+
+ Fr_LPdu.mbi = (mode&FRAY_BUF_MBI_EN) ? 1 : 0; // message buffer interrupt
+ Fr_LPdu.txm = (mode&FRAY_BUF_TX_MODE_CONTINUOUS) ? 0 : 1; // transmission mode(0=continuous mode, 1=single mode)
+ Fr_LPdu.ppit = (mode&FRAY_BUF_NM_EN) ? 1 : 0; // network management Enable
+ Fr_LPdu.cfg = (mode&FRAY_BUF_TX) ? 1 : 0; // message buffer configuration bit (0=RX, 1 = TX)
+ Fr_LPdu.chb = (mode&FRAY_BUF_CHB_EN) ? 1 : 0; // Ch B
+ Fr_LPdu.cha = (mode&FRAY_BUF_CHA_EN) ? 1 : 0; // Ch A
+ Fr_LPdu.cyc = cyc_filter; // Cycle Filtering Code (no cycle filtering)
+ Fr_LPdu.fid = frame_id; // Frame ID
+
+ // Write Header Section 2 (WRHS2)
+ Fr_LPdu.pl = payload; // Payload Length
+
+ // Write Header Section 3 (WRHS3)
+ Fr_LPdu.dp = data_pointer; // Pointer to start of data in message RAM
+
+ Fr_LPdu.sfi = (mode&FRAY_BUF_SFI_EN) ? 1 : 0; // startup frame indicator
+ Fr_LPdu.sync = (mode&FRAY_BUF_SYNC_EN) ? 1 : 0; // sync frame indicator
+
+ // Write Header Section 2 (WRHS2)
+ Fr_LPdu.crc = (mode&FRAY_BUF_TX) ? Fr_header_crc_calc(&Fr_LPdu) : 0;
+
+ // Input buffer configuration
+ Fr_LSdu.ibrh = buf_num; // input buffer number
+ Fr_LSdu.ibsyh = 1; // check for input buffer busy host
+ Fr_LSdu.ibsys = 1; // check for input buffer busy shadow
+
+ Fr_LSdu.stxrh= (mode&FRAY_BUF_TXREQ_EN) ? 1 : 0; // set transmission request
+ Fr_LSdu.ldsh = 0; // load data section
+ Fr_LSdu.lhsh = 1; // load header section
+ Fr_LSdu.obrs = 0; // output buffer number
+ Fr_LSdu.rdss = 0; // read data section
+ Fr_LSdu.rhss = 0; // read header section
+
+ wrhs1 = ((Fr_LPdu.mbi) & 0x1) <<29;
+ wrhs1 |= (Fr_LPdu.txm & 0x1) << 28;
+ wrhs1 |= (Fr_LPdu.ppit & 0x1) << 27;
+ wrhs1 |= (Fr_LPdu.cfg & 0x1) << 26;
+ wrhs1 |= (Fr_LPdu.chb & 0x1) << 25;
+ wrhs1 |= (Fr_LPdu.cha & 0x1) << 24;
+ wrhs1 |= (Fr_LPdu.cyc & 0x7F) << 16;
+ wrhs1 |= (Fr_LPdu.fid & 0x7FF);
+ frayREG->WRHS1_UN.WRHS1_UL = wrhs1;
+
+ wrhs2 = ((Fr_LPdu.pl & 0x7F) << 16) | (Fr_LPdu.crc & 0x7FF);
+ frayREG->WRHS2_UN.WRHS2_UL = wrhs2;
+
+ frayREG->WRHS3_UN.WRHS3_UL = (Fr_LPdu.dp & 0x7FF);
+
+ Fr_transmit_tx_LPdu(&Fr_LSdu);
+}
+
+/**
+ * Fill FIFO filter rejection configuration and configure the buffer.
+ *
+ * @param[in] buf_num number of buffer to be configured (0-128)
+ * @param[in] mode Flag array for buffer configuration. Flags are defined in header file with prefix FRAY_BUF_
+ * @param[in] cyc_filter Setting for cycle filter. 0 - disabled
+ * @param[in] frame_id Id of the frame to be associated with the buffer
+ * @param[in] payload Maximum data size in half-word
+ * @param[in] data_pointer Address of the first word of data in buffer
+ */
+static void Fr_configure_fifo_buffer(uint32_t buf_num, uint16_t mode, uint32_t cyc_filter, uint32_t frame_id, uint32_t payload, uint32_t data_pointer) {
+ frayREG->FRF_UN.FRF_ST.rnf = (mode&FRAY_BUF_REJECT_NULL_FRAMES) ? 1 : 0;
+ frayREG->FRF_UN.FRF_ST.rss = (mode&FRAY_BUF_REJECT_STATIC_SEGMENT) ? 1 : 0;
+ frayREG->FRF_UN.FRF_ST.fid_B11 = frame_id;
+ frayREG->FRFM_UN.FRFM_ST.mfid_B11 = 0x0;
+ frayREG->FRF_UN.FRF_ST.cyf_B7 = cyc_filter;
+ if (mode&FRAY_BUF_CHB_EN && mode&FRAY_BUF_CHA_EN) {
+ frayREG->FRF_UN.FRF_ST.ch_B2 = 0;
+ }
+ else if (mode&FRAY_BUF_CHA_EN) {
+ frayREG->FRF_UN.FRF_ST.ch_B2 = 3;
+ }
+ else {
+ frayREG->FRF_UN.FRF_ST.ch_B2 = 2;
+ }
+ frame_id = 0;
+ Fr_config_buffer(buf_num, mode, cyc_filter, frame_id, payload, data_pointer);
+}
+
+/**
+ * Load data to message buffer. Data must be copied into WRDS register before this function is called.
+ *
+ * @param[in] buf_num Number of buffer
+ * @param[in] len Number of words to be loaded from data to buffer
+ */
+static void Fr_buffer_transmit_data(uint32_t buf_num) {
+ bc write_buffer;
+
+ write_buffer.ibrh = buf_num; // input buffer number
+ write_buffer.stxrh= 1; // set transmission request
+ write_buffer.ldsh = 1; // load data section
+ write_buffer.lhsh = 0; // load header section
+ write_buffer.ibsys = 0; // check for input buffer busy shadow
+ write_buffer.ibsyh = 1; // check for input buffer busy host
+ Fr_transmit_tx_LPdu(&write_buffer);
+}
+
+
/** @fn wait_for_POC_ready(void)
* @brief Wait until POC is not busy
*/
-void Fr_wait_for_POC_ready() {
+inline void Fr_wait_for_POC_ready() {
// Wait for PBSY bit to clear - POC not busy.
// 1: Signals that the POC is busy and cannot accept a command from the host. CMD(3-0) is locked against write accesses.
while(((frayREG->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);
}
+/** @fn clear_msg_ram(void)
+* @brief Clears FRAY message RAMs
+*
+* Send command to POC to set all bits of message RAM to 0.
+* @return SUCCESS or FAILURE when command was not accepted
+*/
+static int Fr_clear_msg_RAM() {
+ Fr_wait_for_POC_ready();
+ frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CLEAR_RAMS;
+ if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) {
+ return FAILURE;
+ }
+ Fr_wait_for_POC_ready();
+ return SUCCESS;
+}
+
+
/**
* @brief Switch POC to config state from any other state
*
*
* @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
*/
-Std_ReturnType Fr_POC_go_to_config() {
+static Std_ReturnType Fr_POC_go_to_config() {
// write SUCC1 configuration
frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CONFIG;
// Check if POC has accepted last command
return E_OK;
}
-/**
- * @brief Switch POC to clear_message_ram state from default_config and config state
- *
- * Send command to POC to set all bits of message RAM to 0. Returns when cleaning is done,
- * resulting in POC switch to origin state.
- *
- * @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
- */
-Std_ReturnType Fr_POC_go_to_clear_rams() {
- Fr_wait_for_POC_ready();
- frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_CLEAR_RAMS;
- if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted) {
- return E_NOT_OK;
- }
- Fr_wait_for_POC_ready();
- return E_OK;
-}
-
/**
* @brief Switch POC to ready state from config state
*
*
* @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
*/
-Std_ReturnType Fr_POC_go_to_ready_from_config() {
+static Std_ReturnType Fr_POC_go_to_ready_from_config() {
Fr_wait_for_POC_ready();
// For CHA and CHB network
if (frayREG->SUCC1_UN.SUCC1_ST.ccha_B1 && frayREG->SUCC1_UN.SUCC1_ST.cchb_B1){
*
* @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
*/
-Std_ReturnType Fr_POC_go_to_ready_from_startup() {
+static Std_ReturnType Fr_POC_go_to_ready_from_startup() {
Fr_wait_for_POC_ready();
frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;
if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
*
* @return E_OK: Call finished successfuly. E_NOT_OK: POC has not accepted command.
*/
-Std_ReturnType Fr_POC_go_to_startup() {
+static Std_ReturnType Fr_POC_go_to_startup() {
Fr_wait_for_POC_ready();
frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_RUN;
if (frayREG->SUCC1_UN.SUCC1_ST.cmd_B4 == CMD_command_not_accepted)
}
/* Clear message RAM */
- if (fray_clear_msg_ram() == FAILURE) {
+ if (Fr_clear_msg_RAM() == FAILURE) {
return E_NOT_OK;
}
} while ( (state_value != FR_POCS_NORMAL_ACTIVE) && (state_value != FR_POCS_INTEGRATION_LISTEN));
if (frayREG->CCSV_UN.CCSV_ST.pocs_B6 == FR_POCS_NORMAL_ACTIVE) // Success, break the start up loop
break;
- // fray_delay();
if (Fr_POC_go_to_ready_from_startup() == E_NOT_OK) { // No success. Switch back to READY state
return E_NOT_OK | FR_STARTUP_ERR_SW_STUP_READY;
}
}
frayREG->WRDS[word] = buffer;
}
- fray_buffer_transmit_data(bufferIndex);
+ Fr_buffer_transmit_data(bufferIndex);
return E_OK;
}
}
mode |= (Fr_BuffersPtrs[i]->rejectStaticSegment == TRUE) ? FRAY_BUF_REJECT_STATIC_SEGMENT : FRAY_BUF_ACCEPT_STATIC_SEGMENT;
mode |= FRAY_BUF_TXREQ_DIS;
if (Fr_BuffersPtrs[i]->isTx == TRUE) {
- fray_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
+ Fr_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
#ifdef DET_ACTIVATED
canceled = TRUE;
#endif
*/
// FIXME: Receiving for FID rejection filter other than zero is not working. Why?
if (bufferIndex >= frayREG->MRC_UN.MRC_ST.ffb_B8 && frayREG->FSR_UN.FSR_ST.rfne_B1 == 1) { // This is RX FIFO buffer and it is not empty
- fray_buffer_receive_data_header(frayREG->MRC_UN.MRC_ST.ffb_B8); // Consume first element from FIFO
+ Fr_buffer_receive_data_header(frayREG->MRC_UN.MRC_ST.ffb_B8); // Consume first element from FIFO
if (frayREG->FSR_UN.FSR_ST.rfne_B1 == 1) { // FIFO not empty after last pop
*Fr_LPduStatusPtr = FR_RECEIVED_MORE_DATA_AVAILABLE;
}
}
else { // Static/dynamic segment buffer
if (*ndat[bufferIndex/32] & (0x1 << bufferIndex%32)) { // New data received
- fray_buffer_receive_data_header(bufferIndex); // Read data and header into output buffer
+ Fr_buffer_receive_data_header(bufferIndex); // Read data and header into output buffer
*Fr_LPduStatusPtr = FR_RECEIVED;
}
else { // No new data received
}
Fr_MsgRAMDataPtrs[i] = Fr_MsgRAMDataOffset;
if (i >= frayREG->MRC_UN.MRC_ST.ffb_B8) { // This is RX FIFO buffer
- fray_configure_fifo_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
+ Fr_configure_fifo_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
}
else { // Static/dynamic segment buffer
- fray_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
+ Fr_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
}
/*
* Calculate new address.
mode = 0;
Fr_MsgRAMDataPtrs[i] = 0;
Fr_BuffersConfigured[i] = FALSE;
- fray_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
+ Fr_config_buffer(i, mode, Fr_BuffersPtrs[i]->cycleCounterFiltering, Fr_BuffersPtrs[i]->slotId, Fr_BuffersPtrs[i]->maxPayload, Fr_MsgRAMDataPtrs[i]);
#ifdef DET_ACTIVATED
disabled = TRUE;
#endif
}
Std_ReturnType Fr_ReadCCConfig( uint8_t Fr_CtrlIdx, uint8_t Fr_ConfigParamIdx, uint32_t* Fr_ConfigParamValuePtr) {
+
#ifdef DET_ACTIVATED
if (Fr_CtrlIdx != 0) {
return E_NOT_OK;
*Fr_ConfigParamValuePtr = Fr_ConfigParPtrs[Fr_ConfigParamIdx];
return E_OK;
}
+
+int Fr_spi_transfer(uint8_t port) {
+ uint32_t commands[2];
+ port_desc_t* desc;
+
+ if (port > FRAY_NUM_PORTS) return -1;
+ desc = hal_port_get_dsc(fray_port_names[port], -1);
+ fray_spi_cmd_sh = fray_spi_cmd;
+ commands[0] = (fray_spi_cmd_sh & 0xFF00) >> 8;
+ commands[1] = (fray_spi_cmd_sh & 0xFF);
+
+ fray_spi_resp[port] = desc->port_setfnc_ptr(desc->config, desc->numValues, commands);
+ return 0;
+}
+
+int Fr_spi_response(uint8_t port) {
+ if (port > FRAY_NUM_PORTS) return -1;
+ return fray_spi_resp[port];
+}
+
+int Fr_spi_get_cmd(uint8_t port) {
+ if (port > FRAY_NUM_PORTS) return -1;
+ return fray_spi_cmd;
+}