SPI_IOC_MESSAGE(N) on Raspberry Pi 3 - linux

I am working on a project on a Raspberry Pi 3, and I saw this code line :
ioctl(sSpiObj.spiFd, SPI_IOC_MESSAGE(1), &sSpiTransfer);
I don't know what SPI_IOC_MESSAGE(1) does, and I tried to find on the internet its explanation, but I couldn't find it. Is there anyone who could explain what it does?

See the ioctl declaration from here: link
You see you have to pass the request type in the second argument to tell the driver what you want. Your second argument is SPI_IOC_MESSAGE which is a macro defined in Linux code here link. It creates a request type number that incorporates the number of messages you want to send and then this is passed to the driver and then driver decodes the request type and the number of messages from this and process the third argument as messages to be send and finally sends the messages.
From the linux kernel Documents:
* SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync().
* Pass it an array of related transfers, they'll execute together.
* Each transfer may be half duplex (either direction) or full duplex.
*
* struct spi_ioc_transfer mesg[4];
* ...
* status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg);
*
* So for example one transfer might send a nine bit command (right aligned
* in a 16-bit word), the next could read a block of 8-bit data before
* terminating that command by temporarily deselecting the chip; the next
* could send a different nine bit command (re-selecting the chip), and the
* last transfer might write some register values.

Related

Returning values from linux binary

First, let me say that I am very new to writing drivers so I apologize if my terminology is completely off.
I am attempting to write a driver to control an LED and read back some registers on my FPGA development board.
As nicely pointed out here I understand that I can supply my binary (or C program) input values by using (in my C program):
int main(int argc, char *argv[]) { /* ... */ }
So, as an example, in my Linux shell if I run:
root#socfpga:~# ./LED_BLINK 182
I can send an input integer of 182 to my binary that is being executed in the linux shell script. In my case this blinks my LED 182 times (this part works). So I know how to give my program inputs, but how do I properly extract outputs from my program?
My main questions are as follows:
1) In general, suppose my binary has variable(s) that I would like to return as outputs, how can I do this? Example, if I want my program to output the value at register 5, I input in the shell:
root#socfpga:~# ./LED_BLINK 1 5
The LED will blink once and then my shell will return the value at register 5 (this register is just a variable in the binary program).
Another way to describe what I am after, suppose if I have a single register (let's say it is a 16 bit value) and I would like my program to output that value, how can I properly achieve this? Can I pass a variable to my binary (such as a pointer?) and have my program write to that value? Can you provide an example of this or a link to a tutorial?
2) Similar to above, what if I have a list of registers (say 20 or more 16 bit values), how could my binary properly output these values ( a pointer array, maybe)?
3) I am sure that this process has a technical name. What is this 'technically' called (so that I can have smarter google search entries)?
Thank you for your help,
James
The most direct way to pass data between programs in a Unix setting is to use standard input and output "pipes" (also known as stdin and stdout).
By default the C statement "printf" will default to writing to stdout and you will see the output on the terminal by default or you can pass it to another program as input using the "|", or to another file-type operation using the ">" operand.
This is explained in more detail on this post: What does it mean to write to stdout in C?

tinyalsa timing and problems with PCM_MMAP

