uart buffer is not read - c

I am trying to read binary data from a serial device in c on linux.
The problem is, that sometimes there are chars in the driver's internal buffer, but polling (with select(2)) returns saying the device is not ready to be read.
I have read and re-read the man of termios and all the related man and searched over the internet. I believe I set all the flags correctly (namely VTIME, VMIN) and unset ICANON.
I tried using the function "tcmakeraw", as well, but it didn't solve the problem.
Do you guys have any ideas about what should I do?
Kind regards & Thanks in advance
Yannay

You should show us the code. I would start with using cfmakeraw on the serial port.
Once you have things working in raw mode, you can make modification and see how it works.
Here is a list of question or things you could check :
after modifying the attribute, using for example cfmakeraw, do you call tcsetattr(...) to
apply your change ?
How do you prove there is still data in the driver receive buffer ?
do you check your system call for errors ?
what is the result of stracing your program ?
Edit based on your comments :
Your protocol "guarantee" .... => check your assumption ! Unchecked, crystal clear guarantee are a good coandidate for "impossible error"
Basically : either select is broken, or your serial driver. Reason for serial driver being broken is a hardware fifo not being full enough to trigger un interrupt, or loosing an interrupt.

What happens when you read directly (not through C) /dev/ttyS0 (or equiv) after you setserial your parameters. Are you able to get the needed data outside of the select()?

Related

What is the difference between a HAL_DAC_Stop_DMA vs a HAL_DAC_Stop?

I am running a DMA transfer through the DAC of an stmf303re nucleo, and was wondering if there was a difference between the HAL_DAC_Stop_DMA vs a HAL_DAC_Stop? I ask this because earlier on in my code I just used a HAL_DAC_Stop and it worked fine, however i now see that there is a HAL_DAC_Stop_DMA also and was wondering what the difference is?
If you started it with DMA you should stop it with the equivalent function. If you use the non-DMA stop function the ADC will stop but the DMA is still running waiting for the ADC to tell it more data is available. Obviously this will never come so the system is left in a funny state. Maybe the next start function can tidy up this funny state, or maybe it can't. Read the source of the functions if you want to find out the exact details.
Another possible problem of not using the DMA stop function could be that the last data produced by the ADC is still being copied by the DMA. This would mean that your destination buffer is not ready for you to use. Whether or not this causes a problem depends on how soon your code reads the destination buffer.

Parsing AT commands & responses in a circular buffer

I have a PIC32MM connected via UART with BT module RN4020 and currently struggling with it's configuration. It uses AT-command format COMMAND+CR+LF (or corresponsive ANSWER+CR+LF).
First, the module is set via special signal line into Command Mode, which after boot-up gives "CMD\r\n" on MCU's RX line. I am using default nifty functions provided by MPLAB IDE, which are based on circular buffers filled byte by byte during RX interrupt routine and I think I've already grasped the simple principle of how they work.
There even is a neat function ReadBuffer(target string, num of bytes to read) provided, which reads given amount of bytes from the rx circ buff into a given char array (buffer, string) to work with then.
My question is - what might be the best way to wait for and recognize a correct answer and then after it came and is checked, which means the module is ready for a command to be send via TX line, send a command. I need to signalize the moment when the answer from the module is fully read in MCU - in other words, when to call the ReadBuffer function so it gives me correct string back and I can be sure that I call ReadBuffer(my_target_string, 5) and my_target_string contains "CMD\r\n". I don't want to move the Head&Tail pointers unnecessarily wrongly, and mess up the structure. Is some kind of timeout a good way to proceed or is it even better to create some indicator flag and (un)set it when CR and LF come?
Thanks for any ideas or hints in advance.
After finding out, that the answer's home, some sort of string compare might be enough to check if it is what is expected I think. (Tricky might be '\0' character, but I'll try to keep that one in mind.)

Spi interrupt handler works when a printf() is used

