How does a kernel driver talk with another device? - unix

I have an FPGA board with unix-based firmware. I need write out the program to run on this firmware that will send commands to some devices via I2C bus and will receive responses. I use for this special character file in Unix that i map in my program and write to it special commands & read from it responses. Each memory area in this mapped memory corresponds specific register of the FPGA which specified in Unix-based firmware (as i understand).
So, the question is the next one. As i understand, when i write some command to that mapped memory region of the special character file the kernel calls certain driver to handle bytes that I've written and send them through I2C bus (for example). Am I right? If so, is there some guarantee that the response from that device will be buffered and I will be able to read it from the mapped region in any time? Or does it depend on implementation specific driver?
I'm sorry if question is not clear some way, I am a newbie in this stuff.

Related

Vector Table for Bootloader

Most, if not all, microcontrollers have a vector table for all the exceptions that are encountered when the program is running. I am quite confused as to whether the bootloader also has its own vector table for executing the reset handler?
I have written a bootloader that has been ported between a number of different embedded processors used within comms products (MSP430, AVR32, DSP56300). This loader had quite limited functional requirements
Hardware initialisation.
Validate the main code image using a checksum or cryptographic signature.
Transfer of control to the main application if the validation passes.
Provide a minimal command interface over a serial port to allow for firmware update.
Reentry point to allow the main application to trigger a new firmware load.
This transfer of operation between the two programmes held in non volatile memory on the same processor meant that I had to provide a re-direction of the interrupt functions between the two completely separate applications. The Interrupt table for the MSP430 is held in FLASH and so cannot be modified easily. It also holds the reset vector that must always point to the start of the bootloader code so erasing and rewriting this area runs the risk of completely bricking the unit.
The solution in this case was to have an interrupt service routine in the bootloader that redirected through a vector table located at a fixed location within the application memory space. Using this method added one indirect jump instruction to each interrupt handler resulting in a minimal extra processor load for each interrupt that is processed. The bootloader was written to not use any interrupts relying on polling the serial port status for all of the communications. If the bootloader needed to use interrupts then the vector table can be moved to RAM and initialised by the bootloader or application as required. (My processor did not have enough RAM to allow this)
There was a simple data structure at a fixed location in the main application code that contained entries for each possible interrupt/exception and the start address of the application code (you could consider this as the application code reset vector). As long as the application provided this data structure in flash and correctly populated it could be compiled and build completely separately as if it was the only application on the processor.
A bootloader is just a program there is no magic there, as with any other program if it needs a vector table the programmers create a vector table. Certainly if it needs to run from reset then it must conform to the hardware/processor rules for that. The processor nor any of the other logic has any way to know that that collection of bits, that collection of instructions is a bootloader or not. It just runs it.
I assume you are talking about the many, but not all, flavors/brands of microcontrollers that have bootloaders programmed at the factory?
Within an mcu there is a processor core with a memory bus. The many items in the chip, ram, flash, gpio, spi, timer, uart, adc, etc all live on that bus like having more than one house on a particular street. Each of these items on the processor bus have address decoders looking for their address on the bus to know when to take or provide data/information. The application flash and bootloader rom are no different, not special. As easy as it is to do in software it is as easy in hardware to have some sort of if-then-else that allows the application flash to answer the processor at the vector table addresses, that flag that drives the then or else cases can be an input pin to the part. Tie the pin high and hit the reset and the part boots from one memory, tie the pin low hit the reset and the part boots from the other. There are other solutions out there that are perhaps not driven by an input pin to the part but by the bootloader software.
Sometimes the processor core itself has a signal that the chip vendor drives however it wants, that within the processor core it does an if-then else, perhaps the then case is 0x00000000 is where it looks for the vector table, and the else case 0xFFFF0000.
At the end of the day though a bootloader is just another program, written by someone for this chip, no different than the program you write for the chip other than the fact that if it is a factory programmed rom bootloader then the programmer for that bootloader might have additional information/documentation for that part that we dont have. But being a bootloader is not magic it is just a program, a collection of instructions. our application can be a bootloader as well, with several possible different applicaitons based on what our bootloader finds, their bootloader can boot our bootloader which then chooses from several applications and runs one of them. All within one part...

Multi-drop bus to rs232 Convert

I have a project using MDB (multi-drop bus) for vending machine (VDM).
The VDM has a MDB-RS232.
I'm not sure if it converts 9bit - 8bit (MDB-UART).
How do I read data from VDM in my computer?
Thanks all
MDB (multi-drop bus) is 9 bit, because after the standard 8 data bits (like in standard RS232 UART communication) there is a 9th bit called "mode".
(Wikipedia on MDB: "the mode bit differentiates between ADDRESS and DATA bytes.")
But you can read such data even with regular 8-bit RS232 interfaces, e.g. a plain standard USB-to-RS232 device for PC.
Here is how:
Use 9600 baud, 8 data bits, 1 stop bit, but RS232 parity setting "Space". Make sure you receive the original character value even in case of a Parity Error indication. Any MDB address byte from your VDM will be received with a Parity Error (but still be displayed correctly). Any data byte will be displayed without error.
For sending MDB ADDRESS and DATA bytes using a standard 8-bit RS232 port, you could apply temporary parity changes: Change the parity setting to "Mark" before sending an address byte, then change back to "Space" before sending data bytes.
On Windows, you can do such tricks with our Docklight software (see Docklight and MDB). It's free for basic testing and there is also a related 9-bit example project.
On Linux / Raspberry Pi other users have successfully implemented the parity trick, too, see this stackexchange post about a MDB + Pi.
But also with RealTerm, Teraterm, Termite, Bray, YAT or any other RS232 application you should be able to read the data, as long as it handles "Space" or "Mark" parity settings correctly.
You'll need an adapter which will do all convert operations on-the-fly and in real time. If you want to emulate VMC (master), you'll need MDB-UART master adapter. If you want to emulate MDB peripheral device (such as coin changer, bill validator etc), you'll need this. For two-way "sniffing" MDB bus you'll need a combination of these devices.
Direct connection PC's RS-232 to MDB will not work due to strict MDB timings (delay between VMC command and peripheral response must not exceed 5ms, delays between POLL requests are 50-300ms in general). I mean pretty reliable functioning available for commercial purposes.