We're on an ARM64 Snapdragon using a Qualcomm PM8916 codec. The goal is to sample a single channel at 48000 samps/sec, and to use high resolution time stamps. The tinyalsa docs insist that we must use PCM_MMAP. When we do, the pcm_open() does not complain, but pcm_readi() fails errno:22 Invalid argument in the ioctl().
Another symptom that I believe is related is that when pcm_open is called in this form (no PCM_MMAP):
tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN, &cfg );
Audio flows wonderfully (period=256), and contrary to the docs pcm_get_htimestamp() returns values just fine. Not sure how accurate the timing is, but tomorrow I will inject GPS 1PPS and do my standard test to figure that out.
But when I follow instructions and use PCM_MMAP, eg:
tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN | PCM_MMAP | PCM_MONOTONIC | PCM_NOIRQ, &cfg );
or
tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN | PCM_MMAP | PCM_NONBLOCK, &cfg );
The read fails as mentioned above. I haven't tried every possible combination, but that's coming. The odd thing is that the whenever PCM_MMAP is specified, the time stamps that
int err = pcm_get_htimestamp( tinyHandle, &available, &timestamp);
returns become non-sensical, and tv_sec contains values circa 4917 or 5013 instead of a reasonable time_t. I'd be tempted to conclude that the tv_sec values are elapsed time since launch, except that the timestamps happen within seconds of launch.
Oh, one other detail. The PCM_NONBLOCK option was not recognized in the version of tinyalsa supplied with the sdk I have been using. So I git cloned tinyalsa, built a static lib, and upgraded to the latest and greatest. The problem I have with PCM_MMAP persists in both versions. This, coupled with the fact that hours of searching for people with the same problem has been largely a bust, leads me to believe that it is something about our new product and not about the libs.
Any thoughts about where to look next?
Thanks!
Confirmed this morning that the ioctl inside pcm_readi() is receiving the proper file descriptor (4) and period size (256). There are no other arguments that could be invalid
OK, GPS 1PPS test shows timestamp accuracy on the order of 2-3msec, which gets us going "enough" with this usage (no PCM_MMAP):
tinyHandle = pcm_open( TINYALSA_CARD, TINYALSA_DEVICE, PCM_IN, &cfg );
Here is the comment that sent me down the rabbit hole:
/** Returns available frames in pcm buffer and corresponding time stamp.
* The clock is CLOCK_MONOTONIC if flag #ref PCM_MONOTONIC was specified in #ref pcm_open,
* otherwise the clock is CLOCK_REALTIME.
* For an input stream, frames available are frames ready for the application to read.
* For an output stream, frames available are the number of empty frames available for the application to write.
* Only available for PCMs opened with the #ref PCM_MMAP flag.
* #param pcm A PCM handle.
* #param avail The number of available frames
* #param tstamp The timestamp
* #return On success, zero is returned; on failure, negative one.
*/
int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
struct timespec *tstamp)
It is misleading, as it deterred me from trying the pcm_get_htimestamp() call without PCM_MMAP working. There will be further investigations, and if I can post them, I will.
Thank you!

list_empty returns 1 (non zero) if the list is not empty

I am working on Linux Device Driver code. I cant reveal what exactly this code is used for. I will try my best to explain my situation. Below code will be executed in interrupt context when we receive an USB interrupt stating that there is some data from USB. The data will arrive as URB's and we will convert them into chunks, add them to Linux Circular Doubly linked list for further processing.
spin_lock(&demod->demod_lock);
/* Delete node from free list */
list_del(&chunk->list_head);
/* Add it to full list */
list_add_tail(&chunk->list_head,&demod->ChunkRefList.full);
/* Update chunk status */
chunk->status=CHUNKDESC_FULL_LIST;
/* Increment the chunks assigned to application */
demod->stats.assigned.c++;
spin_unlock(&demod->demod_lock);
printk("Value returned by list_empty is %d ",list_empty(&demod->ChunkRefList.full));
I repeat, this code gets executed in interrupt context. I am using this code as a part of embedded system which displays Audio & Video(AV) forever.
After approx 12 hours, the AV is frozen and when I analyse, I see the value of list_empty(&demod->ChunkRefList.full) returned is always 0x1 forever. Usually in working case where AV is playing fine, its value will be 0x0 stating that the list is not empty.
As you can see, when above code gets executed, it first adds a node to the full list and checks if full list is empty. Ideally, the value should be always 0x0. Why its value is 0x1
I am monitoring the value of list_empty(&demod->ChunkRefList.full) using timedoctor applicaiton which doesn't introduce any overhead in interrupt context. I have used printk above to make you understand that I am printing its value.
Finally, I was able to figure out the issue.
Since the code is implemented in interrupt context, using list_del followed by list_add_tail was causing issue.
So, I removed these two macros and introduced list_move_tail macro which resolved the issue.
By using list_move_tail, there is no need for us to remove the node and add it to the new list. The kernel will takecare of both operations.
So, to conclude, its better to make Linux Linked list manipulations as minimal as possible in interrupt context.

