Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Implementing Queue in micro-controller to handle packet from Serial Port??

Status
Not open for further replies.

xpress_embedo

Advanced Member level 4
Advanced Member level 4
Joined
Jul 5, 2011
Messages
1,154
Helped
161
Reputation
396
Reaction score
189
Trophy points
1,353
Location
India
embeddedlaboratory.blogspot.in
Activity points
10,591
Hello!! Everyone,

I have to implement a queue in micro-controller, that is simple when the values stored are of single, double bytes, But what to do when there is a need to save a 20 bytes long packet.

I am confused how to implement this.

My Application Requirement is as follow:-

Micro-controller has to receive packet from serial port which is 20 bytes(Maximum) long and then have to check its validity and then store it in a queue and so on until an event occurs.
If an event occurs then the First Packet in Queue is processed, as in FIFO method, if another event occurs then another packet gets processed.
If in between another packet comes, it gets added to Message Queue.

What will be the structure for this, can anyone please help me to solve this.
I am using PIC18F4550 micro-controller and xc8 v1.31 compiler along with MPLAB X 2.10.

Thanks in Advance.
 

the simplest way is probably to implement FIFO using ring buffer of sufficent length to hold the maximum number of packets
e.g. this is for a PIC24 but the concept will work for a PIC18
allocacte storage
Code:
#define BUFFER 100
static unsigned char U2rxBuffer[BUFFER]={0},  
               * U2rxIn=0, * U2rxOut=0;
int U2number=0;		// number of characters in buffer
int U2error=0;    	// number of buffer overflows

in the UART setup initialise the pointers etc
Code:
    U2rxIn= U2rxOut= U2rxBuffer;
    U2number=U2error=0;

in UART interrupt routine add character to buffer
Code:
void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
    * U2rxIn++ = U2RXREG;									// read character into buffer
    if(U2rxIn >= U2rxBuffer+BUFFER) 
          U2rxIn=U2rxBuffer;	// check for end of buffer
    if(U2number++>=BUFFER)     // check for buffer overflow
        {  U2rxIn= U2rxOut= U2rxBuffer;  U2number=0; U2error++;}
   _U2RXIF = 0;						// clear interrupt flag
}
and to extract the data
Code:
//Function:UART GetChar : waits for a byte to be received.  It then returns that byte.
char UART2GetChar()
{
    char Temp;
    while(U2rxIn == U2rxOut) Nop();		// wait for character
    Temp = *U2rxOut++;					// get character
    U2number--;
    if(U2rxOut == U2rxBuffer+BUFFER)  U2rxOut=U2rxBuffer;	// check for end of buffer
    return Temp;
}
the above is working character by character but you can modify it to wait for a packet of the appropriate size or an event etc
 
Last edited:
Alternative but similar code from one of my projects:
Code:
//*******************************************************************************
// receives and buffers data arriving on the system link
void ByteFromBus()   
{
	char BusRxByte = WaitRx();
	
	if(BusRxByte == STX) 
	{
		BusRxPtr = 0;
		*BusRxBuffer = 0;
		return;
	}
	
	if(BusRxByte == CR) 
	{
		BusPacketReceived = 1;
		return;
	}

	if(BusRxPtr < BUSRXBUFFERSIZE - 1)
	{
		BusRxBuffer[BusRxPtr++] = BusRxByte;
		BusRxBuffer[BusRxPtr] = 0;
	}
}

In this application the data starts with an ascii STX character (0x02) and ends with a carriage return character (CR), the routine is called by an interrupt from USART1 and the data is recovered by reading 'WaitRx()'. The BUSRXBUFFERSIZE is defined to be the maximum length of the data packet and the when all bytes are received the result is in the array 'BusRxBuffer[]'. The main program is alerted to the completion of the packet by the 'BusPacketReceived' variable being equal to 1. Note that it prevents buffer overflow and always terminates the buffer with a NUL character.

Brian.
 
as betwixt says in previous post if you are sending a packet it is a good idea to create a frame with frame start and terminator.
STX as start and ETX (or CR) as terminator are fine for ASCII data
if you are sending binary data (where the data may contain the terminator and prematurely terminate the frame) you can use character stuffing to overcome the problem. If using synchronous serial you can use bit stuffing.

if the data is critical it would be a good idea to include a checksum or a CRC check to verify correct reception. In case of error you could either discard the data and display an error message or request retransmission.
 
Hello Thanks for your replies.

My Packet has Header and Footer, in between there are ascii values, and my method which is used is almost similar to the betwixt method, just i am doing that whole thing in UART Interrupt and the process it later in while loop when an event happens.
My problem is storing the whole packet in queue, i didn't able to get how to store the Packet in queue.
whether queue whole packets or just create a pointer which stores the strings and pass this pointer address in queue.
This looks simple but problem is that whether malloc like functions are supported in xc8 compiler, because i had read somewhere that malloc is not supported but when i tried to compile a code it gets compiled but had not tested that program.

I will try to do and post my program here if gets stuck somewhere.
 

Hello Thanks for your replies.

This looks simple but problem is that whether malloc like functions are supported in xc8 compiler, because i had read somewhere that malloc is not supported but when i tried to compile a code it gets compiled but had not tested that program.

I will try to do and post my program here if gets stuck somewhere.
section 5.5.7 Dynamic Memory Allocation of the MPLAB® XC8 C Compiler User’s Guide states
Dynamic memory allocation, (heap-based allocation using malloc, etc.) is not supported
on any 8-bit device. This is due to the limited amount of data memory, and that
this memory is banked. The wasteful nature of dynamic memory allocation does not
suit itself to the 8-bit PIC device architectures.


you will have to allocate a static array assuming to largest set of packets you are likly to receive
 
Dynamic Memory Allocation of the MPLAB® XC8 C Compiler User’s Guide states Dynamic memory allocation, (heap-based allocation using malloc, etc.) is not supported on any 8-bit device.
Even if it would be supported, it's just pointless to use it for an UART FIFO. More generally speaking, dynamic memory allocation is rarely useful in embedded processing. It has a purpose if a block of memory should be alternatively assigned to different tasks, or if an instrument is somehow dynamically configured so that in configuration A a memory block is needed fore one purpose and for different purpose in configuration B.
 
xpress_embedo, in your case it would be simplest to allocate an array of incoming packet buffers and as each receives it's packet, move on to the next. When the last buffer has been used, loop back to the first one again. It's easy to do if you keep two index values for the buffers, one for the buffer you are writing to and one for the buffer you are reading from. One 'chases' the other until their values are equal which means the queue is empty.

Brian.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top