STM32 SAI: Understanding FIFO - stm32

To my understanding, FIFO (in hardware-context) is a buffer which will be managed according to first-in-first-out principle. You put sequentially some bits into it and then you can read them i.e. blockwise when the desired threshold is reached. But I'm confused of the FIFO management of serial audio interface of STM32:
According to datasheet, serial audio interface (SAI) supports FIFO up to 8 words. (8x32bits) The data register (SAI_xDR) of SAI is 1 word (32bits). The documentation explains
A write to this register loads the FIFO provided the FIFO is not full.
A read from this register empties the FIFO if the FIFO is not empty.
How to interpret it?
My guess is: If I make a writing access to this register, it loads the register content(32bits block) into the FIFO as the first word, then at the second writing access, it loads the second word into the FIFO and so on. Then when I make a reading access, it returns the first word on the queue, then the second and so on. Is this right?
If so, what happens, when I write less than 32bits into the register? I.e. I write a 16 bits block. Then I write a 16bits again. Do the both bit blocks share a word or are they transfered to seperate words? If I read a word, would I get both 16bit blocks or only the first 16bit? I'm not understanding how FIFO knows the size of my bit sequence which I fill into the data register. Or does it always take the whole 32bits at each write access?

My guess is: If I make a writing access to this register, … Is this right?
Yes, you are right.
As far as I understand, each FIFO word contains data for/from one SAI slot independently of data size. FIFO connected with 32-bit shift register while shift count depend on data size.
It seems that one can use, for example, 16-bit data access to lower half of SAI_xDR for 8 < data_size <= 16 but anyway a whole 32-bit FIFO word will be used for the transfer and only data_size bits from each word will be shifted in/out.
36.3.9 Serial audio interface (SAI) Internal FIFOs
...
Each FIFO is an 8-word FIFO. Each read or write operation from/to the FIFO targets one word FIFO location whatever the access size. Each FIFO word contains one audio slot. FIFO pointers are incremented by one word after each access to the SAI_xDR register.
Data should be right aligned when it is written in the SAI_xDR.
Data received will be right aligned in the SAI_xDR.

Related

How is data copied from user space to kernel space and vice versa during I/O tasks?

I'm learning an operating system course and on slide 32:
https://people.eecs.berkeley.edu/~kubitron/courses/cs162-S19/sp19/static/lectures/3.pdf
the professor briefly said fread and fwrite implement user space buffer, thus more efficient than directly calling system functions read/write and can save disk access, but didn't explain why.
Imagine these two scenarios: we need to read/write 16 bytes, user buffer is 4-byte, scenario one is using fread/fwrite, scenario two is directing using read/write which process one byte at each time
My questions are:
Since fread calls read underneath, how many read function calls will be invoked respectively?
Is data transfer, whether one single byte or 1mb between user space buffer and kernel space buffer all done by the kernel and no user/kernel mode switch involved during transferring?
How many disk accesses are performed respectively? Won't the kernel buffer come into play during scenario two?
The read function ssize_t read(int fd, void *buf, size_t count) also has buffer and count parameters, can these replace the role of user space buffer?
Since fread calls read underneath, how many read function calls will be invoked respectively?
Because fread() is mostly just slapping a buffer (in user-space, likely in a shared library) in front of read(), the "best case number of read() system calls" will depend on the size of the buffer.
For example; with an 8 KiB buffer; if you read 6 bytes with a single fread(), or if you read 6 individual bytes with 6 fread() calls; then read() will probably be called once (to get up to 8 KiB of data into the buffer).
However; read() may return less data than was requested (and this is very common for some cases - e.g. stdin if the user doesn't type fast enough). This means that fread() might use read() to try to fill it's buffer, but read() might only read a few bytes; so fread() needs to call read() again later when it needs more data in its buffer. For a worst case (where read() only happens to return 1 byte each time) reading 6 bytes with a single fread() may cause read() to be called 6 times.
Is data transfer, whether one single byte or 1mb between user space buffer and kernel space buffer all done by the kernel and no user/kernel mode switch involved during transferring?
Often, read() (in the C standard library) calls some kind of "sys_read()" function provided by the kernel. In this case there's a switch to kernel when "sys_read()" is called, then the kernel does whatever it needs to to obtain and transfer the data, then there's one switch back from kernel to user-space.
However; nothing says that's how a kernel must work. E.g. a kernel could only provide a "sys_mmap()" (and not provide any "sys_read()") and the read() (in the C standard library) could use "sys_mmap()". For another example; with an exo-kernel, file systems might be implemented as shared libraries (with "file system cache" in shared memory) so a read() done by the C library (of a file's data that is in the "file system cache") may not involve the kernel at all.
How many disk accesses are performed respectively? Won't the kernel buffer come into play during scenario two?
There's too many possibilities. E.g.:
a) If you're reading from a pipe (where the data is in a buffer in the kernel and was previously written by a different process) then there will be no disk accesses (because the data was never on any disk to begin with).
b) If you're reading from a file and the OS cached the file's data already; then there may be no disk accesses.
c) If you're reading from a file and the OS cached the file's data already; but the file system needs to update meta-data (e.g. an "accessed time" field in the file's directory entry) then there may be multiple disk accesses that have nothing to do with the file's data.
d) If you're reading from a file and the OS hasn't cached the file's data; then at least one disk access will be necessary. It doesn't matter if it's caused by fread() attempting to read a whole buffer, read() trying to read all 6 bytes at once, or the OS fetching a whole disk block because of the first "read() of one byte" in a series of six separate "read() of one byte" requests. If the OS does no caching at all, then six separate "read() of one byte" requests will be at least 6 separate disk accesses.
e) file system code may need to access some parts of the disk to determine where the file's data actually is before it can read the file's data; and the requested file data may be split between multiple blocks/sectors on the disk; so reading 2 or more bytes from a file (regardless of whether it was caused by fread() or "read() of 2 or more bytes") could cause several disk accesses.
f) with a RAID 5/6 array involving 2 or more physical disks (where reading a "logical block" involves reading the block from one disk and also reading the parity info from a different disk), the number of disk accesses can be doubled.
The read function ssize_t read(int fd, void *buf, size_t count) also has buffer and count parameters, can these replace the role of user space buffer?
Yes; but if you're using it to replace the role of a user space buffer then you're mostly just implementing your own duplicate of fread().
It's more common to use fread() when you want treat the data as stream of bytes, and read() (or maybe mmap()) when you do not want to treat the data as a stream of bytes.
For a random example; maybe you're working with a BMP file; so you read the "guaranteed to be 14 bytes by the file format's spec" header; then check/decode/process the header; then (after determining where it is in the file, how big it is and what format it's in) you might seek() to the pixel data and read all of it into an array (then maybe spawn 8 threads to process the pixel data in the array).

