Spi interrupt handler works when a printf() is used - c

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.

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.

Program runs, calls function but I get no "output" on STM32L1

I encounter a problem currently with a custom STM32L151 board that I will try to explain here.
The program I am testing runs properly for some time, I get debug messages on puTTY as intended but at a time, the program seems to be "blocked".
It is pretty weird behaviour because the function which prints over UART is called (I put a breakpoint here to see if I reach this point) but I get no output on a terminal.
So I was wondering what could be the issue, if someone as an idea because I kinda run out of ideas to be honest, I tried to understand. I will assume there is no hardware issue, it is still possible but I do not think it could be that reason.
Also, the programs is aimed at receiving a FSK message and answering it and it seems that I have the same behaviour with the radio chip: I receive the message and send a response (I get the TxDone callback called which indicates that the FSK message has normally been sent but the device which waits for this response does not receive it).
So to sum up a bit: the program runs properly for a moment then "blocks" & I do not get any output anymore (debug or radio communication) but still runs (functions effectively called) and after a moment again, the program "unblocks" itself and runs properly again (debug messages work).
The device I work on is STM32L151 based, I work with Keil, UART config is: 19200 baudrate, 8 data bits, 1 stop bit, no parity, XON/XOFF flow control & the radio chip I use is SX1272.
If someone has any idea or any trail I can investigate on. If you need any further details, I am not sure I am accurate enough on the description of the problem but any help is appreciated.

Glitchy audio output, no underruns

