Index: App/Services/SystemComm.c =================================================================== diff -u -rc91e9da338d92432930d3589a4055ebbb404c6cb -r833095dbbe2b21a989b05f48bd7ddc390ad964cb --- App/Services/SystemComm.c (.../SystemComm.c) (revision c91e9da338d92432930d3589a4055ebbb404c6cb) +++ App/Services/SystemComm.c (.../SystemComm.c) (revision 833095dbbe2b21a989b05f48bd7ddc390ad964cb) @@ -20,7 +20,6 @@ #include "Common.h" #include "Buttons.h" -#include "CommBuffers.h" #include "MsgQueues.h" #include "SystemComm.h" @@ -43,13 +42,42 @@ NUM_OF_MSG_IDS } MSG_ID_T; +#define NUM_OF_CAN_OUT_BUFFERS 4 // # of CAN buffers for transmit +#define NUM_OF_CAN_IN_BUFFERS 6 // # of CAN buffers for receiving + // ********** private data ********** +const COMM_BUFFER_T CAN_OUT_BUFFERS[NUM_OF_CAN_OUT_BUFFERS] = +{ + COMM_BUFFER_OUT_CAN_HD_ALARM, + COMM_BUFFER_OUT_CAN_HD_2_DG, + COMM_BUFFER_OUT_CAN_HD_2_UI, + COMM_BUFFER_OUT_CAN_HD_BROADCAST +}; +const COMM_BUFFER_T CAN_IN_BUFFERS[NUM_OF_CAN_IN_BUFFERS] = +{ + COMM_BUFFER_IN_CAN_DG_ALARM, + COMM_BUFFER_IN_CAN_UI_ALARM, + COMM_BUFFER_IN_CAN_DG_2_HD, + COMM_BUFFER_IN_CAN_DG_BROADCAST, + COMM_BUFFER_IN_CAN_UI_2_HD, + COMM_BUFFER_IN_CAN_UI_BROADCAST +}; + // ********** private function prototypes ********** +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); +static void transmitNextCANPacket( void ); +static void transmitPendingUARTData( void ); static U32 serializeMessage( MESSAGE_T msg, U08 *data ); +static void processIncomingData( void ); +static U32 parseMessageFromBuffer( U08 *data, U32 len ); +static void consumeBufferDataBeforeSync( COMM_BUFFER_T buffer ); +static void processReceivedMessages( void ); +static void processReceivedMessage( MESSAGE_T *message ); + /************************************************************************* * @brief initSystemComm * The initSystemComm function initializes the SystemComm module. @@ -61,7 +89,7 @@ *************************************************************************/ void initSystemComm( void ) { - + // currently nothing to initialize } /************************************************************************* @@ -75,74 +103,134 @@ *************************************************************************/ void execSystemCommRx( void ) { - // TODO - this is ugly preliminary test code - nowhere near ready for code review - BOOL isThereMsgRcvd; - U08 data[sizeof(MESSAGE_WRAPPER_T)]; - MESSAGE_WRAPPER_T msg; + // parse messages from comm buffers and queue them + processIncomingData(); - // queue any received CAN messages - if ( FALSE != canIsRxMessageArrived( canREG1, canMESSAGE_BOX2 ) ) + // process received messages in the queue + processReceivedMessages(); +} + +/************************************************************************* + * @brief execSystemCommTx + * The execSystemCommTx function manages data to be transmitted to other \n + * sub-systems. + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void execSystemCommTx( void ) +{ + // TODO - check to see if CAN transmitter is idle first + if ( 1 ) // for now, assume it's idle { - MESSAGE_WRAPPER_T rcvMsg; - U08 *dataPtr = data; + transmitNextCANPacket(); + } - canGetData( canREG1, canMESSAGE_BOX2, data ); - blankMessageInWrapper( &rcvMsg ); - memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); - dataPtr += sizeof(MESSAGE_HEADER_T); - memcpy( &(rcvMsg.msg.cargo), dataPtr, rcvMsg.msg.hdr.cargoLen ); - dataPtr += rcvMsg.msg.hdr.cargoLen; - rcvMsg.crc = *dataPtr; - addToMsgQueue( MSG_Q_IN_CAN_UI_2_HD, &rcvMsg ); + // TODO - check to see if UART transmitter is idle first + if ( 1 ) // for now, assume it's idle + { + transmitPendingUARTData(); } +} - // see if any messages received - isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN_CAN_UI_2_HD, &msg ); - if ( TRUE == isThereMsgRcvd ) + +/************************************************************************* +********************** TRANSMIT SUPPORT FUNCTIONS ************************ +*************************************************************************/ + + +/************************************************************************* + * @brief handleCANXmitCompleteInt + * The handleCANXmitCompleteInt function handles a CAN Tx complete interrupt. \n + * A search for the next highest priority pack to transmit is made and a \n + * new packet transmit is initiated on the appropriate CAN message box if \n + * a CAN packet is found. + * @details + * Inputs : Comm buffers + * Outputs : new CAN packet transmission is initiated + * @param none + * @return none + *************************************************************************/ +void handleCANXmitCompleteInt( void ) +{ + transmitNextCANPacket(); +} + +/************************************************************************* + * @brief findNextHighestPriorityCANPacketToTransmit + * The findNextHighestPriorityCANPacketToTransmit function gets the next \n + * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. \n + * @details + * Inputs : Output CAN Comm Buffer(s) + * Outputs : none + * @param msg : none + * @return buffer with highest priority CAN packet to transmit, \n + * COMM_BUFFER_NOT_USED_1 if not CAN packets pending transmit found + *************************************************************************/ +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) +{ + COMM_BUFFER_T result = COMM_BUFFER_NOT_USED_1; + U32 i; + + // search for next priority CAN packet to transmit + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) { - switch ( msg.msg.hdr.msgID ) + if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[i] ) >= CAN_MESSAGE_CARGO_SIZE ) { - case MSG_ID_OFF_BUTTON_PRESS: - userConfirmOffButton( msg.msg.cargo[0] ); -// ***************************** TEST CODE ****************************** -// TODO - remove later -#if 1 - setUserLED( TRUE ); -#endif -// ************************** END TEST CODE ****************************** - break; - - default: - break; + result = CAN_OUT_BUFFERS[i]; + break; // found highest priority packet to transmit - we're done } } + + return result; } /************************************************************************* - * @brief execSystemCommTx - * The execSystemCommTx function manages data to be transmitted to other \n - * sub-systems. + * @brief transmitNextCANPacket + * The transmitNextCANPacket function gets the next 8 byte packet and initiates \n + * a CAN transmit on the appropriate CAN channel. * @details - * Inputs : none - * Outputs : none - * @param none + * Inputs : Output CAN Comm Buffers + * Outputs : CAN packet transmit initiated. + * @param msg : none * @return none *************************************************************************/ -void execSystemCommTx( void ) +static void transmitNextCANPacket( void ) { - // TODO - this is ugly preliminary test code - nowhere near ready for code review - U08 data[sizeof(MESSAGE_WRAPPER_T)]; - U32 dataSize; + COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); - // actually transmit any pending messages - dataSize = getFromCommBuffer( COMM_BUFFER_OUT_CAN_HD_2_UI, data, CAN_MESSAGE_CARGO_SIZE ); - if ( dataSize > 0 ) + // if a buffer is found with a packet to transmit, get packet from buffer and transmit it + if ( buffer != COMM_BUFFER_NOT_USED_1 ) { - canTransmit( canREG1, canMESSAGE_BOX1, data ); + U08 data[CAN_MESSAGE_CARGO_SIZE]; + U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_CARGO_SIZE ); + CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned + + if ( dataSize == CAN_MESSAGE_CARGO_SIZE ) + { + canTransmit( canREG1, mBox, data ); + } } } /************************************************************************* + * @brief transmitPendingUARTData + * The transmitPendingUARTData function sets up and initiates a DMA transmit \n + * of any data currently pending transmit via UART. + * @details + * Inputs : Output UART Comm Buffer(s) + * Outputs : UART DMA transmit initiated. + * @param msg : none + * @return none + *************************************************************************/ +static void transmitPendingUARTData( void ) +{ + // TODO - implement +} + +/************************************************************************* * @brief serializeMessage * The serializeMessage function serializes a given message into a given \n * array of bytes. A sync byte is inserted at the beginning of the message \n @@ -189,11 +277,227 @@ /************************************************************************* -*************** SUITE OFF SEND MESSAGE FUNCTIONS BELOW ******************* +********************** RECEIVE SUPPORT FUNCTIONS ************************* *************************************************************************/ /************************************************************************* + * @brief handleCANPacketReceivedInt + * The handleCANPacketReceivedInt function handles a CAN Rx interrupt. \n + * A new CAN packet is added to the appropriate comm buffer based on the \n + * message box that it came in on. + * @details + * Inputs : none + * Outputs : new CAN packet added to associated comm buffer + * @param srcCANBox : CAN message box that the packet arrived in + * @return none + *************************************************************************/ +void handleCANPacketReceivedInt( CAN_MESSAGE_BOX_T srcCANBox ) +{ + U08 data[CAN_MESSAGE_CARGO_SIZE]; + + // TODO - get received packets from any/all CAN message boxes that have a new packet + if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) // TODO - is this even necessary? when interrupt is calling, don't we already know it's arrived? + { + canGetData( canREG1, srcCANBox, data ); + // TODO - select appropriate comm buffer based on the message box it came in on (s/b same #) + addToCommBuffer( srcCANBox, data, CAN_MESSAGE_CARGO_SIZE ); + } +} + +/************************************************************************* + * @brief processIncomingData + * The processIncomingData function parses out messages from the Input \n + * Comm Buffers and adds them to the Received Message Queue. + * @details + * Inputs : Input Comm Buffers + * Outputs : Parsed message(s) added to Received Message Queue + * @param msg : none + * @return none + *************************************************************************/ +static void processIncomingData( void ) +{ + U08 data[sizeof(MESSAGE_WRAPPER_T)+1]; + U32 i; + + // TODO - remove this later - this should be called by CAN receive interrupt handler when implemented + handleCANPacketReceivedInt( COMM_BUFFER_IN_CAN_UI_2_HD ); + + // queue any received CAN messages + for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) + { + U32 numOfBytesInBuffer; + + //consumeBufferDataBeforeSync( CAN_IN_BUFFERS[i] ); // TODO - call when sync implemented + numOfBytesInBuffer = numberOfBytesInCommBuffer( CAN_IN_BUFFERS[i] ); + if ( numOfBytesInBuffer >= CAN_MESSAGE_CARGO_SIZE ) + { + U32 bytesPeeked = peekFromCommBuffer( CAN_IN_BUFFERS[i], data, MIN(numOfBytesInBuffer,(sizeof(MESSAGE_WRAPPER_T)+1)) ); + U32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); + + if ( msgSize > 0 ) + { + msgSize = getFromCommBuffer( CAN_IN_BUFFERS[i], data, msgSize ); + if ( msgSize > 0 ) + { + MESSAGE_WRAPPER_T rcvMsg; + U08 *dataPtr = data; + + blankMessageInWrapper( &rcvMsg ); + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); + dataPtr += sizeof(MESSAGE_HEADER_T); + memcpy( &(rcvMsg.msg.cargo), dataPtr, rcvMsg.msg.hdr.cargoLen ); + dataPtr += rcvMsg.msg.hdr.cargoLen; + rcvMsg.crc = *dataPtr; + addToMsgQueue( MSG_Q_IN_CAN, &rcvMsg ); + } + } + + +// MESSAGE_WRAPPER_T rcvMsg; +// U08 *dataPtr = data; +// +// getFromCommBuffer( CAN_IN_BUFFERS[i], data, CAN_MESSAGE_CARGO_SIZE ); +// blankMessageInWrapper( &rcvMsg ); +// memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); +// dataPtr += sizeof(MESSAGE_HEADER_T); +// memcpy( &(rcvMsg.msg.cargo), dataPtr, rcvMsg.msg.hdr.cargoLen ); +// dataPtr += rcvMsg.msg.hdr.cargoLen; +// rcvMsg.crc = *dataPtr; +// addToMsgQueue( MSG_Q_IN_CAN, &rcvMsg ); + } + } +} + +/************************************************************************* + * @brief consumeBufferDataBeforeSync + * The consumeBufferDataBeforeSync function removes any bytes in a given \n + * buffer that lie before a sync byte. + * @details + * Inputs : none + * Outputs : none + * @param msg : buffer : the comm buffer to process + * @return none + *************************************************************************/ +static void consumeBufferDataBeforeSync( COMM_BUFFER_T buffer ) +{ + // TODO - implement +} + +/************************************************************************* + * @brief parseMessageFromBuffer + * The parseMessageFromBuffer function looks for a complete message in a \n + * given comm buffer. If found, the given buffer is populated with the \n + * message and its size is returned. + * @details + * Inputs : Comm Buffer + * Outputs : none + * @param msg : data : pointer to byte array to populate with a message if found + * @return size of message, zero if no complete message found. + *************************************************************************/ +static U32 parseMessageFromBuffer( U08 *data, U32 len ) +{ + U32 i; + U32 cargoSize; + U32 msgSize; + U32 result = 0; + + for ( i = 0; i < len; i++ ) + { + // find sync byte + //if ( MESSAGE_SYNC_BYTE == data[i] ) + if (1) // TODO - find sync byte when implemented + { + U32 pos = i; // + 1; // TODO - add one when sync byte implemented + U32 remSize = len - pos; + U32 minSize = sizeof(MESSAGE_HEADER_T) + sizeof(U08); + + // if a minimum sized msg would fit in remaining + if ( remSize >= minSize ) + { + cargoSize = data[pos+sizeof(U16)]; + msgSize = minSize + cargoSize; + if ( msgSize <= remSize ) + { + result = msgSize; + } + } + + break; + } + } + + return result; +} + +/************************************************************************* + * @brief processReceivedMessages + * The processReceivedMessages function processes any messages in the \n + * received message queues. + * @details + * Inputs : Received Message Queues + * Outputs : Message(s) processed. + * @param msg : none + * @return none + *************************************************************************/ +static void processReceivedMessages( void ) +{ + BOOL isThereMsgRcvd; + MESSAGE_WRAPPER_T message; + + // see if any messages received + isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN_CAN, &message ); + if ( TRUE == isThereMsgRcvd ) + { + // TODO - check CRC before processing a message + if ( 1 ) + { + processReceivedMessage( &message.msg ); + } + else // CRC failed + { + // TODO - probably wouldn't want to fault on this. ignore? + } + } + + // TODO - process UART (script) messages too +} + +/************************************************************************* + * @brief processReceivedMessage + * The processReceivedMessage function processes a given message. + * @details + * Inputs : none + * Outputs : message processed + * @param msg : + * @return none + *************************************************************************/ +static void processReceivedMessage( MESSAGE_T *message ) +{ + switch ( message->hdr.msgID ) + { + case MSG_ID_OFF_BUTTON_PRESS: + userConfirmOffButton( message->cargo[0] ); +// ***************************** TEST CODE ****************************** +// TODO - remove later +#if 1 + setUserLED( TRUE ); +#endif +// ************************** END TEST CODE ****************************** + break; + + default: + // TODO - unrecognized message ID received - ignore + break; + } +} + + +/************************************************************************* +**************** SUITE OF SEND MESSAGE FUNCTIONS BELOW ******************* +*************************************************************************/ + +/************************************************************************* * @brief sendOffButtonMsgToUI * The sendOffButtonMsgToUI function constructs an off button msg to the UI \n * and queues the msg for transmit on the appropriate CAN channel.