123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- #include <stdio.h>
- #include <string.h>
- #include <gfambrtucom.h>
- #include "inc/hw_types.h"
- #include "inc/hw_uart.h"
- #include "driverlib/interrupt.h"
- #include "driverlib/sysctl.h"
- #include "driverlib/gpio.h"
- #include "driverlib/uart.h"
- #include <gfautils.h>
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- static HFIFO g_hFifoTX = NULL, g_hFifoRX = NULL;
- static volatile uint32_t g_nTxEchoCount = 0;
- static volatile uint64_t g_nTimerTick = 0;
- static GFA_UART_STATUS_COUNTERS g_statCnt = {0};
- static GFA_UART_CONFIG g_uartCfg = {0};
- static GFA_MODBUS_PROTOCOL_TIMEOUTS g_mpt = {0};
- /////////////////////////////////////////////////////////////////////////////
- #define GFA_UART_BASE g_uartCfg.P_UART_BASE
- #define GFA_UART_BASE_SYSCTL g_uartCfg.P_UART_BASE_SYSCTL
- #define GFA_UART_PORT g_uartCfg.P_UART_PORT
- #define GFA_UART_PORT_SYSCTL g_uartCfg.P_UART_PORT_SYSCTL
- #define GFA_UART_RX_PIN g_uartCfg.P_UART_RX_PIN
- #define GFA_UART_RX_PIN_MUX g_uartCfg.P_UART_RX_PIN_MUX
- #define GFA_UART_TX_PIN g_uartCfg.P_UART_TX_PIN
- #define GFA_UART_TX_PIN_MUX g_uartCfg.P_UART_TX_PIN_MUX
- #define GFA_UART_INT g_uartCfg.P_UART_INT
- #define GFA_EN_485_PORT_SYSCTL g_uartCfg.P_EN_485_PORT_SYSCTL
- #define GFA_EN_485_PORT g_uartCfg.P_EN_485_PORT
- #define GFA_EN_485_PIN g_uartCfg.P_EN_485_PIN
- #define GFA_UART_INT_PRIORITY g_uartCfg.P_UART_INT_PRIORITY
- #define GFA_FRAME_TIMEOUT_US g_mpt.nFrameTimeoutUs
- #define GFA_CHAR_TIMEOUT_US g_mpt.nCharTimeoutUs
- #define IS_INT_ENABLED(f) !!(HWREG(GFA_UART_BASE + UART_O_IM) & (f))
- #define INT_MASK_REGISTER HWREG(GFA_UART_BASE + UART_O_IM)
- /////////////////////////////////////////////////////////////////////////////
- static bool _TimerElapsed(void)
- {
- struct timeval tv;
- return g_nTimerTick < GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv));
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _FrameTimerStart(void)
- {
- struct timeval tv;
- g_nTimerTick = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + GFA_FRAME_TIMEOUT_US;
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _CharTimerStart(void)
- {
- struct timeval tv;
- g_nTimerTick = GfaSystickTimeval2Us(GfaSystickGetUsClock(&tv)) + GFA_CHAR_TIMEOUT_US;
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _OnRxFinalize(void)
- {
- _FrameTimerStart();
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _OnTxPrepare(void)
- {
- return _TimerElapsed();
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _OnTxStart(void)
- {
- uint8_t b;
- if(!UARTBusy(GFA_UART_BASE) && GfaMbFifoPop(g_hFifoTX, &b, false))
- {
- g_nTxEchoCount++;
- GPIOPinWrite(GFA_EN_485_PORT, GFA_EN_485_PIN, GFA_EN_485_PIN); // enable the bus
- UARTIntEnable(GFA_UART_BASE, UART_INT_TX);
- ++g_statCnt.nCharsTransmitted;
- UARTCharPutNonBlocking(GFA_UART_BASE, b);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _OnTxFinalize(void)
- {
- return !UARTBusy(GFA_UART_BASE) && _TimerElapsed();
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _UART_RX_ISR(void)
- {
- uint8_t b;
- if(g_nTxEchoCount)
- {
- UARTCharGetNonBlocking(GFA_UART_BASE); // discard transmit echo chars
- --g_nTxEchoCount;
- _FrameTimerStart();
- return;
- }
- ++g_statCnt.nCharsReceived;
- if(_TimerElapsed()) // check, if the time since the last character was received, is greater than 3.5/1.5 characters
- {
- GfaMbFifoReset(g_hFifoRX, false);
- GfaMbFifoSetFlags(g_hFifoRX, MB_RTU_FLAG_FRAME_GAP_DETECT, false);
- if(GfaMbFifoMatchFlags(g_hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, false))
- {
- GfaMbFifoClearFlags(g_hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, false);
- }
- GfaMbFifoClearFlags(g_hFifoTX, MB_RTU_FLAG_TRANSMIT_END, false);
- }
- else if(GfaMbFifoMatchFlags(g_hFifoRX, MB_RTU_FLAG_IGNORE_FRAME, false))
- {
- UARTCharGetNonBlocking(GFA_UART_BASE); // discard chars
- _FrameTimerStart();
- return;
- }
- else if(GfaMbFifoMatchFlags(g_hFifoTX, MB_RTU_FLAG_TRANSMIT_END, false))
- {
- UARTCharGetNonBlocking(GFA_UART_BASE); // discard chars
- GfaMbFifoReset(g_hFifoRX, false);
- return;
- }
- b = (uint8_t)UARTCharGetNonBlocking(GFA_UART_BASE);
- GfaMbFifoPush(g_hFifoRX, b, false);
- _CharTimerStart();
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _UART_TX_ISR(void)
- {
- uint8_t b;
- if(GfaMbFifoPop(g_hFifoTX, &b, false))
- {
- ++g_nTxEchoCount;
- UARTCharPutNonBlocking(GFA_UART_BASE, b);
- ++g_statCnt.nCharsTransmitted;
- }
- else
- {
- UARTIntDisable(GFA_UART_BASE, UART_INT_TX);
- GPIOPinWrite(GFA_EN_485_PORT, GFA_EN_485_PIN, 0); // disable the bus
- GfaMbFifoClearFlags(g_hFifoTX, MB_RTU_FLAG_TRANSMIT_IN_PROGRESS, false);
- GfaMbFifoSetFlags(g_hFifoTX, MB_RTU_FLAG_TRANSMIT_END, false);
- _FrameTimerStart();
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _UART_OE_ISR(void)
- {
- ++g_statCnt.nOverrunErrors;
- GfaMbFifoSetFlags(g_hFifoRX, MB_RTU_FLAG_OVERRUN_ERROR, false);
- }
- static void _UART_BE_ISR(void)
- {
- ++g_statCnt.nBreakErrors;
- GfaMbFifoSetFlags(g_hFifoRX, MB_RTU_FLAG_BREAK_ERROR, false);
- }
- static void _UART_PE_ISR(void)
- {
- ++g_statCnt.nParityErrors;
- GfaMbFifoSetFlags(g_hFifoRX, MB_RTU_FLAG_PARITY_ERROR, false);
- }
- static void _UART_FE_ISR(void)
- {
- ++g_statCnt.nFramingErrors;
- GfaMbFifoSetFlags(g_hFifoRX, MB_RTU_FLAG_FRAMING_ERROR, false);
- }
- /////////////////////////////////////////////////////////////////////////////
- static void _UART_ISR(void)
- {
- uint32_t nStatus = UARTIntStatus(GFA_UART_BASE, true); // Get the interrrupt status.
- UARTIntClear(GFA_UART_BASE, nStatus); // Clear the asserted interrupts.
- if(nStatus & UART_INT_TX)
- _UART_TX_ISR();
- if(nStatus & UART_INT_RX)
- _UART_RX_ISR();
- if(nStatus & UART_INT_OE) // UART Overrun Error
- _UART_OE_ISR();
- if(nStatus & UART_INT_BE) // UART Break Error
- _UART_BE_ISR();
- if(nStatus & UART_INT_PE) // UART Parity Error
- _UART_PE_ISR();
- if(nStatus & UART_INT_FE) // UART Framing Error
- _UART_FE_ISR();
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _EnableRxInt(bool bEnable)
- {
- bool bIsEnabled = IS_INT_ENABLED(UART_INT_RX);
- if(bEnable && !bIsEnabled)
- UARTIntEnable(GFA_UART_BASE, UART_INT_RX);
- else if(!bEnable && bIsEnabled)
- UARTIntDisable(GFA_UART_BASE, UART_INT_RX);
- return bIsEnabled;
- }
- /////////////////////////////////////////////////////////////////////////////
- static bool _EnableTxInt(bool bEnable)
- {
- bool bIsEnabled = IS_INT_ENABLED(UART_INT_TX);
- if(bEnable && !bIsEnabled)
- UARTIntEnable(GFA_UART_BASE, UART_INT_TX);
- else if(!bEnable && bIsEnabled)
- UARTIntDisable(GFA_UART_BASE, UART_INT_TX);
- return bIsEnabled;
- }
- /////////////////////////////////////////////////////////////////////////////
- static uint32_t _GetDatabits(int nDatabits)
- {
- switch(nDatabits)
- {
- case 5:
- return UART_CONFIG_WLEN_5;
- case 6:
- return UART_CONFIG_WLEN_6;
- case 7:
- return UART_CONFIG_WLEN_7;
- case 8:
- return UART_CONFIG_WLEN_8;
- default:
- return (uint32_t)-1;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static uint32_t _GetStopbits(int nStopbits)
- {
- switch(nStopbits)
- {
- case 1:
- return UART_CONFIG_STOP_ONE;
- case 2:
- return UART_CONFIG_STOP_TWO;
- default:
- return (uint32_t)-1;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- static uint32_t _GetParity(GfA_UART_Parity parity)
- {
- switch(parity)
- {
- case P_None:
- return UART_CONFIG_PAR_NONE;
- case P_Even:
- return UART_CONFIG_PAR_EVEN;
- case P_Odd:
- return UART_CONFIG_PAR_ODD;
- case P_Zero:
- return UART_CONFIG_PAR_ZERO;
- case P_One:
- return UART_CONFIG_PAR_ONE;
- default:
- return (uint32_t)-1;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
- bool GfaMbUartInit(LPCGFA_UART_CONFIG pCfg)
- {
- uint32_t nData, nStop, nPar;
- GFA_FIFO_BACKEND backend;
- /////////////////////////////////////////////////////////////////////////
- // validate parameters
- if(!pCfg)
- return false;
- if((nData = _GetDatabits(pCfg->nDatabits)) == (uint32_t)-1)
- return false;
- if((nStop = _GetStopbits(pCfg->nStopbits)) == (uint32_t)-1)
- return false;
- if((nPar = _GetParity(pCfg->parity)) == (uint32_t)-1)
- return false;
- if(pCfg->nFifoIndexTx == pCfg->nFifoIndexRx)
- return false;
- memcpy(&g_uartCfg, pCfg, sizeof(g_uartCfg));
- /////////////////////////////////////////////////////////////////////////
- // Fifos
- memset(&backend, 0, sizeof(backend));
- backend.pfnLockBackend = _EnableTxInt;
- backend.pfnTxPrepare = _OnTxPrepare;
- backend.pfnTxStart = _OnTxStart;
- backend.pfnTxFinalize = _OnTxFinalize;
- if(!(g_hFifoTX = GfaMbFifoCreate(pCfg->nFifoIndexTx, &backend)))
- return false;
- memset(&backend, 0, sizeof(backend));
- backend.pfnLockBackend = _EnableRxInt;
- backend.pfnRxFinalize = _OnRxFinalize;
- if(!(g_hFifoRX = GfaMbFifoCreate(pCfg->nFifoIndexRx, &backend)))
- {
- GfaMbFifoRelease(g_hFifoTX);
- g_hFifoTX = NULL;
- return false;
- }
- /////////////////////////////////////////////////////////////////////////
- // Timer tick
- g_nTimerTick = 0;
- /////////////////////////////////////////////////////////////////////////
- // UART
- if(!GfaMbCalcProtocolTimeouts(pCfg->nBaud, &g_mpt))
- return false;
- // Enable and setup the PORT that is used for the UART
- SysCtlPeripheralEnable(GFA_UART_PORT_SYSCTL);
- while(!SysCtlPeripheralReady(GFA_UART_PORT_SYSCTL))
- ;
- // Enable and setup the PORT that is used for EN_485
- SysCtlPeripheralEnable(GFA_EN_485_PORT_SYSCTL);
- while(!SysCtlPeripheralReady(GFA_EN_485_PORT_SYSCTL))
- ;
- GPIOPinTypeGPIOOutput(GFA_EN_485_PORT, GFA_EN_485_PIN);
- // Enable the uart used for RS485 interface
- SysCtlPeripheralEnable(GFA_UART_BASE_SYSCTL);
- while(!SysCtlPeripheralReady(GFA_UART_BASE_SYSCTL))
- ;
- // Configure the UART pins
- GPIOPinConfigure(GFA_UART_RX_PIN_MUX);
- GPIOPinConfigure(GFA_UART_TX_PIN_MUX);
- GPIOPinTypeUART(GFA_UART_PORT, GFA_UART_RX_PIN | GFA_UART_TX_PIN);
- // Initialize the UART. Set the baud rate, number of data bits, turn off
- // parity, number of stop bits, and stick mode.
- UARTConfigSetExpClk(GFA_UART_BASE, SysCtlClockGet(), pCfg->nBaud, nData | nStop | nPar);
- // transmit interrupt is asserted when the transmitter is completely idle
- UARTTxIntModeSet(GFA_UART_BASE, UART_TXINT_MODE_EOT);
- // Enable the UART interrupt.
- IntPrioritySet(GFA_UART_INT, GFA_UART_INT_PRIORITY); // priority must be lower than system tick
- UARTIntRegister(GFA_UART_BASE, _UART_ISR);
- UARTIntEnable(GFA_UART_BASE, (UART_INT_RX | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE));
- // Enable the UART.
- UARTEnable(GFA_UART_BASE);
- UARTFIFODisable(GFA_UART_BASE);
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaMbUartRelease(void)
- {
- UARTIntDisable(GFA_UART_BASE, UART_INT_RX | UART_INT_TX | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
- UARTIntUnregister(GFA_UART_BASE);
- UARTDisable(GFA_UART_BASE);
- SysCtlPeripheralDisable(GFA_UART_BASE_SYSCTL);
- SysCtlPeripheralDisable(GFA_EN_485_PORT_SYSCTL);
- SysCtlPeripheralDisable(GFA_UART_PORT_SYSCTL);
- if(g_hFifoRX)
- {
- GfaMbFifoRelease(g_hFifoRX);
- g_hFifoRX = NULL;
- }
- if(g_hFifoTX)
- {
- GfaMbFifoRelease(g_hFifoTX);
- g_hFifoTX = NULL;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- HFIFO GfaMbUartGetRxFifo(void)
- {
- return g_hFifoRX;
- }
- /////////////////////////////////////////////////////////////////////////////
- HFIFO GfaMbUartGetTxFifo(void)
- {
- return g_hFifoTX;
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaMbUartGetProtocolTimeouts(LPGFA_MODBUS_PROTOCOL_TIMEOUTS pmpt)
- {
- if(pmpt)
- memcpy(pmpt, &g_mpt, sizeof(g_mpt));
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaMbUartGetStatusCounters(LPGFA_UART_STATUS_COUNTERS pSc)
- {
- if(pSc)
- {
- uint32_t nIrMask = INT_MASK_REGISTER;
- UARTIntDisable(GFA_UART_BASE, nIrMask);
- memcpy(pSc, &g_statCnt, sizeof(g_statCnt));
- UARTIntEnable(GFA_UART_BASE, nIrMask);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- void GfaMbUartResetStatusCounters(void)
- {
- uint32_t nIrMask = INT_MASK_REGISTER;
- UARTIntDisable(GFA_UART_BASE, nIrMask);
- memset(&g_statCnt, 0, sizeof(g_statCnt));
- UARTIntEnable(GFA_UART_BASE, nIrMask);
- }
|