Why need both quantity of registers and byte count when wirte multiple registers?

By MODBUS Application Protocol Specification, when write multiple registers, we need to specify both quantify of registers and byte count.
But this document also say that "Data is packed as two bytes per register". So, we only need one of them is enough? Either quantity of registers or byte count.
In my opinion, data is not always is packed as two bytes per register. It can be three or four bytes. Is that correct? So that, we need both, is it?
Modbus registers are always 2 bytes. For preset multiple registers command, byte count field is redundant. But it seems byte count field has other uses in other commands and it's not always (register count * 2). For example, see the response of the read coil status command (0x01). This response can contain odd number of bytes.

STM32F302 Adc with DMA for different size and channel

I'm using STM32F302 QFN32 and unfortunately, it has only one ADC module. One channel must get around 500 samples in one period and it must be sync with and PWM (thinking using a timer and this i/o will be toggled in callback, because while reading its ADC channel, I must know the i/o whether high or low, so that according to this value, will decide value). Furthermore, there are 4 more channels which must be read.(More samples doesn't need there like before, 8 or 16 samples will be enough.) However, it has only one ADC module. Consequently, Can I do this? If yes, how? Thank you.
ST ADC have two conversion modes. Regular and Injected.
Regular mode is like all ADC's have. You start it, either by software or trigger (timer/gpio) and it does one or a sequence of conversions. The result is written to a common register, that the DMA takes care of.
Injected mode is a high priority preemption conversion. Once you start an injected conversion sequence by software or trigger. The ADC injects the conversion between the regular conversions. As a higher priority one. The result is stored in one of the injected result channel for the interrupt.
Only regular mode supports DMA. See AN4195 for more info.
I suggest you use a timer to trigger a regular sequence for your fast channel, with a circular DMA setup to move the data. And use another timer to trigger the injected sequence. There is a maximum of 4 injected channels, so you are in luck!
Obviously, you can do this the other way around. Have fast injections and slow regular. But you'll need another timer synchronized to the injected start trigger to get the DMA to move the data.
That is, if your samplerate does not allow immediate processing. Otherwise you can just use the ISR.

Difference between byte stream and bit stream