How does Linux Process Accounting (psacct) work?

I find a lot documents about psacct, but they are addressing usage, not how it works.
Question
I really want to know how process accounting works:
Which part of the system records information about processes?
How does it work?
Already done
I installed psacct on RHEL 6.5.
The service staring script actually (/etc/init.d/psacct) call this:
/sbin/accton $ACCTFILE
The /sbin/accton calls system call acct()
man acct
DESCRIPTION
The acct() system call enables or disables process accounting. If called with the name of an existing file as its argument, accounting is
turned on, and records for each terminating process are appended to filename as it terminates. An argument of NULL causes accounting to be
turned off.
The answer to your question is in the linux source file kernel/acct.c. Particularly in the fill_ac function
/*
* Write an accounting entry for an exiting process
*
* The acct_process() call is the workhorse of the process
* accounting system. The struct acct is built here and then written
* into the accounting file. This function should only be called from
* do_exit() or when switching to a different output file.
*/
static void fill_ac(acct_t *ac)

what is the meaning of this macro _IOR(MY_MACIG, 0, int)?

i was going through ioctl sample programs to check how it communicates with kernel space. in program WRITE_IOCTL is used as command
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
ioctl(fd, WRITE_IOCTL, "hello world")
I am not able to understand what is _IOW(MY_MACIG, 1, int).
here is the link from where i downloaded the program. please help me.
http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-4.html
As you may know, an ioctl should be unique, as explained in the Linux Device Drivers book:
The ioctl command numbers should be unique across the system in order
to prevent errors caused by issuing the right command to the wrong
device.Such a mismatch is not unlikely to happen, and a program might
find itself trying to change the baudrate of a non-serial-port input
stream, such as a FIFO or an audio device. If each ioctl number is
unique, the application gets an EINVAL error rather than succeeding in
doing something unintended.
Furthermore, an ioctl can require to write data to and/or read data from kernel space.
When one creates it's own driver that performs ioctls, he will need to describe all this in the ioctl command.
_IO, _IOW, _IOR, _IORW are helper macros to create a unique ioctl identifier and add the required R/W needed features (direction).
These can take the following params: magic number, the command id, and the data type that will be passed (if any)
The magic number is a unique number that will allow the driver to detect errors such as the one mentioned in the LDD book's quote.
The command id, is a way for your dirver to understand what command is needed to be called.
Last parameter (the type) will allow the kernel to understand the size to be copied.
hope this helps.
PS: you can have more details in Linux Device Drivers book (chapter 6)
https://lwn.net/images/pdf/LDD3/ch06.pdf
From http://www.circlemud.org/jelson/software/fusd/docs/node31.html:
The Linux header file /usr/include/asm/ioctl.h defines macros that must be used to create the ioctl command number. These macros take various combinations of three arguments:
type, an 8-bit integer selected to be specific to the device driver. type should be chosen so as not to conflict with other drivers that might be ``listening'' to the same file descriptor. (Inside the kernel, for example, the TCP and IP stacks use distinct numbers since an ioctl sent to a socket file descriptor might be examined by both stacks.)
number, an 8-bit integer command number. Within a driver, distinct numbers should be chosen for each different kind of ioctl command that the driver services
data_type, the name of a type used to compute how many bytes are exchanged between the client and the driver. This argument is, for example, the name of a structure.
The macros used to generate command numbers are:
_IO(int type, int number), used for a simple ioctl that sends nothing but the type and number, and receives back nothing but an (integer) retval
_IOR(int type, int number, data_type), used for an ioctl that reads data from the device driver. The driver will be allowed to return sizeof(data_type) bytes to the user
_IOW(int type, int number, data_type), similar to _IOR, but used to write data to the driver
_IORW(int type, int number, data_type), a combination of _IOR and _IOW. That is, data is both written to the driver and then read back from the driver by the client

Resources