Index: App/Services/SystemComm.c =================================================================== diff -u -r3323966fe741edbb36dffc78317ccf06ed93a68e -rcb47c5f896477ceae7597cb1a4191b3972e93f0d --- App/Services/SystemComm.c (.../SystemComm.c) (revision 3323966fe741edbb36dffc78317ccf06ed93a68e) +++ App/Services/SystemComm.c (.../SystemComm.c) (revision cb47c5f896477ceae7597cb1a4191b3972e93f0d) @@ -16,10 +16,11 @@ * **************************************************************************/ -#include #include // for memcpy() #include "can.h" +#include "sci.h" +#include "sys_dma.h" #include "Common.h" #include "MsgQueues.h" @@ -35,6 +36,9 @@ #define NUM_OF_CAN_OUT_BUFFERS 4 // # of CAN buffers for transmit #define NUM_OF_CAN_IN_BUFFERS 6 // # of CAN buffers for receiving +#define SCI1_RECEIVE_DMA_REQUEST 30 +#define SCI1_TRANSMIT_DMA_REQUEST 31 + // ********** private data ********** const COMM_BUFFER_T CAN_OUT_BUFFERS[NUM_OF_CAN_OUT_BUFFERS] = @@ -55,16 +59,24 @@ COMM_BUFFER_IN_CAN_UI_BROADCAST }; +static U08 pcXmitPacket[PC_MESSAGE_PACKET_SIZE]; +static U08 pcRecvPacket[PC_MESSAGE_PACKET_SIZE]; + +// DMA control records +static g_dmaCTRL pcDMAXmitControlRecord; +static g_dmaCTRL pcDMARecvControlRecord; + // ********** private function prototypes ********** static void handleCANPacketReceivedInt( CAN_MESSAGE_BOX_T srcCANBox ); static void handleCANXmitCompleteInt( void ); +static void handleUARTXmitCompleteInt( void ); static BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ); static BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ); static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); static void transmitNextCANPacket( void ); -static void transmitPendingUARTData( void ); +static void transmitNextUARTPacket( void ); static void processIncomingData( void ); static U32 parseMessageFromBuffer( U08 *data, U32 len ); @@ -83,7 +95,53 @@ *************************************************************************/ void initSystemComm( void ) { - // currently nothing to initialize + sciEnableLoopback( sciREG, Digital_Lbk ); // TODO - for test only + + // Enable DMA block transfer complete interrupts + dmaEnableInterrupt( DMA_CH1, BTC ); + dmaEnableInterrupt( DMA_CH3, BTC ); + // assign DMA channels to h/w DMA requests + dmaReqAssign( DMA_CH1, SCI1_RECEIVE_DMA_REQUEST ); + dmaReqAssign( DMA_CH3, SCI1_TRANSMIT_DMA_REQUEST ); + // set DMA channel priorities + dmaSetPriority( DMA_CH1, HIGHPRIORITY ); + dmaSetPriority( DMA_CH3, LOWPRIORITY ); + + // initialize PC DMA Transmit Control Record + pcDMAXmitControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + pcDMAXmitControlRecord.DADD = (U32)(&(sciREG->TD)); // dest. is SCI2 xmit register + pcDMAXmitControlRecord.SADD = (U32)pcXmitPacket; // source + pcDMAXmitControlRecord.CHCTRL = 0; // no chaining + pcDMAXmitControlRecord.ELCNT = 1; // frame is 1 element + pcDMAXmitControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames + pcDMAXmitControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + pcDMAXmitControlRecord.WRSIZE = ACCESS_8_BIT; // + pcDMAXmitControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + pcDMAXmitControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed + pcDMAXmitControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + pcDMAXmitControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + pcDMAXmitControlRecord.ELSOFFSET = 0; // # of bytes to advance at source memory after each element + pcDMAXmitControlRecord.ELDOFFSET = 0; // not used + pcDMAXmitControlRecord.FRSOFFSET = 0; // # of bytes to advance at source memory after each frame + pcDMAXmitControlRecord.FRDOFFSET = 0; // not used + + // initialize PC DMA Receipt Control Record + pcDMARecvControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + pcDMARecvControlRecord.SADD = (U32)(&(sciREG->RD));// source is SCI2 recv register + pcDMARecvControlRecord.DADD = (U32)pcRecvPacket; // transfer destination address + pcDMARecvControlRecord.CHCTRL = 0; // no chaining + pcDMARecvControlRecord.ELCNT = 1; // frame is 1 element + pcDMARecvControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE;// block is 8 frames + pcDMARecvControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + pcDMARecvControlRecord.WRSIZE = ACCESS_8_BIT; // + pcDMARecvControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + pcDMARecvControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed + pcDMARecvControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment + pcDMARecvControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + pcDMARecvControlRecord.ELDOFFSET = 0; // # of bytes to advance at destination memory after each element + pcDMARecvControlRecord.ELSOFFSET = 0; // not used + pcDMARecvControlRecord.FRDOFFSET = 0; // # of bytes to advance at destination memory after each frame + pcDMARecvControlRecord.FRSOFFSET = 0; // not used } /************************************************************************* @@ -125,11 +183,26 @@ // TODO - check to see if UART transmitter is idle first if ( 1 ) // for now, assume it's idle { - transmitPendingUARTData(); + transmitNextUARTPacket(); } } /************************************************************************* + * @brief canMessageNotification + * The canMessageNotification function handles CAN message notifications. + * @details + * Inputs : none + * Outputs : CAN message notification handled. + * @param node : which CAN controller + * @param messageBox : which message box triggered the message notification + * @return none + *************************************************************************/ +void canMessageNotification(canBASE_t *node, uint32 messageBox) +{ + handleCANMsgInterrupt( (CAN_MESSAGE_BOX_T)messageBox ); +} + +/************************************************************************* * @brief handleCANMsgInterrupt * The handleCANMsgInterrupt function handles a CAN message interrupt. \n * This may have occurred because a CAN packet transmission has completed \n @@ -159,6 +232,23 @@ } } +void handleUARTMsgRecvPacketInterrupt( void ) +{ + // buffer received packet + addToCommBuffer( COMM_BUFFER_IN_DBG, pcRecvPacket, PC_MESSAGE_PACKET_SIZE ); + // prepare to receive next packet + dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); + dmaSetChEnable( DMA_CH1, DMA_HW ); + sciREG->SETINT = (uint32)((uint32)1U << 18U); /* Rx DMA All */ + sciREG->SETINT = (uint32)((uint32)1U << 17U); /* Rx DMA */ +} + +void handleUARTMsgXmitPacketInterrupt( void ) +{ + handleUARTXmitCompleteInt(); +} + + /************************************************************************* * @brief isCANBoxForXmit * The isCANBoxForXmit function determines whether a given CAN message box \n @@ -236,6 +326,11 @@ transmitNextCANPacket(); } +static void handleUARTXmitCompleteInt( void ) +{ + transmitNextUARTPacket(); +} + /************************************************************************* * @brief findNextHighestPriorityCANPacketToTransmit * The findNextHighestPriorityCANPacketToTransmit function gets the next \n @@ -286,6 +381,7 @@ U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_CARGO_SIZE ); CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned + // if there's another CAN packet to send, send it if ( dataSize == CAN_MESSAGE_CARGO_SIZE ) { canTransmit( canREG1, mBox, data ); @@ -294,18 +390,27 @@ } /************************************************************************* - * @brief transmitPendingUARTData - * The transmitPendingUARTData function sets up and initiates a DMA transmit \n - * of any data currently pending transmit via UART. + * @brief transmitNextUARTPacket + * The transmitNextUARTPacket function sets up and initiates a DMA transmit \n + * of the next packet pending transmit (if any) via UART. * @details * Inputs : Output UART Comm Buffer(s) * Outputs : UART DMA transmit initiated. * @param msg : none * @return none *************************************************************************/ -static void transmitPendingUARTData( void ) +static void transmitNextUARTPacket( void ) { - // TODO - implement + U08 data[PC_MESSAGE_PACKET_SIZE]; + U32 dataSize = getFromCommBuffer( COMM_BUFFER_OUT_DBG, data, PC_MESSAGE_PACKET_SIZE ); + + // if there's another UART packet to send, send it + if ( dataSize == PC_MESSAGE_PACKET_SIZE ) + { + dmaSetCtrlPacket( DMA_CH3, pcDMAXmitControlRecord ); + dmaSetChEnable( DMA_CH3, DMA_HW ); + sciREG->SETINT = (uint32)((uint32)1U << 16U); /* Tx DMA */ + } }