MSDOS API serial port only reading last sent character

I've been playing with the MSDOS API in assembler for some time and I'm trying to build an application to read/write from the serial port. I'm currently using VMware Workstation 11 + VSPE (http://www.eterlogic.com/Products.VSPE.html) to emulate the serial port communication.
One thing I noticed is that if I send let's say "asdfgh" into the serial port and then read it in MSDOS (Using interrupt 21h function 03h, but I also tried interrupt 14h function 02h), it only returns the last character read: "h"
According to some documentation I read, if an application sends data faster than I can process it, characters will be lost, which means that either there is another way to make MSDOS save bytes to a buffer (controlling flow) or I have to write a driver that does this (or maybe a TSR program that manages this I dunno).
So the question is, do I have to write a driver or is there another way to do this?
I managed to write a program that turns on the 16550 FIFO buffer and now It works using the DOS API.
So it was just the FIFO buffer
No need to slow down the baud rate or whatsoever. Nonetheless, if one happen to have a 8250 it's probably either that or implement a communications driver on top of it
Also, this helped a lot:
https://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming#UART_Registers

linux serial ports -- mulithread program

I am working on a smartcard reader project here i will have to read/write data from the smartcard reader.
Also i will have to read/write data from PC application.
There are two serial port on my microcontroller one connected to smartcard reader other to PC.
Smartcard reader <------> Microcontroller <-----> PC
I have ported linux & using /ttys0 & /ttys1 driver for this.
1> My question is if application have to find that some data is available to be read from the port than will i have to always check it with read() system call ?
2> Does ttys0 driver have internal buffer to store received data ? Or data is lost if application do not read data immediately ?
3> Here using seprate threads for rx/tx from each port, is it right approach ?
Please guide me i am new to Embedded linux.
//John
Yes, there's a fair amount of buffering on linux tty's.
You have a few choices for how to interact with them.
you can make them non-blocking, and frequently poll to see if you can read data from them (but this may result in uselessly spinning CPU cycles, slowing other tasks)
you can use select() to yield to the scheduler until one of your devices has data for you to act on
you can use blocking I/O, however since you have multiple ports that may also require multiple threads
TTY programming is similar to socket programming in Linux. So basically you can set the socket to be a asynchronous and receive a signal once data is available. Regarding buffering, yes it's buffered using two flipping buffers. You can check chapter 18 in Linux device drivers 3rd edition regarding TTY implementation in the kernel.

List machine's serial ports

I have an Arduino-based device which connects through USB.
I'd like to detect it from my Qt 4 application, using QExtSerialPort (or whatever necessary), when it's plugged in.
If this weren't possible, I thought I could somehow get a list of the system's port names and just try all of them in search for my Arduino (where I'd implement some kind of handshaking procedure for it to detect it correctly). My concern in this approach is that I'm not sure if a device (for example, printer) would get damaged if I send some kind of handshaking ack at a different baud rate.
So, I don't really know where to start for any of them. Which would be the best approach? How would I implement it?
I believe you can find list of serial ports on Windows by looking into
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
registry key
Each serial port on a UNIX system has one or more device files (files in the /dev directory) associated with it:
System Port 1 Port 2
IRIX® /dev/ttyf1 /dev/ttyf2
HP-UX /dev/tty1p0 /dev/tty2p0
Solaris®/SunOS® /dev/ttya /dev/ttyb
Linux® /dev/ttyS0 /dev/ttyS1
Digital UNIX® /dev/tty01 /dev/tty02
more details on serial programing on POSIX systems here
Since your device is USB, your UART port will be emulated by some kind of conversor in his hardware. So first you must understand what driver is being used on your system.
The most common SERIAL->USB conversor uses PL2303/PL2301 chip, so it would create a path on /dev, if its the first device, it will appear as "/dev/ttyUSB0", but you may also see the list reading the proc path (like "cat /proc/bus/usb/devices").
Under Windows it usually creates a virtual "COM", just go to device manager and check the port.
When you are sure about how the HW talks to your system, you may use QExtSerialPort for wrapping the system API and talk to the device.
Way too hard and too platform specific, using weird Windows Registry keys or rely on hard wired device nodes on Linux.
You are on the right way. Get QextSerialPort or QSerialDevice (which I preffer in my projects, because it got integrated in Qt5), have a look at the examples and simply use it. In both libraries you get some kind of port enumerator class which returns you a list of all configures serial ports. Only platform/device specific settings you will have to do manually (like getting RS485 in half-duplex mode on my current embedded project), but "standard" problems are perfectly encapsulated in a QIODevice implementation.
You can use both QextSerialPort and QSerialDevice like a file. Open it (instead of a filename you specify the device name ie. "COM1" on Windows or "/dev/tty0" on Linux, depending on your configuration) and then read or write like you are doing it with an ordinary QFile, QBuffer, Qwhatever-inherits-from-QIODevice.
If you have any problems opening the port and communicating, don't hesitate to ask! :)

Resources