#include "LPC13xx.h"
#include "dataBufferHandler.h"
#include "usart.h"
#define SystemFrequency SystemCoreClock
extern volatile Queue *qAvailableBuffers;
extern volatile Queue *qRXPacketBReady;
uint32_t UARTTxEmpty = 1;
volatile uint8_t rxTempData;
volatile uint32_t rxTemp;
volatile uint32_t state = 0;
//****************** Added 02/03/12*******
uint32_t flag = 0;
volatile MultiBuffer *usartRxBuffer;
volatile uint32_t rxBufferCount = 0; // keeps track of number of chars available.
//*******************************************************
//********************Added 19/03/12*********************
extern volatile Queue qRXPacketReady;
/*****************************************************************************
** Function name: UARTInit
**
** Descriptions: Initialize UART0 port, setup pin select,
** clock, parity, stop bits, FIFO, etc.
**
** parameters: UART baudrate
** Returned value: None
**
*****************************************************************************/
void UARTInit(void)
{
uint32_t Fdiv;
uint32_t regVal;
uint32_t baudrate = 115200;
NVIC_DisableIRQ(UART_IRQn);
LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */
/* Enable UART clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */
LPC_UART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
regVal = LPC_SYSCON->UARTCLKDIV;
Fdiv = (((SystemFrequency/LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate ; /*baud rate */
LPC_UART->DLM = Fdiv / 256;
LPC_UART->DLL = Fdiv % 256;
LPC_UART->LCR = 0x03; /* DLAB = 0 */
LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
/* Read to clear the line status. */
regVal = LPC_UART->LSR;
/* Ensure a clean start, no data in either TX or RX FIFO. */
// CodeRed - added parentheses around comparison in operand of &
while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
while ( LPC_UART->LSR & LSR_RDR )
{
regVal = LPC_UART->RBR; /* Dump data from RX FIFO */
}
/* Enable the UART Interrupt */
NVIC_EnableIRQ(UART_IRQn);
#if TX_INTERRUPT
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
#else
LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */
#endif
return;
}
/*****************************************************************************
** Function name: UART_IRQHandler
**
** Descriptions: UART interrupt handler
** It really handles reception of packets
**
** parameters: None
** Returned value: None
**
** Notes:
** - I have a bit of a problem with this routine. It seems to have
** to much in it for a interrupt handling routine. I would rather
** prefer if we just incremented/set a flag to denote that there
** are char waiting in the USART RX hardware buffer.
** This will mean that we need to check that flag at regular intervals.
**
** As I add more functionality this routine will create problems because
** I am spending to much time in the interrupt routine.
**
** Thinking about it do I need an interrupt for every character received?
** I don't think so, only if communications on the USART are the priority.
**
*****************************************************************************/
void UART_IRQHandler(void)
{
volatile uint8_t rxTempData;
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;
/******** Added 02/03/12*******/
if(flag == 0) /* flag needs to be Global*/
{
usartRxBuffer = getElementFromQueue(qAvailableBuffers);
flag = 1;
}
/******************************/
IIRValue = LPC_UART->IIR;
IIRValue >>= 1; /* skip pending bit in IIR, this is OK but may be needed
at some other stage*/
IIRValue &= 0x07; /* check bit 1~3, interrupt identification by masking the 3 bits*/
/* One way to check for received data, it also checks for line errors */
if (IIRValue == IIR_RLS) /* Receive Line Status check for type of interrupt */
{
LSRValue = LPC_UART->LSR; /* check if there is any line error */
/* Receive Line Status */
if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
{
/* There are errors or break interrupt, hence we need as minimum
* clear the interrupts we probably should also dump the data
* in the buffer*/
/* Read LSR will clear the interrupt */
rxTemp = LSRValue;
Dummy = LPC_UART->RBR; /* Dummy read on RX to clear
interrupt, then bail out */
return; /* needs checking */
}
}
/* This is a modification to the program's previous version, it should work, but needs checking */
if ((LSRValue & LSR_RDR)|(IIRValue == IIR_RDA)) /* Receive Data Ready | Receive Data Available*/
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt, this is important
* or else on the next if statement bellow it will again react to the interrupt*/
/* Receive Data Available */
rxTempData = LPC_UART->RBR;
/*Check for startChar
No checks required, I think. if a Start Char is received
dump packet and restart. */
if(rxTempData == TXPSTARTCHAR)
{
rxBufferCount = 0;
state = 1;
if (state == 0)
{
usartRxBuffer->buffer[rxBufferCount] = rxTempData;
rxBufferCount++;
state = 1; /*Start character as been received and it is possibly a valid packet */
return;
}
/*Another Start Char as been received without end of packet. needs error handling */
if (state == 1)
{
releaseBuffer(usartRxBuffer);
rxBufferCount = 0;
state = 0;
flag = 0;
}
}
if((state == 1)&(rxTempData != TXPENDCHAR))
{
rxBufferCount++;
/*Resulting Data will not include StartChar*/
usartRxBuffer->buffer[rxBufferCount++] = rxTempData;
/*Resulting Data will not include StartChar*/
}
/*Normal state packet is ready for processing*/
if((state == 1)&(rxTempData == TXPENDCHAR))
{
usartRxBuffer->buffer[rxBufferCount++] = rxTempData;
usartRxBuffer->buffer[107] = rxBufferCount;
addElementToQueue(qRXPacketBReady, usartRxBuffer);
state = 0;
rxBufferCount = 0;
flag = 0;
}
/* Packet length time out, no error handling for now */
if(rxBufferCount > MAXPACKETLENGTH)
{
releaseBuffer(usartRxBuffer);
state = 0;
flag = 0;
}
}
/* Not quiet sure I need this or what actually does */
else if (IIRValue == IIR_CTI) /* Character timeout indicator */
{
/* Character Time-out indicator */
rxTemp |= 0x100; /* Bit 9 as the CTI error */
}
/* This is for the TX part probably not needed */
else if (IIRValue == IIR_THRE) /* THRE, transmit holding register empty */
{
/* THRE interrupt */
LSRValue = LPC_UART->LSR; /* Check status in the LSR to see if
valid data in U0THR or not */
if (LSRValue & LSR_THRE)
{
UARTTxEmpty = 1;
}
else
{
UARTTxEmpty = 0;
}
}
Dummy = LPC_UART->RBR;
}
|