Is it possible to send out a custom message frame on I2C dev from Linux? I am using an i.MX7D board and i would like to use "/dev/i2c-0" device like a simple "serial tty" to "write(fd, bytes, count)". My goal is to send out a single byte for example 0xAB on I2C without any specific slave address and without automatic stop/start bit inserting in my frame.
So i like to make my full custom I2C frame then send it out from Linux. Is it possible, is there any user-space programing techniques in C/C++, Python or any API for it in Linux?
No you can't, because this is limited by the hardware, if you are using the I2c interface, the hardware will limit what you can do.
One way to try is that you can use gpio to simulate i2c or any interface you want to. Many chips support setting the i2c interface to gpio, then you simulate a clock with one gpio, and simulate high and low level with another gpio.
But I don't recommend it, because if you don't follow the i2c protocol, you can't communicate with other i2c devices
Connect two GPIO lines to the I2C bus in addition to the I2C interface. Normally, these will stay tri-stated. When you need to send the magic byte, enable them to send clock and data, then disable them. These won't interfere with I2C, which only drives the bus when transmitting.
Related
What I've been trying to do is send UART communications from an STM32 L152RE Nucleo board to an ESP32, however when I attempt to send these communications I get nothing on the ESP serial monitor. What I am able to see is the STM32 sending messages to its own serial monitor which is great but not what I want.
What I've read so far is that UART 2 is connected to ST-Link so that it can do specifically what I've been witnessing and it explains how this can be reconfigured to allow for the messages to be sent to a peripheral UART device but I'm not sure exactly how to do that.
So in the picture below it says to do this I need to "turn off" SB13 and SB14 and "turn on" SB62 and SB63. I don't really understand how to interpret that, other than to mean "remove resistors from SB13 and SB14 and Place them on SB62 and SB63", is this correct?
I know there are another set of UART pins on the board, can I use those instead somehow?
Your guess ist correct. "SB" means "Solder Bridge". It is just a pair of pads which can be connected with a solder ball, like a simple jumper. Setting SB13 to ON means to connect the pads with a solder ball, setting SB62 to OFF means to remove an existing solder ball connection.
Using a different USART is even easier. Have a look at the STM32L151xE Datasheet to find out that e.g. USART1 is available on pins PA9 (TX) and PA10 (RX). According to user manual of the NUCLEO-L152RE board these pins are available on the ST morpho connector CN10: PA9 at Pin 21 and PA10 at Pin 33.
I am trying to force a 9-bit protocol on a UART in embedded Linux. Currently I am testing this out on the am335x_evm board. I am planning on doing this using stick parity. Ideally I was hoping I would not need to actually modify any of the code for the omap-serial.c driver.
The reason for the 9-bit protocol is to support some legacy hardware that uses it. The parity bit needs to be 1 for the address portion of the message, 0 for the data portion, then 1 again for the termination byte.
I was planning on having a process running in user space that would interface with the UART through standard system calls (open, write, read, ioctl, tcsetattr, etc). I would configure the UART to enable parity and set the stick parity. I would then set the parity to even and call write() to send out my address data. I would then set the parity to 0 and send out the data. My concern is if I change the parity from 1 to 0, when does that take affect? If the UART is not done sending all the address data, will the change in parity apply to any unsent data?
Ended up writing my own 9-bit uart driver. Was the easiest and most efficient solution.
Proper way is to set cs9 on your serial port (and possibly no parity), provided that hardware and driver support this.
I'll search for a link for you...
I'm currently working on a project which involves dealing with a HW device tailor-made for this purpose.
The device will serve the purpose of sending certain data via serial port (COM1, for instance). The data it is supposed to send doesn't matter that much.
I already have some knowledge regarding Windows serial port communication. CreateFile, WriteFile, and so on... BUT...
There is one "engine" on the device, which will send me the data when I ask it to, and in order to do so, I need to send there a signal (10101010) the rate of which will indicate the clock rate of that device "engine".
Here comes the explanation of how this device work. It gets a signal to send data through one pin. I'm supposed to send there 0 for start, 1 for end. Then, after this, it will watch some other pin for signal, sample it, and based on the frequency of ones and zeroes I send to it, it will start sending data via the thrid pin.
My questions are:
How to access individual pins of COM port?
How to manage the frequency and any delays I will need by myself?
I think that maybe I will have to do on this in kernel more by use of device drivers which will have to be developed.
There is an easier way. The COM port will send out the signal of alternating 1s and 0s if you just send a 0xAA byte.
I would like to copy data to user space from kernel module which receives data from serial port and transfers it to DMA, which in turn forwards the data to tty layer and finally to user space.
the current flow is
serial driver FIFO--> DMA-->TTY layer -->User space (the data to tty layer is emptied from DMA upon expiration of timer)
What I want to achieve is
serial driver FIFO-->DMA-->user space. (I am OK with using timer to send the data to user space, if there is a better way let me know)
Also the kernel module handling the serialFIFO->DMA is not a character device.
I would like to bypass tty layer completely. what is the best way to achieve so?
Any pointers/code snippet would be appreciated.
In >=3.10.5 the "serial FIFO" that you refer to is called a uart_port. These are defined in drivers/tty/serial.
I assume that what you want to do is to copy the driver for your UART to a new file, then instead of using uart_insert_char to insert characters from the UART RX FIFO, you want to insert the characters into a buffer that you can access from user space.
The way to do this is to create a second driver, a misc class device driver that has file operations, including mmap, and that allocates kernel memory that the driver's mmap file operation function associates with the userspace mapped memory. There is a good example of code for this written by Maxime Ripard. This example was written for a FIQ handled device, but you can use just the probe routine's dma_zalloc_coherent call and the mmap routine, with it's call to remap_pfn_range, to do the trick, that is, to associate a user space mmap on the misc device file with the alloc'ed memory.
You need to connect the memory that you allocated in your misc driver to the buffer that you write to in your UART driver using either a global void pointer, or else by using an exported symbol, if your misc driver is a module. Initialize the pointer to a known invalid value in the UART driver and test it to make sure the misc driver has assigned it before you try to insert characters to the address to which it points.
Note that you can't add an mmap function to the UART driver directly because the UART driver class does not support an mmap file operation. It only supports the operations defined in the include/linux/serial_core.h struct uart_ops.
Admittedly this is a cumbersome solution - two device drivers, but the alternative is to write a new device class, a UART device that has an mmap operation, and that would be a lot of work compared with the above solution although it would be elegant. No one has done this to date because as Jonathan Corbet say's "...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices", though this is exactly what you are asking for.
I implemented this solution for a polling mode UART driver based on the mxs-auart.c code and Maxime's example. It was non-trivial effort but mostly because I am using a FIQ handler for the polling timer. You should allow two to three weeks to get the whole thing up and running.
The DMA aspect of your question depends on whether the UART supports DMA transfer mode. If so, then you should be able to set it using the serial flags. The i.MX28's PrimeCell auarts support DMA transfer but for my application there was no advantage over simply reading bytes directly from the UART RX FIFO.
I have the I2C (SMBus) working properly in this uC and have a VB GUI which can communicate over USB (using USBXpress) and do I2C transactions from the uC to a separate IC. The problem is that I am having the uC poll a register on the IC every 1s. When I do an asynchronous GUI I2C transaction, every once in a while, I believe it collides with the polling I2C transaction and all the I2C data gets shifted at the GUI (i.e., register 0x00's data shows up on register 0x01) . The I2C data in the IC looks correct (by spying on the I2C bus with a LA). What exactly is happening and how can I fix this?
If the polling between the uC and I2C is happening over the same I2C bus as that used by your GUI app then you need to make sure that access to the I2C is controlled such that one transaction completes before the other is allowed to begin. Maybe you are doing this already but this is not clear from the question.
Also, posting some code or pseudo code of the uC code might help.