When using snd_pcm_writei() in non-blocking mode everything works perfect for a while but eventually the audio gets choppy. It sounds like the ring buffer pointers are getting out of sync (ie. sometimes I can tell that the audio is playing out of order). How long it takes for the problem to start it's hardware dependent. On a Gentoo box on real hardware it seldom happens, but on a buildroot system running on QEMU it happens after about 5 minutes. On both cases draining the pcm stream fixes the problem. I have verified that I'm writing the samples correctly by also writting them to a file and playing them with aplay.
Currently I'm setting avail_min to the period size (1024 frames) and calling snd_pcm_wait() before writting chunks of the period size. But I tried a number of different variations (different chunk sizes, checking avail myself and use pthread_cond_timedwait() instead of snd_pcm_wait(), etc). But the only thing that works fine is using blocking mode but I can not do that.
You can see the current source code here: https://bitbucket.org/frodzdev/mediabox/src/5a6471316c7ae481b329e7e0d4af1bb68a32e71d/src/audio.c?at=staging&fileviewer=file-view-default (it needs a little cleanup since I'm trying all kinds of things). The code that does the actual IO starts at line 375.
Edit:
I think I got a solution but I don't understand why it seems to work. It seems that it does not matter if I'm using non-blocking mode, the problem is when I wait to make sure there's room on the buffer (either through snd_pcm_wait(), pthread_cond_timedwait(), or usleep()).
The version that seems to work is here: https://bitbucket.org/frodzdev/mediabox/src/c3eb290087d9bbe0d5f37653a33a1ba88ef0628b/src/audio.c?fileviewer=file-view-default. I switched to blocking mode while still waiting before calling snd_pcm_writei() and it didn't made a difference. Then I added the call to snd_pcm_avail() before calling snd_pcm_status() on avbox_audiostream_gettime(). This function is called constantly by another thread to get the stream clock and it only uses snd_pcm_status() to get the timestamps. Now it seems to work (at least it is a lot less probable to happen) but I don't understand exactly why. I understand that snd_pcm_avail() will synchronize the pointers with the kernel but I don't really understand when it needs to be called and the difference between snd_pcm_state() et al and snd_pcm_status(). Does snd_pcm_status() also synchronize anything? It seems not because sometimes snd_pcm_status_get_state() will return RUNNING when snd_pcm_avail() returns -EPIPE. The ALSA documentation is really vague. Perhaps understanding these things will help me understand my problem?
Now, when I said that it seems to be working I mean that I cannot reproduce it on real hardware. It still happens on QEMU though way less often. But considering that on the next commit I switched to blocking mode without waiting (which I've used in the past and never had a problem with on real hardware) and it still happens in QEMU and also the fact that this is a common issue with QEMU I'm starting to think that I may have fixed the issue on my end and now it's just a QEMU problem. Is there any way to determine if the problem is a bug on my end that is easier to trigger on the emulator or if it's just an emulator problem?
Edit: I realize that I should fill the buffer before waiting but at this point my concern is not to prevent underruns but to make sure that my code can handle them when they happen. Besides the buffer is filling up after a few iterations. I confirmed this by outputing avail, buffer_size, etc before writing each packet and the numbers I get don't make perfect sense, they show an error of 1 or 2 periods about every 8th period. Also (and this is the main problem) I'm not detecting any underruns, the audio get choppy but all writes succeed. In fact, if the problem start happening and I trigger an underrun by overloading the CPU it will correct itself when the pcm is reset.
In line 505: You're using time as argument to malloc.
In line 568: Weren't you playing audio? In this case you should do wait only after you wrote the frames. Let's think ...
Audio device generates an interrupt when it terminates to process a period.
| period A | period B |
^ ^
irq irq
Before you start the pcm, audio device doesn't generate any interrupt. Notice here that you're waiting and you haven't started the pcm yet. You only starts it when you call snd_pcm_writei().
When you wait for audio data you'll be awake only when the current period has been fully processed -- in your first wait the first period wasn't even written -- so in a comfortable situation you should write the whole buffer, wait for the first interrupt, and then write the just processed period, and on and on.
Initially, buffer is empty:
| | |
write():
|############|############|
wait():
..............
When we wake up:
| |############|
write():
|############|############|
I found the problem is you're writing audio just before it be played, then sometimes it may arrive delayed in the buffer.

uart buffer is not read

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()?

PIC18F locking up if sending data to quickly

I'm working with a PIC18F and am trying to send data via hyperterminal. When I send data at a slow rate by pressing one key every half secondish it recieves the data and echos it correctly but when I start pressing the keys at a faster rate the MCU locks up. Not sure what causes this.
while(index<length){
while(PIR1bits.RCIF==0); // Wait till char recieved
sendData(str2,9); // confirm reception
Delay1KTCYx(5); //delay because without it, it messes up.
rxData[index]= RCREG; //char array
index++;
}
baudrate is 2400 On both PIC and hyperterminal.
This is our receive loop. sendData is just debug code that we send saying "recieved". It's how we know when it has frozen.
It does not freeze at the same amount of loops everytime, it is solely on how fast we input data.
(I did work on MCUs but haven't a deal with PICs, so i'll try to help with common problems)
You do not check any receiver error flags. Receiver may lock up in Overrun Error state and do not receive further, until you clear Overrun flag. Add check for error conditions and resolve them accordinly to PIC documentation.
Good practice is to read received byte as early, as possible when receive complete is indicated, so try to move rxData[index]= RCREG; imediately after while(PIR1bits.RCIF==0);. This lowers possibility
You didn't shown code for sendData. There may be missed checking for TX ready state and error conditions, so it may also lock up.
Unmotivated delay indicates that you're already going wrong somewhere. Try to remove it and THEN debug code.
You should test your receive and transmit separately. At first, check transmitter: try to output long line of text through UART without any receiving. (Say, write "Hello world!" program:))
Check receiver code alone: remove transmission from program, connect LED (voltmeter, oscillosocope, whatever you have) to free GPIO pin, and then make it toggle logic level on it every time it receives a byte. Is it takes only several clock ticks to do, it should not intervene receiving or lockup.
Maybe when you send 2 characters while it is busy sending the "received" one of them is discarded and you never reach your length?
On most microcontrollers, a UART receiver overrun will cause the newly-received byte to be discarded and a flag to be set, but the receiver will continue to operate normally. On the PIC, a receiver overrun will cause the UART to die until the CREN bit is cleared and re-set.

Resources