Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rf100557efc2f7916054a63bbafb187d8017914d0 -rfc4f469fe234371e8f2b9a0625acc66faa6899de --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision f100557efc2f7916054a63bbafb187d8017914d0) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision fc4f469fe234371e8f2b9a0625acc66faa6899de) @@ -13,8 +13,9 @@ #include "FPGA.h" #include "Utilities.h" +#define QUEUE_MAX_SIZE 10 ///< Max queue size. #define FPGA_PAGE_SIZE 256 ///< FPGA register pages are 256 bytes. -#define FPGA_EXPECTED_ID 0x5A ///< Expected ID for HD FPGA. +#define FPGA_MAX_READ_SIZE ( FPGA_PAGE_SIZE - 1 ) #define FPGA_WRITE_CMD_BUFFER_LEN ( FPGA_PAGE_SIZE + 8 ) ///< FPGA write command buffer byte length. #define FPGA_READ_CMD_BUFFER_LEN 8 ///< FPGA read command buffer byte length. #define FPGA_WRITE_RSP_BUFFER_LEN 8 ///< FPGA write command response buffer byte length. @@ -26,13 +27,18 @@ #define GET_LSB_OF_WORD(w) ((U08)((w) & MASK_OFF_MSB)) ///< Macro returns the least signficant byte of a 2-byte word #define GET_MSB_OF_WORD(w) ((U08)(((w) >> SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_MSB)) ///< Macro returns the most signficant byte of a 2-byte word #define MAKE_WORD_OF_BYTES(h, l) ((((U16)(h) << SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_LSB) | ((U16)(l) & MASK_OFF_MSB)) ///< Macro merges two bytes into a 2-byte word +#define INC_WRAP(v, l, u) ((v) >= (u) ? (l) : ((v) + 1)) ///< Macro increments a value and wraps to a minimum when a maximum is reached #define FPGA_READ_CMD_CODE 0x5A ///< FPGA read command code. #define FPGA_HEADER_START_ADDR 0x0000 ///< Start address for FPGA header data. +#define FPGA_BULK_READ_START_ADDR 0x0100 ///< Start address for FPGA continuous priority reads. #define FPGA_READ_CMD_ACK 0xAA ///< FPGA read command ACK code. #define FPGA_READ_CMD_HDR_LEN 4 ///< FPGA read command header byte length. #define FPGA_READ_RSP_HDR_LEN 3 ///< FPGA read command response header byte length. +#define FPGA_UPDATE_REQUEST_INDEX ( FPGA_READ_RSP_HDR_LEN + 1 ) // TODO Get this value from Noe, make sure the index is the same in all of the stacks +#define UPDATE_REQUESTED_VALUE 1 + #define SCI_DMA_TRANSMIT_INT 0x00010000 ///< Bit mask for setting/clearing serial DMA transmit interrupts. #define SCI_DMA_RECEIVE_INT 0x00060000 ///< Bit mask for setting/clearing serial DMA receive interrupts. @@ -48,22 +54,53 @@ typedef enum { - FPGA_START_STATE = 0, - FPGA_RQST_HEADER_STATE, - FPGA_RCV_HEADER_STATE, + FPGA_READ_HEADER = 0, + FPGA_READ_UPDATE_REG, + FPGA_WRITE_UPDATE_REG, + FPGA_RESET_FLASH, + FPGA_ERASE_FLASH, + FPGA_ENABLE_FLASH, + FPGA_CHECK_FIFO, + FPGA_WRITE_UPDATE_DATA, + NUM_OF_FPGA_JOBS, +} FPGA_JOBS_T; + +typedef enum +{ + FPGA_IDLE_STATE = 0, FPGA_WRITE_TO_FPGA_STATE, + FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE, FPGA_READ_FROM_FPGA_STATE, - FPGA_IDLE_STATE, + FPGA_RCV_READ_RESP_FROM_FPGA_STATE, NUM_OF_FPGA_STATES } FPGA_STATE_T; +#pragma pack(push,1) +/*typedef struct +{ + FPGA_COMM_STATE_T fpgaCommRead; // TODO remove + FPGA_COMM_STATE_T fpgaCommWrite; +} FPGA_COMM_STATUS_T; +*/ + typedef struct { + U16 fpgaJobAddress; + U08 fpgaJobSize; + BOOL read; +} FPGA_JOB_SPECS_T; + +typedef struct +{ + U08 fpgaJobsQueue[ QUEUE_MAX_SIZE ]; + U08 fpgaJobRearIndex; + U08 fpgaJobFrontIndex; + U08 fpgaJobsQueueCount; + U08 fpgaCurrentJob; FPGA_COMM_STATE_T fpgaCommRead; FPGA_COMM_STATE_T fpgaCommWrite; -} FPGA_COMM_STATUS_T; -// FPGA Sensors Record -#pragma pack(push,1) +} FPGA_JOBS_Q_STATUS_T; + /// Record structure for FPGA header read. typedef struct { @@ -75,6 +112,20 @@ } FPGA_HEADER_T; // Read only on FPGA #pragma pack(pop) +static const U08 STACK_FPGA_ID[ NUM_OF_FW_STACKS ] = { 0x5A, 0x61, 0xFF }; // TODO update with the real FPGA IDs +static const FPGA_JOB_SPECS_T JOBS_SPECS[ NUM_OF_FPGA_JOBS ] = { + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, + { FPGA_BULK_READ_START_ADDR, FPGA_MAX_READ_SIZE, TRUE }, + + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, // TODO fill up + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE }, + { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), TRUE } +}; + + // FPGA comm buffers static U08 fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_BUFFER_LEN ]; ///< FPGA write command buffer. Holds the next FPGA write command to be transmitted. static U08 fpgaReadCmdBuffer[ FPGA_READ_CMD_BUFFER_LEN ]; ///< FPGA read command buffer. Holds the next FPGA read command to be transmitted. @@ -89,7 +140,8 @@ static FPGA_HEADER_T fpgaHeader; ///< Record of last received FPGA header data. static FPGA_STATE_T fpgaState; -static FPGA_COMM_STATUS_T fpgaCommStatus; +static U08 fpgaUpdateRegisterStatus; +static FPGA_JOBS_Q_STATUS_T fpgaJobsQStatus; static void initDMA( void ); @@ -101,51 +153,53 @@ static void startDMAReceiptOfReadResp( void ); static void startDMAReadCmd( void ); static void resetFPGACommFlags( void ); +static void enqueue( FPGA_JOBS_T job ); +static void dequeue( void ); -static FPGA_STATE_T handleFPGARequestHeaderState( void ); -static FPGA_STATE_T handleFPGARecieveHeaderState( void ); -static FPGA_STATE_T handleFPGAWriteToFPGAState( void ); -static FPGA_STATE_T handleFPGAReadFromFPGAState( void ); static FPGA_STATE_T handleFPGAIdleState( void ); +static FPGA_STATE_T handleFPGAWriteToFPGAState( void ); +static FPGA_STATE_T handleFPGAReceiveWriteRespFromFPGAState( void ); +static FPGA_STATE_T handleFPGAReadFromFPGAState( void ); +static FPGA_STATE_T handleFPGAReceiveReadRespFromFPGAState( void ); + void initFPGA( void ) { memset( &fpgaHeader, 0x0, sizeof( FPGA_HEADER_T ) ); + memset( &fpgaJobsQStatus, 0x0, sizeof( FPGA_JOBS_Q_STATUS_T ) ); initDMA(); consumeUnexpectedData(); - resetFPGACommFlags(); - fpgaState = FPGA_START_STATE; + enqueue( FPGA_READ_HEADER ); + enqueue( FPGA_READ_UPDATE_REG ); + + fpgaState = FPGA_IDLE_STATE; + fpgaUpdateRegisterStatus = 0; } void execFPGA( void ) { switch( fpgaState ) { - case FPGA_START_STATE: - fpgaState = FPGA_RQST_HEADER_STATE; // TODO this needs to be changed read from FPGA state to first see if there is an update or not. This is for test + case FPGA_IDLE_STATE: + fpgaState = handleFPGAIdleState(); break; - case FPGA_RQST_HEADER_STATE: - fpgaState = handleFPGARequestHeaderState(); - break; - - case FPGA_RCV_HEADER_STATE: - fpgaState = handleFPGARecieveHeaderState(); - break; - case FPGA_WRITE_TO_FPGA_STATE: fpgaState = handleFPGAWriteToFPGAState(); break; + case FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE: + fpgaState = handleFPGAReceiveWriteRespFromFPGAState(); + case FPGA_READ_FROM_FPGA_STATE: fpgaState = handleFPGAReadFromFPGAState(); break; - case FPGA_IDLE_STATE: - fpgaState = handleFPGAIdleState(); + case FPGA_RCV_READ_RESP_FROM_FPGA_STATE: + fpgaState = handleFPGAReceiveReadRespFromFPGAState(); break; default: @@ -158,13 +212,13 @@ { // TODO What is the purpose of fpgaReceiptCounter++ in firmware? - if ( FPGA_COMM_WRITE_IN_PROGRESS == fpgaCommStatus.fpgaCommWrite ) + if ( FPGA_COMM_WRITE_IN_PROGRESS == fpgaJobsQStatus.fpgaCommWrite ) { - fpgaCommStatus.fpgaCommWrite = FPGA_COMM_WRITE_RESP_RECEIVED; + fpgaJobsQStatus.fpgaCommWrite = FPGA_COMM_WRITE_RESP_RECEIVED; } - else if ( FPGA_COMM_READ_IN_PROGRESS == fpgaCommStatus.fpgaCommRead ) + else if ( FPGA_COMM_READ_IN_PROGRESS == fpgaJobsQStatus.fpgaCommRead ) { - fpgaCommStatus.fpgaCommRead = FPGA_COMM_READ_RESP_RECEIVED; + fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_READ_RESP_RECEIVED; } } @@ -186,6 +240,25 @@ scilinREG->CLEARINT = SCI_DMA_TRANSMIT_INT; } +BOOL hasUpdateBeenRequested( void ) +{ + BOOL status = FALSE; + + if ( FPGA_IDLE_STATE == fpgaState ) + { + status = ( UPDATE_REQUESTED_VALUE == fpgaUpdateRegisterStatus ? TRUE : FALSE ); + } + + return status; +} + +BOOL isFPGAIDValid( void ) +{ + BOOL status = ( STACK_FPGA_ID[ BL_STACK_ID ] == fpgaHeader.fpgaId ? TRUE : FALSE ); + + return status; +} + static void initDMA( void ) { // Enable interrupt notifications for FPGA serial port @@ -298,7 +371,6 @@ scilinREG->SETINT = SCI_DMA_TRANSMIT_INT; } - static void setupDMAForReadResp( U32 bytes2Receive ) { // Verify # of bytes does not exceed buffer length @@ -333,52 +405,144 @@ static void resetFPGACommFlags( void ) { - memset( &fpgaCommStatus, 0x0, sizeof( FPGA_COMM_STATUS_T ) ); + fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_IDLE; + fpgaJobsQStatus.fpgaCommWrite = FPGA_COMM_IDLE; } -static FPGA_STATE_T handleFPGARequestHeaderState( void ) +static void enqueue( FPGA_JOBS_T job ) { - FPGA_STATE_T state = FPGA_RCV_HEADER_STATE; + U08 currentRearIndex = fpgaJobsQStatus.fpgaJobRearIndex; + + fpgaJobsQStatus.fpgaJobsQueue[ currentRearIndex ] = job; + fpgaJobsQStatus.fpgaJobsQueueCount++; + + fpgaJobsQStatus.fpgaJobRearIndex = INC_WRAP( currentRearIndex, 0, QUEUE_MAX_SIZE - 1 ); +} + +static void dequeue( void ) +{ + U08 tempIndex; + + _disable_IRQ(); + tempIndex = fpgaJobsQStatus.fpgaJobFrontIndex; + + if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 ) + { + U08 frontIndex = fpgaJobsQStatus.fpgaJobFrontIndex; + + fpgaJobsQStatus.fpgaJobFrontIndex = INC_WRAP( frontIndex, 0, QUEUE_MAX_SIZE - 1 ); + fpgaJobsQStatus.fpgaCurrentJob = fpgaJobsQStatus.fpgaJobsQueue[ tempIndex ]; + } + + if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 ) + { + fpgaJobsQStatus.fpgaJobsQueueCount--; + } + _enable_IRQ(); +} + +static FPGA_STATE_T handleFPGAIdleState( void ) +{ + FPGA_STATE_T state = FPGA_IDLE_STATE; + + if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 ) + { + dequeue(); + + state = ( TRUE == JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].read ? FPGA_READ_FROM_FPGA_STATE : FPGA_WRITE_TO_FPGA_STATE ); + } + + return state; +} + +static FPGA_STATE_T handleFPGAWriteToFPGAState( void ) +{ + FPGA_STATE_T state = FPGA_READ_FROM_FPGA_STATE; U16 crc = 0; + // Construct bulk read command to read sensor data registers starting at address 8 + fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); + fpgaReadCmdBuffer[ 3 ] = FPGA_MAX_READ_SIZE; + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + + // Prep DMA for sending the read cmd and receiving the response + //fpgaCommStatus.fpgaCommRead = FPGA_COMM_READ_IN_PROGRESS; + + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + FPGA_MAX_READ_SIZE + sizeof( U16 ) ); + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + sizeof( U16 ) ); + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + + return state; +} + +static FPGA_STATE_T handleFPGAReceiveWriteRespFromFPGAState( void ) +{ + FPGA_STATE_T state = FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE; + + return state; +} + +static FPGA_STATE_T handleFPGAReadFromFPGAState( void ) +{ + FPGA_STATE_T state = FPGA_RCV_READ_RESP_FROM_FPGA_STATE; + U16 crc = 0; + U16 jobAddress = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobAddress; + U08 jobSize = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobSize; + // Construct read command to read 3 registers starting at address 0 fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; - fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_HEADER_START_ADDR ); - fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_HEADER_START_ADDR ); - fpgaReadCmdBuffer[ 3 ] = sizeof( FPGA_HEADER_T ); + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( jobAddress ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( jobAddress ); + fpgaReadCmdBuffer[ 3 ] = jobSize; crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); // Prep DMA for sending the read cmd and receiving the response - fpgaCommStatus.fpgaCommRead = FPGA_COMM_READ_IN_PROGRESS; + fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_READ_IN_PROGRESS; - setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_HEADER_T ) + sizeof( U16 ) ); + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + jobSize + sizeof( U16 ) ); setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + sizeof( U16 ) ); startDMAReceiptOfReadResp(); startDMAReadCmd(); return state; } -static FPGA_STATE_T handleFPGARecieveHeaderState( void ) +static FPGA_STATE_T handleFPGAReceiveReadRespFromFPGAState( void ) { - FPGA_STATE_T state = FPGA_RCV_HEADER_STATE; + FPGA_STATE_T state = FPGA_RCV_READ_RESP_FROM_FPGA_STATE; - if ( FPGA_COMM_READ_RESP_RECEIVED == fpgaCommStatus.fpgaCommRead ) + if ( FPGA_COMM_READ_RESP_RECEIVED == fpgaJobsQStatus.fpgaCommRead ) { if ( FPGA_READ_CMD_ACK == fpgaReadResponseBuffer[ 0 ] ) { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_HEADER_T ); + U32 rspSize = FPGA_READ_RSP_HDR_LEN + FPGA_MAX_READ_SIZE; U32 crcPos = rspSize; U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); // Does the FPGA response CRC check out? if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) { // Capture the read values - memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) ); - state = FPGA_IDLE_STATE; + switch( fpgaJobsQStatus.fpgaCurrentJob ) + { + case FPGA_READ_HEADER: + memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) ); + break; + + case FPGA_READ_UPDATE_REG: + fpgaUpdateRegisterStatus = fpgaReadResponseBuffer[ FPGA_UPDATE_REQUEST_INDEX ]; + break; + } + + fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_IDLE; + state = FPGA_IDLE_STATE; } } } @@ -391,27 +555,3 @@ return state; } -static FPGA_STATE_T handleFPGAWriteToFPGAState( void ) -{ - FPGA_STATE_T state = FPGA_WRITE_TO_FPGA_STATE; - - return state; -} - -static FPGA_STATE_T handleFPGAReadFromFPGAState( void ) -{ - FPGA_STATE_T state = FPGA_READ_FROM_FPGA_STATE; - - // Should not be any data received at this time - consumeUnexpectedData(); - - return state; -} - -static FPGA_STATE_T handleFPGAIdleState( void ) -{ - FPGA_STATE_T state = FPGA_IDLE_STATE; - - return state; -} -