So far I thought they are the same as bytes are made of bits and that both side needs to know byte size and endiannes of the other side and transform stream accordingly. However Wikipedia says that byte stream != bit stream (https://en.wikipedia.org/wiki/Byte_stream ) and that bit streams are specifically used in video coding (https://en.wikipedia.org/wiki/Bitstream_format). In this RFC https://www.rfc-editor.org/rfc/rfc107 they discuss these 2 things and describe Two separate kinds of inefficiency arose from bit streams.. My questions are:
what's the real difference between byte stream and bit stream?
how bit stream works if it's different from byte stream? How does a receiving side know how many bits to process at a given time?
why is bit stream better than byte stream in some cases?
This is a pretty broad question, I'll have to give the 10,000 feet view. Bit streams are common in two distinct usages:
very low-level, it is the fundamental way that lots of hardware operates. Best examples are the data stream that comes off a hard disk or a optical disk or the data sent across a transmission line, like a USB cable or the coax cable or telephone line through which you received this post. The RFC you found applies here.
high-level, they are common in data compression, a variable number of bits per token allows packing data tighter. Huffman coding is the most basic way to compress. The video encoding subjects you found applies here.
what's the real difference between byte stream and bit stream?
Byte streams are highly compatible with computers which are byte-oriented devices and the ones you'll almost always encounter in programming. Bit streams are much more low-level, only system integration engineers ever worry about them. While the payload of a bit stream is often the bytes that a computer is interested in, more overhead is typically required to ensure that the receiver can properly interpret the data. There are usually a lot more bits than necessary to encode the bytes in the data. Extra bits are needed to ensure that the receiver is properly synchronized and can detect and perhaps correct bit errors. NRZ encoding is very common.
The RFC is quite archeological, in 1971 they were still hammering out the basics of getting computers to talk to each other. Back then they were still close to the transmission line behavior, a bit stream, and many computers did not yet agree on 8 bits in a byte. They are fretting over the cost of converting bits to local bytes on very anemic hardware and the need to pack as many bits into a message as possible.
How does a receiving side know how many bits to process at a given time?
The protocol determines that, like that RFC does. In the case of a variable length bit encoding it is bit values themselves that determine it, like Huffman coding does.
why is bit stream better than byte stream in some cases?
Covered already I think, because it is better match for its purpose. Either because the hardware is bit-oriented or because variable bit-length coding is useful.
A bit is a single 1 or 0 in computer code, also known as a binary digit.
The most common use for the bit stream is with the transmission control protocol, or TCP. This series of guidelines tells computers how to send and receive messages between each other. The World Wide Web and e-mail services, among others, rely on TCP guidelines to send information in an orderly fashion. Sending through the bit stream ensures the pieces arrive in the proper order and the message isn't corrupted during delivery, which could make it unreadable.So a bit stream sends one bit after another.
Eight bits make up a byte, and the byte stream transmits these eight-bit packets from computer to computer.
The packets are decoded upon arrival so the computer can interpret them.Thus a byte stream is a special case of bits sent together as a group in sequential order.For a byte stream to be most effective, it flows through a dedicated and reliable path sometimes referred to as a pipe, or pipeline.
When it comes to sending a byte stream over a computer network, a reliable bi-directional transport layer protocol, such as the transmission control protocol (TCP) used on the Internet, is required. These are referred to as a byte stream protocol. Other serial data protocols used with certain types of hardware components, such as the universal asynchronous receiver/transmitter (UART) technique, is a serial data channel that also uses a byte stream for communication. In this case, the byte, or character, is packaged up in a frame on the transmitting end, where an extra starting bit and some optional checking bits are attached and then separated back out of the frame on the receiving end. This technique is sometimes referred to as a byte-oriented protocol.
Taking a general life example,suppose you have a lot of match sticks to send.Then you could send them one stick after the other,one at a
time.. or you could pack a few of them in a match box and send them
together ,one matchbox after the other in sequence.the first is like
bitstream and the latter like bytestream.
Thus it all depends on what the hardware wants or is best suited for..If your hand is small and you cant accept matchboxes but you still want matchsticks then you take them one at a time or else take the box.Also byte streams are better in a sense that every bit does not need to be checked and data can be sent in batches of 8,.if any of it fails the entire 8bits can be re sent.
To add to the other good answers here:
A byte stream is a type of bit stream. A byte stream describes the bits as meaningful "packages" that are 8 bits wide.
Certain (especially low-level) streams may be agnostic of meaning in each 8 bit sequence. It would be a poor description to call these "byte streams"
Similar to how every Honda Civic is a car, but not every car is a Honda Civic...

What is the distinction between spooling and device queue?

I know that each device has its own device queue. Also i see that "Spooling is a type of buffering. The most common spooling application is print spooling, which places a task (or 'print job') into a queue for extended or later processing."
Does that mean the device queue is spooling? I am confused.
Spooling is referred to as buffered queueing. A spooler is a logical device that takes input from a quicker process (such as a word processor or image application) and holds that data in a buffered queue for a slower process (printing or some other slow process). The spool allows the quicker application to not have to wait on the slower process to finish before moving on to other tasks.
Spoolers can also be used in reverse so that a slower process is an input and the spool manages the input and holds it in the buffered queue along with a queue of actions until enough data is present to take the actions on the data. This is known as batch processing. These reverse spools allow for the data processing actions to be spooled along with the incoming data to be processed when the correct data is present and allows the application that requested the spooling to continue on to other tasks.
Device queue is more specific term which take into account about a specific device.you cannot talk about device queue without having an actual device whereas spooling is a generic term that corresponds to usage of disk space as buffer irrespective of the type of device.