MQX UART twrcf51cn problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MQX UART twrcf51cn problem

Jump to solution
2,150 Views
NeuroSolutions
Contributor I

I have a problem with the serial module.

 

First at all I have a LOT of doubts about set up the UART module with MQX. For example:

 

 

serial_fd =  fopen(BSP_DEFAULT_IO_CHANNEL, 0);
    baud_rate = 9600;
    flags=IO_SERIAL_NON_BLOCKING;
    ioctl(serial_fd, IO_IOCTL_SERIAL_SET_BAUD, &baud_rate);
    ioctl(serial_fd, IO_IOCTL_SERIAL_SET_FLAGS, &flags);
Then for reception I have to do the next:
 
char receive[248];
if (fstatus(serial_fd)) {
 read(serial_fd, &receive, 248);
}
Here my doubt with the flag =IO_SERIAL_NON_BLOCKING

 

 

the documentation saids:


 

"In this mode the _io_read() function doesn’t

wait till the receive buffer is full, but it

immediately returns received characters

and number of received characters."

 

I've declared char receive[248] with a size of 248 bytes because it's the maximun number of data that i can receive, but my messages have diffrentes size's. I mean in some moment I can receive "FF 00 09 01 01 14 E8" but in other moment i can receive 

"FF C8 65 00 00 00 0E 02 EA 00 0E 16 72 00 0D EF 62 00 0D D0 22 00 0E 18 66 00 0D ED 6E 00 0E 04 DE 00 0E 22 2A 00 0E 0E A2 00 0D D2 16 00 0D F7 32 00 0D CE 2E 00 0D E7 92 00 0D FD 0E 00 0E 24 1E 00 0E 10 96 00 0D F1 56 00 0E 1E 42 00 0D E5 9E 00 0D FB 1A 00 0E 14 7E 00 0D CC 3A 00 0D FF 02 00 0D E1 B6 00 0D CA 46 00 0D E9 86 00 0D D4 0A 00 0E 08 C6 00 0E 26 12 00 0E 12 8A 00 0D D7 F2 00 0E 0C AE 00 0D DF C2 00 0E 20 36 00 0E 0A BA 00 0D F5 3E 00 0D DD CE 00 0E 1C 4E 00 0D F9 26 00 0D E3 AA 00 0D C8 52 00 0D DB DA 00 0E 06 D2 00 0E 1A 5A 00 0D F3 4A 00 0D C6 5E 00 0D D9 E6 00 0E 00 F6 00 0D D5 FE 00 0D EB 7A 12 02"

 

When i call read(serial_fd, &receive, 248); I have 2 problems:

 

 

1. When i set the flag IO_SERIAL_NON_BLOCKING I only receipt the first byte

2. When I dont set the flag  IO_SERIAL_NON_BLOCKING the read function waits till the receive buffer is full. But it doesnt work for me. i need to receive a variable number of bytes and save the data into a variable.

 

If anyone can help me I'll be very grateful

0 Kudos
1 Solution
636 Views
DavidS
NXP Employee
NXP Employee

Hi Leonardo,

Glad your persistence paid off to allow you to find a solution.   Good work.

The idea behind the itty (SCI interrupt) mode is to hide the underlying driver and isr code from you so you only have to read/write when you want to.  If you really want to replace or edit the SCI interrupt then you are really editing the RTOS driver code rather than creating application level code. 

So your solution of doing the coding at application level to parse the characters received is really the best solution.

The SCI interrupt routine grabs the SCID value and places it in a FIFO buffer.  When you do a fread() if data is present in buffer, then it is given to you.  If not your code blocks.  Therefore you are indirectly reading the SCID register.

The FSLMQX/mqx/examples/isr demo is a good start for learning about linking to an exisiting periodic interrupt (the heart beat of the RTOS).  Pretty cool.

Hope this helps.

Regards,

David

View solution in original post

0 Kudos
4 Replies
636 Views
danielarenas
Contributor I

Hi Leonardo

How does it work the function that you used??

valid = EvaluateReceiveByte(receivedByte); //Machine State


BR

Daniel