I am trying to initiate a spi communication between an omap processor an sam4l one. I have configured spi protocol and omap is the master. Now what I see is the test data I am sending is correctly reaching on sam4l and I can see the isr is printing that data. Using more printf here and there in isr makes the operation happen and the respective operation happens, but if I remove all printfs I can't see any operation happening. What can be the cause of this anomaly? Is it a usual case of wrong frequency settings or something?
If code is needed I will post that too but its big.
Thanks
I think you are trying to print message in driver.
As printing message on console with slow down your driver, it may behave slowly and your driver work well.
Use pr_info() for debug and change setting to not come message on console by editing /proc/sys/kernel/printk to 4 4 1 7
-> It will store debug message in buffer.
-> Driver not slow down because of printing message on screen.
-> And you can see it by typing dmesg command later.
Then find orignal problem which may cause error.
If a routine works with printf "here and there" and not otherwise, almostcertainly the problem is that there are timing issues. As a trivial example, let's say you write to an SPI flash and then check its content. The flash memory write will take some times, so if you check immediately, the data would not be valid, but if you insert a printf call in between, it may have taken enough time that the read back is now valid.

Receive message of undefined size in UART in C

I'm writing my own drivers for LPC2148 and a question came to mind.
How do I receive a message of unspecified size in UART?
The only 2 things that come to mind are: 1 - Configure a watchdog and end the receiving when the time runs out. 2- make it so that whenever a meswsage is sent to it there must be an end of message character.
The first choice seems better in my opinion, but I'd like to know if anybody has a better answer, and I know there must be.
Thank you very much
Just give the caller whatever bytes you have received so far. The UART driver shouldn't try to implement the application protocol, the application should do that.
It looks like a wrong use for a watchdog. I ended up with three solutions for this problem:
Use fixed-size packets and DMA; so, you receive one packet per transaction. Apparently, it is not possible in your case.
Receive message char-by-char until the end-of-message character is received. Kind of error-prone, since the EOM char may appear in the data, probably.
Use a fixed-size header before every packet. In the header, store payload size and/or message type ID.
The third approach is probably the best one. You may combine it with the first one, i.e. use DMA to receive header and then data (in the second transaction, after the data size is known from the header). It is also one of the most flexible approaches.
One more thing to worry about is to keep bytestream in sync. There may be rubbish laying in the UART input buffers, which may get read as data, or you can get only a part of a packet after your MCU is powered (i.e. the beginning of the packet had already been sent by that time). To avoid that, you can add magic bytes in your packet header, and probably CRC.
EDIT
OK, one more option :) Just store everything you receive in a growing buffer for later use. That is basically what PC drivers do.
Real embedded uart drivers usually use a ring buffer. Bytes are stored in order and the clients promise to read from the buffer before it's full.
A state machine can then process the message in multiple passes with no need for a watchdog to tell it reception is over
better to go for option 2) append end of transmission character to the transmission string.
but i suggest to add start of transmission also to validate that you are receiving actual transmission.
Watchdog timer is used to reset system when there is a unexpected behavior of device. I think it is better to use a buffer which can store size of data that your application requires.

Write value to parallel port register

I'm trying to write to my lpt register with the function outb(0x378,val);
well.. I tried to debug with the call int ret=inb(0x378); I always get the ret=255 no matter what value I insert with outb before.
*I'm writing on the kernel mode since my program is a driver, therefore I didn't use ioperm() etc.
thank you in advance.
You have the parameters of outb function wrong, correct order is :
outb(value, port)
so you have to change your code to do:
outb(val, 0x378)
For more details please read Linux I/O Programming Howto .
Do you know for a fact that you have a parallel port installed at that address?
Get yourself a small low-current LED. Stick the long end in one of pin 2 (LSB) to pin 9 (MSB) and the short end in pin 25 (ground).
Try writing various values and see if you can get the LED to change by the bit value of what you write.
This should work (unless as previously mentioned you've gotten it programmed in an input mode) Being able to read back the port value is less certain, depending on the type of parallel port and implementation details (for example, you probably couldn't with the buffer chip that implemented it in the original PC)
Also note that most USB "printer" adapters don't give you bitwise register access. Something hanging off of the PCI or PCMCIA, etc may also have problems with direct register access at the legacy port address. There are nice USB parallel interface chips such as the FT245 and successors which you can use if you don't have a "true" parallel port hanging off the chipset available.
Have you set the direction register? If it is set as input then you will read what is on the port.
inb(0x378) is not required to return what was written; at least I've seen chips to behave so. Well, since you, at some point, have called outb, you know what's on anyway.

Resources