Interrupt driver serial transmission buffer

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

Interrupt driver serial transmission buffer

Jump to solution
4,154 Views
barbercolman
Contributor III

My first MQX project involves serial communications. By using the examples I have the basics working. I have found the fwrite command but I having problems with finding the documentation of fwrite.

 

Specifics like when I call fwrite is it calling a MQX interrupt routine that will send the entire packet, or is there a chance that fwrite will be paused by MQX and the packet will not be sent as a continuous stream?

 

Should be simple, just haven't found the correct documentation.

Thanks

0 Kudos
1 Solution
1,962 Views
DavidS
NXP Employee
NXP Employee

Hi Barber,

No magical document that I can point you too.

The FSLMQX/mqx/examples/tfs example has good fread() and fwrite() stuff.

Using Interrupt mode for the SCI/UARTs/itty serial module is a way to decouple and automate the process for reading and writing serial data.  It is an efficient method by off loading the task/application and just letting the ISR handle the send/receive aspects by using buffers.

Conceptually the fwrite() is placing characters into a write buffer.  Once data is written into the write buffer, the SCI/UART/itty serial interface ISR will handle sending the data out of the buffer while your application continues on doing other stuff.  As long as there is data in the write buffer, the ISR will continuously send data.

Hope this helps.

Regards,

David

View solution in original post

0 Kudos
17 Replies
1,962 Views
kecart
Contributor III

Barber, Since you mentioned serial communications and interrupt, let me point you in the right general direction.  I'm most familiar with the MCF52259 so I'll use it for reference.  fwrite is a define found in fio.h to arrange parameters and call _io_write().  When the interrupt driven uart device driver is installed, the layers of software are set up so that ultimately a call to the function _io_serial_int_write() in serl_int.c is made.  This function may do some translation (cr to crlf) and then calls the next layer down with _io_serial_int_putc_internal().   That function checks for a full buffer and then either makes a call to _mcf52xx_uart_serial_int_putc located in serl_int_mcf52xx.c  or queues up the next byte, as appropriate.

 

I hope this helps.  There is an explaination of how the serial device driver code is structured( roughly what calls what ) in the MQXIOUG.pdf.

1,962 Views
barbercolman
Contributor III

Thanks for the help. I had look for more information on fwrite and missed the connection to io_write and beyond. I am now able to send and receive.

 

My next task is to figure out how to wait for 7 characters or a max of 100ms.

 

 

0 Kudos
1,960 Views
DavidS
NXP Employee
NXP Employee

Hi Barber,

Freescale has updating the UART driver to have timout on the "to-do-list" and hope to have it for our FSLMQX3.8 release in June time frame.

In mean time I played around with some code to do this and attached it.

You should be able to run it using the FSLMQX/mqx/example/io example.  I tested on TWRMCF52259.

Since I was testing with UART by typing....I had the timeout set at 8000 milliseconds.

These are the #define's I created:

#define INPUT_CHARACTER_DELAY_MILLISECONDS 8000
#define MAX_NUMER_OF_CHARACTERS 7

 

Please let forum know if this worked and/or if you modified or enhanced.

Hope this helps.

Regards,

David

PS

I couldn't upload with *.c file extension so named it main.txt :smileysad:

 

0 Kudos
1,960 Views
davidtietz
Contributor III

Hi David,

I was looking to implement character timeout as well in MQX. I see you attached sample code to do this, but I don't see the attachment. Am I doing something wrong? Can you reattach your work if you still have it?

Thanks,

David

0 Kudos
1,962 Views
DavidS
NXP Employee
NXP Employee

Hi David,

Our public forum site was updated Q3 last year and it appears not all attachments were ported.  Sorry.

Attached is my example file.  I haven't tried it lately but hope it is working fine.

Regards,

David

0 Kudos
1,961 Views
Cdn_aye
Senior Contributor I

Hi David

I am trying to solve the same problem and came across this post.

We are waiting for a serial stream from a BT device. We cannot tell how many characters will be in the stream. If we do a read with non blocking we often do not get the entire transmission and have no way to determine where we are in the stream. If we do a blocking read, we may not get any transmission and the whole task will just hang. Even if we get the transmission we do not know how many characters are being transmitted in the stream so we don't have a char count.