0 Kudos
636 Views
DavidS
NXP Employee
NXP Employee

Hi NeuroSolutions,

Interesting issue.  I don't have solution at first but have questions for you.

Is the default TTY set for Polling or Interrupt mode?

Polling mode means that each time you want to read the UART, your code is blocking until it reads X characters.   So in this case you would want to know ahead of time how many bytes you want to receive at once.  Unless you only read one character at a time and them can determine from the data stream dynamically how many will be sent in the the stream. 

Interrupt mode means that even if your task isn't asking for characters, the UART interrupt routine will grab the characters and store them in a buffer (size determined in bsp processor support header (ex: twrmcf52259.h) as BSPCFG_UART0_QUEUE_SIZE.  Using Interrupt mode helps to prevent over running the UART internal charater buffer should you not poll fast enough or have a task blocking your polling efforts.

 

More genericall do you have a protocol established that will let you know what the variable stream length is going to be?  Ex: <size field><data field> or some character sequence that you can decode at beginning of packet stream to determine what the variable number will be? I ask because the issue seems to be not knowing the variable lenght of received data in the packet.  How do you know when to store what you have?

Or is there a variable data stream and it stops for a minute then sends another variable data stream?  So in this case you could use a timeout to say if I haven't received any more data the buffer received is all you get?

Regards,

David

0 Kudos
636 Views
NeuroSolutions
Contributor I

Hi David, thanks for the reply.

 

yes, I have a protocol <Header><size field><data field><CRC> and I already resolved the problem getting one char at time using

 

if (fstatus(serial_fd)) {     
      receivedByte = fgetc(serial_fd);

      valid = EvaluateReceiveByte(receivedByte); //Machine State

}

 

I started using the polled mode ttyb:, then I move to the interrupt mode with ittyb, but the main idea with a interrupt is that you know wich function will be called when a char has been received, and I dont know which is this function. Honestly i dont know how works the interrupts in MQX ( i would like that someone explain me with details :smileyhappy:).

I tried installing an ISR and doesnt work.

 

typedef struct my_isr_struct
{
   MCF51XX_sci_struct               OLD_ISR_DATA;   // Struct that contains the SCI_DATA??
   uint_8                caracter;
} MY_ISR_STRUCT, _PTR_ MY_ISR_STRUCT_PTR;

 

void new_tick_isr  (  pointer user_isr_ptr ){
   MY_ISR_STRUCT_PTR  isr_ptr;

   isr_ptr = (MY_ISR_STRUCT_PTR)user_isr_ptr;
   /* Here I have to get the SCID Value, but i dont know how! */

}

 

isr_ptr->OLD_ISR_DATA = _int_get_isr_data(MCF51CN_INT_Vsci2rx);

_int_install_isr(MCF51CN_INT_Vsci2rx, new_tick_isr, isr_ptr);

 

Then I have another question:

 

when I use_int_get_isr_data(MCF51CN_INT_Vsci2rx);

It returns a pointer with the data,  the data has this prototype MCF51XX_sci_struct????

 

Cause if not, How can I get the SCID value???

 

If you can post an example explaining how to install another ISR for the serial reception and get the SCID value when an interrupt happens it will be very helpful

 

 

Thanks.

 

Leonardo Arango Baena

 

 

0 Kudos
637 Views
DavidS
NXP Employee
NXP Employee

Hi Leonardo,

Glad your persistence paid off to allow you to find a solution.   Good work.

The idea behind the itty (SCI interrupt) mode is to hide the underlying driver and isr code from you so you only have to read/write when you want to.  If you really want to replace or edit the SCI interrupt then you are really editing the RTOS driver code rather than creating application level code. 

So your solution of doing the coding at application level to parse the characters received is really the best solution.

The SCI interrupt routine grabs the SCID value and places it in a FIFO buffer.  When you do a fread() if data is present in buffer, then it is given to you.  If not your code blocks.  Therefore you are indirectly reading the SCID register.

The FSLMQX/mqx/examples/isr demo is a good start for learning about linking to an exisiting periodic interrupt (the heart beat of the RTOS).  Pretty cool.

Hope this helps.

Regards,

David

0 Kudos