/******************************************************************************* * * * Copyright 2010 Rheinmetall Canada Inc. * * * * No part of this document may be reproduced, stored in * * a retrieval system, or transmitted, in any form or by any means, * * electronic, mechanical, photocopying, recording, or otherwise, * * without the prior written permission of Rheinmetall Canada Inc. * * * *******************************************************************************/ /* Description: This is a template file for standard C code file. */ /* ************************************************************************** */ /* ¤Revision: 000 20100616 JFM, Original version. ### YYYYMMDD Initial, Bug Identification Change description. */ /* ************************************************************************** */ /* Includes */ #include "define.h" #include "InternalUart.h" #include "uart.h" #include //#include "Watchdog.h" #include "digitalio.h" #include "NetworkProtocol.h" /* ************************************************************************** */ /* Local variables */ char acIntUartRxBuff[MAX_INTERNAL_UART_PORT][INTERNAL_UART_BUFFER_DEPTH]; //Rx Buffers stInternalUartData astInternalUartData[MAX_INTERNAL_UART_PORT]; //port management data unsigned int LoraData = 0; void process(void); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void InternalUartInit(void) { //Setup port 1 // // U1MODEbits.ON = 0; //disable module // U1STA = 0; // U1STAbits.UTXEN = 0; //disable transmitter // IPC6bits.U1IP = 7; //priority 7 // IPC6bits.U1IS = 3; //sub-priority 3 // U1STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted //// U1STAbits.UTXSEL = 0b01; // //JFM 2012-08-27 // IFS0bits.U1TXIF = 0; //clear interrupt flag // IEC0bits.U1TXIE = 1; //enable tx interrupt // U1STAbits.URXISEL = 0b00; //interrupt for each character received // IFS0bits.U1RXIF = 0; //#ifdef POLL_UART1_RX // IEC0bits.U1RXIE = 0; //disable rx interrupts //#else // IEC0bits.U1RXIE = 1; //enable rx interrupts //#endif // U1STAbits.URXEN = 1; //enable receiver // U1MODEbits.ON = 0; //disable module //Setup port 2 // U2MODEbits.ON = 0; //disable module U2STA = 0; U2STAbits.UTXEN = 0; //disable transmitter IPC8bits.U2IP = 7; //priority 7 IPC8bits.U2IS = 2; //sub-priority 2 U2STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted IFS1bits.U2TXIF = 0; //clear interrupt flag IEC1bits.U2TXIE = 0; //enable tx interrupt U2STAbits.URXISEL = 0b00; //interrupt for each character received IFS1bits.U2RXIF = 0; #ifdef POLL_UART2_RX IEC1bits.U2RXIE = 0; //disable rx interrupts #else IEC1bits.U2RXIE = 1; //enable rx interrupts #endif U2STAbits.URXEN = 1; //enable receiver U2STAbits.UTXEN = 1; U2MODEbits.ON = 0; //disable module //Setup port 5 // U5MODEbits.ON = 0; //disable module U5STA = 0; U5STAbits.UTXEN = 0; //disable transmitter IPC12bits.U5IP = 7; //priority 7 IPC12bits.U5IS = 1; //sub-priority 1 U5STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted IFS2bits.U5TXIF = 0; //clear interrupt flag IEC2bits.U5TXIE = 0; //enable tx interrupt U5STAbits.URXISEL = 0b00; //interrupt for each character received IFS2bits.U5RXIF = 0; #ifdef POLL_UART2_RX IEC1bits.U2RXIE = 0; //disable rx interrupts #else IEC2bits.U5RXIE = 1; //enable rx interrupts #endif U5STAbits.URXEN = 1; //enable receiver U5STAbits.UTXEN = 1; U5MODEbits.ON = 0; //disable module int i; for(i = 0; i < MAX_INTERNAL_UART_PORT; i++) { astInternalUartData[i].pcTxDataPtr = 0; astInternalUartData[i].iNbFIFOPendingBytes = 0; astInternalUartData[i].iTxDataSize = 0; astInternalUartData[i].iTxDataCounter = 0; astInternalUartData[i].iIsBusy = 0; astInternalUartData[i].iIsOpened = 0; astInternalUartData[i].iUartHandle = 0; } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //int SetIntalUartInterrupts(int p_iUartPort, int p_iRxInterrupt,int p_iTxInterrupt) //{ // if(p_iUartPort > MAX_INTERNAL_UART_PORT) // return UART_INVALID_PORT; // // switch(p_iUartPort) // { // case INTERNAL_UART_PORT_1: // { // if(p_iTxInterrupt) // { // IFS0bits.U1TXIF = 0; //clear interrupt flag // IEC0bits.U1TXIE = 1; //enable tx interrupt // } // else // { // IEC0bits.U1TXIE = 0; //disable tx interrupt // U1STAbits.UTXEN = 1; //This bit must be set when working without interrupts // } // if(p_iRxInterrupt) // { // IFS0bits.U1RXIF = 0; // IEC0bits.U1RXIE = 1; //enable rx interrupt // } // else // { // IEC0bits.U1RXIE = 0; //disable rx interrupt // } // break; // } // case INTERNAL_UART_PORT_2: // { // if(p_iTxInterrupt) // { // IFS1bits.U2TXIF = 0; //clear interrupt flag // IEC1bits.U2TXIE = 1; //enable tx interrupt // } // else // { // IEC1bits.U2TXIE = 0; //disable tx interrupt // U2STAbits.UTXEN = 1; //This bit must be set when working without interrupts // } // if(p_iRxInterrupt) // { // IFS1bits.U2RXIF = 0; // IEC1bits.U2RXIE = 1; //enable rx interrupt // } // else // { // IEC1bits.U2RXIE = 0; //disable rx interrupt // } // break; // } // default: // { // return UART_INVALID_PORT; // } // } // return UART_OK; //} //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- int OpenInternalPort(int p_iUartPort,int p_iUartHandle,char *p_pcHeadPtr, char *p_pcTailPtr, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable) { if(p_iUartPort > MAX_INTERNAL_UART_PORT) return UART_INVALID_PORT; int iBRG = (PERIPHERAL_FREQ/(4*p_iBaudRate)) - 1; int iMask = 0; switch(p_iNbStopBits) { case INT_UART_ONE_STOP_BIT: { break; } case INT_UART_TWO_STOP_BITS: { iMask |= 0x00000001; break; } } astInternalUartData[p_iUartPort].iUartHandle = p_iUartHandle; switch(p_iParityEnable) { case INT_UART_NO_PARITY: { break; } case INT_UART_EVEN_PARITY: { iMask |= 0x00000002; break; } case INT_UART_ODD_PARITY: { iMask |= 0x00000004; break; } } switch(p_iUartPort) { case INTERNAL_UART_PORT_1: { INTERNAL_UART1_TX_PIN_DIR = PIN_OUTPUT; INTERNAL_UART1_TX_PIN = 1; U1MODE = iMask; U1MODEbits.BRGH = 1; U1BRG = iBRG; U1MODEbits.ON = 1; //enable module break; } case INTERNAL_UART_PORT_2: { INTERNAL_UART2_TX_PIN_DIR = PIN_OUTPUT; INTERNAL_UART2_TX_PIN = 1; U2MODE = iMask; U2MODEbits.BRGH = 1; U2BRG = iBRG; U2MODEbits.ON = 1; //enable module break; } case INTERNAL_UART_PORT_5: { INTERNAL_UART5_TX_PIN_DIR = PIN_OUTPUT; INTERNAL_UART5_TX_PIN = 1; U5MODE = iMask; U5MODEbits.BRGH = 1; U5BRG = iBRG; U5MODEbits.ON = 1; //enable module break; } } astInternalUartData[p_iUartPort].iIsOpened = 1; return UART_OK; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- int SendInternalUartData(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort, char *p_pcSourceBufferHead, char *p_pcSourceBufferTail) { int iBufSize; int iAvailableBufSize; char *p_cDataPointer; int i; stInternalUartData *p_stUartDataPtr = &astInternalUartData[p_iUartPort]; if(p_stUartDataPtr->iIsOpened == 0) return UART_PORT_NOT_OPENED; //We use a FIFO stack that must be empty before a new transaction can occur //if(p_stUartDataPtr->iNbFIFOPendingBytes != 0) //If FIFO not empty if(p_stUartDataPtr->iIsBusy == 1) return UART_PORT_BUSY; //no space is available so flag the port as BUSY... iBufSize = p_iDataSize; if(iBufSize > INTERNAL_UART_BUFFER_DEPTH) iBufSize = INTERNAL_UART_BUFFER_DEPTH; p_cDataPointer = p_stUartDataPtr->pcTxDataPtr = &p_stUartDataPtr->acIntUartTxFIFO[0]; p_stUartDataPtr->iNbFIFOPendingBytes = iBufSize; //Fill FIFO with data; for(i = 0; i< iBufSize; i++) { *p_cDataPointer++ = *p_pcDataBuf++; if(p_pcDataBuf > p_pcSourceBufferTail) //check for wrapping of source data circular buffer. p_pcDataBuf = p_pcSourceBufferHead; } p_stUartDataPtr->iIsBusy = 1; //informative flag to know we are TXing. //Begin Transmission //A TX interrupt will be generated immediately after setting UTXEN switch(p_iUartPort) { case INTERNAL_UART_PORT_1: { if(IEC0bits.U1TXIE) { //We consider at this point that the data has been sent for the upper layer. DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); U1STAbits.UTXEN = 1; } else { int i; for(i = 0; i < iBufSize; i++) { // KickWatchdog(); U1TXREG = *p_stUartDataPtr->pcTxDataPtr++; while(U1STAbits.TRMT == 0); } p_stUartDataPtr->iIsBusy = 0; DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); } break; } case INTERNAL_UART_PORT_2: { if(IEC1bits.U2TXIE) { //We consider at this point that the data has been sent for the upper layer. DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); U2STAbits.UTXEN = 1; } else { int i; for(i = 0; i < iBufSize; i++) { // KickWatchdog(); U2TXREG = *p_stUartDataPtr->pcTxDataPtr++; while(U2STAbits.TRMT == 0); // LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN; } p_stUartDataPtr->iIsBusy = 0; DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); } break; } case INTERNAL_UART_PORT_5: { if(IEC2bits.U5TXIE) { //We consider at this point that the data has been sent for the upper layer. DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); U5STAbits.UTXEN = 1; } else { int i; for(i = 0; i < iBufSize; i++) { // KickWatchdog(); U5TXREG = *p_stUartDataPtr->pcTxDataPtr++; while(U5STAbits.TRMT == 0); // LTE_MODULE_TX_LED_PIN = ~ LTE_MODULE_TX_LED_PIN; } p_stUartDataPtr->iIsBusy = 0; DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize); } break; } } return UART_OK; } int SendInternalUartDataBlocking(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort) { int i; switch(p_iUartPort) { case INTERNAL_UART_PORT_1: { int temp = IEC1; IEC0bits.U1TXIE = 0; for(i = 0; i < p_iDataSize; i++) { // LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN; U1TXREG = *p_pcDataBuf++; while(U1STAbits.TRMT == 0); } // LORA_MODULE_TX_LED_PIN = LED_OFF; IFS0bits.U1TXIF = 0; IEC1 = temp; break; } case INTERNAL_UART_PORT_2: { int temp = IEC1; IEC1bits.U2TXIE = 0; for(i = 0; i < p_iDataSize; i++) { // LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN; U2TXREG = *p_pcDataBuf++; while(U2STAbits.TRMT == 0); } // LORA_MODULE_TX_LED_PIN = LED_OFF; IFS1bits.U2TXIF = 0; IEC1 = temp; break; } case INTERNAL_UART_PORT_5: { int temp = IEC2; IEC2bits.U5TXIE = 0; for(i = 0; i < p_iDataSize; i++) { // LTE_MODULE_TX_LED_PIN = ~ LTE_MODULE_TX_LED_PIN; U2TXREG = *p_pcDataBuf++; while(U5STAbits.TRMT == 0); } // LTE_MODULE_TX_LED_PIN = LED_OFF; IFS2bits.U5TXIF = 0; IEC2 = temp; break; } } return UART_OK; } void TickInternalUart(void) { #ifdef POLL_UART1_RX if(U1STAbits.URXDA == 1) { if(U1STAbits.OERR) //Buffer overrun error. Data is lost. { U1STAbits.OERR = 0; } int i = 0; while(U1STAbits.URXDA && i < INTERNAL_UART_BUFFER_DEPTH) { char NewByte = U1RXREG; // DriveProtocolRxData(&NewByte,1); acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte; } // UartReceiveData(UART_1,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i); // DriveProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i); } #endif #ifdef POLL_UART2_RX if(U2STAbits.URXDA == 1) { int i = 0; while(U2STAbits.URXDA == 1 && i < INTERNAL_UART_BUFFER_DEPTH) { char NewByte = U2RXREG; // acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte; LORA_MODULE_RX_LED_PIN = ~LORA_MODULE_RX_LED_PIN; ProtocolAnalyzeNewData(NewByte); // LoraData <<= 8; // unsigned int toto = NewByte; // toto &= 0x000000FF; // LoraData |= toto; // // if(LoraData == 0xDEADBEEF) // { // HEARTBEAT_LED_1_PIN = ~HEARTBEAT_LED_1_PIN; // LORA_ACTIVITY_LED_PIN = ~LORA_ACTIVITY_LED_PIN; // LoraData = 0; // } // HEARTBEAT_LED_2_PIN = ~HEARTBEAT_LED_2_PIN; } if(U2STAbits.OERR) //Buffer overrun error. Data is lost. { U2STAbits.OERR = 0; printf("Overrun\n"); } // UartReceiveData(UART_2,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i); // CUProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i); } #endif } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void __ISR(_UART_1_VECTOR, ipl7) InternalUart1AInterrupt(void) { stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1]; if(IFS0bits.U1TXIF && IEC0bits.U1TXIE) { IFS0bits.U1TXIF = 0; //Check if there is still data to send in FIFO if(p_acUartDataPtr->iNbFIFOPendingBytes == 0) { U1STAbits.UTXEN = 0; //all data sent, stop transmitter p_acUartDataPtr->iIsBusy = 0; } else { do { U1TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data p_acUartDataPtr->iNbFIFOPendingBytes--; } while((U1STAbits.UTXBF == 0) && //while there is space in buffer (p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send // HCAM // if(p_acUartDataPtr->iNbFIFOPendingBytes == 0) // { // // U1STAbits.UTXEN = 0; //all data sent, stop transmitter // p_acUartDataPtr->iIsBusy = 0; // } } } if(IFS0bits.U1RXIF && IEC0bits.U1RXIE) { char NewByte; int i; IFS0bits.U1RXIF = 0; if(U1STAbits.OERR) //Buffer overrun error. Data is lost. { U1STAbits.OERR = 0; IFS0bits.U1RXIF = 0; printf("UART1 OERR\n"); return; } i = 0; while(U1STAbits.URXDA) { NewByte = U1RXREG; acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte; } UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i); } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void __ISR(_UART_2_VECTOR, ipl7) InternalUart2Interrupt(void) { stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2]; if(IFS1bits.U2TXIF && IEC1bits.U2TXIE) { IFS1bits.U2TXIF = 0; //Check if there is still data to send in FIFO if(p_acUartDataPtr->iNbFIFOPendingBytes == 0) { U2STAbits.UTXEN = 0; //all data sent, stop transmitter p_acUartDataPtr->iIsBusy = 0; //LORA_MODULE_TX_LED_PIN = LED_OFF; } else { do { U2TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data p_acUartDataPtr->iNbFIFOPendingBytes--; // LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN; } while((U2STAbits.UTXBF == 0) && //while there is space in buffer (p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send } } if(IFS1bits.U2RXIF && IEC1bits.U2RXIE) { IFS1bits.U2RXIF = 0; char NewByte; int i; if(U2STAbits.OERR) //Buffer overrun error. Data is lost. { U2STAbits.OERR = 0; IFS1bits.U2RXIF = 0; printf("UART2 OERR\n"); return; } i = 0; while(U2STAbits.URXDA) { NewByte = U2RXREG; acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte; // LORA_MODULE_RX_LED_PIN = ~LORA_MODULE_RX_LED_PIN; } UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i); } } void __ISR(_UART_5_VECTOR, ipl7) InternalUart5Interrupt(void) { stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_5]; if(IFS2bits.U5TXIF && IEC2bits.U5TXIE) { IFS2bits.U5TXIF = 0; //Check if there is still data to send in FIFO if(p_acUartDataPtr->iNbFIFOPendingBytes == 0) { U5STAbits.UTXEN = 0; //all data sent, stop transmitter p_acUartDataPtr->iIsBusy = 0; //LORA_MODULE_TX_LED_PIN = LED_OFF; } else { // LTE_MODULE_TX_LED_PIN = LED_ON; do { U5TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data p_acUartDataPtr->iNbFIFOPendingBytes--; } while((U5STAbits.UTXBF == 0) && //while there is space in buffer (p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send // LTE_MODULE_TX_LED_PIN = LED_OFF; } } if(IFS2bits.U5RXIF && IEC2bits.U5RXIE) { IFS2bits.U5RXIF = 0; char NewByte; int i; if(U5STAbits.OERR) //Buffer overrun error. Data is lost. { U5STAbits.OERR = 0; IFS2bits.U5RXIF = 0; printf("UART5 OERR\n"); return; } i = 0; while(U5STAbits.URXDA) { NewByte = U5RXREG; acIntUartRxBuff[INTERNAL_UART_PORT_5][i++] = NewByte; // LTE_MODULE_RX_LED_PIN = ~LTE_MODULE_RX_LED_PIN; } UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_5][0], i); } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- /// Resets UART1 without closing it. Used when comm crashes. void ResetUart1(void) { U1MODEbits.ON = 0; //disable module U1STAbits.UTXEN = 0; //disable transmitter IEC0bits.U1TXIE = 0; //disable tx interrupt IFS0bits.U1TXIF = 0; //clear interrupt flag IEC0bits.U1TXIE = 1; //enable tx interrupt IEC0bits.U1RXIE = 0; //disable rx interrupts IEC0bits.U1RXIE = 0; //disable rx interrupts IFS0bits.U1RXIF = 0; #ifdef POLL_UART1_RX IEC0bits.U1RXIE = 0; //disable rx interrupts #else IEC0bits.U1RXIE = 1; //enable rx interrupts #endif U1STAbits.URXEN = 1; //enable receiver astInternalUartData[INTERNAL_UART_PORT_1].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1].acIntUartTxFIFO[0]; astInternalUartData[INTERNAL_UART_PORT_1].iTxDataSize = 0; astInternalUartData[INTERNAL_UART_PORT_1].iIsBusy = 0; U1MODEbits.ON = 1; //enable module } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void ResetUart2(void) { //Setup port 2 // U2MODEbits.ON = 0; //disable module U2STAbits.UTXEN = 0; //disable transmitter IEC1bits.U2TXIE = 0; //disable tx interrupt IFS1bits.U2TXIF = 0; //clear interrupt flag IEC1bits.U2TXIE = 0; //enable tx interrupt IEC1bits.U2RXIE = 0; //disable rx interrupts IFS1bits.U2RXIF = 1; #ifdef POLL_UART2_RX IEC1bits.U2RXIE = 0; //disable rx interrupts #else IEC1bits.U2RXIE = 1; //enable rx interrupts #endif U2STAbits.URXEN = 1; //enable receiver astInternalUartData[INTERNAL_UART_PORT_2].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2].acIntUartTxFIFO[0]; astInternalUartData[INTERNAL_UART_PORT_2].iTxDataSize = 0; astInternalUartData[INTERNAL_UART_PORT_2].iIsBusy = 0; U2MODEbits.ON = 1; //disable module } void ResetUart5(void) { //Setup port 2 // U5MODEbits.ON = 0; //disable module U5STAbits.UTXEN = 0; //disable transmitter IEC2bits.U5TXIE = 0; //disable tx interrupt IFS2bits.U5TXIF = 0; //clear interrupt flag IEC2bits.U5TXIE = 0; //enable tx interrupt IEC2bits.U5RXIE = 0; //disable rx interrupts IFS2bits.U5RXIF = 1; #ifdef POLL_UART2_RX IEC2bits.U5RXIE = 0; //disable rx interrupts #else IEC2bits.U5RXIE = 1; //enable rx interrupts #endif U5STAbits.URXEN = 1; //enable receiver astInternalUartData[INTERNAL_UART_PORT_5].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_5].acIntUartTxFIFO[0]; astInternalUartData[INTERNAL_UART_PORT_5].iTxDataSize = 0; astInternalUartData[INTERNAL_UART_PORT_5].iIsBusy = 0; U5MODEbits.ON = 1; //enable module } //----------------------------------------------------------------------------- void process(void) { } //EOF