I thought what is needed is a read blocking with timeout, then we would read of multiple char's with timeout. Is there another way you could suggest? Or should we go to the work of implementing our own driver and handling each character through an installed MQX ISR?

Thanks

0 Kudos
1,961 Views
DavidS
NXP Employee
NXP Employee

Hi Robert,

Can you use the interrupt mode of the UART driver in MQX (ittyx)?

Then have a task to process the incoming stream and decide what to do with it?

The interrupt driver defaults to a queue size of 64 bytes defined in the (example name) BSP twrk70f120m.h header.  If that isn't big enough you can increase it.

Regards,

David


0 Kudos
1,961 Views
OliverSedlacek
Contributor III

Hi Robert,

This thread keeps coming up in my searches for an example of using itty on MQX. To improve responsiveness and reduce overhead I really, really want to change from polling the serial receiver to an interrupt driven implementation. I keep reading the UG and RM but I'm struggling to figure out what I need to do at a top level, but I'm guessing it would consist of:

* Configuring stdin/getchar to open an itty port rather than a tty port (in the BSP?)

* Installing my own interrupt handler to generate an event when a character has been received.

* Reworking my polling loop to wait on the event.

Am I close?

0 Kudos
1,961 Views
Cdn_aye
Senior Contributor I

Hi Oliver

I am sorry I just saw your post, I haven't checked back here in a long time.

The starting point is to build the MQX bsp for the serial port you are trying to use. You would make that change in the user_config.h file for the board/processor you are using. This is where it gets confusing in my estimation. The BSP files are built around a board concept usually a tower board. We have a custom board using a mk20dx256vll10 chip, we have to build the bsp for the twrk40x256. To me this is counter intuitive and took us a lot of time to resolve. I don't see a way to include my file so I will paste a portion here.

ITTYA enables the irq for UART.

Now I am going from memory of a few years ago here, but you also must modify one of the mqx source files and rebuild the BSP to get the driver to work and also setup your vector table. This was a long time ago. But if you look for my name, there was a question I asked and a person(woman)  replied saying where/how to set up the files.

The uart driver is a driver with blocking and non blocking calls, so you do not have to do all the low level work with registers; however this is also a trap. Read carefully my posts and problems and Davids answers. This is a really dismal driver. You can not do any type of frame recognition without extensive coding. You have to set this up for your own timeout by polling if a first char is received in non blocking mode and then returning to check the timeout and delaying. If character is there you have to find a way to get all the characters if this is a string. There in lies the problem. Where is the end of the string? What happens if the string is broken, you can't just read the buffer, mqx will short change you or give you part of another buffer. All in all, it is not a good driver in my estimation.

*
* $FileName: user_config.h$
* $Version : 3.8.19.0$
* $Date : Sep-18-2012$
*
* Comments:
*
* User configuration for MQX components
*
*END**************************************************************************/

#ifndef __user_config_h__
#define __user_config_h__

/* mandatory CPU identification */
#define MQX_CPU PSP_CPU_MK40DX256Z

#define BSP_DEFAULT_IO_CHANNEL "ttyb:" // rwl, default printf
//#define BSP_DEFAULT_IO_CHANNEL "ittya:" // rwl, change so printf's not going on BT channel, ittya
//#define BSP_DEFAULT_IO_CHANNEL_DEFINED
//#define BSP_DEFAULT_IO_CHANNEL "iodebug:"

#define BSPCFG_ENABLE_IO_SUBSYSTEM 1
//#define BSPCFG_ENABLE_IODEBUG 1

#define BSPCFG_ENABLE_TTYA 0
#define BSPCFG_ENABLE_ITTYA 1
#define BSPCFG_SCI0_BAUD_RATE 9600
#define BSPCFG_SCI0_QUEUE_SIZE 128

#define BSPCFG_ENABLE_TTYB 1 // defined so printf goes here
#define BSPCFG_ENABLE_ITTYB 0

