/************************************************************************** * * Copyright (c) 2019-2019 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file RTC.c * * @date 27-Nov-2019 * @author D. Navaei * * @brief Monitor/Controller Real Time Clock * **************************************************************************/ #include // For calculating epoch #include "Common.h" #include "Timers.h" #include "RTC.h" #include "mibspi.h" // ********** private definitions ********** #define RTC_REG_1_12_HOUR_MODE 0X0004 #define RTC_REG_1_PORO 0X0008 #define RTC_REG_1_CLK_STOPPED 0X0020 #define RTC_REG_1_UNUSED 0X0040 #define RTC_REG_1_EXT_CLK_MODE 0X0080 #define RTC_REG_2_MASK 0X0000 #define RTC_REG_3_MASK 0X0008 // RTC registers indices #define RTC_REG_1_INDEX 1 #define RTC_REG_2_INDEX 2 #define RTC_REG_3_INDEX 3 #define RTC_SECONDS_INDEX 4 #define RTC_MINUTES_INDEX 5 #define RTC_HOURS_INDEX 6 #define RTC_DAYS_INDEX 7 #define RTC_WEEKDAYS_INDEX 8 #define RTC_MONTHS_INDEX 9 #define RTC_YEARS_INDEX 10 // *************** MibSPI values ************* // #define MIBSPI_MAX_BUFFER_LENGTH 127U #define MIBSPI_CONTINUOUS_MODE 4U #define MIBSPI_CHIP_SELECT_ACTIVE 1U #define MIBSPI_CHIP_SELECT_DEACTIVE 0U #define MIBSPI_NO_WDELAY 0U #define MIBSPI_LOCK_TG 0U #define MIBSPI_DATA_FORMAT_ZERO 0U #define MIBSPI_BUFFER_MODE_BIT_SHIFT 13U #define MIBSPI_CHIP_SELECT_BIT_SHIFT 12U #define MIBSPI_NO_WDELAY_BIT_SHIT 10U #define MIBSPI_LOCK_TRANS_BIT_SHIFT 11U #define MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT 8U #define MIBSPI_BUFFER_TRANS_BIT_SHIFT 8U #define RTC_RAM_PREP_BUFFER_LENGTH 3U // This command puts RTC into read mode from // address 0 #define RTC_READ_FROM_REG0 0x00A0 #define RTC_WRITE_TO_REG3 0x0023 // For read or write operations in RAM, 1h and 1Ah // must be sent that becomes 0x003A #define RTC_PREP_RAM_READ_WRITE 0x003A // For write operation in RAM, 1h and 1Ch will // combined to 0x003C #define RTC_WRITE_TO_RAM 0x003C #define RTC_READ_FROM_RAM 0x00BD #define RTC_ACCURACY_TIMEOUT 1000 //ms #define RTC_ACCURACY_TIMEOUT_TOLERANCE 1050 //ms #define TIMER_COUNTER_TO_REQUEST_READ 18 #define MAX_ALLOWED_FAILED_RTC_TRANSFERS 2 #define GENERAL_NUM_OF_ITEMS_TO_READ 11 typedef enum RTC_Self_Test_States { RTC_SELF_TEST_STATE_START = 0, RTC_SELF_TEST_STATE_CHECK_CTRL_REGS, RTC_SELF_TEST_STATE_COMPARE_SECONDS, RTC_SELF_TEST_STATE_CHECK_ACCURACY, RTC_SELF_TEST_STATE_COMPLETE } RTC_SELF_TEST_STATE_T; typedef enum RTC_Read_Data { RTC_SEND_COMMAND = 0, RTC_WAIT_FOR_TRANSFER_AND_READ, RTC_SERVICE_COMPLETE } RTC_GET_DATA_STATE_T; typedef enum RTC_Exec_State { RTC_EXEC_STATE_WAIT_FOR_POST = 0, RTC_EXEC_STATE_IDLE, RTC_EXEC_STATE_PREP_RAM, RTC_EXEC_STATE_WRITE_TO_RAM, RTC_EXEC_STATE_READ_FROM_RAM, RTC_EXEC_STATE_READ, RTC_EXEC_STATE_WRITE, RTC_EXEC_STATE_FAULT } RTC_EXEC_STATE_T; static struct RTCReadTimestamp { U16 seconds; U16 minutes; U16 hours; U16 days; U16 weekdays; U16 months; U16 years; } read_ts; static struct RTCWriteTimestamp { U16 seconds; U16 minutes; U16 hours; U16 days; U16 weekdays; U16 months; U16 years; } write_ts; static RTC_SELF_TEST_STATE_T RTCSelfTestState = RTC_SELF_TEST_STATE_START; static RTC_GET_DATA_STATE_T RTCServiceState = RTC_SEND_COMMAND; static RTC_EXEC_STATE_T RTCExecState = RTC_EXEC_STATE_WAIT_FOR_POST; static SELF_TEST_STATUS_T RTCSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; static U32 RTCSelfTestTimer = 0; static U32 RTCPreviousSecond = 0; static U32 timeCounter = 1; static U32 numberOfFailedRTCTransfers = 0; static BOOL hasWriteToRTCRequested = FALSE; static BOOL hasReadFromRTCRequested = FALSE; static BOOL hasWriteToRAMRequested = TRUE; static BOOL hasReadFromRAMRequested = FALSE; static U16 rxBuffer[MIBSPI_MAX_BUFFER_LENGTH + 1]; static U16 txBuffer[MIBSPI_MAX_BUFFER_LENGTH + 1]; // ********** Private functions prototype ********* static BOOL serviceRTC( U16* buffer ); static BOOL isRTCFunctional(); static U08 convertBCD2Decimal( U08 bcd ); static U08 convertDecimal2BCD( U08 decimal ); static U32 convertTime2Epoch(); static void updateReadTimestampStruct(); static RTC_SELF_TEST_STATE_T handleSelfTestStart(); static RTC_SELF_TEST_STATE_T handleSelfTestCheckCtrlRegs(); static RTC_SELF_TEST_STATE_T handleSelfTestCompareSeconds(); static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy(); static RTC_EXEC_STATE_T handleExecIdleState(); static RTC_EXEC_STATE_T handleExecReadState(); static RTC_EXEC_STATE_T handleExecPrepRAMState( U16 address ); static RTC_EXEC_STATE_T handleExecWriteToRAMState( U08* data, U32 length ); static RTC_EXEC_STATE_T handleExecReadFromRAMState( U32 length ); static RTC_EXEC_STATE_T handleExecWriteState(); static BOOL setMibSPIBufferLength( U16 length ); // ********** Public functions ********** void initRTC() { // Do nothing for now } void setRTCTimestamp( U08 secs, U08 mins, U08 hours, U08 days, U08 months, U16 years ) { hasWriteToRTCRequested = TRUE; U16 decimalSeconds = convertDecimal2BCD( secs ); U16 decimalMins = convertDecimal2BCD( mins ); U16 decimalHours = convertDecimal2BCD( hours ); U16 decimalDays = convertDecimal2BCD( days ); U16 decimalMonths = convertDecimal2BCD( months ); U16 decimalYears = convertDecimal2BCD( years - 2000 ); write_ts.seconds = decimalSeconds; write_ts.minutes = decimalMins; write_ts.hours = decimalHours; write_ts.days = decimalDays; write_ts.weekdays = 0; // Weekdays will not be used write_ts.months = decimalMonths; write_ts.years = decimalYears; } SELF_TEST_STATUS_T execRTCSelfTest( void ) { switch ( RTCSelfTestState ) { case RTC_SELF_TEST_STATE_START: RTCSelfTestState = handleSelfTestStart(); break; case RTC_SELF_TEST_STATE_CHECK_CTRL_REGS: RTCSelfTestState = handleSelfTestCheckCtrlRegs(); break; case RTC_SELF_TEST_STATE_COMPARE_SECONDS: RTCSelfTestState = handleSelfTestCompareSeconds(); break; case RTC_SELF_TEST_STATE_CHECK_ACCURACY: RTCSelfTestState = handleSelfTestCheckAccuracy(); break; case RTC_SELF_TEST_STATE_COMPLETE: break; default: // TODO: Add the alarms RTCSelfTestResult = SELF_TEST_STATUS_FAILED; break; } return RTCSelfTestResult; } void execRTC() { // FOR DEBUGGING PURPOSES ONLY U08 address; U08 data[8]; U32 length; address = 12; data[0] = 4; data[1] = 5; data[2] = 6; data[3] = 71; data[4] = 8; data[5] = 9; data[6] = 13; data[7] = 115; length = sizeof(data); // FOR DEBUGGING PURPOSED ONLY switch ( RTCExecState ) { case RTC_EXEC_STATE_WAIT_FOR_POST: if ( RTCSelfTestState == RTC_SELF_TEST_STATE_COMPLETE && RTCSelfTestResult == SELF_TEST_STATUS_PASSED ) { RTCExecState = RTC_EXEC_STATE_IDLE; } else if ( RTCSelfTestState == RTC_SELF_TEST_STATE_COMPLETE && RTCSelfTestResult == SELF_TEST_STATUS_FAILED ) { RTCExecState = RTC_EXEC_STATE_FAULT; } break; case RTC_EXEC_STATE_IDLE: RTCExecState = handleExecIdleState(); break; case RTC_EXEC_STATE_PREP_RAM: RTCExecState = handleExecPrepRAMState( address ); break; case RTC_EXEC_STATE_WRITE_TO_RAM: RTCExecState = handleExecWriteToRAMState( &data[0], length ); break; case RTC_EXEC_STATE_READ_FROM_RAM: RTCExecState = handleExecReadFromRAMState( length ); break; case RTC_EXEC_STATE_WRITE: RTCExecState = handleExecWriteState(); break; case RTC_EXEC_STATE_READ: RTCExecState = handleExecReadState(); break; case RTC_EXEC_STATE_FAULT: // Something failed set the alarms // TODO: set the alarms and stuff break; default: break; } } U32 getRTCTimestamp() { hasReadFromRTCRequested = TRUE; U32 timestamp = convertTime2Epoch(); hasReadFromRTCRequested = FALSE; return timestamp; } void writeToRAM( U16 address, U08* data, U32 length ) { hasWriteToRAMRequested = TRUE; } // ********** Private functions ********* static BOOL serviceRTC( U16* buffer ) { BOOL result = FALSE; switch ( RTCServiceState ) { case RTC_SEND_COMMAND: mibspiSetData(mibspiREG3, 0, buffer); mibspiTransfer(mibspiREG3, 0); RTCServiceState = RTC_WAIT_FOR_TRANSFER_AND_READ; break; case RTC_WAIT_FOR_TRANSFER_AND_READ: if ( mibspiIsTransferComplete(mibspiREG3, 0) ) { mibspiGetData(mibspiREG3, 0, rxBuffer); RTCServiceState = RTC_SERVICE_COMPLETE; result = TRUE; } else if ( numberOfFailedRTCTransfers >= MAX_ALLOWED_FAILED_RTC_TRANSFERS ) { RTCServiceState = RTC_SERVICE_COMPLETE; } else { // Transfer to RTC failed. This transfer // should be done in 50ms numberOfFailedRTCTransfers++; RTCServiceState = RTC_SEND_COMMAND; } break; case RTC_SERVICE_COMPLETE: // Done with reading and transfer do nothing break; default: // We should never get here break; } return result; } static BOOL isRTCFunctional() { BOOL hasTestPassed = TRUE; U16 controlReg1 = rxBuffer[RTC_REG_1_INDEX]; U16 controlReg2 = rxBuffer[RTC_REG_2_INDEX]; U16 controlReg3 = rxBuffer[RTC_REG_2_INDEX]; if ( ! controlReg1 & RTC_REG_1_12_HOUR_MODE ) { // Set the alarm for 24 hour mode hasTestPassed = FALSE; } if ( ! controlReg1 & RTC_REG_1_PORO ) { // Set the alarm for PORO low mode hasTestPassed = FALSE; } if ( ! controlReg1 & RTC_REG_1_CLK_STOPPED ) { // Set the alarm for clock stopped mode hasTestPassed = FALSE; } if ( ! controlReg1 & RTC_REG_1_UNUSED ) { // Set the alarm for unused bit set to 1 mode hasTestPassed = FALSE; } if ( ! controlReg1 & RTC_REG_1_EXT_CLK_MODE ) { // Set the alarm for clock set on external mode hasTestPassed = FALSE; } if ( ! controlReg2 & RTC_REG_2_MASK ) { // Set the alarm for register 2 hasTestPassed = FALSE; } if ( ! controlReg3 & RTC_REG_3_MASK ) { // Set the alarm for register 3 hasTestPassed = FALSE; } return hasTestPassed; } static U08 convertBCD2Decimal( U08 bcd ) { U08 bcdHigh; U08 bcdLow; U08 decimal; bcdHigh = ( bcd & 0xF0 ) >> 4; bcdLow = ( bcd & 0x0F ); decimal = ( bcdHigh * 10 ) + bcdLow; return decimal; } static U08 convertDecimal2BCD( U08 decimal ) { U08 decimalHigh; U08 decimalLow; U08 bcd; // Assuming all the decimal provided // are maximum 2 digits decimalHigh = decimal / 10; decimalLow = decimal % 10; bcd = (decimalHigh << 4) + decimalLow; return bcd; } static U32 convertTime2Epoch() { struct tm t; time_t epochTime; t.tm_sec = read_ts.seconds; t.tm_min = read_ts.minutes; t.tm_hour = read_ts.hours; t.tm_mday = read_ts.days; t.tm_mon = read_ts.months - 1; t.tm_year = read_ts.years + 2000 - 1970; epochTime = mktime(&t); return (U32)epochTime; } static void updateReadTimestampStruct() { U16 decimalSeconds = convertBCD2Decimal( rxBuffer[RTC_SECONDS_INDEX] ); U16 decimalMins = convertBCD2Decimal( rxBuffer[RTC_MINUTES_INDEX] ); U16 decimalHours = convertBCD2Decimal( rxBuffer[RTC_HOURS_INDEX] ); U16 decimalDays = convertBCD2Decimal( rxBuffer[RTC_DAYS_INDEX] ); U16 decimalMonths = convertBCD2Decimal( rxBuffer[RTC_MONTHS_INDEX] ); U16 decimalYears = convertBCD2Decimal( rxBuffer[RTC_YEARS_INDEX] ); read_ts.seconds = decimalSeconds; read_ts.minutes = decimalMins; read_ts.hours = decimalHours; read_ts.days = decimalDays; read_ts.weekdays = 0; // Weekdays will not be used read_ts.months = decimalMonths; read_ts.years = decimalYears; } static RTC_EXEC_STATE_T handleExecWriteState() { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WRITE; // FOR DEBUGGING ONLY, REMOVE THIS CODE setRTCTimestamp(0, 10, 17, 8, 12, 2019); U16 timestamp[8] = {RTC_WRITE_TO_REG3, write_ts.seconds, write_ts.minutes, write_ts.hours, write_ts.days, write_ts.weekdays, write_ts.months, write_ts.years}; serviceRTC( ×tamp[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { // Reset the counter timeCounter = 1; hasWriteToRTCRequested = FALSE; RTCExecState = RTC_EXEC_STATE_IDLE; } return result; } static RTC_EXEC_STATE_T handleExecIdleState() { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_IDLE; if ( hasWriteToRTCRequested ) { result = RTC_EXEC_STATE_WRITE; } else if ( hasWriteToRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } else if ( hasReadFromRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } // If write to RTC has been requested, we don't have to read // write must be finished first else if ( timeCounter == TIMER_COUNTER_TO_REQUEST_READ || hasReadFromRTCRequested ) { // Reset the RTC Service commands RTCServiceState = RTC_SEND_COMMAND; setMibSPIBufferLength(GENERAL_NUM_OF_ITEMS_TO_READ); txBuffer[0] = RTC_READ_FROM_REG0; U08 i; for (i=1; i< GENERAL_NUM_OF_ITEMS_TO_READ; i++) { txBuffer[i] = 0x0000; } result = RTC_EXEC_STATE_READ; } else { timeCounter++; } return result; } static RTC_EXEC_STATE_T handleExecPrepRAMState( U16 address ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_PREP_RAM; txBuffer[0] = RTC_PREP_RAM_READ_WRITE; txBuffer[1] = ( address >> 8 ); txBuffer[2] = ( address & 0x00FF ); setMibSPIBufferLength( RTC_RAM_PREP_BUFFER_LENGTH ); BOOL isStatusOk = serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { if ( hasWriteToRAMRequested ) { result = RTC_EXEC_STATE_WRITE_TO_RAM; } else if ( hasReadFromRAMRequested ) { result = RTC_EXEC_STATE_READ_FROM_RAM; } // Reset the RTC Service commands RTCServiceState = RTC_SEND_COMMAND; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE && ! isStatusOk ) { result = RTC_EXEC_STATE_FAULT; } return result; } static RTC_EXEC_STATE_T handleExecWriteToRAMState( U08* data, U32 length ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WRITE_TO_RAM; // Set the buffer once if ( hasWriteToRAMRequested ) { U08 i; txBuffer[0] = RTC_WRITE_TO_RAM; for ( i = 0; i < length; i++ ) { // The zeroth element of txBuffer // is the RAM command txBuffer[i + 1] = data[i]; } setMibSPIBufferLength( length + 1 ); // Set the buffer once and done hasWriteToRAMRequested = FALSE; } BOOL isStatusOk = serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { result = RTC_EXEC_STATE_IDLE; // Reset the RTC Service commands RTCServiceState = RTC_SEND_COMMAND; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE && ! isStatusOk ) { result = RTC_EXEC_STATE_FAULT; } return result; } static RTC_EXEC_STATE_T handleExecReadFromRAMState( U32 length ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_READ_FROM_RAM; // Set the buffer once if ( hasReadFromRAMRequested ) { U08 i; txBuffer[0] = RTC_READ_FROM_RAM; for ( i = 0; i < length; i++ ) { txBuffer[i+1] = 0; } setMibSPIBufferLength( length + 1 ); // Set the buffer to the maximum since // we don't know how many buffer are in a hasReadFromRAMRequested = FALSE; } BOOL isStatusOk = serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { result = RTC_EXEC_STATE_IDLE; // Reset the RTC Service commands RTCServiceState = RTC_SEND_COMMAND; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE && ! isStatusOk ) { result = RTC_EXEC_STATE_FAULT; } return result; } static RTC_EXEC_STATE_T handleExecReadState() { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_READ; BOOL isStatusOk = serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { if ( isRTCFunctional() ) { updateReadTimestampStruct(); convertTime2Epoch(); // If an off time read request happened, we shouldn't // reset the counter for auto read if ( timeCounter == TIMER_COUNTER_TO_REQUEST_READ ) { timeCounter = 1; } else if ( hasReadFromRTCRequested ) { hasReadFromRTCRequested = FALSE; } result = RTC_EXEC_STATE_IDLE; } } else if ( RTCServiceState == RTC_SERVICE_COMPLETE && ! isStatusOk ) { result = RTC_EXEC_STATE_FAULT; } return result; } // Private self test functions static RTC_SELF_TEST_STATE_T handleSelfTestStart() { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_START; setMibSPIBufferLength(GENERAL_NUM_OF_ITEMS_TO_READ); txBuffer[0] = RTC_READ_FROM_REG0; U08 i; for (i=1; i< GENERAL_NUM_OF_ITEMS_TO_READ; i++) { txBuffer[i] = 0x0000; } result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; return result; } static RTC_SELF_TEST_STATE_T handleSelfTestCheckCtrlRegs() { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { // Reset the states RTCServiceState = RTC_SEND_COMMAND; if ( isRTCFunctional() ) { result = RTC_SELF_TEST_STATE_COMPARE_SECONDS; } else { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; } } return result; } static RTC_SELF_TEST_STATE_T handleSelfTestCompareSeconds() { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_COMPARE_SECONDS; serviceRTC( &txBuffer[0] ); if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { // Reset the states RTCServiceState = RTC_SEND_COMMAND; U32 RTCCurrentSecond = rxBuffer[RTC_SECONDS_INDEX]; if ( RTCPreviousSecond == 0 ) { RTCPreviousSecond = RTCCurrentSecond; } else if ( RTCCurrentSecond > RTCPreviousSecond ) { RTCSelfTestTimer = getMSTimerCount(); result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; } } return result; } static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy() { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; if ( didTimeout( RTCSelfTestTimer, RTC_ACCURACY_TIMEOUT ) ) { U32 elapsedTime = calcTimeSince(RTCSelfTestTimer); if ( elapsedTime > RTC_ACCURACY_TIMEOUT_TOLERANCE ) { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; } else { RTCSelfTestResult = SELF_TEST_STATUS_PASSED; } result = RTC_SELF_TEST_STATE_COMPLETE; } return result; } static BOOL setMibSPIBufferLength( U16 length ) { BOOL transferStatus = FALSE; // The max allowed buffer length in the // MibSPI RAM is 127 if ( length <= MIBSPI_MAX_BUFFER_LENGTH ) { U32 i = 0; mibspiREG3->TGCTRL[0U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[1U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[1U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[2U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[2U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[3U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[3U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[4U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[4U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[5U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[5U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[6U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[6U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[7U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[7U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); mibspiREG3->TGCTRL[8U] = (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT; mibspiREG3->LTGPEND = ( mibspiREG3->LTGPEND & 0xFFFF00FFU ) | (uint32)( ((uint32)length - 1U) << MIBSPI_BUFFER_TRANS_BIT_SHIFT ); while ( i < ( length - 1U ) ) { mibspiRAM3->tx[i].control = (uint16)( (uint16)MIBSPI_CONTINUOUS_MODE << MIBSPI_BUFFER_MODE_BIT_SHIFT ) /* buffer mode */ | (uint16)( (uint16)MIBSPI_CHIP_SELECT_ACTIVE << MIBSPI_CHIP_SELECT_BIT_SHIFT ) /* chip select hold */ | (uint16)( (uint16)MIBSPI_NO_WDELAY << MIBSPI_NO_WDELAY_BIT_SHIT ) /* enable WDELAY */ | (uint16)( (uint16)MIBSPI_LOCK_TG << MIBSPI_LOCK_TRANS_BIT_SHIFT ) /* lock transmission */ | (uint16)( (uint16)MIBSPI_DATA_FORMAT_ZERO << MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT ) /* data format */ /*SAFETYMCUSW 334 S MR:10.5 "LDRA Tool issue" */ | ((uint16)( ~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU ); /* chip select */ i++; } mibspiRAM3->tx[i].control = (uint16)( (uint16)MIBSPI_CONTINUOUS_MODE << MIBSPI_BUFFER_MODE_BIT_SHIFT ) /* buffer mode */ | (uint16)( (uint16)MIBSPI_CHIP_SELECT_DEACTIVE << MIBSPI_CHIP_SELECT_BIT_SHIFT ) /* chip select hold */ | (uint16)( (uint16)MIBSPI_NO_WDELAY << MIBSPI_NO_WDELAY_BIT_SHIT ) /* enable WDELAY */ | (uint16)( (uint16)MIBSPI_DATA_FORMAT_ZERO << MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT ) /* data format */ /*SAFETYMCUSW 334 S MR:10.5 "LDRA Tool issue" */ | ((uint16)( ~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU ); /* chip select */ i++; transferStatus = TRUE; } else { transferStatus = FALSE; } return transferStatus; }