Reading from and writing to registers of an IMU via UART - c

I have an IMU that has a UART interface. The manufacturer has provided a Windows based program that get all the data from the IMU and displays it in real time. (The device is connected to the PC via the USB). I need to write my own software that does this in order to integrate it into my project.
The datasheet/manual for the IMU gives all details about which registers have to be written to and read from (issue commands and read responses) in order to get the IMU data. My question is, how do I implement this in C under Linux?
The closest information I found out was this one but when compiling it it seems I need Linux kernel headers since that program uses #include <linux/module.h> so I'm not sure if I am on the right track.

You need not any kernel headers to talk over a serial port with any device connected to that serial port.
You would get a 'connection' to your device by simply opening a file /dev/ttyUSB0 with open() call (the actual name could be found by looking into dmesg for relevant device messages or by looking what device node appears under /dev when you plug your device into usb port).
Then you would need to set the baud rate and the word format (number of bits, parity and number of stop bits). To achieve that from the user-space process you would use a set of ioctls. For details read man ioctl and man ioctl_list

Related

Difference between a serial driver and a tty driver

I have a task to write a serial driver for uart and tty_uart driver too on Zephyr (It's my first time in developing drivers).
1.So what is the difference between a serial driver and a tty driver?
Is there any interdependence relation between them? I mean to write a tty driver should I write by first a serial driver, that will be a base to the tty driver or what?
So what is the difference between a serial driver and a tty driver?
A serial driver makes no assumption about the kind of device attached, it merely sends and receives raw "bytes" (see note), and probably offers some way to configure the communication (which baud rate, how many data bits, what kind of parity scheme, what kind of flow control, etc). The device attached to the serial port could be a serial mouse, or a bar code scanner, or a printer, or ... - the serial driver doesn't care.
Note: "byte" might not be a synonym for "octet" - e.g. it could be a group of 7 bits.
A TTY driver is tied to the assumption that the device is an type writer with a keyboard. Note: For the history; before computers existed we went from "people waving flags at each other" (semaphores) to "morse code with a single key" (telegraph) to teleprinters/teletypewriter (see https://en.wikipedia.org/wiki/Teleprinter ); and when computers got invented the (mechanical/electric) teleprinters were simply replaced with (computerized) dumb terminals.
Mostly; TTY is all about what bytes mean (and doesn't care much how the bytes are sent/received); and a serial driver is all about how bytes are sent/received (and doesn't care what the bytes mean).
Is there any interdependence relation between them? I mean to write a tty driver should I write by first a serial driver, that will be a base to the tty driver or what?
Crudely; a TTY driver has IO in 4 directions - getting key press info from local keyboard, sending bytes to remote whatever, receiving bytes from remote whatever, and putting characters on the local screen. For sending/receiving bytes with "remote whatever" you can use a serial driver; but (especially during development/testing) you could use anything else (TCP/IP stream, pipes, file IO, ...) instead - you don't necessarily need to implement the serial driver first.
Regarding your questions:
So what is the difference between a serial driver and a tty
driver? Is there any interdependence relation between them? I
mean to write a tty driver should I write by first a serial driver,
that will be a base to the tty driver or what?
It all depends on your operating system.
Previous answers relate mostly to Linux/Windows. You don't provide more points about it, but I'm assuming your question relates to Zephyr RTOS Project. I also assume you're developing a BSP for a custom board not yet fully supported by the RTOS.
The device driver model in Zephyr is different from Linux's or Window's driver models. You can take a look at the board porting guide and architecture porting guide.
The documentation contains a lot of samples, including quite a few of driver samples.
You'll also find more information here covering how to have access to support from the community.

Detect certain connected USB device

I'm working with a USB device in Linux and have written a library to control this device.
Without going in to TOO many details, the device uses a standard UART protocol, so all I have to do is open a serial connection with open, configure the relevant parameters like baud rate, stop bit, parity, etc, etc, and start bit-banging registers.
The library works fine, however, it its hard coded to assume that this device is /dev/ttyUSB0. That is, this is what I pass to open. If open fails, I exit.
What I would like to do is detect that this device is present, regardless if it's /dev/ttyUSB0, /dev/ttyUSB1, etc. And even detect if there are multiple of these devices connected.
I can write code to poll certain registers on the device that will return serial number, product ID, etc, so I can detect that what is on the other end of the USB is indeed my device... but how can I find a list of connected USB devices, again, in native C?
OR is there a more elegant way of doing this, such as interfacing with it's kernel module, or something? I can provide the USB driver it actually uses, but I'm sort of lost when looking through the code.
Thanks for any insight.
The elegant method is to use udev to create a descriptive symlink for your device when it is connected. Add a line something like this to /etc/udev/rules.d
SUBSYSTEM=="tty",ENV{ID_MODEL}=="My_FlowMeter_Model",ENV{ID_USB_INTERFACE_NUM}=="00",SYMLINK+="flowmeter",RUN+="/bin/su pi -c /home/pi/record-flowmeter.sh
That's a very slightly modified version of an actual udev rule my research group uses to collect data from USB devices connected to battery-powered Raspberry Pi boxes. It also runs a script automatically, which has commands like
stty -F /dev/flowmeter 500000 -ixon -echo -icanon
If you want to know the "real" device filename, you could do readlink /dev/flowmeter. But for most uses you can just use the link: fd = open("/dev/flowmeter"); (or pass it as an argument to your program)
Naturally you should replace flowmeter with a short name for your own device, as well as updating the ID_MODEL based on the output from lsusb.
Multiple devices are a bit more complicated, but there are plenty of examples of udev rules out there.
On Linux, the information you are looking for is in the /sys filesystem, specifically under /sys/bus/usb/devices. From there you will need to search the filesystem to find your device.
For example, I just plugged a USB-serial dongle into my Linux (kernel version 2.6.35) and the device appeared under /sys/bus/usb/devices/2.1-8. Here, I am able to find that this is my device by vendorId:deviceId by checking the files idVendor and idProduct. Here, there is a directory named 2.1-8:1:0 which contains a directory named ttyUSB0.
Obviously, to find your device you will need code (or a shell script using find) to scan the directory tree, looking for the right entries.

Linux USB device driver misconception

My question is going to be rather vague but I will try to explain as detailed as I can what I am trying to resolve.
Trying to learn Linux kernel USB stack I have started to think of making a simple USB driver for my Atmel evaluation board based on ARM M0+ MCU to run away from Windows tools (Visual Studio plugin).
I have spent few days learning kernel's USB API and come to conclusion of how to make this. My driver aims to make my board connected to PC through USB cable act like a simple USB flash drive. Making that I then can easily program it with a new version of firmware written by me.
I have found that I need to find out specific interface (I am talking about interface in terms of USB specification, not interface we used to use as a code abstraction) that holds an endpoint (pipe) responsible for interaction with flash memory. And then I can map it to character device and interact with it using standard I/O operations that are described in struct file_operations structure.
Simply using cat on /proc/* file descriptor that was created by USB Core subsystem I have investigated that interface responsible for interaction with flash memory holds bulk endpoint (likewise, this terms come from USB specification, CMIIAW) that act as a "descriptor". Linux kernel USB Core subsystem gives neat interfaces to talk to different kind of endpoints whether it control, interrupt, bulk or asynchronous endpoint.
Now I have come closer to my very question.
Also the main transfer unit in communication between two USB devices is abstraction called urb - you allocate it, you fill it, you send it to USB Core subsystem, you read it if it was IN type of urb and, finally, you free it. What is confusing for me and tightly related to my question is the next API include/linux/usb.h:
static inline void usb_fill_bulk_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context)
Assume I have obtained an information from board's datasheet about where to write a program code. Let's say, we have 0x00100 - 0x10000 memory region. I will compile my code, obtain a binary and then using standard Linux tools or writing a simple user-space wrapper application I will use lseek to set file's offset to 0x00100 and write system call provided with a buffer (binary compiled previously) and it's length.
In kernel space, I will have to allocate urb in write system call handler, fill it with a buffer sent from user space and submit this urb to USB Core.
BUT I can not find a way how to specify an OFFSET set earlier by lseek. Do I miss something? Maybe I missed some concepts or, perhaps, I am watching in a wrong way?
When your embedded Linux device acts as a USB mass storage device, the flash as a peripheral on Linux device is unmounted, and the gadget driver is loaded. Linux then loses control to the flash, and now the PC connected to your Linux device fully controls the flash. This is because a flash as a USB device can only has one USb host.
The gadget driver works purely in kernel space. It does not receive or transmit data from/to user space. It calls vfs_read() and vfs_write() to access the files on the flash, with an field offset. The offset is got from the USB commands sent from your host - Windows PC.
There is no way to specify offset using USB subsystem's API. I misunderstood whole conception of USB as communication protocol, unwise me. You must first learn underlying protocol your device uses to communicate with others.
If your device acts as a USB HID device then learning specification of how to exchange data with USB HID device is the way to go. If there is something proprietary then you can do nothing but reverse engineer it (listening USB packets with a sniffer on system where a driver for your device exists).
As for my board it has embedded debugger that serves as a communication module besides being debugger itself. Specifically, my device is equipped with EDBG and here is a link on description of protocol it uses for communication.

Detecting a RS-232 com port in Linux

I have an ECR(Electronic Cash Register) device,it has a RS-232 com port cable for the connection to PC but I have not been given any drivers for it. I am trying to connect the device to PC but PC is not able to detect the cable. How to detect this device attached on this RS-232? I am working under Linux. Any help on how to find the device is appreciated?
Following is the code snippet I found in C to connect to device based on Baudrate and Com Port number.
int OpenComport(int comport_number, int baudrate)
int SendByte(int comport_number, unsigned char byte)
int SendBuf(int comport_number, unsigned char *buf, int size)
Please see my answer to a related question which shows how to open and configure the serial port.
On Linux, serial ports are almost always /dev/ttyS[0123] (that is /dev/ttyS0, /dev/ttyS1, etc.) for the hardwired ports, and /dev/ttyUSB* for USB ports. The hardwired "devices" may appear only when the hardware is present on some distributions. On others, they always appear whether there is hardware or not. (Try cat /dev/ttyS2 and see if you get the error "no such device".) This is a kernel configuration option which is frequently set to create the device entries whether the hardware is there or not.
The USB ports are present only when there is hardware plugged in, but if there are multiple USB serial ports, it can be difficult identifying which is which.
There is a mechanism within /etc/udev/rules.d/* which can be configured if some aspects of the devices are consistent. See man 7 udev for details.
For applications I have written, I determine which device is which by writing to the device and identifying its response. For devices which don't respond, this is either a worthy programming challenge or a mundane configuration solution.
I think you need to do a little reading about RS-232, and well, C programming also. There are no drivers for RS-232. It is a very "dumb" protocol - you basically just shove data out the port.
The PC cannot detect the cable? That's because it's not USB. Believe it or not, Plug-and-play didn't always exist; you tell the software what port the device is supposedly connected to, and it tries to talk to it.
Furthermore, those aren't "code snippets", those are just function prototypes. There isn't any actual code there.
1>since there's no operating system on your ECR so I guess u don't need any drivers ,instead a firmware will be there in the ECR , which tries to communicate with your Linux UART driver
2> Rs-232 is basically a serial protocol , I mean it has 9 wires , and hence a connecter with 9 pins are used DB-9 connectors ,all the communications inside a processor is in parallel format so a chip called UART is used to convert all the parallel data into serial data , and since yu want to pass the data in Rs-232 format , it needs to be packaged in that format .
3> Linux kernel already has a uart driver , which is implemented for RS-232 . so need to worry about drivers from Linux side.
4> Open a terminal type " dmesg | grep tty " ( connect only the ECR to the PC for rs-232 ports ). it will return something like ttyS or ttyUSB etc , however u just concentrate on ttyS if u have connected only through rs-232 cable .
5> Once u are sure of the ttyS device from the dmesg use minicom (its easy to use ) to communicate with the device.
regards,
Zubraj

reading USB port in Linux

I am writing a program to read data from a Bluetooth USB dongle. I am using Linux, so I suspect there may be a POSIX library to read from it, or perhaps there is a predefined file descriptor for each USB drive. How do I read a stream of data from a USB port in C?
The most common way of interacting with random USB device is libusb. This provides low-level access to the device, so if you want something more complex (for example, if it's an actual USB drive with a filesystem on it), you might want to use some existing driver for the device rather than trying to interact with it directly.
OK, given the answer above: the PS3 controller is, almost certainly, a HID device. You pair with it like you do any other Bluetooth HID device. It will appear as a joystick (or mouse, or keyboard, as appropriate) automatically once paired, with no software required on your part. This site seems to have a guide, though obviously I haven't tested it: http://www.ydl.net/support/solutions/ydl_6.x/ps3_bluetooth_sixaxis.shtml

Resources