#define BSPCFG_ENABLE_TTYC 0
#define BSPCFG_ENABLE_ITTYC 0

#define BSPCFG_ENABLE_TTYD 0
#define BSPCFG_ENABLE_ITTYD 0

#define BSPCFG_ENABLE_TTYE 0
#define BSPCFG_ENABLE_ITTYE 0

#define BSPCFG_ENABLE_TTYF 0
#define BSPCFG_ENABLE_ITTYF 0

Robert

0 Kudos
1,961 Views
OliverSedlacek
Contributor III

Robert, this forum doesn't seem to send out notifications, so I've only just seen your reply, for which I'm grateful. I've started a new thread in the hope of getting some fresh info.

0 Kudos
1,961 Views
Cdn_aye
Senior Contributor I

Hi David

I came across an old post of yours where you used the fstatus(...) check. This was an excellent solution and that solved the problem. I use the interrupt mode as you suggested, then check that a char is available using fstatus, then read in a stream of (n) bytes with a timeout. That way I never hang. It was impossible to do with just blocked reads and unblocked reads regardless of interrupt mode or not. It was simple to add the timeout and char length to the reads. I was going to post this today but you are ahead of me.

MQX will do just about anything we need, the problem is finding how to do achieve something specific, without the prior knowledge about the best practices and what is available to achieve the end. Once you know how to do it, it's all good and obvious. What is needed are some good tutorials; these questions are going around like a merry go round each year. Finding this out through the forums and by trial and error is really time consuming.

Thanks for replying.

Robert

1,962 Views
barbercolman
Contributor III

Hi

Any idea on when the next update to MQX will be out? Also, all the timer or _time_get functions appear to be using a 2K stack. Is there a way to get the tick count that does not require so much stack space?

 

 

 

0 Kudos
1,962 Views
Fabi
Contributor III

Is the timeout supported in MQX 3.8? I've looked at _io_serial_int_read() but haven't found any stuff for handling it.

0 Kudos
1,962 Views
DavidS
NXP Employee
NXP Employee

Hi Fabi,

I don't see a delay being supported for the serial interrupt driver.

But you can use IOCTL to set the driver mode to "IO_SERIAL_NON_BLOCKING".

When you try to read from the serial interrupt driver, if there are not characters to receive, then instead of blocking and waiting for a character, the driver will return a "0" indicating that no character is present and your code can progress.

Hope this helps.

Regards,

David

0 Kudos
1,962 Views
CarlFST60L
Senior Contributor II

It may also be helpful to note that MQX is based on Posix.

 

From the MQX User guide:

 

 

POSIX
Portable Operating System Interface, produced by IEEE and standardized by ANSI and ISO. MQX co
POSIX.1 (basic OS interfaces), POSIX.4 (real-time extensions), and POSIX.4a (threads extensions).

 

POSIXPortable Operating System Interface, produced by IEEE and standardized by ANSI and ISO. MQX coPOSIX.1 (basic OS interfaces), POSIX.4 (real-time extensions), and POSIX.4a (threads extensions).

 

This is a great place to start your research as this is the building blocks of MQX.

 

You may also want to research C file input/output

http://en.wikipedia.org/wiki/Fwrite#fwrite

 

 

0 Kudos
1,962 Views
DavidS
NXP Employee
NXP Employee

Thanks for helping Kelly.

Regards,

David

0 Kudos
1,963 Views
DavidS
NXP Employee
NXP Employee

Hi Barber,

No magical document that I can point you too.

The FSLMQX/mqx/examples/tfs example has good fread() and fwrite() stuff.

Using Interrupt mode for the SCI/UARTs/itty serial module is a way to decouple and automate the process for reading and writing serial data.  It is an efficient method by off loading the task/application and just letting the ISR handle the send/receive aspects by using buffers.

Conceptually the fwrite() is placing characters into a write buffer.  Once data is written into the write buffer, the SCI/UART/itty serial interface ISR will handle sending the data out of the buffer while your application continues on doing other stuff.  As long as there is data in the write buffer, the ISR will continuously send data.

Hope this helps.

Regards,

David

0 Kudos